Index: /tags/kBuild-0.1.4/COPYING
===================================================================
--- /tags/kBuild-0.1.4/COPYING	(revision 1780)
+++ /tags/kBuild-0.1.4/COPYING	(revision 1780)
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.
+
+		    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.)
+
+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.
+
+  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.
+
+  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
+
+	    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) <year>  <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.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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 Lesser General
+Public License instead of this License.
Index: /tags/kBuild-0.1.4/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/ChangeLog	(revision 1780)
@@ -0,0 +1,354 @@
+/* $Id$ */
+
+The change log has been discontinued. check the trac timeline instead:
+
+    http://svn.netlabs.org/kbuild/timeline
+
+
+2006-12-03:
+    - kBuild/bin/x86.win32:
+        o Rebuild and cleaned out dlls that mv and sed required.
+    - sed:
+        o Fixed parsing of single quoted arguments on windows.
+
+2006-12-02:
+    - kmk:
+        o Fixed bugs dealing with the order SDK properties was applied to sources.
+
+2006-12-01:
+    - kBuild:
+        o Added support for compiling resource files.
+        o Fixed bug causing object files take from the SOURCES to be cleaned up.
+
+2006-11-25:
+    - kmk, kBuild:
+        o Added mv as builtin command.
+        o Added cat as builtin command.
+        o Added GNU sed version 4.1.5 and ported it to MSC.
+        o Added rmdir as builtin and external command.
+        o Made mkdir not modify the argument strings.
+        o Made mkdir deal properly with DOS slashes on OS/2 and Windows.
+
+2006-11-24:
+    - kBuild/bin/x86.win32/kmk.exe, kBuild/bin/x86.linux/kmk:
+        o Rebuilt with current code.
+    - kBuild/footer.kmk:
+        o Fixed some issues with SDKS and linking.
+    - kmk:
+        o Fixed bug in the sdk walking in kbuild_collect_source_prop.
+        o Added --pretty-command-printing for simplifying makefile debugging.
+
+2006-11-23:
+    - dist/portage:
+        o Hacked together two ebuilds for the Gentoo Portage.
+    - Config.kmk, Makefile.kmk:
+        o #6: Hacking *nix install build for Gentoo.
+    - src/gmake/Makefile.kmk, src/lib/Makefile:
+        o Always include header.kmk when testing BUILD_TARGET*.
+    - kBuild/header.kmk:
+        o BUILD_TYPE defaults to 'release'.
+    - kBuild/tools/GCC*.kmk:
+        o Cleaned up the -s and -g usage.
+    - kBuild/bin/x86.win32, kBuild/bin/x86.linux:
+        o Rebuilt with current code.
+    - kBuild/footer.kmk:
+        o #3: Clean link output files.
+    - kBuild/header.kmk, kmk:
+        o #6: Did code changes for unix installation. Will do install goals when creating the gentoo ebuild.
+        o #5: Proper versioning. (#5)
+    - kmk:
+        o Support SDK.$(BUILD_TARGET_ARCH) too (only bug).
+        o Fixed a bug when gather SDKs.
+
+2006-09-28:
+    - kBuild/header.kmk, kBuild/env.sh, kBuild/tools/GCC4MACH.kmk, kBuild/bin/x86.darwin/, src/gmake, Config.kmk:
+        o Initial Mac OS X / Darwin bootstrapping.
+
+2006-09-23:
+    - kBuild/footer.kmk:
+        o Recursive template inheritance.
+    - kBuild/header.kmk, kBuild/footer.kmk:
+        o Removed some checks for features which are present in both gmake 3.81 and kmk.
+          Anyone trying to bootstrap kBuild will have to build gmake 3.81 first.
+    - Config.kmk, src/gmake, src/lib, src/kDepPre, src/kDepIDB:
+        o Allow all kinds of ways of saying Windows in BUILD_TARGET.
+    - kBuild/bin/x86.win32/:
+        o Rebuilt kmk.exe.
+    - kBuild/bin/x86.os2/:
+        o Added kDepPre.exe and kDepIDB.exe.
+        o Rebuilt kmk.exe and kmk_gmake.exe.
+    - src/gmake:
+        o Update KMK_FEATURES to include the optimizations from earlier this week.
+        o Regenerated config.h.os2 and make adjustments to make it all
+          build quietly on OS/2.
+    - kBuild/envos2.cmd:
+        o Environment script (REXX) for OS/2.
+
+2006-09-19:
+    - kBuild/bin/x86.win32/:
+        o Rebuilt kmk.exe and kmk_gmake.exe.
+    - src/gmake:
+        o Fixed some optimization bugs in kbuild.c.
+
+2006-09-18:
+    - kBuild/gmake:
+        o Don't send put j1 in MAKEFLAGS on windows, somehow that doesn't work.
+        o Fixed some variable name typos in kbuild.c.
+        o Fixed missing expansion in kbuild_lookup_variable.
+        o A real attempt at fixing the double quoting problem on windows. ash seems to want a
+          space between a double quote enclosing the last argument on the commandline and the
+          double quote enclosing the commandline (the -c argument).
+        o Fixed a newline escape problem when using batch_mode_shell on windows with kmk_ash.
+
+2006-09-17:
+    - kBuild/gmake:
+        o Optimization summary: libc from ~21 seconds -> 7-8 seconds (os2/nt).
+        o Optimized appending new stuff to variables. (major win)
+        o Optimized variable memory value allocation avoiding a bunch of
+          unnecessary copying and allocating.
+        o Added kBuild specific functions for speeding up source processing.
+        o Fixed assertion in w32_fixcase when shell doesn't have a full path
+          and some other case.
+
+2006-09-16:
+    - kBuild/header.kmk:
+        o Turn off command dependencies when using vanilla GNU Make.
+    - kBuild/footer.kmk:
+        o Made up my mind about the command depency blocker variables;
+          NO_LINK_CMDS_DEPS and NO_COMPILE_CMDS_DEPS.
+    - src/gmake:
+        o Added kmk_gmake which is (almost) vanilla GNU Make.
+        o kmk_ash wants batch files on windows or the double quotes will get screwed up.
+        o Make sure kmk_builtin commands don't get batch files and odd weird stuff.
+        o Cleaning up the modifications. Changes are now either configurable
+          or marked, and dead stuff has been removed (dll shell).
+
+2006-09-15:
+    - kBuild/bin/x86.win32/kmk.exe:
+        o Built new code.
+    - kBuild/header.kmk:
+        o DIRDEP is now the same on all platforms (fixed with 3.81 merge).
+    - kBuild/bin/x86.linux/kmk:
+        o Built new code on system360.
+    - src/gmake:
+        o Some parallel job fixes.
+        o Regenerated config.h.linux on system360.
+        o Fixed stat("dir/", &st) on windows and some warnings.
+        o Merge with GNU Make v3.81 (vendor/gnumake/2005-05-16 -> vendor/gnumake/current).
+
+2006-03-26:
+    - kBuild/bin/x86.os2/:
+        o Rebuilt the OS/2 tools.
+    - src/gmake/variable.c, src/gmake/variable.h, src/gmake/make.h:
+        o Attempt at speeding up performance on OS/2.
+    - src/gmake/kmkbuiltin/rm.c:
+        o OS/2 wants -R.
+    - src/gmake/read.c:
+        o Don't call glob() unless there is a wildcard pattern in the name.
+          This speed things up a bit, at least on FreeBSD and especially on OS/2.
+    - Config.kmk:
+        o Added -pg for profile builds on OS/2.
+
+2006-02-22: bird
+    - kBuild/tools/MINGW32.kmk:
+        o Corrected dependencies to match those generated by GCC3.
+
+2006-02-09: bird
+    - kBuild/tools/YASM.kmk:
+        o Initial config.
+
+2006-01-20: bird
+    - kBuild/footer.kmk, kBuild/header.kmk:
+        o Check for PACKING.$(BUILD_TARGET) as well. Added a quick evaluation
+          of PACKING[.*] in the footer.
+
+2006-01-18: bird
+    - kBuild/footer.kmk, kBuild/header.kmk:
+        o Packing pass change - uses PACKING var instead of packing::.
+    - kBuild/footer.kmk:
+        o Added mode,uid and gid to file INSTALLS.
+        o Implemented template inheritance (_EXTENDS).
+
+2006-01-14: bird
+    - kBuild/env.sh:
+        o Corrected the tool list.
+    - kBuild/bin/x86.linux/:
+        o Rebuild with current tree and static linage. (rhel3)
+    - kBuild/tools/VCC70.kmk:
+        o Enabled new dependcies.
+        o Must use PDB macro to get the case correct on the idb file passed to kDepIDB.
+    - src/lib/kDep.c:
+        o Fixed missing slash fixing
+        o Changed kDepPre error prefix to kDep.
+
+2006-01-12: bird
+    - kBuild/tools/VCC70.kmk:
+        o Use DEP_IDB on win32.
+    - kBuild/header.kmk:
+        o Added DEP_IDB and DEP_IDB_EXT.
+    - kBuild/bin/x86.win32/:
+        o Rebuild with current source, adding kDepIDB.
+    - src/kDepIDB/kDepIDB.c:
+        o Initial coding. (This is a VC++ dependency extractor.)
+    - src/kDepPre/kDepPre.c, src/lib/kDep.h, src/lib/kDep.c, Config.kmk:
+        o Created a library for the dep*() functions.
+        o Removed the IDB hacks from kDepPre.
+
+2006-01-11: bird
+    - kBuild/tools/vcc70.kmk:
+        o Prepared for new IDB based dependencies.s
+    - kBuild/footer.kmk:
+        o Parallel build fixing.
+    - src/gmake/job.c:
+        o Fixed bad parallel bug.
+    - src/gmake/main.c:
+        o Enabled multiple jobs for recursive kmk processes on win32 despite the problems.
+    - src/kDepPre/kDepPre.c:
+        o Added extremely rough support for VC++ IDB files (/FD + /Fd).
+
+2005-12-18: bird
+    - kBuild/*.kmk, kBuild/tools/*.kmk:
+        o Finally I've got around to implement command dependencies.
+        o Use $(INSTALL) instead of $(RM) + $(CP).
+        o More install features.
+    - kBuild/bin/x86.[linux|win32|os2]/:
+        o Rebuilt all the utils.
+        o Renamed all unix utilites so they start with a kmk_ prefix and don't
+          override any local unix utils.
+    - src/gmake/kmkbuiltin/*, src/gmake/kmkbuiltin.c,
+      src/gmake/kmkbuiltin.h, src/gmake/variables.c,
+      src/gmake/Makefile.kmk:
+        o Ported all the builtins to windows - now rebuild works again!
+        o Fixed a few error case bugs in the builtins.
+        o Disabled the -R and -r options for rm and cp.
+        o Added kmk_install / kmk_builtin_install from BSD.
+
+2005-12-13: bird
+    - kBuild/bin/x86.linux/kmk,
+      kBuild/bin/x86.linux/kmk_append,
+      kBuild/bin/x86.linux/kmk_cp,
+      kBuild/bin/x86.linux/kmk_echo,
+      kBuild/bin/x86.linux/kmk_mkdir,
+      kBuild/bin/x86.linux/kmk_rm:
+        o Rebuild with current sources.
+    - src/gmake/Makefile:
+        o Prefixed external tools with kmk_.
+
+2005-12-12: bird
+    - kBuild/footer.kmk, kBuild/header.kmk:
+        o Generic pass stuff.
+        o Enabled and weeded out the new target install method.
+        o Added separate install target type.
+        o Added separate installs pass.
+        o Fixed those $$$$(PATH_<target>) problems.
+        o General clean up removing lot's of duplicate stuff.
+    - kBuild/tools/ALP.kmk, kBuild/tools/GCC.kmk, kBuild/tools/GCC3.kmk,
+      kBuild/tools/GCC3OMF.kmk, kBuild/tools/MINGW32.kmk, kBuild/tools/NASM.kmk,
+      kBuild/tools/VCC70.kmk:
+        o Adjusted to new parameters for the link rules.
+        o List all output files as targets for the rules.
+    - kBuild/config.kmk, kBuild/cfg/x86.win32.va2003.kmk:
+        o Removed early attempts which isn't used anylonger.
+    - src/gmake/remake.c, src/gmake/commands.c, src/gmake/commands.h:
+        o Fixed not parallel assertion on targets with no commands.
+
+2005-12-11: bird
+    - src/gmake/kmkbuiltin/append.c, src/gmake/kmkbuiltin.h, src/gmake/kmkbuiltin.c,
+      src/gmake/Makefile.kmk, src/gmake/variables.c:
+        o New command 'append' which appends text to a file, creating the file if necessary.
+        o KMK_BUILTIN is listing the supported commands (used to be "1").
+    - src/gmake/kmkbuiltin/cp_utils.c:
+        o Add O_BINARY to all open calls.
+    - src/gmake/function.c:
+        o Fixed abspath on OS/2.
+    - src/kDepPre/kDepPre.c:
+        o Killed some warnings and made it build on OS/2 and FreeBSD.
+
+2005-11-07: bird
+    - kBuild/tools/VCC70.kmk:
+        o Use the new -s option for dependencies.
+    - src/kDepPre/kDepPre.c, kBuild/bin/x86.linux/kDepPre, kBuild/bin/x86.win32/kDepPre.exe:
+        o Added new option -s for generating stub dependencies just like -Wp,-MP.
+    - kBuild/tools/GCC3.kmk, kBuild/tools/GCC3OMF.kmk:
+        o Added -Wp,-MP to compile jobs for better dependencies.
+
+2005-10-31: bird
+    - kBuild/tools/VCC70.kmk:
+        o Use the -f option with kDepPre to make sure nt/wine/cl doesn't
+          screw up the path casing anywhere.
+    - kBuild/bin/x86.linux/kDepPre, kBuild/bin/x86.win32/kDepPre.exe:
+        o Rebuild with latest code.
+2005-10-30: bird
+    - kBuild/env.sh:
+        o amd64.
+        o kDepCCxx -> kDepPre. Ash.
+    - kBuild/bin/amd64.linux/kDepPre, src/kDepPre/kDepPre.c:
+        o Fix case option - need it on unix for cl.exe with wine.
+
+2005-10-29: bird
+    - kBuild/bin/amd64.linux/kDepPre, src/kDepPre/kDepPre.c:
+        o Strip drive letters on non-PC OSes.
+
+2005-10-28: bird
+    - kBuild/footer.h:
+        o Fixed a couple of defaults so it all works right on amd64.
+    - kBuild/bin/amd64.linux/:
+        o Added binaries. ash is 32-bit!
+
+2005-10-14: bird
+    - src/kDepPre/kDepPre.c, kBuild/bin/x86.win32/kDepPre.exe:
+        o Corrected bug in line skipping where two lines would be skipped.
+        o Corrected slashes on win32.
+
+2005-10-03: bird
+    - src/kDepPre/kDepPre.c, kBuild/bin/x86.win32/kDepPre.exe:
+        o Fixed stupid stupid bug in the win32 case correcting code.
+          Rebuilt the win32 binary.
+
+2005-08-11: bird
+    - kBuild/footer.kmk:
+        o Enh. the _OBJECT_BASE hack for stripping of source paths within the project.
+
+    - kBuild/tools/VCC70.kmk:
+        o Use $(tolower ) to construct the right .pdb names for cleanup.
+
+    - src/gmake/read.c:
+        o print target name 'target pattern' errors.
+
+    - kBuild/header.kmk:
+        o Use $(abspath ).
+
+    - src/gmake/variable.c:
+        o Added KMK_FEATURES which indicates what's present+working and what's not.
+
+    - src/gmake/w32/pathstuff.c, src/kDepPre/kDepPre.c, src/kDepPre/Makefile.kmk:
+        o Fixed casing paths on win32.
+
+    - src/gmake/function.c, src/gmake/Makefile.kmk:
+        o Fixed $(abspath ) on Win32 and OS/2.
+        o Added $(tolower ) and $(toupper ).
+
+2005-06-16: bird
+    - ALL:
+        o Bootstrap and ported to FreeBSD 5.x on AMD64.
+
+2005-05-06: bird
+    - ALL:
+        o Working on the build system of the build system. :-)
+        o Ported the kmkbuiltin stuff to OS/2 as a prep to the win32 effort.
+
+[missing a lot!]
+
+2002-10-15: bird
+    - ALL:
+        o Created a somewhat rought directory structure.
+
+    - src/fastdep:
+        o Imported current sources from ODIN32.
+
+    - src/kmk:
+        o Imported current sources from the freebsd tree.
+
+2002-10-15: ktk
+    - ALL:      Create repository.
+
Index: /tags/kBuild-0.1.4/Config.kmk
===================================================================
--- /tags/kBuild-0.1.4/Config.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/Config.kmk	(revision 1780)
@@ -0,0 +1,267 @@
+# $Id$
+## @file
+# Build Configuration.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+
+# Enable automatic installation of what's built.
+KBUILD_DO_AUTO_INSTALL := 1
+
+
+#
+# The kBuild version.
+#
+KBUILD_VERSION_MAJOR = 0
+KBUILD_VERSION_MINOR = 1
+KBUILD_VERSION_PATCH = 4
+KBUILD_VERSION = 0.1.4
+DEFS += \
+	KBUILD_VERSION_MAJOR=$(KBUILD_VERSION_MAJOR) \
+	KBUILD_VERSION_MINOR=$(KBUILD_VERSION_MINOR) \
+	KBUILD_VERSION_PATCH=$(KBUILD_VERSION_PATCH)
+
+#
+# Get the svn version.
+# This is shipped with the tarballs in a SvnInfo.kmk in the root.
+#
+ifneq ($(wildcard $(PATH_ROOT)/SvnInfo.kmk),)
+# Shipped
+KBUILD_SVN_INFO_KMK := $(PATH_ROOT)/SvnInfo.kmk
+KBUILD_SVN_INFO_DEP := $(KBUILD_SVN_INFO_KMK)
+
+else ifneq ($(wildcard $(PATH_ROOT)/.svn/entries),)
+# Generate from svn info
+KBUILD_SVN_INFO_KMK := $(PATH_OBJ)/SvnInfo.kmk
+KBUILD_SVN_INFO_DEP := $(KBUILD_SVN_INFO_KMK)
+
+$(PATH_OBJ)/SvnInfo.ts +| $(KBUILD_SVN_INFO_KMK): $(wildcard $(PATH_ROOT)/.svn $(PATH_ROOT)/.svn/entries $(PATH_ROOT)/.svn/all-wcprops $(PATH_ROOT)/.svn/format $(PATH_ROOT)/.svn/props $(PATH_ROOT)/.svn/prop-base )
+	$(call MSG_GENERATE,,$(KBUILD_SVN_INFO_KMK))
+	@$(RM) -f $@ $@.tmp
+	@$(MKDIR) -p $(@D)
+	@$(REDIRECT) -o $@.tmp -E 'LC_ALL=C' -- svn info $(DEPTH)
+	@$(SED) \
+		-e 's/URL: */KBUILD_SVN_URL := /' \
+		-e 's/Revision: */KBUILD_SVN_REV := /' \
+		-e '/KBUILD_SVN_/!d' \
+		--append $@ \
+		$@.tmp
+	@$(RM) -f $@.tmp
+	@$(CP) --changed -fv $@ $(KBUILD_SVN_INFO_KMK)
+
+ ifeq ($(DEPTH),.)
+OTHER_CLEAN += $(KBUILD_SVN_INFO_KMK) $(PATH_OBJ)/SvnInfo.ts
+ endif
+
+else
+# Some incomplete source export...
+KBUILD_SVN_INFO_KMK := $(PATH_OBJ)/SvnInfo.kmk
+KBUILD_SVN_INFO_DEP := $(KBUILD_SVN_INFO_KMK)
+$(warning Neither SvnInfo nor .svn/* was found in the root. Will have to cook up something too keep the build happy.)
+$(KBUILD_SVN_INFO_KMK):
+	$(RM) -f $@
+	$(MKDIR) -p $(@D)
+	$(APPEND) $@ 'KBUILD_SVN_REV := 0'
+	$(APPEND) $@ 'KBUILD_SVN_URL := /dev/null'
+
+ ifeq ($(DEPTH),.)
+OTHER_CLEAN += $(KBUILD_SVN_INFO_KMK)
+ endif
+
+endif
+include $(KBUILD_SVN_INFO_KMK)
+
+
+#
+# The OS and Architecture indicators.
+#
+DEFS.darwin  += KBUILD_OS_DARWIN
+DEFS.freebsd += KBUILD_OS_FREEBSD
+DEFS.linux   += KBUILD_OS_LINUX
+DEFS.netbsd  += KBUILD_OS_NETBSD
+DEFS.openbsd += KBUILD_OS_OPENBSD
+DEFS.os2     += KBUILD_OS_OS2
+DEFS.solaris += KBUILD_OS_SOLARIS
+DEFS.win     += KBUILD_OS_WINDOWS
+
+DEFS.x86     += KBUILD_ARCH_X86
+DEFS.amd64   += KBUILD_ARCH_AMD64
+
+
+#
+# Check if we're building a *nix installation.
+#
+ifdef NIX_INSTALL_DIR
+NIX_INSTALL_DIR_BIN   := $(patsubst /%,%,$(NIX_INSTALL_DIR))/bin
+NIX_INSTALL_DIR_SHARE := $(patsubst /%,%,$(NIX_INSTALL_DIR))/share/kBuild
+DEFS += \
+	KBUILD_PATH=\"/$(NIX_INSTALL_DIR_SHARE)\" \
+	KBUILD_BIN_PATH=\"/$(NIX_INSTALL_DIR_BIN)\"
+endif
+
+#
+# Where to fine the GNU Make stuff (for FreeBSD and Windows).
+#
+PATH_GNUMAKE_SRC               ?= $(PATH_ROOT)/src/kmk
+
+
+#
+# Template for building commandline tools.
+#
+TEMPLATE_BIN = Commandline binary
+
+TEMPLATE_BIN_INCS               = $(PATH_ROOT)/src/lib
+
+ifeq ($(KBUILD_TARGET),os2)
+TEMPLATE_BIN_TOOL               = GCC3OMF
+TEMPLATE_BIN_CFLAGS             = -g
+TEMPLATE_BIN_CFLAGS.profile     = -pg
+TEMPLATE_BIN_CFLAGS.release     = -O3
+TEMPLATE_BIN_LDFLAGS            = -Zhigh-mem -Zstack=1024 -g
+ ifdef NIX_INSTALL_DIR
+TEMPLATE_BIN_INST               = $(NIX_INSTALL_DIR_BIN)/
+ else
+TEMPLATE_BIN_INST               = kBuild/bin/os2.x86/
+ endif
+endif
+
+ifeq ($(KBUILD_TARGET),darwin)
+ ifndef KBUILD_MACOSX_VERSION
+  export KBUILD_MACOSX_VERSION := $(firstword $(subst ., ,$(shell uname -r)))
+ endif
+ KBUILD_MACOSX_SDK             ?= /Developer/SDKs/MacOSX10.4u.sdk
+ TEMPLATE_BIN_TOOL              = GCC4MACHO
+ TEMPLATE_BIN_CFLAGS            = -g -mmacosx-version-min=10.4 -isysroot $(KBUILD_MACOSX_SDK)
+ ifeq ($(USER),bird)
+  TEMPLATE_BIN_CFLAGS          += -Wall -Wextra -pedantic
+ endif
+ TEMPLATE_BIN_CFLAGS.profile    = -O3 -pg
+ TEMPLATE_BIN_CFLAGS.release    = -O3
+ TEMPLATE_BIN_LDFLAGS           = -g -mmacosx-version-min=10.4 -Wl,-syslibroot,$(KBUILD_MACOSX_SDK)
+ ifneq ($(int-ge $(KBUILD_MACOSX_VERSION),9),) # >= 10.5
+  TEMPLATE_BIN_LDFLAGS         += -classic_ld
+ endif
+ TEMPLATE_BIN_LDFLAGS.profile   = -pg
+ ifdef NIX_INSTALL_DIR
+  TEMPLATE_BIN_INST             = $(NIX_INSTALL_DIR_BIN)/
+ else
+  TEMPLATE_BIN_INST             = kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/
+ endif
+endif
+
+ifeq ($(filter-out win nt,$(KBUILD_TARGET)),)
+ ifeq ($(KBUILD_TARGET_ARCH),x86)
+  include $(KBUILD_PATH)/tools/VCC70.kmk	# fixme! template expanding does something bad to _LIBS /me thinks.
+  TEMPLATE_BIN_TOOL             = VCC70
+  TEMPLATE_BIN_DEFS             = WINDOWS32 _CONSOLE __WIN__ WIN32 __WIN32__
+ else ifeq ($(KBUILD_TARGET_ARCH),amd64)
+  TEMPLATE_BIN_TOOL             = VCC80AMD64
+  TEMPLATE_BIN_DEFS             = WINDOWS32 _CONSOLE __WIN__ WIN32 __WIN32__ __WIN64__ WIN64 \
+                                  _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS
+ endif
+ TEMPLATE_BIN_DEFS.profile      = NDEBUG
+ TEMPLATE_BIN_DEFS.release      = NDEBUG
+ TEMPLATE_BIN_CFLAGS            = -W3 -Zi -Zl
+ TEMPLATE_BIN_CFLAGS.release    = -O2
+ TEMPLATE_BIN_CFLAGS.profile    = -O2 -GH -Gh
+ TEMPLATE_BIN_INCS             += \
+	. \
+	$(PATH_GNUMAKE_SRC)/w32/include \
+	$(PATH_GNUMAKE_SRC)/glob
+ TEMPLATE_BIN_LDFLAGS           = /SUBSYSTEM:console /INCREMENTAL:no /NOD /DEBUG
+ ifeq ($(KBUILD_TYPE),profile)
+  TEMPLATE_BIN_SDKS              = WINPSDKINCS
+  TEMPLATE_BIN_CFLAGS          += -MT
+  TEMPLATE_BIN_LIBS             = \
+	D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/lib/kPrf2.lib \
+	D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/lib/kPrf2WinApiWrappersImp.lib \
+  	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/oldnames.lib \
+  	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcmt.lib \
+  	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcpmt.lib \
+	D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/lib/kPrf2WinApiWrappersImp.lib \
+	$(PATH_SDK_WINPSDKINCS_LIB)/AdvAPI32.lib \
+	$(PATH_SDK_WINPSDKINCS_LIB)/User32.lib
+ else
+  TEMPLATE_BIN_SDKS              = WINPSDK
+  TEMPLATE_BIN_CFLAGS          += -MD
+  TEMPLATE_BIN_LIBS             = \
+  	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/oldnames.lib \
+  	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/msvcrt.lib
+  #	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/msvcprt.lib - avoid this to save space!
+ endif
+ ifdef NIX_INSTALL_DIR
+  TEMPLATE_BIN_INST             = $(NIX_INSTALL_DIR_BIN)/
+ else
+  TEMPLATE_BIN_INST             = kBuild/bin/win.$(KBUILD_TARGET_ARCH)/
+ endif
+endif
+
+ifndef TEMPLATE_BIN_TOOL
+ # Use GCC3 when we're certain that the system is using GNU ld and ar.
+ ifeq ($(filter-out linux freebsd openbsd netbsd,$(KBUILD_TARGET)),)
+  TEMPLATE_BIN_TOOL              = GCC3
+ else
+  TEMPLATE_BIN_TOOL              = GCC3PLAIN
+ endif
+ TEMPLATE_BIN_CFLAGS            = -g 
+ ifeq ($(USER),bird)
+  TEMPLATE_BIN_CFLAGS          += -Wall -Wextra -pedantic
+ endif
+ TEMPLATE_BIN_LDFLAGS           = -g
+ TEMPLATE_BIN_CFLAGS.release    = -O3
+ ifeq ($(KBUILD_TARGET),freebsd)
+  TEMPLATE_BIN_INCS            += $(PATH_GNUMAKE_SRC)/glob /usr/local/include
+ endif
+ ifeq ($(KBUILD_TARGET),linux)
+  TEMPLATE_BIN_LIBS            += rt
+ endif
+ ifeq ($(KBUILD_TARGET),solaris)
+  TEMPLATE_BIN_CFLAGS.x86      += -m32
+  TEMPLATE_BIN_CFLAGS.amd64    += -m64
+  TEMPLATE_BIN_CXXFLAGS.x86    += -m32
+  TEMPLATE_BIN_CXXFLAGS.amd64  += -m64
+  TEMPLATE_BIN_LDFLAGS.x86     += -m32
+  TEMPLATE_BIN_LDFLAGS.amd64   += -m64
+  TEMPLATE_BIN_LIBS            += rt
+  TEMPLATE_BIN_LDFLAGS         += -Wl,-i
+ endif
+ ifdef NIX_INSTALL_DIR
+  TEMPLATE_BIN_INST             = $(NIX_INSTALL_DIR_BIN)/
+ else
+  TEMPLATE_BIN_INST             = kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/
+ endif
+endif
+
+#
+# Template for building libraries for the tools.
+#
+TEMPLATE_LIB = Library for Commandline binary
+TEMPLATE_LIB_EXTENDS = BIN
+TEMPLATE_LIB_INST    = lib/
+# for LIB_KDEP
+TEMPLATE_LIB_TOOL    = $(TEMPLATE_BIN_TOOL)
+
+
+LIB_KDEP = $(PATH_OBJ)/kDep/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
+LIB_KUTIL = $(PATH_OBJ)/kUtil/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kUtil$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
+
+
Index: /tags/kBuild-0.1.4/Maintenance.kmk
===================================================================
--- /tags/kBuild-0.1.4/Maintenance.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/Maintenance.kmk	(revision 1780)
@@ -0,0 +1,171 @@
+# $Id$
+## @file
+# Maintenance Makefile for kBuild.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+DEPTH = .
+include $(PATH_KBUILD)/header.kmk
+
+RMTREE = $(ECHO) todo: $(RM) -Rf
+RMTREE = rm -Rf
+SVN = svn
+TAR = tar
+GZIP = gzip
+
+ifeq ($(strip $(KBUILD_SVN_INFO_KMK)),)
+$(error wtf? KBUILD_SVN_INFO_KMK is empty!)
+endif
+
+#
+# Creates the 'all' tarballs.
+#
+$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-all.tar.gz: | $$(dir $$@)
+	$(RM) -f $(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-all.tar $(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-all.tar.gz
+	$(RMTREE)             $(PATH_TARGET)/all/
+	$(MKDIR) -p           $(PATH_TARGET)/all/
+	$(SVN) export .       $(PATH_TARGET)/all/kBuild-$(KBUILD_VERSION)/
+	$(INSTALL) $(KBUILD_SVN_INFO_KMK) \
+	                      $(PATH_TARGET)/all/kBuild-$(KBUILD_VERSION)/SvnInfo.kmk
+	$(TAR) cvf $(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-all.tar \
+	                   -C $(PATH_TARGET)/all/ kBuild-$(KBUILD_VERSION)/
+	$(GZIP) -9 $(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-all.tar
+	$(RMTREE)             $(PATH_TARGET)/all/kBuild-$(KBUILD_VERSION)/
+
+OTHER_CLEAN += \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-all.tar \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-all.tar.gz
+
+
+$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-all.tar.gz: | $$(dir $$@)
+	$(RM) -f $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-all.tar $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-all.tar.gz
+	$(RMTREE)             $(PATH_TARGET)/night-all/
+	$(MKDIR) -p           $(PATH_TARGET)/night-all/
+	$(SVN) export .       $(PATH_TARGET)/night-all/kBuild-$(KBUILD_SVN_REV)/
+	$(INSTALL) $(KBUILD_SVN_INFO_KMK) \
+	                      $(PATH_TARGET)/night-all/kBuild-$(KBUILD_SVN_REV)/SvnInfo.kmk
+	$(TAR) cvf $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-all.tar \
+	                   -C $(PATH_TARGET)/night-all/ kBuild-$(KBUILD_SVN_REV)/
+	$(GZIP) -9 $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-all.tar
+	$(RMTREE)             $(PATH_TARGET)/night-all/kBuild-$(KBUILD_SVN_REV)/
+
+OTHER_CLEAN += \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-all.tar \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-all.tar.gz
+
+
+#
+# Creates the source tarballs.
+#
+$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar.gz: | $$(dir $$@)
+	$(RM) -f $(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar $(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar.gz
+	$(RMTREE)             $(PATH_TARGET)/src/
+	$(MKDIR) -p           $(PATH_TARGET)/src/
+	$(SVN) export .       $(PATH_TARGET)/src/kBuild-$(KBUILD_VERSION)/
+	$(RMTREE)             $(PATH_TARGET)/src/kBuild-$(KBUILD_VERSION)/kBuild/bin
+	$(INSTALL) $(KBUILD_SVN_INFO_KMK) \
+	                      $(PATH_TARGET)/src/kBuild-$(KBUILD_VERSION)/SvnInfo.kmk
+	$(TAR) cvf $(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar \
+	                   -C $(PATH_TARGET)/src/ kBuild-$(KBUILD_VERSION)/
+	$(GZIP) -9 $(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar
+	$(RMTREE)             $(PATH_TARGET)/src/kBuild-$(KBUILD_VERSION)/
+
+OTHER_CLEAN += \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar.gz
+
+
+$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar.gz: | $$(dir $$@)
+	$(RM) -f $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar.gz
+	$(RMTREE)             $(PATH_TARGET)/night-src/
+	$(MKDIR) -p           $(PATH_TARGET)/night-src/
+	$(SVN) export .       $(PATH_TARGET)/night-src/kBuild-$(KBUILD_SVN_REV)/
+	$(RMTREE)             $(PATH_TARGET)/night-src/kBuild-$(KBUILD_SVN_REV)/kBuild/bin
+	$(INSTALL) $(KBUILD_SVN_INFO_KMK) \
+	                      $(PATH_TARGET)/night-src/kBuild-$(KBUILD_SVN_REV)/SvnInfo.kmk
+	$(TAR) cvf $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar \
+	                   -C $(PATH_TARGET)/night-src/ kBuild-$(KBUILD_SVN_REV)/
+	$(GZIP) -9 $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar
+	$(RMTREE)             $(PATH_TARGET)/night-src/kBuild-$(KBUILD_SVN_REV)/
+
+OTHER_CLEAN += \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar.gz
+
+#
+# Creates the binary tarballs.
+#
+$(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar.gz: | $$(dir $$@)
+	$(RM) -f $(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar $(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar.gz
+	$(RMTREE)             $(PATH_TARGET)/bin/
+	$(MKDIR) -p           $(PATH_TARGET)/bin/kBuild-$(KBUILD_VERSION)/
+	$(SVN) export kBuild/ $(PATH_TARGET)/bin/kBuild-$(KBUILD_VERSION)/kBuild/
+	$(TAR) cvf $(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar \
+	                   -C $(PATH_TARGET)/bin/ kBuild-$(KBUILD_VERSION)/
+	$(GZIP) -9 $(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar
+	$(RMTREE)             $(PATH_TARGET)/bin/kBuild-$(KBUILD_VERSION)/
+
+OTHER_CLEAN += \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar.gz
+
+
+$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar.gz: | $$(dir $$@)
+	$(RM) -f $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar.gz
+	$(RMTREE)             $(PATH_TARGET)/night-bin/
+	$(MKDIR) -p           $(PATH_TARGET)/night-bin/kBuild-$(KBUILD_SVN_REV)/
+	$(SVN) export kBuild/ $(PATH_TARGET)/night-bin/kBuild-$(KBUILD_SVN_REV)/kBuild/
+	$(TAR) cvf $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar \
+	                   -C $(PATH_TARGET)/night-bin/ kBuild-$(KBUILD_SVN_REV)/
+	$(GZIP) -9 $(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar
+	$(RMTREE)             $(PATH_TARGET)/night-bin/kBuild-$(KBUILD_SVN_REV)/
+
+OTHER_CLEAN += \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar.gz
+
+
+#
+# Aliases
+#
+tarballs: \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar.gz \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar.gz \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar.gz \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar.gz
+
+release: \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION).tar.gz \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-src.tar.gz \
+	$(PATH_TARGET)/kBuild-$(KBUILD_VERSION)-all.tar.gz
+
+nightly: \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV).tar.gz \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-src.tar.gz \
+	$(PATH_TARGET)/kBuild-$(KBUILD_SVN_REV)-all.tar.gz
+
+.PHONY: tarballs release nightly
+
+include $(PATH_KBUILD)/footer.kmk
+
+
Index: /tags/kBuild-0.1.4/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/Makefile.kmk	(revision 1780)
@@ -0,0 +1,76 @@
+# $Id$
+## @file
+# Top-Level Sub-Makefile for kBuild.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = .
+include $(KBUILD_PATH)/subheader.kmk
+
+include $(PATH_SUB_CURRENT)/src/Makefile.kmk
+
+
+ifdef NIX_INSTALL_DIR
+#
+# When doing a unix install, install all the kBuild scripts.
+#
+INSTALLS += kBuild
+kBuild_INST = $(NIX_INSTALL_DIR_SHARE)
+kBuild_SOURCES := \
+        $(foreach src,\
+			$(wildcard \
+				kBuild/*.kmk \
+				kBuild/tools/*.kmk \
+				kBuild/sdks/*.kmk \
+				kBuild/msgstyles/* \
+				kBuild/templates/*),\
+			$(src)=>$(subst kBuild/,,$(src)))
+endif
+
+#
+# And install any binary only tools and dlls.
+#
+INSTALLS += kBuild_bin
+kBuild_bin_INST = $(TEMPLATE_BIN_INST)
+kBuild_bin_SOURCES =
+
+kBuild_bin_SOURCES.os2 = \
+	kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc062.dll=>libc062.dll
+
+if1of ($(KBUILD_TARGET), nt win)
+kBuild_bin_SOURCES.$(KBUILD_TARGET) = \
+	kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/kmk_ash.exe=>kmk_ash.exe \
+	kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/cygwin1.dll=>cygwin1.dll
+kBuild_bin_SOURCES.$(KBUILD_TARGET).x86 = \
+	kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/msvcr71.dll=>msvcr71.dll
+kBuild_bin_SOURCES.$(KBUILD_TARGET).amd64 = \
+	kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/Microsoft.VC80.CRT/msvcr80.dll=>Microsoft.VC80.CRT/msvcr80.dll \
+	kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest=>Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest
+kBuild_bin_SOURCES.profile = \
+	D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/bin/kPrf2.dll \
+	D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/bin/kPrf2WinApiWrappers.dll
+endif
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
Index: /tags/kBuild-0.1.4/VSlickMacros/kdev.e
===================================================================
--- /tags/kBuild-0.1.4/VSlickMacros/kdev.e	(revision 1780)
+++ /tags/kBuild-0.1.4/VSlickMacros/kdev.e	(revision 1780)
@@ -0,0 +1,3276 @@
+/* $Id$  -*- tab-width: 4 c-indent-level: 4 -*- */
+/**
+ * Visual SlickEdit Documentation Macros.
+ */
+
+/*
+ * Copyright (c) 1999-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ * 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
+ *
+ */
+
+/***
+ *
+ * This define the following keys:
+ *---------------------------------
+ * Ctrl+Shift+C: Class description box.
+ * Ctrl+Shift+F: Function/method description box.
+ * Ctrl+Shift+M: Module(file) description box
+ * Ctrl+Shift+O: One-liner (comment)
+ *
+ * Ctrl+Shift+G: Global box
+ * Ctrl+Shift+H: Header box
+ * Ctrl+Shift+E: Exported Symbols
+ * Ctrl+Shift+I: Internal function box
+ * Ctrl+Shift+K: Const/macro box
+ * Ctrl+Shift+S: Struct/Typedef box
+ *
+ * Ctrl+Shift+A: Signature+Date marker
+ * Ctrl+Shift+P: Mark line as change by me
+ *
+ * Ctrl+Shift+T: Update project tagfile.
+ * Ctrl+Shift+L: Load document variables.
+ *
+ * Ctrl+Shift+B: KLOGENTRYX(..)
+ * Ctrl+Shift+E: KLOGEXIT(..)
+ * Ctrl+Shift+N: Do kLog stuff for the current file. No questions.
+ * Ctrl+Shift+Q: Do kLog stuff for the current file. Ask a lot of questions.
+ *
+ * Remember to set the correct sOdin32UserName, sOdin32UserEmail and sOdin32UserInitials
+ * before compiling and loading the macros into Visual SlickEdit.
+ *
+ * These macros are compatible with both 3.0(c) and 4.0(b).
+ *
+ */
+defeventtab default_keys
+def  'C-S-A' = k_signature
+def  'C-S-C' = k_javadoc_classbox
+def  'C-S-E' = k_box_exported
+def  'C-S-F' = k_javadoc_funcbox
+def  'C-S-G' = k_box_globals
+def  'C-S-H' = k_box_headers
+def  'C-S-I' = k_box_intfuncs
+def  'C-S-K' = k_box_consts
+def  'C-S-M' = k_javadoc_moduleheader
+def  'C-S-O' = k_oneliner
+def  'C-S-P' = k_mark_modified_line
+def  'C-S-S' = k_box_structs
+def  'C-S-T' = odin32_maketagfile
+def  'C-S-L' = k_style_load
+
+//optional stuff
+//def  'C-S-Q' = klib_klog_file_ask
+//def  'C-S-N' = klib_klog_file_no_ask
+//def  'C-S-1' = klib_klogentry
+//def  'C-S-3' = klib_klogexit
+
+
+//MARKER.  Editor searches for this line!
+#pragma option(redeclvars, on)
+#include 'slick.sh'
+#ifndef VS_TAGDETAIL_context_args
+/* newer vslick version. */
+#include 'tagsdb.sh'
+//#pragma option(strict,on)
+/*#else: Version 4.0 (OS/2) */
+#endif
+
+/* Remeber to change these! */
+static _str skUserInitials  = "bird";
+static _str skUserName      = "knut st. osmundsen";
+static _str skUserEmail     = "bird-src-spam@anduin.net";
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+static _str     skCodeStyle     = 'Opt2Ind4'; /* coding style scheme. */
+static _str     skDocStyle      = 'javadoc';/* options: javadoc, */
+static _str     skLicense       = 'GPL';    /* options: GPL, LGPL, Odin32, Confidential */
+static _str     skCompany       = '';       /* empty or company name for copyright */
+static _str     skProgram       = '';       /* Current program name - used by [L]GPL */
+static _str     skChange        = '';       /* Current change identifier. */
+
+static int      ikStyleWidth    = 80;       /* The page width of the style. */
+static boolean  fkStyleFullHeaders = false; /* false: omit some tags. */
+static int      ikStyleOneliner = 41;       /* The oneline comment column. */
+static int      ikStyleModifyMarkColumn = 105;
+static boolean  fkStyleBoxTag   = false;    /* true: Include tag in k_box_start. */
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+/**
+ * Gets iso date.
+ * @returns ISO formatted date.
+ */
+static _str k_date()
+{
+    int i,j;
+    _str date;
+
+    date = _date('U');
+    i = pos("/", date);
+    j = pos("/", date, i+1);
+    _str month = substr(date, 1, i-1);
+    if (length(month) == 1) month = '0'month;
+    _str day   = substr(date, i+1, j-i-1);
+    if (length(day)   == 1) day   = '0'day;
+    _str year  = substr(date, j+1);
+    return year"-"month"-"day;
+}
+
+
+/**
+ * Get the current year.
+ * @returns   Current year string.
+ */
+static _str k_year()
+{
+    _str date = _date('U');
+    return  substr(date, pos("/",date, pos("/",date)+1)+1, 4);
+}
+
+
+/**
+ * Aligns a value up to a given alignment.
+ */
+static int k_alignup(int iValue, iAlign)
+{
+    if (iAlign <= 0)
+    {
+        message('k_alignup: iValue='iValue ' iAlign='iAlign);
+        iAlign = 4;
+    }
+    return ((iValue intdiv iAlign) + 1) * iAlign;
+}
+
+
+/**
+ * Reads the comment setup for this lexer/extension .
+ *
+ * @returns Success indicator.
+ * @param   sLeft       Left comment. (output)
+ * @param   sRight      Right comment. (output)
+ * @param   iColumn     Comment mark column. (1-based) (output)
+ * @param   sExt        The extension to lookup defaults to the current one.
+ * @param   sLexer      The lexer to lookup defaults to the current one.
+ * @remark  This should be exported from box.e, but unfortunately it isn't.
+ */
+static boolean k_commentconfig(_str &sLeft, _str &sRight, int &iColumn, _str sExt = p_extension, _str sLexer = p_lexer_name)
+{
+    /* init returns */
+    sLeft = sRight = '';
+    iColumn = 0;
+
+    /*
+     * Get comment setup from the lexer.
+     */
+    _str sLine = '';
+    if (sLexer)
+    {
+        /* multiline */
+        rc = _ini_get_value(slick_path_search("user.vlx"), sLexer, 'mlcomment', sLine);
+        if (rc)
+            rc = _ini_get_value(slick_path_search("vslick.vlx"), sLexer, 'mlcomment', sLine);
+        if (!rc)
+        {
+            sLeft  = strip(word(sLine, 1));
+            sRight = strip(word(sLine, 2));
+            if (sLeft != '' && sRight != '')
+                return true;
+        }
+
+        /* failed, try single line. */
+        rc = _ini_get_value(slick_path_search("user.vlx"), sLexer, 'linecomment', sLine);
+        if (rc)
+            rc = _ini_get_value(slick_path_search("vslick.vlx"), sLexer, 'linecomment', sLine);
+        if (!rc)
+        {
+            sLeft = strip(word(sLine, 1));
+            sRight = '';
+            iColumn = 0;
+            _str sTmp = word(sLine, 2);
+            if (isnumber(sTmp))
+                iColumn = (int)sTmp;
+            if (sLeft != '')
+                return true;
+        }
+    }
+
+    /*
+     * Read the nonboxchars and determin user or default box.ini.
+     */
+    _str sFile = slick_path_search("ubox.ini");
+    boolean frc = _ini_get_value(sFile, sExt, 'nonboxchars', sLine);
+    if (frc)
+    {
+        sFile = slick_path_search("box.ini");
+        frc = _ini_get_value(sFile, sExt, 'nonboxchars', sLine);
+    }
+
+    if (!frc)
+    {   /*
+         * Found extension.
+         */
+        sLeft = strip(eq_name2value('left',sLine));
+        if (sLeft  == '\e') sLeft = '';
+        sRight = strip(eq_name2value('right',sLine));
+        if (sRight == '\e') sRight = '';
+
+        /* Read comment column too */
+        frc = _ini_get_value(sFile, sExt, 'comment_col', sLine);
+        if (frc)
+        {
+            iColumn = eq_name2value('comment_col', sLine);
+            if (iColumn == '\e') iColumn = 0;
+        }
+        else
+            iColumn = 0;
+        return true;
+    }
+
+    /* failure */
+    sLeft = sRight = '';
+    iColumn = 0;
+
+    return false;
+}
+
+
+/**
+ * Checks if current file only support line comments.
+ * @returns True / False.
+ * @remark  Use builtin extension stuff!
+ */
+static boolean k_line_comment()
+{
+    _str    sRight = '';
+    _str    sLeft = '';
+    int     iColumn;
+    boolean fLineComment = false;
+    if (k_commentconfig(sLeft, sRight, iColumn))
+        fLineComment = (sRight == '' || iColumn > 0);
+    return fLineComment;
+}
+
+
+
+#define KIC_CURSOR_BEFORE 1
+#define KIC_CURSOR_AFTER  2
+#define KIC_CURSOR_AT_END 3
+
+/**
+ * Insert a comment at current or best fitting position in the text.
+ * @param   sStr            The comment to insert.
+ * @param   iCursor         Where to put the cursor.
+ * @param   iPosition       Where to start the comment.
+ *                          Doesn't apply to column based source.
+ *                          -1 means at cursor position. (default)
+ *                          >0 means at end of line, but not before this column (1-based).
+ *                             This also implies a min of one space to EOL.
+ */
+void k_insert_comment(_str sStr, int iCursor, int iPosition = -1)
+{
+    _str    sLeft;
+    _str    sRight;
+    int     iColumn;
+    if (!k_commentconfig(sLeft, sRight, iColumn))
+    {
+        sLeft = '/*'; sRight = '*/'; iColumn = 0;
+    }
+
+    int iCol = 0;
+    if (iColumn <= 0)
+    {   /*
+         * not column based source
+         */
+
+        /* position us first */
+        if (iPosition > 0)
+        {
+            end_line();
+            do {
+                _insert_text(" ");
+            } while (p_col < iPosition);
+        }
+
+        /* insert comment saving the position for _BEFORE. */
+        iCol = p_col;
+        _insert_text(sLeft:+' ':+sStr);
+        if (iCursor == KIC_CURSOR_AT_END)
+            iCol = p_col;
+        /* right comment delimiter? */
+        if (sRight != '')
+            _insert_text(' ':+sRight);
+    }
+    else
+    {
+        if (p_col >= iColumn)
+            _insert_text("\n");
+        do { _insert_text(" "); } while (p_col < iColumn);
+        if (iCursor == KIC_CURSOR_BEFORE)
+            iCol = p_col;
+        _insert_text(sLeft:+' ':+sStr);
+        if (iCursor == KIC_CURSOR_AT_END)
+            iCol = p_col;
+    }
+
+    /* set cursor. */
+    if (iCursor != KIC_CURSOR_AFTER)
+        p_col = iCol;
+}
+
+
+/**
+ * Gets the comment prefix or postfix.
+ * @returns Comment prefix or postfix.
+ * @param   fRight  If clear left comment string - default.
+ *                  If set right comment string.
+ */
+static _str k_comment(boolean fRight = false)
+{
+    _str sLeft, sRight;
+    int iColumn;
+    _str sComment = '/*';
+    if (k_commentconfig(sLeft, sRight, iColumn))
+        sComment = (!fRight || iColumn > 0 ? sLeft : sRight);
+
+    return strip(sComment);
+}
+
+
+/*******************************************************************************
+*   BOXES                                                                      *
+*******************************************************************************/
+
+/**
+ * Inserts the first line in a box.
+ * @param     sTag  Not used - box tag.
+ */
+static void k_box_start(sTag)
+{
+    _str sLeft, sRight;
+    int iColumn;
+    if (!k_commentconfig(sLeft, sRight, iColumn))
+        return;
+    _begin_line();
+    if (iColumn >= 0)
+        while (p_col < iColumn)
+           _insert_text(" ");
+
+    _str sText = sLeft;
+    if (sTag != '' && fkStyleBoxTag)
+    {
+        if (substr(sText, length(sText)) != '*')
+            sText = sText:+'*';
+        sText = sText:+sTag;
+    }
+
+    int i;
+    for (i = length(sText); i <= ikStyleWidth - p_col; i++)
+        sText = sText:+'*';
+    sText = sText:+"\n";
+
+    _insert_text(sText);
+}
+
+
+/**
+ * Places a string, sStr, into a line started and ended by '*'.
+ * @param   sStr    Text to have between the '*'s.
+ */
+static void k_box_line(_str sStr)
+{
+    _str sLeft, sRight;
+    int iColumn;
+    if (!k_commentconfig(sLeft, sRight, iColumn))
+        return;
+    if (iColumn >= 0)
+        while (p_col < iColumn)
+           _insert_text(" ");
+
+    _str sText = '';
+    if (k_line_comment())
+        sText = sLeft;
+    if (sText == '' || substr(sText, length(sText)) != '*')
+        sText = sText:+'*';
+
+    sText = sText:+' ';
+    int i;
+    for (i = length(sText); i < p_SyntaxIndent; i++)
+        sText = sText:+' ';
+
+    sText = sText:+sStr;
+
+    for (i = length(sText) + 1; i <= ikStyleWidth - p_col; i++)
+        sText = sText:+' ';
+    sText = sText:+"*\n";
+
+    _insert_text(sText);
+}
+
+
+/**
+ * Inserts the last line in a box.
+ */
+static void k_box_end()
+{
+    _str sLeft, sRight;
+    int iColumn, i;
+    if (!k_commentconfig(sLeft, sRight, iColumn))
+        return;
+    if (iColumn >= 0)
+        while (p_col < iColumn)
+           _insert_text(" ");
+
+    _str sText = '';
+    if (k_line_comment())
+        sText = sLeft;
+    for (i = length(sText) + length(sRight); i <= ikStyleWidth - p_col; i++)
+        sText = sText:+'*';
+    sText = sText:+sRight:+"\n";
+
+    _insert_text(sText);
+}
+
+
+
+/*******************************************************************************
+*   FUNCTION AND CODE PARSERS                                                  *
+*******************************************************************************/
+/**
+ * Moves cursor to nearest function start.
+ * @returns 0 if ok.
+ *          -1 on failure.
+ */
+static int k_func_goto_nearest_function()
+{
+    boolean fFix = false;               /* cursor at function fix. (last function) */
+    int cur_line = p_line;
+    int prev_line = -1;
+    int next_line = -1;
+    typeless org_pos;
+    _save_pos2(org_pos);
+
+    if (!next_proc(1))
+    {
+        next_line = p_line;
+        if (!prev_proc(1) && p_line == cur_line)
+        {
+            _restore_pos2(org_pos);
+            return 0;
+        }
+        _restore_pos2(org_pos);
+        _save_pos2(org_pos);
+    }
+    else
+    {
+        p_col++;                        /* fixes problem with single function files. */
+        fFix = true;
+    }
+
+    if (!prev_proc(1))
+    {
+        prev_line = p_line;
+        if (!next_proc(1) && p_line == cur_line)
+        {
+            _restore_pos2(org_pos);
+            return 0;
+        }
+        _restore_pos2(org_pos);
+        _save_pos2(org_pos);
+    }
+
+
+    if (prev_line != -1 && (next_line == -1 || cur_line - prev_line <= next_line - cur_line))
+    {
+        if (fFix)
+            p_col++;
+        prev_proc(1);
+        return 0;
+    }
+
+    if (next_line != -1 && (prev_line == -1 || cur_line - prev_line > next_line - cur_line))
+    {
+        next_proc();
+        return 0;
+    }
+
+    _restore_pos2(org_pos);
+    return -1;
+}
+
+
+/**
+ * Check if nearest function is a prototype.
+ * @returns True if function prototype.
+ *          False if not function prototype.
+ */
+static boolean k_func_prototype()
+{
+    /*
+     * Check if this is a real function implementation.
+     */
+    typeless procpos;
+    _save_pos2(procpos);
+    if (!k_func_goto_nearest_function())
+    {
+        int proc_line = p_line;
+
+        if (!k_func_searchcode("{"))
+        {
+            prev_proc();
+            if (p_line != proc_line)
+            {
+                _restore_pos2(procpos);
+                return true;
+            }
+        }
+    }
+    _restore_pos2(procpos);
+
+    return false;
+}
+
+
+/**
+ * Gets the name fo the current function.
+ * @returns The current function name.
+ */
+static _str k_func_getfunction_name()
+{
+    _str sFunctionName = current_proc();
+    if (!sFunctionName)
+        sFunctionName = "";
+    //say 'functionanme='sFunctionName;
+    return sFunctionName;
+}
+
+
+/**
+ * Goes to the neares function and gets its parameters.
+ * @remark  Should be reimplemented to use tags (if someone can figure out how to query that stuff).
+ */
+static _str k_func_getparams()
+{
+    typeless org_pos;
+    _save_pos2(org_pos);
+
+    /*
+     * Try use the tags first.
+     */
+    _UpdateContext(true);
+    int context_id = tag_current_context();
+    if (context_id <= 0)
+    {
+        k_func_goto_nearest_function();
+        context_id = tag_current_context();
+    }
+    if (context_id > 0)
+    {
+        _str args = '';
+        _str type = '';
+       tag_get_detail2(VS_TAGDETAIL_context_args, context_id, args);
+       tag_get_detail2(VS_TAGDETAIL_context_type, context_id, type);
+       if (tag_tree_type_is_func(type))
+           return args
+           //caption = tag_tree_make_caption_fast(VS_TAGMATCH_context,context_id,true,true,false);
+    }
+
+    /*
+     * Go to nearest function.
+     */
+    if (    !k_func_goto_nearest_function()
+        &&  !k_func_searchcode("(")     /* makes some assumptions. */
+        )
+    {
+        /*
+         * Get parameters.
+         */
+        typeless posStart;
+        _save_pos2(posStart);
+        long offStart = _QROffset();
+        if (!find_matching_paren())
+        {
+            long offEnd = _QROffset();
+            _restore_pos2(posStart);
+            p_col++;
+            _str sParamsRaw = strip(get_text((int)(offEnd - offStart - 1)));
+
+
+            /*
+             * Remove new lines and double spaces within params.
+             */
+            _str sParams = "";
+
+            int i;
+            _str chPrev;
+            for (i = 1, chPrev = ' '; i <= length(sParamsRaw); i++)
+            {
+                _str ch = substr(sParamsRaw, i, 1);
+
+                /*
+                 * Do fixups.
+                 */
+                if (ch == " " && chPrev == " ")
+                        continue;
+
+                if ((ch :== "\n") || (ch :== "\r") || (ch :== "\t"))
+                {
+                    if (chPrev == ' ')
+                        continue;
+                    ch = ' ';
+                }
+
+                if (ch == ',' && chPrev == ' ')
+                {
+                    sParams = substr(sParams, 1, length(sParams) - 1);
+                }
+
+                if (ch == '*')
+                {
+                    if (chPrev != ' ')
+                        sParams = sParams :+ ' * ';
+                    else
+                        sParams = sParams :+ '* ';
+                    chPrev = ' ';
+                }
+                else
+                {
+                    sParams = sParams :+ ch;
+                    chPrev = ch;
+                }
+
+            } /* for */
+
+            sParams = strip(sParams);
+            if (sParams == 'void' || sParams == 'VOID')
+                sParams = "";
+            _restore_pos2(org_pos);
+            return sParams;
+        }
+        else
+            message("find_matchin_paren failed");
+    }
+
+    _restore_pos2(org_pos);
+    return false;
+}
+
+
+
+/**
+ * Enumerates the parameters to the function.
+ * @param   sParams     Parameter string from k_func_getparams.
+ * @param   iParam      The index (0-based) of the parameter to get.
+ * @param   sType       Type. (output)
+ * @param   sName       Name. (output)
+ * @param   sDefault    Default value. (output)
+ * @remark  Doesn't perhaps handle function pointers very well (I think)?
+ * @remark  Should be reimplemented to use tags (if someone can figure out how to query that stuff).
+ */
+static int k_func_enumparams(_str sParams, int iParam, _str &sType, _str &sName, _str &sDefault)
+{
+    int     i;
+    int     iParLevel;
+    int     iCurParam;
+    int     iStartParam;
+
+    sType = sName = sDefault = "";
+
+    /* no use working on empty string! */
+    if (length(sParams) == 0)
+        return -1;
+
+    /* find the parameter in question */
+    for (iStartParam = i = 1, iParLevel = iCurParam = 0; i <= length(sParams); i++)
+    {
+        _str ch = substr(sParams, i, 1);
+        if (ch == ',' && iParLevel == 0)
+        {
+            /* is it this parameter ? */
+            if (iParam == iCurParam)
+                break;
+
+            iCurParam++;
+            iStartParam = i + 1;
+        }
+        else if (ch == '(')
+            iParLevel++;
+        else if (ch == ')')
+            iParLevel--;
+    }
+
+    /* did we find the parameter? */
+    if (iParam == iCurParam)
+    {   /* (yeah, we did!) */
+        _str sArg = strip(substr(sParams, iStartParam, i - iStartParam));
+        /* remove M$ stuff */
+        sArg = stranslate(sArg, "", "IN", "E");
+        sArg = stranslate(sArg, "", "OUT", "E");
+        sArg = stranslate(sArg, "", "OPTIONAL", "E");
+        sArg = strip(sArg);
+
+        /* lazy approach, which doens't support function types */
+
+        if (pos('=', sParams) > 0)      /* default */
+        {
+            sDefault = strip(substr(sParams, pos('=', sParams) + 1));
+            sArg = strip(substr(sArg, 1, pos('=', sParams) - 1));
+        }
+
+        for (i = length(sArg); i > 1; i--)
+        {
+            _str ch = substr(sArg, i, 1);
+            if (    !(ch >= 'a' &&  ch <= 'z')
+                &&  !(ch >= 'A' &&  ch <= 'Z')
+                &&  !(ch >= '0'  && ch <= '9')
+                &&  ch != '_' && ch != '$')
+                break;
+        }
+        if (sArg == "...")
+            i = 0;
+        sName = strip(substr(sArg, i + 1));
+        sType = strip(substr(sArg, 1, i));
+
+        return 0;
+    }
+
+    return -1;
+}
+
+
+/**
+ * Counts the parameters to the function.
+ * @param   sParams     Parameter string from k_func_getparams.
+ * @remark  Should be reimplemented to use tags (if someone can figure out how to query that stuff).
+ */
+static int k_func_countparams(_str sParams)
+{
+    int     i;
+    int     iParLevel;
+    int     iCurParam;
+    _str    sType = "", sName = "", sDefault = "";
+
+    /* check for 0 parameters */
+    if (length(sParams) == 0)
+        return 0;
+
+    /* find the parameter in question */
+    for (i = 1, iParLevel = iCurParam = 0; i <= length(sParams); i++)
+    {
+        _str ch = substr(sParams, i, 1);
+        if (ch == ',' && iParLevel == 0)
+        {
+            iCurParam++;
+        }
+        else if (ch == '(')
+            iParLevel++;
+        else if (ch == ')')
+            iParLevel--;
+    }
+
+    return iCurParam + 1;
+}
+
+
+/**
+ * Gets the return type.
+ */
+static _str k_func_getreturntype(boolean fPureType = false)
+{
+    typeless org_pos;
+    _save_pos2(org_pos);
+
+    /*
+     * Go to nearest function.
+     */
+    if (!k_func_goto_nearest_function())
+    {
+        /*
+         * Return type is from function start to function name...
+         */
+        typeless posStart;
+        _save_pos2(posStart);
+        long offStart = _QROffset();
+
+        if (!k_func_searchcode("("))               /* makes some assumptions. */
+        {
+            prev_word();
+            long offEnd = _QROffset();
+            _restore_pos2(posStart);
+            _str sTypeRaw = strip(get_text((int)(offEnd - offStart)));
+
+            //say 'sTypeRaw='sTypeRaw;
+            /*
+             * Remove static, inline, _Optlink, stdcall, EXPENTRY etc.
+             */
+            if (fPureType)
+            {
+                sTypeRaw = stranslate(sTypeRaw, "", "__static__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__static", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "static__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "static", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__inline__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__inline", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "inline__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "inline", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "EXPENTRY", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_Optlink", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__stdcall", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__cdecl", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_cdecl", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "cdecl", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__PASCAL", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_PASCAL", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "PASCAL", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__Far32__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__Far32", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "Far32__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_Far32_", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_Far32", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "Far32_", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "Far32", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__far", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_far", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "far", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__near", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_near", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "near", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__loadds__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__loadds", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "loadds__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_loadds_", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_loadds", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "loadds_", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "loadds", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__loades__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__loades", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "loades__", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_loades_", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "_loades", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "loades_", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "loades", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "WIN32API", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "WINAPI", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "LDRCALL", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "KRNLCALL", "I");
+                sTypeRaw = stranslate(sTypeRaw, "", "__operator__", "I"); /* operator fix */
+                sTypeRaw = stranslate(sTypeRaw, "", "__operator", "I");   /* operator fix */
+                sTypeRaw = stranslate(sTypeRaw, "", "operator__", "I");   /* operator fix */
+                sTypeRaw = stranslate(sTypeRaw, "", "operator", "I");     /* operator fix */
+                sTypeRaw = stranslate(sTypeRaw, "", "IN", "E");
+                sTypeRaw = stranslate(sTypeRaw, "", "OUT", "E");
+                sTypeRaw = stranslate(sTypeRaw, "", "OPTIONAL", "E");
+            }
+
+            /*
+             * Remove new lines and double spaces within params.
+             */
+            _str sType = "";
+
+            int i;
+            _str chPrev;
+            for (i = 1, chPrev = ' '; i <= length(sTypeRaw); i++)
+            {
+                _str ch = substr(sTypeRaw, i, 1);
+
+                /*
+                 * Do fixups.
+                 */
+                if (ch == " " && chPrev == " ")
+                        continue;
+
+                if ((ch :== "\n") || (ch :== "\r") || (ch :== "\t"))
+                {
+                    if (chPrev == ' ')
+                        continue;
+                    ch = ' ';
+                }
+
+                if (ch == ',' && chPrev == ' ')
+                {
+                    sType = substr(sType, 1, length(sType) - 1);
+                }
+
+                if (ch == '*')
+                {
+                    if (chPrev != ' ')
+                        sType = sType :+ ' * ';
+                    else
+                        sType = sType :+ '* ';
+                    chPrev = ' ';
+                }
+                else
+                {
+                    sType = sType :+ ch;
+                    chPrev = ch;
+                }
+
+            } /* for */
+
+            sType = strip(sType);
+
+            _restore_pos2(org_pos);
+            return sType;
+        }
+        else
+            message('k_func_getreturntype: can''t find ''(''.');
+    }
+
+    _restore_pos2(org_pos);
+    return false;
+}
+
+
+/**
+ * Search for some piece of code.
+ */
+static int k_func_searchcode(_str sSearchString, _str sOptions = "E+")
+{
+    int rc;
+    rc = search(sSearchString, sOptions);
+    while (!rc && !k_func_in_code())
+    {
+        p_col++;
+        rc = search(sSearchString, sOptions);
+    }
+    return rc;
+}
+
+
+/**
+ * Checks if cursor is in code or in comment.
+ * @return  True if cursor in code.
+ */
+static boolean k_func_in_code()
+{
+    typeless searchsave;
+    _save_pos2(searchsave);
+    boolean fRc = !_in_comment();
+    _restore_pos2(searchsave);
+    return fRc;
+}
+
+
+/*
+ * Gets the next piece of code.
+ */
+static _str k_func_get_next_code_text()
+{
+    typeless searchsave;
+    _save_pos2(searchsave);
+    _str ch = k_func_get_next_code_text2();
+    _restore_pos2(searchsave);
+    return ch;
+}
+
+
+/**
+ * Checks if there is more code on the line.
+ */
+static boolean k_func_more_code_on_line()
+{
+    boolean fRc;
+    int     curline = p_line;
+    typeless searchsave;
+    _save_pos2(searchsave);
+    k_func_get_next_code_text2();
+    fRc = curline == p_line;
+    _restore_pos2(searchsave);
+
+    return fRc;
+}
+
+
+/**
+ * Gets the next piece of code.
+ * Doesn't preserver cursor position.
+ */
+static _str k_func_get_next_code_text2()
+{
+    _str ch;
+    do
+    {
+        int curcol = ++p_col;
+        end_line();
+        if (p_col <= curcol)
+        {
+            p_line++;
+            p_col = 1;
+        }
+        else
+            p_col = curcol;
+
+        ch = get_text();
+        //say ch ' ('_asc(ch)')';
+        while (ch == "#")                  /* preprocessor stuff */
+        {
+            p_col = 1;
+            p_line++;
+            ch = get_text();
+            //say ch ' ('_asc(ch)')';
+            continue;
+        }
+    } while (ch :== ' ' || ch :== "\t" || ch :== "\n" || ch :== "\r" || !k_func_in_code());
+
+    return ch;
+}
+
+
+
+
+/*******************************************************************************
+*   JAVA DOC STYLED WORKERS                                                    *
+*******************************************************************************/
+
+/** starts a javadoc documentation box. */
+static void k_javadoc_box_start(_str sStr = '', boolean fDouble = true)
+{
+    _str sLeft, sRight;
+    int iColumn;
+    if (!k_commentconfig(sLeft, sRight, iColumn))
+        return;
+    _begin_line();
+    if (iColumn >= 0)
+        while (p_col < iColumn)
+           _insert_text(" ");
+
+    _str sText = sLeft;
+    if (fDouble)
+        sText = sLeft:+substr(sLeft, length(sLeft), 1);
+    if (sStr != '')
+        sText = sText:+' ':+sStr;
+    sText = sText:+"\n";
+
+    _insert_text(sText);
+}
+
+/** inserts a new line in a javadoc documentation box. */
+static void k_javadoc_box_line(_str sStr = '', int iPadd = 0, _str sStr2 = '', int iPadd2 = 0, _str sStr3 = '')
+{
+    _str sLeft, sRight;
+    int iColumn;
+    if (!k_commentconfig(sLeft, sRight, iColumn))
+        return;
+    if (iColumn >= 0)
+        while (p_col < iColumn)
+           _insert_text(" ");
+
+    _str sText;
+    if (k_line_comment())
+        sText = sLeft;
+    else
+    {
+        sText = sLeft;
+        sText = ' ':+substr(sLeft, length(sLeft));
+    }
+
+    if (sStr != '')
+        sText = sText:+' ':+sStr;
+    if (iPadd > 0)
+    {
+        int i;
+        for (i = length(sText); i < iPadd; i++)
+            sText = sText:+' ';
+
+        if (sStr2 != '')
+            sText = sText:+sStr2;
+
+        if (iPadd2 > 0)
+        {
+            for (i = length(sText); i < iPadd2; i++)
+                sText = sText:+' ';
+
+            if (sStr3 != '')
+                sText = sText:+sStr3;
+        }
+    }
+    sText = sText:+"\n";
+
+    _insert_text(sText);
+}
+
+/** ends a javadoc documentation box. */
+static void k_javadoc_box_end()
+{
+    _str sLeft, sRight;
+    int iColumn;
+    if (!k_commentconfig(sLeft, sRight, iColumn))
+        return;
+    if (iColumn >= 0)
+        while (p_col < iColumn)
+           _insert_text(" ");
+
+    _str sText;
+    if (k_line_comment())
+        sText = sLeft;
+    else
+    {
+        sText = sRight;
+        /*if (substr(sText, 1, 1) != '*')
+            sText = '*':+sText;*/
+        sText = ' ':+sText;
+    }
+    sText = sText:+"\n";
+
+    _insert_text(sText);
+}
+
+
+/**
+ * Write a Javadoc styled classbox.
+ */
+void k_javadoc_classbox()
+{
+    int     iCursorLine;
+    int     iPadd = k_alignup(12, p_SyntaxIndent);
+
+    k_javadoc_box_start();
+    iCursorLine = p_RLine;
+    k_javadoc_box_line(' ');
+
+    if (fkStyleFullHeaders)
+    {
+        k_javadoc_box_line('@shortdesc', iPadd);
+        k_javadoc_box_line('@dstruct', iPadd);
+        k_javadoc_box_line('@version', iPadd);
+        k_javadoc_box_line('@verdesc', iPadd);
+    }
+    k_javadoc_box_line('@author', iPadd, skUserName ' <' skUserEmail '>');
+    k_javadoc_box_line('@approval', iPadd);
+    k_javadoc_box_end();
+
+    up(p_RLine - iCursorLine);
+    end_line();
+    keyin(' ');
+}
+
+
+/**
+ * Javadoc - functionbox(/header).
+ */
+void k_javadoc_funcbox()
+{
+    int     cArgs = 1;
+    _str    sArgs = "";
+    int     iCursorLine;
+    int     iPadd = k_alignup(11, p_SyntaxIndent);
+    /* look for parameters */
+    boolean fFoundFn = !k_func_goto_nearest_function();
+    if (fFoundFn)
+    {
+        sArgs = k_func_getparams();
+        cArgs = k_func_countparams(sArgs);
+    }
+
+    k_javadoc_box_start();
+    iCursorLine = p_RLine;
+    k_javadoc_box_line(' ');
+    if (file_eq(p_extension, 'asm'))
+        k_javadoc_box_line('@cproto', iPadd);
+    k_javadoc_box_line('@returns', iPadd);
+    if (fFoundFn)
+    {
+        /*
+         * Determin parameter description indent.
+         */
+        int     iPadd2 = 0;
+        int     i;
+        for (i = 0; i < cArgs; i++)
+        {
+            _str sName, sType, sDefault;
+            if (!k_func_enumparams(sArgs, i, sType, sName, sDefault)
+                && iPadd2 < length(sName))
+                iPadd2 = length(sName);
+        }
+        iPadd2 = k_alignup((iPadd + iPadd2), p_SyntaxIndent);
+
+        /*
+         * Insert parameter.
+         */
+        for (i = 0; i < cArgs; i++)
+        {
+            _str sName, sType, sDefault;
+            if (!k_func_enumparams(sArgs, i, sType, sName, sDefault))
+            {
+                _str sStr3 = '';
+                if (sDefault != "")
+                    sStr3 = '(default='sDefault')';
+                k_javadoc_box_line('@param', iPadd, sName, iPadd2, sStr3);
+            }
+            else
+                k_javadoc_box_line('@param', iPadd);
+        }
+    }
+    else
+        k_javadoc_box_line('@param', iPadd);
+
+    if (file_eq(p_extension, 'asm'))
+        k_javadoc_box_line('@uses', iPadd);
+    if (fkStyleFullHeaders)
+    {
+        k_javadoc_box_line('@equiv', iPadd);
+        k_javadoc_box_line('@time', iPadd);
+        k_javadoc_box_line('@sketch', iPadd);
+        k_javadoc_box_line('@status', iPadd);
+        k_javadoc_box_line('@author', iPadd, skUserName ' <' skUserEmail '>');
+        k_javadoc_box_line('@remark', iPadd);
+    }
+    k_javadoc_box_end();
+
+    up(p_RLine - iCursorLine);
+    end_line();
+    keyin(' ');
+}
+
+
+/**
+ * Javadoc module header.
+ */
+void k_javadoc_moduleheader()
+{
+    int iCursorLine;
+    int fSplit = 0;
+
+    _begin_line();
+    k_insert_comment('$':+'I':+'d: $', KIC_CURSOR_AT_END, -1);
+    _end_line();
+    _insert_text("\n");
+
+    k_javadoc_box_start('@file');
+    //if (1)
+    //{
+        fSplit = 1;
+        iCursorLine = p_RLine;
+        k_javadoc_box_line();
+        k_javadoc_box_end();
+        _insert_text("\n");
+        _insert_text(k_comment() "\n");
+    //}
+    //else
+    //{
+    //    k_javadoc_box_line();
+    //    iCursorLine = p_RLine;
+    //    k_javadoc_box_line();
+    //    k_javadoc_box_line();
+    //}
+
+    if (skLicense == 'Confidential')
+    {
+        k_javadoc_box_line(skCompany ' confidential');
+        k_javadoc_box_line();
+    }
+
+    if (skCompany != '')
+    {
+        if (skLicense != 'Confidential')
+            k_javadoc_box_line('Copyright (C) ' k_year() ' ' skCompany);
+        else
+        {
+            k_javadoc_box_line('Copyright (c) ' k_year() ' ' skCompany);
+            k_javadoc_box_line();
+            k_javadoc_box_line('Author: ' skUserName' <' skUserEmail '>');
+        }
+    }
+    else
+        k_javadoc_box_line('Copyright (c) ' k_year() ' 'skUserName' <' skUserEmail '>');
+    k_javadoc_box_line();
+    switch (skLicense)
+    {
+        case 'Odin32':
+            k_javadoc_box_line('Project Odin Software License can be found in LICENSE.TXT.');
+            break;
+
+        case 'GPL':
+            _str sProg = skProgram;
+            if (!fSplit)
+                k_javadoc_box_line();
+            if (sProg == '')
+                sProg = 'This program';
+            else
+            {
+                k_javadoc_box_line('This file is part of ' sProg '.');
+                k_javadoc_box_line();
+            }
+            k_javadoc_box_line(sProg ' is free software; you can redistribute it and/or modify');
+            k_javadoc_box_line('it under the terms of the GNU General Public License as published by');
+            k_javadoc_box_line('the Free Software Foundation; either version 2 of the License, or');
+            k_javadoc_box_line('(at your option) any later version.');
+            k_javadoc_box_line();
+            k_javadoc_box_line(sProg ' is distributed in the hope that it will be useful,');
+            k_javadoc_box_line('but WITHOUT ANY WARRANTY; without even the implied warranty of');
+            k_javadoc_box_line('MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the');
+            k_javadoc_box_line('GNU General Public License for more details.');
+            k_javadoc_box_line();
+            k_javadoc_box_line('You should have received a copy of the GNU General Public License');
+            k_javadoc_box_line('along with ' sProg '; if not, write to the Free Software');
+            k_javadoc_box_line('Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA');
+            break;
+
+        case 'LGPL':
+            sProg = skProgram;
+            if (!fSplit)
+                k_javadoc_box_line();
+            if (sProg == '')
+                sProg = 'This library';
+            else
+            {
+                k_javadoc_box_line('This file is part of ' sProg '.');
+                k_javadoc_box_line();
+            }
+            k_javadoc_box_line(sProg ' is free software; you can redistribute it and/or');
+            k_javadoc_box_line('modify it under the terms of the GNU Lesser General Public');
+            k_javadoc_box_line('License as published by the Free Software Foundation; either');
+            k_javadoc_box_line('version 2.1 of the License, or (at your option) any later version.');
+            k_javadoc_box_line();
+            k_javadoc_box_line(sProg ' is distributed in the hope that it will be useful,');
+            k_javadoc_box_line('but WITHOUT ANY WARRANTY; without even the implied warranty of');
+            k_javadoc_box_line('MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU');
+            k_javadoc_box_line('Lesser General Public License for more details.');
+            k_javadoc_box_line();
+            k_javadoc_box_line('You should have received a copy of the GNU Lesser General Public');
+            k_javadoc_box_line('License along with ' sProg '; if not, write to the Free Software');
+            k_javadoc_box_line('Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA');
+            break;
+
+        case 'Confidential':
+            k_javadoc_box_line('All Rights Reserved');
+            break;
+
+        case 'VirtualBox':
+            k_javadoc_box_line('This file is part of VirtualBox Open Source Edition (OSE), as')
+            k_javadoc_box_line('available from http://www.virtualbox.org. This file is free software;')
+            k_javadoc_box_line('you can redistribute it and/or modify it under the terms of the GNU')
+            k_javadoc_box_line('General Public License (GPL) as published by the Free Software')
+            k_javadoc_box_line('Foundation, in version 2 as it comes in the "COPYING" file of the')
+            k_javadoc_box_line('VirtualBox OSE distribution. VirtualBox OSE is distributed in the')
+            k_javadoc_box_line('hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.')
+            k_javadoc_box_line('')
+            k_javadoc_box_line('Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa')
+            k_javadoc_box_line('Clara, CA 95054 USA or visit http://www.sun.com if you need')
+            k_javadoc_box_line('additional information or have any questions.')
+            break;
+
+        case 'VirtualBoxGPLAndCDDL':
+            k_javadoc_box_line('This file is part of VirtualBox Open Source Edition (OSE), as')
+            k_javadoc_box_line('available from http://www.virtualbox.org. This file is free software;')
+            k_javadoc_box_line('you can redistribute it and/or modify it under the terms of the GNU')
+            k_javadoc_box_line('General Public License (GPL) as published by the Free Software')
+            k_javadoc_box_line('Foundation, in version 2 as it comes in the "COPYING" file of the')
+            k_javadoc_box_line('VirtualBox OSE distribution. VirtualBox OSE is distributed in the')
+            k_javadoc_box_line('hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.')
+            k_javadoc_box_line('')
+            k_javadoc_box_line('The contents of this file may alternatively be used under the terms')
+            k_javadoc_box_line('of the Common Development and Distribution License Version 1.0')
+            k_javadoc_box_line('(CDDL) only, as it comes in the "COPYING.CDDL" file of the')
+            k_javadoc_box_line('VirtualBox OSE distribution, in which case the provisions of the')
+            k_javadoc_box_line('CDDL are applicable instead of those of the GPL.')
+            k_javadoc_box_line('')
+            k_javadoc_box_line('You may elect to license modified versions of this file under the')
+            k_javadoc_box_line('terms and conditions of either the GPL or the CDDL or both.')
+            k_javadoc_box_line('')
+            k_javadoc_box_line('Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa')
+            k_javadoc_box_line('Clara, CA 95054 USA or visit http://www.sun.com if you need')
+            k_javadoc_box_line('additional information or have any questions.')
+            break;
+
+        default:
+
+    }
+    k_javadoc_box_line();
+    k_javadoc_box_end();
+
+    up(p_RLine - iCursorLine);
+    end_line();
+    keyin(' ');
+}
+
+
+
+
+
+
+
+/*******************************************************************************
+*   Keyboard Shortcuts                                                         *
+*******************************************************************************/
+/** Makes global box. */
+void k_box_globals()
+{
+    k_box_start('Global');
+    k_box_line('Global Variables');
+    k_box_end();
+}
+
+/** Makes header box. */
+void k_box_headers()
+{
+    k_box_start("Header");
+    k_box_line("Header Files");
+    k_box_end();
+}
+
+/** Makes internal function box. */
+void k_box_intfuncs()
+{
+    k_box_start("IntFunc");
+    k_box_line("Internal Functions");
+    k_box_end();
+}
+
+/** Makes def/const box. */
+void k_box_consts()
+{
+    k_box_start("Const");
+    k_box_line("Defined Constants And Macros");
+    k_box_end();
+}
+
+/** Structure box */
+void k_box_structs()
+{
+    k_box_start("Struct");
+    k_box_line("Structures and Typedefs");
+    k_box_end();
+}
+
+/** Makes exported symbols box. */
+void k_box_exported()
+{
+    k_box_start('Exported');
+    k_box_line('Exported Symbols');
+    k_box_end();
+}
+
+
+
+/** oneliner comment */
+void k_oneliner()
+{
+    _str sLeft, sRight;
+    int iColumn;
+    if (    k_commentconfig(sLeft, sRight, iColumn)
+        &&  iColumn > 0)
+    {   /* column based needs some tricky repositioning. */
+        _end_line();
+        if (p_col > iColumn)
+        {
+            _begin_line();
+            _insert_text("\n\r");
+            up();
+        }
+    }
+    k_insert_comment("", KIC_CURSOR_AT_END, ikStyleOneliner);
+}
+
+/** mark line as modified. */
+void k_mark_modified_line()
+{
+    /* not supported for column based sources */
+    _str sLeft, sRight;
+    int iColumn;
+    if (    !k_commentconfig(sLeft, sRight, iColumn)
+        ||  iColumn > 0)
+        return;
+    _str sStr;
+    if (skChange != '')
+        sStr = skChange ' (' skUserInitials ')';
+    else
+        sStr = skUserInitials;
+    k_insert_comment(sStr, KIC_CURSOR_BEFORE, ikStyleModifyMarkColumn);
+    down();
+}
+
+
+/**
+ * Inserts a signature. Form: "//Initials ISO-date:"
+ * @remark    defeventtab
+ */
+void k_signature()
+{
+    /* kso I5-10000 2002-09-10: */
+    _str sSig;
+    if (skChange != '')
+        sSig = skUserInitials ' ' skChange ' ' k_date() ': ';
+    else
+        sSig = skUserInitials ' ' k_date() ': ';
+    k_insert_comment(sSig, KIC_CURSOR_AT_END);
+}
+
+
+/*******************************************************************************
+*   kLIB Logging                                                               *
+*******************************************************************************/
+/**
+ * Hot-Key: Inserts a KLOGENTRY statement at start of nearest function.
+ */
+void klib_klogentry()
+{
+    typeless org_pos;
+    _save_pos2(org_pos);
+
+    /*
+     * Go to nearest function.
+     */
+    if (!k_func_goto_nearest_function())
+    {
+        /*
+         * Get parameters.
+         */
+        _str sParams = k_func_getparams();
+        if (sParams)
+        {
+            _str sRetType = k_func_getreturntype(true);
+            if (!sRetType || sRetType == "")
+                sRetType = "void";      /* paranoia! */
+
+            /*
+             * Insert text.
+             */
+            if (!k_func_searchcode("{"))
+            {
+                p_col++;
+                int cArgs = k_func_countparams(sParams);
+                if (cArgs > 0)
+                {
+                    _str sArgs = "";
+                    int i;
+                    for (i = 0; i < cArgs; i++)
+                    {
+                        _str sType, sName, sDefault;
+                        if (!k_func_enumparams(sParams, i, sType, sName, sDefault))
+                            sArgs = sArgs', 'sName;
+                    }
+
+                    _insert_text("\n    KLOGENTRY"cArgs"(\""sRetType"\",\""sParams"\""sArgs");"); /* todo tab size.. or smart indent */
+                }
+                else
+                    _insert_text("\n    KLOGENTRY0(\""sRetType"\");"); /* todo tab size.. or smart indent */
+
+                /*
+                 * Check if the next word is KLOGENTRY.
+                 */
+                next_word();
+                if (def_next_word_style == 'E')
+                    prev_word();
+                int iIgnorePos = 0;
+                if (substr(cur_word(iIgnorePos), 1, 9) == "KLOGENTRY")
+                    delete_line();
+
+            }
+            else
+                message("didn't find {");
+        }
+        else
+            message("k_func_getparams failed, sParams=" sParams);
+        return;
+    }
+
+    _restore_pos2(org_pos);
+}
+
+
+/**
+ * Hot-Key: Inserts a KLOGEXIT statement at cursor location.
+ */
+void klib_klogexit()
+{
+    typeless org_pos;
+    _save_pos2(org_pos);
+
+    /*
+     * Go to nearest function.
+     */
+    if (!prev_proc())
+    {
+        /*
+         * Get parameters.
+         */
+        _str sType = k_func_getreturntype(true);
+        _restore_pos2(org_pos);
+        if (sType)
+        {
+            boolean fReturn = true;     /* true if an return statment is following the KLOGEXIT statement. */
+
+            /*
+             * Insert text.
+             */
+            int cur_col = p_col;
+            if (sType == 'void' || sType == 'VOID')
+            {   /* procedure */
+                int iIgnorePos;
+                fReturn = cur_word(iIgnorePos) == 'return';
+                if (!fReturn)
+                {
+                    while (p_col <= p_SyntaxIndent)
+                        keyin(" ");
+                }
+
+                _insert_text("KLOGEXITVOID();\n");
+
+                if (fReturn)
+                {
+                    int i;
+                    for (i = 1; i < cur_col; i++)
+                        _insert_text(" ");
+                }
+                search(")","E-");
+            }
+            else
+            {   /* function */
+                _insert_text("KLOGEXIT();\n");
+                int i;
+                for (i = 1; i < cur_col; i++)
+                    _insert_text(" ");
+                search(")","E-");
+
+                /*
+                 * Insert value if possible.
+                 */
+                typeless valuepos;
+                _save_pos2(valuepos);
+                next_word();
+                if (def_next_word_style == 'E')
+                    prev_word();
+                int iIgnorePos;
+                if (cur_word(iIgnorePos) == 'return')
+                {
+                    p_col += length('return');
+                    typeless posStart;
+                    _save_pos2(posStart);
+                    long offStart = _QROffset();
+                    if (!k_func_searchcode(";", "E+"))
+                    {
+                        long offEnd = _QROffset();
+                        _restore_pos2(posStart);
+                        _str sValue = strip(get_text((int)(offEnd - offStart)));
+                        //say 'sValue = 'sValue;
+                        _restore_pos2(valuepos);
+                        _save_pos2(valuepos);
+                        _insert_text(sValue);
+                    }
+                }
+                _restore_pos2(valuepos);
+            }
+
+            /*
+             * Remove old KLOGEXIT statement on previous line if any.
+             */
+            typeless valuepos;
+            _save_pos2(valuepos);
+            int newexitline = p_line;
+            p_line--; p_col = 1;
+            next_word();
+            if (def_next_word_style == 'E')
+                prev_word();
+            int iIgnorePos;
+            if (p_line == newexitline - 1 && substr(cur_word(iIgnorePos), 1, 8) == 'KLOGEXIT')
+                delete_line();
+            _restore_pos2(valuepos);
+
+            /*
+             * Check for missing '{...}'.
+             */
+            if (fReturn)
+            {
+                boolean fFound = false;
+                _save_pos2(valuepos);
+                p_col--; find_matching_paren(); p_col += 2;
+                k_func_searchcode(';', 'E+'); /* places us at the ';' of the return. (hopefully) */
+
+                _str ch = k_func_get_next_code_text();
+                if (ch != '}')
+                {
+                    _restore_pos2(valuepos);
+                    _save_pos2(valuepos);
+                    p_col--; find_matching_paren(); p_col += 2;
+                    k_func_searchcode(';', 'E+'); /* places us at the ';' of the return. (hopefully) */
+                    p_col++;
+                    if (k_func_more_code_on_line())
+                        _insert_text(' }');
+                    else
+                    {
+                        typeless returnget;
+                        _save_pos2(returnget);
+                        k_func_searchcode("return", "E-");
+                        int return_col = p_col;
+                        _restore_pos2(returnget);
+
+                        end_line();
+                        _insert_text("\n");
+                        while (p_col < return_col - p_SyntaxIndent)
+                            _insert_text(' ');
+                        _insert_text('}');
+                    }
+
+                    _restore_pos2(valuepos);
+                    _save_pos2(valuepos);
+                    prev_word();
+                    p_col -= p_SyntaxIndent;
+                    int codecol = p_col;
+                    _insert_text("{\n");
+                    while (p_col < codecol)
+                        _insert_text(' ');
+                }
+
+                _restore_pos2(valuepos);
+            }
+        }
+        else
+            message("k_func_getreturntype failed, sType=" sType);
+        return;
+    }
+
+    _restore_pos2(org_pos);
+}
+
+
+/**
+ * Processes a file - ask user all the time.
+ */
+void klib_klog_file_ask()
+{
+    klib_klog_file_int(true);
+}
+
+
+/**
+ * Processes a file - no questions.
+ */
+void klib_klog_file_no_ask()
+{
+    klib_klog_file_int(false);
+}
+
+
+
+/**
+ * Processes a file.
+ */
+static void klib_klog_file_int(boolean fAsk)
+{
+    show_all();
+    bottom();
+    _refresh_scroll();
+
+    /* ask question so we can get to the right position somehow.. */
+    if (fAsk && _message_box("kLog process this file?", "Visual SlickEdit", MB_YESNO | MB_ICONQUESTION) != IDYES)
+        return;
+
+    /*
+     * Entries.
+     */
+    while (!prev_proc())
+    {
+        //say 'entry main loop: ' k_func_getfunction_name();
+
+        /*
+         * Skip prototypes.
+         */
+        if (k_func_prototype())
+            continue;
+
+        /*
+         * Ask user.
+         */
+        center_line();
+        _refresh_scroll();
+        _str sFunction = k_func_getfunction_name();
+        rc = fAsk ? _message_box("Process this function ("sFunction")?", "Visual SlickEdit", MB_YESNOCANCEL | MB_ICONQUESTION) : IDYES;
+        if (rc == IDYES)
+        {
+            typeless procpos;
+            _save_pos2(procpos);
+            klib_klogentry();
+            _restore_pos2(procpos);
+        }
+        else if (rc == IDNO)
+            continue;
+        else
+            break;
+    }
+
+    /*
+     * Exits.
+     */
+    bottom(); _refresh_scroll();
+    boolean fUserCancel = false;
+    while (!prev_proc() && !fUserCancel)
+    {
+        typeless procpos;
+        _save_pos2(procpos);
+        _str sCurFunction = k_func_getfunction_name();
+        //say 'exit main loop: ' sCurFunction
+
+        /*
+         * Skip prototypes.
+         */
+        if (k_func_prototype())
+            continue;
+
+        /*
+         * Select procedure.
+         */
+        while (   !k_func_searchcode("return", "WE<+")
+               &&  k_func_getfunction_name() == sCurFunction)
+        {
+            //say 'exit sub loop: ' p_line
+            /*
+             * Ask User.
+             */
+            center_line();
+            _refresh_scroll();
+            _str sFunction = k_func_getfunction_name();
+            rc =  fAsk ? _message_box("Process this exit from "sFunction"?", "Visual SlickEdit", MB_YESNOCANCEL | MB_ICONQUESTION) : IDYES;
+            deselect();
+            if (rc == IDYES)
+            {
+                typeless returnpos;
+                _save_pos2(returnpos);
+                klib_klogexit();
+                _restore_pos2(returnpos);
+                p_line++;
+            }
+            else if (rc != IDNO)
+            {
+                fUserCancel = true;
+                break;
+            }
+            p_line++;                       /* just so we won't hit it again. */
+        }
+
+        /*
+         * If void function we'll have to check if there is and return; prior to the ending '}'.
+         */
+        _restore_pos2(procpos);
+        _save_pos2(procpos);
+        _str sType = k_func_getreturntype(true);
+        if (!fUserCancel && sType && (sType == 'void' || sType == 'VOID'))
+        {
+            if (    !k_func_searchcode("{", "E+")
+                &&  !find_matching_paren())
+            {
+                typeless funcend;
+                _save_pos2(funcend);
+                prev_word();
+                int iIgnorePos;
+                if (cur_word(iIgnorePos) != "return")
+                {
+                    /*
+                     * Ask User.
+                     */
+                    _restore_pos2(funcend);
+                    center_line();
+                    _refresh_scroll();
+                    _str sFunction = k_func_getfunction_name();
+                    rc = fAsk ? _message_box("Process this exit from "sFunction"?", "Visual SlickEdit", MB_YESNOCANCEL | MB_ICONQUESTION) : IDYES;
+                    deselect();
+                    if (rc == IDYES)
+                    {
+                        typeless returnpos;
+                        _save_pos2(returnpos);
+                        klib_klogexit();
+                        _restore_pos2(returnpos);
+                    }
+                }
+            }
+        }
+
+        /*
+         * Next proc.
+         */
+        _restore_pos2(procpos);
+    }
+}
+
+
+/*******************************************************************************
+*   Odin32 backward compatibility                                              *
+*******************************************************************************/
+_command void odin32_maketagfile()
+{
+    /* We'll */
+    if (file_match('-p 'maybe_quote_filename(strip_filename(_project_name,'e'):+TAG_FILE_EXT),1) != "")
+    {
+        _project_update_files_retag(false,false,false,false);
+        /*
+        RetagFilesInTagFile2(project_tag_file, orig_view_id, temp_view_id, rebuild_all, false,
+                             doRemove,false,true,true);*/
+    }
+    else
+        _project_update_files_retag(true,false,false,true);
+}
+
+_command void odin32_setcurrentdir()
+{
+    //_ini_get_value(_project_name,"COMPILER","WORKINGDIR", workingdir);
+    //cd(workingdir);
+    /* Go the the directory containing the project filename */
+    cd(strip_filename(_project_name, 'NE'));
+}
+
+
+
+
+/*******************************************************************************
+*   Styles                                                                     *
+*******************************************************************************/
+static _str StyleLanguages[] =
+{
+    "c",
+    "e",
+    "java"
+};
+
+struct StyleScheme
+{
+    _str name;
+    _str settings[];
+};
+
+static StyleScheme StyleSchemes[] =
+{
+    {
+        "Opt2Ind4",
+        {
+           "orig_tabsize=4",
+           "syntax_indent=4",
+           "tabsize=4",
+           "align_on_equal=1",
+           "pad_condition_state=1",
+           "indent_with_tabs=0",
+           "nospace_before_paren=0",
+           "indent_comments=1",
+           "indent_case=1",
+           "statement_comment_col=0",
+           "disable_bestyle=0",
+           "decl_comment_col=0",
+           "bestyle_on_functions=0",
+           "use_relative_indent=1",
+           "nospace_before_brace=0",
+           "indent_fl=1",
+           "statement_comment_state=2",
+           "indent_pp=1",
+           "be_style=1",
+           "parens_on_return=0",
+           "eat_blank_lines=0",
+           "brace_indent=0",
+           "eat_pp_space=1",
+           "align_on_parens=1",
+           "continuation_indent=0",
+           "cuddle_else=0",
+           "nopad_condition=1",
+           "pad_condition=0",
+           "indent_col1_comments=0"
+        }
+    }
+    ,
+    {
+        "Opt2Ind3",
+        {
+           "orig_tabsize=3",
+           "syntax_indent=3",
+           "tabsize=3",
+           "align_on_equal=1",
+           "pad_condition_state=1",
+           "indent_with_tabs=0",
+           "nospace_before_paren=0",
+           "indent_comments=1",
+           "indent_case=1",
+           "statement_comment_col=0",
+           "disable_bestyle=0",
+           "decl_comment_col=0",
+           "bestyle_on_functions=0",
+           "use_relative_indent=1",
+           "nospace_before_brace=0",
+           "indent_fl=1",
+           "statement_comment_state=2",
+           "indent_pp=1",
+           "be_style=1",
+           "parens_on_return=0",
+           "eat_blank_lines=0",
+           "brace_indent=0",
+           "eat_pp_space=1",
+           "align_on_parens=1",
+           "continuation_indent=0",
+           "cuddle_else=0",
+           "nopad_condition=1",
+           "pad_condition=0",
+           "indent_col1_comments=0"
+        }
+    }
+    ,
+    {
+        "Opt2Ind8",
+        {
+           "orig_tabsize=8",
+           "syntax_indent=8",
+           "tabsize=8",
+           "align_on_equal=1",
+           "pad_condition_state=1",
+           "indent_with_tabs=0",
+           "nospace_before_paren=0",
+           "indent_comments=1",
+           "indent_case=1",
+           "statement_comment_col=0",
+           "disable_bestyle=0",
+           "decl_comment_col=0",
+           "bestyle_on_functions=0",
+           "use_relative_indent=1",
+           "nospace_before_brace=0",
+           "indent_fl=1",
+           "statement_comment_state=2",
+           "indent_pp=1",
+           "be_style=1",
+           "parens_on_return=0",
+           "eat_blank_lines=0",
+           "brace_indent=0",
+           "eat_pp_space=1",
+           "align_on_parens=1",
+           "continuation_indent=0",
+           "cuddle_else=0",
+           "nopad_condition=1",
+           "pad_condition=0",
+           "indent_col1_comments=0"
+        }
+    }
+    ,
+    {
+        "Opt3Ind4",
+        {
+           "orig_tabsize=4",
+           "syntax_indent=4",
+           "tabsize=4",
+           "align_on_equal=1",
+           "pad_condition_state=1",
+           "indent_with_tabs=0",
+           "nospace_before_paren=0",
+           "indent_comments=1",
+           "indent_case=1",
+           "statement_comment_col=0",
+           "disable_bestyle=0",
+           "decl_comment_col=0",
+           "bestyle_on_functions=0",
+           "use_relative_indent=1",
+           "nospace_before_brace=0",
+           "indent_fl=1",
+           "statement_comment_state=2",
+           "indent_pp=1",
+           "be_style=2",
+           "parens_on_return=0",
+           "eat_blank_lines=0",
+           "brace_indent=0",
+           "eat_pp_space=1",
+           "align_on_parens=1",
+           "continuation_indent=0",
+           "cuddle_else=0",
+           "nopad_condition=1",
+           "pad_condition=0",
+           "indent_col1_comments=0"
+        }
+    }
+    ,
+    {
+        "Opt3Ind3",
+        {
+            "orig_tabsize=3",
+            "syntax_indent=3",
+            "tabsize=3",
+            "align_on_equal=1",
+            "pad_condition_state=1",
+            "indent_with_tabs=0",
+            "nospace_before_paren=0",
+            "indent_comments=1",
+            "indent_case=1",
+            "statement_comment_col=0",
+            "disable_bestyle=0",
+            "decl_comment_col=0",
+            "bestyle_on_functions=0",
+            "use_relative_indent=1",
+            "nospace_before_brace=0",
+            "indent_fl=1",
+            "statement_comment_state=2",
+            "indent_pp=1",
+            "be_style=2",
+            "parens_on_return=0",
+            "eat_blank_lines=0",
+            "brace_indent=0",
+            "eat_pp_space=1",
+            "align_on_parens=1",
+            "continuation_indent=0",
+            "cuddle_else=0",
+            "nopad_condition=1",
+            "pad_condition=0",
+            "indent_col1_comments=0"
+        }
+    }
+};
+
+
+static void k_styles_create()
+{
+    /*
+     * Find user format ini file.
+     */
+    _str userini = maybe_quote_filename(_config_path():+'uformat.ini');
+    if (file_match('-p 'userini, 1) == '')
+    {
+        _str ini = maybe_quote_filename(slick_path_search('uformat.ini'));
+        if (ini != '') userini = ini;
+    }
+
+
+    /*
+     * Remove any old schemes.
+     */
+    int i,j,tv;
+    for (i = 0; i < StyleSchemes._length(); i++)
+        for (j = 0; j < StyleLanguages._length(); j++)
+        {
+            _str sectionname = StyleLanguages[j]:+'-scheme-':+StyleSchemes[i].name;
+            if (!_ini_get_section(userini, sectionname, tv))
+            {
+                _ini_delete_section(userini, sectionname);
+                _delete_temp_view(tv);
+                //message("delete old scheme");
+            }
+        }
+
+    /*
+     * Create the new schemes.
+     */
+    for (i = 0; i < StyleSchemes._length(); i++)
+    {
+        for (j = 0; j < StyleLanguages._length(); j++)
+        {
+            _str sectionname = StyleLanguages[j]:+'-scheme-':+StyleSchemes[i].name;
+            int temp_view_id, k;
+            _str orig_view_id = _create_temp_view(temp_view_id);
+            activate_view(temp_view_id);
+            for (k = 0; k < StyleSchemes[i].settings._length(); k++)
+                insert_line(StyleSchemes[i].settings[k]);
+
+            /* Insert the scheme section. */
+            _ini_replace_section(userini, sectionname, temp_view_id);
+            //message(userini)
+            //bogus id - activate_view(orig_view_id);
+        }
+    }
+
+    //last_scheme = last scheme name!!!
+}
+
+
+/*
+ * Sets the last used beutify scheme.
+ */
+static k_styles_set(_str scheme)
+{
+
+    /*
+     * Find user format ini file.
+     */
+    _str userini = maybe_quote_filename(_config_path():+'uformat.ini');
+    if (file_match('-p 'userini, 1) == '')
+    {
+        _str ini = maybe_quote_filename(slick_path_search('uformat.ini'));
+        if (ini != '') userini = ini;
+    }
+
+    /*
+     * Set the scheme for each language.
+     */
+    int j;
+    for (j = 0; j < StyleLanguages._length(); j++)
+    {
+        _ini_set_value(userini,
+                       StyleLanguages[j]:+'-scheme-Default',
+                       'last_scheme',
+                       scheme);
+    }
+}
+
+
+static _str defoptions[] =
+{
+    "def-options-sas",
+    "def-options-js",
+    "def-options-bat",
+    "def-options-c",
+    "def-options-pas",
+    "def-options-e",
+    "def-options-java",
+    "def-options-bourneshell",
+    "def-options-csh",
+    "def-options-vlx",
+    "def-options-plsql",
+    "def-options-sqlserver",
+    "def-options-cmd"
+};
+
+static _str defsetups[] =
+{
+    "def-setup-sas",
+    "def-setup-js",
+    "def-setup-bat",
+    "def-setup-fundamental",
+    "def-setup-process",
+    "def-setup-c",
+    "def-setup-pas",
+    "def-setup-e",
+    "def-setup-asm",
+    "def-setup-java",
+    "def-setup-html",
+    "def-setup-bourneshell",
+    "def-setup-csh",
+    "def-setup-vlx",
+    "def-setup-fileman",
+    "def-setup-plsql",
+    "def-setup-sqlserver",
+    "def-setup-s",
+    "def-setup-cmd"
+};
+
+static _str defsetupstab8[] =
+{
+    "def-setup-c"
+};
+
+
+static void k_styles_setindent(int indent, int iBraceStyle, boolean iWithTabs = false)
+{
+    if (iBraceStyle < 1 || iBraceStyle > 3)
+    {
+        message('k_styles_setindent: iBraceStyle is bad (=' :+ iBraceStyle :+ ')');
+        iBraceStyle = 2;
+    }
+
+    /*
+     * def-options for extentions known to have that info.
+     */
+    int i;
+    for (i = 0; i < defoptions._length(); i++)
+    {
+        int idx = find_index(defoptions[i], MISC_TYPE);
+        if (!idx)
+            continue;
+
+        parse name_info(idx) with syntax_indent o2 o3 o4 flags indent_fl o7 indent_case rest;
+
+        /* Begin/end style */
+        flags = flags & ~(1|2);
+        flags = flags | (iBraceStyle - 1); /* Set style (0-based) */
+        flags = flags & ~(16); /* no scape before parent.*/
+        indent_fl = 1;         /* Indent first level */
+        indent_case = 1;       /* Indent case from switch */
+
+        sNewOptions = indent' 'o2' 'o3' 'o4' 'flags' 'indent_fl' 'o7' 'indent_case' 'rest;
+        set_name_info(idx, sNewOptions);
+        _config_modify |= CFGMODIFY_DEFDATA;
+    }
+
+    /*
+     * def-setup for known extentions.
+     */
+    for (i = 0; i < defsetups._length(); i++)
+    {
+        idx = find_index(defsetups[i], MISC_TYPE);
+        if (!idx)
+           continue;
+        sExt = substr(defsetups[i], length('def-setup-') + 1);
+        sSetup = name_info(idx);
+
+        /*
+        parse sSetup with 'MN=' mode_name ','\
+          'TABS=' tabs ',' 'MA=' margins ',' 'KEYTAB=' keytab_name ','\
+          'WW='word_wrap_style ',' 'IWT='indent_with_tabs ','\
+          'ST='show_tabs ',' 'IN='indent_style ','\
+          'WC='word_chars',' 'LN='lexer_name',' 'CF='color_flags','\
+          'LNL='line_numbers_len','rest;
+
+        indent_with_tabs = 0; /* Indent with tabs */
+
+        /* Make sure all the values are legal */
+        _ext_init_values(ext, lexer_name, color_flags);
+        if (!isinteger(line_numbers_len))   line_numbers_len = 0;
+        if (word_chars == '')               word_chars       = 'A-Za-z0-9_$';
+        if (word_wrap_style == '')          word_wrap_style  = 3;
+        if (show_tabs == '')                show_tabs        = 0;
+        if (indent_style == '')             indent_style     = INDENT_SMART;
+
+        /* Set new indent */
+        tabs = '+'indent;
+        */
+
+        sNewSetup = sSetup;
+
+        /* Set new indent */
+        if (pos('TABS=', sNewSetup) > 0)
+        {
+            /*
+             * If either in defoptions or defsetupstab8 use default tab of 8
+             * For those supporting separate syntax indent using the normal tabsize
+             * helps us a lot when reading it...
+             */
+            fTab8 = false;
+            for (j = 0; !fTab8 && j < defsetupstab8._length(); j++)
+                if (substr(defsetupstab8[j], lastpos('-', defsetupstab8[j]) + 1) == sExt)
+                    fTab8 = true;
+            for (j = 0; !fTab8 && j < defoptions._length(); j++)
+                if (substr(defoptions[j], lastpos('-', defoptions[j]) + 1) == sExt)
+                    fTab8 = true;
+
+            parse sNewSetup with sPre 'TABS=' sValue ',' sPost;
+            if (fTab8)
+                sNewSetup = sPre 'TABS=+8,' sPost
+            else
+                sNewSetup = sPre 'TABS=+' indent ',' sPost
+        }
+
+        /* Set indent with tabs flag. */
+        if (pos('IWT=', sNewSetup) > 0)
+        {
+            parse sNewSetup with sPre 'IWT=' sValue ',' sPost;
+            if (iWithTabs)
+                sNewSetup = sPre 'IWT=1,' sPost
+            else
+                sNewSetup = sPre 'IWT=0,' sPost
+        }
+
+        /* Do the real changes */
+        set_name_info(idx, sNewSetup);
+        _config_modify |= CFGMODIFY_DEFDATA;
+        _update_buffers(sExt);
+    }
+}
+
+
+/**
+ * Takes necessary steps to convert a string to integer.
+ */
+static int k_style_emacs_var_integer(_str sVal)
+{
+    int i = (int)sVal;
+    //say 'k_style_emacs_var_integer('sVal') -> 'i;
+    return (int)sVal;
+}
+
+
+/**
+ * Sets a Emacs style variable.
+ */
+static int k_style_emacs_var(_str sVar, _str sVal)
+{
+    /* check input. */
+    if (sVar == '' || sVal == '')
+        return -1;
+    //say 'k_style_emacs_var: 'sVar'='sVal;
+
+    /*
+     * Unpack the mode style parameters.
+     */
+    _str sStyle = name_info(_edit_window().p_index);
+    _str sStyleName = p_mode_name;
+    typeless iIndentAmount, fExpansion, iMinAbbrivation, fIndentAfterOpenParen, iBeginEndStyle, fIndent1stLevel, iMainStyle, iSwitchStyle,
+             sRest, sRes0, sRes1;
+    if (sStyleName == 'Slick-C')
+    {
+         parse sStyle with iMinAbbrivation sRes0 iBeginEndStyle fIndent1stLevel sRes1 iSwitchStyle sRest;
+         iIndentAmount = p_SyntaxIndent;
+    }
+    else /* C */
+         parse sStyle with iIndentAmount fExpansion iMinAbbrivation fIndentAfterOpenParen iBeginEndStyle fIndent1stLevel iMainStyle iSwitchStyle sRest;
+
+
+    /*
+     * Process the variable.
+     */
+    switch (sVar)
+    {
+        case 'mode':
+        case 'Mode':
+        {
+            switch (sVal)
+            {
+                case 'c':
+                case 'C':
+                case 'c++':
+                case 'C++':
+                case 'cpp':
+                case 'CPP':
+                case 'cxx':
+                case 'CXX':
+                    p_extension = 'c';
+                    p_mode_name = 'C';
+                    break;
+
+                case 'e':
+                case 'slick-c':
+                case 'Slick-c':
+                case 'Slick-C':
+                    p_extension = 'e';
+                    p_mode_name = 'Slick-C';
+                    break;
+
+                default:
+                    message('emacs mode "'sVal'" is not known to us');
+                    return -3;
+            }
+            break;
+        }
+/* relevant emacs code:
+(defconst c-style-alist
+  '(("gnu"
+     (c-basic-offset . 2)
+     (c-comment-only-line-offset . (0 . 0))
+     (c-offsets-alist . ((statement-block-intro . +)
+			 (knr-argdecl-intro . 5)
+			 (substatement-open . +)
+			 (label . 0)
+			 (statement-case-open . +)
+			 (statement-cont . +)
+			 (arglist-intro . c-lineup-arglist-intro-after-paren)
+			 (arglist-close . c-lineup-arglist)
+			 (inline-open . 0)
+			 (brace-list-open . +)
+			 ))
+     (c-special-indent-hook . c-gnu-impose-minimum)
+     (c-block-comment-prefix . "")
+     )
+    ("k&r"
+     (c-basic-offset . 5)
+     (c-comment-only-line-offset . 0)
+     (c-offsets-alist . ((statement-block-intro . +)
+			 (knr-argdecl-intro . 0)
+			 (substatement-open . 0)
+			 (label . 0)
+			 (statement-cont . +)
+			 ))
+     )
+    ("bsd"
+     (c-basic-offset . 8)
+     (c-comment-only-line-offset . 0)
+     (c-offsets-alist . ((statement-block-intro . +)
+			 (knr-argdecl-intro . +)
+			 (substatement-open . 0)
+			 (label . 0)
+			 (statement-cont . +)
+			 (inline-open . 0)
+			 (inexpr-class . 0)
+			 ))
+     )
+    ("stroustrup"
+     (c-basic-offset . 4)
+     (c-comment-only-line-offset . 0)
+     (c-offsets-alist . ((statement-block-intro . +)
+			 (substatement-open . 0)
+			 (label . 0)
+			 (statement-cont . +)
+			 ))
+     )
+    ("whitesmith"
+     (c-basic-offset . 4)
+     (c-comment-only-line-offset . 0)
+     (c-offsets-alist . ((knr-argdecl-intro . +)
+			 (label . 0)
+			 (statement-cont . +)
+			 (substatement-open . +)
+			 (block-open . +)
+			 (statement-block-intro . c-lineup-whitesmith-in-block)
+			 (block-close . c-lineup-whitesmith-in-block)
+			 (inline-open . +)
+			 (defun-open . +)
+			 (defun-block-intro . c-lineup-whitesmith-in-block)
+			 (defun-close . c-lineup-whitesmith-in-block)
+			 (brace-list-open . +)
+			 (brace-list-intro . c-lineup-whitesmith-in-block)
+			 (brace-entry-open . c-indent-multi-line-block)
+			 (brace-list-close . c-lineup-whitesmith-in-block)
+			 (class-open . +)
+			 (inclass . c-lineup-whitesmith-in-block)
+			 (class-close . +)
+			 (inexpr-class . 0)
+			 (extern-lang-open . +)
+			 (inextern-lang . c-lineup-whitesmith-in-block)
+			 (extern-lang-close . +)
+			 (namespace-open . +)
+			 (innamespace . c-lineup-whitesmith-in-block)
+			 (namespace-close . +)
+			 ))
+     )
+    ("ellemtel"
+     (c-basic-offset . 3)
+     (c-comment-only-line-offset . 0)
+     (c-hanging-braces-alist     . ((substatement-open before after)))
+     (c-offsets-alist . ((topmost-intro        . 0)
+                         (topmost-intro-cont   . 0)
+                         (substatement         . +)
+			 (substatement-open    . 0)
+                         (case-label           . +)
+                         (access-label         . -)
+                         (inclass              . ++)
+                         (inline-open          . 0)
+                         ))
+     )
+    ("linux"
+     (c-basic-offset  . 8)
+     (c-comment-only-line-offset . 0)
+     (c-hanging-braces-alist . ((brace-list-open)
+				(brace-entry-open)
+				(substatement-open after)
+				(block-close . c-snug-do-while)))
+     (c-cleanup-list . (brace-else-brace))
+     (c-offsets-alist . ((statement-block-intro . +)
+			 (knr-argdecl-intro     . 0)
+			 (substatement-open     . 0)
+			 (label                 . 0)
+			 (statement-cont        . +)
+			 ))
+     )
+    ("python"
+     (indent-tabs-mode . t)
+     (fill-column      . 78)
+     (c-basic-offset   . 8)
+     (c-offsets-alist  . ((substatement-open . 0)
+			  (inextern-lang . 0)
+			  (arglist-intro . +)
+			  (knr-argdecl-intro . +)
+			  ))
+     (c-hanging-braces-alist . ((brace-list-open)
+				(brace-list-intro)
+				(brace-list-close)
+				(brace-entry-open)
+				(substatement-open after)
+				(block-close . c-snug-do-while)
+				))
+     (c-block-comment-prefix . "")
+     )
+    ("java"
+     (c-basic-offset . 4)
+     (c-comment-only-line-offset . (0 . 0))
+     ;; the following preserves Javadoc starter lines
+     (c-offsets-alist . ((inline-open . 0)
+			 (topmost-intro-cont    . +)
+			 (statement-block-intro . +)
+ 			 (knr-argdecl-intro     . 5)
+ 			 (substatement-open     . +)
+ 			 (label                 . +)
+ 			 (statement-case-open   . +)
+ 			 (statement-cont        . +)
+ 			 (arglist-intro  . c-lineup-arglist-intro-after-paren)
+ 			 (arglist-close  . c-lineup-arglist)
+ 			 (access-label   . 0)
+			 (inher-cont     . c-lineup-java-inher)
+			 (func-decl-cont . c-lineup-java-throws)
+			 ))
+     )
+    )
+*/
+
+        case 'c-file-style':
+        case 'c-indentation-style':
+            switch (sVal)
+            {
+                case 'bsd':
+                case '"bsd"':
+                case 'BSD':
+                    iBeginEndStyle = 1 | (iBeginEndStyle & ~3);
+                    p_indent_with_tabs = true;
+                    iIndentAmount = 8;
+                    p_SyntaxIndent = 8;
+                    p_tabs = "+8";
+                    //say 'bsd';
+                    break;
+
+                case 'k&r':
+                case '"k&r"':
+                case 'K&R':
+                    iBeginEndStyle = 0 | (iBeginEndStyle & ~3);
+                    p_indent_with_tabs = false;
+                    iIndentAmount = 4;
+                    p_SyntaxIndent = 4;
+                    p_tabs = "+4";
+                    //say 'k&r';
+                    break;
+
+                case 'linux-c':
+                case '"linux-c"':
+                    iBeginEndStyle = 0 | (iBeginEndStyle & ~3);
+                    p_indent_with_tabs = true;
+                    iIndentAmount = 4;
+                    p_SyntaxIndent = 4;
+                    p_tabs = "+4";
+                    //say 'linux-c';
+                    break;
+
+                case 'yet-to-be-found':
+                    iBeginEndStyle = 2 | (iBeginEndStyle & ~3);
+                    p_indent_with_tabs = false;
+                    iIndentAmount = 4;
+                    p_SyntaxIndent = 4;
+                    p_tabs = "+4";
+                    //say 'todo';
+                    break;
+
+                default:
+                    message('emacs "'sVar'" value "'sVal'" is not known to us.');
+                    return -3;
+            }
+            break;
+
+        case 'c-label-offset':
+        {
+            int i = k_style_emacs_var_integer(sVal);
+            if (i >= -16 && i <= 16)
+            {
+                if (i == -p_SyntaxIndent)
+                    iSwitchStyle = 0;
+                else
+                    iSwitchStyle = 1;
+            }
+            break;
+        }
+
+
+        case 'indent-tabs-mode':
+            p_indent_with_tabs = sVal == 't';
+            break;
+
+        case 'c-indent-level':
+        case 'c-basic-offset':
+        {
+            int i = k_style_emacs_var_integer(sVal);
+            if (i > 0 && i <= 16)
+            {
+                iIndentAmount = i;
+                p_SyntaxIndent = i;
+            }
+            else
+            {
+                message('emacs "'sVar'" value "'sVal'" is out of range.');
+                return -4;
+            }
+            break;
+        }
+
+        case 'tab-width':
+        {
+            int i = k_style_emacs_var_integer(sVal);
+            if (i > 0 && i <= 16)
+                p_tabs = '+'i;
+            else
+            {
+                message('emacs "'sVar'" value "'sVal'" is out of range.');
+                return -4;
+            }
+            break;
+        }
+
+        case 'nuke-trailing-whitespace-p':
+        {
+            _str sName = 'def-koptions-'p_buf_id;
+            int idx = insert_name(sName, MISC_TYPE, "kstyledoc");
+            if (!idx)
+                idx = find_index(sName, MISC_TYPE);
+            if (idx)
+            {
+                if (sVal == 't')
+                    set_name_info(idx, "saveoptions: +S");
+                else
+                    set_name_info(idx, "saveoptions: -S");
+                say 'sVal=' sVal;
+            }
+            break;
+        }
+
+        default:
+            message('emacs variable "'sVar'" (value "'sVal'") is unknown to us.');
+            return -5;
+    }
+
+    /*
+     * Update the style?
+     */
+    _str sNewStyle = "";
+    if (sStyleName == 'Slick-C')
+        sNewStyle = iMinAbbrivation' 'sRes0' 'iBeginEndStyle' 'fIndent1stLevel' 'sRes1' 'iSwitchStyle' 'sRest;
+    else
+        sNewStyle = iIndentAmount' 'fExpansion' 'iMinAbbrivation' 'fIndentAfterOpenParen' 'iBeginEndStyle' 'fIndent1stLevel' 'iMainStyle' 'iSwitchStyle' 'sRest;
+    if (   sNewStyle != ""
+        && sNewStyle != sStyle
+        && sStyleName == p_mode_name)
+    {
+        _str sName = name_name(_edit_window().p_index)
+        //say '   sStyle='sStyle' p_mode_name='p_mode_name;
+        //say 'sNewStyle='sNewStyle' sName='sName;
+        if (pos('kstyledoc-', sName) <= 0)
+        {
+            sName = 'def-kstyledoc-'p_buf_id;
+            int idx = insert_name(sName, MISC_TYPE, "kstyledoc");
+            if (!idx)
+                idx = find_index(sName, MISC_TYPE);
+            if (idx)
+            {
+                if (!set_name_info(idx, sNewStyle))
+                    _edit_window().p_index = idx;
+            }
+            //say sName'='idx;
+        }
+        else
+            set_name_info(_edit_window().p_index, sNewStyle);
+    }
+
+    return 0;
+}
+
+
+/**
+ * Parses a string with emacs variables.
+ *
+ * The variables are separated by new line. Junk at
+ * the start and end of the line is ignored.
+ */
+static int k_style_emac_vars(_str sVars)
+{
+    /* process them line by line */
+    int iLine = 0;
+    while (sVars != '' && iLine++ < 20)
+    {
+        int iNext, iEnd;
+        iEnd = iNext = pos("\n", sVars);
+        if (iEnd <= 0)
+            iEnd = iNext = length(sVars);
+        else
+            iEnd--;
+        iNext++;
+
+        sLine = strip(substr(sVars, 1, iEnd), 'B', " \t\n\r");
+        sVars = strip(substr(sVars, iNext), 'L', " \t\n\r");
+        //say 'iLine='iLine' sVars='sVars'<eol>';
+        //say 'iLine='iLine' sLine='sLine'<eol>';
+        if (sLine != '')
+        {
+            rc = pos('[^a-zA-Z0-9-_]*([a-zA-Z0-9-_]+)[ \t]*:[ \t]*([^ \t]*)', sLine, 1, 'U');
+            //say '0={'pos('S0')','pos('0')',"'substr(sLine,pos('S0'),pos('0'))'"'
+            //say '1={'pos('S1')','pos('1')',"'substr(sLine,pos('S1'),pos('1'))'"'
+            //say '2={'pos('S2')','pos('2')',"'substr(sLine,pos('S2'),pos('2'))'"'
+            //say '3={'pos('S3')','pos('3')',"'substr(sLine,pos('S3'),pos('3'))'"'
+            //say '4={'pos('S4')','pos('4')',"'substr(sLine,pos('S4'),pos('4'))'"'
+            if (rc > 0)
+                k_style_emacs_var(substr(sLine,pos('S1'),pos('1')),
+                                  substr(sLine,pos('S2'),pos('2')));
+        }
+    }
+    return 0;
+}
+
+/**
+ * Searches for Emacs style specification for the current document.
+ */
+void k_style_load()
+{
+    /* save the position before we start looking around the file. */
+    typeless saved_pos;
+    _save_pos2(saved_pos);
+
+    int rc;
+
+    /* Check first line. */
+    top_of_buffer();
+    _str sLine;
+    get_line(sLine);
+    strip(sLine);
+    if (pos('-*-[ \t]+(.*:.*)[ \t]+-*-', sLine, 1, 'U'))
+    {
+        _str sVars;
+        sVars = substr(sLine, pos('S1'), pos('1'));
+        sVars = translate(sVars, "\n", ";");
+        k_style_emac_vars(sVars);
+    }
+
+    /* Look for the "Local Variables:" stuff from the end of the file. */
+    bottom_of_buffer();
+    rc = search('Local Variables:[ \t]*\n\om(.*)\ol\n.*End:.*\n', '-EU');
+    if (!rc)
+    {
+        /* copy the variables out to a buffer. */
+        _str sVars;
+        sVars = get_text(match_length("1"), match_length("S1"));
+        k_style_emac_vars(sVars);
+    }
+
+    _restore_pos2(saved_pos);
+}
+
+
+/**
+ * Callback function for the event of a new buffer.
+ *
+ * This is used to make sure there are no left over per buffer options
+ * hanging around.
+ */
+void _buffer_add_kdev(int buf_id)
+{
+    _str sName = 'def-koptions-'buf_id;
+    int idx = insert_name(sName, MISC_TYPE, "kstyledoc");
+    if (!idx)
+        idx = find_index(sName, MISC_TYPE);
+    if (idx)
+        set_name_info(idx, "");
+    //message("_buffer_add_kdev: " idx);
+}
+
+
+/**
+ * Callback function for the event of quitting a buffer.
+ *
+ * This is used to make sure there are no left over per buffer options
+ * hanging around.
+ */
+void _cbquit2_kdev(int buf_id)
+{
+    _str sName = 'def-koptions-'buf_id;
+    int idx = find_index(sName, MISC_TYPE);
+    if (idx)
+        delete_name(idx);
+    //message("_cbquit2_kdev: " idx " " sName);
+
+    sName = 'def-kstyledoc-'buf_id;
+    idx = find_index(sName, MISC_TYPE);
+    if (idx)
+        delete_name(idx);
+}
+
+
+/**
+ * Called to get save options for the current buffer.
+ *
+ * This requires a modified loadsave.e!
+ */
+_str _buffer_save_kdev(int buf_id)
+{
+    _str sRet = ""
+    _str sName = 'def-koptions-'buf_id;
+    int idx = find_index(sName, MISC_TYPE);
+    if (idx)
+    {
+        _str sOptions = strip(name_info(idx));
+        if (sOptions != "")
+            parse sOptions with . "saveoptions:" sRet .
+        message("_buffer_save_kdev: " idx " " sName " " sOptions);
+    }
+    return sRet;
+}
+
+
+
+/*******************************************************************************
+*   Menu and Menu commands                                                     *
+*******************************************************************************/
+static int  iTimer = 0;
+static int  mhkDev = 0;
+static int  mhCode = 0;
+static int  mhDoc = 0;
+static int  mhLic = 0;
+static int  mhPre = 0;
+
+/*
+ * Creates the kDev menu.
+ */
+static k_menu_create()
+{
+    if (arg(1) == 'timer')
+        _kill_timer(iTimer);
+    menu_handle = _mdi.p_menu_handle;
+    menu_index  = find_index(_cur_mdi_menu,oi2type(OI_MENU));
+
+    /*
+     * Remove any old menu.
+     */
+    mhDelete = iPos = 0;
+    index = _menu_find(menu_handle, "kDev", mhDelete, iPos, 'C');
+    //message("index="index " mhDelete="mhDelete " iPos="iPos);
+    if (index == 0)
+        _menu_delete(mhDelete, iPos);
+
+
+    /*
+     * Insert the "kDev" menu.
+     */
+    mhkDev = _menu_insert(menu_handle, 9, MF_SUBMENU, "&kDev", "", "kDev");
+    mhCode=_menu_insert(mhkDev,  -1, MF_ENABLED | MF_SUBMENU,   "Coding &Style",  "", "coding");
+    rc   = _menu_insert(mhCode,  -1, MF_ENABLED | MF_UNCHECKED, "Braces 2, Syntax Indent 4 (knut)",    "k_menu_style Opt2Ind4",    "Opt2Ind4");
+    rc   = _menu_insert(mhCode,  -1, MF_ENABLED | MF_UNCHECKED, "Braces 2, Syntax Indent 3",           "k_menu_style Opt2Ind3",    "Opt2Ind3");
+    rc   = _menu_insert(mhCode,  -1, MF_ENABLED | MF_UNCHECKED, "Braces 2, Syntax Indent 8",           "k_menu_style Opt2Ind8",    "Opt2Ind8");
+    rc   = _menu_insert(mhCode,  -1, MF_ENABLED | MF_UNCHECKED, "Braces 3, Syntax Indent 4 (giws)",    "k_menu_style Opt3Ind4",    "Opt3Ind4");
+    rc   = _menu_insert(mhCode,  -1, MF_ENABLED | MF_UNCHECKED, "Braces 3, Syntax Indent 3 (giws)",    "k_menu_style Opt3Ind3",    "Opt3Ind3");
+
+    mhDoc= _menu_insert(mhkDev,  -1, MF_ENABLED | MF_SUBMENU,   "&Documentation",       "",                             "doc");
+    mhDSJ= _menu_insert(mhDoc,   -1, MF_ENABLED | MF_UNCHECKED, "&Javadoc Style",       "k_menu_doc_style javadoc",     "javadoc");
+    mhDSL= _menu_insert(mhDoc,   -1, MF_GRAYED  | MF_UNCHECKED, "&Linux Kernel Style",  "k_menu_doc_style linux",       "linux");
+
+    mhLic= _menu_insert(mhkDev,  -1, MF_ENABLED | MF_SUBMENU,   "&License",             "",                             "License");
+    rc   = _menu_insert(mhLic,   -1, MF_ENABLED | MF_UNCHECKED, "&Odin32",              "k_menu_license Odin32",        "Odin32");
+    rc   = _menu_insert(mhLic,   -1, MF_ENABLED | MF_UNCHECKED, "&GPL",                 "k_menu_license GPL",           "GPL");
+    rc   = _menu_insert(mhLic,   -1, MF_ENABLED | MF_UNCHECKED, "&LGPL",                "k_menu_license LGPL",          "LGPL");
+    rc   = _menu_insert(mhLic,   -1, MF_ENABLED | MF_UNCHECKED, "&VirtualBox",          "k_menu_license VirtualBox",    "VirtualBox");
+    rc   = _menu_insert(mhLic,   -1, MF_ENABLED | MF_UNCHECKED, "&VirtualBox GPL And CDDL","k_menu_license VirtualBoxGPLAndCDDL", "VirtualBoxGPLAndCDDL");
+    rc   = _menu_insert(mhLic,   -1, MF_ENABLED | MF_UNCHECKED, "&Confidential",        "k_menu_license Confidential",  "Confidential");
+
+    rc   = _menu_insert(mhkDev,  -1, MF_ENABLED, "-", "", "dash vars");
+    rc   = _menu_insert(mhkDev,  -1, MF_ENABLED, skChange  == '' ? '&Change...'  : '&Change (' skChange ')...',   "k_menu_change", "");
+    rc   = _menu_insert(mhkDev,  -1, MF_ENABLED, skProgram == '' ? '&Program...' : '&Program (' skProgram ')...', "k_menu_program", "");
+    rc   = _menu_insert(mhkDev,  -1, MF_ENABLED, skCompany == '' ? 'Co&mpany...' : 'Co&mpany (' skCompany ')...', "k_menu_company", "");
+    rc   = _menu_insert(mhkDev,  -1, MF_ENABLED, '&User Name (' skUserName ')...',          "k_menu_user_name",     "username");
+    rc   = _menu_insert(mhkDev,  -1, MF_ENABLED, 'User &e-mail (' skUserEmail ')...',       "k_menu_user_email",    "useremail");
+    rc   = _menu_insert(mhkDev,  -1, MF_ENABLED, 'User &Initials (' skUserInitials ')...',  "k_menu_user_initials", "userinitials");
+    rc   = _menu_insert(mhkDev,  -1, MF_ENABLED, "-", "", "dash preset");
+    mhPre= _menu_insert(mhkDev,  -1, MF_SUBMENU, "P&resets", "", "");
+    rc   = _menu_insert(mhPre,   -1, MF_ENABLED, "The Bird",    "k_menu_preset javadoc, GPL, Opt2Ind4",                 "bird");
+    rc   = _menu_insert(mhPre,   -1, MF_ENABLED, "kLIBC",       "k_menu_preset javadoc, GPL, Opt2Ind4,, kLIBC",         "kLIBC");
+    rc   = _menu_insert(mhPre,   -1, MF_ENABLED, "kBuild",      "k_menu_preset javadoc, GPL, Opt2Ind4,, kBuild",        "kBuild");
+    rc   = _menu_insert(mhPre,   -1, MF_ENABLED, "kStuff",      "k_menu_preset javadoc, GPL, Opt2Ind4,, kStuff",        "kStuff");
+    rc   = _menu_insert(mhPre,   -1, MF_ENABLED, "sun",         "k_menu_preset javadoc, Confidential, Opt2Ind4, sun",   "sun");
+    rc   = _menu_insert(mhPre,   -1, MF_ENABLED, "VirtualBox",  "k_menu_preset javadoc, VirtualBox, Opt2Ind4, sun",     "VirtualBox");
+
+    k_menu_doc_style();
+    k_menu_license();
+    k_menu_style();
+}
+
+
+/**
+ * Change change Id.
+ */
+_command k_menu_change()
+{
+    sRc = show("-modal k_form_simple_input", "Change ID", skChange);
+    if (sRc != "\r")
+    {
+        skChange = sRc;
+        k_menu_create();
+    }
+}
+
+
+/**
+ * Change program name.
+ */
+_command k_menu_program()
+{
+    sRc = show("-modal k_form_simple_input", "Program", skProgram);
+    if (sRc != "\r")
+    {
+        skProgram = sRc;
+        k_menu_create();
+    }
+}
+
+
+/**
+ * Change company.
+ */
+_command k_menu_company()
+{
+    if (skCompany == '')
+        sRc = show("-modal k_form_simple_input", "Company", 'innotek GmbH');
+    else
+        sRc = show("-modal k_form_simple_input", "Company", skCompany);
+    if (sRc != "\r")
+    {
+        skCompany = sRc;
+        k_menu_create();
+    }
+}
+
+
+/**
+ * Change user name.
+ */
+_command k_menu_user_name()
+{
+    sRc = show("-modal k_form_simple_input", "User Name", skUserName);
+    if (sRc != "\r" && sRc != '')
+    {
+        skUserName = sRc;
+        k_menu_create();
+    }
+}
+
+
+/**
+ * Change user email.
+ */
+_command k_menu_user_email()
+{
+    sRc = show("-modal k_form_simple_input", "User e-mail", skUserEmail);
+    if (sRc != "\r" && sRc != '')
+    {
+        skUserEmail = sRc;
+        k_menu_create();
+    }
+}
+
+
+/**
+ * Change user initials.
+ */
+_command k_menu_user_initials()
+{
+    sRc = show("-modal k_form_simple_input", "User e-mail", skUserInitials);
+    if (sRc != "\r" && sRc != '')
+    {
+        skUserInitials = sRc;
+        k_menu_create();
+    }
+}
+
+
+
+/**
+ * Checks the correct menu item.
+ */
+_command void k_menu_doc_style(_str sNewDocStyle = '')
+{
+    //say 'sNewDocStyle='sNewDocStyle;
+    if (sNewDocStyle != '')
+        skDocStyle = sNewDocStyle
+    _menu_set_state(mhDoc, "javadoc",   MF_UNCHECKED);
+    _menu_set_state(mhDoc, "linux",     MF_UNCHECKED | MF_GRAYED);
+    _menu_set_state(mhDoc, skDocStyle,  MF_CHECKED);
+}
+
+
+/**
+ * Checks the correct menu item.
+ */
+_command void k_menu_license(_str sNewLicense = '')
+{
+    //say 'sNewLicense='sNewLicense;
+    if (sNewLicense != '')
+        skLicense = sNewLicense
+    _menu_set_state(mhLic, "Odin32",        MF_UNCHECKED);
+    _menu_set_state(mhLic, "GPL",           MF_UNCHECKED);
+    _menu_set_state(mhLic, "LGPL",          MF_UNCHECKED);
+    _menu_set_state(mhLic, "Confidential",  MF_UNCHECKED);
+    _menu_set_state(mhLic, skLicense,       MF_CHECKED);
+}
+
+
+/**
+ * Check the correct style menu item.
+ */
+_command void k_menu_style(_str sNewStyle = '')
+{
+    //say 'sNewStyle='sNewStyle;
+    _menu_set_state(mhCode, "Opt1Ind4", MF_UNCHECKED);
+    _menu_set_state(mhCode, "Opt1Ind3", MF_UNCHECKED);
+    _menu_set_state(mhCode, "Opt1Ind8", MF_UNCHECKED);
+    _menu_set_state(mhCode, "Opt2Ind4", MF_UNCHECKED);
+    _menu_set_state(mhCode, "Opt2Ind3", MF_UNCHECKED);
+    _menu_set_state(mhCode, "Opt2Ind8", MF_UNCHECKED);
+    _menu_set_state(mhCode, "Opt3Ind4", MF_UNCHECKED);
+    _menu_set_state(mhCode, "Opt3Ind3", MF_UNCHECKED);
+    _menu_set_state(mhCode, "Opt3Ind8", MF_UNCHECKED);
+
+    if (sNewStyle != '')
+    {
+        int iIndent = (int)substr(sNewStyle, 8, 1);
+        int iBraceStyle = (int)substr(sNewStyle, 4, 1);
+        skCodeStyle = sNewStyle;
+        k_styles_setindent(iIndent, iBraceStyle);
+        k_styles_set(sNewStyle);
+    }
+
+    _menu_set_state(mhCode, skCodeStyle, MF_CHECKED);
+}
+
+
+/**
+ * Load a 'preset'.
+ */
+_command void k_menu_preset(_str sArgs = '')
+{
+    parse sArgs with sNewDocStyle ',' sNewLicense ',' sNewStyle ',' sNewCompany ',' sNewProgram ',' sNewChange
+    sNewDocStyle= strip(sNewDocStyle);
+    sNewLicense = strip(sNewLicense);
+    sNewStyle   = strip(sNewStyle);
+    sNewCompany = strip(sNewCompany);
+    if (sNewCompany == 'sun')
+        sNewCompany = 'Sun Microsystems, Inc.'
+    sNewProgram = strip(sNewProgram);
+    sNewChange  = strip(sNewChange);
+
+    //say 'k_menu_preset('sNewDocStyle',' sNewLicense',' sNewStyle',' sNewCompany',' sNewProgram')';
+    k_menu_doc_style(sNewDocStyle);
+    k_menu_license(sNewLicense);
+    k_menu_style(sNewStyle);
+    skCompany = sNewCompany;
+    skProgram = sNewProgram;
+    skChange = sNewChange;
+    k_menu_create();
+}
+
+
+
+/* future ones..
+_command k_menu_setcolor()
+{
+    createMyColorSchemeAndUseIt();
+}
+
+
+_command k_menu_setkeys()
+{
+    rc = load("d:/knut/VSlickMacros/BoxerDef.e");
+}
+
+_command k_menu_settings()
+{
+    mySettings();
+}
+*/
+
+
+/*******************************************************************************
+*   Dialogs                                                                    *
+*******************************************************************************/
+_form k_form_simple_input {
+   p_backcolor=0x80000005
+   p_border_style=BDS_DIALOG_BOX
+   p_caption='Simple Input'
+   p_clip_controls=FALSE
+   p_forecolor=0x80000008
+   p_height=1120
+   p_width=5020
+   p_x=6660
+   p_y=6680
+   _text_box entText {
+      p_auto_size=TRUE
+      p_backcolor=0x80000005
+      p_border_style=BDS_FIXED_SINGLE
+      p_completion=NONE_ARG
+      p_font_bold=FALSE
+      p_font_italic=FALSE
+      p_font_name='MS Sans Serif'
+      p_font_size=8
+      p_font_underline=FALSE
+      p_forecolor=0x80000008
+      p_height=270
+      p_tab_index=1
+      p_tab_stop=TRUE
+      p_text='text'
+      p_width=3180
+      p_x=1680
+      p_y=240
+      p_eventtab2=_ul2_textbox
+   }
+   _label lblLabel {
+      p_alignment=AL_VCENTERRIGHT
+      p_auto_size=FALSE
+      p_backcolor=0x80000005
+      p_border_style=BDS_NONE
+      p_caption='Label'
+      p_font_bold=FALSE
+      p_font_italic=FALSE
+      p_font_name='MS Sans Serif'
+      p_font_size=8
+      p_font_underline=FALSE
+      p_forecolor=0x80000008
+      p_height=240
+      p_tab_index=2
+      p_width=1380
+      p_word_wrap=FALSE
+      p_x=180
+      p_y=240
+   }
+   _command_button btnOK {
+      p_cancel=FALSE
+      p_caption='&OK'
+      p_default=TRUE
+      p_font_bold=FALSE
+      p_font_italic=FALSE
+      p_font_name='MS Sans Serif'
+      p_font_size=8
+      p_font_underline=FALSE
+      p_height=360
+      p_tab_index=3
+      p_tab_stop=TRUE
+      p_width=1020
+      p_x=180
+      p_y=660
+   }
+   _command_button btnCancel {
+      p_cancel=TRUE
+      p_caption='Cancel'
+      p_default=FALSE
+      p_font_bold=FALSE
+      p_font_italic=FALSE
+      p_font_name='MS Sans Serif'
+      p_font_size=8
+      p_font_underline=FALSE
+      p_height=360
+      p_tab_index=4
+      p_tab_stop=TRUE
+      p_width=840
+      p_x=1380
+      p_y=660
+   }
+}
+
+defeventtab k_form_simple_input
+btnOK.on_create(_str sLabel = '', _str sText = '')
+{
+    p_active_form.p_caption = sLabel;
+    lblLabel.p_caption = sLabel;
+    entText.p_text = sText;
+}
+
+btnOK.lbutton_up()
+{
+    sText = entText.p_text;
+    p_active_form._delete_window(sText);
+}
+btnCancel.lbutton_up()
+{
+    sText = entText.p_text;
+    p_active_form._delete_window("\r");
+}
+
+
+
+/**
+ * Module initiation.
+ */
+definit()
+{
+    /* do cleanup. */
+    for (i = 0; i < 200; i++)
+    {
+        index = name_match("def-koptions-", 1, MISC_TYPE);
+        if (!index)
+            break;
+        delete_name(index);
+    }
+
+    /* do init */
+    k_styles_create();
+    k_menu_create();
+    iTimer = _set_timer(1000, k_menu_create, "timer");
+    /* createMyColorSchemeAndUseIt();*/
+}
Index: /tags/kBuild-0.1.4/VSlickMacros/kkeys.e
===================================================================
--- /tags/kBuild-0.1.4/VSlickMacros/kkeys.e	(revision 1780)
+++ /tags/kBuild-0.1.4/VSlickMacros/kkeys.e	(revision 1780)
@@ -0,0 +1,248 @@
+/* $Id$ */
+/** @file
+ * Bird's key additions to Visual Slickedit.
+ */
+
+/*
+ *
+ * Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+defeventtab default_keys
+def  'A-UP'     = find_prev
+def  'A-DOWN'   = find_next
+def  'A-PGUP'   = prev_proc
+def  'A-PGDN'   = next_proc
+def  'A-d'      = delete_line
+def  'A-o'      = kkeys_duplicate_line
+def  'A-s'      = kkeys_switch_lines
+def  'A-u'      = undo_cursor           /* will cursor movement in one undo step. */
+def  'A-g'      = goto_line
+def  'A-z'      = kkeys_fullscreen
+def  'INS'      = boxer_paste
+def  'S-INS'    = insert_toggle
+def  'C-UP'     = kkeys_scroll_down
+def  'C-DOWN'   = kkeys_scroll_up
+def  'C-PGUP'   = prev_window
+def  'C-PGDN'   = next_window
+def  'C-DEL'    = kkeys_delete_right
+/* For the mac (A/M mix, all except A-z): */
+def  'M-UP'     = find_prev
+def  'M-DOWN'   = find_next
+def  'M-PGUP'   = prev_proc
+def  'M-PGDN'   = next_proc
+def  'M-d'      = delete_line
+def  'M-o'      = kkeys_duplicate_line
+def  'M-s'      = kkeys_switch_lines
+def  'M-u'      = undo_cursor
+def  'M-g'      = goto_line
+/* Fixing brainfucked slickedit silliness: */
+def  'M-v'      = paste
+
+_command kkeys_switch_lines()
+{
+   /* Allocate a selection for copying the current line. */
+   cursor_down();
+   mark_id= _alloc_selection();
+   if (mark_id>=0)
+   {
+      _select_line(mark_id);
+      cursor_up();
+      cursor_up();
+      _move_to_cursor(mark_id);
+      cursor_down();
+      _free_selection(mark_id);
+      // This selection can be freed because it is not the active selection.
+   }
+   else
+      message(get_message(mark_id));
+}
+
+_command kkeys_duplicate_line()
+{
+   /* Allocate a selection for copying the current line. */
+   mark_id= _alloc_selection();
+   if (mark_id>=0)
+   {
+      _select_line(mark_id);
+      _copy_to_cursor(mark_id);
+      // This selection can be freed because it is not the active selection.
+      _free_selection(mark_id);
+      cursor_down();
+   }
+   else
+       message(get_message(mark_id));
+}
+
+_command kkeys_delete_right()
+{
+   col=p_col
+   search('[ \t]#|?|$|^','r+');
+   if ( match_length()&& get_text(1,match_length('s'))=='' )
+   {
+      _nrseek(match_length('s'));
+      _delete_text(match_length());
+   }
+   else
+      delete_word();
+   p_col=col
+   //retrieve_command_results()
+
+}
+
+_command kkeys_delete_left()
+{
+   //denne virker ikkje som den skal!!!
+   message "not implemented"
+/*
+   return;
+   col=p_col
+   search('[ \t]#|?|$|^','r-');
+   if ( match_length()&& get_text(1,match_length('s'))=='' )
+   {
+      _nrseek(match_length('s'));
+      _delete_text(match_length());
+   }
+   else
+      delete_word();
+   p_col=col
+*/
+}
+
+_command kkeys_scroll_up()
+{
+   if (p_cursor_y == 0)
+      down();
+   set_scroll_pos(p_left_edge, p_cursor_y-1);
+}
+
+_command kkeys_scroll_down()
+{
+   if (p_cursor_y intdiv p_font_height == p_char_height-1)
+      up()
+   set_scroll_pos(p_left_edge, p_cursor_y+p_font_height);
+}
+
+_command boxer_paste()
+{
+   int rc;
+   offset = _QROffset();
+   message(offset);
+   rc = paste();
+   _GoToROffset(offset);
+}
+
+_command kkeys_fullscreen()
+{
+    fullscreen();
+}
+
+
+/* for later, not used yet. */
+
+_command boxer_select()
+{
+   if (command_state())
+      fSelected = (p_sel_length != 0);
+   else
+      fSelected = select_active();
+
+   key = last_event();
+   if (key :== name2event('s-down'))
+   {
+      if (!fSelected)
+         select_line();
+      else
+         cursor_down();
+   }
+   else if (key :== name2event('s-up'))
+   {
+      if (!fSelected)
+         select_line();
+      else
+         cursor_up();
+   }
+   else if (key :== name2event('s-left'))
+   {
+      if (!fSelected)
+         select_char();
+      else
+         cursor_left();
+   }
+   else if (key :== name2event('s-right'))
+   {
+      if (!fSelected)
+         select_char();
+      else
+         cursor_right();
+   }
+   else if (key :== name2event('s-home'))
+   {
+      if (!fSelected) select_char();
+      begin_line_text_toggle();
+   }
+   else if (key :== name2event('s-end'))
+   {
+      if (!fSelected) select_char();
+      end_line();
+      if (p_col > 0) //this is not identical with boxer...
+         cursor_left();
+   }
+   else if (key :== name2event('c-s-home'))
+   {
+      if (!fSelected) select_char();
+      top_of_buffer();
+   }
+   else if (key :== name2event('c-s-end'))
+   {
+      if (!fSelected) select_char();
+      bottom_of_buffer();
+   }
+   else if (key :== name2event('c-s-left'))
+   {
+      if (!fSelected)
+      {
+         cursor_left();
+         select_char(); /* start this selection non-inclusive */
+      }
+      prev_word();
+   }
+   else if (key :== name2event('c-s-right'))
+   {
+      if (!fSelected)
+      {
+         select_char(); /* start this selection non-inclusive */
+      }
+      /* temporary hack */
+      prevpos = p_col;
+      prevline = p_line;
+      p_col++;
+      next_word();
+      if ((p_line == prevline && p_col > prevpos + 1) || (p_line != prevline && p_col > 0))
+         p_col--;
+   }
+}
+
+
+void nop()
+{
+
+}
+
Index: /tags/kBuild-0.1.4/VSlickMacros/uscheme.ini
===================================================================
--- /tags/kBuild-0.1.4/VSlickMacros/uscheme.ini	(revision 1780)
+++ /tags/kBuild-0.1.4/VSlickMacros/uscheme.ini	(revision 1780)
@@ -0,0 +1,73 @@
+[knut's]
+CFG_COMMENTfg=0xFF00
+CFG_COMMENTbg=0x840000
+CFG_COMMENTff=0x2
+CFG_CLINEfg=0xFFFF00
+CFG_CLINEbg=0x840000
+CFG_CLINEff=0x0
+CFG_CURSORfg=0x0
+CFG_CURSORbg=0xC0C0C0
+CFG_CURSORff=0x0
+CFG_NOSAVE_LINEfg=0xFFFF
+CFG_NOSAVE_LINEbg=0x840000
+CFG_NOSAVE_LINEff=0x0
+CFG_INSERTED_LINEfg=0xFFFFFF
+CFG_INSERTED_LINEbg=0x80
+CFG_INSERTED_LINEff=0x0
+CFG_KEYWORDfg=0xFF
+CFG_KEYWORDbg=0x840000
+CFG_KEYWORDff=0x0
+CFG_LINENUMfg=0x808080
+CFG_LINENUMbg=0x840000
+CFG_LINENUMff=0x0
+CFG_MESSAGEfg=0x80000008
+CFG_MESSAGEbg=0x80000005
+CFG_MESSAGEff=0x0
+CFG_MODIFIED_LINEfg=0xFF
+CFG_MODIFIED_LINEbg=0x840000
+CFG_MODIFIED_LINEff=0x0
+CFG_NUMBERfg=0xFF
+CFG_NUMBERbg=0x840000
+CFG_NUMBERff=0x0
+CFG_PPKEYWORDfg=0xC0C0C0
+CFG_PPKEYWORDbg=0x840000
+CFG_PPKEYWORDff=0x0
+CFG_SELECTED_CLINEfg=0x800000
+CFG_SELECTED_CLINEbg=0x808000
+CFG_SELECTED_CLINEff=0x0
+CFG_SELECTIONfg=0x800000
+CFG_SELECTIONbg=0x808000
+CFG_SELECTIONff=0x0
+CFG_STATUSfg=0x80000008
+CFG_STATUSbg=0x80000005
+CFG_STATUSff=0x0
+CFG_STRINGfg=0xFFFF
+CFG_STRINGbg=0x840000
+CFG_STRINGff=0x0
+CFG_WINDOW_TEXTfg=0xFFFF00
+CFG_WINDOW_TEXTbg=0x840000
+CFG_WINDOW_TEXTff=0x0
+CFG_SYMBOL1fg=0xC0C0C0
+CFG_SYMBOL1bg=0x840000
+CFG_SYMBOL1ff=0x0
+CFG_SYMBOL2fg=0xFF00FF
+CFG_SYMBOL2bg=0x840000
+CFG_SYMBOL2ff=0x0
+CFG_SYMBOL3fg=0x8080
+CFG_SYMBOL3bg=0x840000
+CFG_SYMBOL3ff=0x0
+CFG_SYMBOL4fg=0x0
+CFG_SYMBOL4bg=0x840000
+CFG_SYMBOL4ff=0x0
+CFG_FUNCTIONfg=0x808000
+CFG_FUNCTIONbg=0x840000
+CFG_FUNCTIONff=0x0
+CFG_FILENAMEfg=0xFF0000
+CFG_FILENAMEbg=0x808000
+CFG_FILENAMEff=0x0
+CFG_HILIGHTfg=0x840000
+CFG_HILIGHTbg=0xFFFF00
+CFG_HILIGHTff=0x0
+CFG_ATTRIBUTEfg=0xFF00FF
+CFG_ATTRIBUTEbg=0x840000
+CFG_ATTRIBUTEff=0x0
Index: /tags/kBuild-0.1.4/VSlickMacros/user.vlx
===================================================================
--- /tags/kBuild-0.1.4/VSlickMacros/user.vlx	(revision 1780)
+++ /tags/kBuild-0.1.4/VSlickMacros/user.vlx	(revision 1780)
@@ -0,0 +1,16 @@
+[kmk]
+idchars=a-zA-Z 0-9_
+case-sensitive=y
+styles=dqbackslash sqbackslash
+punctuation= ( ) : ; [ ] { }
+operators= ! # $ % & * + , - . / < = > ? ^ ` | ~ := += >= |+ : ::
+keywords= export override
+libkeywords= abspath abspathex addprefix addsuffix and basename call comp-cmds comp-vars date date-utc dir eq error eval expr file-size filter filter-out findstring firstword flavor foreach if-expr info int-add int-and int-div int-eq int-ge int-gt int-le int-lt int-mod int-mul int-ne int-not int-or int-sub int-xor join kb-obj-base kb-obj-suff kb-src-one kb-src-prop kb-src-tool lastword nanots not notdir or origin patsubst realpath rsort shell sort stack-pop stack-popv stack-push stack-top strip subst suffix tolower toupper value warning which wildcard word wordlist words xargs
+ppkeywords= bool define defined else endif endef if if1of ifn1of ifdef ifndef ifeq ifneq include includedep num string target
+linecomment=#
+
+[def]
+idchars=a-zA-Z 0-9_
+case-sensitive=n
+linecomment=;
+
Index: /tags/kBuild-0.1.4/VSlickMacros/usrprjtemplates.vpt
===================================================================
--- /tags/kBuild-0.1.4/VSlickMacros/usrprjtemplates.vpt	(revision 1780)
+++ /tags/kBuild-0.1.4/VSlickMacros/usrprjtemplates.vpt	(revision 1780)
@@ -0,0 +1,52 @@
+<!DOCTYPE Templates SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpt.dtd">
+<Templates
+	Version="10.0"
+	VendorName="SlickEdit">
+	<Template Name="kBuild">
+		<Config Name="Release">
+			<Menu>
+				<Target
+					Name="Compile"
+					MenuCaption="&amp;Compile"
+					CaptureOutputWith="ProcessBuffer"
+					SaveOption="SaveCurrent"
+					RunFromDir="%p"
+					ClearProcessBuffer="1">
+					<Exec CmdLine="kmk -C %p %n.o"/>
+				</Target>
+				<Target
+					Name="Build"
+					MenuCaption="&amp;Build"
+					CaptureOutputWith="ProcessBuffer"
+					SaveOption="SaveWorkspaceFiles"
+					RunFromDir="%rw"
+					ClearProcessBuffer="1">
+					<Exec CmdLine="kmk"/>
+				</Target>
+				<Target
+					Name="Rebuild"
+					MenuCaption="&amp;Rebuild"
+					CaptureOutputWith="ProcessBuffer"
+					SaveOption="SaveWorkspaceFiles"
+					RunFromDir="%rw"
+					ClearProcessBuffer="1">
+					<Exec CmdLine="kmk rebuild"/>
+				</Target>
+				<Target
+					Name="Debug"
+					MenuCaption="&amp;Debug"
+					SaveOption="SaveNone"
+					RunFromDir="%rw">
+					<Exec/>
+				</Target>
+				<Target
+					Name="Execute"
+					MenuCaption="E&amp;xecute"
+					SaveOption="SaveNone"
+					RunFromDir="%rw">
+					<Exec CmdLine='"%&lt;e.exe"'/>
+				</Target>
+			</Menu>
+		</Config>
+	</Template>
+</Templates>
Index: /tags/kBuild-0.1.4/bootstrap.gmk
===================================================================
--- /tags/kBuild-0.1.4/bootstrap.gmk	(revision 1780)
+++ /tags/kBuild-0.1.4/bootstrap.gmk	(revision 1780)
@@ -0,0 +1,226 @@
+# $Id$
+## @file
+# GNU Make Compatible bootstrap Makefile.
+#
+
+#
+# Copyright (c) 2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+
+
+#
+# ASSUMES:
+#   - KBUILD_TARGET, KBUILD_HOST, KBUILD_HOST_ARCH, and KBUILD_TYPE in the env.
+#   - KBUILD_PATH points to ./kBuild with an absolute path.
+#   - KBUILD_BIN_PATH and PATH_KBUILD_BIN must *NOT* be defined anywhere.
+#   - Current directory == bootstrap.gmk directory.
+#   - mkdir -p works.
+#   - ln -s works
+#   - cp -f works
+#   - cd somedir && command works.
+#   - echo done > some-file works.
+#   - Recent GNU make that implements CURDIR, $(error) and ifdef.
+#
+# Tip: kBuild/env.sh --full (g(nu))make -f bootstrap.kmk
+#
+#
+
+#
+# OPTIONAL:
+#   Set env.var. NIX_INSTALL_DIR to /usr/local or /usr
+#   (see Config.kmk and wiki for details)
+#
+
+#
+# Deal with legacy env.vars. - no niceties here.
+#
+ifndef KBUILD_HOST
+ KBUILD_HOST := $(BUILD_PLATFORM)
+endif
+ifndef KBUILD_HOST_ARCH
+ KBUILD_HOST_ARCH := $(BUILD_PLATFORM_ARCH)
+endif
+ifndef KBUILD_HOST_CPU
+ KBUILD_HOST_CPU := $(BUILD_PLATFORM_CPU)
+endif
+
+ifndef KBUILD_TARGET
+ KBUILD_TARGET := $(BUILD_TARGET)
+endif
+ifndef KBUILD_TARGET_ARCH
+ KBUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH)
+endif
+ifndef KBUILD_TARGET_CPU
+ KBUILD_TARGET_CPU := $(BUILD_TARGET_CPU)
+endif
+
+ifndef KBUILD_TYPE
+ KBUILD_TYPE := $(BUILD_TYPE)
+endif
+
+ifndef KBUILD_PATH
+ KBUILD_PATH := $(PATH_KBUILD)
+endif
+
+#
+# Check (some of) the assumptions.
+#
+ifndef KBUILD_TARGET
+ $(error KBUILD_TARGET not set)
+endif
+
+ifndef KBUILD_HOST
+ $(error KBUILD_HOST not set)
+endif
+
+ifndef KBUILD_HOST_ARCH
+ $(error KBUILD_HOST_ARCH not set)
+endif
+
+ifndef KBUILD_TYPE
+ $(error KBUILD_TYPE not set)
+endif
+
+ifndef KBUILD_TYPE
+ $(error KBUILD_TYPE not set)
+endif
+
+ifndef KBUILD_PATH
+ $(error KBUILD_PATH not set)
+endif
+
+ifdef KBUILD_BIN_PATH
+ $(error KBUILD_BIN_PATH is set)
+endif
+ifdef PATH_KBUILD_BIN
+ $(error PATH_KBUILD_BIN is set)
+endif
+
+
+#
+# Globals
+#
+SRCDIR = $(CURDIR)
+OUTDIR = $(SRCDIR)/out/$(KBUILD_HOST).$(KBUILD_HOST_ARCH)/$(KBUILD_TYPE)/bootstrap
+
+# Override this on the make commandline if you need to (FreeBSD).
+AUTORECONF = autoreconf
+
+all: stage1 stage2
+
+
+#
+# Stage 1 - Build bootstrap kmk, kmk_redirect and sed, refresh config.h caches, link
+#           up kmk_ash so $(OUTDIR)/kmk can serve as kBuild bin dir.
+#
+stage1: \
+    $(OUTDIR)/kmk/kmk \
+    $(OUTDIR)/kmk/kmk_ash \
+    $(OUTDIR)/kmk/kmk_sed \
+    $(SRCDIR)/src/kmk/config.h.$(KBUILD_TARGET) \
+    $(SRCDIR)/src/sed/config.h.$(KBUILD_TARGET)
+
+# kmk
+$(OUTDIR)/kmk/ts-autoreconf:
+	mkdir -p $(@D)
+	cd $(SRCDIR)/src/kmk && $(AUTORECONF) -i -v
+	echo done > $@
+
+$(OUTDIR)/kmk/ts-configured: $(OUTDIR)/kmk/ts-autoreconf
+	cd $(OUTDIR)/kmk && $(SRCDIR)/src/kmk/configure
+	echo done > $@
+
+$(OUTDIR)/kmk/config.h: $(OUTDIR)/kmk/ts-configured
+
+$(SRCDIR)/src/kmk/config.h.$(KBUILD_TARGET): $(OUTDIR)/kmk/config.h
+	cp -f $(OUTDIR)/kmk/config.h $(SRCDIR)/src/kmk/config.h.$(KBUILD_TARGET)
+
+$(OUTDIR)/kmk/kmk: $(OUTDIR)/kmk/ts-configured
+	$(MAKE) -C $(@D)
+
+# sed
+$(OUTDIR)/sed/ts-autoreconf:
+	mkdir -p $(@D)
+	@cd $(SRCDIR)/src/sed && $(AUTORECONF) -i -v --force
+	echo done > $@
+
+$(OUTDIR)/sed/ts-configured: $(OUTDIR)/sed/ts-autoreconf
+	cd $(OUTDIR)/sed && $(SRCDIR)/src/sed/configure --without-libintl --disable-nls
+	echo done > $@
+
+$(OUTDIR)/sed/config.h: $(OUTDIR)/sed/ts-configured
+
+$(SRCDIR)/src/sed/config.h.$(KBUILD_TARGET): $(OUTDIR)/sed/config.h
+	cp -f $< $@
+
+$(OUTDIR)/sed/sed/sed: $(OUTDIR)/sed/ts-configured
+	$(MAKE) -C $(@D)/..
+
+$(OUTDIR)/kmk/kmk_sed: $(OUTDIR)/sed/sed/sed
+	cp -f $< $@
+
+$(OUTDIR)/kmk/kmk_ash:
+	ln -s /bin/sh $@
+
+#
+# Stage 2 - Build kBuild using the bootstrap tools from the previous step
+#           and install it to kBuild/bin/x.y.
+#
+stage2: \
+    $(OUTDIR)/ts-stage2-build \
+    $(OUTDIR)/ts-stage2-install
+
+$(OUTDIR)/ts-stage2-build: \
+		$(SRCDIR)/src/kmk/config.h.$(KBUILD_TARGET) \
+                $(SRCDIR)/src/sed/config.h.$(KBUILD_TARGET) \
+		$(OUTDIR)/kmk/kmk
+	$(OUTDIR)/kmk/kmk -C $(SRCDIR)
+	echo done > $@
+
+$(OUTDIR)/ts-stage2-install: $(OUTDIR)/ts-stage2-build
+	$(OUTDIR)/kmk/kmk -C $(SRCDIR) PATH_INS=$(SRCDIR) install
+	echo done > $@
+
+
+#
+# Clean the output files...
+#
+clean:
+	rm -Rf $(SRCDIR)/out/ \
+		$(SRCDIR)/src/kmk/autom4te.cache/ \
+		$(SRCDIR)/src/sed/autom4te.cache/
+	rm -f $(SRCDIR)/src/kmk/Makefile.in \
+		$(SRCDIR)/src/kmk/config.h.in \
+		$(SRCDIR)/src/kmk/configure \
+		$(SRCDIR)/src/kmk/aclocal.m4 \
+		$(SRCDIR)/src/kmk/glob/Makefile.in \
+		$(SRCDIR)/src/kmk/config/Makefile.in \
+		$(SRCDIR)/src/kmk/config/depcomp \
+		$(SRCDIR)/src/kmk/config/compile \
+		$(SRCDIR)/src/kmk/config/missing \
+		$(SRCDIR)/src/kmk/config/config.guess \
+		$(SRCDIR)/src/kmk/config/config.sub \
+		$(SRCDIR)/src/kmk/config/install-sh \
+		$(SRCDIR)/src/kmk/w32/Makefile.in
+
+
+# can't hurt...
+.NOTPARALLEL:
+
Index: /tags/kBuild-0.1.4/dist/macports/PortIndex
===================================================================
--- /tags/kBuild-0.1.4/dist/macports/PortIndex	(revision 1780)
+++ /tags/kBuild-0.1.4/dist/macports/PortIndex	(revision 1780)
@@ -0,0 +1,4 @@
+kbuild 336
+variants universal description kBuild portdir devel/kbuild homepage http://svn.netlabs.org/kbuild epoch 0 platforms darwin name kbuild long_description {See http://svn.netlabs.org/kbuild (I'm lazy). Stable version, well, soon to be stable anyways.} maintainers bird-kBuild-spam@anduin.net categories devel version 0.1.3-beta revision 0
+kbuild-head 310
+variants universal description {kBuild subversion trunk} portdir devel/kbuild-head homepage http://svn.netlabs.org/kbuild epoch 0 platforms darwin name kbuild-head long_description {See http://svn.netlabs.org/kbuild (I'm lazy).} maintainers bird-kBuild-spam@anduin.net categories devel version 9999 revision 0
Index: /tags/kBuild-0.1.4/dist/macports/devel/kbuild-head/Portfile
===================================================================
--- /tags/kBuild-0.1.4/dist/macports/devel/kbuild-head/Portfile	(revision 1780)
+++ /tags/kBuild-0.1.4/dist/macports/devel/kbuild-head/Portfile	(revision 1780)
@@ -0,0 +1,35 @@
+# $Id$
+# Very crude atm, everything is exec'ed.
+
+PortSystem 1.0
+name            kbuild-head
+version         9999
+categories      devel
+maintainers     bird-kBuild-spam@anduin.net
+description     kBuild subversion trunk
+long_description \
+    See http://svn.netlabs.org/kbuild (I'm lazy).
+
+homepage        http://svn.netlabs.org/kbuild
+platforms       darwin
+fetch.type      svn
+svn.url         http://svn.netlabs.org/repos/kbuild/trunk
+#svn.url         svn://system360/svn-mirrors/kbuild/trunk
+worksrcdir   	trunk
+
+test.run        no
+
+configure {}
+
+build {
+    system "${workpath}/${worksrcdir}/kBuild/env.sh --release kmk -C ${workpath}/${worksrcdir} NIX_INSTALL_DIR=${prefix} -j ${buildmakejobs}"
+}
+
+test {
+    system "${workpath}/${worksrcdir}/out/darwin.x86/release/kBuild/bin/darwin.x86/kmk -C ${workpath}/${worksrcdir}/tests nothing"
+}
+
+destroot {
+    system "${workpath}/${worksrcdir}/kBuild/env.sh --release kmk -C ${workpath}/${worksrcdir} NIX_INSTALL_DIR=${prefix} PATH_INS=${destroot}/"
+}
+
Index: /tags/kBuild-0.1.4/dist/macports/devel/kbuild/Portfile
===================================================================
--- /tags/kBuild-0.1.4/dist/macports/devel/kbuild/Portfile	(revision 1780)
+++ /tags/kBuild-0.1.4/dist/macports/devel/kbuild/Portfile	(revision 1780)
@@ -0,0 +1,35 @@
+# $Id$
+# Very crude atm, everything is exec'ed.
+
+PortSystem 1.0
+name            kbuild
+version         0.1.3
+categories      devel
+maintainers     bird-kBuild-spam@anduin.net
+description     kBuild
+long_description \
+    See http://svn.netlabs.org/kbuild (I'm lazy). Stable version, well, soon to be stable anyways.
+
+homepage        http://svn.netlabs.org/kbuild
+platforms       darwin
+fetch.type      svn
+svn.url         http://svn.netlabs.org/repos/kbuild/trunk
+svn.tag         1651
+worksrcdir   	trunk
+
+test.run        no
+
+configure {}
+
+build {
+    system "${workpath}/${worksrcdir}/kBuild/env.sh --release kmk -C ${workpath}/${worksrcdir} NIX_INSTALL_DIR=${prefix} -j ${buildmakejobs}"
+}
+
+test {
+    system "${workpath}/${worksrcdir}/out/darwin.x86/release/kBuild/bin/darwin.x86/kmk -C ${workpath}/${worksrcdir}/tests nothing"
+}
+
+destroot {
+    system "${workpath}/${worksrcdir}/kBuild/env.sh --release kmk -C ${workpath}/${worksrcdir} NIX_INSTALL_DIR=${prefix} PATH_INS=${destroot}/"
+}
+
Index: /tags/kBuild-0.1.4/dist/portage/dev-util/kBuild-svn/kBuild-svn-0.1.ebuild
===================================================================
--- /tags/kBuild-0.1.4/dist/portage/dev-util/kBuild-svn/kBuild-svn-0.1.ebuild	(revision 1780)
+++ /tags/kBuild-0.1.4/dist/portage/dev-util/kBuild-svn/kBuild-svn-0.1.ebuild	(revision 1780)
@@ -0,0 +1,34 @@
+# Copyright (c) 2006 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit subversion
+
+DESCRIPTION="kBuild"
+HOMEPAGE="http://svn.netlabs.org/kbuild"
+ESVN_REPO_URI="http://svn.netlabs.org/repos/kbuild/trunk"
+ESVN_STORE_DIR="${DISTDIR}/svn-src"
+ESVN_PROJECT="${PN/-svn}"
+
+SLOT="0"
+LICENSE="GPL-2"
+KEYWORDS="amd64 ~ppc ~sparc x86"
+IUSE=""
+
+KBUILD_SRC_TREE="${ESVN_STORE_DIR}/kBuild/trunk"
+
+src_compile() {
+    append-cflags -g
+    append-ldflags -g
+    ${KBUILD_SRC_TREE}/kBuild/env.sh \
+        kmk NIX_INSTALL_DIR=/usr BUILD_TYPE=release -C ${KBUILD_SRC_TREE} \
+            || die "kmk failed"
+}
+
+src_install () {
+    append-cflags -g
+    append-ldflags -g
+    ${KBUILD_SRC_TREE}/kBuild/env.sh \
+        kmk NIX_INSTALL_DIR=/usr BUILD_TYPE=release -C ${KBUILD_SRC_TREE} PATH_INS=${D} install \
+            || die "kmk install failed"
+}
Index: /tags/kBuild-0.1.4/dist/portage/dev-util/kBuild/kBuild-0.1.0.ebuild
===================================================================
--- /tags/kBuild-0.1.4/dist/portage/dev-util/kBuild/kBuild-0.1.0.ebuild	(revision 1780)
+++ /tags/kBuild-0.1.4/dist/portage/dev-util/kBuild/kBuild-0.1.0.ebuild	(revision 1780)
@@ -0,0 +1,34 @@
+# Copyright (c) 2006-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit eutils
+
+DESCRIPTION="kBuild"
+HOMEPAGE="http://svn.netlabs.org/kbuild"
+#SRC_URI="http://ftp.netlabs.org/pub/kBuild/${P}.tar.gz"
+SRC_URI="file:///home/bird/coding/kBuild/svn/${P}.tar.gz"
+
+SLOT="0"
+LICENSE="GPL-2"
+KEYWORDS="amd64 ~ppc ~sparc x86"
+IUSE=""
+
+KBUILD_SRC_TREE="${WORKDIR}/trunk/"
+
+src_compile() {
+    append-cflags -g
+    append-ldflags -g
+    ${KBUILD_SRC_TREE}/kBuild/env.sh \
+        kmk NIX_INSTALL_DIR=/usr BUILD_TYPE=release -C ${KBUILD_SRC_TREE} \
+        || die "kmk failed"
+}
+
+src_install () {
+    append-cflags -g
+    append-ldflags -g
+    ${KBUILD_SRC_TREE}/kBuild/env.sh \
+        kmk NIX_INSTALL_DIR=/usr BUILD_TYPE=release -C ${KBUILD_SRC_TREE} PATH_INS=${D} install \
+        || die "kmk install failed"
+}
+
Index: /tags/kBuild-0.1.4/kBuild/COPYING
===================================================================
--- /tags/kBuild-0.1.4/kBuild/COPYING	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/COPYING	(revision 1780)
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.
+
+		    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.)
+
+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.
+
+  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.
+
+  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
+
+	    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) <year>  <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.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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 Lesser General
+Public License instead of this License.
Index: /tags/kBuild-0.1.4/kBuild/bin/win.amd64/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest
===================================================================
--- /tags/kBuild-0.1.4/kBuild/bin/win.amd64/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/bin/win.amd64/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest	(revision 1780)
@@ -0,0 +1,8 @@
+﻿<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+    <noInheritable></noInheritable>
+    <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="amd64" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
+    <file name="msvcr80.dll" hash="1a4afbb799882b9a07d902c94d652e18932c518d" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>xfKIV7TTqdGCucJfPVmbuEzLiss=</dsig:DigestValue></asmv2:hash></file>
+    <file name="msvcp80.dll" hash="0702b235e0ddcc887882d0220c9fbd88abd98055" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>1pETDkgIkQ7VygZAFQubrcgSQkM=</dsig:DigestValue></asmv2:hash></file>
+    <file name="msvcm80.dll" hash="cfe561a26e8a79dc6e21a16e85d539c1493a0c7b" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>2jBihChyTNKBFRpgo2GydheyZQg=</dsig:DigestValue></asmv2:hash></file>
+</assembly>
Index: /tags/kBuild-0.1.4/kBuild/env.sh
===================================================================
--- /tags/kBuild-0.1.4/kBuild/env.sh	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/env.sh	(revision 1780)
@@ -0,0 +1,579 @@
+#!/bin/sh
+# $Id$
+## @file
+# Environment setup script.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+#set -x
+
+#
+# Check if we're in eval mode or not.
+#
+ERR_REDIR=1
+DBG_REDIR=1
+EVAL_OPT=
+EVAL_EXPORT="export "
+DBG_OPT=
+QUIET_OPT=
+FULL_OPT=
+LEGACY_OPT=
+VAR_OPT=
+VALUE_ONLY_OPT=
+EXP_TYPE_OPT=
+while test $# -gt 0;
+do
+    case "$1" in
+        "--debug-script")
+            DBG_OPT="true"
+            ;;
+        "--no-debug-script")
+            DBG_OPT=
+            ;;
+        "--quiet")
+            QUIET_OPT="true"
+            ;;
+        "--verbose")
+            QUIET_OPT=
+            ;;
+        "--full")
+            FULL_OPT="true"
+            ;;
+        "--normal")
+            FULL_OPT=
+            ;;
+        "--legacy")
+            LEGACY_OPT="true"
+            ;;
+        "--no-legacy")
+            LEGACY_OPT=
+            ;;
+        "--eval")
+            EVAL_OPT="true"
+            ERR_REDIR=2
+            DBG_REDIR=2
+            ;;
+        "--set")
+            EVAL_OPT="true"
+            EVAL_EXPORT=""
+            ERR_REDIR=2
+            DBG_REDIR=2
+            ;;
+        "--var")
+            shift
+            VAR_OPT="${VAR_OPT} $1"
+            ERR_REDIR=2
+            DBG_REDIR=2
+            ;;
+        "--value-only")
+            VALUE_ONLY_OPT="true"
+            ;;
+        "--name-and-value")
+            VALUE_ONLY_OPT=
+            ;;
+        "--release")
+            EXP_TYPE_OPT=1
+            KBUILD_TYPE=release
+            BUILD_TYPE=
+            ;;
+        "--debug")
+            EXP_TYPE_OPT=1
+            KBUILD_TYPE=debug
+            BUILD_TYPE=
+            ;;
+        "--profile")
+            EXP_TYPE_OPT=1
+            KBUILD_TYPE=profile
+            BUILD_TYPE=
+            ;;
+
+        "--help")
+            echo "kBuild Environment Setup Script, v0.1.4"
+            echo ""
+            echo "syntax: $0 [options] [command [args]]"
+            echo "    or: $0 [options] --var <varname>"
+            echo "    or: $0 [options] --eval"
+            echo "    or: $0 [options] --eval --var <varname>"
+            echo ""
+            echo "The first form will execute the command, or if no command is given start"
+            echo "an interactive shell."
+            echo "The second form will print the specfified variable(s)."
+            echo "The third form will print all exported variables suitable for bourne shell"
+            echo "evalutation."
+            echo "The forth form will only print the specified variable(s)."
+            echo ""
+            echo "Options:"
+            echo "  --debug, --release, --profile"
+            echo "      Alternative way of specifying KBUILD_TYPE."
+            echo "  --debug-script, --no-debug-script"
+            echo "      Controls debug output. Default: --no-debug-script"
+            echo "  --quiet, --verbose"
+            echo "      Controls informational output. Default: --verbose"
+            echo "  --full, --normal"
+            echo "      Controls the variable set. Default: --normal"
+            echo "  --legacy, --no-legacy"
+            echo "      Include legacy variables in result. Default: --no-legacy"
+            echo "  --value-only, --name-and-value"
+            echo "      Controls what the result of a --var query. Default: --name-and-value"
+            echo "  --set, --export"
+            echo "      Whether --eval explicitly export the variables. --set is useful for"
+            echo "      getting a list of environment vars for a commandline, while --eval"
+            echo "      is useful for eval `env.sh`. Default: --export"
+            echo ""
+            exit 1
+            ;;
+        *)
+            break
+            ;;
+    esac
+    shift
+done
+
+
+#
+# Deal with legacy environment variables.
+#
+if test -n "$PATH_KBUILD"; then
+    if test -n "$KBUILD_PATH"  -a  "$KBUILD_PATH" != "$PATH_KBUILD"; then
+        echo "$0: error: KBUILD_PATH ($KBUILD_PATH) and PATH_KBUILD ($PATH_KBUILD) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_PATH=$PATH_KBUILD
+fi
+if test -n "$PATH_KBUILD_BIN"; then
+    if test -n "$KBUILD_BIN_PATH"  -a  "$KBUILD_BIN_PATH" != "$PATH_KBUILD_BIN"; then
+        echo "$0: error: KBUILD_BIN_PATH ($KBUILD_BIN_PATH) and PATH_KBUILD_BIN ($PATH_KBUILD_BIN) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_BIN_PATH=$PATH_KBUILD_BIN
+fi
+
+if test -n "$BUILD_TYPE"; then
+    if test -n "$KBUILD_TYPE"  -a  "$KBUILD_TYPE" != "$BUILD_TYPE"; then
+        echo "$0: error: KBUILD_TYPE ($KBUILD_TYPE) and BUILD_TYPE ($BUILD_TYPE) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_TYPE=$BUILD_TYPE
+fi
+
+if test -n "$BUILD_PLATFORM"; then
+    if test -n "$KBUILD_HOST"  -a  "$KBUILD_HOST" != "$BUILD_PLATFORM"; then
+        echo "$0: error: KBUILD_HOST ($KBUILD_HOST) and BUILD_PLATFORM ($BUILD_PLATFORM) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_HOST=$BUILD_PLATFORM
+fi
+if test -n "$BUILD_PLATFORM_ARCH"; then
+    if test -n "$KBUILD_HOST_ARCH"  -a  "$KBUILD_HOST_ARCH" != "$BUILD_PLATFORM_ARCH"; then
+        echo "$0: error: KBUILD_HOST_ARCH ($KBUILD_HOST_ARCH) and BUILD_PLATFORM_ARCH ($BUILD_PLATFORM_ARCH) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_HOST_ARCH=$BUILD_PLATFORM_ARCH
+fi
+if test -n "$BUILD_PLATFORM_CPU"; then
+    if test -n "$KBUILD_HOST_CPU"  -a  "$KBUILD_HOST_CPU" != "$BUILD_PLATFORM_CPU"; then
+        echo "$0: error: KBUILD_HOST_CPU ($KBUILD_HOST_CPU) and BUILD_PLATFORM_CPU ($BUILD_PLATFORM_CPU) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_HOST_CPU=$BUILD_PLATFORM_CPU
+fi
+
+if test -n "$BUILD_TARGET"; then
+    if test -n "$KBUILD_TARGET"  -a  "$KBUILD_TARGET" != "$BUILD_TARGET"; then
+        echo "$0: error: KBUILD_TARGET ($KBUILD_TARGET) and BUILD_TARGET ($BUILD_TARGET) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_TARGET=$BUILD_TARGET
+fi
+if test -n "$BUILD_TARGET_ARCH"; then
+    if test -n "$KBUILD_TARGET_ARCH"  -a  "$KBUILD_TARGET_ARCH" != "$BUILD_TARGET_ARCH"; then
+        echo "$0: error: KBUILD_TARGET_ARCH ($KBUILD_TARGET_ARCH) and BUILD_TARGET_ARCH ($BUILD_TARGET_ARCH) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_TARGET_ARCH=$BUILD_TARGET_ARCH
+fi
+if test -n "$BUILD_TARGET_CPU"; then
+    if test -n "$KBUILD_TARGET_CPU"  -a  "$KBUILD_TARGET_CPU" != "$BUILD_TARGET_CPU"; then
+        echo "$0: error: KBUILD_TARGET_CPU ($KBUILD_TARGET_CPU) and BUILD_TARGET_CPU ($BUILD_TARGET_CPU) disagree." 1>&${ERR_REDIR}
+        sleep 1
+        exit 1
+    fi
+    KBUILD_TARGET_CPU=$BUILD_TARGET_CPU
+fi
+
+
+#
+# Set default build type.
+#
+if test -z "$KBUILD_TYPE"; then
+    KBUILD_TYPE=release
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_TYPE=$KBUILD_TYPE" 1>&${DBG_REDIR}
+
+#
+# Determin the host platform.
+#
+# The CPU isn't important, only the other two are.  But, since the cpu,
+# arch and platform (and build type) share a common key space, try make
+# sure any new additions are unique. (See header.kmk, KBUILD_OSES/ARCHES.)
+#
+if test -z "$KBUILD_HOST"; then
+    KBUILD_HOST=`uname`
+    case "$KBUILD_HOST" in
+        Darwin|darwin)
+            KBUILD_HOST=darwin
+            ;;
+
+        DragonFly)
+            KBUILD_HOST=dragonfly
+            ;;
+
+        freebsd|FreeBSD|FREEBSD)
+            KBUILD_HOST=freebsd
+            ;;
+
+        linux|Linux|GNU/Linux|LINUX)
+            KBUILD_HOST=linux
+            ;;
+
+        netbsd|NetBSD|NETBSD)
+            KBUILD_HOST=netbsd
+            ;;
+
+        openbsd|OpenBSD|OPENBSD)
+            KBUILD_HOST=openbsd
+            ;;
+
+        os2|OS/2|OS2)
+            KBUILD_HOST=os2
+            ;;
+
+        SunOS)
+            KBUILD_HOST=solaris
+            ;;
+
+        WindowsNT|CYGWIN_NT-*)
+            KBUILD_HOST=win
+            ;;
+
+        *)
+            echo "$0: unknown os $KBUILD_HOST" 1>&${ERR_REDIR}
+            sleep 1
+            exit 1
+            ;;
+    esac
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_HOST=$KBUILD_HOST" 1>&${DBG_REDIR}
+
+if test -z "$KBUILD_HOST_ARCH"; then
+    # Try deduce it from the cpu if given.
+    if test -n "$KBUILD_HOST_CPU"; then
+        case "$KBUILD_HOST_CPU" in
+            i[3456789]86)
+                KBUILD_HOST_ARCH='x86'
+                ;;
+            k8|k8l|k9|k10)
+                KBUILD_HOST_ARCH='amd64'
+                ;;
+        esac
+    fi
+fi
+if test -z "$KBUILD_HOST_ARCH"; then
+    # Use uname -m or isainfo (lots of guesses here, please help clean this up...)
+    if test "$KBUILD_HOST" = "solaris"; then
+        KBUILD_HOST_ARCH=`isainfo | cut -f 1 -d ' '`
+
+    else
+        KBUILD_HOST_ARCH=`uname -m`
+    fi
+    case "$KBUILD_HOST_ARCH" in
+        x86_64|AMD64|amd64|k8|k8l|k9|k10)
+            KBUILD_HOST_ARCH='amd64'
+            ;;
+        x86|i86pc|ia32|i[3456789]86)
+            KBUILD_HOST_ARCH='x86'
+            ;;
+        sparc32|sparc)
+            KBUILD_HOST_ARCH='sparc32'
+            ;;
+        sparc64)
+            KBUILD_HOST_ARCH='sparc64'
+            ;;
+        s390)
+            KBUILD_HOST_ARCH='s390'
+            ;;
+        s390x)
+            KBUILD_HOST_ARCH='s390x'
+            ;;
+        ppc32|ppc|powerpc)
+            KBUILD_HOST_ARCH='ppc32'
+            ;;
+        ppc64|powerpc64)
+            KBUILD_HOST_ARCH='ppc64'
+            ;;
+        mips32|mips)
+            KBUILD_HOST_ARCH='mips32'
+            ;;
+        mips64)
+            KBUILD_HOST_ARCH='mips64'
+            ;;
+        ia64)
+            KBUILD_HOST_ARCH='ia64'
+            ;;
+        hppa32|parisc32|parisc)
+            KBUILD_HOST_ARCH='hppa32'
+            ;;
+        hppa64|parisc64)
+            KBUILD_HOST_ARCH='hppa64'
+            ;;
+        arm|armv4l|armv5tel|armv5tejl)
+            KBUILD_HOST_ARCH='arm'
+            ;;
+        alpha)
+            KBUILD_HOST_ARCH='alpha'
+            ;;
+
+        *)  echo "$0: unknown cpu/arch - $KBUILD_HOST_ARCH" 1>&${ERR_REDIR}
+            sleep 1
+            exit 1
+            ;;
+    esac
+
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_HOST_ARCH=$KBUILD_HOST_ARCH" 1>&${DBG_REDIR}
+
+if test -z "$KBUILD_HOST_CPU"; then
+    KBUILD_HOST_CPU="blend"
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_HOST_CPU=$KBUILD_HOST_CPU" 1>&${DBG_REDIR}
+
+#
+# The target platform.
+# Defaults to the host when not specified.
+#
+if test -z "$KBUILD_TARGET"; then
+    KBUILD_TARGET="$KBUILD_HOST"
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_TARGET=$KBUILD_TARGET" 1>&${DBG_REDIR}
+
+if test -z "$KBUILD_TARGET_ARCH"; then
+    KBUILD_TARGET_ARCH="$KBUILD_HOST_ARCH"
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_TARGET_ARCH=$KBUILD_TARGET_ARCH" 1>&${DBG_REDIR}
+
+if test -z "$KBUILD_TARGET_CPU"; then
+    if test "$KBUILD_TARGET_ARCH" = "$KBUILD_HOST_ARCH"; then
+        KBUILD_TARGET_CPU="$KBUILD_HOST_CPU"
+    else
+        KBUILD_TARGET_CPU="blend"
+    fi
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_TARGET_CPU=$KBUILD_TARGET_CPU" 1>&${DBG_REDIR}
+
+#
+# Determin executable extension and path separator.
+#
+_SUFF_EXE=
+_PATH_SEP=":"
+case "$KBUILD_HOST" in
+    os2|win|nt)
+        _SUFF_EXE=".exe"
+        _PATH_SEP=";"
+        ;;
+esac
+
+#
+# Determin KBUILD_PATH from the script location and calc KBUILD_BIN_PATH from there.
+#
+if test -z "$KBUILD_PATH"; then
+    KBUILD_PATH=`dirname "$0"`
+    KBUILD_PATH=`cd "$KBUILD_PATH" ; /bin/pwd`
+fi
+if test ! -f "$KBUILD_PATH/footer.kmk" -o ! -f "$KBUILD_PATH/header.kmk" -o ! -f "$KBUILD_PATH/rules.kmk"; then
+    echo "$0: error: KBUILD_PATH ($KBUILD_PATH) is not pointing to a popluated kBuild directory." 1>&${ERR_REDIR}
+    sleep 1
+    exit 1
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_PATH=$KBUILD_PATH" 1>&${DBG_REDIR}
+
+if test -z "$KBUILD_BIN_PATH"; then
+    KBUILD_BIN_PATH="${KBUILD_PATH}/bin/${KBUILD_HOST}.${KBUILD_HOST_ARCH}"
+fi
+test -n "$DBG_OPT" && echo "dbg: KBUILD_BIN_PATH=${KBUILD_BIN_PATH}" 1>&${DBG_REDIR}
+
+#
+# Add the bin/x.y/ directory to the PATH.
+# NOTE! Once bootstrapped this is the only thing that is actually necessary.
+#
+PATH="${KBUILD_BIN_PATH}${_PATH_SEP}$PATH"
+test -n "$DBG_OPT" && echo "dbg: PATH=$PATH" 1>&${DBG_REDIR}
+
+#
+# Sanity and x bits.
+#
+if test ! -d "${KBUILD_BIN_PATH}/"; then
+    echo "$0: warning: The bin directory for this platform doesn't exist. (${KBUILD_BIN_PATH}/)" 1>&${ERR_REDIR}
+else
+    for prog in kmk kDepPre kDepIDB kmk_append kmk_ash kmk_cat kmk_cp kmk_echo kmk_install kmk_ln kmk_mkdir kmk_mv kmk_rm kmk_rmdir kmk_sed;
+    do
+        chmod a+x ${KBUILD_BIN_PATH}/${prog} > /dev/null 2>&1
+        if test ! -f "${KBUILD_BIN_PATH}/${prog}${_SUFF_EXE}"; then
+            echo "$0: warning: The ${prog} program doesn't exist for this platform. (${KBUILD_BIN_PATH}/${prog}${_SUFF_EXE})" 1>&${ERR_REDIR}
+        fi
+    done
+fi
+
+#
+# The environment is in place, now take the requested action.
+#
+MY_RC=0
+if test -n "${VAR_OPT}"; then
+    # Echo variable values or variable export statements.
+    for var in ${VAR_OPT};
+    do
+        val=
+        case "$var" in
+            PATH)
+                val=$PATH
+                ;;
+            KBUILD_PATH)
+                val=$KBUILD_PATH
+                ;;
+            KBUILD_BIN_PATH)
+                val=$KBUILD_BIN_PATH
+                ;;
+            KBUILD_HOST)
+                val=$KBUILD_HOST
+                ;;
+            KBUILD_HOST_ARCH)
+                val=$KBUILD_HOST_ARCH
+                ;;
+            KBUILD_HOST_CPU)
+                val=$KBUILD_HOST_CPU
+                ;;
+            KBUILD_TARGET)
+                val=$KBUILD_TARGET
+                ;;
+            KBUILD_TARGET_ARCH)
+                val=$KBUILD_TARGET_ARCH
+                ;;
+            KBUILD_TARGET_CPU)
+                val=$KBUILD_TARGET_CPU
+                ;;
+            KBUILD_TYPE)
+                val=$KBUILD_TYPE
+                ;;
+            *)
+                echo "$0: error: Unknown variable $var specified in --var request." 1>&${ERR_REDIR}
+                sleep 1
+                exit 1
+                ;;
+        esac
+
+        if test -n "$EVAL_OPT"; then
+            echo "${EVAL_EXPORT} $var=$val"
+        else
+            if test -n "$VALUE_ONLY_OPT"; then
+                echo "$val"
+            else
+                echo "$var=$val"
+            fi
+        fi
+    done
+else
+    if test -n "$EVAL_OPT"; then
+        # Echo statements for the shell to evaluate.
+        test -n "$DBG_OPT" && echo "dbg: echoing exported variables" 1>&${DBG_REDIR}
+        echo "${EVAL_EXPORT} PATH=${PATH}"
+        test -n "${FULL_OPT}" -o "${EXP_TYPE_OPT}" && echo "${EVAL_EXPORT} KBUILD_TYPE=${KBUILD_TYPE}"
+        if test -n "${FULL_OPT}"; then
+            echo "${EVAL_EXPORT} KBUILD_PATH=${KBUILD_PATH}"
+            echo "${EVAL_EXPORT} KBUILD_HOST=${KBUILD_HOST}"
+            echo "${EVAL_EXPORT} KBUILD_HOST_ARCH=${KBUILD_HOST_ARCH}"
+            echo "${EVAL_EXPORT} KBUILD_HOST_CPU=${KBUILD_HOST_CPU}"
+            echo "${EVAL_EXPORT} KBUILD_TARGET=${KBUILD_TARGET}"
+            echo "${EVAL_EXPORT} KBUILD_TARGET_ARCH=${KBUILD_TARGET_ARCH}"
+            echo "${EVAL_EXPORT} KBUILD_TARGET_CPU=${KBUILD_TARGET_CPU}"
+
+            if test -n "${LEGACY_OPT}"; then
+                echo "${EVAL_EXPORT} PATH_KBUILD=${KBUILD_PATH}"
+                echo "${EVAL_EXPORT} BUILD_TYPE=${KBUILD_TYPE}"
+                echo "${EVAL_EXPORT} BUILD_PLATFORM=${KBUILD_HOST}"
+                echo "${EVAL_EXPORT} BUILD_PLATFORM_ARCH=${KBUILD_HOST_ARCH}"
+                echo "${EVAL_EXPORT} BUILD_PLATFORM_CPU=${KBUILD_HOST_CPU}"
+                echo "${EVAL_EXPORT} BUILD_TARGET=${KBUILD_TARGET}"
+                echo "${EVAL_EXPORT} BUILD_TARGET_ARCH=${KBUILD_TARGET_ARCH}"
+                echo "${EVAL_EXPORT} BUILD_TARGET_CPU=${KBUILD_TARGET_CPU}"
+            fi
+        fi
+    else
+        # Export variables.
+        export PATH
+        test -n "${FULL_OPT}" -o "${EXP_TYPE_OPT}" && export KBUILD_TYPE
+        if test -n "${FULL_OPT}"; then
+            export KBUILD_PATH
+            export KBUILD_HOST
+            export KBUILD_HOST_ARCH
+            export KBUILD_HOST_CPU
+            export KBUILD_TARGET
+            export KBUILD_TARGET_ARCH
+            export KBUILD_TARGET_CPU
+
+            if test -n "${LEGACY_OPT}"; then
+                export PATH_KBUILD=$KBUILD_PATH
+                export BUILD_TYPE=$KBUILD_TYPE
+                export BUILD_PLATFORM=$KBUILD_HOST
+                export BUILD_PLATFORM_ARCH=$KBUILD_HOST_ARCH
+                export BUILD_PLATFORM_CPU=$KBUILD_HOST_CPU
+                export BUILD_TARGET=$KBUILD_TARGET
+                export BUILD_TARGET_ARCH=$KBUILD_TARGET_ARCH
+                export BUILD_TARGET_CPU=$KBUILD_TARGET_CPU
+            fi
+        fi
+
+        # Execute command or spawn shell.
+        if test $# -eq 0; then
+            test -z "${QUIET_OPT}" && echo "$0: info: Spawning work shell..." 1>&${ERR_REDIR}
+            if test "$TERM" != 'dumb'  -a  -n "$BASH"; then
+                export PS1='\[\033[01;32m\]\u@\h \[\033[01;34m\]\W \$ \[\033[00m\]'
+            fi
+            $SHELL -i
+            MY_RC=$?
+        else
+            test -z "${QUIET_OPT}" && echo "$0: info: Executing command: $*" 1>&${ERR_REDIR}
+            $*
+            MY_RC=$?
+            test -z "${QUIET_OPT}" -a "$MY_RC" -ne 0 && echo "$0: info: rc=$MY_RC: $*" 1>&${ERR_REDIR}
+        fi
+    fi
+fi
+test -n "$DBG_OPT" && echo "dbg: finished (rc=$MY_RC)" 1>&${DBG_REDIR}
+exit $MY_RC
+
Index: /tags/kBuild-0.1.4/kBuild/envos2.cmd
===================================================================
--- /tags/kBuild-0.1.4/kBuild/envos2.cmd	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/envos2.cmd	(revision 1780)
@@ -0,0 +1,801 @@
+/*
+echo this is a rexx script!
+cancel & quit & exit
+*/
+/* $Id$ */
+/** @file
+ * Environment setup script for OS/2.
+ */
+ 
+/*
+ *
+ * Copyright (c) 1999-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*
+ * Setup the usual suspects.
+ */
+Address CMD '@echo off';
+signal on novalue name NoValueHandler
+if (RxFuncQuery('SysLoadFuncs') = 1) then
+do
+    call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs';
+    call SysLoadFuncs;
+end
+
+/*
+ * Apply the CMD.EXE workaround.
+ */
+call FixCMDEnv;
+
+/*
+ * Globals
+ */
+skBuildPath       = EnvGet("KBUILD_PATH");
+skBuildBinPath    = EnvGet("KBUILD_BIN_PATH");
+skBuildType       = EnvGet("KBUILD_TYPE");
+skBuildTarget     = EnvGet("KBUILD_TARGET");
+skBuildTargetArch = EnvGet("KBUILD_TARGET_ARCH");
+skBuildTargetCpu  = EnvGet("KBUILD_TARGET_CPU");
+skBuildHost       = EnvGet("KBUILD_HOST");
+skBuildHostArch   = EnvGet("KBUILD_HOST_ARCH");
+skBuildHostCpu    = EnvGet("KBUILD_HOST_CPU");
+
+/*
+ * Process arguments.
+ */
+fOptFull = 0
+fOptLegacy = 0
+fOptDbg = 0
+fOptQuiet = 0
+sOptVars = ""
+fOptValueOnly = 0
+sShowVarPrefix = "";
+fOptOverrideAll = 0
+fOptOverrideType = 0;
+fSetType = 0;
+fOptOverrideTarget = 0;
+fOptOverrideTargetArch = 0;
+fOptDefault = 0;
+
+parse arg sArgs
+do while (sArgs <> '')
+    parse value sArgs with sArg sRest
+    say 'sArgs='sArgs';'
+    say ' sArg='sArg';'
+    say 'sRest='sRest';'
+    
+    select 
+        when (sArg = "--debug-script") then do
+            fOptDbg = 1;
+        end
+        when (sArg = "--no-debug-script") then do
+            fOptDbg = 0;
+        end
+        when (sArg = "--quiet") then do
+            fOptQuiet = 1;
+        end
+        when (sArg = "--verbose") then do
+            fOptQuiet = 0;
+        end
+        when (sArg = "--full") then do
+            fOptFull = 1;
+        end
+        when (sArg = "--normal") then do
+            fOptFull = 0;
+        end
+        when (sArg = "--legacy") then do
+            fOptLegacy = 1;
+        end
+        when (sArg = "--no-legacy") then do
+            fOptLegacy = 0;
+        end
+        when (sArg = "--eval") then do
+            say "error: --eval is not supported on OS/2."
+        end
+        when (sArg = "--var") then do
+            parse value sRest with sVar sRest2
+            sRest = sRest2;
+            if (sVar = '') then do
+                say "syntax error: --var is missing the variable name";
+                call SysSleep 1
+                exit 1;
+            end
+            if (sVar = "all" | sOptVars = "all") then
+                sOptVars = "all";
+            else
+                sOptVars = sOptVars || " " || sVar;
+        end
+        when (sArg = "--set") then do
+            sShowVarPrefix = "SET ";
+        end
+        when (sArg = "--no-set") then do
+            sShowVarPrefix = "";
+        end
+        when (sArg = "--value-only") then do
+            fOptValueOnly = 1;
+        end
+        when (sArg = "--name-and-value") then do
+            fOptValueOnly = 0;
+        end
+        when (sArg = "--release") then do
+            fOptOverrideType = 1;
+            fSetType = 1;
+            skBuildType = 'release';
+        end
+        when (sArg = "--debug") then do
+            fOptOverrideType = 1;
+            fSetType = 1;
+            skBuildType = 'debug';
+        end
+        when (sArg = "--profile") then do
+            fOptOverrideType = 1;
+            fSetType = 1;
+            skBuildType = 'profile';
+        end
+        when (sArg = "--defaults") then do
+            fOptOverrideAll = 1;
+            skBuildType = "";
+            skBuildTarget = "";
+            skBuildTargetArch = "";
+            skBuildTargetCpu = "";
+            skBuildHost = "";
+            skBuildHostArch = "";
+            skBuildHostCpu = "";
+            skBuildPath = "";
+            skBuildBinPath = "";
+        end
+
+        when (sArg = "--help" | sArg = "-h" | sArg = "-?" | sArg = "/?" | sArg = "/h") then do
+            say "kBuild Environment Setup Script, v0.1.4"
+            say ""
+            say "syntax: envos2.cmd [options] [command [args]]"
+            say "    or: envos2.cmd [options] --var <varname>"
+            say ""
+            say "The first form will execute the command, or if no command is given"
+            say "modify the current invoking shell."
+            say "The second form will print the specfified variable(s)."
+            say ""
+            say "Options:"
+            say "  --debug, --release, --profile"
+            say "      Alternative way of specifying KBUILD_TYPE."
+            say "  --defaults"
+            say "      Enforce defaults for all the KBUILD_* values."
+            say "  --debug-script, --no-debug-script"
+            say "      Controls debug output. Default: --no-debug-script"
+            say "  --quiet, --verbose"
+            say "      Controls informational output. Default: --verbose"
+            say "  --full, --normal"
+            say "      Controls the variable set. Default: --normal"
+            say "  --legacy, --no-legacy"
+            say "      Include legacy variables in result. Default: --no-legacy"
+            say "  --value-only, --name-and-value"
+            say "      Controls what the result of a --var query. Default: --name-and-value"
+            say "  --set, --no-set"
+            say "      Whether to prefix the variable output with 'SET'."
+            say "      Default: --no-set"
+            say ""
+            exit 1
+        end
+        
+        when (sArg = "--") then do
+            sArgs = sRest;
+            leave;
+        end
+        
+        when (left(sArg, 2) = '--') then do
+            say 'syntax error: unknown option: '||sArg
+            call SysSleep 1
+            exit 1
+        end
+        
+        otherwise do
+            leave
+        end
+    end
+    sArgs = sRest;
+end
+sCommand = strip(sArgs);        
+   
+/*
+ * Deal with legacy environment variables.
+ */
+if (\fOptOverrideAll) then do
+    if (EnvGet("PATH_KBUILD") <> '') then do
+        if (skBuildPath <> '' & skBuildPath <> EnvGet("PATH_KBUILD")) then do
+            say "error: KBUILD_PATH ("||skBuildPath||") and PATH_KBUILD ("||EnvGet("PATH_KBUILD")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildPath = EnvGet("PATH_KBUILD");
+    end
+    
+    if (EnvGet("PATH_KBUILD_BIN") <> '') then do
+        if (skBuildPath <> '' & skBuildBinPath <> EnvGet("PATH_KBUILD_BIN")) then do
+            say "error: KBUILD_BIN_PATH ("||skBuildBinPath||") and PATH_KBUILD_BIN ("||EnvGet("PATH_KBUILD_BIN")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildBinPath = EnvGet("PATH_KBUILD_BIN");
+    end
+
+    if (EnvGet("BUILD_TYPE") <> '') then do
+        if (skBuildType <> '' & skBuildType <> EnvGet("BUILD_TYPE")) then do
+            say "error: KBUILD_TYPE ("||skBuildType||") and BUILD_TYPE ("||EnvGet("BUILD_TYPE")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildType = EnvGet("BUILD_TYPE");
+    end
+
+    if (EnvGet("BUILD_TARGET") <> '') then do
+        if (skBuildTarget <> '' & skBuildTarget <> EnvGet("BUILD_TARGET")) then do
+            say "error: KBUILD_TARGET ("||skBuildTarget||") and BUILD_TARGET ("||EnvGet("BUILD_TARGET")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildTarget = EnvGet("BUILD_TARGET");
+    end
+
+    if (EnvGet("BUILD_TARGET_ARCH") <> '') then do
+        if (skBuildTargetArch <> '' & skBuildTargetArch <> EnvGet("BUILD_TARGET_ARCH")) then do
+            say "error: KBUILD_TARGET_ARCH ("||skBuildTargetArch ||") and BUILD_TARGET_ARCH ("||EnvGet("BUILD_TARGET_ARCH")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildTargetArch = EnvGet("BUILD_TARGET_ARCH");
+    end
+    
+    if (EnvGet("BUILD_TARGET_CPU") <> '') then do
+        if (skBuildTargetCpu <> '' & skBuildTargetCpu <> EnvGet("BUILD_TARGET_CPU")) then do
+            say "error: KBUILD_TARGET_CPU ("||skBuildTargetCpu ||") and BUILD_TARGET_CPU ("||EnvGet("BUILD_TARGET_CPU")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildTargetCpu = EnvGet("BUILD_TARGET_CPU");
+    end
+
+    if (EnvGet("BUILD_PLATFORM") <> '') then do
+        if (skBuildHost <> '' & skBuildHost <> EnvGet("BUILD_PLATFORM")) then do
+            say "error: KBUILD_HOST ("||skBuildHost||") and BUILD_PLATFORM ("||EnvGet("BUILD_PLATFORM")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        if (skBuildHost = '' & EnvGet("BUILD_PLATFORM") = "OS2") then do
+            say "error: BUILD_PLATFORM=OS2! Please unset it or change it to 'os2'."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildHost = EnvGet("BUILD_PLATFORM");
+    end
+
+    if (EnvGet("BUILD_PLATFORM_ARCH") <> '') then do
+        if (skBuildHostArch <> '' & skBuildHostArch <> EnvGet("BUILD_PLATFORM_ARCH")) then do
+            say "error: KBUILD_HOST_ARCH ("||skBuildHostArch ||") and BUILD_PLATFORM_ARCH ("||EnvGet("BUILD_PLATFORM_ARCH")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildHostArch = EnvGet("BUILD_PLATFORM_ARCH");
+    end
+    
+    if (EnvGet("BUILD_PLATFORM_CPU") <> '') then do
+        if (skBuildHostCpu <> '' & skBuildHostCpu <> EnvGet("BUILD_PLATFORM_CPU")) then do
+            say "error: KBUILD_HOST_CPU ("||skBuildHostCpu ||") and BUILD_PLATFORM_CPU ("||EnvGet("BUILD_PLATFORM_CPU")||") disagree."
+            call SysSleep 1;
+            exit 1;
+        end
+        skBuildHostCpu = EnvGet("BUILD_PLATFORM_CPU");
+    end
+end
+                        
+/*
+ * Set default build type.
+ */ 
+if (skBuildType = '') then 
+    skBuildType = 'release';
+if (fOptDbg <> 0) then say "dbg: KBUILD_TYPE="||skBuildType
+
+/*
+ * Determin the host platform (OS/2)
+ */
+if (skBuildHost = '') then 
+    skBuildHost = 'os2';
+if (fOptDbg <> 0) then say "dbg: KBUILD_HOST="||skBuildHost
+
+if (skBuildHostArch = '') then do
+    select 
+        when (skBuildHostCpu = 'i386',
+            | skBuildHostCpu = 'i486',
+            | skBuildHostCpu = 'i586',
+            | skBuildHostCpu = 'i686',
+            | skBuildHostCpu = 'i786',
+            | skBuildHostCpu = 'i886',
+            | skBuildHostCpu = 'i986') then do
+            skBuildHostArch = "x86";
+        end
+        otherwise do
+            skBuildHostArch = "x86";
+        end
+    end
+end
+if (fOptDbg <> 0) then say "dbg: KBUILD_HOST_ARCH="||skBuildHostArch
+
+if (skBuildHostCpu = '') then 
+    skBuildHostCpu = 'blend';
+if (fOptDbg <> 0) then say "dbg: KBUILD_HOST_CPU="||skBuildHostCpu
+
+
+/*
+ * The target platform.
+ * Defaults to the host when not specified.
+ */
+if (skBuildTarget = '') then
+    skBuildTarget = skBuildHost;
+if (fOptDbg <> 0) then say "dbg: KBUILD_TARGET="||skBuildTarget
+
+if (skBuildTargetArch = '') then
+    skBuildTargetArch = skBuildHostArch;
+if (fOptDbg <> 0) then say "dbg: KBUILD_TARGET_ARCH="||skBuildTargetArch
+
+if (skBuildTargetCpu = '') then do
+    if (skBuildTargetArch = skBuildHostArch) then
+        skBuildTargetCpu = skBuildHostCpu;
+    else
+        skBuildTargetCpu = "blend";
+end    
+if (fOptDbg <> 0) then say "dbg: KBUILD_TARGET_CPU="||skBuildTargetCpu
+
+
+/*
+ * Determin KBUILD_PATH from the script location and calc KBUILD_BIN_PATH from there.
+ */
+if (skBuildPath = '') then do
+    skBuildPath = GetScriptDir()
+end
+skBuildPath = translate(skBuildPath, '/', '\')
+if (  FileExists(skBuildPath||"/footer.kmk") = 0,
+    | FileExists(skBuildPath||"/header.kmk") = 0,
+    | FileExists(skBuildPath||"/rules.kmk") = 0) then do
+    say "error: KBUILD_PATH ("skBuildPath||") is not pointing to a popluated kBuild directory."
+    call SysSleep 1
+    exit 1
+end
+if (fOptDbg <> 0) then say "dbg: KBUILD_PATH="||skBuildPath;
+
+if (skBuildBinPath = '') then do
+    skBuildBinPath = skBuildPath||'/bin/'||skBuildHost||'.'||skBuildHostArch;
+end
+skBuildBinPath = translate(skBuildBinPath, '/', '\')
+if (fOptDbg <> 0) then say "dbg: KBUILD_BIN_PATH="||skBuildBinPath;
+
+/*
+ * Add the bin/x.y/ directory to the PATH and BEGINLIBPATH.
+ * NOTE! Once bootstrapped this is the only thing that is actually necessary.
+ */
+sOldPath = EnvGet("PATH");
+call EnvAddFront 0, "PATH", translate(skBuildBinPath, '\', '/');
+sNewPath = EnvGet("PATH");
+call EnvSet 0, "PATH", sOldPath;
+if (fOptDbg <> 0) then say "dbg: PATH="||sNewPath;
+
+sOldBeginLibPath = EnvGet("BEGINLIBPATH");
+call EnvAddFront 0, "BEGINLIBPATH", translate(skBuildBinPath, '\', '/');
+sNewBeginLibPath = EnvGet("BEGINLIBPATH");
+call EnvSet 0, "BEGINLIBPATH", sOldBeginLibPath;
+if (fOptDbg <> 0) then say "dbg: BEGINLIBPATH="||sNewBeginLibPath;
+
+/* 
+ * Sanity check 
+ */
+if (DirExists(skBuildBinPath) = 0) then
+    say "warning: The bin directory for the build platform doesn't exist. ("||skBuildBinPath||")";
+else
+do
+    sPrograms = "kmk kDepPre kDepIDB kmk_append kmk_ash kmk_cat kmk_cp kmk_echo kmk_install kmk_ln kmk_mkdir kmk_mv kmk_redirect kmk_rm kmk_rmdir kmk_sed";
+    do i = 1 to words(sPrograms)
+        sProgram = word(sPrograms, i);
+        if (FileExists(skBuildBinPath||"\"||sProgram||".exe") = 0) then
+            say "warning: The "||sProgram||" program doesn't exit for this platform. ("||skBuildBinPath||")";
+    end
+end
+
+
+/*
+ * The environment is in place, now take the requested action.
+ */
+iRc = 0;
+if (sOptVars <> '') then 
+do
+    if (sOptVars = "all") then
+        sOptVars = "KBUILD_PATH KBUILD_BIN_PATH KBUILD_TYPE ",
+                || "KBUILD_TARGET KBUILD_TARGET_ARCH KBUILD_TARGET_CPU ",
+                || "KBUILD_HOST KBUILD_HOST_ARCH KBUILD_HOST_CPU ";
+                
+    /* Echo variable values or variable export statements. */
+    do i = 1 to words(sOptVars)
+        sVar = word(sOptVars, i)
+        sVal = '';
+        select 
+            when (sVar = "PATH") then               sVal = sNewPath;
+            when (sVar = "BEGINLIBPATH") then       sVal = sNewBeginLibPath;
+            when (sVar = "KBUILD_PATH") then        sVal = skBuildPath;
+            when (sVar = "KBUILD_BIN_PATH") then    sVal = skBuildBinPath;
+            when (sVar = "KBUILD_TYPE") then        sVal = skBuildType;
+            when (sVar = "KBUILD_HOST") then        sVal = skBuildHost;
+            when (sVar = "KBUILD_HOST_ARCH") then   sVal = skBuildHostArch;
+            when (sVar = "KBUILD_HOST_CPU") then    sVal = skBuildHostCpu;
+            when (sVar = "KBUILD_TARGET") then      sVal = skBuildTarget;
+            when (sVar = "KBUILD_TARGET_ARCH") then sVal = skBuildTargetArch;
+            when (sVar = "KBUILD_TARGET_CPU") then  sVal = skBuildTargetCpu;
+            otherwise do
+                say "error: Unknown variable "||sVar||" specified in --var request."
+                call SysSleep 1
+                exit 1
+            end
+
+        end
+        if (fOptValueOnly <> 0) then 
+            say sVal
+        else
+            say sShowVarPrefix||sVar||"="||sVal;
+    end
+end
+else
+do
+    /* Wipe out all variables - legacy included - with --default. */
+    if (fOptOverrideAll <> 0) then do
+        call EnvSet 0, KBUILD_PATH, ''
+        call EnvSet 0, KBUILD_BIN_PATH, ''
+        call EnvSet 0, KBUILD_HOST, ''
+        call EnvSet 0, KBUILD_HOST_ARCH, ''
+        call EnvSet 0, KBUILD_HOST_CPU, ''
+        call EnvSet 0, KBUILD_TARGET, ''
+        call EnvSet 0, KBUILD_TARGET_ARCH, ''
+        call EnvSet 0, KBUILD_TARGET_CPU, ''
+
+        call EnvSet 0, PATH_KBUILD, ''
+        call EnvSet 0, PATH_KBUILD_BIN, ''
+        call EnvSet 0, BUILD_PLATFORM, ''
+        call EnvSet 0, BUILD_PLATFORM_ARCH, ''
+        call EnvSet 0, BUILD_PLATFORM_CPU, ''
+        call EnvSet 0, BUILD_TARGET, ''
+        call EnvSet 0, BUILD_TARGET_ARCH, ''
+        call EnvSet 0, BUILD_TARGET_CPU, ''
+    end
+
+    /* Export the variables. */
+    call EnvSet 0, "PATH", sNewPath
+    call EnvSet 0, "BEGINLIBPATH", sNewBeginLibPath
+    if (fOptOverrideType <> 0) then call EnvSet 0, "KBUILD_TYPE", skBuildType
+    if (fOptFull <> 0) then do
+        call EnvSet 0, KBUILD_PATH,         skBuildPath
+        call EnvSet 0, KBUILD_HOST,         skBuildHost
+        call EnvSet 0, KBUILD_HOST_ARCH,    skBuildHostArch
+        call EnvSet 0, KBUILD_HOST_CPU,     skBuildHostCpu
+        call EnvSet 0, KBUILD_TARGET,       skBuildTarget
+        call EnvSet 0, KBUILD_TARGET_ARCH,  skBuildTargetArch
+        call EnvSet 0, KBUILD_TARGET_CPU,   skBuildTargetCpu
+
+        if (fOptLegacy <> 0) then do
+            call EnvSet 0, PATH_KBUILD,         skBuildPath      
+            call EnvSet 0, BUILD_PLATFORM,      skBuildHost      
+            call EnvSet 0, BUILD_PLATFORM_ARCH, skBuildHostArch  
+            call EnvSet 0, BUILD_PLATFORM_CPU,  skBuildHostCpu   
+            call EnvSet 0, BUILD_TARGET,        skBuildTarget    
+            call EnvSet 0, BUILD_TARGET_ARCH,   skBuildTargetArch
+            call EnvSet 0, BUILD_TARGET_CPU,    skBuildTargetCpu 
+        end
+    end
+        
+    /*
+     * Execute left over arguments.
+     */
+    if (strip(sCommand) <> '') then do
+        if (fOptQuiet <> 0) then say "info: Executing command: "|| sCommand
+        address CMD sCommand
+        iRc = rc;  
+        if (fOptQuiet <> 0 & iRc <> 0) then say "info: rc="||iRc||": "|| sCommand
+    end
+end
+if (fOptDbg <> 0) then say "dbg: finished (rc="||rc||")"
+exit (iRc);
+
+
+/*******************************************************************************
+*   Procedure Section                                                          *
+*******************************************************************************/
+
+/**
+ * Give the script syntax
+ */
+syntax: procedure
+    say 'syntax: envos2.cmd [command to be executed and its arguments]'
+    say ''
+return 0;
+
+
+/**
+ * No value handler
+ */
+NoValueHandler:
+    say 'NoValueHandler: line 'SIGL;
+exit(16);
+
+
+
+/**
+ * Add sToAdd in front of sEnvVar.
+ * Note: sToAdd now is allowed to be alist!
+ *
+ * Known features: Don't remove sToAdd from original value if sToAdd
+ *                 is at the end and don't end with a ';'.
+ */
+EnvAddFront: procedure
+    parse arg fRM, sEnvVar, sToAdd, sSeparator
+
+    /* sets default separator if not specified. */
+    if (sSeparator = '') then sSeparator = ';';
+
+    /* checks that sToAdd ends with an ';'. Adds one if not. */
+    if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then
+        sToAdd = sToAdd || sSeparator;
+
+    /* check and evt. remove ';' at start of sToAdd */
+    if (substr(sToAdd, 1, 1) = ';') then
+        sToAdd = substr(sToAdd, 2);
+
+    /* loop thru sToAdd */
+    rc = 0;
+    i = length(sToAdd);
+    do while i > 1 & rc = 0
+        j = lastpos(sSeparator, sToAdd, i-1);
+        rc = EnvAddFront2(fRM, sEnvVar, substr(sToAdd, j+1, i - j), sSeparator);
+        i = j;
+    end
+
+return rc;
+
+/**
+ * Add sToAdd in front of sEnvVar.
+ *
+ * Known features: Don't remove sToAdd from original value if sToAdd
+ *                 is at the end and don't end with a ';'.
+ */
+EnvAddFront2: procedure
+    parse arg fRM, sEnvVar, sToAdd, sSeparator
+
+    /* sets default separator if not specified. */
+    if (sSeparator = '') then sSeparator = ';';
+
+    /* checks that sToAdd ends with a separator. Adds one if not. */
+    if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then
+        sToAdd = sToAdd || sSeparator;
+
+    /* check and evt. remove the separator at start of sToAdd */
+    if (substr(sToAdd, 1, 1) = sSeparator) then
+        sToAdd = substr(sToAdd, 2);
+
+    /* Get original variable value */
+    sOrgEnvVar = EnvGet(sEnvVar);
+
+    /* Remove previously sToAdd if exists. (Changing sOrgEnvVar). */
+    i = pos(translate(sToAdd), translate(sOrgEnvVar));
+    if (i > 0) then
+        sOrgEnvVar = substr(sOrgEnvVar, 1, i-1) || substr(sOrgEnvVar, i + length(sToAdd));
+
+    /* set environment */
+    if (fRM) then
+        return EnvSet(0, sEnvVar, sOrgEnvVar);
+return EnvSet(0, sEnvVar, sToAdd||sOrgEnvVar);
+
+
+/**
+ * Add sToAdd as the end of sEnvVar.
+ * Note: sToAdd now is allowed to be alist!
+ *
+ * Known features: Don't remove sToAdd from original value if sToAdd
+ *                 is at the end and don't end with a ';'.
+ */
+EnvAddEnd: procedure
+    parse arg fRM, sEnvVar, sToAdd, sSeparator
+
+    /* sets default separator if not specified. */
+    if (sSeparator = '') then sSeparator = ';';
+
+    /* checks that sToAdd ends with a separator. Adds one if not. */
+    if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then
+        sToAdd = sToAdd || sSeparator;
+
+    /* check and evt. remove ';' at start of sToAdd */
+    if (substr(sToAdd, 1, 1) = sSeparator) then
+        sToAdd = substr(sToAdd, 2);
+
+    /* loop thru sToAdd */
+    rc = 0;
+    i = length(sToAdd);
+    do while i > 1 & rc = 0
+        j = lastpos(sSeparator, sToAdd, i-1);
+        rc = EnvAddEnd2(fRM, sEnvVar, substr(sToAdd, j+1, i - j), sSeparator);
+        i = j;
+    end
+
+return rc;
+
+
+/**
+ * Add sToAdd as the end of sEnvVar.
+ *
+ * Known features: Don't remove sToAdd from original value if sToAdd
+ *                 is at the end and don't end with a ';'.
+ */
+EnvAddEnd2: procedure
+    parse arg fRM, sEnvVar, sToAdd, sSeparator
+
+    /* sets default separator if not specified. */
+    if (sSeparator = '') then sSeparator = ';';
+
+    /* checks that sToAdd ends with a separator. Adds one if not. */
+    if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then
+        sToAdd = sToAdd || sSeparator;
+
+    /* check and evt. remove separator at start of sToAdd */
+    if (substr(sToAdd, 1, 1) = sSeparator) then
+        sToAdd = substr(sToAdd, 2);
+
+    /* Get original variable value */
+    sOrgEnvVar = EnvGet(sEnvVar);
+
+    if (sOrgEnvVar <> '') then
+    do
+        /* Remove previously sToAdd if exists. (Changing sOrgEnvVar). */
+        i = pos(translate(sToAdd), translate(sOrgEnvVar));
+        if (i > 0) then
+            sOrgEnvVar = substr(sOrgEnvVar, 1, i-1) || substr(sOrgEnvVar, i + length(sToAdd));
+
+        /* checks that sOrgEnvVar ends with a separator. Adds one if not. */
+        if (sOrgEnvVar = '') then
+            if (right(sOrgEnvVar,1) <> sSeparator) then
+                sOrgEnvVar = sOrgEnvVar || sSeparator;
+    end
+
+    /* set environment */
+    if (fRM) then return EnvSet(0, sEnvVar, sOrgEnvVar);
+return EnvSet(0, sEnvVar, sOrgEnvVar||sToAdd);
+
+
+/**
+ * Sets sEnvVar to sValue.
+ */
+EnvSet: procedure
+    parse arg fRM, sEnvVar, sValue
+
+    /* if we're to remove this, make valuestring empty! */
+    if (fRM) then
+        sValue = '';
+    sEnvVar = translate(sEnvVar);
+
+    /*
+     * Begin/EndLibpath fix:
+     *      We'll have to set internal these using both commandline 'SET'
+     *      and internal VALUE in order to export it and to be able to
+     *      get it (with EnvGet) again.
+     */
+    if ((sEnvVar = 'BEGINLIBPATH') | (sEnvVar = 'ENDLIBPATH')) then
+    do
+        if (length(sValue) >= 1024) then
+            say 'Warning: 'sEnvVar' is too long,' length(sValue)' char.';
+        return SysSetExtLibPath(sValue, substr(sEnvVar, 1, 1));
+    end
+
+    if (length(sValue) >= 1024) then
+    do
+        say 'Warning: 'sEnvVar' is too long,' length(sValue)' char.';
+        say '    This may make CMD.EXE unstable after a SET operation to print the environment.';
+    end
+    sRc = VALUE(sEnvVar, sValue, 'OS2ENVIRONMENT');
+return 0;
+
+
+/**
+ * Gets the value of sEnvVar.
+ */
+EnvGet: procedure
+    parse arg sEnvVar
+    if ((translate(sEnvVar) = 'BEGINLIBPATH') | (translate(sEnvVar) = 'ENDLIBPATH')) then
+        return SysQueryExtLibPath(substr(sEnvVar, 1, 1));
+return value(sEnvVar,, 'OS2ENVIRONMENT');
+
+
+/**
+ * Checks if a file exists.
+ * @param   sFile       Name of the file to look for.
+ * @param   sComplain   Complaint text. Complain if non empty and not found.
+ * @returns TRUE if file exists.
+ *          FALSE if file doesn't exists.
+ */
+FileExists: procedure
+    parse arg sFile, sComplain
+    rc = stream(sFile, 'c', 'query exist');
+    if ((rc = '') & (sComplain <> '')) then
+        say sComplain ''''sFile'''.';
+return rc <> '';
+
+
+/**
+ * Checks if a directory exists.
+ * @param   sDir        Name of the directory to look for.
+ * @param   sComplain   Complaint text. Complain if non empty and not found.
+ * @returns TRUE if file exists.
+ *          FALSE if file doesn't exists.
+ */
+DirExists: procedure
+    parse arg sDir, sComplain
+    rc = SysFileTree(sDir, 'sDirs', 'DO');
+    if (rc = 0 & sDirs.0 = 1) then
+        return 1;
+    if (sComplain <> '') then
+        say sComplain ''''sDir'''.';
+return 0;
+
+
+/**
+ *  Workaround for bug in CMD.EXE.
+ *  It messes up when REXX have expanded the environment.
+ */
+FixCMDEnv: procedure
+/* do this anyway
+    /* check for 4OS2 first */
+    Address CMD 'set 4os2test_env=%@eval[2 + 2]';
+    if (value('4os2test_env',, 'OS2ENVIRONMENT') = '4') then
+        return 0;
+*/
+
+    /* force environment expansion by setting a lot of variables and freeing them.
+     * ~6600 (bytes) */
+    do i = 1 to 100
+        Address CMD '@set dummyenvvar'||i'=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    end
+    do i = 1 to 100
+        Address CMD '@set dummyenvvar'||i'=';
+    end
+return 0;
+
+
+/**
+ * Translate a string to lower case.
+ */
+ToLower: procedure
+    parse arg sString
+return translate(sString, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
+
+
+/**
+ * Gets the script directory.
+ */
+GetScriptDir: procedure
+    /*
+     * Assuming this script is in the root directory, we can determing
+     * the abs path to it by using the 'parse source' feature in rexx.
+     */
+    parse source . . sScript
+    sScriptDir = filespec('drive', sScript) || strip(filespec('path', sScript), 'T', '\');
+return ToLower(sScriptDir);
+
Index: /tags/kBuild-0.1.4/kBuild/envwin.cmd
===================================================================
--- /tags/kBuild-0.1.4/kBuild/envwin.cmd	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/envwin.cmd	(revision 1780)
@@ -0,0 +1,725 @@
+@echo off
+REM $Id: $
+REM REM @file
+REM Environment setup script.
+REM
+
+REM
+REM Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+REM
+REM This file is part of kBuild.
+REM
+REM kBuild is free software; you can redistribute it and/or modify
+REM it under the terms of the GNU General Public License as published by
+REM the Free Software Foundation; either version 2 of the License, or
+REM (at your option) any later version.
+REM
+REM kBuild is distributed in the hope that it will be useful,
+REM but WITHOUT ANY WARRANTY; without even the implied warranty of
+REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+REM GNU General Public License for more details.
+REM
+REM You should have received a copy of the GNU General Public License
+REM along with kBuild; if not, write to the Free Software
+REM Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+REM
+
+REM
+REM Globals
+REM
+set _KBUILD_CURDIR=%CD%
+for /f "tokens=*" %%d in ('cd') do set _KBUILD_CURDIR=%%d
+
+set _KBUILD_PATH=%KBUILD_PATH%
+set _KBUILD_BIN_PATH=%KBUILD_BIN_PATH%
+set _KBUILD_TYPE=%KBUILD_TYPE%
+set _KBUILD_TARGET=%KBUILD_TARGET%
+set _KBUILD_TARGET_ARCH=%KBUILD_TARGET_ARCH%
+set _KBUILD_TARGET_CPU=%KBUILD_TARGET_CPU%
+set _KBUILD_HOST=%KBUILD_HOST%
+set _KBUILD_HOST_ARCH=%KBUILD_HOST_ARCH%
+set _KBUILD_HOST_CPU=%KBUILD_HOST_CPU%
+
+set _KBUILD_OVERRIDE_TYPE=0
+set _KBUILD_OVERRIDE_TARGET=0
+set _KBUILD_OVERRIDE_TARGET_ARCH=0
+
+REM
+REM Parse the arguments.
+REM
+REM Note: The 0 argument must be safed as it is also shifted.
+REM
+set _KBUILD_SELF=%0
+set _KBUILD_OPT_FULL=0
+set _KBUILD_OPT_LEGACY=0
+set _KBUILD_OPT_VAR=
+set _KBUILD_OPT_VALUE_ONLY=0
+set _KBUILD_SHOW_VAR_PREFIX=
+set _KBUILD_OPT_DBG=1
+set _KBUILD_OPT_OVERRIDE_ALL=0
+
+:argument_loop
+if ".%1" == ".-h"           goto do_help
+if ".%1" == "./h"           goto do_help
+if ".%1" == "./H"           goto do_help
+if ".%1" == ".-h"           goto do_help
+if ".%1" == ".-help"        goto do_help
+if ".%1" == ".--help"       goto do_help
+
+if ".%1" == ".--win"        goto want_win
+if ".%1" == ".-win"         goto want_win
+if ".%1" == ".--win32"      goto want_win32_bit
+if ".%1" == ".-win32"       goto want_win32_bit
+if ".%1" == ".-win64"       goto want_win64_bit
+if ".%1" == ".--win64"      goto want_win64_bit
+if ".%1" == ".--nt"         goto want_nt
+if ".%1" == ".-nt"          goto want_nt
+if ".%1" == ".--nt32"       goto want_nt32_bit
+if ".%1" == ".-nt32"        goto want_nt32_bit
+if ".%1" == ".--nt64"       goto want_nt64_bit
+if ".%1" == ".-nt64"        goto want_nt64_bit
+
+if ".%1" == ".--release"    goto want_release
+if ".%1" == ".--profile"    goto want_profile
+if ".%1" == ".--debug"      goto want_debug
+
+if ".%1" == ".--full"               goto opt_full
+if ".%1" == ".--normal"             goto opt_normal
+if ".%1" == ".--legacy"             goto opt_legacy
+if ".%1" == ".--no-legacy"          goto opt_no_legacy
+if ".%1" == ".--debug-script"       goto opt_debug_script
+if ".%1" == ".--no-debug-script"    goto opt_no_debug_script
+if ".%1" == ".--var"                goto opt_var
+if ".%1" == ".--value-only"         goto opt_value_only
+if ".%1" == ".--name-and-value"     goto opt_name_and_value
+if ".%1" == ".--set"                goto opt_set
+if ".%1" == ".--no-set"             goto opt_no_set
+
+goto done_arguments
+
+:want_win
+shift
+set _KBUILD_TARGET=win
+set _KBUILD_OVERRIDE_TARGET=1
+goto argument_loop
+
+:want_win32_bit
+shift
+set _KBUILD_TARGET=win
+set _KBUILD_TARGET_ARCH=x86
+set _KBUILD_OVERRIDE_TARGET=1
+set _KBUILD_OVERRIDE_TARGET_ARCH=1
+goto argument_loop
+
+:want_win64_bit
+shift
+set _KBUILD_TARGET=win
+set _KBUILD_TARGET_ARCH=amd64
+set _KBUILD_OVERRIDE_TARGET=1
+set _KBUILD_OVERRIDE_TARGET_ARCH=1
+goto argument_loop
+
+:want_nt
+shift
+set _KBUILD_TARGET=nt
+set _KBUILD_OVERRIDE_TARGET=1
+goto argument_loop
+
+:want_nt32_bit
+shift
+set _KBUILD_TARGET=nt
+set _KBUILD_TARGET_ARCH=x86
+set _KBUILD_OVERRIDE_TARGET=1
+set _KBUILD_OVERRIDE_TARGET_ARCH=1
+goto argument_loop
+
+:want_nt64_bit
+shift
+set _KBUILD_TARGET=nt
+set _KBUILD_TARGET_ARCH=amd64
+set _KBUILD_OVERRIDE_TARGET=1
+set _KBUILD_OVERRIDE_TARGET_ARCH=1
+goto argument_loop
+
+:want_release
+shift
+set _KBUILD_TYPE=release
+set _KBUILD_OVERRIDE_TYPE=1
+goto argument_loop
+
+:want_profile
+shift
+set _KBUILD_TYPE=profile
+set _KBUILD_OVERRIDE_TYPE=1
+goto argument_loop
+
+:want_debug
+shift
+set _KBUILD_TYPE=debug
+set _KBUILD_OVERRIDE_TYPE=1
+goto argument_loop
+
+:opt_full
+shift
+set _KBUILD_OPT_FULL=1
+goto argument_loop
+
+:opt_normal
+shift
+set _KBUILD_OPT_FULL=0
+goto argument_loop
+
+:opt_legacy
+shift
+set _KBUILD_OPT_LEGACY=1
+goto argument_loop
+
+:opt_no_legacy
+shift
+set _KBUILD_OPT_LEGACY=0
+goto argument_loop
+
+:opt_debug_script
+shift
+set _KBUILD_OPT_DBG=1
+goto argument_loop
+
+:opt_no_debug_script
+shift
+set _KBUILD_OPT_DBG=0
+goto argument_loop
+
+:opt_var
+shift
+if ".%1" == "." echo syntax error: --var is missing it's variable name.
+if ".%1" == "." goto failure
+set _KBUILD_OPT_VAR=%_KBUILD_OPT_VAR% %1
+shift
+goto argument_loop
+
+:opt_value_only
+shift
+set _KBUILD_OPT_VALUE_ONLY=1
+goto argument_loop
+
+:opt_name_and_value
+shift
+set _KBUILD_OPT_VALUE_ONLY=0
+goto argument_loop
+
+:opt_set
+shift
+set _KBUILD_SHOW_VAR_PREFIX=SET %_KBUILD_NON_EXISTING_VAR%
+goto argument_loop
+
+:opt_no_set
+shift
+set _KBUILD_SHOW_VAR_PREFIX=
+goto argument_loop
+
+
+REM #
+REM # Syntax
+REM #
+:do_help
+echo kBuild environment setup script for Windows NT.
+echo Syntax: envwin.cmd [options] [command to be executed]
+echo     or: envwin.cmd [options] --var varname
+echo .
+echo Options:
+echo   --win
+echo       Force windows target and host platform.
+echo   --win32
+echo       Force x86 32-bit windows target platform.
+echo   --win64
+echo       Force AMD64 64-bit windows target platform.
+echo   --nt
+echo       Force NT target and host platform.
+echo   --nt32
+echo       Force x86 32-bit NT target platform.
+echo   --nt64
+echo       Force AMD64 64-bit NT target platform.
+echo   --debug, --release, --profile
+echo       Alternative way of specifying KBUILD_TYPE.
+echo   --full, --normal
+echo       Controls the variable set. Default: --normal
+echo   --legacy, --no-legacy
+echo       Include legacy variables in result. Default: --legacy
+echo   --value-only, --name-and-value
+echo       Controls what the result of a --var query. Default: --name-and-value
+echo   --set, --no-set
+echo       Whether to prefix the variable output with 'SET' or not.
+echo       Default: --no-set
+
+goto end
+
+:done_arguments
+
+REM
+REM Convert legacy variable names.
+REM
+if ".%_KBUILD_OPT_OVERRIDE_ALL%" == ".1" goto legacy_convertion_done
+
+set _KBUILD_VARS=KBUILD_HOST (%_KBUILD_HOST%) and BUILD_PLATFORM (%BUILD_PLATFORM%)
+if not ".%BUILD_PLATFORM%" == "." if not ".%_KBUILD_HOST%" == "." if ".%_KBUILD_HOST%" == ".%BUILD_PLATFORM%" goto legacy_mismatch
+if not ".%BUILD_PLATFORM%" == "." set _KBUILD_HOST=%BUILD_PLATFORM%
+
+set _KBUILD_VARS=KBUILD_HOST_ARCH (%_KBUILD_HOST_ARCH%) and BUILD_PLATFORM_ARCH (%BUILD_PLATFORM_ARCH%)
+if not ".%BUILD_PLATFORM_ARCH%" == "." if not ".%_KBUILD_HOST_ARCH%" == "." if ".%_KBUILD_HOST_ARCH%" == ".%BUILD_PLATFORM_ARCH%" goto legacy_mismatch
+if not ".%BUILD_PLATFORM_ARCH%" == "." set _KBUILD_HOST_ARCH=%BUILD_PLATFORM_ARCH%
+
+set _KBUILD_VARS=KBUILD_HOST_CPU (%_KBUILD_HOST_CPU%) and BUILD_PLATFORM_CPU (%BUILD_PLATFORM_CPU%)
+if not ".%BUILD_PLATFORM_CPU%" == "." if not ".%_KBUILD_HOST_CPU%" == "." if ".%_KBUILD_HOST_CPU%" == ".%BUILD_PLATFORM_CPU%" goto legacy_mismatch
+if not ".%BUILD_PLATFORM_CPU%" == "." set _KBUILD_HOST_CPU=%BUILD_PLATFORM_CPU%
+
+if ".%_KBUILD_OVERRIDE_TARGET%" == ".1" goto legacy_skip_target
+set _KBUILD_VARS=KBUILD_TARGET (%_KBUILD_TARGET%) and BUILD_TARGET (%BUILD_TARGET%)
+if not ".%BUILD_TARGET%" == "." if not ".%_KBUILD_TARGET%" == "." if ".%_KBUILD_TARGET%" == ".%BUILD_TARGET%" goto legacy_mismatch
+if not ".%BUILD_TARGET%" == "." set _KBUILD_TARGET=%BUILD_TARGET%
+:legacy_skip_target
+
+if ".%_KBUILD_OVERRIDE_TARGET%" == ".1" goto legacy_skip_target_arch
+set _KBUILD_VARS=KBUILD_TARGET_ARCH (%_KBUILD_TARGET_ARCH%) and BUILD_TARGET_ARCH (%BUILD_TARGET_ARCH%)
+if not ".%BUILD_TARGET_ARCH%" == "." if not ".%_KBUILD_TARGET_ARCH%" == "." if ".%_KBUILD_TARGET_ARCH%" == ".%BUILD_TARGET_ARCH%" goto legacy_mismatch
+if not ".%BUILD_TARGET_ARCH%" == "." set _KBUILD_TARGET_ARCH=%BUILD_TARGET_ARCH%
+:legacy_skip_target_arch
+
+if ".%_KBUILD_OVERRIDE_TARGET%" == ".1" goto legacy_skip_target_cpu
+set _KBUILD_VARS=KBUILD_TARGET_CPU (%_KBUILD_TARGET_CPU%) and BUILD_TARGET_CPU (%BUILD_TARGET_CPU%)
+if not ".%BUILD_TARGET_CPU%" == "." if not ".%_KBUILD_TARGET_CPU%" == "." if ".%_KBUILD_TARGET_CPU%" == ".%BUILD_TARGET_CPU%" goto legacy_mismatch
+if not ".%BUILD_TARGET_CPU%" == "." set _KBUILD_TARGET_CPU=%BUILD_TARGET_CPU%
+:legacy_skip_target_cpu
+
+if ".%_KBUILD_OVERRIDE_TARGET%" == ".1" goto legacy_skip_type
+set _KBUILD_VARS=KBUILD_TYPE (%_KBUILD_TYPE%) and BUILD_TYPE (%BUILD_TYPE%)
+if not ".%BUILD_TYPE%" == "." if not ".%_KBUILD_TYPE%" == "." if ".%_KBUILD_TYPE%" == ".%BUILD_TYPE%" goto legacy_mismatch
+if not ".%BUILD_TYPE%" == "." set _KBUILD_TYPE=%BUILD_TYPE%
+:legacy_skip_type
+
+set _KBUILD_VARS=KBUILD_PATH (%_KBUILD_PATH%) and PATH_KBUILD (%PATH_KBUILD%)
+if not ".%PATH_KBUILD%" == "." if not ".%_KBUILD_PATH%" == "." if ".%_KBUILD_PATH%" == ".%PATH_KBUILD%" goto legacy_mismatch
+if not ".%PATH_KBUILD%" == "." set _KBUILD_PATH=%PATH_KBUILD%
+goto legacy_convertion_done
+
+:legacy_mismatch
+echo error: %_KBUILD_VARS% disagree.
+goto failed
+
+:legacy_convertion_done
+
+
+REM
+REM Check for illegal target/platforms.
+REM
+:target_and_platform
+if "%_KBUILD_TARGET" == "win32"  goto illegal_target
+if "%_KBUILD_TARGET" == "win64"  goto illegal_target
+if "%_KBUILD_HOST"   == "win32"  goto illegal_host
+if "%_KBUILD_HOST"   == "win64"  goto illegal_host
+goto target_and_platform_ok
+
+:illegal_target
+echo error: KBUILD_TARGET=%KBUILD_TARGET% is no longer valid.
+echo        Only 'win' and 'nt' are permitted for targeting microsoft windows.
+goto failed
+
+:illegal_host
+echo error: KBUILD_HOST=%KBUILD_HOST is no longer valid.
+echo        Only 'win' and 'nt' are permitted for building on microsoft windows.
+goto failed
+
+:target_and_platform_ok
+
+REM
+REM Find kBuild.
+REM
+REM We'll try determin the location of this script first and use that
+REM as a starting point for guessing the kBuild directory.
+REM
+
+REM Check if set via KBUILD_PATH.
+if not ".%_KBUILD_PATH%" == "."  if exist %_KBUILD_PATH%\footer.kmk goto found_kbuild
+
+REM Determin a correct self - by %0
+if exist "%_KBUILD_SELF%" goto found_self
+set _KBUILD_SELF=%_KBUILD_SELF%.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+
+REM Determin a correct self - by the PATH
+REM This is very verbose because nested for loops didn't work out.
+for /f "tokens=1  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=2  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=3  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=4  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=5  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=6  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=7  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=8  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=9  delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=10 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=11 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=12 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=13 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=14 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=15 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=16 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=17 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=18 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=19 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+for /f "tokens=20 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd
+if exist "%_KBUILD_SELF%" goto found_self
+goto try_by_pwd
+
+:found_self
+cd "%_KBUILD_SELF%\.."
+for /f "tokens=*" %%d in ('cd') do set _KBUILD_PATH=%%d
+cd "%_KBUILD_CURDIR%"
+if exist "%_KBUILD_PATH%\footer.kmk"      goto found_kbuild
+
+REM Try relative to the current directory.
+:try_by_pwd
+if exist "%_KBUILD_PATH%\footer.kmk"    goto found_kbuild
+set _KBUILD_PATH=%_KBUILD_CURDIR%
+if exist "%_KBUILD_PATH%\footer.kmk"    goto found_kbuild
+set _KBUILD_PATH=%_KBUILD_CURDIR%\kBuild
+if exist "%_KBUILD_PATH%\footer.kmk"    goto found_kbuild
+set _KBUILD_PATH=%_KBUILD_CURDIR%\..\kBuild
+if exist "%_KBUILD_PATH%\footer.kmk"    goto found_kbuild
+set _KBUILD_PATH=%_KBUILD_CURDIR%\..\..\kBuild
+if exist "%_KBUILD_PATH%\footer.kmk"    goto found_kbuild
+set _KBUILD_PATH=%_KBUILD_CURDIR%\..\..\..\kBuild
+if exist "%_KBUILD_PATH%\footer.kmk"    goto found_kbuild
+set _KBUILD_PATH=%_KBUILD_CURDIR%\..\..\..\..\kBuild
+if exist "%_KBUILD_PATH%\footer.kmk"    goto found_kbuild
+echo kBuild: Can't find the kBuild directory!
+set CURDIR=
+goto failed
+
+:found_kbuild
+cd "%_KBUILD_PATH%"
+for /f "tokens=*" %%d in ('cd') do set _KBUILD_PATH=%%d
+cd "%_KBUILD_CURDIR%"
+if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_PATH=%_KBUILD_PATH%
+
+
+REM
+REM Type - release is the default.
+REM
+if not ".%_KBUILD_TYPE%" == "."         goto have_type
+set _KBUILD_TYPE=release
+:have_type
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_TYPE=%_KBUILD_TYPE%
+
+
+REM
+REM Host platform - windows
+REM
+if not ".%_KBUILD_HOST%" == "."         goto have_host
+set _KBUILD_HOST=win
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_HOST=%_KBUILD_HOST%
+:have_host
+
+if not ".%_KBUILD_HOST_ARCH%" == "."    goto have_host_arch
+REM try guess from _KBUILD_HOST_CPU
+if ".%KBUILD_HOST_CPU%" == ".i386"      set _KBUILD_HOST_ARCH=x86
+if ".%KBUILD_HOST_CPU%" == ".i486"      set _KBUILD_HOST_ARCH=x86
+if ".%KBUILD_HOST_CPU%" == ".i586"      set _KBUILD_HOST_ARCH=x86
+if ".%KBUILD_HOST_CPU%" == ".i686"      set _KBUILD_HOST_ARCH=x86
+if ".%KBUILD_HOST_CPU%" == ".i786"      set _KBUILD_HOST_ARCH=x86
+if ".%KBUILD_HOST_CPU%" == ".i886"      set _KBUILD_HOST_ARCH=x86
+if ".%KBUILD_HOST_CPU%" == ".i986"      set _KBUILD_HOST_ARCH=x86
+if ".%KBUILD_HOST_CPU%" == ".k8"        set _KBUILD_HOST_ARCH=amd64
+if ".%KBUILD_HOST_CPU%" == ".k9"        set _KBUILD_HOST_ARCH=amd64
+if ".%KBUILD_HOST_CPU%" == ".k10"       set _KBUILD_HOST_ARCH=amd64
+if not ".%_KBUILD_HOST_ARCH%" == "."    goto have_host_arch
+REM try guess from PROCESSOR_ARCHITEW6432 and PROCESSOR_ARCHITECTURE
+set _KBUILD_TMP=%PROCESSOR_ARCHITECTURE%
+if not ".%PROCESSOR_ARCHITEW6432%" == "." set _KBUILD_TMP=%PROCESSOR_ARCHITEW6432%
+if "%_KBUILD_TMP%" == "x86"             set _KBUILD_HOST_ARCH=x86
+if "%_KBUILD_TMP%" == "X86"             set _KBUILD_HOST_ARCH=x86
+if "%_KBUILD_TMP%" == "amd64"           set _KBUILD_HOST_ARCH=amd64
+if "%_KBUILD_TMP%" == "Amd64"           set _KBUILD_HOST_ARCH=amd64
+if "%_KBUILD_TMP%" == "AMD64"           set _KBUILD_HOST_ARCH=amd64
+if "%_KBUILD_TMP%" == "x64"             set _KBUILD_HOST_ARCH=amd64
+if "%_KBUILD_TMP%" == "X64"             set _KBUILD_HOST_ARCH=amd64
+if not ".%_KBUILD_HOST_ARCH%" == "."    goto have_host_arch
+echo error: Cannot figure KBUILD_HOST_ARCH!
+goto failed
+:have_host_arch
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_HOST_ARCH=%_KBUILD_HOST_ARCH%
+
+if not ".%_KBUILD_HOST_CPU%" == "."     goto have_host_cpu
+set _KBUILD_HOST_CPU=blend
+:have_host_cpu
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_HOST_CPU=%_KBUILD_HOST_CPU%
+
+REM
+REM The target platform.
+REM Defaults to the host when not specified.
+REM
+if not ".%_KBUILD_TARGET%" == "."       goto have_target
+set _KBUILD_TARGET=%_KBUILD_HOST%
+:have_target
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_TARGET=%_KBUILD_TARGET%
+
+if not ".%_KBUILD_TARGET_ARCH%" == "."  goto have_target_arch
+set _KBUILD_TARGET_ARCH=%_KBUILD_HOST_ARCH%
+:have_target_arch
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH%
+
+if not ".%_KBUILD_TARGET_CPU%" == "."  goto have_target_cpu
+if ".%_KBUILD_TARGET_ARCH%" == ".%_KBUILD_HOST_ARCH%" set _KBUILD_TARGET_CPU=%_KBUILD_HOST_CPU%
+if not ".%_KBUILD_TARGET_CPU%" == "."  goto have_target_cpu
+set _KBUILD_TARGET_CPU=%_KBUILD_HOST_CPU%
+:have_target_cpu
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_TARGET_CPU=%_KBUILD_TARGET_CPU%
+
+REM
+REM Calc KBUILD_BIN_PATH and the new PATH value.
+REM
+if not ".%_KBUILD_BIN_PATH%" == "."     goto have_kbuild_bin_path
+set _KBUILD_BIN_PATH=%_KBUILD_PATH%\bin\win.%_KBUILD_HOST_ARCH%
+:have_kbuild_bin_path
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_BIN_PATH=%_KBUILD_BIN_PATH%
+
+set _KBUILD_NEW_PATH=%_KBUILD_BIN_PATH%;%PATH%
+if ".%_KBUILD_OPT_DBG%" == ".1"         echo dbg: _KBUILD_NEW_PATH=%_KBUILD_NEW_PATH%
+
+REM
+REM Sanity check.
+REM
+if not exist "%_KBUILD_BIN_PATH%" goto missing_bin_path
+if not exist "%_KBUILD_BIN_PATH%" goto done_chekcing_for_tools
+set _KBUILD_TMP=kmk kDepPre kDepIDB kmk_append kmk_ash kmk_cat kmk_cp kmk_echo kmk_install kmk_ln kmk_mkdir kmk_mv kmk_rm kmk_rmdir kmk_sed
+for %%i in ( %_KBUILD_TMP% ) do if not exist "%_KBUILD_BIN_PATH%\%%i.exe" echo warning: The %%i program doesn't exist for this platform. (%_KBUILD_BIN_PATH%\%%i.exe)"
+goto done_chekcing_for_tools
+
+:missing_bin_path
+echo warning: The bin directory for this platform doesn't exist. (%_KBUILD_BIN_PATH%)
+:done_chekcing_for_tools
+
+REM
+REM The environment is in place, now take the requested action.
+REM
+if ".%_KBUILD_OPT_VAR%" == "." goto exec_or_setup_env
+goto show_variable
+
+REM
+REM Show a set of variables.
+REM
+REM Note: 4nt doesn't grok the setlocal delayed expansion option.
+REM       So, we'll have to identify which shell we're running.
+REM
+:show_variable
+for %%i in ( %_KBUILD_OPT_VAR% ) do if "%%i" == "all" goto show_all_variables
+
+if not ".%_4VER%" == "." goto 4nt
+setlocal ENABLEDELAYEDEXPANSION
+if errorlevel 1 goto no_delay_expansion
+
+for %%i in ( %_KBUILD_OPT_VAR% ) do (
+    set _KBUILD_VAR=%%i
+    set _KBUILD_TMP=
+    if "%%i" == "KBUILD_PATH"         set _KBUILD_TMP=%_KBUILD_PATH%
+    if "%%i" == "KBUILD_BIN_PATH"     set _KBUILD_TMP=%_KBUILD_BIN_PATH%
+    if "%%i" == "KBUILD_TYPE"         set _KBUILD_TMP=%_KBUILD_TYPE%
+    if "%%i" == "KBUILD_HOST"         set _KBUILD_TMP=%_KBUILD_HOST%
+    if "%%i" == "KBUILD_HOST_ARCH"    set _KBUILD_TMP=%_KBUILD_HOST_ARCH%
+    if "%%i" == "KBUILD_HOST_CPU"     set _KBUILD_TMP=%_KBUILD_HOST_CPU%
+    if "%%i" == "KBUILD_TARGET"       set _KBUILD_TMP=%_KBUILD_TARGET%
+    if "%%i" == "KBUILD_TARGET_ARCH"  set _KBUILD_TMP=%_KBUILD_TARGET_ARCH%
+    if "%%i" == "KBUILD_TARGET_CPU"   set _KBUILD_TMP=%_KBUILD_TARGET_CPU%
+    if ".!_KBUILD_TMP!" == "."                      goto varible_not_found
+    if not ".%_KBUILD_OPT_VALUE_ONLY%" == ".1"      echo %_KBUILD_SHOW_VAR_PREFIX%%%i=!_KBUILD_TMP!
+    if ".%_KBUILD_OPT_VALUE_ONLY%" == ".1"          echo !_KBUILD_TMP!
+)
+
+endlocal
+goto end
+
+:no_delay_expansion
+echo error: Unable to enable delayed expansion in the shell.
+
+:4nt
+for %%i in ( %_KBUILD_OPT_VAR% ) do (
+    set _KBUILD_VAR=%%i
+    set _KBUILD_TMP=
+    if "%%i" == "KBUILD_PATH"         set _KBUILD_TMP=%_KBUILD_PATH%
+    if "%%i" == "KBUILD_BIN_PATH"     set _KBUILD_TMP=%_KBUILD_BIN_PATH%
+    if "%%i" == "KBUILD_TYPE"         set _KBUILD_TMP=%_KBUILD_TYPE%
+    if "%%i" == "KBUILD_HOST"         set _KBUILD_TMP=%_KBUILD_HOST%
+    if "%%i" == "KBUILD_HOST_ARCH"    set _KBUILD_TMP=%_KBUILD_HOST_ARCH%
+    if "%%i" == "KBUILD_HOST_CPU"     set _KBUILD_TMP=%_KBUILD_HOST_CPU%
+    if "%%i" == "KBUILD_TARGET"       set _KBUILD_TMP=%_KBUILD_TARGET%
+    if "%%i" == "KBUILD_TARGET_ARCH"  set _KBUILD_TMP=%_KBUILD_TARGET_ARCH%
+    if "%%i" == "KBUILD_TARGET_CPU"   set _KBUILD_TMP=%_KBUILD_TARGET_CPU%
+    if ".%_KBUILD_TMP%" == "."                      goto varible_not_found
+    if not ".%_KBUILD_OPT_VALUE_ONLY%" == ".1"      echo %_KBUILD_SHOW_VAR_PREFIX%%i=%_KBUILD_TMP%
+    if ".%_KBUILD_OPT_VALUE_ONLY%" == ".1"          echo %_KBUILD_TMP%
+)
+goto end
+
+:varible_not_found
+echo error: Unknown variable %_KBUILD_VAR% specified in --var request.
+goto failed
+
+:show_all_variables
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_PATH=%_KBUILD_PATH%
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_BIN_PATH=%_KBUILD_BIN_PATH%
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_TYPE=%_KBUILD_TYPE%
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_HOST=%_KBUILD_HOST%
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_HOST_ARCH=%_KBUILD_HOST_ARCH%
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_HOST_CPU=%_KBUILD_HOST_CPU%
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_TARGET=%_KBUILD_TARGET%
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH%
+echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_TARGET_CPU=%_KBUILD_TARGET_CPU%
+goto end
+
+REM
+REM Setup environment for the current shell or execute a command.
+REM
+REM Note: We use setlocal if we're going to execute a command as we
+REM       don't want the environment of the invoking shell to be changed.
+REM
+:exec_or_setup_env
+if not ".%1" == "." setlocal
+
+REM The PATH is always set.
+set PATH=%_KBUILD_NEW_PATH%
+
+REM Clear up anything that should be overridden.
+if not "%_KBUILD_OPT_OVERRIDE_ALL%" == "1" goto skip_override_all
+set KBUILD_TYPE=
+set KBUILD_HOST=
+set KBUILD_HOST_ARCH=
+set KBUILD_HOST_CPU=
+set KBUILD_TARGET=
+set KBUILD_TARGET_ARCH=
+set KBUILD_TARGET_CPU=
+set KBUILD_PATH=
+set KBUILD_BIN_PATH=
+if not "%_KBUILD_OPT_LEGACY%" == "1" goto skip_override_all
+set BUILD_TYPE=
+set BUILD_PLATFORM=
+set BUILD_PLATFORM_ARCH=
+set BUILD_PLATFORM_CPU=
+set BUILD_TARGET=
+set BUILD_TARGET_ARCH=
+set BUILD_TARGET_CPU=
+set PATH_KBUILD=
+set PATH_KBUILD_BIN=
+:skip_override_all
+
+REM Specific overrides, these implicitly deletes the legacy variable.
+if "%_KBUILD_OVERRIDE_TARGET%" == "1"       set KBUILD_TARGET=%_KBUILD_TARGET%
+if "%_KBUILD_OVERRIDE_TARGET%" == "1"       set BUILD_TARGET=
+if "%_KBUILD_OVERRIDE_TARGET_ARCH%" == "1"  set KBUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH%
+if "%_KBUILD_OVERRIDE_TARGET_ARCH%" == "1"  set BUILD_TARGET_ARCH=
+if "%_KBUILD_OVERRIDE_TYPE%" == "1"         set KBUILD_TYPE=%_KBUILD_TYPE%
+if "%_KBUILD_OVERRIDE_TYPE%" == "1"         set BUILD_TYPE=
+
+if not "%_KBUILD_OPT_FULL%" == "1"          goto env_setup_done
+set KBUILD_PATH=%_KBUILD_PATH%
+set KBUILD_BIN_PATH=%_KBUILD_BIN_PATH%
+set KBUILD_TYPE=%_KBUILD_TYPE%
+set KBUILD_HOST=%_KBUILD_HOST%
+set KBUILD_HOST_ARCH=%_KBUILD_HOST_ARCH%
+set KBUILD_HOST_CPU=%_KBUILD_HOST_CPU%
+set KBUILD_TARGET=%_KBUILD_TARGET%
+set KBUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH%
+set KBUILD_TARGET_CPU=%_KBUILD_TARGET_CPU%
+
+if not "%_KBUILD_OPT_LEGACY%" == "1"        goto env_setup_done
+set PATH_KBUILD=%_KBUILD_PATH%
+set PATH_KBUILD_BIN=%_KBUILD_BIN_PATH%
+set BUILD_TYPE=%_KBUILD_TYPE%
+set BUILD_PLATFORM=%_KBUILD_HOST%
+set BUILD_PLATFORM_ARCH=%_KBUILD_HOST_ARCH%
+set BUILD_PLATFORM_CPU=%_KBUILD_HOST_CPU%
+set BUILD_TARGET=%_KBUILD_TARGET%
+set BUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH%
+set BUILD_TARGET_CPU=%_KBUILD_TARGET_CPU%
+
+:env_setup_done
+if ".%1" == "." goto end
+
+REM Execute the specified command
+if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: Executing: %1 %2 %3 %4 %5 %6 %7 %8 %9
+set _KBUILD_CLEAN_GOTO=exec_command & goto cleanup
+:exec_command
+SET _KBUILD_CLEAN_GOTO=
+%1 %2 %3 %4 %5 %6 %7 %8 %9
+endlocal
+goto end_no_exit
+
+
+
+REM
+REM All exit paths leads to 'end' or 'failed' depending on
+REM which exit code is desire. This is required as we're manually
+REM performing environment cleanup (setlocal/endlocal is crap).
+REM
+:cleanup
+set _KBUILD_CURDIR=
+set _KBUILD_PATH=
+set _KBUILD_BIN_PATH=
+set _KBUILD_NEW_PATH=
+set _KBUILD_TYPE=
+set _KBUILD_TARGET=
+set _KBUILD_TARGET_ARCH=
+set _KBUILD_TARGET_CPU=
+set _KBUILD_HOST=
+set _KBUILD_HOST_ARCH=
+set _KBUILD_HOST_CPU=
+set _KBUILD_OPT_OVERRIDE_ALL=
+set _KBUILD_OVERRIDE_TYPE=
+set _KBUILD_OVERRIDE_TARGET=
+set _KBUILD_OVERRIDE_TARGET_ARCH=
+
+set _KBUILD_SELF=
+set _KBUILD_OPT_FULL=
+set _KBUILD_OPT_LEGACY=
+set _KBUILD_OPT_VAR=
+set _KBUILD_OPT_VALUE_ONLY=
+set _KBUILD_SHOW_VAR_PREFIX=
+set _KBUILD_OPT_DBG=
+set _KBUILD_OPT_OVERRIDE_ALL=
+
+set _KBUILD_TMP=
+set _KBUILD_VAR=
+set _KBUILD_VARS=
+goto %_KBUILD_CLEAN_GOTO%
+
+:failed
+set _KBUILD_CLEAN_GOTO=failed_done & goto cleanup
+:failed_done
+set _KBUILD_CLEAN_GOTO=
+exit /b 1
+
+:end
+set _KBUILD_CLEAN_GOTO=end_done & goto cleanup
+:end_done
+set _KBUILD_CLEAN_GOTO=
+exit /b 0
+
+:end_no_exit
+
Index: /tags/kBuild-0.1.4/kBuild/footer.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/footer.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/footer.kmk	(revision 1780)
@@ -0,0 +1,3569 @@
+# $Id$
+## @file
+# kBuild - File included at top of makefile.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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 source of the License, or
+# (at your option) any later version.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+ifndef __footer_kmk__
+# start-of-file-content
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_FOOTER_START := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_FOOTER_START), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_FOOTER_START), $(_KBUILD_TS_PREV)) - start of footer.kmk)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_FOOTER_START)
+endif
+
+#
+# Variables.
+# (Some of these need initialization before including definitions using them.)
+#
+
+# All targets of each types.
+_ALL_BLDPROGS    := $(BLDPROGS)    $(BLDPROGS.$(KBUILD_HOST))        $(BLDPROGS.$(KBUILD_HOST).$(KBUILD_HOST_ARCH))            $(BLDPROGS.$(KBUILD_HOST_ARCH))      $(BLDPROGS.$(KBUILD_HOST_CPU))       $(BLDPROGS.$(KBUILD_TYPE))
+_ALL_LIBRARIES   := $(LIBRARIES)   $(LIBRARIES.$(KBUILD_TARGET))     $(LIBRARIES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))       $(LIBRARIES.$(KBUILD_TARGET_ARCH))   $(LIBRARIES.$(KBUILD_TARGET_CPU))    $(LIBRARIES.$(KBUILD_TYPE))
+_ALL_IMPORT_LIBS := $(IMPORT_LIBS) $(IMPORT_LIBS.$(KBUILD_TARGET))   $(IMPORT_LIBS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))     $(IMPORT_LIBS.$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_CPU))  $(IMPORT_LIBS.$(KBUILD_TYPE))
+_ALL_DLLS        := $(DLLS)        $(DLLS.$(KBUILD_TARGET))          $(DLLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))            $(DLLS.$(KBUILD_TARGET_ARCH))        $(DLLS.$(KBUILD_TARGET_CPU))         $(DLLS.$(KBUILD_TYPE))
+_ALL_PROGRAMS    := $(PROGRAMS)    $(PROGRAMS.$(KBUILD_TARGET))      $(PROGRAMS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))        $(PROGRAMS.$(KBUILD_TARGET_ARCH))    $(PROGRAMS.$(KBUILD_TARGET_CPU))     $(PROGRAMS.$(KBUILD_TYPE))
+_ALL_SYSMODS     := $(SYSMODS)     $(SYSMODS.$(KBUILD_TARGET))       $(SYSMODS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))         $(SYSMODS.$(KBUILD_TARGET_ARCH))     $(SYSMODS.$(KBUILD_TARGET_CPU))      $(SYSMODS.$(KBUILD_TYPE))
+_ALL_OTHERS      := $(OTHERS)      $(OTHERS.$(KBUILD_TARGET))        $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))          $(OTHERS.$(KBUILD_TARGET_ARCH))      $(OTHERS.$(KBUILD_TARGET_CPU))       $(OTHERS.$(KBUILD_TYPE))
+_ALL_INSTALLS    := $(INSTALLS)    $(INSTALLS.$(KBUILD_TARGET))      $(INSTALLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))        $(INSTALLS.$(KBUILD_TARGET_ARCH))    $(INSTALLS.$(KBUILD_TARGET_CPU))     $(INSTALLS.$(KBUILD_TYPE))
+_ALL_FETCHES     := $(FETCHES)     $(FETCHES.$(KBUILD_TARGET))       $(FETCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))         $(FETCHES.$(KBUILD_TARGET_ARCH))     $(FETCHES.$(KBUILD_TARGET_CPU))      $(FETCHES.$(KBUILD_TYPE))
+_ALL_PATCHES     := $(PATCHES)     $(PATCHES.$(KBUILD_TARGET))       $(PATCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))         $(PATCHES.$(KBUILD_TARGET_ARCH))     $(PATCHES.$(KBUILD_TARGET_CPU))      $(PATCHES.$(KBUILD_TYPE))
+
+# all targets.
+_ALL_TARGETS = \
+	$(_ALL_FETCHES) \
+	$(_ALL_PATCHES) \
+	$(_ALL_BLDPROGS) \
+	$(_ALL_LIBRARIES) \
+	$(_ALL_IMPORT_LIBS) \
+	$(_ALL_DLLS) \
+	$(_ALL_PROGRAMS) \
+	$(_ALL_SYSMODS) \
+	$(_ALL_INSTALLS) \
+	$(_ALL_OTHERS)
+
+# all $(KBUILD_TARGET) targets.
+_ALL_TARGET_TARGETS = \
+	$(_ALL_FETCHES) \
+	$(_ALL_PATCHES) \
+	$(_ALL_LIBRARIES) \
+	$(_ALL_IMPORT_LIBS) \
+	$(_ALL_DLLS) \
+	$(_ALL_PROGRAMS) \
+	$(_ALL_SYSMODS) \
+	$(_ALL_INSTALLS) \
+	$(_ALL_OTHERS)
+
+# all $(KBUILD_HOST) targets.
+_ALL_HOST_TARGETS = \
+	$(_ALL_BLDPROGS)
+
+# all targets making use of srcname.
+_ALL_SRCNAME_TARGETS = \
+	$(_ALL_FETCHES) \
+	$(_ALL_PATCHES)
+
+# Dependency files. (currently not on target level, only this global stuff)
+_DEPFILES        := $(DEPFILES)    $(DEPFILES.$(KBUILD_TARGET))      $(DEPFILES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))        $(DEPFILES.$(KBUILD_TARGET_ARCH))    $(DEPFILES.$(KBUILD_TARGET_CPU))     $(DEPFILES.$(KBUILD_TYPE))
+
+# included dependency files.
+_DEPFILES_INCLUDED :=
+
+
+# All kind of output files except for _OBJS and _DEPFILES.
+# Compiling or linking definition outputting other things that $@ and any
+# required dependency file must add those output files to this variable.
+_OUT_FILES :=
+
+# Files which only requires cleaning up.
+_CLEAN_FILES :=
+
+# all of a type
+_OBJS     :=
+_FETCHES  :=
+_DOWNLOADS:=
+_UNPACKS  :=
+_PATCHES  :=
+_UNFETCHES:=
+_BLDPROGS :=
+_LIBS     :=
+_DLLS     :=
+_PROGRAMS :=
+_SYSMODS  :=
+_INSTALLS :=
+_INSTALLS_FILES :=
+_INSTALLS_DIRS :=
+_OTHERS   :=
+_PACKING  :=
+_DIRS     := $(PATH_TARGET)/ $(PATH_TARGET) $(BLDDIRS)
+_IMPORT_LIBS :=
+
+# misc
+pass_prev :=
+
+
+
+#
+# Footer macros
+#
+
+## Figure out the tool for a target.
+# @param    $1           normalized target.
+# @param    $2           tooltype.
+# @param    bld_trg      build target.
+# @param    bld_trg_arch build target architecture.
+_TARGET_TOOL = $(strip $(firstword \
+	$($(1)_$(2)TOOL.$(bld_trg).$(bld_trg_arch)) \
+	$($(1)_$(2)TOOL.$(bld_trg)) \
+	$($(1)_$(2)TOOL) \
+	$($(1)_TOOL.$(bld_trg).$(bld_trg_arch)) \
+	$($(1)_TOOL.$(bld_trg)) \
+	$($(1)_TOOL) \
+	$($(2)TOOL.$(bld_trg).$(bld_trg_arch)) \
+	$($(2)TOOL.$(bld_trg)) \
+	$($(2)TOOL) \
+	$(TOOL.$(bld_trg).$(bld_trg_arch)) \
+	$(TOOL.$(bld_trg)) \
+	$(TOOL) \
+	))
+
+## Figure out the actual name of an installed file.
+# @param	$1		The file to install.
+# @param	$2		The target name.
+# @param	$3		The _INST value (can be empty).
+# @param	$4		The default directory to use when $3 is empty.
+_INSTALL_FILE = $(patsubst %/,%/$(notdir $(1)),$(if $(3),$(PATH_INS)/$(3),$(4)/))
+
+
+
+## Inherit one keyword in a non-accumulative manner.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+define def_inherit_one_keyword
+ifdef $(trg)_$(prop).$(src_key)
+ ifndef $(trg)_$(prop).$(trg_key)
+  $(trg)_$(prop).$(trg_key) = $($(trg)_$(prop).$(src_key))
+ endif
+endif
+endef
+
+
+# EXPAND_BY = overriding
+
+## Inherit one keyword in a non-accumulative manner.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+define def_inherit_one_keyword_overriding_now_l
+ifdef $(trg)_$(prop).$(src_key)
+ ifndef $(trg)_$(prop).$(trg_key)
+  $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(src_key))
+ endif
+endif
+endef
+
+## @copydoc def_inherit_one_overriding_now_l
+define def_inherit_one_keyword_overriding_now_r
+ifdef $(trg)_$(prop).$(src_key)
+ ifndef $(trg)_$(prop).$(trg_key)
+  $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(src_key))
+ endif
+endif
+endef
+
+## Inherit one keyword in a non-accumulative manner, deferred expansion.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+# @remark This define relies on double evaluation
+define def_inherit_one_keyword_overriding_deferred
+ifdef $(trg)_$(prop).$(src_key)
+ ifndef $(trg)_$(prop).$(trg_key)
+  $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key))
+ endif
+endif
+endef
+
+## @copydoc def_inherit_one_overriding_deferred
+define def_inherit_one_keyword_overriding_deferred_l
+ifdef $(trg)_$(prop).$(src_key)
+ ifndef $(trg)_$(prop).$(trg_key)
+  $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key))
+ endif
+endif
+endef
+
+## @copydoc def_inherit_one_overriding_deferred
+define def_inherit_one_keyword_overriding_deferred_r
+ifdef $(trg)_$(prop).$(src_key)
+ ifndef $(trg)_$(prop).$(trg_key)
+  $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key))
+ endif
+endif
+endef
+
+
+# EXPAND_BY = prepending
+
+## Inherit one keyword in a prepending manner.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+define def_inherit_one_keyword_prepending_now_l
+ifdef $(trg)_$(prop).$(src_key)
+ $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(src_key)) $($(trg)_$(prop).$(trg_key))
+endif
+endef
+
+## @copydoc def_inherit_one_prepending_now_l
+define def_inherit_one_keyword_prepending_now_r
+ifdef $(trg)_$(prop).$(src_key)
+ $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(trg_key)) $($(trg)_$(prop).$(src_key))
+endif
+endef
+
+## Inherit one keyword in a non-accumulative manner, deferred expansion.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+# @remark This define relies on double evaluation
+define def_inherit_one_keyword_prepending_deferred
+ifdef $(trg)_$(prop).$(src_key)
+ ifndef $(trg)_$(prop).$(trg_key)
+  $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key))
+ endif
+endif
+endef
+
+## Inherit one keyword in a prepending manner, deferred expansion.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+define def_inherit_one_keyword_prepending_deferred_l
+ifdef $(trg)_$(prop).$(src_key)
+ $(trg)_$(prop).$(trg_key) <= $$($(trg)_$(prop).$(src_key))
+endif
+endef
+
+## @copydoc def_inherit_one_prepending_deferred_l
+define def_inherit_one_keyword_prepending_deferred_r
+ifdef $(trg)_$(prop).$(src_key)
+  $(trg)_$(prop).$(trg_key) += $$($(trg)_$(prop).$(src_key))
+endif
+endef
+
+
+# EXPAND_BY = appending
+
+## Inherit one keyword in an appending manner.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+define def_inherit_one_keyword_appending_now_l
+ifdef $(trg)_$(prop).$(src_key)
+ $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(trg_key)) $($(trg)_$(prop).$(src_key))
+endif
+endef
+
+## @copydoc def_inherit_one_appending_now_l
+define def_inherit_one_keyword_appending_now_r
+ifdef $(trg)_$(prop).$(src_key)
+ $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(src_key)) $($(trg)_$(prop).$(trg_key))
+endif
+endef
+
+## Inherit one keyword in a non-accumulative manner, deferred expansion.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+# @remark This define relies on double evaluation
+define def_inherit_one_keyword_appending_deferred
+ifdef $(trg)_$(prop).$(src_key)
+ ifndef $(trg)_$(prop).$(trg_key)
+  $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key))
+ endif
+endif
+endef
+
+## Inherit one keyword in an appending manner, deferred expansion.
+# @param    $(trg)          Target object.
+# @param    $(prop)     	The property.
+# @param    $(src_key)      Source keyword.
+# @param    $(trg_key)      Target keyword.
+define def_inherit_one_keyword_appending_deferred_l
+ifdef $(trg)_$(prop).$(src_key)
+ $(trg)_$(prop).$(trg_key) += $$($(trg)_$(prop).$(src_key))
+endif
+endef
+
+## @copydoc def_inherit_one_appending_deferred_l
+define def_inherit_one_keyword_appending_deferred_r
+ifdef $(trg)_$(prop).$(src_key)
+  $(trg)_$(prop).$(trg_key) <= $$($(trg)_$(prop).$(src_key))
+endif
+endef
+
+
+## Worker fro def_inherit that deals with one keyword that makes
+# use of inheritance.
+# @param    prefix_keyword        key_prefix:keyword. The cool join/split game as usual.
+# @param    trg                   Object to consider for inheriting.
+# @param    properties            List of the properties with straight expansion.
+# @param    properties_now_l      List of the properties with immediate expansion, accumulating on the left side.
+# @param    properties_now_r      List of the properties with immediate expansion, accumulating on the right side.
+# @param    properties_deferred   List of the properties with deferred expansion (e.g. function), non-accumulative .
+# @param    properties_deferred_l List of the properties with deferred expansion (e.g. function), accumulating on the left side.
+# @param    properties_deferred_r List of the properties with deferred expansion (e.g. function), accumulating on the right side.
+define def_inherit_keyword
+local prefix   := $(word 1,$(subst :, ,$(prefix_keyword)))
+local trg_key  := $(word 2,$(subst :, ,$(prefix_keyword)))
+local src_key  := $($(prefix)_$(trg_key)_EXTENDS)
+local by       := $($(prefix)_$(trg_key)_EXTENDS_BY)
+
+# Inherit the properties.
+$(foreach prop, $(properties),            $(eval $(def_inherit_one_keyword)))
+$(foreach prop, $(properties_now_l),      $(eval $(def_inherit_one_keyword_$(by)_now_l)))
+$(foreach prop, $(properties_now_r),      $(eval $(def_inherit_one_keyword_$(by)_now_r)))
+$(foreach prop, $(properties_deferred),   $(eval $(def_inherit_one_keyword_$(by)_deferred)))
+$(foreach prop, $(properties_deferred_l), $(eval $(def_inherit_one_keyword_$(by)_deferred_l)))
+$(foreach prop, $(properties_deferred_r), $(eval $(def_inherit_one_keyword_$(by)_deferred_r)))
+
+endef # def_inherit_keyword
+
+
+## Inherit one template property in a non-accumulative manner.
+# @param    $(prop)         Property name
+# @param    $(src)          Source (parent) object.
+# @param    $(trg)          Target (child) object.
+define def_inherit_one
+ifdef $(src)_$(prop)
+ ifndef $(trg)_$(prop)
+  $(trg)_$(prop) = $($(src)_$(prop))
+ endif
+endif
+endef
+
+
+# EXPAND_BY = overriding
+
+## Inherit one template property in a non-accumulative manner.
+# @param    $(prop)         Property name
+# @param    $(src)          Source (parent) object.
+# @param    $(trg)          Target (child) object.
+define def_inherit_one_overriding_now_l
+ifdef $(src)_$(prop)
+ ifndef $(trg)_$(prop)
+  $(trg)_$(prop) := $($(src)_$(prop))
+ endif
+endif
+endef
+
+## @copydoc def_inherit_one_overriding_now_l
+define def_inherit_one_overriding_now_r
+ifdef $(src)_$(prop)
+ ifndef $(trg)_$(prop)
+  $(trg)_$(prop) := $($(src)_$(prop))
+ endif
+endif
+endef
+
+## Inherit one template property in a non-accumulative manner, deferred expansion.
+# @param    $(prop)         Property name
+# @param    $(src)          Source
+# @param    $(trg)          Target
+# @remark This define relies on double evaluation
+define def_inherit_one_overriding_deferred
+ifdef $(src)_$(prop)
+ ifndef $(trg)_$(prop)
+  $(trg)_$(prop) = $$($(src)_$(prop))
+ endif
+endif
+endef
+
+## @copydoc def_inherit_one_overriding_deferred
+define def_inherit_one_overriding_deferred_l
+ifdef $(src)_$(prop)
+ ifndef $(trg)_$(prop)
+  $(trg)_$(prop) = $$($(src)_$(prop))
+ endif
+endif
+endef
+
+## @copydoc def_inherit_one_overriding_deferred
+define def_inherit_one_overriding_deferred_r
+ifdef $(src)_$(prop)
+ ifndef $(trg)_$(prop)
+  $(trg)_$(prop) = $$($(src)_$(prop))
+ endif
+endif
+endef
+
+
+# EXPAND_BY = prepending
+
+## Inherit one template property in a prepending manner.
+# @param    $(prop)         Property name
+# @param    $(src)          Source (parent) object.
+# @param    $(trg)          Target (child) object.
+define def_inherit_one_prepending_now_l
+ifdef $(src)_$(prop)
+ $(trg)_$(prop) := $($(src)_$(prop)) $($(trg)_$(prop))
+endif
+endef
+
+## @copydoc def_inherit_one_prepending_now_l
+define def_inherit_one_prepending_now_r
+ifdef $(src)_$(prop)
+ $(trg)_$(prop) := $($(trg)_$(prop)) $($(src)_$(prop))
+endif
+endef
+
+## Inherit one template property in a non-accumulative manner, deferred expansion.
+# @param    $(prop)         Property name
+# @param    $(src)          Source
+# @param    $(trg)          Target
+# @remark This define relies on double evaluation
+define def_inherit_one_prepending_deferred
+ifdef $(src)_$(prop)
+ ifndef $(trg)_$(prop)
+  $(trg)_$(prop) = $$($(src)_$(prop))
+ endif
+endif
+endef
+
+## Inherit one template property in a prepending manner, deferred expansion.
+# @param    $(prop)         Property name
+# @param    $(src)          Source (parent) object.
+# @param    $(trg)          Target (child) object.
+define def_inherit_one_prepending_deferred_l
+ifdef $(src)_$(prop)
+ $(trg)_$(prop) <= $$($(src)_$(prop))
+endif
+endef
+
+## @copydoc def_inherit_one_prepending_deferred_l
+define def_inherit_one_prepending_deferred_r
+ifdef $(src)_$(prop)
+  $(trg)_$(prop) += $$($(src)_$(prop))
+endif
+endef
+
+
+# EXPAND_BY = appending
+
+## Inherit one template property in an appending manner.
+# @param    $(prop)         Property name
+# @param    $(src)          Source (parent) object.
+# @param    $(trg)          Target (child) object.
+define def_inherit_one_appending_now_l
+ifdef $(src)_$(prop)
+ $(trg)_$(prop) := $($(trg)_$(prop)) $($(src)_$(prop))
+endif
+endef
+
+## @copydoc def_inherit_one_appending_now_l
+define def_inherit_one_appending_now_r
+ifdef $(src)_$(prop)
+ $(trg)_$(prop) := $($(src)_$(prop)) $($(trg)_$(prop))
+endif
+endef
+
+## Inherit one template property in a non-accumulative manner, deferred expansion.
+# @param    $(prop)         Property name
+# @param    $(src)          Source
+# @param    $(trg)          Target
+# @remark This define relies on double evaluation
+define def_inherit_one_appending_deferred
+ifdef $(src)_$(prop)
+ ifndef $(trg)_$(prop)
+  $(trg)_$(prop) = $$($(src)_$(prop))
+ endif
+endif
+endef
+
+## Inherit one template property in an appending manner, deferred expansion.
+# @param    $(prop)         Property name
+# @param    $(src)          Source (parent) object.
+# @param    $(trg)          Target (child) object.
+define def_inherit_one_appending_deferred_l
+ifdef $(src)_$(prop)
+ $(trg)_$(prop) += $$($(src)_$(prop))
+endif
+endef
+
+## @copydoc def_inherit_one_appending_deferred_l
+define def_inherit_one_appending_deferred_r
+ifdef $(src)_$(prop)
+  $(trg)_$(prop) <= $$($(src)_$(prop))
+endif
+endef
+
+
+## combines the specified properties $(1) with the $(_KEYWORDS) list.
+_INHERIT_JOIN_KEYWORDS = $(1)  $(foreach keyword,$(_KEYWORDS), $(addsuffix .$(keyword), $(1)))
+
+
+## Generic inheritance for use with targets templates and tools.
+# @param    trg                   Object to consider for inheriting.
+# @param    src_prefix            What to prefix the value found in EXTENDS with to get the object.
+# @param    load_function         Load function for stuff that needs
+# @param    properties            List of the properties with straight expansion.
+# @param    properties_now_l      List of the properties with immediate expansion, accumulating on the left side.
+# @param    properties_now_r      List of the properties with immediate expansion, accumulating on the right side.
+# @param    properties_deferred   List of the properties with deferred expansion (e.g. function), non-accumulative .
+# @param    properties_deferred_l List of the properties with deferred expansion (e.g. function), accumulating on the left side.
+# @param    properties_deferred_r List of the properties with deferred expansion (e.g. function), accumulating on the right side.
+define def_inherit
+
+# Load it - loading is a mess, fix.
+ifneq ($(load_function),)
+ local loading := $(patsubst $(src_prefix)%,%,$(trg))
+ $(evalvalctx $(load_function))
+endif
+
+local src := $(strip $($(trg)_EXTENDS))
+ifneq ($(src),)
+ ifndef $(trg)_EXTENDS_STATUS_
+  $(trg)_EXTENDS_STATUS_ := 0
+
+  # Load the source.
+  ifneq ($(load_function),)
+   local loading := $(src)
+   $(evalvalctx $(load_function))
+  endif
+
+  # less typing.
+  local src := $(src_prefix)$(src)
+
+  # Recursivly process the parent (src) if it's inherting from somebody too.
+  ifdef $(src)_EXTENDS
+   ifneq ($($(src)_EXTENDS_STATUS_),42)
+    # 'foreach' will create 'trg' in a new variable context hiding
+    # out current variable. 'src' OTOH will be overwritten.
+    $(foreach trg, $(src), $(evalval def_inherit))
+    local src := $(src_prefix)$(strip $($(trg)_EXTENDS))
+   endif
+  endif
+
+  # Get & check EXTENDS_BY.
+  local by = $(strip $($(trg)_EXTENDS_BY))
+  ifeq ($(by),)
+   local by = overriding
+  else ifn1of ($(by), overriding appending prepending)
+   $(error kBuild: Invalid EXTENDS_BY value '$(by)' on '$(trg)'!)
+  endif
+
+  # Inherit the properties.
+  $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties)),            $(eval $(def_inherit_one)))
+  $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_now_l)),      $(eval $(def_inherit_one_$(by)_now_l)))
+  $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_now_r)),      $(eval $(def_inherit_one_$(by)_now_r)))
+  $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_deferred)),   $(eval $(def_inherit_one_$(by)_deferred)))
+  $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_deferred_l)), $(eval $(def_inherit_one_$(by)_deferred_l)))
+  $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_deferred_r)), $(eval $(def_inherit_one_$(by)_deferred_r)))
+
+  # Mark the target as done.
+  $(trg)_EXTENDS_STATUS_ := 42
+ else
+  # Check for inheritance loops.
+  ifneq ($($(trg)_EXTENDS_STATUS_),42)
+   $(error kBuild: Target inheritance loop! target=$(trg) $(trg)_EXTENDS_STATUS_=$($(trg)_EXTENDS_STATUS_))
+  endif
+ endif
+endif
+
+# Keyword inheritance.
+$(foreach prefix_keyword, $(join $(_KEYWORDS_PREFIX), $(addprefix :,$(_KEYWORDS_EXTENDS))), $(evalval def_inherit_keyword))
+
+endef # def_inherit
+
+
+#
+# Load global units before doing any inheriting so they can add new properties.
+#
+# This only applies to the guys listed in the global USES since there is
+# no reliable way to deal with things on a target level without first
+# applying templates. So, to avoid having USES mess up all targets,
+# we'll make the global and per-target USES property work differently:
+#     The global USES does not apply to targets, just globally.
+#
+
+## Unit load function.
+# @param loading    The unit name
+define def_unit_load_function
+ifndef UNIT_$(loading)
+ UNIT_$(loading)_KMK_FILE := $(firstword $(foreach path, $(KBUILD_UNIT_PATHS) $(KBUILD_PATH)/units $(KBUILD_DEFAULT_PATHS), $(wildcard $(path)/$(loading).kmk)))
+ ifeq ($(UNIT_$(loading)_KMK_FILE),)
+  $(error kBuild: Cannot find include file for the unit '$(loading)'! Searched: $(KBUILD_UNIT_PATHS) $(KBUILD_PATH)/units $(KBUILD_DEFAULT_PATHS))
+ endif
+ include $(UNIT_$(loading)_KMK_FILE)
+ ifndef UNIT_$(loading)
+  $(warning kBuild: UNIT_$(loading) was not defined by $(UNIT_$(loading)_KMK_FILE)!)
+ endif
+endif
+endef # def_unit_load_function
+
+$(foreach loading, \
+	$(USES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \
+	$(USES.$(KBUILD_TARGET_CPU)) \
+	$(USES.$(KBUILD_TARGET_ARCH)) \
+	$(USES.$(KBUILD_TARGET)) \
+	$(USES.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) \
+	$(USES.$(KBUILD_HOST_CPU)) \
+	$(USES.$(KBUILD_HOST_ARCH)) \
+	$(USES.$(KBUILD_TARGET)) \
+	$(USES.$(KBUILD_TYPE)) \
+	$(USES),$(evalval def_unit_load_function))
+
+
+#
+# Determin all the templates that is being used and make
+# sure they are present before we try collect keywords.
+#
+_TEMPLATES := $(TEMPLATE)
+define def_templates
+ifdef $(target)_TEMPLATE
+ ifneq ("$($(target)_TEMPLATE)","$(strip $($(target)_TEMPLATE))")
+  $$(error kBuild: The template name of target '$(target)' contains tabs ($($(target)_TEMPLATE))). Please remove them)
+ endif
+ _TEMPLATES += $($(target)_TEMPLATE)
+endif
+endef # def_templates
+$(foreach target, $(_ALL_TARGETS), $(eval $(def_templates)))
+_TEMPLATES := $(sort $(_TEMPLATES))
+
+## Template load function.
+# @param loading    The template name. This is prefixed.
+define def_templates_load_function
+ifndef TEMPLATE_$(loading)
+ TEMPLATE_$(loading)_KMK_FILE := $(firstword $(foreach path, $(KBUILD_TEMPLATE_PATHS) $(KBUILD_PATH)/templates $(KBUILD_DEFAULT_PATHS), $(wildcard $(path)/$(loading).kmk)))
+ ifeq ($(TEMPLATE_$(loading)_KMK_FILE),)
+  $(error kBuild: Cannot find include file for the template '$(loading)'! Searched: $(KBUILD_TEMPLATE_PATHS) $(KBUILD_PATH)/templates $(KBUILD_DEFAULT_PATHS))
+ endif
+ include $(TEMPLATE_$(loading)_KMK_FILE)
+ ifndef TEMPLATE_$(loading)
+  $(warning kBuild: TEMPLATE_$(loading) was not defined by $(TEMPLATE_$(loading)_KMK_FILE)!)
+ endif
+endif
+endef # def_templates_load_function
+$(foreach loading, $(_TEMPLATES), $(evalval def_templates_load_function))
+
+
+#
+# Determin the keywords required for correct inherting and setup keyword inheritance.
+#
+# This means walking all the lists of immediate template and targets and
+# pick up all the BLD_T* keywords. Since templates that are referenced
+# indirectly in the inheritance hierarchy, the result from this exercise
+# might not be 100% accurate... :-/
+#
+_BLD_TYPES   := $(KBUILD_TYPE)
+_BLD_TARGETS := $(KBUILD_TARGET) $(KBUILD_HOSTS)
+_BLD_ARCHES  := $(KBUILD_TARGET_ARCH) $(KBUILD_HOST_ARCH)
+_BLD_CPUS    := $(KBUILD_TARGET_CPU) $(KBUILD_HOST_CPU)
+
+define def_collect_bld_xyz
+ifdef $(src)_BLD_TYPE
+ ifn1of ($($(src)_BLD_TYPE), $(KBUILD_BLD_TYPES))
+  $(error kBuild: $(src)_BLD_TYPE=$($(src)_BLD_TYPE) not in KBUILD_BLD_TYPES={$(KBUILD_BLD_TYPES)}!)
+ endif
+ _BLD_TYPES += $($(src)_BLD_TYPE)
+endif
+ifdef $(src)_BLD_TRG
+ ifn1of ($($(src)_BLD_TRG), $(KBUILD_OSES))
+  $(error kBuild: $(src)_BLD_TRG=$($(src)_BLD_TRG) not in KBUILD_OSES={$(KBUILD_OSES)}!)
+ endif
+ _BLD_TARGETS += $($(src)_BLD_TRG)
+endif
+ifdef $(src)_BLD_TRG_ARCH
+ ifn1of ($($(src)_BLD_TRG_ARCH), $(KBUILD_ARCHES))
+  $(error kBuild: $(src)_BLD_TRG_ARCH=$($(src)_BLD_TRG_ARCH) not in KBUILD_ARCHES={$(KBUILD_ARCHES)}!)
+ endif
+ _BLD_ARCHES += $($(src)_BLD_TRG_ARCH)
+endif
+ifdef $(src)_BLD_TRG_CPU
+ if1of ($($(src)_BLD_CPU), $(KBUILD_ARCHES) $(KBUILD_OSES) $(KBUILD_BLD_TYPES))
+  $(error kBuild: $(src)_BLD_TRG_CPU=$($(src)_BLD_TRG_CPU) found in KBUILD_ARCHES, KBUILD_OSES or KBUILD_BLD_TYPES!)
+ endif
+ _BLD_CPUS += $($(src)_BLD_TRG_CPU)
+endif
+endef # def_collect_bld_xyz
+$(foreach src, $(addprefix TEMPLATE_, $(_TEMPLATES)) $(_ALL_TARGETS) \
+	,$(evalval def_collect_bld_xyz))
+
+# Drop duplicate values.
+# WARNING! These list might not include keywords only involved in inheritance.
+_BLD_TYPES   := $(sort $(_BLD_TYPES))
+_BLD_TARGETS := $(sort $(_BLD_TARGETS))
+_BLD_ARCHES  := $(sort $(_BLD_ARCHES))
+_BLD_CPUS    := $(sort $(_BLD_CPUS))
+
+## Look for keywords which extends others and order them.
+# @param    keyword
+# @param    prefix
+# @param    valid
+define def_keyword_ordering
+# Check for EXTENDS, fix and validate it if found.
+local src := $(strip $($(prefix)_$(keyword)_EXTENDS))
+ifneq ($(src),)
+ ifndef $(prefix)_$(keyword)_EXTENDS_STATUS_
+  ifn1of ($(src), $(valid))
+   $(error kBuild: $(keyword) tries to extend unknown keyword '$(src)'! (known = $(valid)))
+  endif
+
+  # Recursivly process the parent (src).
+  ifneq ($($(prefix)_$(src)_EXTENDS_STATUS_),42)
+   $(prefix)_$(keyword)_EXTENDS_STATUS_ := 0
+   # 'foreach' will create 'keyword' in a new variable context hiding
+   # out current variable. 'src' OTOH will be overwritten.
+   $(foreach keyword, $(src), $(evalval def_keyword_ordering))
+   local src := $(strip $($(prefix)_$(keyword)_EXTENDS))
+  endif
+
+  # Check and strip EXTENDS_BY.
+  local by = $(strip $($(prefix)_$(keyword)_EXTENDS_BY))
+  ifeq ($(by),)
+   local by = overriding
+  else ifn1of ($(by), overriding appending prepending)
+   $(error kBuild: Invalid EXTENDS_BY value '$(by)' on '$(keyword)'!)
+  endif
+
+  # Update the attributes with stripped
+  $(prefix)_$(keyword)_EXTENDS_BY := $(by)
+  $(prefix)_$(keyword)_EXTENDS := $(src)
+
+  # Add it to the list and mark it as done.
+  _KEYWORDS_EXTENDS += $(keyword)
+  _KEYWORDS_PREFIX  += $(prefix)
+  $(prefix)_$(keyword)_EXTENDS_STATUS_ := 42
+ else
+  # Check for inheritance loops.
+  ifneq ($($(trg)_EXTENDS_STATUS_),42)
+   $(error kBuild: Keyword inheritance loop! keyword=$(keyword) $(prefix)_$(keyword)_EXTENDS_STATUS_=$($(prefix)_$(keyword)_EXTENDS_STATUS_))
+  endif
+ endif
+else
+ # Add it to the ordered list and mark it as done.
+ _KEYWORDS_ORDERED += $(keyword)
+ $(prefix)_$(src)_EXTENDS_STATUS_ := 42
+endif
+endef # def_keyword_ordering
+
+# Look for keywords which extends others and their parents, and from this
+# construct two lists.
+_KEYWORDS_ORDERED :=
+_KEYWORDS_EXTENDS :=
+_KEYWORDS_PREFIX  :=
+
+prefix := BLD_TYPE
+valid := $(KBUILD_BLD_TYPES)
+$(foreach keyword, $(_BLD_TYPES)  , $(evalval def_keyword_ordering))
+
+prefix := BLD_TRG
+valid := $(KBUILD_OSES)
+$(foreach keyword, $(_BLD_TARGETS), $(evalval def_keyword_ordering))
+
+prefix := BLD_ARCH
+valid := $(KBUILD_ARCHES)
+$(foreach keyword, $(_BLD_ARCHES) , $(evalval def_keyword_ordering))
+
+prefix := BLD_CPU
+valid := $(KBUILD_CPUS)
+$(foreach keyword, $(_BLD_CPUS)   , $(evalval def_keyword_ordering))
+
+## @todo Inherit bld_trg.bld_arch for too?
+
+# Construct all the possible keywords.
+_KEYWORDS := $(_KEYWORDS_ORDERED) $(_KEYWORDS_EXTENDS) \
+	$(foreach bld_trg,$(_BLD_TARGETS),$(addprefix $(bld_trg).,$(_BLD_ARCHES)))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done keywords)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# Target inheritance.
+#
+# This has to be done on a per target list basis as to avoid adding
+# incorrect properties that will wast memory, time, and may confuse
+# later strictness checks. This also has to be done *before* templates
+# are applied to the targets. Since we're doing that part rather
+# early on, the target inheritance feature is a bit restricted at
+# the moment. However, this will be addressed in a little(?) while.
+#
+
+src_prefix :=
+load_function :=
+properties_deferred_l :=
+properties_deferred_r :=
+
+# Fetches.
+properties          := $(PROPS_FETCHES_SINGLE)
+properties_now_l    := $(PROPS_FETCHES_ACCUMULATE_L)
+properties_now_r    := $(PROPS_FETCHES_ACCUMULATE_R)
+properties_deferred := $(PROPS_FETCHES_DEFERRED)
+$(foreach trg, $(_ALL_FETCHES),$(evalval def_inherit))
+
+## Patches. - not implemented yet.
+#properties          := $(PROPS_PATCHES_SINGLE)
+#properties_now_l    := $(PROPS_PATCHES_ACCUMULATE_L)
+#properties_now_r    := $(PROPS_PATCHES_ACCUMULATE_R)
+#properties_deferred := $(PROPS_PATCHES_DEFERRED)
+#$(foreach trg, $(_ALL_PATCHES),$(evalval def_inherit))
+
+# Programs and build programs.
+properties          := $(PROPS_PROGRAMS_SINGLE)
+properties_now_l    := $(PROPS_PROGRAMS_ACCUMULATE_L)
+properties_now_r    := $(PROPS_PROGRAMS_ACCUMULATE_R)
+properties_deferred := $(PROPS_PROGRAMS_DEFERRED)
+$(foreach trg, $(_ALL_BLDPROGS) $(_ALL_PROGRAMS),$(evalval def_inherit))
+
+# Libraries and import libraries.
+properties          := $(PROPS_LIBRARIES_SINGLE)
+properties_now_l    := $(PROPS_LIBRARIES_ACCUMULATE_L)
+properties_now_r    := $(PROPS_LIBRARIES_ACCUMULATE_R)
+properties_deferred := $(PROPS_LIBRARIES_DEFERRED)
+if1of ($(KBUILD_TARGET), nt os2 win)
+ $(foreach trg, $(_ALL_LIBRARIES) $(_ALL_IMPORT_LIBS),$(evalval def_inherit))
+else
+ $(foreach trg, $(_ALL_LIBRARIES),$(evalval def_inherit))
+endif
+
+# DLLs.
+properties          := $(PROPS_DLLS_SINGLE)
+properties_now_l    := $(PROPS_DLLS_ACCUMULATE_L)
+properties_now_r    := $(PROPS_DLLS_ACCUMULATE_R)
+properties_deferred := $(PROPS_DLLS_DEFERRED)
+if1of ($(KBUILD_TARGET), nt os2 win)
+ $(foreach trg, $(_ALL_DLLS),$(evalval def_inherit))
+else
+ $(foreach trg, $(_ALL_DLLS) $(_ALL_IMPORT_LIBS),$(evalval def_inherit))
+endif
+
+# System modules.
+properties          := $(PROPS_SYSMODS_SINGLE)
+properties_now_l    := $(PROPS_SYSMODS_ACCUMULATE_L)
+properties_now_r    := $(PROPS_SYSMODS_ACCUMULATE_R)
+properties_deferred := $(PROPS_SYSMODS_DEFERRED)
+$(foreach trg, $(_ALL_SYSMODS),$(evalval def_inherit))
+
+# Installs.
+properties          := $(PROPS_INSTALLS_SINGLE)
+properties_now_l    := $(PROPS_INSTALLS_ACCUMULATE_L)
+properties_now_r    := $(PROPS_INSTALLS_ACCUMULATE_R)
+properties_deferred := $(PROPS_INSTALLS_DEFERRED)
+$(foreach trg, $(_ALL_INSTALLS),$(evalval def_inherit))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done target inheritance)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# Template Inheritance.
+#
+# This is much the same as with target inheritance, except we cannot
+# restrict the properties involved since we haven't got a clue which
+# target platforms/archs are using them. But, we can drop the instance
+# expansion we're doing for targets since there won't be any more
+# changes to either the source nor the target templates beyond this
+# exercise.
+#
+
+src_prefix := TEMPLATE_
+load_function := def_templates_load_function
+properties :=
+properties_now_l :=
+properties_now_r :=
+properties_deferred   := $(PROPS_SINGLE) $(PROPS_DEFERRED)
+properties_deferred_l := $(PROPS_ACCUMULATE_L)
+properties_deferred_r := $(PROPS_ACCUMULATE_R)
+$(foreach trg, $(addprefix TEMPLATE_,$(_TEMPLATES)),$(evalval def_inherit))
+
+# done inheriting.
+src_prefix :=
+load_function :=
+properties :=
+properties_now_l :=
+properties_now_r :=
+properties_deferred :=
+properties_deferred_l :=
+properties_deferred_r :=
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done template inheritance)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+
+
+#
+# Template/Target Expansion.
+#
+# Extend all targets with the values from the template. Doing this up front
+# allows more generic code and less mess down in the pass 2 target handling.
+# However it does eat a good deal of memory.
+#
+
+## Inherit one template property in a non-accumulative manner.
+# @param    $(prop)     Property name
+# @param    $(target)	Target name
+# @todo fix the precedence order for some properties.
+define def_inherit_template_one
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
+ifndef $(target)_$(prop)
+$(target)_$(prop) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
+endif
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
+ifndef $(target)_$(prop).$(bld_trg)
+$(target)_$(prop).$(bld_trg) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
+endif
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
+ifndef $(target)_$(prop).$(bld_trg).$(bld_trg_arch)
+$(target)_$(prop).$(bld_trg).$(bld_trg_arch) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
+endif
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
+ifndef $(target)_$(prop).$(bld_trg_arch)
+$(target)_$(prop).$(bld_trg_arch) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
+endif
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
+ifndef $(target)_$(prop).$(bld_trg_cpu)
+$(target)_$(prop).$(bld_trg_cpu) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
+endif
+endif
+endef
+
+## Inherit one template property in a non-accumulative manner, deferred expansion.
+# @param    1: $(prop)     Property name
+# @param    2: $(target)	Target name
+# @todo fix the precedence order for some properties.
+# @remark this define relies on double evaluation
+define def_inherit_template_one_deferred
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
+ifndef $(target)_$(prop)
+$(target)_$(prop) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
+endif
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
+ifndef $(target)_$(prop).$(bld_trg)
+$(target)_$(prop).$(bld_trg) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
+endif
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
+ifndef $(target)_$(prop).$(bld_trg).$(bld_trg_arch)
+$(target)_$(prop).$(bld_trg).$(bld_trg_arch) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
+endif
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
+ifndef $(target)_$(prop).$(bld_trg_arch)
+$(target)_$(prop).$(bld_trg_arch) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
+endif
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
+ifndef $(target)_$(prop).$(bld_trg_cpu)
+$(target)_$(prop).$(bld_trg_cpu) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
+endif
+endif
+endef
+
+## Inherit one acculumlative template property where the 'most significant' items are at the left end.
+# @param    $(prop)     Property name
+# @param    $(target)	Target name
+define def_inherit_template_one_accumulate_l
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
+$(target)_$(prop) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE)
+$(target)_$(prop).$(KBUILD_TYPE) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
+$(target)_$(prop).$(bld_trg) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
+$(target)_$(prop).$(bld_trg).$(bld_trg_arch) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
+$(target)_$(prop).$(bld_trg_cpu) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
+$(target)_$(prop).$(bld_trg_arch) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
+endif
+endef
+
+## Inherit one acculumlative template property where the 'most significant' items are at the right end.
+# @param    $(prop)     Property name
+# @param    $(target)	Target name
+define def_inherit_template_one_accumulate_r
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
+$(target)_$(prop) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE)
+$(target)_$(prop).$(KBUILD_TYPE) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
+$(target)_$(prop).$(bld_trg) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
+$(target)_$(prop).$(bld_trg).$(bld_trg_arch) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
+$(target)_$(prop).$(bld_trg_cpu) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
+endif
+ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
+$(target)_$(prop).$(bld_trg_arch) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
+endif
+endef
+
+
+## Inherit template properties for on target.
+# @param    $(target)    Target name.
+define def_inherit_template
+# sanity check.
+ifdef _$(target)_ALREADY_PROCESSED
+ $(error kBuild: The target $(target) appears more than once in the target lists! Please correct the makefile(s))
+endif
+_$(target)_ALREADY_PROCESSED := 1
+
+# Inherit any default template.
+ifdef TEMPLATE
+ifeq ($($(target)_TEMPLATE),)
+$(eval $(target)_TEMPLATE:=$(TEMPLATE))
+endif
+endif
+# Expand the template if specified.
+ifneq ($($(target)_TEMPLATE),)
+$(foreach prop,$(PROPS_SINGLE),$(evalval def_inherit_template_one))
+$(foreach prop,$(PROPS_DEFERRED),$(eval $(def_inherit_template_one_deferred))) # exploits the 2 evaluation, so no value!
+$(foreach prop,$(PROPS_ACCUMULATE_L),$(eval $(def_inherit_template_one_accumulate_l))) # += works fine without value
+$(foreach prop,$(PROPS_ACCUMULATE_R),$(eval $(def_inherit_template_one_accumulate_r))) # use <= (kmk addition)
+endif
+endef
+
+# Inherit template properties
+bld_trg := $(KBUILD_TARGET)
+bld_trg_arch := $(KBUILD_TARGET_ARCH)
+bld_trg_cpu := $(KBUILD_TARGET_CPU)
+$(foreach target, $(_ALL_TARGET_TARGETS),$(evalval def_inherit_template))
+
+bld_trg := $(KBUILD_HOST)
+bld_trg_arch := $(KBUILD_HOST_ARCH)
+bld_trg_cpu := $(KBUILD_HOST_CPU)
+$(foreach target, $(_ALL_HOST_TARGETS),$(evalval def_inherit_template))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done template/target expansion)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# Include tools, sdks and units.
+#
+# The first part of this exercise is to figure out which TOOLS and SDKS
+# that should be included.
+#
+_TOOLS := $(TOOL.$(KBUILD_TARGET))   $(TOOL.$(KBUILD_TARGET_ARCH))   $(TOOL.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \
+          $(TOOL.$(KBUILD_HOST)) $(TOOL.$(KBUILD_HOST_ARCH)) $(TOOL.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) \
+	  $(TOOL)
+_SDKS  := $(SDKS.$(KBUILD_TARGET))   $(SDKS.$(KBUILD_TARGET_ARCH))   $(SDKS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \
+          $(SDKS.$(KBUILD_HOST)) $(SDKS.$(KBUILD_HOST_ARCH)) $(SDKS.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) \
+	  $(SDKS.$(KBUILD_TYPE)) \
+	  $(SDKS)
+_USES  := $(USES.$(KBUILD_TARGET))   $(USES.$(KBUILD_TARGET_ARCH))   $(USES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \
+          $(USES.$(KBUILD_HOST)) $(USES.$(KBUILD_HOST_ARCH)) $(USES.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) \
+	  $(USES.$(KBUILD_TYPE)) \
+	  $(USES)
+define def_tools_sdks_target_source
+$(eval _TOOLS += $(foreach prop, $(PROPS_TOOLS), \
+	$($(source)_$(prop).$(_bld_trg)) \
+	$($(target)_$(source)_$(prop).$(_bld_trg)) \
+	$($(source)_$(prop).$(_bld_trg).$(_bld_trg_arch)) \
+	$($(target)_$(source)_$(prop).$(_bld_trg).$(_bld_trg_arch)) \
+	$($(source)_$(prop).$(_bld_trg_arch)) \
+	$($(target)_$(source)_$(prop).$(_bld_trg_arch)) \
+	$($(source)_$(prop)) \
+	$($(target)_$(source)_$(prop))))
+$(eval _SDKS += \
+	$($(source)_SDKS.$(_bld_trg)) \
+	$($(target)_$(source)_SDKS.$(_bld_trg)) \
+	$($(source)_SDKS.$(_bld_trg).$(_bld_trg_arch)) \
+	$($(target)_$(source)_SDKS.$(_bld_trg).$(_bld_trg_arch)) \
+	$($(source)_SDKS.$(_bld_trg_arch)) \
+	$($(target)_$(source)_SDKS.$(_bld_trg_arch)) \
+	$($(source)_SDKS.$(KBUILD_TYPE)) \
+	$($(target)_$(source)_SDKS.$(KBUILD_TYPE)) \
+	$($(source)_SDKS) \
+	$($(target)_$(source)_SDKS))
+$(eval _USES += \
+	$($(source)_USES.$(_bld_trg)) \
+	$($(target)_$(source)_USES.$(_bld_trg)) \
+	$($(source)_USES.$(_bld_trg).$(_bld_trg_arch)) \
+	$($(target)_$(source)_USES.$(_bld_trg).$(_bld_trg_arch)) \
+	$($(source)_USES.$(_bld_trg_arch)) \
+	$($(target)_$(source)_USES.$(_bld_trg_arch)) \
+	$($(source)_USES.$(KBUILD_TYPE)) \
+	$($(target)_$(source)_USES.$(KBUILD_TYPE)) \
+	$($(source)_USES) \
+	$($(target)_$(source)_USES))
+endef # def_tools_sdks_target_source
+
+define def_tools_sdks_target
+local _bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE))
+local _bld_trg := $(firstword $($(target)_BLD_TRG) $(bld_trg))
+local _bld_trg_arch := $(firstword $($(target)_BLD_TRG_ARCH) $(bld_trg_arch))
+local _bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(bld_trg_cpu))
+
+$(eval _TOOLS += $(foreach prop, $(PROPS_TOOLS), \
+	$($(target)_$(prop).$(_bld_trg)) \
+	$($(target)_$(prop).$(_bld_trg_arch)) \
+	$($(target)_$(prop).$(_bld_trg).$(_bld_trg_arch)) \
+	$($(target)_$(prop))))
+$(eval _SDKS += \
+	$($(target)_SDKS.$(_bld_trg)) \
+	$($(target)_SDKS.$(_bld_trg_arch)) \
+	$($(target)_SDKS.$(_bld_trg).$(_bld_trg_arch)) \
+	$($(target)_SDKS))
+$(eval _USES += \
+	$($(target)_USES.$(_bld_trg)) \
+	$($(target)_USES.$(_bld_trg_arch)) \
+	$($(target)_USES.$(_bld_trg).$(_bld_trg_arch)) \
+	$($(target)_USES))
+$(foreach source, \
+	$($(target)_SOURCES.$(_bld_trg)) \
+	$($(target)_SOURCES.$(_bld_trg_arch)) \
+	$($(target)_SOURCES.$(_bld_trg).$(_bld_trg_arch)) \
+	$($(target)_SOURCES.$(_bld_trg_cpu)) \
+	$($(target)_SOURCES.$(_bld_type)) \
+	$($(target)_SOURCES) \
+	, $(evalval def_tools_sdks_target_source))
+endef # def_tools_sdks_target
+
+define def_tools_srcname_target
+local _bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE))
+local _bld_trg := $(firstword $($(target)_BLD_TRG) $(bld_trg))
+local _bld_trg_arch := $(firstword $($(target)_BLD_TRG_ARCH) $(bld_trg_arch))
+local _bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(bld_trg_cpu))
+
+$(foreach source, $(notdir\
+	$($(target)_SOURCES.$(_bld_trg)) \
+	$($(target)_SOURCES.$(_bld_trg_arch)) \
+	$($(target)_SOURCES.$(_bld_trg).$(_bld_trg_arch)) \
+	$($(target)_SOURCES.$(_bld_trg_cpu)) \
+	$($(target)_SOURCES.$(_bld_type)) \
+	$($(target)_SOURCES) \
+	), $(evalval def_tools_sdks_target_source))
+endef # def_tools_srcname_target
+
+bld_trg := $(KBUILD_TARGET)
+bld_trg_arch := $(KBUILD_TARGET_ARCH)
+bld_trg_cpu := $(KBUILD_TARGET_CPU)
+$(foreach target, $(_ALL_TARGET_TARGETS), $(evalval def_tools_sdks_target))
+$(foreach target, $(_ALL_SRCNAME_TARGETS), $(evalval def_tools_srcname_target))
+
+bld_trg := $(KBUILD_HOST)
+bld_trg_arch := $(KBUILD_HOST_ARCH)
+bld_trg_cpu := $(KBUILD_HOST_CPU)
+$(foreach target, $(_ALL_HOST_TARGETS), $(evalval def_tools_sdks_target))
+
+_TOOLS := $(sort $(_TOOLS))
+_SDKS := $(sort $(_SDKS))
+
+## Tool load function.
+# @param loading    The tool name
+define def_tools_load_function
+ifndef TOOL_$(loading)
+ TOOL_$(loading)_KMK_FILE := $(firstword $(foreach path, $(KBUILD_TOOL_PATHS) $(KBUILD_PATH)/tools $(KBUILD_DEFAULT_PATHS), $(wildcard $(path)/$(loading).kmk)))
+ ifeq ($(TOOL_$(loading)_KMK_FILE),)
+  $(error kBuild: Cannot find include file for the tool '$(loading)'! Searched: $(KBUILD_TOOL_PATHS) $(KBUILD_PATH)/tools $(KBUILD_DEFAULT_PATHS))
+ endif
+ include $(TOOL_$(loading)_KMK_FILE)
+ ifndef TOOL_$(loading)
+  $(warning kBuild: TOOL_$(loading) was not defined by $(TOOL_$(loading)_KMK_FILE)!)
+ endif
+endif
+endef # def_tools_include
+
+## SDK load function.
+# @param loading    The tool name
+define def_sdk_load_function
+ifndef SDK_$(loading)
+ SDK_$(loading)_KMK_FILE := $(firstword $(foreach path, $(KBUILD_SDK_PATHS) $(KBUILD_PATH)/sdks $(KBUILD_DEFAULT_PATHS), $(wildcard $(path)/$(loading).kmk)))
+ ifeq ($(SDK_$(loading)_KMK_FILE),)
+  $(error kBuild: Cannot find include file for the SDK '$(loading)'! Searched: $(KBUILD_SDK_PATHS) $(KBUILD_PATH)/sdks $(KBUILD_DEFAULT_PATHS))
+ endif
+ include $(SDK_$(loading)_KMK_FILE)
+ ifndef SDK_$(loading)
+  $(warning kBuild: SDK_$(loading) was not defined by $(SDK_$(loading)_KMK_FILE)!)
+ endif
+endif
+endef # def_sdk_load_function
+
+
+properties :=
+properties_now_l :=
+properties_now_r :=
+properties_deferred   := $(PROPS_SINGLE) $(PROPS_DEFERRED)
+properties_deferred_l := $(PROPS_ACCUMULATE_L)
+properties_deferred_r := $(PROPS_ACCUMULATE_R)
+
+src_prefix := TOOL_
+load_function := def_tools_load_function
+$(foreach trg, $(addprefix TOOL_,$(_TOOLS)), $(evalval def_inherit))
+
+src_prefix := SDK_
+load_function := def_sdk_load_function
+$(foreach trg, $(addprefix SDK_,$(_SDKS)), $(evalval def_inherit))
+
+# done inheriting.
+src_prefix :=
+load_function :=
+properties :=
+properties_now_l :=
+properties_now_r :=
+properties_deferred :=
+properties_deferred_l :=
+properties_deferred_r :=
+
+# No inheriting for the uses, they're just global 'code'.
+$(foreach loading, $(_USES), $(evalval def_unit_load_function))
+
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done tools, sdks and units)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+
+#
+#
+# Target lists - Pass 1
+#
+#       This pass is for defining variables that might be referenced in
+#       properties of other targets.
+#
+#
+
+# Don't do anything for fetch targets (yet).
+
+##
+# Link prolog for Pass 1.
+#
+# @param    $(target)           Normalized target name.
+# @param    $(EXT)              EXE,DLL,SYS,LIB.
+# @param    $(EXTPRE)           HOST or nothing.
+# @param    $(definst)          The default _INST value.
+# @param    $(tool_prefix)      LD or AR.
+# @param    $(bld_trg_base_var) TARGET or PLATFORM.
+define def_pass1_link_common
+
+local bld_type    := $(firstword $($(target)_BLD_TYPE)     $(KBUILD_TYPE))
+local bld_trg     := $(firstword $($(target)_BLD_TRG)      $(BUILD_$(bld_trg_base_var)))
+local bld_trg_arch:= $(firstword $($(target)_BLD_TRG_ARCH) $(BUILD_$(bld_trg_base_var)_ARCH))
+local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU)  $(BUILD_$(bld_trg_base_var)_CPU))
+
+local tool        := $(call _TARGET_TOOL,$(target),$(tool_prefix))
+local name        := $(firstword\
+	$($(target)_NAME.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg))\
+	$($(target)_NAME.$(bld_type))\
+	$($(target)_NAME)\
+	$(target))
+local outbase     := $(call TARGET_BASE,$(name),$(target))
+ifndef PATH_$(target)
+ PATH_$(target) := $(patsubst %/,%,$(dir $(outbase)))
+else ifneq ($(PATH_$(target)),$(patsubst %/,%,$(dir $(outbase))))
+ $(error kBuild internal error: PATH_$(target)=$(PATH_$(target)) expected $(patsubst %/,%,$(dir $(outbase))))
+endif
+ifeq ($(tool_prefix),AR) ## @todo fix this mess!
+local suff := $(firstword\
+	$($(target)_$(EXT)SUFF.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_$(EXT)SUFF.$(bld_trg))\
+	$($(target)_$(EXT)SUFF)\
+	$(TOOL_$(tool)_$(tool_prefix)$(EXT)SUFF.$(bld_trg).$(bld_trg_arch))\
+	$(TOOL_$(tool)_$(tool_prefix)$(EXT)SUFF.$(bld_trg))\
+	$(TOOL_$(tool)_$(tool_prefix)$(EXT)SUFF)\
+	$(SUFF_LIB))
+else
+local suff := $(firstword \
+	$($(target)_$(EXT)SUFF) \
+	$($(target)_$(EXT)SUFF) \
+	$(TOOL_$(tool)_$(tool_prefix)$(EXT)SUFF) \
+	$($(EXTPRE)SUFF_$(EXT)))
+endif
+local out := $(outbase)$(suff)
+
+# TARGET_*
+TARGET_$(target) := $(out)
+
+# INSTARGET_*
+ifeq ($(strip $($(target)_NOINST) $($(target)_NOINST.$(bld_trg)) $($(target)_NOINST.$(bld_trg).$(bld_trg_arch)) $($(target)_NOINST.$(bld_trg).$(bld_trg_arch).$(bld_type))  $($(target)_NOINST.$(bld_trg_arch)) $($(target)_NOINST.$(bld_trg_cpu)) $($(target)_NOINST.$(bld_trg_type))),)
+ ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_trg_arch))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_trg_arch)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_type)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg_arch))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg_arch)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg)))
+ else ifneq ($(strip $($(target)_INST.$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_type)))
+ else ifneq ($(strip $($(target)_INST)),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST))
+ else
+  local inst := $(definst)/
+ endif
+ INSTARGET_$(target) := $(patsubst %/,%/$(notdir $(out)),$(inst))
+
+else # NOINST
+ INSTARGET_$(target) :=
+endif # NOINST
+
+endef
+
+
+#
+# BLDPROGS (Pass 1)
+#
+define def_pass1_bldprog
+# set NOINST if not forced installation before doing the usual stuff.
+ifndef $(target)_INST
+$(target)_NOINST := 1
+endif
+$(evalval def_pass1_link_common)
+endef
+
+EXT     := EXE
+EXTPRE  := HOST
+definst := $(PATH_BIN)
+tool_prefix := LD
+bld_trg_base_var := PLATFORM
+$(foreach target, $(_ALL_BLDPROGS), \
+	$(evalval def_pass1_bldprog))
+
+
+#
+# LIBRARIES (Pass 1)
+#
+EXT     := LIB
+EXTPRE  :=
+definst := $(PATH_LIB)
+tool_prefix := AR
+bld_trg_base_var := TARGET
+$(foreach target, $(_ALL_LIBRARIES), \
+	$(evalval def_pass1_link_common))
+
+
+#
+# DLLS  (Pass 1)
+#
+EXT     := DLL
+EXTPRE  :=
+definst := $(PATH_DLL)
+tool_prefix := LD
+bld_trg_base_var := TARGET
+$(foreach target, $(_ALL_DLLS), \
+	$(evalval def_pass1_link_common))
+
+
+#
+# IMPORT LIBRARIES (Pass 1)
+#
+#   - On OS/2 and windows these are libraries.
+#   - On other platforms they are fake DLLs.
+#
+if1of ($(KBUILD_TARGET), nt os2 win win64 win32)
+ EXT     := LIB
+ EXTPRE  :=
+ definst := $(PATH_LIB)
+ tool_prefix := AR
+ bld_trg_base_var := TARGET
+ $(foreach target, $(_ALL_IMPORT_LIBS), \
+	$(evalval def_pass1_link_common))
+else
+ EXT     := DLL
+ EXTPRE  :=
+ definst := $(PATH_DLL)
+ tool_prefix := LD
+ bld_trg_base_var := TARGET
+ $(foreach target, $(_ALL_IMPORT_LIBS), \
+	$(evalval def_pass1_link_common))
+endif
+
+
+#
+# PROGRAMS (Pass 1)
+#
+EXT     := EXE
+EXTPRE  :=
+definst := $(PATH_BIN)
+tool_prefix := LD
+bld_trg_base_var := TARGET
+$(foreach target, $(_ALL_PROGRAMS), \
+	$(evalval def_pass1_link_common))
+
+
+#
+# SYSMODS (Pass 1)
+#
+EXT     := SYS
+EXTPRE  :=
+definst := $(PATH_SYS)
+tool_prefix := LD
+bld_trg_base_var := TARGET
+$(foreach target, $(_ALL_SYSMODS), \
+	$(evalval def_pass1_link_common))
+
+
+#
+# INSTALLS (Pass 1)
+# 	Note! INSTARGET_* for INSTALLS aren't available until later.
+#
+define def_pass1_install
+local bld_type    := $(firstword $($(target)_BLD_TYPE)     $(KBUILD_TYPE))
+local bld_trg     := $(firstword $($(target)_BLD_TRG)      $(KBUILD_TARGET))
+local bld_trg_arch:= $(firstword $($(target)_BLD_TRG_ARCH) $(KBUILD_TARGET_ARCH))
+local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU)  $(KBUILD_TARGET_CPU))
+# TARGET_*
+TARGET_$(target)  := $(PATH_TARGET)/$(target).ins
+# INSTARGET_ later.
+# PATH_*
+local outbase     := $(call TARGET_BASE,$(target),$(target))
+PATH_$(target)    := $(patsubst %/,%,$(dir $(outbase)))
+endef # def_pass1_install
+$(foreach target, $(_ALL_INSTALLS), \
+	$(evalval def_pass1_install))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done pass 1)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+
+
+#
+#
+# Target lists - Pass 2
+#
+#
+
+
+## @page pg_fetches 	Fetching Tools, Sources and Similar.
+#
+# The targets listed in the the FETCHES target list have the following attributes:
+#	SOURCES
+#	INST
+#   FETCHTOOL
+#   FETCHFLAGS
+#   FETCHDIR
+#   UNPACKTOOL
+#   UNPACKFLAGS
+#
+# As usual the target name is an alias for 'creating' the target. Other
+# aliases are:
+#	pass_fetches
+#	fetch
+#	unfetch
+# 	download
+# 	unpack
+#
+# @remark
+#
+#   This is a little bit complex because we must guarantee that if a source file
+#   changes only sligtly we must refetch it and to a proper unpacking of it. It
+#   is also a desire that fetched archives and unpacked files can be deleted to
+#   save space.
+#
+#   Thus, we must be able to cleanup what we've unpacked should any of the
+#   sources be removed. We do this by maintaining a file listing the files
+#   and directories that was unpacked. This operation is named 'unfetch'.
+#
+#   We make use of the SIZE and MD5 attributes for each of the sources to
+#   create a digest that is stored in the primary target file. Subsequent
+#   runswill compare their digest with it to decide if a refetch is required.
+#   When a refetch is found necessary, an 'unfetch' is performed first to
+#	clean out old files and directores. Note even changes in source order
+#   will cause a refetch due to the way the digest is constructed and
+#   evaluated.
+#
+#   By not depending directly on the archives (nor on any unpacked files)
+#	but on a goal made up from the archive name, size and md5, we allow
+#   the user to delete the archives. Naturally, this means we'll have to
+#   check and fetch missing archives before attempting to unpack them.
+#
+# @remark
+#
+#	This feature will *NOT* work correctly with vanilla GNU make becuase
+#   it makes use of includedep to avoid too many unnecessary files.
+#
+# @todo
+#   1. Download corruption / continuation.
+#   2. It's quite possible that there is one too many indirect dependency now...
+#
+
+## generates the fetch rule
+define def_fetch_src_fetch_rule
+# Indirect goal for downloading something.
+.PRECIOUS: $(out)
+$(out) + $($(target)_$(srcname)_FETCH_OUTPUT_) +| $($(target)_$(srcname)_FETCH_OUTPUT_MAYBE_)  : \
+		| $($(target)_$(srcname)_FETCH_DEPORD_)
+	%$$(call MSG_FETCH_DL,$(target),$(source),$(out))
+	@## @todo do fancy stuff like download continuation.
+	$$(QUIET)$$(RM) -f -- $(out)
+	$($(target)_$(srcname)_FETCH_CMDS_)
+	$$(QUIET)$(if $(md5),$$(MD5SUM_EXT) -b -C $(md5) $(out))
+
+
+
+# Intermediate goal for making sure the md5 and size matches. it will (re) fetch the archive if necessary.
+$(out).checked_$(md5)_$(size): $($(target)_$(srcname)_FETCH_DEPEND_) | $($(target)_$(srcname)_FETCH_DEPORD_)
+	%$$(call MSG_FETCH_CHK,$(target),$(source),$(out))
+	$$(QUIET)$$(RM) -f -- $$@
+	@# (re)fetch the file if it doesn't exist or if it doesn't matches the md5.
+	@## @todo do fancy stuff like download continuation.
+	$$(QUIET)( test -f $(out) && $(if $(md5),$$(MD5SUM_EXT) -b -C $(md5) $(out), true) ) \
+	          || (   $$(RM_EXT) -f $(out) \
+		      && $$(MAKE)      $(out) -f $(MAKEFILE) --no-print-directory )
+	$$(QUIET2)$$(APPEND) $$@
+
+_TARGET_$(target)_FETCHED += $(out) $(out).checked_$(md5)_$(size)
+
+# Just a little precaution.
+.NOTPARALLEL: $(out) $(out).checked_$(md5)_$(size)
+
+endef
+
+## generates the unpack rule
+define def_fetch_src_unpack_rule
+# This is the unpack rule. it has an order-only dependency on the download check.
+$(out) + $($(target)_$(srcname)_UNPACK_OUTPUT_) +| $($(target)_$(srcname)_UNPACK_OUTPUT_MAYBE_) : \
+		$($(target)_$(srcname)_UNPACK_DEPEND_) \
+		| $($(target)_$(srcname)_UNPACK_DEPORD_) $(archive).checked_$(md5)_$(size)
+	%$$(call MSG_FETCH_UP,$(target),$(archive),$(inst))
+	$$(QUIET)$$(RM) -f -- $(out)
+	@# if the source archive doesn't exist fetch it (can have been deleted to save space).
+	$$(QUIET)test -f $(archive) \
+	         || (   $$(RM_EXT) -f $(archive).checked_$(md5)_$(size) \
+	             && $$(MAKE)      $(archive).checked_$(md5)_$(size) -f $(MAKEFILE) --no-print-directory )
+	$($(target)_$(srcname)_UNPACK_CMDS_)
+	$$(QUIET2)$$(APPEND) $(out) $(notdir $(archive).checked_$(md5)_$(size))
+	$$(QUIET2)$$(APPEND) $(out) $(notdir $(out))
+
+$(eval _TARGET_$(target)_UNPACKED += $(out))
+_TARGET_$(target)_DIGEST := $(_TARGET_$(target)_DIGEST)-$(srcname)_$(md5)_$(size)
+
+.NOTPARALLEL: $(out)
+
+endef
+
+## Processes a fetch source
+#
+define def_fetch_src
+#$ (warning dbg: def_fetch_src: source='$(source)' target='$(target)')
+
+# common
+local srcname := $(notdir $(source))
+local inst := $(firstword \
+	$($(target)_$(source)_INST)\
+	$($(target)_$(srcname)_INST)\
+	$($(source)_INST)\
+	$($(srcname)_INST)\
+	$($(target)_INST)\
+)
+ifneq ($(patsubst %/,ok,$(inst)),ok)
+$(error kBuild: Bad or missing INST property for source '$(source)' in target '$(target)': $(inst))
+endif
+INSTARGET_$(target)_$(srcname) := $(inst)
+local fetchdir := $(firstword \
+	$($(target)_$(source)_FETCHDIR)\
+	$($(target)_$(srcname)_FETCHDIR)\
+	$($(source)_FETCHDIR)\
+	$($(srcname)_FETCHDIR)\
+	$($(target)_FETCHDIR)\
+	$(FETCHDIR)\
+	$(PATH_TARGET)\
+)
+local deps := \
+	$($(target)_$(source)_DEPS)\
+	$($(target)_$(srcname)_DEPS)\
+	$($(source)_DEPS)\
+	$($(srcname)_DEPS)\
+	$($(target)_DEPS)
+local orderdeps := \
+	$($(target)_$(source)_ORDERDEPS)\
+	$($(target)_$(srcname)_ORDERDEPS)\
+	$($(source)_ORDERDEPS)\
+	$($(srcname)_ORDERDEPS)\
+	$($(target)_ORDERDEPS)
+local md5 := $(firstword \
+	$($(target)_$(source)_MD5)\
+	$($(target)_$(srcname)_MD5)\
+	$($(source)_MD5)\
+	$($(srcname)_MD5)\
+	$($(target)_MD5)\
+)
+local size := $(firstword \
+	$($(target)_$(source)_SIZE)\
+	$($(target)_$(srcname)_SIZE)\
+	$($(source)_SIZE)\
+	$($(srcname)_SIZE)\
+	$($(target)_SIZE)\
+)
+clean_files += \
+	$($(target)_$(source)_CLEAN)\
+	$($(target)_$(srcname)_CLEAN)\
+	$($(source)_CLEAN)\
+	$($(srcname)_CLEAN)
+local dep := # not legal for fetch and unpack tools
+
+
+#
+# The fetching.
+#
+local out := $(fetchdir)/$(srcname)
+local archive := $(out)
+TARGET_$(target)_$(srcname) := $(out)
+local dirdep := $(call DIRDEP,$(fetchdir))
+local tool := $(firstword \
+	$($(target)_$(source)_FETCHTOOL)\
+	$($(target)_$(srcname)_FETCHTOOL)\
+	$($(target)_$(source)_TOOL)\
+	$($(target)_$(srcname)_TOOL)\
+	$($(source)_FETCHTOOL)\
+	$($(srcname)_FETCHTOOL)\
+	$($(source)_TOOL)\
+	$($(srcname)_TOOL)\
+	$($(target)_FETCHTOOL)\
+	$($(target)_TOOL)\
+	)
+local flags :=\
+	$(TOOL_$(tool)_FETCHFLAGS)\
+	$(FETCHFLAGS)\
+	$($(target)_FETCHFLAGS)\
+	$($(srcname)_FETCHFLAGS)\
+	$($(source)_FETCHFLAGS)\
+	$($(target)_$(srcname)_FETCHFLAGS)\
+	$($(target)_$(source)_FETCHFLAGS)
+
+#$ (warning dbg: target=$(target) source=$(source) $(srcname)=$(srcname) tool=$(tool) out=$(out) flags=$(flags) dirdep=$(dirdep) fetchdir=$(fetchdir) md5=$(md5) size=$(size))
+
+ifndef TOOL_$(tool)_FETCH_CMDS
+$(warning kBuild: tools: \
+	1 $($(target)_$(source)_FETCHTOOL)\
+	2 $($(target)_$(srcname)_FETCHTOOL)\
+	3 $($(target)_$(source)_TOOL)\
+	4 $($(target)_$(srcname)_TOOL)\
+	5 $($(source)_FETCHTOOL)\
+	6 $($(srcname)_FETCHTOOL)\
+	7 $($(source)_TOOL)\
+	8 $($(srcname)_TOOL)\
+	9 $($(target)_FETCHTOOL)\
+	10 $($(target)_TOOL) )
+$(error kBuild: TOOL_$(tool)_FETCH_CMDS is not defined. source=$(source) target=$(target) )
+endif
+
+# call the tool
+$(target)_$(srcname)_FETCH_CMDS_   := $(TOOL_$(tool)_FETCH_CMDS)
+$(target)_$(srcname)_FETCH_OUTPUT_ := $(TOOL_$(tool)_FETCH_OUTPUT)
+$(target)_$(srcname)_FETCH_OUTPUT_MAYBE_ := $(TOOL_$(tool)_FETCH_OUTPUT_MAYBE)
+$(target)_$(srcname)_FETCH_DEPEND_ := $(TOOL_$(tool)_FETCH_DEPEND) $(deps)
+$(target)_$(srcname)_FETCH_DEPORD_ := $(TOOL_$(tool)_FETCH_DEPORD) $(dirdep) $(orderdeps)
+
+# generate the fetch rule.
+$(eval $(def_fetch_src_fetch_rule))
+
+
+#
+# The unpacking / installing.
+#
+local out := $(inst)_kBuild_$(target)_$(srcname)_unpacked.lst
+local dirdep := $(call DIRDEP,$(inst))
+local tool := $(firstword \
+	$($(target)_$(source)_UNPACKTOOL)\
+	$($(target)_$(srcname)_UNPACKTOOL)\
+	$($(target)_$(source)_TOOL)\
+	$($(target)_$(srcname)_TOOL)\
+	$($(source)_UNPACKTOOL)\
+	$($(srcname)_UNPACKTOOL)\
+	$($(source)_TOOL)\
+	$($(srcname)_TOOL)\
+	$($(target)_UNPACKTOOL)\
+	$($(target)_TOOL) \
+	)
+ifeq ($(tool),)
+local tool := $(toupper $(subst .,,$(suffix $(subst tar.,TAR,$(srcname)))))
+$(evalval def_tools_include)
+endif
+local flags :=\
+	$(TOOL_$(tool)_UNPACKFLAGS)\
+	$(UNPACKFLAGS)\
+	$($(target)_UNPACKFLAGS)\
+	$($(srcname)_UNPACKFLAGS)\
+	$($(source)_UNPACKFLAGS)\
+	$($(target)_$(srcname)_UNPACKFLAGS)\
+	$($(target)_$(source)_UNPACKFLAGS)
+
+#$ (warning dbg: target=$(target) source=$(source) $(srcname)=$(srcname) tool=$(tool) out=$(out) flags=$(flags) dirdep=$(dirdep) inst=$(inst) md5=$(md5) size=$(size))
+ifndef TOOL_$(tool)_UNPACK_CMDS
+$(warning kBuild: tools: \
+	1 $($(target)_$(source)_UNPACKTOOL)\
+	2 $($(target)_$(srcname)_UNPACKTOOL)\
+	3 $($(target)_$(source)_TOOL)\
+	4 $($(target)_$(srcname)_TOOL)\
+	5 $($(source)_UNPACKTOOL)\
+	6 $($(srcname)_UNPACKTOOL)\
+	7 $($(source)_TOOL)\
+	8 $($(srcname)_TOOL)\
+	9 $($(target)_UNPACKTOOL)\
+	10 $($(target)_TOOL) \
+	11 $(toupper $(subst tar.,TAR,$(ext $(srcname)))) \
+	)
+$(error kBuild: TOOL_$(tool)_UNPACK_CMDS is not defined. source=$(source) target=$(target) )
+endif
+
+# call the tool
+$(target)_$(srcname)_UNPACK_CMDS_   := $(TOOL_$(tool)_UNPACK_CMDS)
+$(target)_$(srcname)_UNPACK_OUTPUT_ := $(TOOL_$(tool)_UNPACK_OUTPUT)
+$(target)_$(srcname)_UNPACK_OUTPUT_MAYBE_ := $(TOOL_$(tool)_UNPACK_OUTPUT_MAYBE)
+$(target)_$(srcname)_UNPACK_DEPEND_ := $(TOOL_$(tool)_UNPACK_DEPEND) $(deps)
+$(target)_$(srcname)_UNPACK_DEPORD_ := $(TOOL_$(tool)_UNPACK_DEPORD) $(dirdep) $(orderdeps)
+
+# generate the fetch rule.
+$(eval $(def_fetch_src_unpack_rule))
+
+_DIRS += $(inst) $(fetchdir)
+
+endef
+
+
+##
+# Define the target level rules for a fetch.
+# @param	target
+# @param	out
+# @param	inst
+# @param	_TARGET_$(target)_UNPACKED
+# @param	_TARGET_$(target)_DIGEST
+# @param	bld_trg
+# @param	bld_trg_arch
+define def_fetch_rules
+
+$(out).lst: $(_TARGET_$(target)_UNPACKED) | $(call DIRDEP,$(inst))
+	%$$(call MSG_FETCH_OK,$(target))
+	$$(QUIET)$$(RM) -f -- $$@ $$@.tmp
+	$$(QUIET2)$$(APPEND) $$@.tmp '$(notdir $(out))'
+	$$(QUIET)$(if $(_TARGET_$(target)_UNPACKED),$$(CAT_EXT) $(_TARGET_$(target)_UNPACKED) >> $$@.tmp)
+	$$(QUIET)$$(MV) -f -- $$@.tmp $$@
+
+$(out)_unfetched:
+	%$$(call MSG_UNFETCH,$(target))
+	$$(QUIET)$$(RM) -f -- $$(addprefix $(inst),$$(shell $$(CAT_EXT) $(out).lst 2> /dev/null | $$(SED) -e '/\/$$$$/d'))
+	$$(QUIET)$$(RMDIR) -p --ignore-fail-on-non-empty --ignore-fail-on-not-exist -- $$(dir $$@) \
+		$$(addprefix $(inst),$$(sort $$(dir $$(shell $$(CAT_EXT) $(out).lst 2> /dev/null))))
+	$$(QUIET)$$(RM) -f -- $(out).lst $(out)
+	$$(QUIET)$$(RMDIR) -p --ignore-fail-on-non-empty --ignore-fail-on-not-exist -- $$(dir $$@)
+
+$(out): $(comp-vars _TARGET_$(target)_DIGEST_PREV,_TARGET_$(target)_DIGEST,FORCE) | $(call DIRDEP,$(inst))
+	$$(QUIET)$$(RM) -f -- $$@
+	%$$(if $$(_TARGET_$(target)_DIGEST),$$(if $$(wildcard $(out).lst)\
+		,$$(call MSG_REFETCH,$(target)),$$(call MSG_FETCH,$(target))),$$(call MSG_UNFETCH,$(target)))
+	$$(QUIET)$$(if $$(wildcard $(out).lst      ),$$(MAKE) -f $(MAKEFILE) --no-print-directory $(out)_unfetched)
+	$$(QUIET)$$(if  $$(_TARGET_$(target)_DIGEST),$$(MAKE) -f $(MAKEFILE) --no-print-directory $(out).lst,$$(RMDIR) -p --ignore-fail-on-non-empty --ignore-fail-on-not-exist -- $$(dir $$@))
+	$$(QUIET2)$$(if $$(_TARGET_$(target)_DIGEST),$$(APPEND) $$@ "_TARGET_$(target)_DIGEST_PREV := $(_TARGET_$(target)_DIGEST)")
+
+.NOTPARALLEL: $(out).lst $(out)_unfetched $(out)
+
+endef
+
+
+##
+# Deal with one fetch target.
+# @param	target
+# @param	bld_trg
+# @param	bld_trg_arch
+define def_fetch
+# common
+INSTARGET_$(target) := $($(target)_INST)
+ifneq ($(patsubst %/,ok,$(INSTARGET_$(target))),ok)
+$(error kBuild: Bad or missing INST property for target '$(target)'. \
+	$(target)_INST='$($(target)_INST)' ($(origin $(target)_INST)))
+endif
+_TARGET_$(target)_FETCHED :=
+_TARGET_$(target)_UNPACKED :=
+_TARGET_$(target)_DIGEST :=
+local clean_files := $($(target)_CLEAN) $($(target)_CLEAN.$(bld_trg)) $($(target)_CLEAN.$(bld_trg).$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_arch)) $($(target)_CLEAN.$(KBUILD_TYPE))
+
+# The 'sources'.
+#$ (warning dbg fetch: target=$(target) sources=$($(target)_SOURCES) $($(target)_SOURCES.$(KBUILD_TYPE)) $($(target)_SOURCES.$(KBUILD_TARGET)) $($(target)_SOURCES.$(bld_trg_arch)) $($(target)_SOURCES.$(KBUILD_TARGET).$(bld_trg_arch)))
+$(foreach source,$($(target)_SOURCES) $($(target)_SOURCES.$(KBUILD_TYPE)) $($(target)_SOURCES.$(bld_trg)) $($(target)_SOURCES.$(bld_trg_arch)) $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)),\
+	$(evalval def_fetch_src))
+
+# The target.
+local inst := $(INSTARGET_$(target))
+local out := $(inst)_kBuild_fetch_$(target)
+
+$(eval includedep $(out))
+
+$(eval $(def_fetch_rules))
+
+# Define the aliases here (doesn't work if defined in def_fetch_rules, just like includedep).
+$(target): $(out)
+$(target)_unfetch: $(out)_unfetched
+
+_FETCHES += $(out)
+_DOWNLOADS += $(_TARGET_$(target)_FETCHED)
+_UNPACKS += $(_TARGET_$(target)_UNPACKED)
+_UNFETCHES += $(out)_unfetched
+_DIRS += $(inst)
+_CLEAN_FILES += $(clean_files)
+
+endef
+
+# Walk the FETCH target lists.
+bld_trg := $(KBUILD_TARGET)
+bld_trg_arch := $(KBUILD_TARGET_ARCH)
+$(foreach target, $(_ALL_FETCHES), \
+	$(evalvalctx def_fetch))
+
+# some aliases.
+download: $(_DOWNLOADS)
+unpack: $(_UNPACKS)
+fetch: $(_FETCHES)
+unfetch: $(_UNFETCHES)
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done fetching targets)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+
+##
+## Patching.
+##
+##
+#define def_patch_src
+#
+#endef
+#
+#
+## Deal with one patch target.
+#define def_patch
+#
+#$(foreach source,$($(target)_SOURCES) $($(target)_SOURCES.$(KBUILD_TYPE)) $($(target)_SOURCES.$(KBUILD_TARGET)) $($(target)_SOURCES.$(KBUILD_TARGET_ARCH)) $($(target)_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)),\
+#	$(evalval def_patch_src))
+#
+#_PATCHES +=
+#endef
+#
+#$(foreach target, $(_ALL_PATCHES), \
+#	$(evalval def_patch))
+#
+
+
+#
+# Object processing.
+#
+
+## wrapper the compile command dependency check.
+ifndef NO_COMPILE_CMDS_DEPS
+ _DEP_COMPILE_CMDS = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_CMDS_PREV_),$$(commands $(obj)),FORCE)
+else
+ _DEP_COMPILE_CMDS =
+endif
+
+## Generates the rules for building a specific object, and the aliases
+# for building a source file.
+# @param    $(obj)    The object file.
+define def_target_source_rule
+ifdef TOOL_$(tool)_COMPILE_$(type)_USES_KOBJCACHE
+$(outbase).koc +| $(obj) $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_) : \
+		$($(target)_$(source)_DEPEND_) \
+		$(value _DEP_COMPILE_CMDS) \
+		| \
+		$($(target)_$(source)_DEPORD_) \
+		$$$$($(target)_INTERMEDIATES)
+	%$$(call MSG_COMPILE,$(target),$(source),$$@,$(type))
+else
+$(obj) + $($(target)_$(source)_OUTPUT_) +| $($(target)_$(source)_OUTPUT_MAYBE_) : \
+		$($(target)_$(source)_DEPEND_) \
+		$(value _DEP_COMPILE_CMDS) \
+		| \
+		$($(target)_$(source)_DEPORD_) \
+		$$$$($(target)_INTERMEDIATES)
+	%$$(call MSG_COMPILE,$(target),$(source),$$@,$(type))
+ifdef TOOL_$(tool)_COMPILE_$(type)_DONT_PURGE_OUTPUT
+	$$(QUIET)$$(RM) -f -- $(dep) $(obj) $($(target)_$(source)_OUTPUT_) $($(target)_OUTPUT_MAYBE_)
+endif
+endif
+
+$($(target)_$(source)_CMDS_)
+
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(obj)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(basename $(notdir $(obj))).o: $(obj)
+$(basename $(notdir $(obj))).obj: $(obj)
+
+## @todo make this 'local cmds' in 0.2.x or when a new kb-src-one is added.
+$(target)_$(source)_CMDS_ :=
+endef
+
+
+## wrapper the link command dependency check.
+ifndef NO_LINK_CMDS_DEPS
+ _DEP_LINK_CMDS = $$(comp-cmds-ex $$($(target)_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _DEP_LINK_CMDS =
+endif
+
+## Generate the link rule for a target.
+# @param    $(target)               The normalized target name.
+# @param    $(dirdep)               Directories we depend upon begin created before linking.
+# @param    $(dep)                  The name of the dependency file.
+# @param    $(out)
+# @param    $($(target)_OUTPUT_)    Output files from the link.
+# @param    $($(target)_OUTPUT_MAYBE_)	Output files that the link may perhaps create.
+# @param    $($(target)_DEPEND_)    Dependencies.
+# @param    $($(target)_DEPORD_)    Dependencies which should only affect build order.
+# @param    $(cmds)                 The link commands.
+# @param    $($(target)_CMDS_PREV_) The link commands from the previous run.
+define def_link_rule
+$(out) + $($(target)_OUTPUT_) +| $($(target)_OUTPUT_MAYBE_) : \
+		$($(target)_DEPEND_) \
+		$(value _DEP_LINK_CMDS) \
+		| \
+		$($(target)_DEPORD_)
+	%$$(call MSG_LINK,$(target),$$@,$(tool_do))
+	$$(QUIET)$$(RM) -f -- $(dep) $(out) $($(target)_OUTPUT_) $($(target)_OUTPUT_MAYBE_)
+
+$(cmds)
+
+ifndef NO_LINK_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(basename $(notdir $(out))):: $(out)
+
+endef
+
+
+## Generate the link & lib install rule
+# @param    $(target)   Normalized target name.
+# @param    $(out)      The build target.
+# @param    $(INSTARGET_$(target))  The installation targets.
+# @param    $(mode)     The file mode (optional)
+define def_link_install_rule
+$(INSTARGET_$(target)) : $(out) | $(call DIRDEP,$(dir $(INSTARGET_$(target))))
+	%$$(call MSG_INST_TRG,$(target),$(out),$$@)
+	$$(QUIET)$$(INSTALL) $$(if $(mode),-m $(mode)) -- $(out) $$@
+
+ifdef KBUILD_DO_AUTO_INSTALL
+$(basename $(notdir $(out))):: $(INSTARGET_$(target))
+endif
+endef
+
+
+## def_src_handler_*
+#
+# @{
+define def_src_handler_c
+local type := C
+ $(kb-src-one )
+endef
+
+define def_src_handler_cxx
+local type := CXX
+ $(kb-src-one )
+endef
+
+define def_src_handler_objc
+local type := OBJC
+ $(kb-src-one )
+endef
+
+define def_src_handler_asm
+local type := AS
+ $(kb-src-one )
+endef
+
+define def_src_handler_rc
+local type := RC
+ $(kb-src-one )
+endef
+
+define def_src_handler_obj
+ifeq ($(defpath),)
+ $(target)_OBJS_ += $(source)
+else
+ $(target)_OBJS_ += $(abspathex $(source), $(defpath))
+endif
+endef
+## @}
+
+## Handle one source.
+# .
+define def_src_handler_one
+local suff := $(suffix $(source))
+local src_handler := $(firstword $(filter $(suff):%, $($(target)_$(source)_SRC_HANDLERS) $($(source)_SRC_HANDLERS) $(target_src_handlers) ))
+local handler := $(patsubst $(suff):%,%,$(src_handler))
+ifneq ($(handler),)
+ $(evalvalctx $(handler))
+else
+ othersrc += $(source)
+endif
+endef
+
+## Generic macro for processing all target sources.
+# @param    $(target)   Normalized target name.
+# @param    $(defpath)
+# @param    much-more...
+# @returns  othersrc, $(target)_OBJS_, ++
+define def_target_sources
+local target_src_handlers := $($(target)_SRC_HANDLERS) $(KBUILD_SRC_HANDLERS)
+$(foreach source,\
+	$($(target)_SOURCES)\
+	$($(target)_SOURCES.$(bld_trg))\
+	$($(target)_SOURCES.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_SOURCES.$(bld_trg_arch))\
+	$($(target)_SOURCES.$(bld_trg_cpu))\
+	$($(target)_SOURCES.$(bld_type))\
+	,$(evalval def_src_handler_one) )
+
+$(foreach source,\
+	$($(target)_GEN_SOURCES_)\
+	$($(target)_GEN_SOURCES_.$(bld_trg))\
+	$($(target)_GEN_SOURCES_.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_GEN_SOURCES_.$(bld_trg_arch))\
+	$($(target)_GEN_SOURCES_.$(bld_trg_cpu))\
+	$($(target)_GEN_SOURCES_.$(bld_type))\
+	,$(evalval def_src_handler_one) )
+endef
+
+
+
+## Generic macro for generating the install rule(s) for a target
+# and update the globals with default out.
+#
+# @param	$(target)   Normalized target name.
+# @param	$(out)      The output file.
+# @param	$(definst)  The default _INST value.
+# @param	$(typevar)  The name of the variable with all the root targets of its type.
+# @remark   Only library uses this now.
+define def_target_install_pluss
+ifeq ($(strip $($(target)_NOINST) $($(target)_NOINST.$(bld_trg)) $($(target)_NOINST.$(bld_trg).$(bld_trg_arch)) $($(target)_NOINST.$(bld_trg).$(bld_trg_arch).$(bld_type))  $($(target)_NOINST.$(bld_trg_arch)) $($(target)_NOINST.$(bld_trg_cpu)) $($(target)_NOINST.$(bld_trg_type))),)
+ ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_trg_arch))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_trg_arch)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_type)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg_arch))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg_arch)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg)))
+ else ifneq ($(strip $($(target)_INST.$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_type)))
+ else ifneq ($(strip $($(target)_INST)),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST))
+ else
+  local inst := $(definst)/
+ endif
+ INSTARGET_$(target) := $(patsubst %/,%/$(notdir $(out)),$(inst))
+
+$(eval $(def_link_install_rule))
+
+ _INSTALLS_FILES += $(INSTARGET_$(target))
+
+ ifdef KBUILD_DO_AUTO_INSTALL
+  $(typevar) += $(INSTARGET_$(target))
+ else
+  $(typevar) += $(out)
+ endif
+else # _NOINST
+ $(typevar) += $(out)
+endif
+
+_OUT_FILES += $($(target)_OUTPUT_) $($(target)_OUTPUT_MAYBE_) $(out)
+_CLEAN_FILES += $($(target)_CLEAN) $($(target)_CLEAN.$(bld_trg)) $($(target)_CLEAN.$(bld_trg).$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_cpu)) $($(target)_CLEAN.$(bld_type))
+_DIRS += $($(target)_BLDDIRS) $($(target)_BLDDIRS.$(bld_trg)) $($(target)_BLDDIRS.$(bld_trg).$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_cpu)) $($(target)_BLDDIRS.$(bld_type))
+_OBJS += $($(target)_OBJS_)
+
+endef
+
+
+
+#
+# LIBRARIES
+#
+
+## Library (one).
+# @param    $(target)   Normalized library (target) name.
+define def_lib
+# library basics
+## @todo prefix
+local bld_type    := $(firstword $($(target)_BLD_TYPE)     $(KBUILD_TYPE))
+local bld_trg     := $(firstword $($(target)_BLD_TRG)      $(KBUILD_TARGET))
+local bld_trg_arch:= $(firstword $($(target)_BLD_TRG_ARCH) $(KBUILD_TARGET_ARCH))
+local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU)  $(KBUILD_TARGET_CPU))
+local tool        := $(call _TARGET_TOOL,$(target),AR)
+ifeq ($(tool),)
+$(error kBuild: Library target $(target) does not have a tool defined!)
+endif
+local name        := $(firstword\
+	$($(target)_NAME.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg))\
+	$($(target)_NAME.$(bld_type))\
+	$($(target)_NAME)\
+	$(target))
+local outbase     := $(call TARGET_BASE,$(name),$(target))
+ifndef PATH_$(target)
+ PATH_$(target)   := $(patsubst %/,%,$(dir $(outbase)))
+else ifneq ($(PATH_$(target)),$(patsubst %/,%,$(dir $(outbase))))
+ $(error kBuild internal error: PATH_$(target)=$(PATH_$(target)) expected $(patsubst %/,%,$(dir $(outbase))))
+endif
+local suff        := $(firstword\
+	$($(target)_LIBSUFF.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_LIBSUFF.$(bld_trg))\
+	$($(target)_LIBSUFF)\
+	$(TOOL_$(tool)_ARLIBSUFF.$(bld_trg).$(bld_trg_arch))\
+	$(TOOL_$(tool)_ARLIBSUFF.$(bld_trg))\
+	$(TOOL_$(tool)_ARLIBSUFF)\
+	$(SUFF_LIB))
+local out         := $(outbase)$(suff)
+local defpath     := $(firstword $($(target)_PATH) $($(target)_DEFPATH))
+TARGET_$(target)  := $(out)
+# no local here - must be writable across some foreachs.
+othersrc          :=
+$(target)_OBJS_   :=
+
+# Do units pre source callouts.
+local units       := \
+	$($(target)_USES.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_USES.$(bld_trg_arch))\
+	$($(target)_USES.$(bld_trg))\
+	$($(target)_USES.$(bld_type))\
+	$($(target)_USES)
+$(foreach unit,$(units),$(evalval def_unit_$(unit)_target_pre))
+
+# source -> object
+$(evalval def_target_sources)
+
+# library linking
+local tool        := $(call _TARGET_TOOL,$(target),AR)
+local name        := $(firstword\
+	$($(target)_NAME.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg))\
+	$($(target)_NAME.$(bld_type))\
+	$($(target)_NAME)\
+	$(target))
+local outbase     := $(call TARGET_BASE,$(name),$(target))
+local flags       :=\
+	$(TOOL_$(tool)_ARFLAGS)\
+	$(TOOL_$(tool)_ARFLAGS.$(bld_type))\
+	$(ARFLAGS)\
+	$(ARFLAGS.$(bld_type))\
+	$($(target)_ARFLAGS)\
+	$($(target)_ARFLAGS.$(bld_type)) \
+	$($(target)_ARFLAGS.$(bld_trg)) \
+	$($(target)_ARFLAGS.$(bld_trg_arch)) \
+	$($(target)_ARFLAGS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_ARFLAGS.$(bld_trg_cpu))
+local dirdep      := $(call DIRDEP,$(dir $(out)))
+local deps        := \
+	$($(target)_DEPS.$(bld_trg_cpu)) \
+	$($(target)_DEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \
+	$($(target)_DEPS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_DEPS.$(bld_trg).$(bld_type)) \
+	$($(target)_DEPS.$(bld_trg_arch)) \
+	$($(target)_DEPS.$(bld_trg)) \
+	$($(target)_DEPS.$(bld_type)) \
+	$($(target)_DEPS) \
+	$($(target)_LNK_DEPS.$(bld_trg_cpu)) \
+	$($(target)_LNK_DEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \
+	$($(target)_LNK_DEPS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_LNK_DEPS.$(bld_trg).$(bld_type)) \
+	$($(target)_LNK_DEPS.$(bld_trg_arch)) \
+	$($(target)_LNK_DEPS.$(bld_trg)) \
+	$($(target)_LNK_DEPS.$(bld_type)) \
+	$($(target)_LNK_DEPS)
+local orderdeps   := \
+	$($(target)_ORDERDEPS.$(bld_trg_cpu)) \
+	$($(target)_ORDERDEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \
+	$($(target)_ORDERDEPS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_ORDERDEPS.$(bld_trg).$(bld_type)) \
+	$($(target)_ORDERDEPS.$(bld_trg_arch)) \
+	$($(target)_ORDERDEPS.$(bld_trg)) \
+	$($(target)_ORDERDEPS.$(bld_type)) \
+	$($(target)_ORDERDEPS) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg_cpu)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_type)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg_arch)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_type)) \
+	$($(target)_LNK_ORDERDEPS)
+
+# Adjust paths if we got a default path.
+ifneq ($(defpath),)
+ $(target)_OBJS_  := $(abspathex $($(target)_OBJS_),$(defpath))
+ local deps       := $(abspathex $(deps),$(defpath))
+ local orderdeps  := $(abspathex $(orderdeps),$(defpath))
+ othersrc := $(abspathex $(othersrc),$(defpath))
+endif
+
+
+# Custom pre-link actions.
+## @todo bld_trg_cpu is missing here.
+ifdef $(target)_PRE_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type))
+else ifdef $(target)_PRE_CMDS.$(bld_trg).$(bld_trg_arch)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg).$(bld_trg_arch))
+else ifdef $(target)_PRE_CMDS.$(bld_trg).$(bld_type)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg).$(bld_type))
+else ifdef $(target)_PRE_CMDS.$(bld_trg_arch)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg_arch))
+else ifdef $(target)_PRE_CMDS.$(bld_trg)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg))
+else ifdef $(target)_PRE_CMDS.$(bld_type)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_type))
+else ifdef $(target)_PRE_CMDS
+ local pre_cmds := $($(target)_PRE_CMDS)
+else ifdef PRE_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type))
+else ifdef PRE_CMDS.$(bld_trg).$(bld_trg_arch)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg).$(bld_trg_arch))
+else ifdef PRE_CMDS.$(bld_trg).$(bld_type)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg).$(bld_type))
+else ifdef PRE_CMDS.$(bld_trg_arch)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg_arch))
+else ifdef PRE_CMDS.$(bld_trg)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg))
+else ifdef PRE_CMDS.$(bld_type)
+ local pre_cmds := $(PRE_CMDS.$(bld_type))
+else
+ local pre_cmds := $(PRE_CMDS)
+endif
+
+# Custom post-link actions.
+ifdef $(target)_POST_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type))
+else ifdef $(target)_POST_CMDS.$(bld_trg).$(bld_trg_arch)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg).$(bld_trg_arch))
+else ifdef $(target)_POST_CMDS.$(bld_trg).$(bld_type)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg).$(bld_type))
+else ifdef $(target)_POST_CMDS.$(bld_trg_arch)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg_arch))
+else ifdef $(target)_POST_CMDS.$(bld_trg)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg))
+else ifdef $(target)_POST_CMDS.$(bld_type)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_type))
+else ifdef $(target)_POST_CMDS
+ local post_cmds := $($(target)_POST_CMDS)
+else ifdef POST_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type)
+ local post_cmds := $(POST_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type))
+else ifdef POST_CMDS.$(bld_trg).$(bld_trg_arch)
+ local post_cmds := $(POST_CMDS.$(bld_trg).$(bld_trg_arch))
+else ifdef POST_CMDS.$(bld_trg).$(bld_type)
+ local post_cmds := $(POST_CMDS.$(bld_trg).$(bld_type))
+else ifdef POST_CMDS.$(bld_trg_arch)
+ local post_cmds := $(POST_CMDS.$(bld_trg_arch))
+else ifdef POST_CMDS.$(bld_trg)
+ local post_cmds := $(POST_CMDS.$(bld_trg))
+else ifdef POST_CMDS.$(bld_type)
+ local post_cmds := $(POST_CMDS.$(bld_type))
+else
+ local post_cmds := $(POST_CMDS)
+endif
+
+# eliminate this guy?
+local objs = $($(target)_OBJS_)
+
+# dependency file
+local dep := $(out)$(SUFF_DEP)
+ifndef NO_LINK_CMDS_DEPS
+ _DEPFILES_INCLUDED += $(dep)
+ $(eval includedep $(dep))
+endif
+
+# check that the tool is defined.
+ifndef TOOL_$(tool)_LINK_LIBRARY_CMDS
+$(warning kBuild: tools: \
+	1 $($(target)_$(source)TOOL.$(bld_trg).$(bld_trg_arch)) \
+	2 $($(target)_$(source)TOOL.$(bld_trg)) \
+	3 $($(target)_$(source)TOOL) \
+	4 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
+	5 $($(target)_TOOL.$(bld_trg)) \
+	6 $($(target)_TOOL) \
+	7 $($(source)TOOL) \
+	8 $($(source)TOOL.$(bld_trg).$(bld_trg_arch)) \
+	9 $($(source)TOOL.$(bld_trg)) \
+	10 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
+	11 $(TOOL.$(bld_trg)) \
+	12 $(TOOL) )
+$(error kBuild: TOOL_$(tool)_LINK_LIBRARY_CMDS isn't defined! target=$(target) )
+endif
+
+# call the tool
+local cmds := $(TOOL_$(tool)_LINK_LIBRARY_CMDS)
+ifneq ($(pre_cmds),)
+ local cmds := $(TAB)$(pre_cmds)$(NL)$(TAB)$(cmds)
+endif
+ifneq ($(post_cmds),)
+ local cmds  := $(cmds)$(NL)$(TAB)$(post_cmds)
+endif
+$(target)_OUTPUT_ := $(TOOL_$(tool)_LINK_LIBRARY_OUTPUT)
+$(target)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_LINK_LIBRARY_OUTPUT_MAYBE)
+$(target)_DEPEND_ := $(TOOL_$(tool)_LINK_LIBRARY_DEPEND) $(deps) $($(target)_OBJS_)
+$(target)_DEPORD_ := $(TOOL_$(tool)_LINK_LIBRARY_DEPORD) $(dirdep) $(orderdeps)
+
+# generate the link rule.
+$(eval $(def_link_rule))
+
+# installing and globals
+$(evalval def_target_install_pluss)
+endef
+
+# Process libraries
+definst := $(PATH_LIB)
+typevar := _LIBS
+tool_do := LINK_LIBRARY
+mode := 0644
+$(foreach target, $(_ALL_LIBRARIES), $(evalval def_lib))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done library targets)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# Link operations.
+#
+
+##
+# Link prolog
+#
+# @param    $(target)   Normalized target name.
+# @param    $(EXT)      EXE,DLL,SYS.
+# @param    $(definst)  The default _INST value.
+# @param    $(typevar)  The name of the variable with all the root targets of its type.
+define def_link_common
+# basics
+local bld_type    := $(firstword $($(target)_BLD_TYPE)     $(KBUILD_TYPE))
+local bld_trg     := $(firstword $($(target)_BLD_TRG)      $(BUILD_$(bld_trg_base_var)))
+local bld_trg_arch:= $(firstword $($(target)_BLD_TRG_ARCH) $(BUILD_$(bld_trg_base_var)_ARCH))
+local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU)  $(BUILD_$(bld_trg_base_var)_CPU))
+
+local tool        := $(call _TARGET_TOOL,$(target),LD)
+local name        := $(firstword\
+	$($(target)_NAME.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg))\
+	$($(target)_NAME.$(bld_type))\
+	$($(target)_NAME)\
+	$(target))
+local outbase     := $(call TARGET_BASE,$(name),$(target))
+ifndef PATH_$(target)
+ PATH_$(target)   := $(patsubst %/,%,$(dir $(outbase)))
+else ifneq ($(PATH_$(target)),$(patsubst %/,%,$(dir $(outbase))))
+ $(error kBuild internal error: PATH_$(target)=$(PATH_$(target)) expected $(patsubst %/,%,$(dir $(outbase))))
+endif
+local suff        := $(firstword \
+	$($(target)_$(EXT)SUFF) \
+	$($(target)_$(EXT)SUFF) \
+	$(TOOL_$(tool)_LD$(EXT)SUFF) \
+	$($(EXTPRE)SUFF_$(EXT)))
+local out         := $(outbase)$(suff)
+TARGET_$(target)  := $(out)
+local defpath     := $(firstword $($(target)_PATH) $($(target)_DEFPATH))
+# no local here - must be writable across some foreachs.
+othersrc          :=
+$(target)_OBJS_   :=
+
+# Do units pre source callouts.
+local units       := \
+	$($(target)_USES.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_USES.$(bld_trg_arch))\
+	$($(target)_USES.$(bld_trg))\
+	$($(target)_USES.$(bld_type))\
+	$($(target)_USES)
+$(foreach unit,$(units),$(evalval def_unit_$(unit)_target_pre))
+
+# source -> object
+$(evalval def_target_sources)
+
+# more link stuff.
+local tool        := $(call _TARGET_TOOL,$(target),LD)
+local name        := $(firstword\
+	$($(target)_NAME.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg_arch))\
+	$($(target)_NAME.$(bld_trg))\
+	$($(target)_NAME.$(bld_type))\
+	$($(target)_NAME)\
+	$(target))
+local outbase     := $(call TARGET_BASE,$(name),$(target))
+local flags       :=\
+	$(TOOL_$(tool)_LDFLAGS)\
+	$(TOOL_$(tool)_LDFLAGS.$(bld_type))\
+	$(TOOL_$(tool)_LDFLAGS.$(bld_trg))\
+	$(TOOL_$(tool)_LDFLAGS.$(bld_trg_arch))\
+	$(TOOL_$(tool)_LDFLAGS.$(bld_trg).$(bld_trg_arch))\
+	$(TOOL_$(tool)_LDFLAGS.$(bld_trg_cpu))\
+	$(foreach sdk, $(SDKS) \
+	               $(SDKS.$(bld_type)) \
+	               $(SDKS.$(bld_trg)) \
+	               $(SDKS.$(bld_trg_arch)) \
+	               $(SDKS.$(bld_trg).$(bld_trg_arch)),\
+		$(SDK_$(sdk)_LDFLAGS)\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_type))\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_trg))\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_trg_cpu)))\
+	$(LDFLAGS)\
+	$(LDFLAGS.$(bld_type))\
+	$(LDFLAGS.$(bld_trg))\
+	$(LDFLAGS.$(bld_trg_arch))\
+	$(LDFLAGS.$(bld_trg).$(bld_trg_arch))\
+	$(LDFLAGS.$(bld_trg_cpu))\
+	$(foreach sdk, $($(target)_SDKS) \
+	               $($(target)_SDKS.$(bld_type)) \
+	               $($(target)_SDKS.$(bld_trg)) \
+	               $($(target)_SDKS.$(bld_trg_arch)) \
+	               $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)),\
+		$(SDK_$(sdk)_LDFLAGS)\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_type))\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_trg))\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_LDFLAGS.$(bld_trg_cpu)))\
+	$($(target)_LDFLAGS)\
+	$($(target)_LDFLAGS.$(bld_type))\
+	$($(target)_LDFLAGS.$(bld_trg))\
+	$($(target)_LDFLAGS.$(bld_trg_arch))\
+	$($(target)_LDFLAGS.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_LDFLAGS.$(bld_trg_cpu))
+local libs        :=\
+	$($(target)_LIBS.$(bld_trg_cpu))\
+	$($(target)_LIBS.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_LIBS.$(bld_trg_arch))\
+	$($(target)_LIBS.$(bld_trg))\
+	$($(target)_LIBS.$(bld_type))\
+	$($(target)_LIBS)\
+	$(foreach sdk, $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
+		       $($(target)_SDKS.$(bld_trg_arch)) \
+		       $($(target)_SDKS.$(bld_trg)) \
+		       $($(target)_SDKS.$(bld_type)) \
+		       $($(target)_SDKS),\
+		$(SDK_$(sdk)_LIBS.$(bld_trg_cpu))\
+		$(SDK_$(sdk)_LIBS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_LIBS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_LIBS.$(bld_trg))\
+		$(SDK_$(sdk)_LIBS.$(bld_type))\
+		$(SDK_$(sdk)_LIBS))\
+	$(LIBS.$(bld_trg_cpu))\
+	$(LIBS.$(bld_trg).$(bld_trg_arch))\
+	$(LIBS.$(bld_trg_arch))\
+	$(LIBS.$(bld_trg))\
+	$(LIBS.$(bld_type))\
+	$(LIBS)\
+	$(foreach sdk, $(SDKS.$(bld_trg).$(bld_trg_arch)) \
+	               $(SDKS.$(bld_trg_arch)) \
+	               $(SDKS.$(bld_trg)) \
+	               $(SDKS.$(bld_type)) \
+	               $(SDKS),\
+		$(SDK_$(sdk)_LIBS.$(bld_trg_cpu))\
+		$(SDK_$(sdk)_LIBS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_LIBS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_LIBS.$(bld_trg))\
+		$(SDK_$(sdk)_LIBS.$(bld_type))\
+		$(SDK_$(sdk)_LIBS))\
+	$(TOOL_$(tool)_LIBS.$(bld_trg_cpu))\
+	$(TOOL_$(tool)_LIBS.$(bld_trg).$(bld_trg_arch))\
+	$(TOOL_$(tool)_LIBS.$(bld_trg_arch))\
+	$(TOOL_$(tool)_LIBS.$(bld_trg))\
+	$(TOOL_$(tool)_LIBS.$(bld_type))\
+	$(TOOL_$(tool)_LIBS)
+local libpath    :=\
+	$($(target)_LIBPATH.$(bld_trg_cpu))\
+	$($(target)_LIBPATH.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_LIBPATH.$(bld_trg_arch))\
+	$($(target)_LIBPATH.$(bld_trg))\
+	$($(target)_LIBPATH.$(bld_type))\
+	$($(target)_LIBPATH)\
+	$(foreach sdk, $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
+		       $($(target)_SDKS.$(bld_trg_arch)) \
+		       $($(target)_SDKS.$(bld_trg)) \
+		       $($(target)_SDKS.$(bld_type)) \
+		       $($(target)_SDKS),\
+		$(SDK_$(sdk)_LIBPATH.$(bld_trg_cpu))\
+		$(SDK_$(sdk)_LIBPATH.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_LIBPATH.$(bld_trg_arch))\
+		$(SDK_$(sdk)_LIBPATH.$(bld_trg))\
+		$(SDK_$(sdk)_LIBPATH.$(bld_type))\
+		$(SDK_$(sdk)_LIBPATH))\
+	$(LIBPATH.$(bld_trg_cpu))\
+	$(LIBPATH.$(bld_trg).$(bld_trg_arch))\
+	$(LIBPATH.$(bld_trg_arch))\
+	$(LIBPATH.$(bld_trg))\
+	$(LIBPATH.$(bld_type))\
+	$(LIBPATH)\
+	$(foreach sdk, $(SDKS.$(bld_trg).$(bld_trg_arch)) \
+	               $(SDKS.$(bld_trg_arch)) \
+	               $(SDKS.$(bld_trg)) \
+	               $(SDKS.$(bld_type)) \
+	               $(SDKS),\
+		$(SDK_$(sdk)_LIBPATH.$(bld_trg_cpu))\
+		$(SDK_$(sdk)_LIBPATH.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_LIBPATH.$(bld_trg_arch))\
+		$(SDK_$(sdk)_LIBPATH.$(bld_trg))\
+		$(SDK_$(sdk)_LIBPATH.$(bld_type))\
+		$(SDK_$(sdk)_LIBPATH))\
+	$(TOOL_$(tool)_LIBPATH.$(bld_trg_cpu))\
+	$(TOOL_$(tool)_LIBPATH.$(bld_trg).$(bld_trg_arch))\
+	$(TOOL_$(tool)_LIBPATH.$(bld_trg_arch))\
+	$(TOOL_$(tool)_LIBPATH.$(bld_trg))\
+	$(TOOL_$(tool)_LIBPATH.$(bld_type))\
+	$(TOOL_$(tool)_LIBPATH)
+local dirdep      := $(call DIRDEP,$(dir $(out)))
+local deps        := \
+	$($(target)_DEPS.$(bld_trg_cpu)) \
+	$($(target)_DEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \
+	$($(target)_DEPS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_DEPS.$(bld_trg).$(bld_type)) \
+	$($(target)_DEPS.$(bld_trg_arch)) \
+	$($(target)_DEPS.$(bld_trg)) \
+	$($(target)_DEPS.$(bld_type)) \
+	$($(target)_DEPS) \
+	$($(target)_LNK_DEPS.$(bld_trg_cpu)) \
+	$($(target)_LNK_DEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \
+	$($(target)_LNK_DEPS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_LNK_DEPS.$(bld_trg).$(bld_type)) \
+	$($(target)_LNK_DEPS.$(bld_trg_arch)) \
+	$($(target)_LNK_DEPS.$(bld_trg)) \
+	$($(target)_LNK_DEPS.$(bld_type)) \
+	$($(target)_LNK_DEPS)
+local orderdeps   := \
+	$($(target)_ORDERDEPS.$(bld_trg_cpu)) \
+	$($(target)_ORDERDEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \
+	$($(target)_ORDERDEPS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_ORDERDEPS.$(bld_trg).$(bld_type)) \
+	$($(target)_ORDERDEPS.$(bld_trg_arch)) \
+	$($(target)_ORDERDEPS.$(bld_trg)) \
+	$($(target)_ORDERDEPS.$(bld_type)) \
+	$($(target)_ORDERDEPS) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg_cpu)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_type)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg_arch)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_trg)) \
+	$($(target)_LNK_ORDERDEPS.$(bld_type)) \
+	$($(target)_LNK_ORDERDEPS)
+
+# Adjust paths if we got a default path.
+ifneq ($(defpath),)
+ local libpath    := $(abspathex $(libpath),$(defpath))
+ $(target)_OBJS_  := $(abspathex $($(target)_OBJS_),$(defpath))
+ local deps       := $(abspathex $(deps),$(defpath))
+ local orderdeps  := $(abspathex $(orderdeps),$(defpath))
+ othersrc := $(abspathex $(othersrc),$(defpath))
+ # libs are not subject to this because of the the -l<lib> stuff. Use $(<target>_DEFPATH)/lib if relative to current dir!
+endif
+
+# Custom pre-link actions.
+ifdef $(target)_PRE_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type))
+else ifdef $(target)_PRE_CMDS.$(bld_trg).$(bld_trg_arch)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg).$(bld_trg_arch))
+else ifdef $(target)_PRE_CMDS.$(bld_trg).$(bld_type)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg).$(bld_type))
+else ifdef $(target)_PRE_CMDS.$(bld_trg_arch)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg_arch))
+else ifdef $(target)_PRE_CMDS.$(bld_trg)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_trg))
+else ifdef $(target)_PRE_CMDS.$(bld_type)
+ local pre_cmds := $($(target)_PRE_CMDS.$(bld_type))
+else ifdef $(target)_PRE_CMDS
+ local pre_cmds := $($(target)_PRE_CMDS)
+else ifdef PRE_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type))
+else ifdef PRE_CMDS.$(bld_trg).$(bld_trg_arch)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg).$(bld_trg_arch))
+else ifdef PRE_CMDS.$(bld_trg).$(bld_type)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg).$(bld_type))
+else ifdef PRE_CMDS.$(bld_trg_arch)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg_arch))
+else ifdef PRE_CMDS.$(bld_trg)
+ local pre_cmds := $(PRE_CMDS.$(bld_trg))
+else ifdef PRE_CMDS.$(bld_type)
+ local pre_cmds := $(PRE_CMDS.$(bld_type))
+else
+ local pre_cmds := $(PRE_CMDS)
+endif
+
+# Custom post-link actions.
+ifdef $(target)_POST_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type))
+else ifdef $(target)_POST_CMDS.$(bld_trg).$(bld_trg_arch)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg).$(bld_trg_arch))
+else ifdef $(target)_POST_CMDS.$(bld_trg).$(bld_type)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg).$(bld_type))
+else ifdef $(target)_POST_CMDS.$(bld_trg_arch)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg_arch))
+else ifdef $(target)_POST_CMDS.$(bld_trg)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_trg))
+else ifdef $(target)_POST_CMDS.$(bld_type)
+ local post_cmds := $($(target)_POST_CMDS.$(bld_type))
+else ifdef $(target)_POST_CMDS
+ local post_cmds := $($(target)_POST_CMDS)
+else ifdef POST_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type)
+ local post_cmds := $(POST_CMDS.$(bld_trg).$(bld_trg_arch).$(bld_type))
+else ifdef POST_CMDS.$(bld_trg).$(bld_trg_arch)
+ local post_cmds := $(POST_CMDS.$(bld_trg).$(bld_trg_arch))
+else ifdef POST_CMDS.$(bld_trg).$(bld_type)
+ local post_cmds := $(POST_CMDS.$(bld_trg).$(bld_type))
+else ifdef POST_CMDS.$(bld_trg_arch)
+ local post_cmds := $(POST_CMDS.$(bld_trg_arch))
+else ifdef POST_CMDS.$(bld_trg)
+ local post_cmds := $(POST_CMDS.$(bld_trg))
+else ifdef POST_CMDS.$(bld_type)
+ local post_cmds := $(POST_CMDS.$(bld_type))
+else
+ local post_cmds := $(POST_CMDS)
+endif
+
+# eliminate this guy?
+local objs = $($(target)_OBJS_)
+
+# installation targets
+ifeq ($(strip $($(target)_NOINST) $($(target)_NOINST.$(bld_trg)) $($(target)_NOINST.$(bld_trg).$(bld_trg_arch)) $($(target)_NOINST.$(bld_trg).$(bld_trg_arch).$(bld_type))  $($(target)_NOINST.$(bld_trg_arch)) $($(target)_NOINST.$(bld_trg_cpu)) $($(target)_NOINST.$(bld_trg_type))),)
+ ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_trg_arch))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_trg_arch)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg).$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg).$(bld_type)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg_arch))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg_arch)))
+ else ifneq ($(strip $($(target)_INST.$(bld_trg))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_trg)))
+ else ifneq ($(strip $($(target)_INST.$(bld_type))),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST.$(bld_type)))
+ else ifneq ($(strip $($(target)_INST)),)
+  local inst := $(addprefix $(PATH_INS)/,$($(target)_INST))
+ else
+  local inst := $(definst)/
+ endif
+ INSTARGET_$(target) := $(patsubst %/,%/$(notdir $(out)),$(inst))
+ ifdef KBUILD_DO_AUTO_INSTALL
+  $(typevar)  += $(INSTARGET_$(target))
+ else
+  $(typevar)  += $(out)
+ endif
+ # generate the install rule
+$(eval $(def_link_install_rule))
+
+else # NOINST
+ INSTARGET_$(target) :=
+ $(typevar)  += $(out)
+endif # NOINST
+
+# dependency file
+local dep := $(outbase)$(SUFF_DEP)
+ifndef NO_LINK_CMDS_DEPS
+ _DEPFILES_INCLUDED += $(dep)
+ $(eval includedep $(dep))
+endif
+
+# check that the tool is defined.
+ifndef TOOL_$(tool)_$(tool_do)_CMDS
+$(warning kBuild: tools: \
+	1 $($(target)_$(source)TOOL.$(bld_trg).$(bld_trg_arch)) \
+	2 $($(target)_$(source)TOOL.$(bld_trg)) \
+	3 $($(target)_$(source)TOOL) \
+	4 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
+	5 $($(target)_TOOL.$(bld_trg)) \
+	6 $($(target)_TOOL) \
+	7 $($(source)TOOL.$(bld_trg).$(bld_trg_arch)) \
+	8 $($(source)TOOL.$(bld_trg)) \
+	9 $($(source)TOOL) \
+	10 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
+	11 $(TOOL.$(bld_trg)) \
+	12 $(TOOL) )
+$(error kBuild: TOOL_$(tool)_$(tool_do)_CMDS isn't defined! target=$(target) )
+endif
+
+# call the tool
+local cmds   := $(TOOL_$(tool)_$(tool_do)_CMDS)
+ifneq ($(pre_cmds),)
+ local cmds  := $(TAB)$(pre_cmds)$(NL)$(TAB)$(cmds)
+endif
+ifneq ($(post_cmds),)
+ local cmds  := $(cmds)$(NL)$(TAB)$(post_cmds)
+endif
+$(target)_OUTPUT_ := $(TOOL_$(tool)_$(tool_do)_OUTPUT)
+$(target)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_$(tool_do)_OUTPUT_MAYBE)
+$(target)_DEPEND_ := $(TOOL_$(tool)_$(tool_do)_DEPEND) $(deps) $($(target)_OBJS_)
+$(target)_DEPORD_ := $(TOOL_$(tool)_$(tool_do)_DEPORD) $(dirdep) $(orderdeps)
+
+# generate the link rule.
+$(eval $(def_link_rule))
+
+
+# Update globals.
+_OBJS += $($(target)_OBJS_)
+_OUT_FILES += $($(target)_OUTPUT_) $(out)
+_CLEAN_FILES += $($(target)_CLEAN) $($(target)_CLEAN.$(bld_trg)) $($(target)_CLEAN.$(bld_trg).$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_cpu)) $($(target)_CLEAN.$(bld_type))
+_DIRS += $($(target)_BLDDIRS) $($(target)_BLDDIRS.$(bld_trg)) $($(target)_BLDDIRS.$(bld_trg).$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_cpu)) $($(target)_BLDDIRS.$(bld_type))
+_INSTALLS_FILES += $(INSTARGET_$(target))
+
+endef
+
+
+#
+# BLDPROGS
+#
+
+## Build program (one).
+# @param    $(target)   Normalized target (program) name.
+define def_bldprog
+
+# set NOINST if not forced installation.
+ifndef $(target)_INST
+$(target)_NOINST := 1
+endif
+
+# do the usual stuff.
+$(evalval def_link_common)
+
+endef
+
+# Process build programs.
+EXT     := EXE
+EXTPRE  := HOST
+tool_do := LINK_PROGRAM
+definst := $(PATH_BIN)
+typevar := _BLDPROGS
+mode    := 0755
+bld_trg_base_var := PLATFORM
+$(foreach target, $(_ALL_BLDPROGS), $(evalval def_bldprog))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done build program targets)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# DLLS
+#
+
+# Process dlls
+EXT     := DLL
+EXTPRE  :=
+tool_do := LINK_DLL
+definst := $(PATH_DLL)
+typevar := _DLLS
+mode    := 0644
+bld_trg_base_var := TARGET
+$(foreach target, $(_ALL_DLLS), $(evalval def_link_common))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done dll targets)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# IMPORT LIBRARIES
+#
+#   - On OS/2 and windows these are libraries.
+#   - On other platforms they are fake DLLs.
+#
+EXTPRE  :=
+typevar := _IMPORT_LIBS
+mode    := 0644
+bld_trg_base_var := TARGET
+ifeq ($(filter-out nt os2 win win64 win32,$(KBUILD_TARGET)),)
+ EXT     := LIB
+ tool_do := LINK_LIBRARY
+ definst := $(PATH_LIB)
+ $(foreach target, $(_ALL_IMPORT_LIBS), $(evalval def_lib))
+else
+ EXT     := DLL
+ tool_do := LINK_DLL
+ definst := $(PATH_DLL)
+ $(foreach target, $(_ALL_IMPORT_LIBS), $(evalval def_link_common))
+endif
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done import library targets)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# PROGRAMS
+#
+
+# Process programs
+EXT     := EXE
+EXTPRE  :=
+tool_do := LINK_PROGRAM
+definst := $(PATH_BIN)
+typevar := _PROGRAMS
+mode    := 0755
+bld_trg_base_var := TARGET
+$(foreach target, $(_ALL_PROGRAMS), $(evalval def_link_common))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done program targets)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# SYSMODS
+#
+
+# Process sysmods
+EXT     := SYS
+EXTPRE  :=
+tool_do := LINK_SYSMOD
+definst := $(PATH_SYS)
+typevar := _SYSMODS
+mode    := 0644
+bld_trg_base_var := TARGET
+$(foreach target, $(_ALL_SYSMODS), $(evalval def_link_common))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done sysmod targets)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# OTHERS
+#
+_OTHERS = $(OTHERS) $(OTHERS.$(KBUILD_TARGET)) $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))
+
+
+#
+# INSTALLS
+#
+
+## generate the install rule
+define def_install_src_rule
+# the install rule
+$(insdst) : $(srcsrc) | $(call DIRDEP,$(dir $(insdst)))
+	%$$(call MSG_INST_FILE,$(srcsrc),$(insdst))
+	$$(QUIET)$(inscmd)
+endef
+
+## install one file
+define def_install_src
+
+# deal with '=>' in the source file name.
+local srcdst := $(subst =>, ,$(src))
+local srcsrc := $(firstword $(srcdst))
+local srcdstdir := $(dir $(word 2,$(srcdst)))
+local srcdst := $(word $(words $(srcdst)),$(srcdst))
+
+# _INSTFUN
+ifdef $(srcsrc)_INSTFUN
+ local instfun := $(srcsrc)_INSTFUN
+else ifdef $(target)_INSTFUN
+ local instfun := $(target)_INSTFUN
+else
+ local instfun := _INSTALL_FILE
+endif
+
+# _INST
+ifdef $(srcsrc)_INST
+ local inst := $(patsubst %/,%,$($(srcsrc)_INST))/$(dir $(srcdstdir))
+else ifdef $(target)_INST
+ local inst := $(patsubst %/,%,$($(target)_INST))/$(dir $(srcdstdir))
+else
+ local inst := $(dir $(srcdstdir))
+endif
+
+# calc target
+local insdst := $(call $(instfun),$(srcdst),$(target),$(inst),$(PATH_INS))
+#$(warning instfun=$(instfun) srcdst=$(srcdst) target=$(target) inst=$(inst) => insdst=$(insdst))
+
+# mode, uid and gid
+local mode := $(firstword \
+	$($(target)_$(srcsrc)_MODE.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcsrc)_MODE.$(bld_trg)) \
+	$($(target)_$(srcsrc)_MODE) \
+	$($(target)_$(srcdst)_MODE.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcdst)_MODE.$(bld_trg)) \
+	$($(target)_$(srcdst)_MODE) \
+	$($(srcsrc)_MODE.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcsrc)_MODE.$(bld_trg)) \
+	$($(srcsrc)_MODE) \
+	$($(srcdst)_MODE.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcdst)_MODE.$(bld_trg)) \
+	$($(srcdst)_MODE) \
+	$($(target)_MODE.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_MODE.$(bld_trg)) \
+	$($(target)_MODE))
+local uid := $(firstword \
+	$($(target)_$(srcsrc)_UID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcsrc)_UID.$(bld_trg)) \
+	$($(target)_$(srcsrc)_UID) \
+	$($(target)_$(srcdst)_UID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcdst)_UID.$(bld_trg)) \
+	$($(target)_$(srcdst)_UID) \
+	$($(srcsrc)_UID.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcsrc)_UID.$(bld_trg)) \
+	$($(srcsrc)_UID) \
+	$($(srcdst)_UID.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcdst)_UID.$(bld_trg)) \
+	$($(srcdst)_UID) \
+	$($(target)_UID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_UID.$(bld_trg)) \
+	$($(target)_UID))
+local gid := $(firstword \
+	$($(target)_$(srcsrc)_GID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcsrc)_GID.$(bld_trg)) \
+	$($(target)_$(srcsrc)_GID) \
+	$($(target)_$(srcdst)_GID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcdst)_GID.$(bld_trg)) \
+	$($(target)_$(srcdst)_GID) \
+	$($(srcsrc)_GID.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcsrc)_GID.$(bld_trg)) \
+	$($(srcsrc)_GID) \
+	$($(srcdst)_GID.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcdst)_GID.$(bld_trg)) \
+	$($(srcdst)_GID) \
+	$($(target)_GID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_GID.$(bld_trg)) \
+	$($(target)_GID))
+local flags := \
+	$($(target)_IFFLAGS) \
+	$($(target)_IFFLAGS.$(bld_trg)) \
+	$($(target)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcdst)_IFFLAGS) \
+	$($(srcdst)_IFFLAGS.$(bld_trg)) \
+	$($(srcdst)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcsrc)_IFFLAGS) \
+	$($(srcsrc)_IFFLAGS.$(bld_trg)) \
+	$($(srcsrc)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcdst)_IFFLAGS) \
+	$($(target)_$(srcdst)_IFFLAGS.$(bld_trg)) \
+	$($(target)_$(srcdst)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcsrc)_IFFLAGS) \
+	$($(target)_$(srcsrc)_IFFLAGS.$(bld_trg)) \
+	$($(target)_$(srcsrc)_IFFLAGS.$(bld_trg).$(bld_trg_arch))
+clean_files += \
+	$($(srcdst)_CLEAN) \
+	$($(srcdst)_CLEAN.$(bld_trg)) \
+	$($(srcdst)_CLEAN.$(bld_trg).$(bld_trg_arch)) \
+	$($(srcsrc)_CLEAN) \
+	$($(srcsrc)_CLEAN.$(bld_trg)) \
+	$($(srcsrc)_CLEAN.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcdst)_CLEAN) \
+	$($(target)_$(srcdst)_CLEAN.$(bld_trg)) \
+	$($(target)_$(srcdst)_CLEAN.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(srcsrc)_CLEAN) \
+	$($(target)_$(srcsrc)_CLEAN.$(bld_trg)) \
+	$($(target)_$(srcsrc)_CLEAN.$(bld_trg).$(bld_trg_arch))
+
+
+# Adjust the source if we got a default PATH. (This must be done this late!)
+local defpath := $(firstword $($(target)_PATH) $($(target)_DEFPATH))
+ifneq ($(defpath),)
+ local srcsrc := $(abspathex $(srcsrc),$(defpath))
+endif
+
+# create the command
+ifdef $(srcsrc)_INSTALLER
+ local inscmd := $(call $(srcsrc)_INSTALLER,$(srcsrc),$(insdst),$(target),$(flags))
+else ifdef $(target)_INSTALLER
+ local inscmd := $(call $(target)_INSTALLER,$(srcsrc),$(insdst),$(target),$(flags))
+else
+ local inscmd := $$(INSTALL)\
+		$(if $(uid),-o $(uid))\
+		$(if $(gid),-g $(gid))\
+		$(if $(mode),-m $(mode))\
+		$(flags) -- \
+		$(srcsrc) $(insdst)
+endif
+
+# generate the rule (need double evaluation here)
+$(eval $(def_install_src_rule))
+
+INSTARGET_$(target) += $(insdst)
+endef
+
+
+## generate the symlink rule
+define def_install_symlink_rule
+# the install rule
+$(insdst) : | $(call DIRDEP,$(dir $(insdst)))
+	%$$(call MSG_INST_SYM,$(insdst),$(symdst))
+	$$(QUIET)$$(RM) -f -- $$@
+	$$(QUIET)$$(LN_SYMLINK) $(symdst) $(insdst)
+endef
+
+## create one symlink
+define def_install_symlink
+
+# deal with '=>' in the source file name.
+local symdst := $(subst =>, ,$(src))
+local symlnk := $(firstword $(symdst))
+local symdst := $(word $(words $(symdst)),$(symdst))
+
+# _INSTFUN
+ifdef $(symlnk)_INSTFUN
+ local instfun := $(symlnk)_INSTFUN
+else ifdef $(target)_INSTFUN
+ local instfun := $(target)_INSTFUN
+else
+ local instfun := _INSTALL_FILE
+endif
+
+# _INST
+ifdef $(symlnk)_INST
+ local inst := $(patsubst %/,%,$($(symlnk)_INST))/$(dir $(symlnk))
+else ifdef $(target)_INST
+ local inst := $(patsubst %/,%,$($(target)_INST))/$(dir $(symlnk))
+else
+ local inst := $(dir $(symlnk))
+endif
+
+# calc target
+local insdst := $(call $(instfun),$(symlnk),$(target),$(inst),$(PATH_INS))
+#$(warning symlnk=$(symlnk) symdst=$(symdst) insdst=$(insdst) instfun=$(instfun) inst='$(inst)')
+
+# generate the rule (need double evaluation here)
+$(eval $(def_install_symlink_rule))
+
+INSTARGET_$(target) += $(insdst)
+endef
+
+
+## generate the install rule
+define def_install_directory_rule
+# the install rule
+$(insdst):
+	%$$(call MSG_INST_DIR,$(insdst))
+	$$(QUIET)$$(INSTALL) -d \
+		$(if $(uid),-o $(uid))\
+		$(if $(gid),-g $(gid))\
+		$(if $(mode),-m $(mode))\
+		$(flags) -- \
+		$(insdst)
+
+.NOTPARALLEL: $(insdst)
+endef
+
+
+## create one directory
+define def_install_directory
+
+# _INST
+ifdef $(directory)_INST
+ local inst := $(PATH_INS)/$(patsubst %/,%,$($(directory)_INST))
+else ifdef $(target)_INST
+ local inst := $(PATH_INS)/$(patsubst %/,%,$($(target)_INST))
+else
+ local inst := $(PATH_INS)
+endif
+
+local mode := $(firstword \
+	$($(target)_$(directory)_MODE.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(directory)_MODE.$(bld_trg)) \
+	$($(target)_$(directory)_MODE) \
+	$($(directory)_MODE.$(bld_trg).$(bld_trg_arch)) \
+	$($(directory)_MODE.$(bld_trg)) \
+	$($(directory)_MODE) \
+	$($(target)_MODE.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_MODE.$(bld_trg)) \
+	$($(target)_MODE))
+local uid := $(firstword \
+	$($(target)_$(directory)_UID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(directory)_UID.$(bld_trg)) \
+	$($(target)_$(directory)_UID) \
+	$($(directory)_UID.$(bld_trg).$(bld_trg_arch)) \
+	$($(directory)_UID.$(bld_trg)) \
+	$($(directory)_UID) \
+	$($(target)_UID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_UID.$(bld_trg)) \
+	$($(target)_UID))
+local gid := $(firstword \
+	$($(target)_$(directory)_GID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(directory)_GID.$(bld_trg)) \
+	$($(target)_$(directory)_GID) \
+	$($(directory)_GID.$(bld_trg).$(bld_trg_arch)) \
+	$($(directory)_GID.$(bld_trg)) \
+	$($(directory)_GID) \
+	$($(target)_GID.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_GID.$(bld_trg)) \
+	$($(target)_GID))
+local flags := \
+	$($(target)_IDFLAGS)\
+	$($(target)_IDFLAGS.$(bld_trg)) \
+	$($(target)_IDFLAGS.$(bld_trg).$(bld_trg_arch)) \
+	$($(directory)_IDFLAGS) \
+	$($(directory)_IDFLAGS.$(bld_trg)) \
+	$($(directory)_IDFLAGS.$(bld_trg).$(bld_trg_arch)) \
+	$($(target)_$(directory)_IDFLAGS) \
+	$($(target)_$(directory)_IDFLAGS.$(bld_trg)) \
+	$($(target)_$(directory)_IDFLAGS.$(bld_trg).$(bld_trg_arch))
+
+local insdst := $(inst)/$(directory)/
+#$(warning directory=$(directory) inst=$(inst) insdst=$(insdst) mode=$(mode) gid=$(gid) uid=$(uid))
+
+# generate the rule (need double evaluation here)
+$(eval $(def_install_directory_rule))
+
+INSTARGET_DIRS_$(target) += $(insdst)
+endef
+
+
+## process one install target.
+define def_install
+# the basics.
+local bld_type  := $(firstword $($(target)_BLD_TYPE)     $(KBUILD_TYPE))
+local bld_trg   := $(firstword $($(target)_BLD_TRG)      $(KBUILD_TARGET))
+local bld_trg_arch:= $(firstword $($(target)_BLD_TRG_ARCH) $(KBUILD_TARGET_ARCH))
+local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU)  $(KBUILD_TARGET_CPU))
+
+INSTARGET_$(target) := $($(target)_GOALS)
+INSTARGET_DIRS_$(target) :=
+local outbase := $(call TARGET_BASE,$(target),$(target))
+ifndef PATH_$(target)
+ PATH_$(target) := $(patsubst %/,%,$(dir $(outbase)))
+else ifneq ($(PATH_$(target)),$(patsubst %/,%,$(dir $(outbase))))
+ $(error kBuild internal error: PATH_$(target)=$(PATH_$(target)) expected $(patsubst %/,%,$(dir $(outbase))))
+endif
+
+local clean_files := $($(target)_CLEAN) $($(target)_CLEAN.$(bld_trg)) $($(target)_CLEAN.$(bld_trg).$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_cpu)) $($(target)_CLEAN.$(bld_type))
+
+$(foreach directory,$($(target)_DIRS) $($(target)_DIRS.$(bld_trg)) $($(target)_DIRS.$(bld_trg).$(bld_trg_arch)) $($(target)_DIRS.$(bld_trg_arch)) $($(target)_DIRS.$(bld_trg_cpu)) $($(target)_DIRS.$(bld_type)), \
+	$(evalval def_install_directory))
+
+$(foreach src,$($(target)_SOURCES) $($(target)_SOURCES.$(bld_trg)) $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)) $($(target)_SOURCES.$(bld_trg_arch)) $($(target)_SOURCES.$(bld_trg_cpu)) $($(target)_SOURCES.$(bld_type)), \
+	$(evalval def_install_src))
+
+$(foreach src,$($(target)_SYMLINKS) $($(target)_SYMLINKS.$(bld_trg)) $($(target)_SYMLINKS.$(bld_trg).$(bld_trg_arch)) $($(target)_SYMLINKS.$(bld_trg_arch)) $($(target)_SYMLINKS.$(bld_trg_cpu)) $($(target)_SYMLINKS.$(bld_type)), \
+	$(evalval def_install_symlink))
+
+# the collection target
+TARGET_$(target) := $(PATH_TARGET)/$(target).ins
+$(TARGET_$(target)): $(INSTARGET_$(target)) | $(INSTARGET_DIRS_$(target)) $(call DIRDEP,$(PATH_TARGET))
+	@$(QUIET2)$(APPEND) $@
+
+$(target): $(TARGET_$(target))
+
+_INSTALLS += $(TARGET_$(target))
+_INSTALLS_FILES += $(INSTARGET_$(target))
+_INSTALLS_DIRS += $(INSTARGET_DIRS_$(target))
+_CLEAN_FILES += $(clean_files)
+_DIRS += $(PATH_$(target)) $($(target)_BLDDIRS) $($(target)_BLDDIRS.$(bld_trg)) $($(target)_BLDDIRS.$(bld_trg).$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_cpu)) $($(target)_BLDDIRS.$(bld_type))
+endef
+
+## process all install targets
+$(foreach target, $(_ALL_INSTALLS), \
+	$(evalvalctx def_install))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done install targets)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+#
+# TESTING
+#
+_TESTING += $(TESTING) $(TESTING.$(KBUILD_TARGET)) $(TESTING.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(TESTING.$(KBUILD_TARGET_ARCH)) $(TESTING.$(KBUILD_TARGET_CPU))
+
+
+#
+# PACKING
+#
+_PACKING += $(PACKING) $(PACKING.$(KBUILD_TARGET)) $(PACKING.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PACKING.$(KBUILD_TARGET_ARCH)) $(PACKING.$(KBUILD_TARGET_CPU))
+
+
+#
+# DOCS
+#
+
+
+#
+# DIRECTORIES
+#
+_DIR_ALL := $(sort $(addsuffix /,$(patsubst %/,%,$(_DIRS))) $(dir $(_OUT_FILES) $(_OBJS) $(_INSTALLS_FILES)))
+$(foreach directory,$(_INSTALLS_DIRS), $(eval _DIR_ALL := $(filter-out $(directory),$(_DIR_ALL))))
+
+
+define def_mkdir_rule
+$(directory):
+	%$$(call MSG_MKDIR,$$@)
+	$$(QUIET)$$(MKDIR) -p -- $$@
+endef
+
+$(foreach directory,$(_DIR_ALL),$(eval $(def_mkdir_rule)))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done directories)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# NOTHING
+#
+do-nothing:
+ifdef KBUILD_PROFILE_SELF
+	@$(ECHO) 'prof: $(int-sub $(nanots ), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(nanots ), $(_KBUILD_TS_PREV)) - executing $@'
+	@$(ECHO) 'stat: $(make-stats )'
+endif
+	%$(call MSG_NOTHING)
+
+
+#
+# CLEAN UP
+#
+do-clean:
+	%$(call MSG_CLEAN)
+	$(QUIET)$(RM) -f -- $(_OUT_FILES) $(_OBJS) $(_DEPFILES) $(_DEPFILES_INCLUDED) $(_CLEAN_FILES) $(OTHER_CLEAN)
+	$(QUIET)$(RMDIR) -p --ignore-fail-on-non-empty --ignore-fail-on-not-exist -- $(rsort $(dir $(_OUT_FILES) $(_OBJS) $(_DEPFILES) $(_DEPFILES_INCLUDED) $(_CLEAN_FILES) $(OTHER_CLEAN)))
+
+
+
+#
+# PASSES (including directory and makefile walking)
+#
+
+#
+# First, check whether we need to order the passes explicitly or not.
+# This depends on whether we're a leaf makefile or not. A leaf will
+# know all its dependencies, while a recursive one relies on the
+# order sub-directories and other makefiles are executed it.
+#
+
+## Setup a pass and check for optimizations.
+# @param	$(PASS)		Uppercase pass name.
+define def_pass_setup_and_optimize
+
+# The setup. ## @todo This is looks a bit weird...
+ifndef SUBDIRS_$(PASS)
+ SUBDIRS_$(PASS)          := $(SUBDIRS)          $(SUBDIRS.$(KBUILD_TARGET))          $(SUBDIRS.$(KBUILD_TARGET.$(KBUILD_TARGET_ARCH)))
+endif
+ifndef SUBDIRS_AFTER_$(PASS)
+ SUBDIRS_AFTER_$(PASS)    := $(SUBDIRS_AFTER)    $(SUBDIRS_AFTER.$(KBUILD_TARGET))    $(SUBDIRS_AFTER.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))
+endif
+ifndef MAKEFILES_BEFORE_$(PASS)
+ MAKEFILES_BEFORE_$(PASS) := $(MAKEFILES_BEFORE) $(MAKEFILES_BEFORE.$(KBUILD_TARGET)) $(MAKEFILES_BEFORE.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))
+endif
+ifndef MAKEFILES_AFTER_$(PASS)
+ MAKEFILES_AFTER_$(PASS)  := $(MAKEFILES_AFTER)  $(MAKEFILES_AFTER.$(KBUILD_TARGET))  $(MAKEFILES_AFTER.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))
+endif
+
+# The check.
+ifeq ($(_KBUILD_STRICT_PASS_ORDER),nonstrict)
+ ifneq ($(strip \
+          $(SUBDIRS_$(PASS))          $(SUBDIRS_$(PASS).$(KBUILD_TARGET))          $(SUBDIRS_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))           \
+          $(MAKEFILES_BEFORE_$(PASS)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))  \
+          $(SUBDIRS_AFTER_$(PASS))    $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET))    $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))     \
+          $(MAKEFILES_AFTER_$(PASS))  $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET))  $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))   \
+         ),)
+  _KBUILD_STRICT_PASS_ORDER := strict
+ endif
+endif # _KBUILD_STRICT_PASS_ORDER == nonstrict
+endef # def_pass_setup_and_optimize
+
+## PASS: Setup & optimization.
+# Check if we can apply the non-strict pass order optimzation (no SUBDIRS_* and MAKEFILES_*),
+# and set up the pass specific variables as we go along.
+_KBUILD_STRICT_PASS_ORDER := nonstrict
+$(foreach PASS, $(PASSES), $(evalval def_pass_setup_and_optimize))
+#$ (error _KBUILD_STRICT_PASS_ORDER=$(_KBUILD_STRICT_PASS_ORDER))
+
+
+## Subdir
+# @param	$(pass)		Lowercase pass name.
+# @param	$(PASS)		Uppercase pass name.
+# @param	$(subdir)	Subdirectory
+# @param	$(tag)		tag to attach to the rule name.
+define def_pass_subdir
+pass_$(pass)$(tag):: $(dep)
+	+ $$(QUIET)$$(MAKE) -C $(subdir) -f $$(notdir $$(firstword $$(wildcard $$(addprefix $(subdir)/,$$(DEFAULT_MAKEFILE))))) pass_$(pass)
+endef
+
+## Submakefile
+# @param	$(pass)		Lowercase pass name.
+# @param	$(PASS)		Uppercase pass name.
+# @param	$(makefile)	Makefile.
+# @param	$(tag)		tag to attach to the rule name.
+define def_pass_makefile
+pass_$(pass)$(tag):: $(dep)
+	+ $$(QUIET)$$(MAKE) -C $(patsubst %/,%,$(dir $(makefile))) -f $(notdir $(makefile)) pass_$(pass)
+endef
+
+## Execute a pass, strict order.
+# @param	$(pass)		Lowercase pass name.
+# @param	$(PASS)		Uppercase pass name.
+define def_pass_strict
+$(eval tag:=_before)
+$(eval dep:=)
+$(foreach subdir,  $(SUBDIRS_$(PASS))          $(SUBDIRS_$(PASS).$(KBUILD_TARGET))          $(SUBDIRS_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))         ,$(eval $(def_pass_subdir)))
+$(foreach makefile,$(MAKEFILES_BEFORE_$(PASS)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)),$(eval $(def_pass_makefile)))
+
+$(eval tag:=_after)
+$(eval dep:=pass_$(pass)_doit)
+$(foreach subdir,  $(SUBDIRS_AFTER_$(PASS))    $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET))    $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))   ,$(eval $(def_pass_subdir)))
+$(foreach makefile,$(MAKEFILES_AFTER_$(PASS))  $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET))  $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) ,$(eval $(def_pass_makefile)))
+
+ifdef KBUILD_SAFE_PARALLEL
+.NOTPARALLEL: pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_this
+.PHONY:       pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_this pass_$(pass)_doit
+pass_$(pass)_doit:      $(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$(var))
+pass_$(pass)_this:      pass_$(pass)_before
+	+ $$(QUIET)$$(MAKE) -f $$(MAKEFILE) pass_$(pass)_doit
+pass_$(pass)_after::    pass_$(pass)_this
+pass_$(pass):           pass_$(pass)_after
+else  # !KBUILD_SAFE_PARALLEL
+.PHONY:       pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_doit
+.NOTPARALLEL: pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_doit
+pass_$(pass)_doit: pass_$(pass)_before \
+		$(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$($(var)))
+pass_$(pass): \
+		pass_$(pass)_before \
+		pass_$(pass)_doit \
+		pass_$(pass)_after
+endif # !KBUILD_SAFE_PARALLEL
+
+#$ (warning pass=$(pass) PASS=$(PASS): $(PASS_$(PASS)_trgs) $(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$($(var))))
+endef # def_pass_strict
+
+## Execute a pass, non-strict pass ordering.
+# @param	$(pass)		Lowercase pass name.
+# @param	$(PASS)		Uppercase pass name.
+define def_pass_nonstrict
+.PHONY:       pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_doit
+pass_$(pass)_doit: $(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$($(var)))
+pass_$(pass):	pass_$(pass)_doit
+endef # def_pass_nonstrict
+
+## PASS: rules
+# Generate the rules for the defined passes.
+$(foreach PASS, $(PASSES), \
+	$(eval pass := $(PASS_$(PASS)_pass)) \
+	$(eval $(def_pass_$(_KBUILD_STRICT_PASS_ORDER))))
+
+
+## Pass order, strict.
+# @param	$(pass)		Current pass name.
+# @param	$(prev_pass)	The previous pass name.
+define def_pass_order_strict
+ifdef KBUILD_SAFE_PARALLEL
+.PHONY:       pass_$(pass)_order
+.NOTPARALLEL: pass_$(pass)_order
+pass_$(pass)_order: $(pass_prev)
+	%$$(call MSG_PASS,$$(if $$(PASS_$(PASS)),$$(PASS_$(PASS)),$(pass)))
+	+ $$(QUIET)$$(MAKE) -f $$(MAKEFILE) pass_$(pass)
+else  # !KBUILD_SAFE_PARALLEL
+.NOTPARALLEL: pass_$(pass)_order pass_$(pass)_banner
+.PHONY:       pass_$(pass)_order pass_$(pass)_banner
+pass_$(pass)_banner:
+	%$$(call MSG_PASS,$$(if $$(PASS_$(PASS)),$$(PASS_$(PASS)),$(pass)))
+pass_$(pass)_order: \
+		$(pass_prev) \
+		pass_$(pass)_banner \
+		pass_$(pass)
+endif # !KBUILD_SAFE_PARALLEL
+$(eval pass_prev := pass_$(pass)_order)
+endef # def_pass_order_strict
+
+## Pass order, non-strict.
+# @param	$(pass)		Current pass name.
+# @param	$(prev_pass)	The previous pass name.
+define def_pass_order_nonstrict
+.PHONY:       pass_$(pass)_order pass_$(pass)_banner
+pass_$(pass)_banner:
+	%$$(call MSG_PASS,$$(if $$(PASS_$(PASS)),$$(PASS_$(PASS)),$(pass)))
+pass_$(pass)_order: \
+		$(pass_prev) \
+		pass_$(pass)_banner \
+		pass_$(pass)
+$(eval pass_prev := pass_$(pass)_order)
+endef # def_pass_order_nonstrict
+
+## PASS: order
+# Use dependencies to ensure correct pass order.
+pass_prev :=
+$(foreach PASS,$(DEFAULT_PASSES),\
+	$(eval pass := $(PASS_$(PASS)_pass)) \
+	$(eval $(def_pass_order_$(_KBUILD_STRICT_PASS_ORDER))))
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - done passes)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+endif
+
+
+#
+# THE MAIN RULES
+#
+all_recursive: $(pass_prev)
+
+rebuild: clean
+	+ $(MAKE) -f $(firstword $(MAKEFILE_LIST)) all_recursive
+
+# @todo make this a non-default pass!
+uninstall:
+	$(RM) -f -- $(_INSTALLS_FILES)
+
+install: pass_installs
+
+# misc shortcuts.
+targets:   bldprogs libraries dlls programs sysmods others installs
+objects:   $(_OBJS)
+bldprogs:  $(_BLDPROGS)
+libraries: $(_LIBS) $(_IMPORT_LIBS) $(_OTHER_LIBRARIES)
+dlls:      $(_DLLS)
+programs:  $(_PROGRAMS)
+sysmods:   $(_SYSMODS)
+others:    $(_OTHERS)
+installs:  $(_INSTALLS) $(_INSTALLS_DIRS) $(_INSTALLS_FILES)
+
+
+
+#
+# kBuild debugging stuff.
+#
+## @todo this doesn't work. Move to a debug unit and expand it.
+show_targets:
+	@$(foreach target, $(_ALL_TARGETS),\
+	@$(ECHO) "target: $(target)" $(NLTAB)\
+	@$(ECHO) "  PATH_$(target)=$(PATH_$(target))" $(NLTAB)\
+	@$(ECHO) "  TARGET_$(target)=$(TARGET_$(target))" $(NLTAB)\
+	@$(ECHO) "  INSTARGET_$(target)=$(INSTARGET_$(target))" $(NLTAB)\
+$(foreach prop,$(PROPS_SINGLE) $(PROPS_ACCUMULATE_L) $(PROPS_ACCUMULATE_R) OBJS_ CLEAN, \
+	$(eval _tmp:=$(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET))) \
+	$(if $($(target)_$(prop).$(_tmp)),\
+		@$(ECHO) "  $(target)_$(prop).$(_tmp)=$($(target)_$(prop).$(_tmp))" $(NLTAB)) \
+	$(if $($(target)_$(prop)), $(NLTAB)@$(ECHO) "  $(target)_$(prop)=$($(target)_$(prop))" $(NLTAB)) \
+)\
+$(foreach prop,$(PROPS_DEFERRED), \
+	$(eval _tmp:=$(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET))) \
+	$(if $(value $(target)_$(prop).$(_tmp)),\
+		@$(ECHO) '  $(target)_$(prop).$(_tmp)=$(value $(TARGET)_$(prop).$(_tmp))' $(NLTAB)) \
+	$(if $(value $(target)_$(prop)), $(NLTAB)@$(ECHO) '  $(target)_$(prop)=$(value $(target)_$(prop))' $(NLTAB)) \
+))
+
+
+
+#
+# Include dependency files.
+#
+ifneq ($(_DEPFILES),)
+ includedep $(_DEPFILES)
+endif
+
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_FOOTER_END := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_FOOTER_END), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_FOOTER_END), $(_KBUILD_TS_PREV)) - end of footer.kmk)
+ $(info prof: footer.kmk: $(int-sub $(_KBUILD_TS_FOOTER_END), $(_KBUILD_TS_FOOTER_START)))
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_FOOTER_END)
+endif
+
+# end-of-file-content
+__footer_kmk__ := target
+endif # __footer_kmk__
+
Index: /tags/kBuild-0.1.4/kBuild/header.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/header.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/header.kmk	(revision 1780)
@@ -0,0 +1,1214 @@
+# $Id$
+## @file
+# kBuild - File included at top of a makefile.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+ifndef __header_kmk__
+# start-of-file-content
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_HEADER_START := $(nanots ) # just a dummy warm up query
+ $(info prof: since start - since previous - event description)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_HEADER_START := $(nanots )
+ _KBUILD_TS_PREV := $(_KBUILD_TS_HEADER_START)
+endif
+
+
+#
+# Check make version before we do anything else.
+#
+ifndef KMK_VERSION
+ $(error kBuild: The kmk default variable KMK_VERSION isn't defined! Make sure you are using 'kmk' and not 'make', 'gmake', 'kmk_gmake', 'dmake' or any other make program)
+endif
+ifneq ($(KBUILD_VERSION_MAJOR).$(KBUILD_VERSION_MINOR),0.1)
+ ifneq ($(KBUILD_VERSION_MAJOR),0)
+  $(warning kBuild: kmk major version mismatch! Expected '0' but found '$(KBUILD_VERSION_MAJOR)'!)
+ else
+  $(warning kBuild: kmk minor version mismatch! Expected '1' but found '$(KBUILD_VERSION_MINOR)'!)
+ endif
+else
+ ifneq ($(int-ge $(KBUILD_VERSION_PATCH),4),1)
+  $(warning kBuild: kmk version mismatch! Expected 0.1.4 or later. Actual version is $(KBUILD_VERSION_MAJOR).$(KBUILD_VERSION_MINOR).$(KBUILD_VERSION_PATCH).)
+ endif
+endif
+
+#
+# The revision in which this file was last modified.
+# This can be useful when using development versions of kBuild.
+#
+KMK_REVISION := $(patsubst %:,,  $Rev$  )
+
+
+#
+# Define the default goal.
+#
+.PHONY: all all_recursive
+all: all_recursive
+
+#
+# The phony FORCE target.
+#
+.PHONY: FORCE
+FORCE:
+
+
+#
+# Enable delete on error and second expansion of prerequisites.
+#
+.DELETE_ON_ERROR:
+
+.SECONDEXPANSION:
+
+
+#
+# General purpose macros.
+#
+
+##
+# Newline character(s).
+define NL
+
+
+endef
+
+##
+# Tab character.
+TAB := $(subst .,	,.)
+
+##
+# Newline + tab characters (for generating commands).
+NLTAB = $(NL)$(TAB)
+
+##
+# Space character.
+SP := $(subst ., ,.)
+
+##
+# Hash character.
+define HASH
+#
+endef
+
+##
+# Colon character.
+COLON := :
+
+##
+# Semicolon character.
+SEMICOLON := ;
+
+##
+# Comma character.
+COMMA := ,
+
+##
+# Dot character.
+DOT := .
+
+##
+# Dollar character.
+DOLLAR := $$
+
+##
+# Equal character.
+EQUAL := =
+
+
+#
+# The list of standard build types in kBuild.
+#
+# This list can be extended in Config.kmk and it's possible to extend
+# (inherit) another build type.
+#
+KBUILD_BLD_TYPES := release profile debug
+
+
+#
+# The OSes, Architectures and CPUs that kBuild recognizes.
+#
+# When kBuild is ported to a new OS or architecture a unique keyword needs
+# to be assigned to it and added here. This strictness is required because
+# this keyword namespace is shared between OSes, architectures, cpus and
+# build types. (PORTME)
+#
+KBUILD_OSES   := darwin dragonfly freebsd l4 linux netbsd nt openbsd os2 solaris win
+KBUILD_ARCHES := x86 amd64 sparc32 sparc64 s390 s390x ppc32 ppc64 mips32 mips64 ia64 hppa32 hppa64 arm alpha
+
+
+#
+# Set default build type.
+#
+ifndef KBUILD_TYPE
+ ifdef BUILD_TYPE
+  KBUILD_TYPE := $(BUILD_TYPE)
+ endif
+else ifdef BUILD_TYPE
+ ifneq ($(KBUILD_TYPE),$(BUILD_TYPE))
+  ifeq ($(origin KBUILD_TYPE):$(origin BUILD_TYPE),environment:command line)
+   KBUILD_TYPE := $(BUILD_TYPE)
+  else ifneq ($(origin KBUILD_TYPE):$(origin BUILD_TYPE),command line:environment)
+   $(error kBuild: KBUILD_TYPE and BUILD_TYPE disagree.)
+  endif
+ endif
+endif
+override BUILD_TYPE = $(KBUILD_TYPE)
+
+ifndef KBUILD_TYPE
+ KBUILD_TYPE := release
+else
+ if1of ($(KBUILD_TYPE), $(KBUILD_OSES) $(KBUILD_ARCHES))
+  $(error kBuild: The KBUILD_TYPE value '$(KBUILD_TYPE)' is an OS or architecture!)
+ endif
+ ifneq (.$(words $(KBUILD_TYPE)).$(KBUILD_TYPE).,.1.$(strip $(KBUILD_TYPE)).)
+  $(error kBuild: The KBUILD_TYPE value '$(KBUILD_TYPE)' contains spaces/tabs!)
+ endif
+endif
+
+
+#
+# Host platform legacy
+# kmk deals with this, so this is only temporary until I've rebuilt everything.
+#
+ifndef KBUILD_HOST
+ KBUILD_HOST := $(BUILD_PLATFORM)
+endif
+ifndef KBUILD_HOST_ARCH
+ KBUILD_HOST_ARCH := $(BUILD_PLATFORM_ARCH)
+endif
+ifndef KBUILD_HOST_CPU
+ KBUILD_HOST_CPU := $(BUILD_PLATFORM_CPU)
+endif
+
+
+#
+# Assert valid build platform variables.
+#
+# All these are set by kmk so they shouldn't be any trouble
+# unless the user starts messing about with environment variables.
+#
+ifneq (.$(words $(KBUILD_HOST)).$(KBUILD_HOST).,.1.$(strip $(KBUILD_HOST)).)
+ $(error kBuild: The KBUILD_HOST value '$(KBUILD_HOST)' contains spaces/tabs!)
+endif
+ifneq ($(words $(filter $(KBUILD_HOST),$(KBUILD_OSES))),1)
+ $(error kBuild: KBUILD_HOST value '$(KBUILD_HOST)' is not recognized (valid: $(KBUILD_OSES)))
+endif
+
+ifneq (.$(words $(KBUILD_HOST_ARCH)).$(KBUILD_HOST_ARCH).,.1.$(strip $(KBUILD_HOST_ARCH)).)
+ $(error kBuild: The KBUILD_HOST_ARCH value '$(KBUILD_HOST_ARCH)' contains spaces/tabs!)
+endif
+ifneq ($(words $(filter $(KBUILD_HOST_ARCH),$(KBUILD_ARCHES))),1)
+ $(error kBuild: KBUILD_HOST_ARCH value '$(KBUILD_HOST_ARCH)' is not recognized (valid: $(KBUILD_ARCHES)))
+endif
+
+ifeq ($(strip $(KBUILD_HOST_CPU)),)
+ KBUILD_HOST_CPU := blend
+else
+ ifneq (.$(words $(KBUILD_HOST_CPU)).$(KBUILD_HOST_CPU).,.1.$(strip $(KBUILD_HOST_CPU)).)
+  $(error kBuild: The KBUILD_HOST_CPU value '$(KBUILD_HOST_CPU)' contains spaces/tabs!)
+ endif
+ if1of ($(KBUILD_HOST_CPU), $(KBUILD_OSES) $(BUILD_ARCHES))
+  $(error kBuild: The KBUILD_HOST_CPU value '$(KBUILD_HOST_CPU)' was found in the OS or architecture keywords!)
+ endif
+ ifeq ($(KBUILD_HOST_CPU),$(KBUILD_TYPE))
+  $(error kBuild: The KBUILD_HOST_CPU value '$(KBUILD_HOST_CPU)' is the same as the KBUILD_TYPE!)
+ endif
+endif
+
+
+#
+# Deal with target platform legacy.
+#
+ifndef KBUILD_TARGET
+ ifdef BUILD_TARGET
+  KBUILD_TARGET := $(BUILD_TARGET)
+ endif
+else ifdef BUILD_TARGET
+ ifneq ($(KBUILD_TARGET),$(BUILD_TARGET))
+  ifeq ($(origin KBUILD_TARGET):$(origin BUILD_TARGET),environment:command line)
+   KBUILD_TARGET := $(BUILD_TARGET)
+  else ifneq ($(origin KBUILD_TARGET):$(origin BUILD_TARGET),command line:environment)
+   $(error kBuild: KBUILD_TARGET and BUILD_TARGET disagree)
+  endif
+ endif
+endif
+override BUILD_TARGET = $(KBUILD_TARGET)
+
+ifndef KBUILD_TARGET_ARCH
+ ifdef BUILD_TARGET_ARCH
+  KBUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH)
+ endif
+else ifdef BUILD_TARGET_ARCH
+ ifneq ($(KBUILD_TARGET_ARCH),$(BUILD_TARGET_ARCH))
+  ifeq ($(origin KBUILD_TARGET_ARCH):$(origin BUILD_TARGET_ARCH),environment:command line)
+   KBUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH)
+  else ifneq ($(origin KBUILD_TARGET_ARCH):$(origin BUILD_TARGET_ARCH),command line:environment)
+   $(error kBuild: KBUILD_TARGET_ARCH and BUILD_TARGET_ARCH disagree)
+  endif
+ endif
+endif
+override BUILD_TARGET_ARCH = $(KBUILD_TARGET_ARCH)
+
+ifndef KBUILD_TARGET_CPU
+ ifdef BUILD_TARGET_CPU
+  KBUILD_TARGET_CPU := $(BUILD_TARGET_CPU)
+ endif
+else ifdef BUILD_TARGET_CPU
+ ifneq ($(KBUILD_TARGET_CPU),$(BUILD_TARGET_CPU))
+  ifeq ($(origin KBUILD_TARGET_CPU):$(origin BUILD_TARGET_CPU),environment:command line)
+   KBUILD_TARGET_CPU := $(BUILD_TARGET_CPU)
+  else ifneq ($(origin KBUILD_TARGET_CPU):$(origin BUILD_TARGET_CPU),command line:environment)
+   $(error kBuild: KBUILD_TARGET_CPU and BUILD_TARGET_CPU disagree)
+  endif
+ endif
+endif
+override BUILD_TARGET_CPU = $(KBUILD_TARGET_CPU)
+
+
+#
+# Assert or set default target platform.
+# When not defined use the corresponding KBUILD_HOST value.
+#
+ifndef KBUILD_TARGET
+ KBUILD_TARGET := $(KBUILD_HOST)
+else
+ ifneq (.$(words $(KBUILD_TARGET)).$(KBUILD_TARGET).,.1.$(strip $(KBUILD_TARGET)).)
+  $(error kBuild: The KBUILD_TARGET value '$(KBUILD_TARGET)' contains spaces/tabs!)
+ endif
+ ifneq ($(words $(filter $(KBUILD_TARGET),$(KBUILD_OSES))),1)
+  $(error kBuild: KBUILD_TARGET value '$(KBUILD_TARGET)' is not recognized (valid: $(KBUILD_OSES)))
+ endif
+endif
+
+ifndef KBUILD_TARGET_ARCH
+ KBUILD_TARGET_ARCH := $(KBUILD_HOST_ARCH)
+else
+ ifneq (.$(words $(KBUILD_TARGET_ARCH)).$(KBUILD_TARGET_ARCH).,.1.$(strip $(KBUILD_TARGET_ARCH)).)
+  $(error kBuild: The KBUILD_TARGET_ARCH value '$(KBUILD_TARGET_ARCH)' contains spaces/tabs!)
+ endif
+ ifneq ($(words $(filter $(KBUILD_TARGET_ARCH),$(KBUILD_ARCHES))),1)
+  $(error kBuild: KBUILD_TARGET_ARCH value '$(KBUILD_TARGET_ARCH)' is not recognized (valid: $(KBUILD_ARCHES)))
+ endif
+endif
+
+ifndef KBUILD_TARGET_CPU
+ KBUILD_TARGET_CPU := $(KBUILD_HOST_CPU)
+else ifeq ($(strip $(KBUILD_TARGET_CPU)),)
+ ifeq ($(KBUILD_TARGET_ARCH),$(KBUILD_HOST_ARCH))
+  KBUILD_TARGET_CPU := $(KBUILD_HOST_CPU)
+ else
+  KBUILD_TARGET_CPU := blend
+ endif
+else
+ ifneq (.$(words $(KBUILD_TARGET_CPU)).$(KBUILD_TARGET_CPU).,.1.$(strip $(KBUILD_TARGET_CPU)).)
+  $(error kBuild: The KBUILD_TARGET_CPU value '$(KBUILD_TARGET_CPU)' contains spaces/tabs!)
+ endif
+ if1of ($(KBUILD_TARGET_CPU), $(KBUILD_OSES) $(BUILD_ARCHES))
+  $(error kBuild: The KBUILD_TARGET_CPU value was found in the OS or architecture keywords!)
+ endif
+ ifeq ($(KBUILD_TARGET_CPU),$(KBUILD_TYPE))
+  $(error kBuild: The KBUILD_TARGET_CPU value '$(KBUILD_TARGET_CPU)' is the same as the KBUILD_TYPE!)
+ endif
+endif
+
+
+#
+# Paths and stuff.
+#
+
+# Adjust DEPTH first.
+DEPTH := $(strip $(DEPTH))
+ifeq ($(DEPTH),)
+ DEPTH := .
+endif
+
+## PATH_CURRENT is the current directory (getcwd).
+PATH_CURRENT        := $(abspath $(CURDIR))
+## PATH_SUB_CURRENT points to current directory of the current makefile.
+# Meaning that it will change value as we enter and exit sub-makefiles.
+PATH_SUB_CURRENT    := $(PATH_CURRENT)
+## PATH_ROOT points to the project root directory.
+PATH_ROOT           := $(abspath $(PATH_CURRENT)/$(DEPTH))
+## PATH_SUB_ROOT points to the directory of the top-level makefile.
+ifneq ($(strip $(SUB_DEPTH)),)
+ SUB_DEPTH          := $(strip $(SUB_DEPTH))
+ PATH_SUB_ROOT      := $(abspath $(PATH_CURRENT)/$(SUB_DEPTH))
+else
+ PATH_SUB_ROOT      := $(PATH_CURRENT)
+endif
+
+## CURSUBDIR is PATH_SUB_ROOT described relative to PATH_ROOT.
+# This variable is used to determin where the object files and other output goes.
+ifneq ($(PATH_ROOT),$(PATH_SUB_ROOT))
+ CURSUBDIR          := $(patsubst $(PATH_ROOT)/%,%,$(PATH_SUB_ROOT))
+else
+ CURSUBDIR          := .
+endif
+
+# Output directories.
+ifndef PATH_OUT_BASE
+ PATH_OUT_BASE      := $(PATH_ROOT)/out
+endif
+ifndef PATH_OUT
+ ifdef BUILD_TARGET_SUB # (BUILD_TARGET_SUB is not currently recognized by kBuild in any other places - obsolete)
+  PATH_OUT           = $(PATH_OUT_BASE)/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH).$(BUILD_TARGET_SUB)/$(KBUILD_TYPE)
+ else
+  PATH_OUT           = $(PATH_OUT_BASE)/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/$(KBUILD_TYPE)
+ endif
+endif # !define PATH_OUT
+PATH_OBJCACHE        = $(PATH_OUT_BASE)/kObjCache
+PATH_OBJ             = $(PATH_OUT)/obj
+PATH_TARGET          = $(PATH_OBJ)/$(CURSUBDIR)
+PATH_INS             = $(PATH_OUT)
+PATH_BIN             = $(PATH_INS)/bin
+PATH_DLL             = $(PATH_INS)/bin
+PATH_SYS             = $(PATH_INS)/bin
+PATH_LIB             = $(PATH_INS)/lib
+PATH_DOC             = $(PATH_INS)/doc
+
+# KBUILD_PATH / PATH_KBUILD is determined by kmk.
+ifndef KBUILD_PATH
+ KBUILD_PATH := $(PATH_KBUILD)
+endif
+ifeq ($(strip $(KBUILD_PATH)),)
+ $(error kBuild: KBUILD_PATH is missing or empty! kmk is supposed to set it.)
+endif
+# KBUILD_BIN_PATH / PATH_KBUILD_BIN is determined by kmk.
+ifndef KBUILD_BIN_PATH
+ KBUILD_BIN_PATH := $(PATH_KBUILD_BIN)
+endif
+ifeq ($(strip $(KBUILD_BIN_PATH)),)
+ $(error kBuild: KBUILD_BIN_PATH is missing or empty! kmk is supposed to set it.)
+endif
+
+# kBuild files which might be of interest.
+FILE_KBUILD_HEADER := $(KBUILD_PATH)/header.kmk
+#FILE_KBUILD_CONFIG := $(KBUILD_PATH)/config.kmk
+FILE_KBUILD_FOOTER := $(KBUILD_PATH)/footer.kmk
+FILE_KBUILD_SUB_HEADER := $(KBUILD_PATH)/subheader.kmk
+FILE_KBUILD_SUB_FOOTER := $(KBUILD_PATH)/subfooter.kmk
+
+## MAKEFILE is the name of the main makefile.
+MAKEFILE            := $(firstword $(MAKEFILE_LIST))
+## MAKEFILE_CURRENT is the name of the current makefile.
+# This is updated everything a sub-makefile is included.
+MAKEFILE_CURRENT    := $(MAKEFILE)
+
+
+## @todo this should be done via SUFF_XYZ.target/host...
+
+#
+# Build platform setup.
+# (PORTME)
+#
+if1of ($(KBUILD_HOST), win nt)
+# Win, Win32, Win64, NT.
+EXEC_X86_WIN32      :=
+HOSTSUFF_EXE        := .exe
+
+# OS/2.
+else ifeq ($(KBUILD_HOST),os2)
+EXEC_X86_WIN32      := innopec.exe
+HOSTSUFF_EXE        := .exe
+
+else if1of ($(KBUILD_HOST), freebsd dragonfly linux openbsd netbsd)
+# Unix (like) systems with wine.
+EXEC_X86_WIN32      := wine
+HOSTSUFF_EXE        :=
+
+else
+# Unix (like) systems without wine.
+EXEC_X86_WIN32      := false
+HOSTSUFF_EXE        :=
+endif
+
+
+#
+# Build target setup.
+# (PORTME)
+#
+SUFF_DEP    := .dep
+if1of ($(KBUILD_TARGET), win nt os2)
+SUFF_OBJ    := .obj
+SUFF_LIB    := .lib
+SUFF_DLL    := .dll
+SUFF_EXE    := .exe
+SUFF_SYS    := .sys
+SUFF_RES    := .res
+else ifeq ($(KBUILD_TARGET),l4)
+SUFF_OBJ    := .o
+SUFF_LIB    := .a
+SUFF_DLL    := .s.so
+SUFF_EXE    :=
+SUFF_SYS    := .a
+SUFF_RES    :=
+else ifeq ($(KBUILD_TARGET),darwin)
+SUFF_OBJ    := .o
+SUFF_LIB    := .a
+SUFF_DLL    := .dylib
+SUFF_EXE    :=
+SUFF_SYS    :=
+SUFF_RES    :=
+else
+SUFF_OBJ    := .o
+SUFF_LIB    := .a
+SUFF_DLL    := .so
+SUFF_EXE    :=
+ if1of ($(KBUILD_TARGET), dragonfly freebsd linux netbsd openbsd) ## @todo check netbsd and openbsd.
+SUFF_SYS    := .ko
+ else
+SUFF_SYS    :=
+ endif
+SUFF_RES    :=
+endif
+
+#
+# Standard kBuild tools.
+#
+ifeq ($(KMK),kmk)
+KMK         := $(KBUILD_BIN_PATH)/kmk$(HOSTSUFF_EXE)
+endif
+MAKE        := $(KMK)
+
+GMAKE       := $(KBUILD_BIN_PATH)/kmk_gmake$(HOSTSUFF_EXE)
+
+DEP_EXT     := $(KBUILD_BIN_PATH)/kDep$(HOSTSUFF_EXE)
+if1of (kDep, $(KMK_BUILTIN))
+DEP         := kmk_builtin_kDep
+else
+DEP         := $(DEP_EXT)
+endif
+
+DEP_IDB_EXT := $(KBUILD_BIN_PATH)/kDepIDB$(HOSTSUFF_EXE)
+if1of (kDepIDB, $(KMK_BUILTIN))
+DEP_IDB     := kmk_builtin_kDepIDB
+else
+DEP_IDB     := $(DEP_IDB_EXT)
+endif
+
+DEP_PRE_EXT := $(KBUILD_BIN_PATH)/kDepPre$(HOSTSUFF_EXE)
+if1of (kDepPre, $(KMK_BUILTIN))
+DEP_PRE     := kmk_builtin_kDepPre
+else
+DEP_PRE     := $(DEP_PRE_EXT)
+endif
+
+KOBJCACHE_EXT := $(KBUILD_BIN_PATH)/kObjCache$(HOSTSUFF_EXE)
+if1of (kObjCache, $(KMK_BUILTIN))
+KOBJCACHE   := kmk_builtin_kObjCache
+else
+KOBJCACHE   := $(KOBJCACHE_EXT)
+endif
+
+APPEND_EXT  := $(KBUILD_BIN_PATH)/kmk_append$(HOSTSUFF_EXE)
+APPEND      := kmk_builtin_append
+
+CAT_EXT     := $(KBUILD_BIN_PATH)/kmk_cat$(HOSTSUFF_EXE)
+CAT         := kmk_builtin_cat
+
+CHMOD_EXT   := $(KBUILD_BIN_PATH)/kmk_chmod$(HOSTSUFF_EXE)
+CHMOD       := kmk_builtin_chmod
+
+CMP_EXT     := $(KBUILD_BIN_PATH)/kmk_cmp$(HOSTSUFF_EXE)
+CMP         := kmk_builtin_cmp
+
+CP_EXT      := $(KBUILD_BIN_PATH)/kmk_cp$(HOSTSUFF_EXE)
+CP          := kmk_builtin_cp
+
+ECHO_EXT    := $(KBUILD_BIN_PATH)/kmk_echo$(HOSTSUFF_EXE)
+ECHO        := kmk_builtin_echo
+
+EXPR_EXT    := $(KBUILD_BIN_PATH)/kmk_expr$(HOSTSUFF_EXE)
+EXPR        := kmk_builtin_expr
+
+INSTALL_EXT := $(KBUILD_BIN_PATH)/kmk_install$(HOSTSUFF_EXE)
+INSTALL     := kmk_builtin_install
+
+LN_EXT      := $(KBUILD_BIN_PATH)/kmk_ln$(HOSTSUFF_EXE)
+LN          := kmk_builtin_ln
+
+MD5SUM_EXT  := $(KBUILD_BIN_PATH)/kmk_md5sum$(HOSTSUFF_EXE)
+MD5SUM      := kmk_builtin_md5sum
+
+MKDIR_EXT   := $(KBUILD_BIN_PATH)/kmk_mkdir$(HOSTSUFF_EXE)
+MKDIR       := kmk_builtin_mkdir
+
+MV_EXT      := $(KBUILD_BIN_PATH)/kmk_mv$(HOSTSUFF_EXE)
+MV          := kmk_builtin_mv
+
+PRINTF_EXT  := $(KBUILD_BIN_PATH)/kmk_printf$(HOSTSUFF_EXE)
+PRINTF      := kmk_builtin_printf
+
+REDIRECT_EXT:= $(KBUILD_BIN_PATH)/kmk_redirect$(HOSTSUFF_EXE)
+if1of (redirect, $(KMK_BUILTIN))
+REDIRECT    := kmk_builtin_redirect
+else
+REDIRECT    := $(REDIRECT_EXT)
+endif
+
+RM_EXT      := $(KBUILD_BIN_PATH)/kmk_rm$(HOSTSUFF_EXE)
+RM          := kmk_builtin_rm
+
+RMDIR_EXT   := $(KBUILD_BIN_PATH)/kmk_rmdir$(HOSTSUFF_EXE)
+RMDIR       := kmk_builtin_rmdir
+
+SED_EXT     := $(KBUILD_BIN_PATH)/kmk_sed$(HOSTSUFF_EXE)
+if1of (sed, $(KMK_BUILTIN))
+SED_INT     := kmk_builtin_sed
+else
+SED_INT     := $(SED_EXT)
+endif
+SED         := $(SED_EXT)
+
+TEST_EXT    := $(KBUILD_BIN_PATH)/kmk_test$(HOSTSUFF_EXE)
+TEST        := kmk_builtin_test
+
+# Our default shell is the Almquist shell from *BSD.
+ASH         := $(KBUILD_BIN_PATH)/kmk_ash$(HOSTSUFF_EXE)
+MAKESHELL   := $(ASH)
+SHELL       := $(ASH)
+export SHELL MAKESHELL
+
+# Symlinking is problematic on some platforms...
+LN_SYMLINK  := $(LN) -s
+
+
+#
+# Some Functions.
+# The lower cased ones are either fallbacks or candidates for functions.c.
+#
+
+## ABSPATH - make paths absolute.
+# This implementation is clumsy and doesn't resolve '..' and '.' components.
+#
+# @param	$1	The paths to make absolute.
+# @obsolete Use the GNU make function $(abspath) directly now.
+ABSPATH = $(abspath $(1))$(warning ABSPATH is deprecated, use abspath directly!)
+
+## DIRDEP - make create directory dependencies.
+#
+# @param	$1	The paths to the directories which must be created.
+DIRDEP = $(foreach path,$(patsubst %/,%,$(1)),$(path)/)
+
+## Cygwin kludge.
+# This converts /cygdrive/x/% to x:%.
+#
+# @param	$1	The paths to make native.
+# @remark	This macro is pretty much obsolete since we don't use cygwin base make.
+ifneq ($(patsubst /cygdrive/%,%,$(CURDIR)),$(CURDIR))
+ CYGPATHMIXED = $(foreach path,$(1)\
+   ,$(if $(patsubst /cygdrive/%,,$(path)),$(path),$(patsubst $(strip $(firstword $(subst /, ,$(patsubst /cygdrive/%,%,$(path)))))/%,$(strip $(firstword $(subst /, ,$(patsubst /cygdrive/%,%,$(path))))):/%,$(patsubst /cygdrive/%,%,$(path)))))
+else
+ CYGPATHMIXED = $(1)
+endif
+
+## Removes the drive letter from a path (if it has one)
+# @param	$1 		the path
+no-drive    = $(word $(words $(subst :, ,$(1))),$(subst :, ,$(1)))
+
+## Removes the root slash from a path (if it has one)
+# @param	$1 		the path
+no-root-slash = $(patsubst /%,%,$(1))
+
+## Figure out where to put object files.
+# @param    $1      real target name.
+# @param    $2      normalized main target
+TARGET_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(1)))
+
+## Figure out where to put object files.
+# @param    $1      normalized main target
+TARGET_PATH = $(PATH_TARGET)/$(1)
+
+
+#
+# Initialize some of the globals which the Config.kmk and
+# others can add stuff to if they like for processing in the footer.
+#
+
+## KBUILD_TEMPLATE_PATHS
+# List a paths (separated by space) where templates can be found.
+KBUILD_TEMPLATE_PATHS :=
+
+## KBUILD_TOOL_PATHS
+# List of paths (separated by space) where tools can be found.
+KBUILD_TOOL_PATHS :=
+
+## KBUILD_SDK_PATHS
+# List of paths (separated by space) where SDKs can be found.
+KBUILD_SDK_PATHS :=
+
+## KBUILD_UNIT_PATHS
+# List of paths (separated by space) where units (USES) can be found.
+KBUILD_UNIT_PATHS :=
+
+## KBUILD_DEFAULT_PATHS
+# List of paths (separated by space) to search for stuff as a last resort.
+KBUILD_DEFAULT_PATHS :=
+
+## Proritized list of the default makefile when walking subdirectories.
+# The user can overload this list.
+DEFAULT_MAKEFILE := Makefile.kmk makefile.kmk Makefile makefile
+
+## KBUILD_SRC_HANDLERS
+# The list of source handlers, pair of extension and handler.
+# The user can overload this list to provide additional or custom
+# handlers. On a per-target/template see SRC_HANDLERS.
+KBUILD_SRC_HANDLERS := \
+  .c:def_src_handler_c \
+  .C:def_src_handler_c \
+.cxx:def_src_handler_cxx \
+.CXX:def_src_handler_cxx \
+.cpp:def_src_handler_cxx \
+.CPP:def_src_handler_cxx \
+ .cc:def_src_handler_cxx \
+ .CC:def_src_handler_cxx \
+  .m:def_src_handler_objc \
+.asm:def_src_handler_asm \
+.ASM:def_src_handler_asm \
+  .s:def_src_handler_asm \
+  .S:def_src_handler_asm \
+ .rc:def_src_handler_rc \
+.obj:def_src_handler_obj \
+  .o:def_src_handler_obj \
+.res:def_src_handler_obj
+
+## PROPS_TOOLS
+# This is a subset of PROPS_SINGLE.
+PROPS_TOOLS := TOOL CTOOL CXXTOOL OBJCTOOL ASTOOL RCTOOL ARTOOL LDTOOL LEXTOOL FETCHTOOL UNPACKTOOL PATCHTOOL
+
+## PROPS_SINGLE
+# The list of non-accumulative target properties.
+# A Config.kmk file can add it's own properties to this list and kBuild
+# will do the necessary inheritance for templates, sdks, tools and targets.
+PROPS_SINGLE := $(PROPS_TOOLS) TEMPLATE INST NOINST BLD_TYPE BLD_TRG BLD_TRG_ARCH BLD_TRG_CPU FETCHDIR \
+	OBJSUFF COBJSUFF CXXOBJSUFF OBJCOBJSUFF ASOBJSUFF RCOBJSUFF SYSSUFF EXESUFF DLLSUFF LIBSUFF ARLIBSUFF
+## PROPS_SINGLE_LNK
+# Subset of PROPS_SINGLE which applies to all linkable targets.
+PROPS_SINGLE_LNK := TOOL TEMPLATE CTOOL CXXTOOL OBJCTOOL ASTOOL RCTOOL \
+	INST NOINST BLD_TYPE BLD_TRG BLD_TRG_ARCH BLD_TRG_CPU \
+	OBJSUFF COBJSUFF CXXOBJSUFF OBJCOBJSUFF ASOBJSUFF RCOBJSUFF
+
+## PROPS_DEFERRED
+# This list of non-accumulative target properties which are or may be
+# functions, and thus should not be expanded until the very last moment.
+PROPS_DEFERRED := INSTFUN INSTALLER PRE_CMDS POST_CMDS NAME SONAME
+
+## PROPS_ACCUMULATE_R
+# The list of accumulative target properties where the right most value/flag
+# is the 'most significant'.
+# A Config.kmk file can add it's own properties to this list and kBuild
+# will do the necessary inheritance from templates to targets.
+PROPS_ACCUMULATE_R := \
+	DEPS LNK_DEPS ORDERDEPS LNK_ORDERDEPS DEFS \
+	ARFLAGS \
+	CFLAGS CDEFS \
+	CXXFLAGS CXXDEFS \
+	OBJCFLAGS OBJCDEFS \
+	ASFLAGS ASDEFS \
+	RCFLAGS RCDEFS \
+	LDFLAGS \
+	IDFLAGS IFDLAGS ISFLAGS \
+	FETCHFLAGS UNPACKFLAGS PATCHFLAGS
+## PROPS_ACCUMULATE_R_LNK
+# Subset of PROPS_ACCUMULATE_R which applies to all linkable targets.
+PROPS_ACCUMULATE_R_LNK := \
+	DEPS LNK_DEPS ORDERDEPS LNK_ORDERDEPS DEFS \
+	CFLAGS CDEFS \
+	CXXFLAGS CXXDEFS \
+	OBJCFLAGS OBJCDEFS \
+	ASFLAGS ASDEFS \
+	RCFLAGS RCDEFS \
+	IDFLAGS IFDLAGS ISFLAGS
+
+## PROPS_ACCUMULATE
+# The list of accumulative target properties where the left most value/flag
+# is the 'most significant'.
+# A Config.kmk file can add it's own properties to this list and kBuild
+# will do the necessary inheritance from templates to targets.
+PROPS_ACCUMULATE_L := \
+	SDKS USES SOURCES SRC_HANDLERS INTERMEDIATES \
+	INCS CINCS CXXINCS OBJCINCS ASINCS RCINCS \
+	LIBS LIBPATH \
+	DIRS BLDDIRS CLEAN
+## PROPS_ACCUMULATE_L_LNK
+# Subset of PROPS_ACCUMULATE_L which applies to all linkable targets.
+PROPS_ACCUMULATE_L_LNK := \
+	SDKS SOURCES SRC_HANDLERS \
+	INCS CINCS CXXINCS OBJCINCS ASINCS RCINCS \
+	BLDDIRS CLEAN
+
+## PROPS_ALL
+# List of all the properties.
+PROPS_ALL = $(PROPS_SINGLE) $(PROPS_DEFERRED) $(PROPS_ACCUMULATE_L) $(PROPS_ACCUMULATE_R)
+
+
+## @name Properties valid on programs (BLDPROGS and PROGRAMS)
+## @{
+PROPS_PROGRAMS_SINGLE        := $(PROPS_SINGLE_LNK) LDTOOL EXESUFF
+PROPS_PROGRAMS_DEFERRED      := $(PROPS_DEFERRED)
+PROPS_PROGRAMS_ACCUMULATE_R  := $(PROPS_ACCUMULATE_R_LNK) LDFLAGS
+PROPS_PROGRAMS_ACCUMULATE_L  := $(PROPS_ACCUMULATE_L_LNK) LIBS LIBPATH
+## @}
+
+## @name Properties valid on libraries (LIBRARIES and IMPORT_LIBS)
+## @{
+PROPS_LIBRARIES_SINGLE       := $(PROPS_SINGLE_LNK) ARTOOL LIBSUFF ARLIBSUFF LIBSUFF
+PROPS_LIBRARIES_DEFERRED     := $(filter-out SONAME,$(PROPS_DEFERRED))
+PROPS_LIBRARIES_ACCUMULATE_R := $(PROPS_ACCUMULATE_R_LNK) ARFLAGS
+PROPS_LIBRARIES_ACCUMULATE_L := $(PROPS_ACCUMULATE_L_LNK)
+## @}
+
+## @name Properties valid on dlls (DLLS)
+## @{
+PROPS_DLLS_SINGLE            := $(PROPS_SINGLE_LNK) LDTOOL DLLSUFF LIBSUFF
+PROPS_DLLS_DEFERRED          := $(PROPS_DEFERRED)
+PROPS_DLLS_ACCUMULATE_R      := $(PROPS_ACCUMULATE_R_LNK) LDFLAGS
+PROPS_DLLS_ACCUMULATE_L      := $(PROPS_ACCUMULATE_L_LNK) LIBS LIBPATH
+## @}
+
+## @name Properties valid on system modules (SYSMODS)
+## @{
+PROPS_SYSMODS_SINGLE         := $(PROPS_SINGLE_LNK) LDTOOL SYSSUFF
+PROPS_SYSMODS_DEFERRED       := $(PROPS_DEFERRED)
+PROPS_SYSMODS_ACCUMULATE_R   := $(PROPS_ACCUMULATE_R_LNK) LDFLAGS
+PROPS_SYSMODS_ACCUMULATE_L   := $(PROPS_ACCUMULATE_L_LNK) LIBS LIBPATH
+## @}
+
+## @name Properties valid on installs (INSTALLS)
+## @{
+PROPS_INSTALLS_SINGLE        := TOOL TEMPLATE INST NOINST
+PROPS_INSTALLS_DEFERRED      := INSTFUN INSTALLER
+PROPS_INSTALLS_ACCUMULATE_R  := DEPS ORDERDEPS
+PROPS_INSTALLS_ACCUMULATE_L  := SOURCES DIRS CLEAN
+## @}
+
+## @name Properties valid on fetches (INSTALLS)
+## @{
+PROPS_FETCHES_SINGLE         := TOOL TEMPLATE FETCHTOOL UNPACKTOOL PATCHTOOL INST FETCHDIR
+PROPS_FETCHES_DEFERRED       :=
+PROPS_FETCHES_ACCUMULATE_R   := FETCHFLAGS UNPACKFLAGS PATCHFLAGS
+PROPS_FETCHES_ACCUMULATE_L   := SOURCES CLEAN
+## @}
+
+
+#
+# Here is a special 'hack' to prevent innocent environment variables being
+# picked up and treated as properties. (The most annoying example of why
+# this is necessary is the Visual C++ commandline with it's LIBPATH.)
+#
+# Define KBUILD_DONT_KILL_ENV_PROPS in the env. or on the commandline to
+# disable this 'hack'.
+#
+ifndef KBUILD_DONT_KILL_ENV_PROPS
+
+define def_nuke_environment_prop
+ifeq ($(origin $(prop)),environment)
+$(prop) =
+endif
+endef
+$(foreach prop, $(PROPS_ALL) \
+	FETCHES PATCHES BLDPROGS LIBRARIES IMPORT_LIBS DLLS PROGRAMS SYSMODS INSTALLS OTHERS \
+	SUBDIRS MAKEFILES BLDDIRS \
+	,$(eval $(value def_nuke_environment_prop)))
+
+endif # KBUILD_DONT_KILL_ENV_PROPS
+
+
+#
+# Pass configuration.
+#
+# The PASS_<passname>_trgs variable is listing the targets.
+# The PASS_<passname>_vars variable is listing the target variables.
+# The PASS_<passname>_pass variable is the lowercased passname.
+#
+
+## PASS: fetches
+# This pass fetches and unpacks things needed to complete the build.
+PASS_FETCHES        := Fetches
+PASS_FETCHES_trgs   :=
+PASS_FETCHES_vars   := _FETCHES
+PASS_FETCHES_pass   := fetches
+
+## PASS: patches
+# This pass applies patches.
+PASS_PATCHES        := Patches
+PASS_PATCHES_trgs   :=
+PASS_PATCHES_vars   := _PATCHES
+PASS_PATCHES_pass   := patches
+
+## PASS: bldprogs
+# This pass builds targets which are required for building the rest.
+PASS_BLDPROGS       := Build Programs
+PASS_BLDPROGS_trgs  :=
+PASS_BLDPROGS_vars  := _BLDPROGS
+PASS_BLDPROGS_pass  := bldprogs
+
+## PASS: libraries
+# This pass builds library targets.
+PASS_LIBRARIES      := Libraries
+PASS_LIBRARIES_trgs :=
+PASS_LIBRARIES_vars := _LIBS _IMPORT_LIBS _OTHER_LIBRARIES
+PASS_LIBRARIES_pass := libraries
+
+## PASS: binaries
+# This pass builds dll targets.
+PASS_DLLS           := DLLs
+PASS_DLLS_trgs      :=
+PASS_DLLS_vars      := _DLLS _OTHER_DLLS
+PASS_DLLS_pass      := dlls
+
+## PASS: binaries
+# This pass builds binary targets, i.e. programs, system modules and stuff.
+PASS_BINARIES       := Programs
+PASS_BINARIES_trgs  :=
+PASS_BINARIES_vars  := _PROGRAMS _SYSMODS _OTHER_BINARIES
+PASS_BINARIES_pass  := binaries
+
+## PASS: others
+# This pass builds other targets.
+PASS_OTHERS         := Other Stuff
+PASS_OTHERS_trgs    :=
+PASS_OTHERS_vars    := _OTHERS
+PASS_OTHERS_pass    := others
+
+## PASS: install
+# This pass installs the built entities to a sandbox area.
+## @todo split this up into build install (to sandbox) and real installation.
+PASS_INSTALLS       := Install
+PASS_INSTALLS_trgs  :=
+PASS_INSTALLS_vars  := _INSTALLS_DIRS _INSTALLS _INSTALLS_FILES
+PASS_INSTALLS_pass  := installs
+
+## PASS: testing
+# This pass processes custom rules for executing tests.
+PASS_TESTING        := Tests
+PASS_TESTING_trgs   :=
+PASS_TESTING_vars   := _TESTING
+PASS_TESTING_pass   := testing
+# aliases
+.PHONY: check test
+check test: pass_testing
+
+## PASS: packing
+# This pass processes custom packing rules.
+PASS_PACKING        := Packing
+PASS_PACKING_trgs   :=
+PASS_PACKING_vars   := _PACKING
+PASS_PACKING_pass   := packing
+# alias
+.PHONY: packing
+packing: pass_packing
+
+## PASS: clean
+# This pass removes all generated files.
+PASS_CLEAN          := Clean
+PASS_CLEAN_trgs     := do-clean
+PASS_CLEAN_vars     :=
+PASS_CLEAN_pass     := clean
+# alias
+.PHONY: clean
+clean: pass_clean
+
+## PASS: nothing
+# This pass just walks the tree.
+PASS_NOTHING        := Nothing
+PASS_NOTHING_trgs   := do-nothing
+PASS_NOTHING_vars   :=
+PASS_NOTHING_pass   := nothing
+# alias
+.PHONY: nothing
+nothing: pass_nothing
+
+## DEFAULT_PASSES
+# The default passes and their order.
+DEFAULT_PASSES := BLDPROGS LIBRARIES DLLS BINARIES OTHERS INSTALLS
+
+## PASSES
+# The passes that should be defined. This must include
+# all passes mentioned by DEFAULT_PASSES.
+PASSES := FETCHES PATCHES $(DEFAULT_PASSES) TESTING PACKING CLEAN NOTHING
+
+
+#
+# Check for --pretty-command-printing before including the Config.kmk
+# so that anyone overriding the message macros can take the implied
+# verbosity level change into account.
+#
+ifndef KBUILD_VERBOSE
+ ifndef KBUILD_QUIET
+  ifeq ($(KMK_OPTS_PRETTY_COMMAND_PRINTING),1)
+   export KBUILD_VERBOSE := 2
+  endif
+ endif
+endif
+
+
+#
+# Legacy variable translation.
+# These will be eliminated when switching to the next version.
+#
+ifdef USE_KOBJCACHE
+ ifndef KBUILD_USE_KOBJCACHE
+  export KBUILD_USE_KOBJCACHE := $(USE_KOBJCACHE)
+ endif
+endif
+
+
+#
+# This is how we find the closest config.kmk.
+# It's a little hacky but I think it works fine.
+#
+_CFGDIR     := .
+_CFGFILES   := ./Config.kmk ./config.kmk
+define def_include_config
+$(eval _CFGDIR := $(_CFGDIR)/$(dir))
+_CFGFILES   += $(_CFGDIR)/Config.kmk $(_CFGDIR)/config.kmk
+endef
+# walk down the _RELATIVE_ path specified by DEPTH.
+$(foreach dir,$(subst /, ,$(DEPTH)), $(eval $(def_include_config)) )
+# add the default config file.
+_CFGFILE    := $(firstword $(wildcard $(_CFGFILES) $(FILE_KBUILD_CONFIG)))
+_CFGFILES   :=
+_CFGDIR     :=
+ifeq ($(_CFGFILE),)
+$(error kBuild: no Config.kmk file found! Check the DEPTH: DEPTH='$(DEPTH)' PATH_CURRENT='$(PATH_CURRENT)')
+endif
+
+# Include the config.kmk we found file (or the default one).
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - including $(_CFGFILE))
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+
+ include $(_CFGFILE)
+
+ _KBUILD_TS_NOW := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_NOW), $(_KBUILD_TS_PREV)) - included $(_CFGFILE))
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_NOW)
+else
+ include $(_CFGFILE)
+endif
+
+
+
+#
+# Finalize a the central path variables now that we've included the Config.kmk file.
+#
+# This prevents some trouble when users override the defaults for these
+# variables and uses relative paths or paths with incorrect case.
+#
+PATH_OUT_BASE := $(abspath $(PATH_OUT_BASE))
+PATH_OUT    := $(abspath $(PATH_OUT))
+PATH_OBJ    := $(abspath $(PATH_OBJ))
+PATH_TARGET := $(abspath $(PATH_TARGET))
+PATH_INS    := $(abspath $(PATH_INS))
+PATH_BIN    := $(abspath $(PATH_BIN))
+PATH_DLL    := $(abspath $(PATH_DLL))
+PATH_SYS    := $(abspath $(PATH_SYS))
+PATH_LIB    := $(abspath $(PATH_LIB))
+PATH_DOC    := $(abspath $(PATH_DOC))
+
+
+#
+# Setup the message style. The default one is inlined.
+#
+# See kBuild/msgstyles for more styles or use KBUILD_MSG_STYLE_PATHS
+# to create your own message style.
+#
+KBUILD_MSG_STYLE ?= default
+ifeq ($(KBUILD_MSG_STYLE),default)
+ #
+ # The 'default' style.
+ #
+
+ ## Fetch starting.
+ # @param 1     Target name.
+ MSG_FETCH    ?= $(call MSG_L1,Fetching $1...)
+ ## Re-fetch starting.
+ # @param 1     Target name.
+ MSG_REFETCH  ?= $(call MSG_L1,Re-fetching $1...)
+ ## Downloading a fetch component.
+ # @param 1     Target name.
+ # @param 2     The source URL.
+ # @param 3     The destination file name.
+ MSG_FETCH_DL ?= $(call MSG_L1,Downloading $1 - $2,=> $3)
+ ## Checking a fetch component.
+ # @param 1     Target name.
+ # @param 2     The source URL.
+ # @param 3     The destination file name.
+ MSG_FETCH_CHK?= $(call MSG_L1,Checking $1 - $3, ($2))
+ ## Unpacking a fetch component.
+ # @param 1     Target name.
+ # @param 2     The archive file name.
+ # @param 3     The target directory.
+ MSG_FETCH_UP ?= $(call MSG_L1,Unpacking $1 - $2 => $3)
+ ## Fetch completed.
+ # @param 1     Target name.
+ MSG_FETCH_OK ?= $(call MSG_L1,Successfully fetched $1)
+ ## Unfetch a fetch target.
+ # @param 1     Target name.
+ MSG_UNFETCH  ?= $(call MSG_L1,Unfetching $1...)
+ ## Compiling a source file.
+ # @param 1     Target name.
+ # @param 2     The source filename.
+ # @param 3     The primary link output file name.
+ # @param 4     The source type (C,CXX,OBJC,AS,RC,++).
+ MSG_COMPILE  ?= $(call MSG_L1,Compiling $1 - $2,=> $3)
+ ## Tool
+ # @param 1     The tool name (bin2c,...)
+ # @param 2     Target name.
+ # @param 3     The source filename.
+ # @param 4     The primary output file name.
+ MSG_TOOL     ?= $(call MSG_L1,$1 $2 - $3,=> $4)
+ ## Generate a file, typically a source file.
+ # @param 1     Target name if applicable.
+ # @param 2     Output file name.
+ # @param 3     What it's generated from
+ MSG_GENERATE ?= $(call MSG_L1,Generating $(if $1,$1 - )$2,$(if $3,from $3))
+ ## Linking a bldprog/dll/program/sysmod target.
+ # @param 1     Target name.
+ # @param 2     The primary link output file name.
+ # @param 3     The link tool operation (LINK_LIBRARY,LINK_PROGRAM,LINK_DLL,LINK_SYSMOD,++).
+ MSG_LINK     ?= $(call MSG_L1,Linking $1,=> $2)
+ ## Merging a library into the target (during library linking).
+ # @param 1     Target name.
+ # @param 2     The output library name.
+ # @param 3     The input library name.
+ MSG_AR_MERGE ?= $(call MSG_L1,Merging $3 into $1, ($2))
+ ## Creating a directory (build).
+ # @param 1     Directory name.
+ MSG_MKDIR    ?= $(call MSG_L2,Creating directory $1)
+ ## Cleaning.
+ MSG_CLEAN    ?= $(call MSG_L1,Cleaning...)
+ ## Nothing.
+ MSG_NOTHING  ?= $(call MSG_L1,Did nothing in $(CURDIR))
+ ## Pass
+ # @param 1     The pass name.
+ MSG_PASS     ?= $(call MSG_L1,Pass - $1)
+ ## Installing a bldprog/lib/dll/program/sysmod target.
+ # @param 1     Target name.
+ # @param 2     The source filename.
+ # @param 3     The destination file name.
+ MSG_INST_TRG ?= $(call MSG_L1,Installing $1 => $3)
+ ## Installing a file (install target).
+ # @param 1     The source filename.
+ # @param 2     The destination filename.
+ MSG_INST_FILE?= $(call MSG_L1,Installing $2,(<= $1))
+ ## Installing a symlink.
+ # @param 1     Symlink
+ # @param 2     Link target
+ MSG_INST_SYM ?= $(call MSG_L1,Installing symlink $1,=> $2)
+ ## Installing a directory.
+ # @param 1     Directory name.
+ MSG_INST_DIR ?= $(call MSG_L1,Installing directory $1)
+
+else
+ _KBUILD_MSG_STYLE_FILE := $(firstword $(foreach path, $(KBUILD_MSG_STYLE_PATHS) $(KBUILD_PATH)/msgstyles, $(wildcard $(path)/$(KBUILD_MSG_STYLE).kmk)))
+ ifneq ($(_KBUILD_MSG_STYLE_FILE),)
+  include $(_KBUILD_MSG_STYLE_FILE)
+ else
+  $(error kBuild: Can't find the style setup file for KBUILD_MSG_STYLE '$(KBUILD_MSG_STYLE)')
+ endif
+endif
+
+
+#
+# Message macros.
+#
+# This is done after including Config.kmk as to allow for
+# KBUILD_QUIET and KBUILD_VERBOSE to be configurable.
+#
+ifdef KBUILD_QUIET
+ # No output
+ QUIET := @
+ QUIET2:= @
+ MSG_L1	=
+ MSG_L2 =
+else
+ ifndef KBUILD_VERBOSE
+  # Default output level.
+  QUIET  := @
+  QUIET2 := @
+  MSG_L1 ?= %@$(ECHO) "kBuild: $1"
+  MSG_L2  =
+ else ifeq ($(KBUILD_VERBOSE),1)
+  # A bit more output
+  QUIET  := @
+  QUIET2 := @
+  MSG_L1 ?= %@$(ECHO) "kBuild: $1 $2"
+  MSG_L2  =
+ else ifeq ($(KBUILD_VERBOSE),2)
+  # Lot more output
+  QUIET  :=
+  QUIET2 := @
+  MSG_L1 ?= %@$(ECHO) "kBuild: $1 $2"
+  MSG_L2 ?= %@$(ECHO) "kBuild: $1"
+ else
+  # maximal output.
+  QUIET  :=
+  QUIET2 :=
+  MSG_L1 ?= %@$(ECHO) "kBuild: $1 $2"
+  MSG_L2 ?= %@$(ECHO) "kBuild: $1"
+ endif
+endif
+
+
+#
+# Validate any KBUILD_BLD_TYPES additions and finally the KBUILD_TYPE.
+#
+if1of ($(KBUILD_BLD_TYPES), $(KBUILD_OSES))
+ $(error kBuild: found KBUILD_BLD_TYPES in KBUILD_OSES!)
+endif
+if1of ($(KBUILD_BLD_TYPES), $(KBUILD_ARCHES))
+ $(error kBuild: found KBUILD_BLD_TYPES in KBUILD_ARCHES!)
+endif
+if1of ($(KBUILD_OSES), $(KBUILD_ARCHES))
+ $(error kBuild: found KBUILD_OSES in KBUILD_ARCHES!)
+endif
+ifn1of ($(KBUILD_TYPE), $(KBUILD_BLD_TYPES))
+ $(error kBuild: KBUILD_TYPE(=$(KBUILD_TYPE)) is not found in KBUILD_BLD_TYPES(=$(KBUILD_BLD_TYPES))!)
+endif
+
+
+
+ifdef KBUILD_PROFILE_SELF
+ _KBUILD_TS_HEADER_END := $(nanots )
+ $(info prof: $(int-sub $(_KBUILD_TS_HEADER_END), $(_KBUILD_TS_HEADER_START)) - $(int-sub $(_KBUILD_TS_HEADER_END), $(_KBUILD_TS_PREV)) - end of header.kmk)
+ $(info stat: $(make-stats ))
+ _KBUILD_TS_PREV := $(_KBUILD_TS_HEADER_END)
+endif
+
+# end-of-file-content
+__header_kmk__ := 1
+endif # __header_kmk__
+
+
Index: /tags/kBuild-0.1.4/kBuild/msgstyles/brief.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/msgstyles/brief.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/msgstyles/brief.kmk	(revision 1780)
@@ -0,0 +1,123 @@
+# $Id$
+## @file
+# kBuild Message Style - 'brief'
+#
+
+#
+# Copyright (c) 2007-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+# Indent the messages, drop the kBuild: prefix, and shorten paths.
+ifndef KBUILD_VERBOSE
+ ifndef MSG_L1
+  MSG_L1 = @$(PRINTF) "  %-7s %s\n" \
+	"$(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1))))" \
+	"$(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$2))))"
+ endif
+else
+ MSG_L1 ?= @$(ECHO) "  $(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1 $2))))"
+ MSG_L2 ?= @$(ECHO) "  $(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1))))"
+endif
+
+## Fetch starting.
+# @param 1     Target name.
+MSG_FETCH    ?= $(call MSG_L1,FTCH,$1...)
+## Re-fetch starting.
+# @param 1     Target name.
+MSG_REFETCH  ?= $(call MSG_L1,RFTCH,$1...)
+## Downloading a fetch component.
+# @param 1     Target name.
+# @param 2     The source URL.
+# @param 3     The destination file name.
+MSG_FETCH_DL ?= $(call MSG_L1,GET,$1 - $2,=> $3)
+## Checking a fetch component.
+# @param 1     Target name.
+# @param 2     The source URL.
+# @param 3     The destination file name.
+MSG_FETCH_CHK?= $(call MSG_L1,CHK,$1 - $3, ($2))
+## Unpacking a fetch component.
+# @param 1     Target name.
+# @param 2     The archive file name.
+# @param 3     The target directory.
+MSG_FETCH_UP ?= $(call MSG_L1,UNPK,$1 - $2,=> $3)
+## Fetch completed.
+# @param 1     Target name.
+MSG_FETCH_OK ?= $(call MSG_L1,DONE,$1)
+## Unfetch a fetch target.
+# @param 1     Target name.
+MSG_UNFETCH  ?= $(call MSG_L1,RM,$1...)
+## Compiling a source file.
+# @param 1     Target name.
+# @param 2     The source filename.
+# @param 3     The primary link output file name.
+# @param 4     The source type (CXX,C,AS,RC,++).
+MSG_COMPILE  ?= $(call MSG_L1,$4,$1 - $2,=> $3)
+## Tool
+# @param 1     The tool name (bin2c,...)
+# @param 2     Target name.
+# @param 3     The source filename.
+# @param 4     The primary output file name.
+MSG_TOOL     ?= $(call MSG_L1,$1,$2 - $3,=> $4)
+## Generate a file, typically a source file.
+# @param 1     Target name if applicable.
+# @param 2     Output file name.
+# @param 3     What it's generated from
+MSG_GENERATE ?= $(call MSG_L1,GEN,$2)
+## Linking a bldprog/dll/program/sysmod target.
+# @param 1     Target name.
+# @param 2     The primary link output file name.
+# @param 3     The link tool operation (LINK_LIBRARY,LINK_PROGRAM,LINK_DLL,LINK_SYSMOD,++).
+MSG_LINK     ?= $(call MSG_L1,$(if $(eq $3,LINK_LIBRARY),AR,LD),$1,=> $2)
+## Merging a library into the target (during library linking).
+# @param 1     Target name.
+# @param 2     The output library name.
+# @param 3     The input library name.
+MSG_AR_MERGE ?= $(NO_SUCH_VARIABLE)
+## Creating a directory (build).
+# @param 1     Directory name.
+MSG_MKDIR    ?= $(call MSG_L2,DIR,$1)
+## Cleaning.
+MSG_CLEAN    ?= $(call MSG_L1,CLEAN)
+## Nothing.
+MSG_NOTHING  ?= $(call MSG_L1,NOTHING $(CURDIR))
+## Installing a bldprog/lib/dll/program/sysmod target.
+# @param 1     Target name.
+# @param 2     The source filename.
+# @param 3     The destination file name.
+MSG_INST_TRG ?= $(call MSG_L1,INST,$1 => $3)
+## Installing a file (install target).
+# @param 1     The source filename.
+# @param 2     The destination filename.
+MSG_INST_FILE?= $(call MSG_L1,IFIL,$2,(<= $1))
+## Installing a symlink.
+# @param 1     Symlink
+# @param 2     Link target
+MSG_INST_SYM ?= $(call MSG_L1,ISYM,$1,=> $2)
+## Installing a directory.
+# @param 1     Directory name.
+MSG_INST_DIR ?= $(call MSG_L1,IDIR,$1)
+
Index: /tags/kBuild-0.1.4/kBuild/rules.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/rules.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/rules.kmk	(revision 1780)
@@ -0,0 +1,44 @@
+# $Id$
+## @file
+# kBuild - File included at top of makefile.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+ifdef PATH_KBUILD
+# Usual location.
+include $(PATH_KBUILD)/header.kmk
+else
+# Default location.
+include $(DEPTH)/kBuild/header.kmk
+endif
+
+# PATH_KBUILD is defined now.
+include $(PATH_KBUILD)/footer.kmk
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/DXSDK.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/DXSDK.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/DXSDK.kmk	(revision 1780)
@@ -0,0 +1,67 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Direct X SDK, targeting $(KBUILD_TARGET).
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_DXSDK := The Microsoft Direct X SDK, targeting $(KBUILD_TARGET)
+
+# SDK Specific Properties
+ifndef PATH_SDK_DXSDK
+ ## @todo which order is logical here, BLD and then TRG or the other way?
+ PATH_SDK_DXSDK := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/dxsdk/2*))
+ ifeq ($(PATH_SDK_DXSDK),)
+  PATH_SDK_DXSDK := $(sort $(wildcard $(PATH_DEVTOOLS_TRG)/dxsdk/2*))
+ endif
+ ifeq ($(PATH_SDK_DXSDK),)
+  PATH_SDK_DXSDK := $(sort $(wildcard $(PATH_DEVTOOLS)/win.x86/dxsdk/2*))
+ endif
+ ifeq ($(PATH_SDK_DXSDK),)
+  PATH_SDK_DXSDK := $(sort $(wildcard $(PATH_DEVTOOLS)/win.amd64/dxsdk/2*))
+ endif
+ ifneq ($(PATH_SDK_DXSDK),)
+  PATH_SDK_DXSDK := $(call lastword,$(PATH_SDK_DXSDK))
+ else
+  $(warning kBuild: PATH_SDK_DXSDK couldn't be determined!)
+  PATH_SDK_DXSDK := $(PATH_DEVTOOLS_TRG)/dxsdk/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_DXSDK := $(PATH_SDK_DXSDK)
+endif
+PATH_SDK_DXSDK_INC ?= $(PATH_SDK_DXSDK)/Include
+PATH_SDK_DXSDK_LIB.x86 ?= $(PATH_SDK_DXSDK)/Lib/x86
+PATH_SDK_DXSDK_LIB.amd64 ?= $(PATH_SDK_DXSDK)/Lib/x64
+PATH_SDK_DXSDK_LIB ?= $(PATH_SDK_DXSDK_LIB.$(KBUILD_TARGET_ARCH))
+
+# General Properties used by kBuild
+SDK_DXSDK_INCS ?= $(PATH_SDK_DXSDK_INC)
+SDK_DXSDK_LIBPATH ?= $(PATH_SDK_DXSDK_LIB)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/DXSDKAMD64.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/DXSDKAMD64.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/DXSDKAMD64.kmk	(revision 1780)
@@ -0,0 +1,62 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Direct X SDK, targeting AMD64.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_DXSDKAMD64 := The Microsoft Direct X SDK, targeting AMD64.
+
+# SDK Specific Properties
+ifndef PATH_SDK_DXSDKAMD64
+ PATH_SDK_DXSDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/dxsdk/2*)
+ ifeq ($(PATH_SDK_DXSDKAMD64),)
+  PATH_SDK_DXSDKAMD64 := $(PATH_SDK_DXSDK)
+ endif
+ ifeq ($(PATH_SDK_DXSDKAMD64),)
+  PATH_SDK_DXSDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/dxsdk/2*)
+ endif
+ ifneq ($(PATH_SDK_DXSDKAMD64),)
+  PATH_SDK_DXSDKAMD64 := $(lastword $(sort $(PATH_SDK_DXSDKAMD64)))
+ else
+  $(warning kBuild: PATH_SDK_DXSDKAMD64 couldn't be determined!)
+  PATH_SDK_DXSDKAMD64 := $(PATH_DEVTOOLS)/win.amd64/dxsdk/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_DXSDKAMD64 := $(PATH_SDK_DXSDKAMD64)
+endif
+PATH_SDK_DXSDKAMD64_INC ?= $(PATH_SDK_DXSDKAMD64)/Include
+PATH_SDK_DXSDKAMD64_LIB ?= $(PATH_SDK_DXSDKAMD64)/Lib/x64
+
+# General Properties used by kBuild
+SDK_DXSDKAMD64_INCS ?= $(PATH_SDK_DXSDKAMD64_INC)
+SDK_DXSDKAMD64_LIBPATH ?= $(PATH_SDK_DXSDKAMD64_LIB)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/DXSDKX86.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/DXSDKX86.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/DXSDKX86.kmk	(revision 1780)
@@ -0,0 +1,62 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Direct X SDK, targeting X86.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+
+SDK_DXSDKX86 := The Microsoft Direct X SDK, targeting X86.
+
+# SDK Specific Properties
+ifndef PATH_SDK_DXSDKX86
+ PATH_SDK_DXSDKX86 := $(wildcard $(PATH_DEVTOOLS)/win.x86/dxsdk/2*)
+ ifeq ($(PATH_SDK_DXSDKX86),)
+  PATH_SDK_DXSDKX86 := $(PATH_SDK_DXSDK)
+ endif
+ ifeq ($(PATH_SDK_DXSDKX86),)
+  PATH_SDK_DXSDKX86 := $(wildcard $(PATH_DEVTOOLS)/amd64.win/dxsdk/2*)
+ endif
+ ifneq ($(PATH_SDK_DXSDKX86),)
+  PATH_SDK_DXSDKX86 := $(lastword $(sort $(PATH_SDK_DXSDKX86)))
+ else
+  $(warning kBuild: PATH_SDK_DXSDKX86 couldn't be determined!)
+  PATH_SDK_DXSDKX86 := $(PATH_DEVTOOLS)/win.x86/dxsdk/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_DXSDKX86 := $(PATH_SDK_DXSDKX86)
+endif
+PATH_SDK_DXSDKX86_INC ?= $(PATH_SDK_DXSDKX86)/Include
+PATH_SDK_DXSDKX86_LIB ?= $(PATH_SDK_DXSDKX86)/Lib/x86
+
+# General Properties used by kBuild
+SDK_DXSDKX86_INCS ?= $(PATH_SDK_DXSDKX86_INC)
+SDK_DXSDKX86_LIBPATH ?= $(PATH_SDK_DXSDKX86_LIB)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/LIBSDL.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/LIBSDL.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/LIBSDL.kmk	(revision 1780)
@@ -0,0 +1,196 @@
+# $Id$
+## @file
+# kBuild SDK - Simple DirectMedia Layer, targeting $(KBUILD_TARGET).
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_LIBSDL := Simple DirectMedia Layer, targeting $(KBUILD_TARGET).
+
+# SDK Specific Properties
+_SDK_LIBSDK_IS_FRAMEWORK := no
+ifndef PATH_SDK_LIBSDL
+ PATH_SDK_LIBSDL := $(wildcard $(PATH_DEVTOOLS_TRG)/libsdl/v*)
+ ifeq ($(PATH_SDK_LIBSDL),)
+  PATH_SDK_LIBSDL := $(wildcard $(PATH_DEVTOOLS_BLD)/libsdl/v*)
+ endif
+ ifneq ($(PATH_SDK_LIBSDL),)
+  PATH_SDK_LIBSDL := $(lastword $(sort $(PATH_SDK_LIBSDL)))
+ else
+
+  # Darwin might have a framework for it.
+  ifeq ($(KBUILD_TARGET),darwin)
+   PATH_SDK_LIBSDL := $(firstword $(wildcard \
+	/System/Library/Frameworks/SDL.framework/SDL \
+	/Library/Frameworks/SDL.framework/SDL \
+	) )
+   ifneq ($(PATH_SDK_LIBSDL),)
+    PATH_SDK_LIBSDL := $(patsubst %/,%,$(dir $(PATH_SDK_LIBSDL)))
+    _SDK_LIBSDK_IS_FRAMEWORK := yes
+   endif
+  endif
+
+  ifeq ($(PATH_SDK_LIBSDL),)
+   # Search in the typical unix places.
+   ifeq ($(filter-out %64,$(KBUILD_TARGET_ARCH)),)
+    PATH_SDK_LIBSDL := $(firstword $(wildcard \
+	/lib64/libSDL.* \
+	/lib/libSDL.* \
+	/usr/lib64/libSDL.* \
+	/usr/lib/libSDL.* \
+	/usr/local/lib64/libSDL.* \
+	/usr/local/lib/libSDL.* \
+	/opt/lib64/libSDL.* \
+	/opt/lib/libSDL.* \
+	/opt/local/lib64/libSDL.* \
+	/opt/local/lib/libSDL.* \
+	/sw/lib64/libSDL.* \
+	/sw/lib/libSDL.* \
+	) )
+   else
+    PATH_SDK_LIBSDL := $(firstword $(wildcard \
+	/lib32/libSDL.* \
+	/lib/libSDL.* \
+	/usr/lib32/libSDL.* \
+	/usr/lib/libSDL.* \
+	/usr/local/lib32/libSDL.* \
+	/usr/local/lib/libSDL.* \
+	/opt/lib32/libSDL.* \
+	/opt/lib/libSDL.* \
+	/opt/local/lib32/libSDL.* \
+	/opt/local/lib/libSDL.* \
+	/sw/lib32/libSDL.* \
+	/sw/lib/libSDL.* \
+	) )
+   endif
+   ifneq ($(PATH_SDK_LIBSDL),)
+    PATH_SDK_LIBSDL := $(patsubst %/,%,$(dir $(patsubst %/,%,$(dir $(PATH_SDK_LIBSDL)))))
+   else
+    $(warning kBuild: PATH_SDK_LIBSDL couldn't be determined!)
+    PATH_SDK_LIBSDL := $(PATH_DEVTOOLS_TRG)/libsdl/not/found
+   endif
+  endif
+ endif
+else
+ PATH_SDK_LIBSDL := $(PATH_SDK_LIBSDL)
+ ifeq ($(KBUILD_TARGET),darwin)
+  # Check if it's the framework or not.
+  _SDK_LIBSDK_IS_FRAMEWORK := $(if $(wildcard $(PATH_SDK_LIBSDL)/Headers/SDL.h),yes)
+ endif
+endif
+
+#
+# The way libsdl is distributed on the different platforms
+# varies quite a bit, thus this kludge.
+#
+ifeq ($(KBUILD_TARGET),os2)
+ LIB_SDK_LIBSDL_SDLMAIN  ?=
+ DLL_SDK_LIBSDL_SDL      ?= $(PATH_SDK_LIBSDL)/SDL/SDL12.dll
+ DLL_SDK_LIBSDL_FSLIB    ?= $(PATH_SDK_LIBSDL)/SDL/FSLib.dll
+ LIB_SDK_LIBSDL_SDL      ?= $(PATH_SDK_LIBSDL)/SDL/SDL12.lib
+ LIB_SDK_LIBSDL_SDLGFX   ?= $(PATH_SDK_LIBSDL)/SDLGfx/SDLGFX.lib
+ LIB_SDK_LIBSDL_SDLIMAGE ?= $(PATH_SDK_LIBSDL)/SDLImage/SDLIMAGE.lib
+ LIB_SDK_LIBSDL_SDLMIXER ?= $(PATH_SDK_LIBSDL)/SDLMixer/SDLMIXER.lib
+ LIB_SDK_LIBSDL_SDLNET   ?= $(PATH_SDK_LIBSDL)/SDLNet/SDLNET.lib
+ LIB_SDK_LIBSDL_SDLTTF   ?= $(PATH_SDK_LIBSDL)/SDLTTF/SDLTTF.lib
+
+ # General Properties used by kBuild
+ SDK_LIBSDL_INCS ?= \
+ 	$(PATH_SDK_LIBSDL)/SDL/include \
+ 	$(PATH_SDK_LIBSDL)/SDLGfx \
+ 	$(PATH_SDK_LIBSDL)/SDLImage \
+ 	$(PATH_SDK_LIBSDL)/SDLMixer \
+ 	$(PATH_SDK_LIBSDL)/SDLNet \
+ 	$(PATH_SDK_LIBSDL)/SDLTTF
+ SDK_LIBSDL_LIBS ?= \
+ 	$(LIB_SDK_LIBSDL_SDL)
+ SDK_LIBSDL_LIBPATH ?= \
+ 	$(PATH_SDK_LIBSDL)/SDL \
+ 	$(PATH_SDK_LIBSDL)/SDLGfx \
+ 	$(PATH_SDK_LIBSDL)/SDLImage \
+ 	$(PATH_SDK_LIBSDL)/SDLMixer \
+ 	$(PATH_SDK_LIBSDL)/SDLNet \
+ 	$(PATH_SDK_LIBSDL)/SDLTTF
+
+else ifeq ($(KBUILD_TARGET),win) # ASSUMES VC++ on windows, sorry.
+ LIB_SDK_LIBSDL_SDLMAIN  ?= $(PATH_SDK_LIBSDL)/lib/SDLmain.lib
+ LIB_SDK_LIBSDL_SDL      ?= $(PATH_SDK_LIBSDL)/lib/SDL.lib
+ DLL_SDK_LIBSDL_SDL      ?= $(PATH_SDK_LIBSDL)/lib/SDL.dll
+ LIB_SDK_LIBSDL_SDLGFX   ?= $(PATH_SDK_LIBSDL)/lib/SDL_gfx.lib
+ LIB_SDK_LIBSDL_SDLIMAGE ?= $(PATH_SDK_LIBSDL)/lib/SDL_image.lib
+ LIB_SDK_LIBSDL_SDLMIXER ?= $(PATH_SDK_LIBSDL)/lib/SDL_mixer.lib
+ LIB_SDK_LIBSDL_SDLNET   ?= $(PATH_SDK_LIBSDL)/lib/SDL_net.lib
+ LIB_SDK_LIBSDL_SDLTTF   ?= $(PATH_SDK_LIBSDL)/lib/SDL_ttf.lib
+ DLL_SDK_LIBSDL_SDLTTF   ?= $(PATH_SDK_LIBSDL)/lib/SDL_ttf.dll
+
+ # General Properties used by kBuild
+ SDK_LIBSDL_INCS ?= \
+	$(PATH_SDK_LIBSDL)/include/SDL \
+	$(PATH_SDK_LIBSDL)/include
+ SDK_LIBSDL_LIBS ?= \
+	$(LIB_SDK_LIBSDL_SDL)
+ SDK_LIBSDL_LIBPATH ?= \
+ 	$(PATH_SDK_LIBSDL)/lib
+
+else ifeq ($(KBUILD_TARGET).$(_SDK_LIBSDK_IS_FRAMEWORK),darwin.yes)
+ # darwin + framework
+ LIB_SDK_LIBSDL_SDLMAIN  ?= $(NO_SUCH_VARIABLE)
+ LIB_SDK_LIBSDL_SDL      ?= $(NO_SUCH_VARIABLE)
+ LIB_SDK_LIBSDL_SDLGFX   ?= $(NO_SUCH_VARIABLE)
+ LIB_SDK_LIBSDL_SDLIMAGE ?= $(NO_SUCH_VARIABLE)
+ LIB_SDK_LIBSDL_SDLMIXER ?= $(NO_SUCH_VARIABLE)
+ LIB_SDK_LIBSDL_SDLNET   ?= $(NO_SUCH_VARIABLE)
+ LIB_SDK_LIBSDL_SDLTTF   ?= $(NO_SUCH_VARIABLE)
+
+ # General Properties used by kBuild
+ SDK_LIBSDL_INCS         ?= $(PATH_SDK_LIBSDL)/Headers
+ SDK_LIBSDL_LDFLAGS      ?= -framework SDL
+
+else # ASSUMES Unix like system
+ LIB_SDK_LIBSDL_SDLMAIN  ?= SDLmain
+ LIB_SDK_LIBSDL_SDL      ?= SDL
+ LIB_SDK_LIBSDL_SDLGFX   ?= SDL_gfx
+ LIB_SDK_LIBSDL_SDLIMAGE ?= SDL_image
+ LIB_SDK_LIBSDL_SDLMIXER ?= SDL_mixer
+ LIB_SDK_LIBSDL_SDLNET   ?= SDL_net
+ LIB_SDK_LIBSDL_SDLTTF   ?= SDL_ttf
+
+ # General Properties used by kBuild
+ ifndef SDK_LIBSDL_INCS
+  ifneq ($(wildcard $(PATH_SDK_LIBSDL)/include/SDL/),)
+   SDK_LIBSDL_INCS := $(PATH_SDK_LIBSDL)/include/SDL
+  else
+   SDK_LIBSDL_INCS := $(PATH_SDK_LIBSDL)/include
+  endif
+ endif
+ SDK_LIBSDL_LIBS ?= \
+	$(LIB_SDK_LIBSDL_SDL)
+ SDK_LIBSDL_LIBPATH ?= \
+ 	$(PATH_SDK_LIBSDL)/lib
+endif
Index: /tags/kBuild-0.1.4/kBuild/sdks/MACOSX104.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/MACOSX104.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/MACOSX104.kmk	(revision 1780)
@@ -0,0 +1,51 @@
+# $Id$
+## @file
+# kBuild SDK - Mac OS X v10.4 SDK.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_MACOSX104 := Mac OS X v10.4 SDK
+
+# SDK Specific Properties
+ifndef PATH_SDK_MACOSX104
+ PATH_SDK_MACOSX104 := /Developer/SDKs/MacOSX10.4u.sdk
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_MACOSX104 := $(PATH_SDK_MACOSX104)
+endif
+
+# General Properties (used by kBuild)
+# Note: The MAC_OS_X_VERSION_MAX_ALLOWED is left free for the SDK user to define.
+SDK_MACOSX104_DEFS      ?= MAC_OS_X_VERSION_MIN_REQUIRED=1040
+SDK_MACOSX104_CFLAGS    ?= -mmacosx-version-min=10.4 -isysroot $(PATH_SDK_MACOSX104)
+SDK_MACOSX104_CXXFLAGS  ?= -mmacosx-version-min=10.4 -isysroot $(PATH_SDK_MACOSX104)
+SDK_MACOSX104_OBJCFLAGS ?= -mmacosx-version-min=10.4 -isysroot $(PATH_SDK_MACOSX104)
+SDK_MACOSX104_LDFLAGS   ?= -mmacosx-version-min=10.4 -Wl,-syslibroot,$(PATH_SDK_MACOSX104)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/MACOSX104INCS.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/MACOSX104INCS.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/MACOSX104INCS.kmk	(revision 1780)
@@ -0,0 +1,50 @@
+# $Id$
+## @file
+# kBuild SDK - Mac OS X v10.4 SDK, includes only.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_MACOSX104INCS := Mac OS X v10.4 SDK
+
+# SDK Specific Properties
+ifndef PATH_SDK_MACOSX104INCS
+ ifdef PATH_SDK_MACOSX104
+  PATH_SDK_MACOSX104INCS := $(PATH_SDK_MACOSX104)
+ else
+  PATH_SDK_MACOSX104INCS := /Developer/SDKs/MacOSX10.4u.sdk
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_MACOSX104INCS := $(PATH_SDK_MACOSX104INCS)
+endif
+
+# General Properties (used by kBuild)
+SDK_MACOSX104INCS_INCS   = $(PATH_SDK_MACOSX104INCS)/usr/include
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/MACOSX105.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/MACOSX105.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/MACOSX105.kmk	(revision 1780)
@@ -0,0 +1,51 @@
+# $Id$
+## @file
+# kBuild SDK - Mac OS X v10.5 SDK.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_MACOSX105 := Mac OS X v10.5 SDK
+
+# SDK Specific Properties
+ifndef PATH_SDK_MACOSX105
+ PATH_SDK_MACOSX105 := /Developer/SDKs/MacOSX10.5.sdk
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_MACOSX105 := $(PATH_SDK_MACOSX105)
+endif
+
+# General Properties (used by kBuild)
+# Note: The MAC_OS_X_VERSION_MAX_ALLOWED is left free for the SDK user to define.
+SDK_MACOSX105_DEFS      ?= MAC_OS_X_VERSION_MIN_REQUIRED=1050
+SDK_MACOSX105_CFLAGS    ?= -mmacosx-version-min=10.5 -isysroot $(PATH_SDK_MACOSX105)
+SDK_MACOSX105_CXXFLAGS  ?= -mmacosx-version-min=10.5 -isysroot $(PATH_SDK_MACOSX105)
+SDK_MACOSX105_OBJCFLAGS ?= -mmacosx-version-min=10.5 -isysroot $(PATH_SDK_MACOSX105)
+SDK_MACOSX105_LDFLAGS   ?= -mmacosx-version-min=10.5 -Wl,-syslibroot,$(PATH_SDK_MACOSX105)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/MACOSX105INCS.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/MACOSX105INCS.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/MACOSX105INCS.kmk	(revision 1780)
@@ -0,0 +1,50 @@
+# $Id$
+## @file
+# kBuild SDK - Mac OS X v10.5 SDK, includes only.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_MACOSX105INCS := Mac OS X v10.5 SDK
+
+# SDK Specific Properties
+ifndef PATH_SDK_MACOSX105INCS
+ ifdef PATH_SDK_MACOSX105
+  PATH_SDK_MACOSX105INCS := $(PATH_SDK_MACOSX105)
+ else
+  PATH_SDK_MACOSX105INCS := /Developer/SDKs/MacOSX10.5.sdk
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_MACOSX105INCS := $(PATH_SDK_MACOSX105INCS)
+endif
+
+# General Properties (used by kBuild)
+SDK_MACOSX105INCS_INCS   = $(PATH_SDK_MACOSX105INCS)/usr/include
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/NT4DDK.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/NT4DDK.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/NT4DDK.kmk	(revision 1780)
@@ -0,0 +1,59 @@
+# $Id$
+## @file
+# kBuild SDK - The Windows NT 4 DDK, targeting X86.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_NT4DDK := The MicroSoft NT 4 DDK, targeting X86 (free, not checked).
+
+# SDK Specific Properties
+ifndef PATH_SDK_NT4DDK
+ PATH_SDK_NT4DDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddknt4/1* $(PATH_DEVTOOLS)/win.x86/ddknt4/2*)
+ ifeq ($(PATH_SDK_NT4DDK),)
+  PATH_SDK_NT4DDK := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddknt4)
+ endif
+ ifneq ($(PATH_SDK_NT4DDK),)
+  PATH_SDK_NT4DDK := $(lastword $(sort $(PATH_SDK_NT4DDK)))
+ else
+  $(warning kBuild: PATH_SDK_NT4DDK couldn't be determined!)
+  PATH_SDK_NT4DDK := $(PATH_DEVTOOLS)/x86.win/ddknt4/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_NT4DDK := $(PATH_SDK_NT4DDK)
+endif
+PATH_SDK_NT4DDK_INC ?= $(PATH_SDK_NT4DDK)/inc
+PATH_SDK_NT4DDK_LIB ?= $(PATH_SDK_NT4DDK)/lib/i386/free
+
+# General Properties used by kBuild
+SDK_NT4DDK_DEFS ?= _X86_
+SDK_NT4DDK_INCS	?= $(PATH_SDK_NT4DDK_INC)
+SDK_NT4DDK_LIBPATH ?= $(PATH_SDK_NT4DDK_LIB)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDK.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDK.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDK.kmk	(revision 1780)
@@ -0,0 +1,81 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Windows 2003 DDK, targeting $(KBUILD_TARGET).
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_W2K3DDK := The Microsoft Windows 2003 DDK, targeting $(KBUILD_TARGET).
+
+# SDK Specific Properties
+ifndef PATH_SDK_W2K3DDK
+ PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS_TRG)/ddkwin2k3/2*)
+ ifeq ($(PATH_SDK_W2K3DDK),)
+  PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS_BLD)/ddkwin2k3/2*)
+ endif
+ ifeq ($(PATH_SDK_W2K3DDK),)
+  PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddkwin2k3/2*)
+ endif
+ ifeq ($(PATH_SDK_W2K3DDK),)
+  PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddkwin2k3/2*)
+ endif
+ ifeq ($(PATH_SDK_W2K3DDK),)
+  PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3/2*)
+ endif
+ ifeq ($(PATH_SDK_W2K3DDK),)
+  ifneq ($(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3/lib/wnet/i386/*.lib),)
+   PATH_SDK_W2K3DDK := $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3
+  endif
+ endif
+ ifneq ($(PATH_SDK_W2K3DDK),)
+  PATH_SDK_W2K3DDK := $(lastword $(sort $(PATH_SDK_W2K3DDK)))
+ else
+  $(warning kBuild: PATH_SDK_W2K3DDK couldn't be determined!)
+  PATH_SDK_W2K3DDK := $(PATH_DEVTOOLS)/win.x86/ddkwin2k3/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_W2K3DDK := $(PATH_SDK_W2K3DDK)
+endif
+PATH_SDK_W2K3DDK_INC ?= $(PATH_SDK_W2K3DDK)/inc
+PATH_SDK_W2K3DDK_LIB.amd64 ?= $(PATH_SDK_W2K3DDK)/lib/wnet/AMD64
+PATH_SDK_W2K3DDK_LIB.x86 ?= $(PATH_SDK_W2K3DDK)/lib/wnet/i386
+PATH_SDK_W2K3DDK_LIB ?= $(PATH_SDK_W2K3DDK_LIB.$(KBUILD_TARGET_ARCH))
+
+# General Properties used by kBuild
+SDK_W2K3DDK_DEFS.amd64 ?= _AMD64_
+SDK_W2K3DDK_DEFS.x86 ?= _X86_
+SDK_W2K3DDK_INCS ?= \
+	$(PATH_SDK_W2K3DDK_INC)/ddk \
+	$(PATH_SDK_W2K3DDK_INC)/ddk/wnet \
+	$(PATH_SDK_W2K3DDK_INC)/wnet \
+	$(PATH_SDK_W2K3DDK_INC)/ddk/wdm/wnet
+SDK_W2K3DDK_LIBPATH.amd64 ?= $(PATH_SDK_W2K3DDK_LIB.amd64)
+SDK_W2K3DDK_LIBPATH.x86 ?= $(PATH_SDK_W2K3DDK_LIB.x86)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDKAMD64.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDKAMD64.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDKAMD64.kmk	(revision 1780)
@@ -0,0 +1,71 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Windows 2003 DDK, targeting amd64.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_W2K3DDKAMD64 := The Microsoft Windows 2003 DDK, targeting amd64.
+
+# SDK Specific Properties
+ifndef PATH_SDK_W2K3DDKAMD64
+ PATH_SDK_W2K3DDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddkwin2k3/2*)
+ ifeq ($(PATH_SDK_W2K3DDKAMD64),)
+  PATH_SDK_W2K3DDKAMD64 := $(PATH_SDK_W2K3DDK)
+ endif
+ ifeq ($(PATH_SDK_W2K3DDKAMD64),)
+  PATH_SDK_W2K3DDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddkwin2k3/2*)
+ endif
+ # legacy:
+ ifeq ($(PATH_SDK_W2K3DDKAMD64),)
+  PATH_SDK_W2K3DDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3/2*)
+ endif
+ ifneq ($(PATH_SDK_W2K3DDKAMD64),)
+  PATH_SDK_W2K3DDKAMD64 := $(lastword $(sort $(PATH_SDK_W2K3DDKAMD64)))
+ else
+  $(warning kBuild: PATH_SDK_W2K3DDKAMD64 couldn't be determined!)
+  PATH_SDK_W2K3DDKAMD64 := $(PATH_DEVTOOLS)/win.amd64/ddkwin2k3/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_W2K3DDKAMD64 := $(PATH_SDK_W2K3DDKAMD64)
+endif
+PATH_SDK_W2K3DDKAMD64_INC ?= $(PATH_SDK_W2K3DDKAMD64)/inc
+PATH_SDK_W2K3DDKAMD64_LIB ?= $(PATH_SDK_W2K3DDKAMD64)/lib/wnet/AMD64
+
+# General Properties used by kBuild
+SDK_W2K3DDKAMD64_DEFS ?= _AMD64_
+SDK_W2K3DDKAMD64_INCS ?= \
+	$(PATH_SDK_W2K3DDKAMD64_INC)/ddk \
+	$(PATH_SDK_W2K3DDKAMD64_INC)/ddk/wnet \
+	$(PATH_SDK_W2K3DDKAMD64_INC)/wnet \
+	$(PATH_SDK_W2K3DDKAMD64_INC)/ddk/wdm/wnet
+SDK_W2K3DDKAMD64_LIBPATH ?= \
+	$(PATH_SDK_W2K3DDKAMD64_LIB)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDKX86.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDKX86.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/W2K3DDKX86.kmk	(revision 1780)
@@ -0,0 +1,74 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Windows 2003 DDK, targeting x86.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_W2K3DDKX86 := The Microsoft Windows 2003 DDK, targeting x86.
+
+# SDK Specific Properties
+ifndef PATH_SDK_W2K3DDKX86
+ PATH_SDK_W2K3DDKX86 := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddkwin2k3/2*)
+ ifeq ($(PATH_SDK_W2K3DDKX86),)
+  PATH_SDK_W2K3DDKX86 := $(PATH_SDK_W2K3DDK)
+ endif
+ ifeq ($(PATH_SDK_W2K3DDKX86),)
+  PATH_SDK_W2K3DDKX86 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddkwin2k3/2*)
+ endif
+ # legacy:
+ ifeq ($(PATH_SDK_W2K3DDKX86),)
+  PATH_SDK_W2K3DDKX86 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3/2*)
+ endif
+ ifeq ($(PATH_SDK_W2K3DDKX86),)
+  PATH_SDK_W2K3DDKX86 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3)
+ endif
+ ifneq ($(PATH_SDK_W2K3DDKX86),)
+  PATH_SDK_W2K3DDKX86 := $(lastword $(sort $(PATH_SDK_W2K3DDKX86)))
+ else
+  $(warning kBuild: PATH_SDK_W2K3DDKX86 couldn't be determined!)
+  PATH_SDK_W2K3DDKX86 := $(PATH_DEVTOOLS)/x86.win/ddkwin2k3/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_W2K3DDKX86 := $(PATH_SDK_W2K3DDKX86)
+endif
+PATH_SDK_W2K3DDKX86_INC ?= $(PATH_SDK_W2K3DDKX86)/inc
+PATH_SDK_W2K3DDKX86_LIB ?= $(PATH_SDK_W2K3DDKX86)/lib/wnet/i386
+
+# General Properties used by kBuild
+SDK_W2K3DDKX86_DEFS ?= _X86_
+SDK_W2K3DDKX86_INCS ?= \
+	$(PATH_SDK_W2K3DDKX86_INC)/ddk \
+	$(PATH_SDK_W2K3DDKX86_INC)/ddk/wnet \
+	$(PATH_SDK_W2K3DDKX86_INC)/wnet \
+	$(PATH_SDK_W2K3DDKX86_INC)/ddk/wdm/wnet
+SDK_W2K3DDKX86_LIBPATH	?= \
+	$(PATH_SDK_W2K3DDKX86_LIB)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/W32API.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/W32API.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/W32API.kmk	(revision 1780)
@@ -0,0 +1,58 @@
+# $Id$
+## @file
+# kBuild SDK - w32api (MinGW), targeting x86.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_W32API := w32api (MinGW), targeting x86.
+
+# SDK Specific Properties
+ifndef PATH_SDK_W32API
+ PATH_SDK_W32API := $(wildcard $(PATH_DEVTOOLS)/win.x86/w32api/v*)
+ ifeq ($(PATH_SDK_W32API),)
+  PATH_SDK_W32API := $(wildcard $(PATH_DEVTOOLS)/x86.win32/w32api/v*)
+ endif
+ ifneq ($(PATH_SDK_W32API),)
+  PATH_SDK_W32API := $(lastword $(sort $(PATH_SDK_W32API)))
+ else
+  $(warning kBuild: PATH_SDK_W32API couldn't be determined!)
+  PATH_SDK_W32API := $(PATH_DEVTOOLS)/x86.win/w32api/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_W32API := $(PATH_SDK_W32API)
+endif
+PATH_SDK_W32API_INC ?= $(PATH_SDK_W32API)/include
+PATH_SDK_W32API_LIB ?= $(PATH_SDK_W32API)/lib
+
+# General Properties used by kBuild
+SDK_W32API_INCS	?= $(PATH_SDK_W32API_INC)
+SDK_W32API_LIBPATH ?= $(PATH_SDK_W32API_LIB)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WIN32SDK.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WIN32SDK.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WIN32SDK.kmk	(revision 1780)
@@ -0,0 +1,93 @@
+# $Id$
+## @file
+# kBuild SDK - The Windows Platform SDK, targeting x86.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_WIN32SDK := The Windows Platform SDK, targeting x86.
+
+# SDK Specific Properties
+ifndef PATH_SDK_WIN32SDK
+ PATH_SDK_WIN32SDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*)
+ ifeq ($(PATH_SDK_WIN32SDK),)
+  PATH_SDK_WIN32SDK := $(PATH_SDK_WINPSDK)
+ endif
+ ifeq ($(PATH_SDK_WIN32SDK),)
+  PATH_SDK_WIN32SDK := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk/2*)
+ endif
+ ifeq ($(PATH_SDK_WIN32SDK),)
+  PATH_SDK_WIN32SDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*)
+ endif
+ ifneq ($(PATH_SDK_WIN32SDK),)
+  PATH_SDK_WIN32SDK := $(lastword $(sort $(PATH_SDK_WIN32SDK)))
+ else
+  $(warning kBuild: PATH_SDK_WIN32SDK couldn't be determined!)
+  PATH_SDK_WIN32SDK := $(PATH_DEVTOOLS)/win.x86/sdk/not/found
+ endif
+endif
+ifndef PATH_SDK_WIN32SDK_INC
+PATH_SDK_WIN32SDK_INC := $(firstword $(wildcard $(PATH_SDK_WIN32SDK)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WIN32SDK)/Include)
+endif
+ifndef PATH_SDK_WIN32SDK_LIB
+PATH_SDK_WIN32SDK_LIB := $(firstword $(wildcard $(PATH_SDK_WIN32SDK)/[Ll][Ii][Bb]) $(PATH_SDK_WIN32SDK)/Lib)
+endif
+ifndef PATH_SDK_WIN32SDK_BIN
+PATH_SDK_WIN32SDK_BIN := $(firstword $(wildcard $(PATH_SDK_WIN32SDK)/[Bb][Ii][Nn]) $(PATH_SDK_WIN32SDK)/Bin)
+endif
+
+
+# General Properties used by kBuild
+SDK_WIN32SDK_INCS ?= $(PATH_SDK_WIN32SDK_INC)
+SDK_WIN32SDK_LIBPATH ?= $(PATH_SDK_WIN32SDK_LIB)
+SDK_WIN32SDK_LIBS ?= \
+	$(PATH_SDK_WIN32SDK_LIB)/Kernel32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/User32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/Gdi32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/AdvAPI32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/Shell32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/ShLwApi.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/SetupAPI.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/Uuid.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/Version.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/WS2_32.Lib \
+	\
+	$(PATH_SDK_WIN32SDK_LIB)/Ole32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/OleAut32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/OleDlg.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/RpcRT4.Lib \
+	\
+	$(PATH_SDK_WIN32SDK_LIB)/DbgHelp.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/ImageHlp.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/IPHlpApi.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/ComCtl32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/ComDlg32.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/WinSpool.Lib \
+	$(PATH_SDK_WIN32SDK_LIB)/WinMM.Lib \
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WIN32SDK2002.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WIN32SDK2002.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WIN32SDK2002.kmk	(revision 1780)
@@ -0,0 +1,90 @@
+# $Id$
+## @file
+# kBuild SDK - Windows Platform SDK (from ~2002), targeting x86.
+#              Differs in that it has ddraw.lib and dxguid.lib.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+
+SDK_WIN32SDK2002 := Windows Platform SDK (from ~2002), targeting x86. \
+	Differs in that it has ddraw.lib and dxguid.lib.
+
+# SDK Specific Properties
+ifndef PATH_SDK_WIN32SDK2002
+ PATH_SDK_WIN32SDK2002 := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2002*)
+ ifeq ($(PATH_SDK_WIN32SDK2002),)
+  PATH_SDK_WIN32SDK2002 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk/2002*)
+ endif
+ ifeq ($(PATH_SDK_WIN32SDK2002),)
+  PATH_SDK_WIN32SDK2002 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk2002*)
+ endif
+ ifneq ($(PATH_SDK_WIN32SDK2002),)
+  PATH_SDK_WIN32SDK2002 := $(lastword $(sort $(PATH_SDK_WIN32SDK2002)))
+ else
+  $(warning kBuild: PATH_SDK_WIN32SDK2002 couldn't be determined!)
+  PATH_SDK_WIN32SDK2002 := $(PATH_DEVTOOLS)/win.x86/sdk/2002/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_WIN32SDK2002 := $(PATH_SDK_WIN32SDK2002)
+endif
+PATH_SDK_WIN32SDK2002_INC ?= $(PATH_SDK_WIN32SDK2002)/include
+PATH_SDK_WIN32SDK2002_LIB ?= $(PATH_SDK_WIN32SDK2002)/lib
+
+# General Properties used by kBuild
+SDK_WIN32SDK2002_INCS ?= $(PATH_SDK_WIN32SDK2002_INC)
+SDK_WIN32SDK2002_LIBPATH ?= $(PATH_SDK_WIN32SDK2002_LIB)
+SDK_WIN32SDK2002_LIBS ?= \
+	$(PATH_SDK_WIN32SDK2002_LIB)/Kernel32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/User32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/Gdi32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/AdvAPI32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/Shell32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/ShLwApi.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/SetupAPI.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/Uuid.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/Version.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/WS2_32.Lib \
+	\
+	$(PATH_SDK_WIN32SDK2002_LIB)/Ole32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/OleAut32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/OleDlg.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/RpcRT4.Lib \
+	\
+	$(PATH_SDK_WIN32SDK2002_LIB)/DbgHelp.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/ImageHlp.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/IPHlpApi.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/ddraw.lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/dxguid.lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/ComCtl32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/ComDlg32.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/WinSpool.Lib \
+	$(PATH_SDK_WIN32SDK2002_LIB)/WinMM.Lib
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WIN64SDK.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WIN64SDK.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WIN64SDK.kmk	(revision 1780)
@@ -0,0 +1,99 @@
+# $Id$
+## @file
+# kBuild SDK - The Windows Platform SDK, targeting AMD64.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+
+SDK_WIN64SDK := The Windows Platform SDK, targeting AMD64.
+
+# SDK Specific Properties
+ifndef PATH_SDK_WIN64SDK
+ PATH_SDK_WIN64SDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*)
+ ifeq ($(PATH_SDK_WIN64SDK),)
+  PATH_SDK_WIN64SDK := $(PATH_SDK_WINPSDK)
+ endif
+ ifeq ($(PATH_SDK_WIN64SDK),)
+  PATH_SDK_WIN64SDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*)
+ endif
+ ifneq ($(PATH_SDK_WIN64SDK),)
+  PATH_SDK_WIN64SDK := $(lastword $(sort $(PATH_SDK_WIN64SDK)))
+ else
+  $(warning kBuild: PATH_SDK_WIN64SDK couldn't be determined!)
+  PATH_SDK_WIN64SDK := $(PATH_DEVTOOLS)/win.amd64/sdk/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_WIN64SDK := $(PATH_SDK_WIN64SDK)
+endif
+ifndef PATH_SDK_WIN64SDK_INC
+PATH_SDK_WIN64SDK_INC := $(firstword $(wildcard $(PATH_SDK_WIN64SDK)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WIN64SDK)/Include)
+endif
+
+ifndef PATH_SDK_WIN64SDK_LIB
+PATH_SDK_WIN64SDK_LIB := $(firstword $(wildcard $(PATH_SDK_WIN64SDK)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64 $(PATH_SDK_WIN64SDK)/[Ll][Ii][Bb]/[xX]64) $(PATH_SDK_WIN64SDK)/Lib/AMD64)
+endif
+
+ifndef PATH_SDK_WIN64SDK_BIN
+PATH_SDK_WIN64SDK_BIN := $(firstword $(wildcard $(PATH_SDK_WIN64SDK)/[Bb][Ii][Nn]) $(PATH_SDK_WIN64SDK)/Bin)
+endif
+ifndef PATH_SDK_WIN64SDK_BIN_AMD64
+PATH_SDK_WIN64SDK_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WIN64SDK_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64 $(PATH_SDK_WIN64SDK_BIN)/[Ww][Ii][Nn]64/[Xx]86) $(PATH_SDK_WIN64SDK_BIN)/win64/AMD64)
+endif
+
+
+# General Properties used by kBuild
+SDK_WIN64SDK_INCS ?= $(PATH_SDK_WIN64SDK_INC)
+SDK_WIN64SDK_LIBPATH ?= $(PATH_SDK_WIN64SDK_LIB)
+SDK_WIN64SDK_LIBS ?= \
+	$(PATH_SDK_WIN64SDK_LIB)/Kernel32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/User32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/Gdi32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/AdvAPI32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/Shell32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/ShLwApi.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/SetupAPI.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/Uuid.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/Version.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/WS2_32.Lib \
+	\
+	$(PATH_SDK_WIN64SDK_LIB)/Ole32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/OleAut32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/OleDlg.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/RpcRT4.Lib \
+	\
+	$(PATH_SDK_WIN64SDK_LIB)/DbgHelp.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/ImageHlp.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/IPHlpApi.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/ComCtl32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/ComDlg32.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/WinSpool.Lib \
+	$(PATH_SDK_WIN64SDK_LIB)/WinMM.Lib
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WINDDK.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WINDDK.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WINDDK.kmk	(revision 1780)
@@ -0,0 +1,133 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs.
+#              Defaults to $(KBUILD_TARGET_ARCH). Base SDK.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_WINDDK := The Microsoft Windows Vista and Server 2008 DDKs. \
+              Defaults to $(KBUILD_TARGET_ARCH). Base SDK.
+
+# SDK Specific Properties
+ifndef PATH_SDK_WINDDK
+ PATH_SDK_WINDDK := $(wildcard $(PATH_DEVTOOLS_TRG)/ddk/6*)
+ ifeq ($(PATH_SDK_WINDDK),)
+  PATH_SDK_WINDDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddk/6*)
+ endif
+ ifeq ($(PATH_SDK_WINDDK),)
+  PATH_SDK_WINDDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddk/6*)
+ endif
+ ifeq ($(PATH_SDK_WINDDK),)
+  ifeq ($(KBUILD_HOST),win)
+   PATH_SDK_WINDDK := $(wildcard C:/WinDDK/6*)
+  endif
+ endif
+ ifneq ($(PATH_SDK_WINDDK),)
+  PATH_SDK_WINDDK := $(lastword $(sort $(PATH_SDK_WINDDK)))
+ else
+  $(warning kBuild: PATH_SDK_WINDDK couldn't be determined!)
+  PATH_SDK_WINDDK := $(PATH_DEVTOOLS)/win.x86/ddk/not/found
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_WINDDK := $(PATH_SDK_WINDDK)
+endif
+
+PATH_SDK_WINDDK_INC     ?= $(PATH_SDK_WINDDK)/inc
+PATH_SDK_WINDDK_INC_API ?= $(PATH_SDK_WINDDK_INC)/api
+PATH_SDK_WINDDK_INC_CRT ?= $(PATH_SDK_WINDDK_INC)/crt
+PATH_SDK_WINDDK_INC_DDK ?= $(PATH_SDK_WINDDK_INC)/ddk
+
+PATH_SDK_WINDDK_LIB_ROOT      ?= $(PATH_SDK_WINDDK)/lib
+PATH_SDK_WINDDK_LIB_WLH_ROOT  ?= $(PATH_SDK_WINDDK_LIB_ROOT)/wlh
+PATH_SDK_WINDDK_LIB_WNET_ROOT ?= $(PATH_SDK_WINDDK_LIB_ROOT)/wnet
+PATH_SDK_WINDDK_LIB_WXP_ROOT  ?= $(PATH_SDK_WINDDK_LIB_ROOT)/wxp
+PATH_SDK_WINDDK_LIB_W2K_ROOT  ?= $(PATH_SDK_WINDDK_LIB_ROOT)/w2k
+PATH_SDK_WINDDK_LIB_WDF_ROOT  ?= $(PATH_SDK_WINDDK_LIB_ROOT)/w2k
+
+PATH_SDK_WINDDK_LIB_WLH.amd64 ?= $(PATH_SDK_WINDDK_LIB_WLH_ROOT)/amd64
+PATH_SDK_WINDDK_LIB_WLH.ia64  ?= $(PATH_SDK_WINDDK_LIB_WLH_ROOT)/ia64
+PATH_SDK_WINDDK_LIB_WLH.x86   ?= $(PATH_SDK_WINDDK_LIB_WLH_ROOT)/i386
+PATH_SDK_WINDDK_LIB_WLH       ?= $(PATH_SDK_WINDDK_LIB_WLH.$(KBUILD_TARGET_ARCH))
+
+PATH_SDK_WINDDK_LIB_WNET.amd64?= $(PATH_SDK_WINDDK_LIB_WNET_ROOT)/amd64
+PATH_SDK_WINDDK_LIB_WNET.ia64 ?= $(PATH_SDK_WINDDK_LIB_WNET_ROOT)/ia64
+PATH_SDK_WINDDK_LIB_WNET.x86  ?= $(PATH_SDK_WINDDK_LIB_WNET_ROOT)/i386
+PATH_SDK_WINDDK_LIB_WNET      ?= $(PATH_SDK_WINDDK_LIB_WNET.$(KBUILD_TARGET_ARCH))
+
+PATH_SDK_WINDDK_LIB_WXP.x86   ?= $(PATH_SDK_WINDDK_LIB_WXP_ROOT)/i386
+PATH_SDK_WINDDK_LIB_WXP       ?= $(PATH_SDK_WINDDK_LIB_WXP.$(KBUILD_TARGET_ARCH))
+
+PATH_SDK_WINDDK_LIB_W2K.x86   ?= $(PATH_SDK_WINDDK_LIB_W2K_ROOT)/i386
+PATH_SDK_WINDDK_LIB_W2K       ?= $(PATH_SDK_WINDDK_LIB_W2K.$(KBUILD_TARGET_ARCH))
+
+PATH_SDK_WINDDK_LIB.amd64     ?= $(PATH_SDK_WINDDK_LIB_WLH.amd64)
+PATH_SDK_WINDDK_LIB.ia64      ?= $(PATH_SDK_WINDDK_LIB_WLH.ia64)
+PATH_SDK_WINDDK_LIB.x86       ?= $(PATH_SDK_WINDDK_LIB_WLH.x86)
+PATH_SDK_WINDDK_LIB           ?= $(PATH_SDK_WINDDK_LIB.$(KBUILD_TARGET_ARCH))
+
+# General Properties used by kBuild
+SDK_WINDDK_DEFS.amd64    ?= _AMD64_ AMD64 _WIN64
+SDK_WINDDK_DEFS.ia64     ?= _IA64_=1 IA64=1 _WIN64 _MSC_EXTENSIONS
+SDK_WINDDK_DEFS.x86      ?= _X86_=1 i386=1 STD_CALL
+SDK_WINDDK_INCS          ?= \
+	$(PATH_SDK_WINDDK_INC_API) \
+	$(PATH_SDK_WINDDK_INC_DDK)
+# The compiler tool(s) will have to select the appropriate crt includes.
+SDK_WINDDK_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK_LIB_WLH.amd64)
+SDK_WINDDK_LIBPATH.ia64  ?= $(PATH_SDK_WINDDK_LIB_WLH.ia64)
+SDK_WINDDK_LIBPATH.x86   ?= $(PATH_SDK_WINDDK_LIB_WLH.x86)
+
+#
+# CDFS defines for the various build environments. Just to give an idea what
+# you should put in your templates and target DEFS.
+#
+
+# Vista / Server Longhorn x64 Free:  NT_INST=0 WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL
+# Vista / Server Longhorn ia64 Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL NO_HW_DETECT _MSC_EXTENSIONS _MERCED_A0_=1 FPO=0
+# Vista / Server Longhorn x86 Free:  NT_INST=0 WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0
+# Windows Server 2003 amd64 Free:    NT_INST=0 WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL
+# Windows Server 2003 ia64 Free:     NT_INST=0 WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL NO_HW_DETECT _MSC_EXTENSIONS _MERCED_A0_=1 FPO=0
+# Windows Server 2003 x86 Free:      NT_INST=0 WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0
+# Windows XP Free:                   NT_INST=0 WIN32=100 _WIN32_WINNT=0x0501 WINVER=0x0501 _WIN32_IE=0x0603 NTDDI_VERSION=0x05010200 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0
+# Windows 2000 Free:                 NT_INST=0 WIN32=100 _WIN32_WINNT=0x0500 WINVER=0x0500 _WIN32_IE=0x0501 NTDDI_VERSION=0x05000400 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0
+# Windows 2000 Checked:              NT_INST=0 WIN32=100 _WIN32_WINNT=0x0500 WINVER=0x0500 _WIN32_IE=0x0501 NTDDI_VERSION=0x05000400 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0 MSC_NOOPT
+
+# Some notes about the defines:
+#  NTDDI_VERSION indicates the target NT version, looks kind of important to get right.
+#  _WIN32_WINNT, WINVER and _WIN32_IE are used by a bunch of headers for selecting features.
+#  WIN32_LEAN_AND_MEAN is used by api\WINDOWS.H to drop a bunch of includes.
+#  WIN32 is just used for some ifdef'ing by a handful headers.
+#  __BUILDMACHINE__ is used by api\common.ver (for resources it seems).
+#  STD_CALL is used by ddk\stdcall.inc (masm).
+#  DEVL governs the IF_NTOS_DEBUG() macro in ddk\wdm.h.
+#  NDEBUG is used by crt\assert.h dictated by the standards.
+#  CONDITION_HANDLING, FPO, KMDF_MAJOR_VERSION, KMDF_MINOR_VERSION, MSC_NOOPT and NT_INST are not referenced in any headers.
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WINDDKW2K.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WINDDKW2K.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WINDDKW2K.kmk	(revision 1780)
@@ -0,0 +1,43 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows 2000 (x86).
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_WINDDKW2K := The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows 2000 (x86).
+SDK_WINDDKW2K_EXTENDS = WINDDK
+SDK_WINDDKW2K_DEFS          ?= WIN32=100 _WIN32_WINNT=0x0500 WINVER=0x0500 _WIN32_IE=0x0501 NTDDI_VERSION=0x05000400
+SDK_WINDDKW2K_LIBPATH.x86   ?= $(PATH_SDK_WINDDK_LIB_W2K.x86)
+
+# SDK Specific Properties.
+# Note! extends the WINDDK sdk, so use those variables where ever possible
+PATH_SDK_WINDDKW2K_LIB.x86  ?= $(PATH_SDK_WINDDK_LIB_W2K.x86)
+PATH_SDK_WINDDKW2K_LIB      ?= $(PATH_SDK_WINDDKW2K_LIB.x86)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWLH.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWLH.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWLH.kmk	(revision 1780)
@@ -0,0 +1,47 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs, Targeting Vista and 2008 (KBUILD_TARGET_ARCH).
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_WINDDKWLH := The Microsoft Windows Vista and Server 2008 DDKs, Targeting Vista and 2008 (KBUILD_TARGET_ARCH).
+SDK_WINDDKWLH_EXTENDS = WINDDK
+SDK_WINDDKWLH_DEFS          ?= WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005
+SDK_WINDDKWLH_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK_LIB_WLH.amd64)
+SDK_WINDDKWLH_LIBPATH.ia64  ?= $(PATH_SDK_WINDDK_LIB_WLH.ia64)
+SDK_WINDDKWLH_LIBPATH.x86   ?= $(PATH_SDK_WINDDK_LIB_WLH.x86)
+
+# SDK Specific Properties.
+# Note! extends the WINDDK sdk, so use those variables where ever possible
+PATH_SDK_WINDDKWLH_LIB.amd64?= $(PATH_SDK_WINDDK_LIB_WLH.amd64)
+PATH_SDK_WINDDKWLH_LIB.ia64 ?= $(PATH_SDK_WINDDK_LIB_WLH.ia64)
+PATH_SDK_WINDDKWLH_LIB.x86  ?= $(PATH_SDK_WINDDK_LIB_WLH.x86)
+PATH_SDK_WINDDKWLH_LIB      ?= $(PATH_SDK_WINDDKWLH_LIB.$(KBUILD_TARGET_ARCH))
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWNET.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWNET.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWNET.kmk	(revision 1780)
@@ -0,0 +1,47 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows Server 2003 (KBUILD_TARGET_ARCH).
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_WINDDKWNET := The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows Server 2003 (KBUILD_TARGET_ARCH).
+SDK_WINDDKWNET_EXTENDS = WINDDK
+SDK_WINDDKWNET_DEFS          ?= WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100
+SDK_WINDDKWNET_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK_LIB_WNET.amd64)
+SDK_WINDDKWNET_LIBPATH.ia64  ?= $(PATH_SDK_WINDDK_LIB_WNET.ia64)
+SDK_WINDDKWNET_LIBPATH.x86   ?= $(PATH_SDK_WINDDK_LIB_WNET.x86)
+
+# SDK Specific Properties.
+# Note! extends the WINDDK sdk, so use those variables where ever possible
+PATH_SDK_WINDDKWNET_LIB.amd64?= $(PATH_SDK_WINDDK_LIB_WNET.amd64)
+PATH_SDK_WINDDKWNET_LIB.ia64 ?= $(PATH_SDK_WINDDK_LIB_WNET.ia64)
+PATH_SDK_WINDDKWNET_LIB.x86  ?= $(PATH_SDK_WINDDK_LIB_WNET.x86)
+PATH_SDK_WINDDKWNET_LIB      ?= $(PATH_SDK_WINDDKWNET_LIB.$(KBUILD_TARGET_ARCH))
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWXP.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWXP.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WINDDKWXP.kmk	(revision 1780)
@@ -0,0 +1,43 @@
+# $Id$
+## @file
+# kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows XP (x86).
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_WINDDKWXP := The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows XP (x86).
+SDK_WINDDKWXP_EXTENDS = WINDDK
+SDK_WINDDKWXP_DEFS          ?= WIN32=100 _WIN32_WINNT=0x0501 WINVER=0x0501 _WIN32_IE=0x0603 NTDDI_VERSION=0x05010200
+SDK_WINDDKWXP_LIBPATH.x86   ?= $(PATH_SDK_WINDDK_LIB_WXP.x86)
+
+# SDK Specific Properties.
+# Note! extends the WINDDK sdk, so use those variables where ever possible
+PATH_SDK_WINDDKWXP_LIB.x86  ?= $(PATH_SDK_WINDDK_LIB_WXP.x86)
+PATH_SDK_WINDDKWXP_LIB      ?= $(PATH_SDK_WINDDKWXP_LIB.x86)
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WINPSDK.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WINPSDK.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WINPSDK.kmk	(revision 1780)
@@ -0,0 +1,111 @@
+# $Id$
+## @file
+# kBuild SDK - The Windows Platform SDK, targeting (KBUILD_TARGET).
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_WINPSDK := The Windows Platform SDK, targeting (KBUILD_TARGET).
+
+# SDK Specific Properties
+ifndef PATH_SDK_WINPSDK
+ PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS_BLD)/sdk/2*)
+ ifeq ($(PATH_SDK_WINPSDK),)
+  PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS_TRG)/sdk/2*)
+ endif
+ ifeq ($(PATH_SDK_WINPSDK),)
+  PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*)
+ endif
+ ifeq ($(PATH_SDK_WINPSDK),)
+  PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk/2*)
+ endif
+ ifeq ($(PATH_SDK_WINPSDK),)
+  PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*)
+ endif
+ ifneq ($(PATH_SDK_WINPSDK),)
+  PATH_SDK_WINPSDK := $(lastword $(sort $(PATH_SDK_WINPSDK)))
+ else
+  $(warning kBuild: PATH_SDK_WINPSDK couldn't be determined!)
+  PATH_SDK_WINPSDK := $(PATH_DEVTOOLS_BLD)/sdk/not/found
+ endif
+else
+ PATH_SDK_WINPSDK := $(PATH_SDK_WINPSDK)
+endif
+
+ifndef PATH_SDK_WINPSDK_INC
+PATH_SDK_WINPSDK_INC := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WINPSDK)/Include)
+endif
+
+ifndef PATH_SDK_WINPSDK_LIB.x86
+PATH_SDK_WINPSDK_LIB.x86 := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Ll][Ii][Bb]) $(PATH_SDK_WINPSDK)/Lib)
+endif
+ifndef PATH_SDK_WINPSDK_LIB.amd64
+PATH_SDK_WINPSDK_LIB.amd64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64 $(PATH_SDK_WINPSDK)/[Ll][Ii][Bb]/[xX]64) $(PATH_SDK_WINPSDK)/Lib/AMD64)
+endif
+PATH_SDK_WINPSDK_LIB ?= $(PATH_SDK_WINPSDK_LIB.$(KBUILD_TARGET_ARCH))
+
+ifndef PATH_SDK_WINPSDK_BIN
+PATH_SDK_WINPSDK_BIN := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Bb][Ii][Nn]) $(PATH_SDK_WINPSDK)/Bin)
+endif
+ifndef PATH_SDK_WINPSDK_BIN_AMD64
+PATH_SDK_WINPSDK_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64 $(PATH_SDK_WINPSDK_BIN)/[Ww][Ii][Nn]64/[Xx]86) $(PATH_SDK_WINPSDK_BIN)/win64/AMD64)
+endif
+ifndef PATH_SDK_WINPSDK_BIN_IA64
+PATH_SDK_WINPSDK_BIN_IA64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK_BIN)/[Ww][Ii][Nn]64) $(PATH_SDK_WINPSDK_BIN)/win64)
+endif
+
+
+# General Properties used by kBuild
+SDK_WINPSDK_INCS ?= $(PATH_SDK_WINPSDK_INC)
+SDK_WINPSDK_LIBPATH ?= $(PATH_SDK_WINPSDK_LIB)
+SDK_WINPSDK_LIBS ?= \
+	$(PATH_SDK_WINPSDK_LIB)/Kernel32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/User32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/Gdi32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/AdvAPI32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/Shell32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/ShLwApi.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/SetupAPI.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/Uuid.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/Version.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/WS2_32.Lib \
+	\
+	$(PATH_SDK_WINPSDK_LIB)/Ole32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/OleAut32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/OleDlg.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/RpcRT4.Lib \
+	\
+	$(PATH_SDK_WINPSDK_LIB)/DbgHelp.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/ImageHlp.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/IPHlpApi.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/ComCtl32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/ComDlg32.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/WinSpool.Lib \
+	$(PATH_SDK_WINPSDK_LIB)/WinMM.Lib
+
Index: /tags/kBuild-0.1.4/kBuild/sdks/WINPSDKINCS.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/sdks/WINPSDKINCS.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/sdks/WINPSDKINCS.kmk	(revision 1780)
@@ -0,0 +1,93 @@
+# $Id$
+## @file
+# kBuild SDK - The Windows Platform SDK, targeting (KBUILD_TARGET) but
+#              without any libraries or LIBPATH properties.
+#              Basically for finding specstrings.h when using the DDK.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+SDK_WINPSDKINCS := The Windows Platform SDK, targeting (KBUILD_TARGET) but \
+	without any library or LIBPATH properties. \
+	Basically for finding specstrings.h when using the DDK.
+
+# SDK Specific Properties
+ifndef PATH_SDK_WINPSDKINCS
+ ifdef PATH_SDK_WINPSDK
+  PATH_SDK_WINPSDKINCS := $(PATH_SDK_WINPSDK)
+ else
+  PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS_BLD)/sdk/2*)
+  ifeq ($(PATH_SDK_WINPSDKINCS),)
+   PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS_TRG)/sdk/2*)
+  endif
+  ifeq ($(PATH_SDK_WINPSDKINCS),)
+   PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*)
+  endif
+  ifeq ($(PATH_SDK_WINPSDKINCS),)
+   PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk/2*)
+  endif
+  ifeq ($(PATH_SDK_WINPSDKINCS),)
+   PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*)
+  endif
+  ifneq ($(PATH_SDK_WINPSDKINCS),)
+   PATH_SDK_WINPSDKINCS := $(lastword $(sort $(PATH_SDK_WINPSDKINCS)))
+  else
+   $(warning kBuild: PATH_SDK_WINPSDKINCS couldn't be determined!)
+   PATH_SDK_WINPSDKINCS := $(PATH_DEVTOOLS_BLD)/sdk/not/found
+  endif
+ endif
+else
+ PATH_SDK_WINPSDKINCS := $(PATH_SDK_WINPSDKINCS)
+endif
+ifndef PATH_SDK_WINPSDKINCS_INC
+PATH_SDK_WINPSDKINCS_INC := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WINPSDKINCS)/Include)
+endif
+
+ifndef PATH_SDK_WINPSDKINCS_LIB.x86
+PATH_SDK_WINPSDKINCS_LIB.x86 := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS)/[Ll][Ii][Bb]) $(PATH_SDK_WINPSDKINCS)/Lib)
+endif
+ifndef PATH_SDK_WINPSDKINCS_LIB.amd64
+PATH_SDK_WINPSDKINCS_LIB.amd64 := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64) $(PATH_SDK_WINPSDKINCS)/Lib/AMD64)
+endif
+PATH_SDK_WINPSDKINCS_LIB ?= $(PATH_SDK_WINPSDKINCS_LIB.$(KBUILD_TARGET_ARCH))
+
+ifndef PATH_SDK_WINPSDKINCS_BIN
+PATH_SDK_WINPSDKINCS_BIN := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS)/[Bb][Ii][Nn]) $(PATH_SDK_WINPSDKINCS)/Bin)
+endif
+ifndef PATH_SDK_WINPSDKINCS_BIN_AMD64
+PATH_SDK_WINPSDKINCS_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64) $(PATH_SDK_WINPSDKINCS_BIN)/win64/AMD64)
+endif
+ifndef PATH_SDK_WINPSDKINCS_BIN_IA64
+PATH_SDK_WINPSDKINCS_BIN_IA64 := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS_BIN)/[Ww][Ii][Nn]64) $(PATH_SDK_WINPSDKINCS_BIN)/win64)
+endif
+
+
+# General Properties used by kBuild
+SDK_WINPSDKINCS_INCS ?= $(PATH_SDK_WINPSDKINCS_INC)
+
Index: /tags/kBuild-0.1.4/kBuild/subfooter.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/subfooter.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/subfooter.kmk	(revision 1780)
@@ -0,0 +1,92 @@
+# $Id$
+## @file
+# kBuild - File included at bottom of a makefile or sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+#
+# Sanity check.
+#
+ifdef __footer_kmk__
+ $(error kBuild: footer.kmk has already been included. Fix your sub-makefiles! $(MAKEFILE_CURRENT))
+endif
+
+#
+# Set the default path for all new targets.
+#
+define def_subheader
+ ifndef $(target)_PATH
+  ifdef $(target)_DEFPATH
+   $(target)_PATH := $($(target)_DEFPATH)
+  else
+   $(target)_PATH := $(PATH_SUB_CURRENT)
+  endif
+ else ifndef $(target)_DEFPATH
+  $(target)_DEFPATH := $($(target)_PATH)
+ endif
+ ifndef $(target)_MAKEFILE
+  $(target)_MAKEFILE := $(MAKEFILE_CURRENT)
+ endif
+ ifndef PATH_$(target)
+  PATH_$(target) := $(call TARGET_PATH,$(target))
+ endif
+endef
+
+$(foreach target,\
+	$(ALL_TARGETS) \
+	$(FETCHES)     $(FETCHES.$(KBUILD_TARGET))      $(FETCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))     $(FETCHES.$(KBUILD_TARGET_ARCH))     $(FETCHES.$(KBUILD_TARGET_CPU))     $(FETCHES.$(KBUILD_TYPE))     \
+	$(PATCHES)     $(PATCHES.$(KBUILD_TARGET))      $(PATCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))     $(PATCHES.$(KBUILD_TARGET_ARCH))     $(PATCHES.$(KBUILD_TARGET_CPU))     $(PATCHES.$(KBUILD_TYPE))     \
+	$(BLDPROGS)    $(BLDPROGS.$(KBUILD_HOST))       $(BLDPROGS.$(KBUILD_HOST).$(BUILD_PLATFORM_ARCH))     $(BLDPROGS.$(KBUILD_HOST_ARCH))      $(BLDPROGS.$(KBUILD_HOST_CPU))      $(BLDPROGS.$(KBUILD_TYPE))    \
+	$(LIBRARIES)   $(LIBRARIES.$(KBUILD_TARGET))    $(LIBRARIES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))   $(LIBRARIES.$(KBUILD_TARGET_ARCH))   $(LIBRARIES.$(KBUILD_TARGET_CPU))   $(LIBRARIES.$(KBUILD_TYPE))   \
+	$(IMPORT_LIBS) $(IMPORT_LIBS.$(KBUILD_TARGET))  $(IMPORT_LIBS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_CPU)) $(IMPORT_LIBS.$(KBUILD_TYPE)) \
+	$(DLLS)        $(DLLS.$(KBUILD_TARGET))         $(DLLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))        $(DLLS.$(KBUILD_TARGET_ARCH))        $(DLLS.$(KBUILD_TARGET_CPU))        $(DLLS.$(KBUILD_TYPE))        \
+	$(PROGRAMS)    $(PROGRAMS.$(KBUILD_TARGET))     $(PROGRAMS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))    $(PROGRAMS.$(KBUILD_TARGET_ARCH))    $(PROGRAMS.$(KBUILD_TARGET_CPU))    $(PROGRAMS.$(KBUILD_TYPE))    \
+	$(SYSMODS)     $(SYSMODS.$(KBUILD_TARGET))      $(SYSMODS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))     $(SYSMODS.$(KBUILD_TARGET_ARCH))     $(SYSMODS.$(KBUILD_TARGET_CPU))     $(SYSMODS.$(KBUILD_TYPE))     \
+	$(INSTALLS)    $(INSTALLS.$(KBUILD_TARGET))     $(INSTALLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))    $(INSTALLS.$(KBUILD_TARGET_ARCH))    $(INSTALLS.$(KBUILD_TARGET_CPU))    $(INSTALLS.$(KBUILD_TYPE))    \
+	$(OTHERS)      $(OTHERS.$(KBUILD_TARGET))       $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))      $(OTHERS.$(KBUILD_TARGET_ARCH))      $(OTHERS.$(KBUILD_TARGET_CPU))      $(OTHERS.$(KBUILD_TYPE))      \
+,$(eval $(def_subheader)))
+
+
+
+ifneq ($(_SUB_MAKEFILE_STACK),)
+ #
+ # Switch back to the context of previous makefile on the stack.
+ #
+ MAKEFILE_CURRENT := $(stack-pop _SUB_MAKEFILE_STACK)
+ PATH_SUB_CURRENT := $(abspath $(dir $(MAKEFILE_CURRENT)))
+
+else
+ #
+ # We've reached the end of the line, include the real footer.
+ #
+ include $(PATH_KBUILD)/footer.kmk
+
+endif
+
Index: /tags/kBuild-0.1.4/kBuild/subheader.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/subheader.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/subheader.kmk	(revision 1780)
@@ -0,0 +1,100 @@
+# $Id$
+## @file
+# kBuild - File included at top of a makefile or sub-makefile.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+
+#
+# Sanity check.
+#
+ifdef __footer_kmk__
+$(error kBuild: footer.kmk has already been included. Fix your sub-makefiles! $(MAKEFILE_CURRENT))
+endif
+
+ifndef _SUB_MAKEFILE_NOT_FIRST
+
+ #
+ # The first time we just take the makefile context set by header.kmk.
+ #
+ _SUB_MAKEFILE_NOT_FIRST := 1
+ DEPTH ?= $(SUB_DEPTH)
+ include $(PATH_KBUILD)/header.kmk
+
+else
+
+ #
+ # Set the default path and makefile for all new targets.
+ #
+ define def_subfooter
+  ifndef $(target)_PATH
+   ifdef $(target)_DEFPATH
+    $(target)_PATH := $($(target)_DEFPATH)
+   else
+    $(target)_PATH := $(PATH_SUB_CURRENT)
+   endif
+  else ifndef $(target)_DEFPATH
+   $(target)_DEFPATH := $($(target)_PATH)
+  endif
+  ifndef $(target)_MAKEFILE
+   $(target)_MAKEFILE := $(MAKEFILE_CURRENT)
+  endif
+  ifndef PATH_$(target)
+   PATH_$(target) := $(call TARGET_PATH,$(target))
+  endif
+ endef
+
+ $(foreach target,\
+	$(ALL_TARGETS) \
+	$(FETCHES)     $(FETCHES.$(KBUILD_TARGET))      $(FETCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))     $(FETCHES.$(KBUILD_TARGET_ARCH))     $(FETCHES.$(KBUILD_TARGET_CPU))     $(FETCHES.$(KBUILD_TYPE))     \
+	$(PATCHES)     $(PATCHES.$(KBUILD_TARGET))      $(PATCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))     $(PATCHES.$(KBUILD_TARGET_ARCH))     $(PATCHES.$(KBUILD_TARGET_CPU))     $(PATCHES.$(KBUILD_TYPE))     \
+	$(BLDPROGS)    $(BLDPROGS.$(KBUILD_HOST))       $(BLDPROGS.$(KBUILD_HOST).$(BUILD_PLATFORM_ARCH))     $(BLDPROGS.$(KBUILD_HOST_ARCH))      $(BLDPROGS.$(KBUILD_HOST_CPU))      $(BLDPROGS.$(KBUILD_TYPE))    \
+	$(LIBRARIES)   $(LIBRARIES.$(KBUILD_TARGET))    $(LIBRARIES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))   $(LIBRARIES.$(KBUILD_TARGET_ARCH))   $(LIBRARIES.$(KBUILD_TARGET_CPU))   $(LIBRARIES.$(KBUILD_TYPE))   \
+	$(IMPORT_LIBS) $(IMPORT_LIBS.$(KBUILD_TARGET))  $(IMPORT_LIBS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_CPU)) $(IMPORT_LIBS.$(KBUILD_TYPE)) \
+	$(DLLS)        $(DLLS.$(KBUILD_TARGET))         $(DLLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))        $(DLLS.$(KBUILD_TARGET_ARCH))        $(DLLS.$(KBUILD_TARGET_CPU))        $(DLLS.$(KBUILD_TYPE))        \
+	$(PROGRAMS)    $(PROGRAMS.$(KBUILD_TARGET))     $(PROGRAMS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))    $(PROGRAMS.$(KBUILD_TARGET_ARCH))    $(PROGRAMS.$(KBUILD_TARGET_CPU))    $(PROGRAMS.$(KBUILD_TYPE))    \
+	$(SYSMODS)     $(SYSMODS.$(KBUILD_TARGET))      $(SYSMODS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))     $(SYSMODS.$(KBUILD_TARGET_ARCH))     $(SYSMODS.$(KBUILD_TARGET_CPU))     $(SYSMODS.$(KBUILD_TYPE))     \
+	$(INSTALLS)    $(INSTALLS.$(KBUILD_TARGET))     $(INSTALLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))    $(INSTALLS.$(KBUILD_TARGET_ARCH))    $(INSTALLS.$(KBUILD_TARGET_CPU))    $(INSTALLS.$(KBUILD_TYPE))    \
+	$(OTHERS)      $(OTHERS.$(KBUILD_TARGET))       $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))      $(OTHERS.$(KBUILD_TARGET_ARCH))      $(OTHERS.$(KBUILD_TARGET_CPU))      $(OTHERS.$(KBUILD_TYPE))      \
+ ,$(eval $(def_subfooter)))
+
+
+ #
+ # Switch context.
+ #
+
+ # push the current old makefile onto the stack.
+ $(stack-push _SUB_MAKEFILE_STACK,$(MAKEFILE_CURRENT))
+
+ # the current makefile is the 2nd from the end of the MAKEFILE_LIST (we're the last one).
+ __tmp := $(MAKEFILE_LIST)
+ $(stack-popv __tmp)
+ MAKEFILE_CURRENT := $(stack-top __tmp)
+ PATH_SUB_CURRENT := $(abspath $(dir $(MAKEFILE_CURRENT)))
+endif
+
Index: /tags/kBuild-0.1.4/kBuild/tools/ALP.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/ALP.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/ALP.kmk	(revision 1780)
@@ -0,0 +1,77 @@
+# $Id$
+## @file
+# kBuild Tool Config - ALP or later.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_ALP := The IBM Assembly Language Processor
+
+# Tool Specific Properties
+ifndef PATH_TOOL_ALP
+ PATH_TOOL_ALP := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/alp/v*.*))
+ ifneq ($(PATH_TOOL_ALP),)
+  PATH_TOOL_ALP := $(call lastword,$(PATH_TOOL_ALP))
+ endif
+endif
+ifneq ($(PATH_TOOL_ALP),)
+ TOOL_ALP_AS ?= $(PATH_TOOL_ALP)/alp$(HOSTSUFF_EXE)
+else
+ TOOL_ALP_AS ?= alp$(HOSTSUFF_EXE)
+endif
+
+# General Properties used by kBuild
+TOOL_ALP_ASFLAGS ?= -Mb
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_ALP_COMPILE_AS_OUTPUT = $(outbase).lst
+TOOL_ALP_COMPILE_AS_DEPEND =
+TOOL_ALP_COMPILE_AS_DEPORD =
+define TOOL_ALP_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_ALP_AS)\
+		$(flags) $(addsuffix /,$(addprefix -I:, $(incs))) $(addprefix -D:, $(defs))\
+		$(source)\
+		-Fl:$(outbase).lst\
+		-Fd:$(dep)\
+		-Fo:$(obj)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/FLEX.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/FLEX.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/FLEX.kmk	(revision 1780)
@@ -0,0 +1,36 @@
+# $Id$
+## @file
+# flex tool
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+TOOL_FLEX = flex
+TOOL_FLEX_LEX ?= flex$(HOSTSUFF_EXE)
+TOOL_FLEX_LEXFLAGS ?=
+TOOL_FLEX_LEX_OUTPUT =
+TOOL_FLEX_LEX_DEPEND =
+TOOL_FLEX_LEX_DEPORD =
+define TOOL_FLEX_LEX_CMDS
+	$(TOOL_FLEX_LEX) $(flags) -o $(out) $(source)
+endef
+
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GCC.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GCC.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GCC.kmk	(revision 1780)
@@ -0,0 +1,228 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic GCC Using The System GCC.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GCC := Generic GCC Using The System GCC.
+
+# Tool Specific Properties
+TOOL_GCC_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GCC_AS  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC_AR  ?= ar$(HOSTSUFF_EXE)
+TOOL_GCC_RANLIB ?= ranlib$(HOSTSUFF_EXE)
+TOOL_GCC_LD  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC_LDFLAGS.dll.os2 ?= -Zdll
+TOOL_GCC_LDFLAGS.dll.darwin ?= -dynamiclib
+ifndef TOOL_GCC_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GCC_LDFLAGS.dll ?= -shared
+else
+TOOL_GCC_LDFLAGS.dll ?= $(TOOL_GCC_LDFLAGS.$(KBUILD_TARGET))
+endif
+
+# General Properties used by kBuild
+TOOL_GCC_COBJSUFF         ?= .o
+TOOL_GCC_CFLAGS           ?=
+TOOL_GCC_CFLAGS.debug     ?= -g
+TOOL_GCC_CFLAGS.profile   ?= -g -O2 #-pg
+TOOL_GCC_CFLAGS.release   ?= -O2
+TOOL_GCC_CINCS            ?=
+TOOL_GCC_CDEFS            ?=
+
+TOOL_GCC_CXXOBJSUFF       ?= .o
+TOOL_GCC_CXXOBJSUFF       ?= .o
+TOOL_GCC_CXXFLAGS         ?=
+TOOL_GCC_CXXFLAGS.debug   ?= -g -O0
+TOOL_GCC_CXXFLAGS.profile ?= -g -O2 #-pg
+TOOL_GCC_CXXFLAGS.release ?= -O2
+TOOL_GCC_CXXINCS          ?=
+TOOL_GCC_CXXDEFS          ?=
+
+TOOL_GCC_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GCC_ASFLAGS.debug    ?= -g
+TOOL_GCC_ASFLAGS.profile  ?= -g
+TOOL_GCC_ASOBJSUFF        ?= .o
+
+TOOL_GCC_ARFLAGS          ?= cr
+TOOL_GCC_ARLIBSUFF        ?= .a
+
+TOOL_GCC_LDFLAGS          ?=
+TOOL_GCC_LDFLAGS.debug    ?= -g
+TOOL_GCC_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GCC_COMPILE_C_OUTPUT =
+TOOL_GCC_COMPILE_C_DEPEND =
+TOOL_GCC_COMPILE_C_DEPORD =
+define TOOL_GCC_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GCC_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC_COMPILE_CXX_OUTPUT =
+TOOL_GCC_COMPILE_CXX_DEPEND =
+TOOL_GCC_COMPILE_CXX_DEPORD =
+define TOOL_GCC_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GCC_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GCC_COMPILE_AS_OUTPUT =
+TOOL_GCC_COMPILE_AS_DEPEND =
+TOOL_GCC_COMPILE_AS_DEPORD =
+define TOOL_GCC_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GCC_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC_LINK_LIBRARY_OUTPUT =
+TOOL_GCC_LINK_LIBRARY_DEPEND =
+TOOL_GCC_LINK_LIBRARY_DEPORD =
+define TOOL_GCC_LINK_LIBRARY_CMDS
+	$(QUIET)$(TOOL_GCC_AR) $(flags) $(out) $(objs)
+	$(call xargs,$(QUIET)$(TOOL_GCC_AR) $(flags) $(out),$(objs))
+	$(foreach lib,$(othersrc)\
+		,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \
+		$(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \
+			&& $(TOOL_GCC_AR) x $(abspath $(lib)) \
+			&& $(TOOL_GCC_AR) $(flags) $(out) *) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/)
+	$(QUIET)$(TOOL_GCC_RANLIB) $(out)
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC_LINK_PROGRAM_OUTPUT =
+TOOL_GCC_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC_LINK_PROGRAM_DEPORD =
+define TOOL_GCC_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GCC_LD) $(flags) -o $(out) $(objs) \
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+TOOL_GCC_LINK_DLL_OUTPUT =
+TOOL_GCC_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC_LINK_DLL_DEPORD =
+define TOOL_GCC_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GCC_LD) $(TOOL_GCC_LDFLAGS.dll) $(flags) -o $(out) $(objs) \
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GCC3.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GCC3.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GCC3.kmk	(revision 1780)
@@ -0,0 +1,320 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic GCC v3.2.x or later Using The System GCC and Binutils.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GCC3 := Generic GCC v3.2.x or later Using The System GCC and Binutils.
+
+# Tool Specific Properties
+TOOL_GCC3_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC3_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GCC3_AS  ?= gcc$(HOSTSUFF_EXE)
+ifeq ($(KBUILD_TARGET),solaris) ## @todo drop the MRI script!
+ TOOL_GCC3_AR ?= gar$(HOSTSUFF_EXE)
+else
+ TOOL_GCC3_AR ?= ar$(HOSTSUFF_EXE)
+endif
+ifeq ($(KBUILD_TARGET),os2)
+ TOOL_GCC3_AR_IMP ?= emximp$(HOSTSTUFF_EXE)
+else
+ TOOL_GCC3_AR_IMP ?= $(ECHO) not supported!
+endif
+TOOL_GCC3_LD ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC3_LD_SYSMOD ?= ld$(HOSTSUFF_EXE)
+ifndef TOOL_GCC3_LDFLAGS.$(KBUILD_TARGET)
+ TOOL_GCC3_LDFLAGS.dll ?= -shared
+else
+ TOOL_GCC3_LDFLAGS.dll ?= $(TOOL_GCC3_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GCC3_LDFLAGS.sysmod ?= -r
+TOOL_GCC3_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+ifeq ($(KBUILD_TARGET),os2)
+ TOOL_GCC3_LD_MAP ?= -Zmap=$(1)
+ TOOL_GCC3_LD_SYSMOD_MAP ?= -Zmap=$(1)
+else
+ TOOL_GCC3_LD_MAP ?=
+ TOOL_GCC3_LD_SYSMOD_MAP ?=
+endif
+ifdef SLKRUNS
+ TOOL_GCC3_CC  += -fmessage-length=0
+ TOOL_GCC3_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GCC3_COBJSUFF         ?= .o
+TOOL_GCC3_CFLAGS           ?=
+TOOL_GCC3_CFLAGS.debug     ?= -g
+TOOL_GCC3_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GCC3_CFLAGS.release   ?= -O2
+TOOL_GCC3_CINCS            ?=
+TOOL_GCC3_CDEFS            ?=
+
+TOOL_GCC3_CXXOBJSUFF       ?= .o
+TOOL_GCC3_CXXOBJSUFF       ?= .o
+TOOL_GCC3_CXXFLAGS         ?=
+TOOL_GCC3_CXXFLAGS.debug   ?= -g
+TOOL_GCC3_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GCC3_CXXFLAGS.release ?= -O2
+TOOL_GCC3_CXXINCS          ?=
+TOOL_GCC3_CXXDEFS          ?=
+
+TOOL_GCC3_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GCC3_ASFLAGS.debug    ?= -g
+TOOL_GCC3_ASFLAGS.profile  ?= -g
+TOOL_GCC3_ASOBJSUFF        ?= .o
+
+TOOL_GCC3_ARFLAGS          ?= cr
+TOOL_GCC3_ARLIBSUFF        ?= .a
+
+TOOL_GCC3_LDFLAGS          ?=
+TOOL_GCC3_LDFLAGS.debug    ?= -g
+TOOL_GCC3_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC3_COMPILE_C_DEPEND =
+TOOL_GCC3_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC3_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GCC3_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GCC3_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GCC3_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC3_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GCC3_COMPILE_C_OUTPUT =
+define TOOL_GCC3_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GCC3_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC3_COMPILE_CXX_DEPEND =
+TOOL_GCC3_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC3_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GCC3_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GCC3_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GCC3_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC3_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GCC3_COMPILE_CXX_OUTPUT =
+define TOOL_GCC3_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GCC3_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GCC3_COMPILE_AS_OUTPUT =
+TOOL_GCC3_COMPILE_AS_DEPEND =
+TOOL_GCC3_COMPILE_AS_DEPORD =
+define TOOL_GCC3_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GCC3_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3_LINK_LIBRARY_OUTPUT = $(out).ar-script
+TOOL_GCC3_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).imp.a
+TOOL_GCC3_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GCC3_LINK_LIBRARY_DEPORD =
+define TOOL_GCC3_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)'
+	$(QUIET)$(APPEND) -n $(out).ar-script \
+		$(foreach o,$(objs), 'ADDMOD $(o)') \
+		$(foreach o,$(filter-out %.def %.imp,$(othersrc)), 'ADDLIB $(o)')
+	$(if $(filter %.def %.imp,$(othersrc))\
+		,$(TOOL_GCC3_AR_IMP) -o $(outbase).imp.a $(filter %.def %.imp,$(othersrc))\
+		 $(NL)$(TAB)$(QUIET)$(APPEND) $(out).ar-script 'ADDLIB $(outbase).imp.a')
+	$(QUIET)$(APPEND) $(out).ar-script 'SAVE'
+	$(QUIET)$(APPEND) $(out).ar-script 'END'
+	$(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GCC3_AR) -M
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3_LINK_PROGRAM_OUTPUT =
+TOOL_GCC3_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC3_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GCC3_LINK_PROGRAM_DEPORD =
+define TOOL_GCC3_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GCC3_LD) $(flags) -o $(out) $(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC3_LD_MAP,$(outbase).map)
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3_LINK_DLL_OUTPUT =
+TOOL_GCC3_LINK_DLL_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC3_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GCC3_LINK_DLL_DEPORD =
+define TOOL_GCC3_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GCC3_LD) $(TOOL_GCC3_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win32 os2, $(KBUILD_TARGET)),$(call TOOL_GCC3_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC3_LD_MAP,$(outbase).map)
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3_LINK_SYSMOD_OUTPUT =
+TOOL_GCC3_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC3_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GCC3_LINK_SYSMOD_DEPORD =
+define TOOL_GCC3_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_GCC3_LD_SYSMOD) $(TOOL_GCC3_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC3_LD_SYSMOD_MAP,$(outbase).map)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GCC32.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GCC32.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GCC32.kmk	(revision 1780)
@@ -0,0 +1,306 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic 32-bit GCC v3.2.x or later Using The System GCC.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GCC32 := Generic 32-bit GCC v3.2.x or later Using The System GCC. \
+	More or less Linux/ELF specfic.
+
+# Tool Specific Properties
+TOOL_GCC32_CC  ?= gcc$(HOSTSUFF_EXE) -m32
+TOOL_GCC32_CXX ?= g++$(HOSTSUFF_EXE) -m32
+TOOL_GCC32_AS  ?= gcc$(HOSTSUFF_EXE) -m32
+TOOL_GCC32_AR  ?= ar$(HOSTSUFF_EXE)
+TOOL_GCC32_LD  ?= gcc$(HOSTSUFF_EXE) -m32
+TOOL_GCC32_LD_SYSMOD ?= ld$(HOSTSUFF_EXE)
+ifndef TOOL_GCC32_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GCC32_LDFLAGS.dll ?= -shared
+else
+TOOL_GCC32_LDFLAGS.dll ?= $(TOOL_GCC32_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GCC32_LDFLAGS.sysmod ?= -r -m elf_i386
+TOOL_GCC32_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+ifeq ($(KBUILD_TARGET),os2)
+TOOL_GCC32_LD_MAP ?= -Zmap=$(1)
+else
+TOOL_GCC32_LD_MAP ?=
+endif
+ifeq ($(KBUILD_TARGET),os2)
+TOOL_GCC32_LD_SYSMOD_MAP ?= -Zmap=$(1)
+else
+TOOL_GCC32_LD_SYSMOD_MAP ?=
+endif
+ifdef SLKRUNS
+TOOL_GCC32_CC  += -fmessage-length=0
+TOOL_GCC32_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GCC32_COBJSUFF         ?= .o
+TOOL_GCC32_CFLAGS           ?=
+TOOL_GCC32_CFLAGS.debug     ?= -g
+TOOL_GCC32_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GCC32_CFLAGS.release   ?= -O2
+TOOL_GCC32_CINCS            ?=
+TOOL_GCC32_CDEFS            ?=
+
+TOOL_GCC32_CXXOBJSUFF       ?= .o
+TOOL_GCC32_CXXOBJSUFF       ?= .o
+TOOL_GCC32_CXXFLAGS         ?=
+TOOL_GCC32_CXXFLAGS.debug   ?= -g
+TOOL_GCC32_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GCC32_CXXFLAGS.release ?= -O2
+TOOL_GCC32_CXXINCS          ?=
+TOOL_GCC32_CXXDEFS          ?=
+
+TOOL_GCC32_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GCC32_ASFLAGS.debug    ?= -g
+TOOL_GCC32_ASFLAGS.profile  ?= -g
+TOOL_GCC32_ASOBJSUFF        ?= .o
+
+TOOL_GCC32_ARFLAGS          ?= cr
+TOOL_GCC32_ARLIBSUFF        ?= .a
+
+TOOL_GCC32_LDFLAGS          ?=
+TOOL_GCC32_LDFLAGS.debug    ?= -g
+TOOL_GCC32_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC32_COMPILE_C_DEPEND =
+TOOL_GCC32_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC32_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GCC32_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GCC32_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GCC32_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC32_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GCC32_COMPILE_C_OUTPUT =
+define TOOL_GCC32_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GCC32_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC32_COMPILE_CXX_DEPEND =
+TOOL_GCC32_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC32_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GCC32_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GCC32_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GCC32_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC32_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+
+TOOL_GCC32_COMPILE_CXX_OUTPUT =
+define TOOL_GCC32_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GCC32_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GCC32_COMPILE_AS_OUTPUT =
+TOOL_GCC32_COMPILE_AS_DEPEND =
+TOOL_GCC32_COMPILE_AS_DEPORD =
+define TOOL_GCC32_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GCC32_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC32_LINK_LIBRARY_OUTPUT = $(out).ar-script
+TOOL_GCC32_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GCC32_LINK_LIBRARY_DEPORD =
+define TOOL_GCC32_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)'
+	$(QUIET)$(APPEND) -n $(out).ar-script \
+		$(foreach o,$(objs), 'ADDMOD $(o)') \
+		$(foreach o,$(othersrc), 'ADDLIB $(o)')
+	$(QUIET)$(APPEND) $(out).ar-script 'SAVE'
+	$(QUIET)$(APPEND) $(out).ar-script 'END'
+	$(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GCC32_AR) -M
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC32_LINK_PROGRAM_OUTPUT =
+TOOL_GCC32_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC32_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC32_LINK_PROGRAM_DEPORD =
+define TOOL_GCC32_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GCC32_LD) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC32_LD_MAP,$(outbase).map)
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC32_LINK_DLL_OUTPUT =
+TOOL_GCC32_LINK_DLL_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC32_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC32_LINK_DLL_DEPORD =
+define TOOL_GCC32_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GCC32_LD) $(TOOL_GCC32_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GCC32_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC32_LD_MAP,$(outbase).map)
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC32_LINK_SYSMOD_OUTPUT =
+TOOL_GCC32_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC32_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC32_LINK_SYSMOD_DEPORD =
+define TOOL_GCC32_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_GCC32_LD_SYSMOD) $(TOOL_GCC32_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC32_LD_SYSMOD_MAP,$(outbase).map)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GCC3OMF.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GCC3OMF.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GCC3OMF.kmk	(revision 1780)
@@ -0,0 +1,313 @@
+# $Id$
+## @file
+# kBuild Tool Config - GCC v3 targeting OS/2 OMF.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GCC3OMF := GCC v3 targeting OS/2 OMF.
+
+# Tool Specific Properties
+TOOL_GCC3OMF_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC3OMF_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GCC3OMF_AS  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC3OMF_AR  ?= emxomfar$(HOSTSUFF_EXE)
+TOOL_GCC3OMF_AR_IMP ?= emximp$(HOSTSUFF_EXE)
+TOOL_GCC3OMF_LD ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC3OMF_LD_SYSMOD ?= gcc$(HOSTSUFF_EXE)
+ifndef TOOL_GCC3OMF_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GCC3OMF_LDFLAGS.dll ?= -shared -Zdll
+else
+TOOL_GCC3OMF_LDFLAGS.dll ?= $(TOOL_GCC3OMF_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GCC3OMF_LDFLAGS.sysmod ?= -nostdlib
+TOOL_GCC3OMF_LD_MAP ?= -Zmap=$(1)
+TOOL_GCC3OMF_LD_SYSMOD_MAP ?= -Zmap=$(1)
+
+ifdef SLKRUNS
+TOOL_GCC3OMF_CC  += -fmessage-length=0
+TOOL_GCC3OMF_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GCC3OMF_COBJSUFF         ?= .o
+TOOL_GCC3OMF_CFLAGS           ?= -Zomf
+TOOL_GCC3OMF_CFLAGS.debug     ?= -g
+TOOL_GCC3OMF_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GCC3OMF_CFLAGS.release   ?= -O2
+TOOL_GCC3OMF_CINCS            ?=
+TOOL_GCC3OMF_CDEFS            ?=
+
+TOOL_GCC3OMF_CXXOBJSUFF       ?= .o
+TOOL_GCC3OMF_CXXOBJSUFF       ?= .o
+TOOL_GCC3OMF_CXXFLAGS         ?= -Zomf
+TOOL_GCC3OMF_CXXFLAGS.debug   ?= -g
+TOOL_GCC3OMF_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GCC3OMF_CXXFLAGS.release ?= -O2
+TOOL_GCC3OMF_CXXINCS          ?=
+TOOL_GCC3OMF_CXXDEFS          ?=
+
+TOOL_GCC3OMF_ASFLAGS          ?= -x assembler-with-cpp -Zomf
+TOOL_GCC3OMF_ASFLAGS.debug    ?= -g
+TOOL_GCC3OMF_ASFLAGS.profile  ?= -g
+TOOL_GCC3OMF_ASOBJSUFF        ?= .obj
+
+TOOL_GCC3OMF_ARFLAGS          ?= cr
+TOOL_GCC3OMF_ARLIBSUFF        ?= .lib
+
+TOOL_GCC3OMF_LDFLAGS          ?= -Zomf
+TOOL_GCC3OMF_LDFLAGS.debug    ?= -g
+TOOL_GCC3OMF_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC3OMF_COMPILE_C_DEPEND =
+TOOL_GCC3OMF_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC3OMF_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GCC3OMF_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GCC3OMF_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GCC3OMF_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC3OMF_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GCC3OMF_COMPILE_C_OUTPUT =
+define TOOL_GCC3OMF_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GCC3OMF_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC3OMF_COMPILE_CXX_DEPEND =
+TOOL_GCC3OMF_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC3OMF_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GCC3OMF_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GCC3OMF_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GCC3OMF_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC3OMF_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GCC3OMF_COMPILE_CXX_OUTPUT =
+define TOOL_GCC3OMF_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GCC3OMF_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GCC3OMF_COMPILE_AS_OUTPUT =
+TOOL_GCC3OMF_COMPILE_AS_DEPEND =
+TOOL_GCC3OMF_COMPILE_AS_DEPORD =
+define TOOL_GCC3OMF_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GCC3OMF_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3OMF_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_GCC3OMF_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GCC3OMF_LINK_LIBRARY_DEPORD =
+define TOOL_GCC3OMF_LINK_LIBRARY_CMDS
+	$(if $(filter %.def %.imp,$(othersrc))\
+		,$(QUIET)$(APPEND) -n $(outbase).rsp $(filter %.def %.imp,$(othersrc))\
+		 $(NL)$(TAB)$(QUIET)$(QUIET)$(TOOL_GCC3OMF_AR_IMP) -o $(out) @$(outbase).rsp\
+		 $(NL)$(TAB)$(QUIET)$(RM) -f $(outbase).rsp)
+	$(QUIET)$(APPEND) -n $(outbase).rsp $(flags) $(out) $(objs) $(filter-out %.def %.imp,$(othersrc))
+	$(TOOL_GCC3OMF_AR) @$(outbase).rsp
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3OMF_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_GCC3OMF_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_GCC3OMF_LINK_PROGRAM_DEPORD =
+define TOOL_GCC3OMF_LINK_PROGRAM_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp\
+		$(flags)\
+		-o $(out)\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(othersrc)\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		-Zmap=$(outbase).map
+	$(QUIET)$(TOOL_GCC3OMF_LD) @$(outbase).rsp
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3OMF_LINK_DLL_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_GCC3OMF_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_GCC3OMF_LINK_DLL_DEPORD =
+define TOOL_GCC3OMF_LINK_DLL_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp\
+		$(TOOL_GCC3OMF_LDFLAGS.dll)\
+		$(flags)\
+		-o $(out)\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(othersrc)\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		-Zmap=$(outbase).map
+	$(TOOL_GCC3OMF_LD) @$(outbase).rsp
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3OMF_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_GCC3OMF_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_GCC3OMF_LINK_SYSMOD_DEPORD =
+define TOOL_GCC3OMF_LINK_SYSMOD_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp\
+		$(TOOL_GCC3OMF_LDFLAGS.sysmod)\
+		$(flags)\
+		-o $(out)\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(othersrc)\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		-Zmap=$(outbase).map
+	$(QUIET)$(TOOL_GCC3OMF_LD_SYSMOD) @$(outbase).rsp
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GCC3PLAIN.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GCC3PLAIN.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GCC3PLAIN.kmk	(revision 1780)
@@ -0,0 +1,315 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic GCC v3.2.x or later Using The System GCC, any Unix Linker and Unix Archiver.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GCC3PLAIN := Generic GCC v3.2.x or later Using The System GCC, any Unix Linker and Unix Archiver.
+
+# Tool Specific Properties
+TOOL_GCC3PLAIN_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC3PLAIN_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GCC3PLAIN_AS  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC3PLAIN_AR  ?= ar$(HOSTSUFF_EXE)
+TOOL_GCC3PLAIN_RANLIB ?= ranlib$(HOSTSUFF_EXE)
+TOOL_GCC3PLAIN_LD  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC3PLAIN_LD_SYSMOD ?= ld$(HOSTSUFF_EXE)
+TOOL_GCC3PLAIN_LD_SYSMOD.os2 ?= g++$(HOSTSUFF_EXE)
+TOOL_GCC3PLAIN_LDFLAGS.dll.os2 ?= -Zdll
+TOOL_GCC3PLAIN_LDFLAGS.dll.darwin ?= -dynamiclib
+ifndef TOOL_GCC3PLAIN_LDFLAGS.$(KBUILD_TARGET)
+ TOOL_GCC3PLAIN_LDFLAGS.dll ?= -shared
+else
+ TOOL_GCC3PLAIN_LDFLAGS.dll ?= $(TOOL_GCC3PLAIN_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GCC3PLAIN_LD_SONAME.darwin ?= $(NO_SUCH_VARIABLE)
+TOOL_GCC3PLAIN_LD_SONAME.os2 ?= $(NO_SUCH_VARIABLE)
+TOOL_GCC3PLAIN_LD_SONAME.solaris ?= -Wl,-h,$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+TOOL_GCC3PLAIN_LD_SONAME.win ?= $(NO_SUCH_VARIABLE)
+ifndef TOOL_GCC3PLAIN_LD_SONAME.$(KBUILD_TARGET)
+ TOOL_GCC3PLAIN_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+else
+ TOOL_GCC3PLAIN_LD_SONAME ?= $(TOOL_GCC3PLAIN_LD_SONAME.$(KBUILD_TARGET))
+endif
+ifdef SLKRUNS
+ TOOL_GCC3PLAIN_CC  += -fmessage-length=0
+ TOOL_GCC3PLAIN_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GCC3PLAIN_COBJSUFF         ?= .o
+TOOL_GCC3PLAIN_CFLAGS           ?=
+TOOL_GCC3PLAIN_CFLAGS.debug     ?= -g
+TOOL_GCC3PLAIN_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GCC3PLAIN_CFLAGS.release   ?= -O2
+TOOL_GCC3PLAIN_CINCS            ?=
+TOOL_GCC3PLAIN_CDEFS            ?=
+
+TOOL_GCC3PLAIN_CXXOBJSUFF       ?= .o
+TOOL_GCC3PLAIN_CXXOBJSUFF       ?= .o
+TOOL_GCC3PLAIN_CXXFLAGS         ?=
+TOOL_GCC3PLAIN_CXXFLAGS.debug   ?= -g
+TOOL_GCC3PLAIN_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GCC3PLAIN_CXXFLAGS.release ?= -O2
+TOOL_GCC3PLAIN_CXXINCS          ?=
+TOOL_GCC3PLAIN_CXXDEFS          ?=
+
+TOOL_GCC3PLAIN_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GCC3PLAIN_ASFLAGS.debug    ?= -g
+TOOL_GCC3PLAIN_ASFLAGS.profile  ?= -g
+TOOL_GCC3PLAIN_ASOBJSUFF        ?= .o
+
+TOOL_GCC3PLAIN_ARFLAGS          ?= cr
+TOOL_GCC3PLAIN_ARLIBSUFF        ?= .a
+
+TOOL_GCC3PLAIN_LDFLAGS          ?=
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC3PLAIN_COMPILE_C_DEPEND =
+TOOL_GCC3PLAIN_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC3PLAIN_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GCC3PLAIN_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GCC3PLAIN_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GCC3PLAIN_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC3PLAIN_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GCC3PLAIN_COMPILE_C_OUTPUT =
+define TOOL_GCC3PLAIN_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GCC3PLAIN_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC3PLAIN_COMPILE_CXX_DEPEND =
+TOOL_GCC3PLAIN_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC3PLAIN_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GCC3PLAIN_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GCC3PLAIN_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GCC3PLAIN_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC3PLAIN_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GCC3PLAIN_COMPILE_CXX_OUTPUT =
+define TOOL_GCC3PLAIN_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GCC3PLAIN_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GCC3PLAIN_COMPILE_AS_OUTPUT =
+TOOL_GCC3PLAIN_COMPILE_AS_DEPEND =
+TOOL_GCC3PLAIN_COMPILE_AS_DEPORD =
+define TOOL_GCC3PLAIN_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GCC3PLAIN_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3PLAIN_LINK_LIBRARY_OUTPUT =
+TOOL_GCC3PLAIN_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GCC3PLAIN_LINK_LIBRARY_DEPORD =
+define TOOL_GCC3PLAIN_LINK_LIBRARY_CMDS
+	$(call xargs,$(QUIET)$(TOOL_GCC3PLAIN_AR) $(flags) $(out),$(objs))
+	$(foreach lib,$(othersrc)\
+		,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \
+		$(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \
+			&& $(TOOL_GCC3PLAIN_AR) x $(abspath $(lib)) \
+			&& $(TOOL_GCC3PLAIN_AR) $(flags) $(out) *) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/)
+	$(QUIET)$(TOOL_GCC3PLAIN_RANLIB) $(out)
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3PLAIN_LINK_PROGRAM_OUTPUT =
+TOOL_GCC3PLAIN_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC3PLAIN_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GCC3PLAIN_LINK_PROGRAM_DEPORD =
+define TOOL_GCC3PLAIN_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GCC3PLAIN_LD) $(flags) -o $(out) $(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3PLAIN_LINK_DLL_OUTPUT =
+TOOL_GCC3PLAIN_LINK_DLL_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC3PLAIN_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GCC3PLAIN_LINK_DLL_DEPORD =
+define TOOL_GCC3PLAIN_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GCC3PLAIN_LD) $(TOOL_GCC3PLAIN_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win32 os2, $(KBUILD_TARGET)),$(call TOOL_GCC3PLAIN_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# This tool target might not work everywhere, but is provided for the
+# platforms where it works (Solaris, etc).
+#
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC3PLAIN_LINK_SYSMOD_OUTPUT =
+TOOL_GCC3PLAIN_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC3PLAIN_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GCC3PLAIN_LINK_SYSMOD_DEPORD =
+define TOOL_GCC3PLAIN_LINK_SYSMOD_CMDS
+	$(QUIET)$(if $(TOOL_GCC3PLAIN_LD_SYSMOD.$(bld_trg)),$(TOOL_GCC3PLAIN_LD_SYSMOD.$(bld_trg)),$(TOOL_GCC3PLAIN_LD_SYSMOD))\
+		$(TOOL_GCC3PLAIN_LDFLAGS_SYSMOD.$(bld_trg))  $(flags) -o $(out)\
+		$(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GCC4MACHO.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GCC4MACHO.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GCC4MACHO.kmk	(revision 1780)
@@ -0,0 +1,351 @@
+# $Id$
+## @file
+# kBuild Tool Config - GCC v4 targeting Darwin (Mac OS X) Mach-o.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GCC4MACHO := GCC v4 targeting Darwin (Mac OS X) Mach-o.
+
+# Tool Specific Properties
+TOOL_GCC4MACHO_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC4MACHO_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GCC4MACHO_OBJC?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC4MACHO_AS  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC4MACHO_LD  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GCC4MACHO_LD_SYSMOD ?= gcc$(HOSTSUFF_EXE)
+ifndef TOOL_GCC4MACHO_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GCC4MACHO_LDFLAGS.dll ?= -dynamiclib
+else
+TOOL_GCC4MACHO_LDFLAGS.dll ?= $(TOOL_GCC4MACHO_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GCC4MACHO_LDFLAGS.sysmod ?= -r
+#TOOL_GCC4MACHO_LD_SONAME = -Wl,-dylib_install_name $(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+
+ifdef SLKRUNS
+TOOL_GCC4MACHO_CC  += -fmessage-length=0
+TOOL_GCC4MACHO_CXX += -fmessage-length=0
+TOOL_GCC4MACHO_OBJC+= -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GCC4MACHO_COBJSUFF         ?= .o
+TOOL_GCC4MACHO_CFLAGS           ?=
+TOOL_GCC4MACHO_CFLAGS.debug     ?= -g
+TOOL_GCC4MACHO_CFLAGS.profile   ?= -g -O2 #-pg
+TOOL_GCC4MACHO_CFLAGS.release   ?= -O2
+TOOL_GCC4MACHO_CINCS            ?=
+TOOL_GCC4MACHO_CDEFS            ?=
+
+TOOL_GCC4MACHO_CXXOBJSUFF       ?= .o
+TOOL_GCC4MACHO_CXXOBJSUFF       ?= .o
+TOOL_GCC4MACHO_CXXFLAGS         ?=
+TOOL_GCC4MACHO_CXXFLAGS.debug   ?= -g
+TOOL_GCC4MACHO_CXXFLAGS.profile ?= -g -O2 #-pg
+TOOL_GCC4MACHO_CXXFLAGS.release ?= -O2
+TOOL_GCC4MACHO_CXXINCS          ?=
+TOOL_GCC4MACHO_CXXDEFS          ?=
+
+TOOL_GCC4MACHO_OBJCOBJSUFF      ?= .o
+TOOL_GCC4MACHO_OBJCOBJSUFF      ?= .o
+TOOL_GCC4MACHO_OBJCFLAGS        ?=
+TOOL_GCC4MACHO_OBJCFLAGS.debug  ?= -g
+TOOL_GCC4MACHO_OBJCFLAGS.profile?= -O2 #-g -pg
+TOOL_GCC4MACHO_OBJCFLAGS.release?= -O2
+TOOL_GCC4MACHO_OBJCINCS         ?=
+TOOL_GCC4MACHO_OBJCDEFS         ?=
+
+TOOL_GCC4MACHO_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GCC4MACHO_ASFLAGS.debug    ?= -g
+TOOL_GCC4MACHO_ASFLAGS.profile  ?= -g
+TOOL_GCC4MACHO_ASOBJSUFF        ?= .o
+
+TOOL_GCC4MACHO_AR               ?= ar$(HOSTSUFF_EXE)
+TOOL_GCC4MACHO_ARFLAGS          ?= -c -rs
+TOOL_GCC4MACHO_ARLIBSUFF        ?= .a
+
+TOOL_GCC4MACHO_LDFLAGS          ?=
+TOOL_GCC4MACHO_LDFLAGS.debug    ?= -g
+TOOL_GCC4MACHO_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC4MACHO_COMPILE_C_DEPEND =
+TOOL_GCC4MACHO_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC4MACHO_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GCC4MACHO_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GCC4MACHO_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GCC4MACHO_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC4MACHO_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else  # !KBUILD_USE_KOBJCACHE
+TOOL_GCC4MACHO_COMPILE_C_OUTPUT =
+define TOOL_GCC4MACHO_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GCC4MACHO_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KUSE_OBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC4MACHO_COMPILE_CXX_DEPEND =
+TOOL_GCC4MACHO_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC4MACHO_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GCC4MACHO_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GCC4MACHO_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GCC4MACHO_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC4MACHO_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else  # !KBUILD_USE_KOBJCACHE
+TOOL_GCC4MACHO_COMPILE_CXX_OUTPUT =
+define TOOL_GCC4MACHO_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GCC4MACHO_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Objective-C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC4MACHO_COMPILE_OBJC_DEPEND =
+TOOL_GCC4MACHO_COMPILE_OBJC_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC4MACHO_COMPILE_OBJC_USES_KOBJCACHE = 1
+TOOL_GCC4MACHO_COMPILE_OBJC_OUTPUT = $(outbase).mi
+define TOOL_GCC4MACHO_COMPILE_OBJC_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GCC4MACHO_OBJC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC4MACHO_OBJC) -c\
+		$(flags) -fpreprocessed -x cbjective-c\
+		-o $(obj)\
+		-
+endef
+else  # !KBUILD_USE_KOBJCACHE
+TOOL_GCC4MACHO_COMPILE_OBJC_OUTPUT =
+define TOOL_GCC4MACHO_COMPILE_OBJC_CMDS
+	$(QUIET)$(TOOL_GCC4MACHO_OBJC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GCC4MACHO_COMPILE_AS_OUTPUT =
+TOOL_GCC4MACHO_COMPILE_AS_DEPEND =
+TOOL_GCC4MACHO_COMPILE_AS_DEPORD =
+define TOOL_GCC4MACHO_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GCC4MACHO_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC4MACHO_LINK_LIBRARY_OUTPUT =
+TOOL_GCC4MACHO_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GCC4MACHO_LINK_LIBRARY_DEPORD =
+define TOOL_GCC4MACHO_LINK_LIBRARY_CMDS
+	$(if $(strip $(objs)),$(call xargs,$(QUIET)$(TOOL_GCC4MACHO_AR) $(flags) $(out),$(objs)))
+	$(foreach lib,$(othersrc)\
+		,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \
+		$(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \
+			&& $(TOOL_GCC4MACHO_AR) -x $(abspath $(lib)) \
+		    && $(RM_EXT) -f ./__.SYMDEF* \
+			&& $(TOOL_GCC4MACHO_AR) $(flags) $(out) *) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/)
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC4MACHO_LINK_PROGRAM_OUTPUT = $(outbase).rsp
+TOOL_GCC4MACHO_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC4MACHO_LINK_PROGRAM_DEPORD =
+define TOOL_GCC4MACHO_LINK_PROGRAM_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp $(objs)
+	$(QUIET)$(TOOL_GCC4MACHO_LD) $(flags) -o $(out)\
+		-filelist $(outbase).rsp\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC4MACHO_LINK_DLL_OUTPUT = $(outbase).rsp
+TOOL_GCC4MACHO_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC4MACHO_LINK_DLL_DEPORD =
+define TOOL_GCC4MACHO_LINK_DLL_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp $(objs)
+	$(QUIET)$(TOOL_GCC4MACHO_LD) $(TOOL_GCC4MACHO_LDFLAGS.dll) $(flags) -o $(out)\
+		$(call TOOL_GCC4MACHO_LD_SONAME,$(target),$(out))\
+		-filelist $(outbase).rsp\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC4MACHO_LINK_SYSMOD_OUTPUT = $(outbase).rsp
+TOOL_GCC4MACHO_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC4MACHO_LINK_SYSMOD_DEPORD =
+define TOOL_GCC4MACHO_LINK_SYSMOD_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp $(objs)
+	$(QUIET)$(TOOL_GCC4MACHO_LD_SYSMOD) $(TOOL_GCC4MACHO_LDFLAGS.sysmod) $(flags) -o $(out)\
+		-filelist $(outbase).rsp\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GCC64.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GCC64.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GCC64.kmk	(revision 1780)
@@ -0,0 +1,306 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic 64-bit GCC v3.2.x or later Using The System GCC.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GCC64 := Generic 64-bit GCC v3.2.x or later Using The System GCC. \
+	More or less Linux/ELF specfic.
+
+# Tool Specific Properties
+TOOL_GCC64_CC  ?= gcc$(HOSTSUFF_EXE) -m64
+TOOL_GCC64_CXX ?= g++$(HOSTSUFF_EXE) -m64
+TOOL_GCC64_AS  ?= gcc$(HOSTSUFF_EXE) -m64
+TOOL_GCC64_AR  ?= ar$(HOSTSUFF_EXE)
+TOOL_GCC64_LD  ?= gcc$(HOSTSUFF_EXE) -m64
+TOOL_GCC64_LD_SYSMOD ?= ld$(HOSTSUFF_EXE)
+ifndef TOOL_GCC64_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GCC64_LDFLAGS.dll ?= -shared
+else
+TOOL_GCC64_LDFLAGS.dll ?= $(TOOL_GCC64_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GCC64_LDFLAGS.sysmod ?= -r -m elf_x86_64
+TOOL_GCC64_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+ifeq ($(KBUILD_TARGET),os2)
+TOOL_GCC64_LD_MAP ?= -Zmap=$(1)
+else
+TOOL_GCC64_LD_MAP ?=
+endif
+ifeq ($(KBUILD_TARGET),os2)
+TOOL_GCC64_LD_SYSMOD_MAP ?= -Zmap=$(1)
+else
+TOOL_GCC64_LD_SYSMOD_MAP ?=
+endif
+ifdef SLKRUNS
+TOOL_GCC64_CC  += -fmessage-length=0
+TOOL_GCC64_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GCC64_COBJSUFF         ?= .o
+TOOL_GCC64_CFLAGS           ?=
+TOOL_GCC64_CFLAGS.debug     ?= -g
+TOOL_GCC64_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GCC64_CFLAGS.release   ?= -O2
+TOOL_GCC64_CINCS            ?=
+TOOL_GCC64_CDEFS            ?=
+
+TOOL_GCC64_CXXOBJSUFF       ?= .o
+TOOL_GCC64_CXXOBJSUFF       ?= .o
+TOOL_GCC64_CXXFLAGS         ?=
+TOOL_GCC64_CXXFLAGS.debug   ?= -g
+TOOL_GCC64_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GCC64_CXXFLAGS.release ?= -O2
+TOOL_GCC64_CXXINCS          ?=
+TOOL_GCC64_CXXDEFS          ?=
+
+TOOL_GCC64_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GCC64_ASFLAGS.debug    ?= -g
+TOOL_GCC64_ASFLAGS.profile  ?= -g
+TOOL_GCC64_ASOBJSUFF        ?= .o
+
+TOOL_GCC64_ARFLAGS          ?= cr
+TOOL_GCC64_ARLIBSUFF        ?= .a
+
+TOOL_GCC64_LDFLAGS          ?=
+TOOL_GCC64_LDFLAGS.debug    ?= -g
+TOOL_GCC64_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC64_COMPILE_C_DEPEND =
+TOOL_GCC64_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC64_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GCC64_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GCC64_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GCC64_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC64_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GCC64_COMPILE_C_OUTPUT =
+define TOOL_GCC64_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GCC64_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GCC64_COMPILE_CXX_DEPEND =
+TOOL_GCC64_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GCC64_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GCC64_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GCC64_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GCC64_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GCC64_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+
+TOOL_GCC64_COMPILE_CXX_OUTPUT =
+define TOOL_GCC64_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GCC64_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GCC64_COMPILE_AS_OUTPUT =
+TOOL_GCC64_COMPILE_AS_DEPEND =
+TOOL_GCC64_COMPILE_AS_DEPORD =
+define TOOL_GCC64_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GCC64_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC64_LINK_LIBRARY_OUTPUT = $(out).ar-script
+TOOL_GCC64_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GCC64_LINK_LIBRARY_DEPORD =
+define TOOL_GCC64_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)'
+	$(QUIET)$(APPEND) -n $(out).ar-script \
+		$(foreach o,$(objs), 'ADDMOD $(o)') \
+		$(foreach o,$(othersrc), 'ADDLIB $(o)')
+	$(QUIET)$(APPEND) $(out).ar-script 'SAVE'
+	$(QUIET)$(APPEND) $(out).ar-script 'END'
+	$(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GCC64_AR) -M
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC64_LINK_PROGRAM_OUTPUT =
+TOOL_GCC64_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC64_LINK_PROGRAM_DEPORD =
+define TOOL_GCC64_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GCC64_LD) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC64_LD_MAP,$(outbase).map)
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC64_LINK_DLL_OUTPUT =
+TOOL_GCC64_LINK_DLL_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC64_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC64_LINK_DLL_DEPORD =
+define TOOL_GCC64_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GCC64_LD) $(TOOL_GCC64_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GCC64_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC64_LD_MAP,$(outbase).map)
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GCC64_LINK_SYSMOD_OUTPUT =
+TOOL_GCC64_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map
+TOOL_GCC64_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GCC64_LINK_SYSMOD_DEPORD =
+define TOOL_GCC64_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_GCC64_LD_SYSMOD) $(TOOL_GCC64_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GCC64_LD_SYSMOD_MAP,$(outbase).map)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GXX.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GXX.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GXX.kmk	(revision 1780)
@@ -0,0 +1,228 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic GCC using the system GCC, for building C++ code.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GXX := Generic GCC using the system GCC, for building C++ code.
+
+# Tool Specific Properties
+TOOL_GXX_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX_AS  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX_AR  ?= ar$(HOSTSUFF_EXE)
+TOOL_GXX_RANLIB ?= ranlib$(HOSTSUFF_EXE)
+TOOL_GXX_LD  ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX_LDFLAGS.dll.os2 ?= -Zdll
+TOOL_GXX_LDFLAGS.dll.darwin ?= -dynamiclib
+ifndef TOOL_GXX_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GXX_LDFLAGS.dll ?= -shared
+else
+TOOL_GXX_LDFLAGS.dll ?= $(TOOL_GXX_LDFLAGS.$(KBUILD_TARGET))
+endif
+
+# General Properties used by kBuild
+TOOL_GXX_COBJSUFF         ?= .o
+TOOL_GXX_CFLAGS           ?=
+TOOL_GXX_CFLAGS.debug     ?= -g
+TOOL_GXX_CFLAGS.profile   ?= -g -O2 #-pg
+TOOL_GXX_CFLAGS.release   ?= -O2
+TOOL_GXX_CINCS            ?=
+TOOL_GXX_CDEFS            ?=
+
+TOOL_GXX_CXXOBJSUFF       ?= .o
+TOOL_GXX_CXXOBJSUFF       ?= .o
+TOOL_GXX_CXXFLAGS         ?=
+TOOL_GXX_CXXFLAGS.debug   ?= -g -O0
+TOOL_GXX_CXXFLAGS.profile ?= -g -O2 #-pg
+TOOL_GXX_CXXFLAGS.release ?= -O2
+TOOL_GXX_CXXINCS          ?=
+TOOL_GXX_CXXDEFS          ?=
+
+TOOL_GXX_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GXX_ASFLAGS.debug    ?= -g
+TOOL_GXX_ASFLAGS.profile  ?= -g
+TOOL_GXX_ASOBJSUFF        ?= .o
+
+TOOL_GXX_ARFLAGS          ?= cr
+TOOL_GXX_ARLIBSUFF        ?= .a
+
+TOOL_GXX_LDFLAGS          ?=
+TOOL_GXX_LDFLAGS.debug    ?= -g
+TOOL_GXX_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GXX_COMPILE_C_OUTPUT =
+TOOL_GXX_COMPILE_C_DEPEND =
+TOOL_GXX_COMPILE_C_DEPORD =
+define TOOL_GXX_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GXX_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX_COMPILE_CXX_OUTPUT =
+TOOL_GXX_COMPILE_CXX_DEPEND =
+TOOL_GXX_COMPILE_CXX_DEPORD =
+define TOOL_GXX_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GXX_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GXX_COMPILE_AS_OUTPUT =
+TOOL_GXX_COMPILE_AS_DEPEND =
+TOOL_GXX_COMPILE_AS_DEPORD =
+define TOOL_GXX_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GXX_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX_LINK_LIBRARY_OUTPUT =
+TOOL_GXX_LINK_LIBRARY_DEPEND =
+TOOL_GXX_LINK_LIBRARY_DEPORD =
+define TOOL_GXX_LINK_LIBRARY_CMDS
+	$(QUIET)$(TOOL_GXX_AR) $(flags) $(out) $(objs)
+	$(call xargs,$(QUIET)$(TOOL_GXX_AR) $(flags) $(out),$(objs))
+	$(foreach lib,$(othersrc)\
+		,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \
+		$(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \
+			&& $(TOOL_GXX_AR) x $(abspath $(lib)) \
+			&& $(TOOL_GXX_AR) $(flags) $(out) *) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/)
+	$(QUIET)$(TOOL_GXX_RANLIB) $(out)
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX_LINK_PROGRAM_OUTPUT =
+TOOL_GXX_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX_LINK_PROGRAM_DEPORD =
+define TOOL_GXX_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GXX_LD) $(flags) -o $(out) $(objs) \
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+TOOL_GXX_LINK_DLL_OUTPUT =
+TOOL_GXX_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX_LINK_DLL_DEPORD =
+define TOOL_GXX_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GXX_LD) $(TOOL_GXX_LDFLAGS.dll) $(flags) -o $(out) $(objs) \
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GXX3.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GXX3.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GXX3.kmk	(revision 1780)
@@ -0,0 +1,321 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic GCC v3.2.x using the system GCC and Binutils, for building C++ code.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GXX3 := Generic GCC v3.2.x or later using the system GCC and Binutils, for building C++ code.
+
+# Tool Specific Properties
+TOOL_GXX3_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX3_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX3_AS  ?= gcc$(HOSTSUFF_EXE)
+ifeq ($(KBUILD_TARGET),solaris)
+ TOOL_GXX3_AR ?= gar$(HOSTSUFF_EXE)
+else
+ TOOL_GXX3_AR ?= ar$(HOSTSUFF_EXE)
+endif
+ifeq ($(KBUILD_TARGET),os2)
+ TOOL_GXX3_AR_IMP ?= emximp$(HOSTSTUFF_EXE)
+else
+ TOOL_GXX3_AR_IMP ?= $(ECHO) not supported!
+endif
+TOOL_GXX3_LD ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX3_LD_SYSMOD ?= ld$(HOSTSUFF_EXE)
+ifndef TOOL_GXX3_LDFLAGS.$(KBUILD_TARGET)
+ TOOL_GXX3_LDFLAGS.dll ?= -shared
+else
+ TOOL_GXX3_LDFLAGS.dll ?= $(TOOL_GXX3_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GXX3_LDFLAGS.sysmod ?= -r
+TOOL_GXX3_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+ifeq ($(KBUILD_TARGET),os2)
+ TOOL_GXX3_LD_MAP ?= -Zmap=$(1)
+ TOOL_GXX3_LD_SYSMOD_MAP ?= -Zmap=$(1)
+else
+ TOOL_GXX3_LD_MAP ?=
+ TOOL_GXX3_LD_SYSMOD_MAP ?=
+endif
+ifdef SLKRUNS
+ TOOL_GXX3_CC  += -fmessage-length=0
+ TOOL_GXX3_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GXX3_COBJSUFF         ?= .o
+TOOL_GXX3_CFLAGS           ?=
+TOOL_GXX3_CFLAGS.debug     ?= -g
+TOOL_GXX3_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GXX3_CFLAGS.release   ?= -O2
+TOOL_GXX3_CINCS            ?=
+TOOL_GXX3_CDEFS            ?=
+
+TOOL_GXX3_CXXOBJSUFF       ?= .o
+TOOL_GXX3_CXXOBJSUFF       ?= .o
+TOOL_GXX3_CXXFLAGS         ?=
+TOOL_GXX3_CXXFLAGS.debug   ?= -g
+TOOL_GXX3_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GXX3_CXXFLAGS.release ?= -O2
+TOOL_GXX3_CXXINCS          ?=
+TOOL_GXX3_CXXDEFS          ?=
+
+TOOL_GXX3_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GXX3_ASFLAGS.debug    ?= -g
+TOOL_GXX3_ASFLAGS.profile  ?= -g
+TOOL_GXX3_ASOBJSUFF        ?= .o
+
+TOOL_GXX3_ARFLAGS          ?= cr
+TOOL_GXX3_ARLIBSUFF        ?= .a
+
+TOOL_GXX3_LDFLAGS          ?=
+TOOL_GXX3_LDFLAGS.debug    ?= -g
+TOOL_GXX3_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX3_COMPILE_C_DEPEND =
+TOOL_GXX3_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX3_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GXX3_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GXX3_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GXX3_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX3_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX3_COMPILE_C_OUTPUT =
+define TOOL_GXX3_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GXX3_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX3_COMPILE_CXX_DEPEND =
+TOOL_GXX3_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX3_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GXX3_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GXX3_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GXX3_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX3_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX3_COMPILE_CXX_OUTPUT =
+define TOOL_GXX3_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GXX3_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GXX3_COMPILE_AS_OUTPUT =
+TOOL_GXX3_COMPILE_AS_DEPEND =
+TOOL_GXX3_COMPILE_AS_DEPORD =
+define TOOL_GXX3_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GXX3_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3_LINK_LIBRARY_OUTPUT = $(out).ar-script
+TOOL_GXX3_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).imp.a
+TOOL_GXX3_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GXX3_LINK_LIBRARY_DEPORD =
+define TOOL_GXX3_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)'
+	$(QUIET)$(APPEND) -n $(out).ar-script \
+		$(foreach o,$(objs), 'ADDMOD $(o)') \
+		$(foreach o,$(filter-out %.def %.imp,$(othersrc)), 'ADDLIB $(o)')
+	$(if $(filter %.def %.imp,$(othersrc))\
+		,$(TOOL_GXX3_AR_IMP) -o $(outbase).imp.a $(filter %.def %.imp,$(othersrc))\
+		 $(NL)$(TAB)$(QUIET)$(APPEND) $(out).ar-script 'ADDLIB $(outbase).imp.a')
+	$(QUIET)$(APPEND) $(out).ar-script 'SAVE'
+	$(QUIET)$(APPEND) $(out).ar-script 'END'
+	$(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GXX3_AR) -M
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3_LINK_PROGRAM_OUTPUT =
+TOOL_GXX3_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX3_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GXX3_LINK_PROGRAM_DEPORD =
+define TOOL_GXX3_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GXX3_LD) $(flags) -o $(out) $(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX3_LD_MAP,$(outbase).map)
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3_LINK_DLL_OUTPUT =
+TOOL_GXX3_LINK_DLL_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX3_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GXX3_LINK_DLL_DEPORD =
+define TOOL_GXX3_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GXX3_LD) $(TOOL_GXX3_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win32 os2, $(KBUILD_TARGET)),$(call TOOL_GXX3_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX3_LD_MAP,$(outbase).map)
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3_LINK_SYSMOD_OUTPUT =
+TOOL_GXX3_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX3_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GXX3_LINK_SYSMOD_DEPORD =
+define TOOL_GXX3_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_GXX3_LD_SYSMOD) $(TOOL_GXX3_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX3_LD_SYSMOD_MAP,$(outbase).map)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GXX32.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GXX32.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GXX32.kmk	(revision 1780)
@@ -0,0 +1,305 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic 32-bit GCC v3.2.x or later using the system GCC, for building C++ code.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GXX32 := Generic 32-bit GCC v3.2.x or later using the system GCC, for building C++ code. \
+	More or less Linux/ELF specfic.
+
+# Tool Specific Properties
+TOOL_GXX32_CC  ?= gcc$(HOSTSUFF_EXE) -m32
+TOOL_GXX32_CXX ?= g++$(HOSTSUFF_EXE) -m32
+TOOL_GXX32_AS  ?= gcc$(HOSTSUFF_EXE) -m32
+TOOL_GXX32_AR  ?= ar$(HOSTSUFF_EXE)
+TOOL_GXX32_LD  ?= g++$(HOSTSUFF_EXE) -m32
+TOOL_GXX32_LD_SYSMOD ?= ld$(HOSTSUFF_EXE)
+ifndef TOOL_GXX32_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GXX32_LDFLAGS.dll ?= -shared
+else
+TOOL_GXX32_LDFLAGS.dll ?= $(TOOL_GXX32_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GXX32_LDFLAGS.sysmod ?= -r -m elf_i386
+TOOL_GXX32_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+ifeq ($(KBUILD_TARGET),os2)
+TOOL_GXX32_LD_MAP ?= -Zmap=$(1)
+else
+TOOL_GXX32_LD_MAP ?=
+endif
+ifeq ($(KBUILD_TARGET),os2)
+TOOL_GXX32_LD_SYSMOD_MAP ?= -Zmap=$(1)
+else
+TOOL_GXX32_LD_SYSMOD_MAP ?=
+endif
+ifdef SLKRUNS
+TOOL_GXX32_CC  += -fmessage-length=0
+TOOL_GXX32_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GXX32_COBJSUFF         ?= .o
+TOOL_GXX32_CFLAGS           ?=
+TOOL_GXX32_CFLAGS.debug     ?= -g
+TOOL_GXX32_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GXX32_CFLAGS.release   ?= -O2
+TOOL_GXX32_CINCS            ?=
+TOOL_GXX32_CDEFS            ?=
+
+TOOL_GXX32_CXXOBJSUFF       ?= .o
+TOOL_GXX32_CXXOBJSUFF       ?= .o
+TOOL_GXX32_CXXFLAGS         ?=
+TOOL_GXX32_CXXFLAGS.debug   ?= -g
+TOOL_GXX32_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GXX32_CXXFLAGS.release ?= -O2
+TOOL_GXX32_CXXINCS          ?=
+TOOL_GXX32_CXXDEFS          ?=
+
+TOOL_GXX32_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GXX32_ASFLAGS.debug    ?= -g
+TOOL_GXX32_ASFLAGS.profile  ?= -g
+TOOL_GXX32_ASOBJSUFF        ?= .o
+
+TOOL_GXX32_ARFLAGS          ?= cr
+TOOL_GXX32_ARLIBSUFF        ?= .a
+
+TOOL_GXX32_LDFLAGS          ?=
+TOOL_GXX32_LDFLAGS.debug    ?= -g
+TOOL_GXX32_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX32_COMPILE_C_DEPEND =
+TOOL_GXX32_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX32_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GXX32_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GXX32_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GXX32_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX32_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX32_COMPILE_C_OUTPUT =
+define TOOL_GXX32_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GXX32_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX32_COMPILE_CXX_DEPEND =
+TOOL_GXX32_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX32_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GXX32_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GXX32_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GXX32_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX32_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX32_COMPILE_CXX_OUTPUT =
+define TOOL_GXX32_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GXX32_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GXX32_COMPILE_AS_OUTPUT =
+TOOL_GXX32_COMPILE_AS_DEPEND =
+TOOL_GXX32_COMPILE_AS_DEPORD =
+define TOOL_GXX32_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GXX32_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX32_LINK_LIBRARY_OUTPUT = $(out).ar-script
+TOOL_GXX32_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GXX32_LINK_LIBRARY_DEPORD =
+define TOOL_GXX32_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)'
+	$(QUIET)$(APPEND) -n $(out).ar-script \
+		$(foreach o,$(objs), 'ADDMOD $(o)') \
+		$(foreach o,$(othersrc), 'ADDLIB $(o)')
+	$(QUIET)$(APPEND) $(out).ar-script 'SAVE'
+	$(QUIET)$(APPEND) $(out).ar-script 'END'
+	$(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GXX32_AR) -M
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX32_LINK_PROGRAM_OUTPUT =
+TOOL_GXX32_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX32_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX32_LINK_PROGRAM_DEPORD =
+define TOOL_GXX32_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GXX32_LD) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX32_LD_MAP,$(outbase).map)
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX32_LINK_DLL_OUTPUT =
+TOOL_GXX32_LINK_DLL_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX32_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX32_LINK_DLL_DEPORD =
+define TOOL_GXX32_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GXX32_LD) $(TOOL_GXX32_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GXX32_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX32_LD_MAP,$(outbase).map)
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX32_LINK_SYSMOD_OUTPUT =
+TOOL_GXX32_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX32_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX32_LINK_SYSMOD_DEPORD =
+define TOOL_GXX32_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_GXX32_LD_SYSMOD) $(TOOL_GXX32_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX32_LD_SYSMOD_MAP,$(outbase).map)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GXX3OMF.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GXX3OMF.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GXX3OMF.kmk	(revision 1780)
@@ -0,0 +1,314 @@
+# $Id$
+## @file
+# kBuild Tool Config - GCC v3 targeting OS/2 OMF, for building C++ code.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GXX3OMF := GCC v3 targeting OS/2 OMF, for building C++ code.
+
+# Tool Specific Properties
+TOOL_GXX3OMF_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX3OMF_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX3OMF_AS  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX3OMF_AR  ?= emxomfar$(HOSTSUFF_EXE)
+TOOL_GXX3OMF_AR_IMP ?= emximp$(HOSTSUFF_EXE)
+TOOL_GXX3OMF_LD ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX3OMF_LD_SYSMOD ?= g++$(HOSTSUFF_EXE)
+ifndef TOOL_GXX3OMF_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GXX3OMF_LDFLAGS.dll ?= -shared -Zdll
+else
+TOOL_GXX3OMF_LDFLAGS.dll ?= $(TOOL_GXX3OMF_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GXX3OMF_LDFLAGS.sysmod ?= -nostdlib
+TOOL_GXX3OMF_LD_MAP ?= -Zmap=$(1)
+TOOL_GXX3OMF_LD_SYSMOD_MAP ?= -Zmap=$(1)
+
+ifdef SLKRUNS
+TOOL_GXX3OMF_CC  += -fmessage-length=0
+TOOL_GXX3OMF_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GXX3OMF_COBJSUFF         ?= .o
+TOOL_GXX3OMF_CFLAGS           ?= -Zomf
+TOOL_GXX3OMF_CFLAGS.debug     ?= -g
+TOOL_GXX3OMF_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GXX3OMF_CFLAGS.release   ?= -O2
+TOOL_GXX3OMF_CINCS            ?=
+TOOL_GXX3OMF_CDEFS            ?=
+
+TOOL_GXX3OMF_CXXOBJSUFF       ?= .o
+TOOL_GXX3OMF_CXXOBJSUFF       ?= .o
+TOOL_GXX3OMF_CXXFLAGS         ?= -Zomf
+TOOL_GXX3OMF_CXXFLAGS.debug   ?= -g
+TOOL_GXX3OMF_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GXX3OMF_CXXFLAGS.release ?= -O2
+TOOL_GXX3OMF_CXXINCS          ?=
+TOOL_GXX3OMF_CXXDEFS          ?=
+
+TOOL_GXX3OMF_ASFLAGS          ?= -x assembler-with-cpp -Zomf
+TOOL_GXX3OMF_ASFLAGS.debug    ?= -g
+TOOL_GXX3OMF_ASFLAGS.profile  ?= -g
+TOOL_GXX3OMF_ASOBJSUFF        ?= .obj
+
+TOOL_GXX3OMF_ARFLAGS          ?= cr
+TOOL_GXX3OMF_ARLIBSUFF        ?= .lib
+
+TOOL_GXX3OMF_LDFLAGS          ?= -Zomf
+TOOL_GXX3OMF_LDFLAGS.debug    ?= -g
+TOOL_GXX3OMF_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX3OMF_COMPILE_C_DEPEND =
+TOOL_GXX3OMF_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX3OMF_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GXX3OMF_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GXX3OMF_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GXX3OMF_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX3OMF_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX3OMF_COMPILE_C_OUTPUT =
+define TOOL_GXX3OMF_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GXX3OMF_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX3OMF_COMPILE_CXX_DEPEND =
+TOOL_GXX3OMF_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX3OMF_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GXX3OMF_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GXX3OMF_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GXX3OMF_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX3OMF_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX3OMF_COMPILE_CXX_OUTPUT =
+define TOOL_GXX3OMF_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GXX3OMF_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP \
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GXX3OMF_COMPILE_AS_OUTPUT =
+TOOL_GXX3OMF_COMPILE_AS_DEPEND =
+TOOL_GXX3OMF_COMPILE_AS_DEPORD =
+define TOOL_GXX3OMF_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GXX3OMF_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3OMF_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_GXX3OMF_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GXX3OMF_LINK_LIBRARY_DEPORD =
+define TOOL_GXX3OMF_LINK_LIBRARY_CMDS
+	$(if $(filter %.def %.imp,$(othersrc))\
+		,$(QUIET)$(APPEND) -n $(outbase).rsp $(filter %.def %.imp,$(othersrc))\
+		 $(NL)$(TAB)$(QUIET)$(QUIET)$(TOOL_GXX3OMF_AR_IMP) -o $(out) @$(outbase).rsp\
+		 $(NL)$(TAB)$(QUIET)$(RM) -f $(outbase).rsp)
+	$(QUIET)$(APPEND) -n $(outbase).rsp $(flags) $(out) $(objs) $(filter-out %.def %.imp,$(othersrc))
+	$(TOOL_GXX3OMF_AR) @$(outbase).rsp
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3OMF_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_GXX3OMF_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_GXX3OMF_LINK_PROGRAM_DEPORD =
+define TOOL_GXX3OMF_LINK_PROGRAM_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp\
+		$(flags)\
+		-o $(out)\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(othersrc)\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		-Zmap=$(outbase).map
+	$(QUIET)$(TOOL_GXX3OMF_LD) @$(outbase).rsp
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3OMF_LINK_DLL_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_GXX3OMF_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_GXX3OMF_LINK_DLL_DEPORD =
+define TOOL_GXX3OMF_LINK_DLL_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp\
+		$(TOOL_GXX3OMF_LDFLAGS.dll)\
+		$(flags)\
+		-o $(out)\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(othersrc)\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		-Zmap=$(outbase).map
+	$(TOOL_GXX3OMF_LD) @$(outbase).rsp
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3OMF_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_GXX3OMF_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_GXX3OMF_LINK_SYSMOD_DEPORD =
+define TOOL_GXX3OMF_LINK_SYSMOD_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp\
+		$(TOOL_GXX3OMF_LDFLAGS.sysmod)\
+		$(flags)\
+		-o $(out)\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(othersrc)\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		-Zmap=$(outbase).map
+	$(QUIET)$(TOOL_GXX3OMF_LD_SYSMOD) @$(outbase).rsp
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GXX3PLAIN.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GXX3PLAIN.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GXX3PLAIN.kmk	(revision 1780)
@@ -0,0 +1,315 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic GCC v3.2.x or later using the system GCC, any Unix linker and Unix archiver to build C++ code.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GXX3PLAIN := Generic GCC v3.2.x or later using the system GCC, any Unix linker and Unix archiver to build C++ code.
+
+# Tool Specific Properties
+TOOL_GXX3PLAIN_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX3PLAIN_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX3PLAIN_AS  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX3PLAIN_AR  ?= ar$(HOSTSUFF_EXE)
+TOOL_GXX3PLAIN_RANLIB ?= ranlib$(HOSTSUFF_EXE)
+TOOL_GXX3PLAIN_LD  ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX3PLAIN_LD_SYSMOD ?= ld$(HOSTSUFF_EXE)
+TOOL_GXX3PLAIN_LD_SYSMOD.os2 ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX3PLAIN_LDFLAGS.dll.os2 ?= -Zdll
+TOOL_GXX3PLAIN_LDFLAGS.dll.darwin ?= -dynamiclib
+ifndef TOOL_GXX3PLAIN_LDFLAGS.$(KBUILD_TARGET)
+ TOOL_GXX3PLAIN_LDFLAGS.dll ?= -shared
+else
+ TOOL_GXX3PLAIN_LDFLAGS.dll ?= $(TOOL_GXX3PLAIN_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GXX3PLAIN_LD_SONAME.darwin ?= $(NO_SUCH_VARIABLE)
+TOOL_GXX3PLAIN_LD_SONAME.os2 ?= $(NO_SUCH_VARIABLE)
+TOOL_GXX3PLAIN_LD_SONAME.solaris ?= -Wl,-h,$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+TOOL_GXX3PLAIN_LD_SONAME.win ?= $(NO_SUCH_VARIABLE)
+ifndef TOOL_GXX3PLAIN_LD_SONAME.$(KBUILD_TARGET)
+ TOOL_GXX3PLAIN_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+else
+ TOOL_GXX3PLAIN_LD_SONAME ?= $(TOOL_GXX3PLAIN_LD_SONAME.$(KBUILD_TARGET))
+endif
+ifdef SLKRUNS
+ TOOL_GXX3PLAIN_CC  += -fmessage-length=0
+ TOOL_GXX3PLAIN_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GXX3PLAIN_COBJSUFF         ?= .o
+TOOL_GXX3PLAIN_CFLAGS           ?=
+TOOL_GXX3PLAIN_CFLAGS.debug     ?= -g
+TOOL_GXX3PLAIN_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GXX3PLAIN_CFLAGS.release   ?= -O2
+TOOL_GXX3PLAIN_CINCS            ?=
+TOOL_GXX3PLAIN_CDEFS            ?=
+
+TOOL_GXX3PLAIN_CXXOBJSUFF       ?= .o
+TOOL_GXX3PLAIN_CXXOBJSUFF       ?= .o
+TOOL_GXX3PLAIN_CXXFLAGS         ?=
+TOOL_GXX3PLAIN_CXXFLAGS.debug   ?= -g
+TOOL_GXX3PLAIN_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GXX3PLAIN_CXXFLAGS.release ?= -O2
+TOOL_GXX3PLAIN_CXXINCS          ?=
+TOOL_GXX3PLAIN_CXXDEFS          ?=
+
+TOOL_GXX3PLAIN_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GXX3PLAIN_ASFLAGS.debug    ?= -g
+TOOL_GXX3PLAIN_ASFLAGS.profile  ?= -g
+TOOL_GXX3PLAIN_ASOBJSUFF        ?= .o
+
+TOOL_GXX3PLAIN_ARFLAGS          ?= cr
+TOOL_GXX3PLAIN_ARLIBSUFF        ?= .a
+
+TOOL_GXX3PLAIN_LDFLAGS          ?=
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX3PLAIN_COMPILE_C_DEPEND =
+TOOL_GXX3PLAIN_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX3PLAIN_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GXX3PLAIN_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GXX3PLAIN_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GXX3PLAIN_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX3PLAIN_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX3PLAIN_COMPILE_C_OUTPUT =
+define TOOL_GXX3PLAIN_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GXX3PLAIN_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX3PLAIN_COMPILE_CXX_DEPEND =
+TOOL_GXX3PLAIN_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX3PLAIN_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GXX3PLAIN_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GXX3PLAIN_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GXX3PLAIN_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX3PLAIN_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX3PLAIN_COMPILE_CXX_OUTPUT =
+define TOOL_GXX3PLAIN_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GXX3PLAIN_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GXX3PLAIN_COMPILE_AS_OUTPUT =
+TOOL_GXX3PLAIN_COMPILE_AS_DEPEND =
+TOOL_GXX3PLAIN_COMPILE_AS_DEPORD =
+define TOOL_GXX3PLAIN_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GXX3PLAIN_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3PLAIN_LINK_LIBRARY_OUTPUT =
+TOOL_GXX3PLAIN_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GXX3PLAIN_LINK_LIBRARY_DEPORD =
+define TOOL_GXX3PLAIN_LINK_LIBRARY_CMDS
+	$(call xargs,$(QUIET)$(TOOL_GXX3PLAIN_AR) $(flags) $(out),$(objs))
+	$(foreach lib,$(othersrc)\
+		,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \
+		$(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \
+			&& $(TOOL_GXX3PLAIN_AR) x $(abspath $(lib)) \
+			&& $(TOOL_GXX3PLAIN_AR) $(flags) $(out) *) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/)
+	$(QUIET)$(TOOL_GXX3PLAIN_RANLIB) $(out)
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3PLAIN_LINK_PROGRAM_OUTPUT =
+TOOL_GXX3PLAIN_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX3PLAIN_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GXX3PLAIN_LINK_PROGRAM_DEPORD =
+define TOOL_GXX3PLAIN_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GXX3PLAIN_LD) $(flags) -o $(out) $(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3PLAIN_LINK_DLL_OUTPUT =
+TOOL_GXX3PLAIN_LINK_DLL_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX3PLAIN_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GXX3PLAIN_LINK_DLL_DEPORD =
+define TOOL_GXX3PLAIN_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GXX3PLAIN_LD) $(TOOL_GXX3PLAIN_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win32 os2, $(KBUILD_TARGET)),$(call TOOL_GXX3PLAIN_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# This tool target might not work everywhere, but is provided for the
+# platforms where it works (Solaris, etc).
+#
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX3PLAIN_LINK_SYSMOD_OUTPUT =
+TOOL_GXX3PLAIN_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX3PLAIN_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+		$(filter %.def, $(othersrc))
+TOOL_GXX3PLAIN_LINK_SYSMOD_DEPORD =
+define TOOL_GXX3PLAIN_LINK_SYSMOD_CMDS
+	$(QUIET)$(if $(TOOL_GXX3PLAIN_LD_SYSMOD.$(bld_trg)),$(TOOL_GXX3PLAIN_LD_SYSMOD.$(bld_trg)),$(TOOL_GXX3PLAIN_LD_SYSMOD))\
+		$(TOOL_GXX3PLAIN_LDFLAGS_SYSMOD.$(bld_trg)) $(flags) -o $(out) \
+		$(objs)\
+		$(filter %.def, $(othersrc))\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GXX4MACHO.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GXX4MACHO.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GXX4MACHO.kmk	(revision 1780)
@@ -0,0 +1,352 @@
+# $Id$
+## @file
+# kBuild Tool Config - GCC v4 targeting Darwin (Mac OS X) Mach-o, for building C++ code.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GXX4MACHO := GCC v4 targeting Darwin (Mac OS X) Mach-o, for building C++ code.
+
+# Tool Specific Properties
+TOOL_GXX4MACHO_CC  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX4MACHO_CXX ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX4MACHO_OBJC?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX4MACHO_AS  ?= gcc$(HOSTSUFF_EXE)
+TOOL_GXX4MACHO_LD  ?= g++$(HOSTSUFF_EXE)
+TOOL_GXX4MACHO_LD_SYSMOD ?= g++$(HOSTSUFF_EXE)
+ifndef TOOL_GXX4MACHO_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GXX4MACHO_LDFLAGS.dll ?= -dynamiclib
+else
+TOOL_GXX4MACHO_LDFLAGS.dll ?= $(TOOL_GXX4MACHO_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GXX4MACHO_LDFLAGS.sysmod ?= -r
+#TOOL_GXX4MACHO_LD_SONAME = -Wl,-dylib_install_name $(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+
+ifdef SLKRUNS
+TOOL_GXX4MACHO_CC  += -fmessage-length=0
+TOOL_GXX4MACHO_CXX += -fmessage-length=0
+TOOL_GXX4MACHO_OBJC+= -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GXX4MACHO_COBJSUFF         ?= .o
+TOOL_GXX4MACHO_CFLAGS           ?=
+TOOL_GXX4MACHO_CFLAGS.debug     ?= -g
+TOOL_GXX4MACHO_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GXX4MACHO_CFLAGS.release   ?= -O2
+TOOL_GXX4MACHO_CINCS            ?=
+TOOL_GXX4MACHO_CDEFS            ?=
+
+TOOL_GXX4MACHO_CXXOBJSUFF       ?= .o
+TOOL_GXX4MACHO_CXXOBJSUFF       ?= .o
+TOOL_GXX4MACHO_CXXFLAGS         ?=
+TOOL_GXX4MACHO_CXXFLAGS.debug   ?= -g
+TOOL_GXX4MACHO_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GXX4MACHO_CXXFLAGS.release ?= -O2
+TOOL_GXX4MACHO_CXXINCS          ?=
+TOOL_GXX4MACHO_CXXDEFS          ?=
+
+TOOL_GXX4MACHO_OBJCOBJSUFF      ?= .o
+TOOL_GXX4MACHO_OBJCOBJSUFF      ?= .o
+TOOL_GXX4MACHO_OBJCFLAGS        ?=
+TOOL_GXX4MACHO_OBJCFLAGS.debug  ?= -g
+TOOL_GXX4MACHO_OBJCFLAGS.profile?= -O2 #-g -pg
+TOOL_GXX4MACHO_OBJCFLAGS.release?= -O2
+TOOL_GXX4MACHO_OBJCINCS         ?=
+TOOL_GXX4MACHO_OBJCDEFS         ?=
+
+TOOL_GXX4MACHO_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GXX4MACHO_ASFLAGS.debug    ?= -g
+TOOL_GXX4MACHO_ASFLAGS.profile  ?= -g
+TOOL_GXX4MACHO_ASOBJSUFF        ?= .o
+
+TOOL_GXX4MACHO_AR               ?= ar$(HOSTSUFF_EXE)
+TOOL_GXX4MACHO_ARFLAGS          ?= -c -rs
+TOOL_GXX4MACHO_ARLIBSUFF        ?= .a
+
+TOOL_GXX4MACHO_LDFLAGS          ?=
+TOOL_GXX4MACHO_LDFLAGS.debug    ?= -g
+TOOL_GXX4MACHO_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX4MACHO_COMPILE_C_DEPEND =
+TOOL_GXX4MACHO_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX4MACHO_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GXX4MACHO_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GXX4MACHO_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GXX4MACHO_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX4MACHO_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else  # !KBUILD_USE_KOBJCACHE
+TOOL_GXX4MACHO_COMPILE_C_OUTPUT =
+define TOOL_GXX4MACHO_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GXX4MACHO_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KUSE_OBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX4MACHO_COMPILE_CXX_DEPEND =
+TOOL_GXX4MACHO_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX4MACHO_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GXX4MACHO_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GXX4MACHO_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GXX4MACHO_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX4MACHO_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else  # !KBUILD_USE_KOBJCACHE
+TOOL_GXX4MACHO_COMPILE_CXX_OUTPUT =
+define TOOL_GXX4MACHO_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GXX4MACHO_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KUSE_OBJCACHE
+
+
+## Compile Objective-C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX4MACHO_COMPILE_OBJC_DEPEND =
+TOOL_GXX4MACHO_COMPILE_OBJC_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX4MACHO_COMPILE_OBJC_USES_KOBJCACHE = 1
+TOOL_GXX4MACHO_COMPILE_OBJC_OUTPUT = $(outbase).mi
+define TOOL_GXX4MACHO_COMPILE_OBJC_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GXX4MACHO_OBJC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX4MACHO_OBJC) -c\
+		$(flags) -fpreprocessed -x objective-c \
+		-o $(obj)\
+		-
+endef
+else  # !KBUILD_USE_KOBJCACHE
+TOOL_GXX4MACHO_COMPILE_OBJC_OUTPUT =
+define TOOL_GXX4MACHO_COMPILE_OBJC_CMDS
+	$(QUIET)$(TOOL_GXX4MACHO_OBJC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KUSE_OBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GXX4MACHO_COMPILE_AS_OUTPUT =
+TOOL_GXX4MACHO_COMPILE_AS_DEPEND =
+TOOL_GXX4MACHO_COMPILE_AS_DEPORD =
+define TOOL_GXX4MACHO_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GXX4MACHO_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX4MACHO_LINK_LIBRARY_OUTPUT =
+TOOL_GXX4MACHO_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GXX4MACHO_LINK_LIBRARY_DEPORD =
+define TOOL_GXX4MACHO_LINK_LIBRARY_CMDS
+	$(if $(strip $(objs)),$(call xargs,$(QUIET)$(TOOL_GXX4MACHO_AR) $(flags) $(out),$(objs)))
+	$(foreach lib,$(othersrc)\
+		,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \
+		$(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \
+			&& $(TOOL_GXX4MACHO_AR) -x $(abspath $(lib)) \
+		    && $(RM_EXT) -f ./__.SYMDEF* \
+			&& $(TOOL_GXX4MACHO_AR) $(flags) $(out) *) \
+		$(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \
+		$(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/)
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX4MACHO_LINK_PROGRAM_OUTPUT = $(outbase).rsp
+TOOL_GXX4MACHO_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX4MACHO_LINK_PROGRAM_DEPORD =
+define TOOL_GXX4MACHO_LINK_PROGRAM_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp $(objs)
+	$(QUIET)$(TOOL_GXX4MACHO_LD) $(flags) -o $(out)\
+		-filelist $(outbase).rsp\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX4MACHO_LINK_DLL_OUTPUT = $(outbase).rsp
+TOOL_GXX4MACHO_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX4MACHO_LINK_DLL_DEPORD =
+define TOOL_GXX4MACHO_LINK_DLL_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp $(objs)
+	$(QUIET)$(TOOL_GXX4MACHO_LD) $(TOOL_GXX4MACHO_LDFLAGS.dll) $(flags) -o $(out)\
+		$(call TOOL_GXX4MACHO_LD_SONAME,$(target),$(out))\
+		-filelist $(outbase).rsp\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX4MACHO_LINK_SYSMOD_OUTPUT = $(outbase).rsp
+TOOL_GXX4MACHO_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX4MACHO_LINK_SYSMOD_DEPORD =
+define TOOL_GXX4MACHO_LINK_SYSMOD_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp $(objs)
+	$(QUIET)$(TOOL_GXX4MACHO_LD_SYSMOD) $(TOOL_GXX4MACHO_LDFLAGS.sysmod) $(flags) -o $(out)\
+		-filelist $(outbase).rsp\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/GXX64.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/GXX64.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/GXX64.kmk	(revision 1780)
@@ -0,0 +1,305 @@
+# $Id$
+## @file
+# kBuild Tool Config - Generic 64-bit GCC v3.2.x or later using the system GCC, for building C++ code.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_GXX64 := Generic 64-bit GCC v3.2.x or later using the system GCC, for building C++ code. \
+	More or less Linux/ELF specfic.
+
+# Tool Specific Properties
+TOOL_GXX64_CC  ?= gcc$(HOSTSUFF_EXE) -m64
+TOOL_GXX64_CXX ?= g++$(HOSTSUFF_EXE) -m64
+TOOL_GXX64_AS  ?= gcc$(HOSTSUFF_EXE) -m64
+TOOL_GXX64_AR  ?= ar$(HOSTSUFF_EXE)
+TOOL_GXX64_LD  ?= g++$(HOSTSUFF_EXE) -m64
+TOOL_GXX64_LD_SYSMOD ?= ld$(HOSTSUFF_EXE)
+ifndef TOOL_GXX64_LDFLAGS.$(KBUILD_TARGET)
+TOOL_GXX64_LDFLAGS.dll ?= -shared
+else
+TOOL_GXX64_LDFLAGS.dll ?= $(TOOL_GXX64_LDFLAGS.$(KBUILD_TARGET))
+endif
+TOOL_GXX64_LDFLAGS.sysmod ?= -r -m elf_x86_64
+TOOL_GXX64_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+ifeq ($(KBUILD_TARGET),os2)
+TOOL_GXX64_LD_MAP ?= -Zmap=$(1)
+else
+TOOL_GXX64_LD_MAP ?=
+endif
+ifeq ($(KBUILD_TARGET),os2)
+TOOL_GXX64_LD_SYSMOD_MAP ?= -Zmap=$(1)
+else
+TOOL_GXX64_LD_SYSMOD_MAP ?=
+endif
+ifdef SLKRUNS
+TOOL_GXX64_CC  += -fmessage-length=0
+TOOL_GXX64_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_GXX64_COBJSUFF         ?= .o
+TOOL_GXX64_CFLAGS           ?=
+TOOL_GXX64_CFLAGS.debug     ?= -g
+TOOL_GXX64_CFLAGS.profile   ?= -O2 #-g -pg
+TOOL_GXX64_CFLAGS.release   ?= -O2
+TOOL_GXX64_CINCS            ?=
+TOOL_GXX64_CDEFS            ?=
+
+TOOL_GXX64_CXXOBJSUFF       ?= .o
+TOOL_GXX64_CXXOBJSUFF       ?= .o
+TOOL_GXX64_CXXFLAGS         ?=
+TOOL_GXX64_CXXFLAGS.debug   ?= -g
+TOOL_GXX64_CXXFLAGS.profile ?= -O2 #-g -pg
+TOOL_GXX64_CXXFLAGS.release ?= -O2
+TOOL_GXX64_CXXINCS          ?=
+TOOL_GXX64_CXXDEFS          ?=
+
+TOOL_GXX64_ASFLAGS          ?= -x assembler-with-cpp
+TOOL_GXX64_ASFLAGS.debug    ?= -g
+TOOL_GXX64_ASFLAGS.profile  ?= -g
+TOOL_GXX64_ASOBJSUFF        ?= .o
+
+TOOL_GXX64_ARFLAGS          ?= cr
+TOOL_GXX64_ARLIBSUFF        ?= .a
+
+TOOL_GXX64_LDFLAGS          ?=
+TOOL_GXX64_LDFLAGS.debug    ?= -g
+TOOL_GXX64_LDFLAGS.profile  ?= -g
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX64_COMPILE_C_DEPEND =
+TOOL_GXX64_COMPILE_C_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX64_COMPILE_C_USES_KOBJCACHE = 1
+TOOL_GXX64_COMPILE_C_OUTPUT = $(outbase).i
+define TOOL_GXX64_COMPILE_C_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).i\
+		$(TOOL_GXX64_CC) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX64_CC) -c\
+		$(flags) -fpreprocessed -x c\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX64_COMPILE_C_OUTPUT =
+define TOOL_GXX64_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_GXX64_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_GXX64_COMPILE_CXX_DEPEND =
+TOOL_GXX64_COMPILE_CXX_DEPORD =
+ifdef KBUILD_USE_KOBJCACHE
+TOOL_GXX64_COMPILE_CXX_USES_KOBJCACHE = 1
+TOOL_GXX64_COMPILE_CXX_OUTPUT = $(outbase).ii
+define TOOL_GXX64_COMPILE_CXX_CMDS
+	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\
+		--kObjCache-cpp $(outbase).ii\
+		$(TOOL_GXX64_CXX) -E -o -\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		$(abspath $(source))\
+		--kObjCache-cc $(obj)\
+		$(TOOL_GXX64_CXX) -c\
+		$(flags) -fpreprocessed -x c++\
+		-o $(obj)\
+		-
+endef
+else # !KBUILD_USE_KOBJCACHE
+TOOL_GXX64_COMPILE_CXX_OUTPUT =
+define TOOL_GXX64_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_GXX64_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_GXX64_COMPILE_AS_OUTPUT =
+TOOL_GXX64_COMPILE_AS_DEPEND =
+TOOL_GXX64_COMPILE_AS_DEPORD =
+define TOOL_GXX64_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_GXX64_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX64_LINK_LIBRARY_OUTPUT = $(out).ar-script
+TOOL_GXX64_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_GXX64_LINK_LIBRARY_DEPORD =
+define TOOL_GXX64_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)'
+	$(QUIET)$(APPEND) -n $(out).ar-script \
+		$(foreach o,$(objs), 'ADDMOD $(o)') \
+		$(foreach o,$(othersrc), 'ADDLIB $(o)')
+	$(QUIET)$(APPEND) $(out).ar-script 'SAVE'
+	$(QUIET)$(APPEND) $(out).ar-script 'END'
+	$(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GXX64_AR) -M
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX64_LINK_PROGRAM_OUTPUT =
+TOOL_GXX64_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX64_LINK_PROGRAM_DEPORD =
+define TOOL_GXX64_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_GXX64_LD) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX64_LD_MAP,$(outbase).map)
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX64_LINK_DLL_OUTPUT =
+TOOL_GXX64_LINK_DLL_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX64_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX64_LINK_DLL_DEPORD =
+define TOOL_GXX64_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_GXX64_LD) $(TOOL_GXX64_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GXX64_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX64_LD_MAP,$(outbase).map)
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_GXX64_LINK_SYSMOD_OUTPUT =
+TOOL_GXX64_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map
+TOOL_GXX64_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_GXX64_LINK_SYSMOD_DEPORD =
+define TOOL_GXX64_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_GXX64_LD_SYSMOD) $(TOOL_GXX64_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\
+		$(call TOOL_GXX64_LD_SYSMOD_MAP,$(outbase).map)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/MINGW32.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/MINGW32.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/MINGW32.kmk	(revision 1780)
@@ -0,0 +1,271 @@
+# $Id$
+## @file
+# kBuild Tool Config - MinGW32 GCC v3.3+.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_MINGW32 := MinGW32 GCC v3.3+.
+
+# Tool Specific Properties
+ifndef PATH_TOOL_MINGW32
+ PATH_TOOL_MINGW32 := $(wildcard $(PATH_DEVTOOLS_BLD)/mingw32/v*.*)
+ ifeq ($(PATH_TOOL_MINGW32),)
+  PATH_TOOL_MINGW32 := $(wildcard $(PATH_DEVTOOLS)/win.x86/mingw32/v*.*)
+ endif
+ ifeq ($(PATH_TOOL_MINGW32),)
+  PATH_TOOL_MINGW32 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/mingw32/v*.*)
+ endif
+ ifneq ($(PATH_TOOL_MINGW32),)
+  PATH_TOOL_MINGW32 := $(lastword $(sort $(PATH_TOOL_MINGW32)))
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_MINGW32 := $(PATH_TOOL_MINGW32)
+endif
+
+# figure out if it's native or needs a win32 launcher
+TOOL_MINGW32_HOSTSUFF_EXE ?= $(HOSTSUFF_EXE)
+ifndef TOOL_MINGW32_PREFIX
+ ifneq ($(PATH_TOOL_MINGW32),)
+  TOOL_MINGW32_PREFIX := $(PATH_TOOL_MINGW32)/bin/
+ else
+  TOOL_MINGW32_PREFIX :=
+ endif
+ ifneq ($(KBUILD_HOST),win)
+  # we're cross compiling either using an emulator (wine/odin) or a cross compiler.
+  ifneq ($(PATH_TOOL_MINGW32),$(subst /win.x86,,$(subst /x86.win,,$(PATH_TOOL_MINGW32))))
+   TOOL_MINGW32_PREFIX := $(EXEC_X86_WIN32) $(TOOL_MINGW32_PREFIX)
+   TOOL_MINGW32_HOSTSUFF_EXE := .exe
+  else
+   TOOL_MINGW32_PREFIX := $(TOOL_MINGW32_PREFIX)i386-mingw32msvc-
+   TOOL_MINGW32_HOSTSUFF_EXE :=
+   TOOL_MINGW32_XCOMPILE := 1
+  endif
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ TOOL_MINGW32_PREFIX :=
+endif
+
+TOOL_MINGW32_CC  ?= $(TOOL_MINGW32_PREFIX)gcc$(TOOL_MINGW32_HOSTSUFF_EXE)
+TOOL_MINGW32_CXX ?= $(TOOL_MINGW32_PREFIX)g++$(TOOL_MINGW32_HOSTSUFF_EXE)
+TOOL_MINGW32_AS  ?= $(TOOL_MINGW32_PREFIX)gcc$(TOOL_MINGW32_HOSTSUFF_EXE)
+TOOL_MINGW32_AR  ?= $(TOOL_MINGW32_PREFIX)ar$(TOOL_MINGW32_HOSTSUFF_EXE)
+ifndef TOOL_MINGW32_XCOMPILE# The gentoo package doesn't have g++.
+TOOL_MINGW32_LD  ?= $(TOOL_MINGW32_PREFIX)g++$(TOOL_MINGW32_HOSTSUFF_EXE)
+else
+TOOL_MINGW32_LD  ?= $(TOOL_MINGW32_PREFIX)gcc$(TOOL_MINGW32_HOSTSUFF_EXE)
+endif
+TOOL_MINGW32_DLLWRAP ?= $(TOOL_MINGW32_PREFIX)dllwrap$(TOOL_MINGW32_HOSTSUFF_EXE)
+TOOL_MINGW32_DLLTOOL ?= $(TOOL_MINGW32_PREFIX)dlltool$(TOOL_MINGW32_HOSTSUFF_EXE)
+
+# General Properties used by kBuild
+TOOL_MINGW32_COBJSUFF           ?= .o
+TOOL_MINGW32_CFLAGS             ?= -g
+TOOL_MINGW32_CFLAGS.debug       ?= -O0
+TOOL_MINGW32_CFLAGS.release     ?= -O2
+TOOL_MINGW32_CFLAGS.profile     ?= -O2 #-pg
+TOOL_MINGW32_CINCS              ?=
+TOOL_MINGW32_CDEFS              ?=
+
+TOOL_MINGW32_CXXOBJSUFF         ?= .o
+TOOL_MINGW32_CXXOBJSUFF         ?= .o
+TOOL_MINGW32_CXXFLAGS           ?= -g
+TOOL_MINGW32_CXXFLAGS.debug     ?= -O0
+TOOL_MINGW32_CXXFLAGS.release   ?= -O2
+TOOL_MINGW32_CXXFLAGS.profile   ?= -O2 #-pg
+TOOL_MINGW32_CXXINCS            ?=
+TOOL_MINGW32_CXXDEFS            ?=
+
+TOOL_MINGW32_ASFLAGS            ?= -g -x assembler-with-cpp
+TOOL_MINGW32_ASOBJSUFF          ?= .o
+
+TOOL_MINGW32_ARFLAGS            ?= cr
+TOOL_MINGW32_ARLIBSUFF          ?= .a
+
+TOOL_MINGW32_LDFLAGS            ?=
+TOOL_MINGW32_LDFLAGS.debug      ?= -g
+TOOL_MINGW32_LDFLAGS.release    ?= -s
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_MINGW32_COMPILE_C_OUTPUT =
+TOOL_MINGW32_COMPILE_C_DEPEND =
+TOOL_MINGW32_COMPILE_C_DEPORD =
+define TOOL_MINGW32_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_MINGW32_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_MINGW32_COMPILE_CXX_OUTPUT =
+TOOL_MINGW32_COMPILE_CXX_DEPEND =
+TOOL_MINGW32_COMPILE_CXX_DEPORD =
+define TOOL_MINGW32_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_MINGW32_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_MINGW32_COMPILE_AS_OUTPUT =
+TOOL_MINGW32_COMPILE_AS_DEPEND =
+TOOL_MINGW32_COMPILE_AS_DEPORD =
+define TOOL_MINGW32_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_MINGW32_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_MINGW32_LINK_LIBRARY_OUTPUT = $(out).ar-script
+TOOL_MINGW32_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_MINGW32_LINK_LIBRARY_DEPORD =
+define TOOL_MINGW32_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)'
+	$(QUIET)$(APPEND) -n $(out).ar-script \
+		$(foreach o,$(objs), 'ADDMOD $(o)') \
+		$(foreach o,$(othersrc), 'ADDLIB $(o)')
+	$(QUIET)$(APPEND) $(out).ar-script 'SAVE'
+	$(QUIET)$(APPEND) $(out).ar-script 'END'
+	$(QUIET)$(TOOL_MINGW32_AR) -M < $(out).ar-script
+endef
+
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_MINGW32_LINK_PROGRAM_OUTPUT =
+TOOL_MINGW32_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_MINGW32_LINK_PROGRAM_DEPORD =
+define TOOL_MINGW32_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_MINGW32_LD) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib)))
+endef
+
+
+## Link DLL.
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      DLL name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_MINGW32_LINK_DLL_OUTPUT =
+TOOL_MINGW32_LINK_DLL_OUTPUT_MAYBE = $(outbase).a $(outbase).exp $(PATH_LIB)/$(notdir $(outbase)).exp $(PATH_LIB)/$(notdir $(outbase)).a
+## @todo Find a better solution for installing the extra files (.a, .exp, .pdb, etc).
+TOOL_MINGW32_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\
+	$(filter %.def %.res,$(othersrc))
+TOOL_MINGW32_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_LIB))
+define TOOL_MINGW32_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_MINGW32_DLLWRAP) $(flags)\
+		--dllname=$(out)\
+		--output-exp=$(outbase).exp\
+		--output-lib=$(outbase).a\
+		$(foreach def,$(filter %.def,$(othersrc)), --def $(def))\
+		$(filter %.res,$(othersrc))\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib)))
+	$(QUIET)$(CP) $(outbase).exp $(outbase).a $(PATH_LIB)/
+endef
+## @todo separate install stuff!
Index: /tags/kBuild-0.1.4/kBuild/tools/NASM.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/NASM.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/NASM.kmk	(revision 1780)
@@ -0,0 +1,86 @@
+# $Id$
+## @file
+# kBuild Tool Config - Netwide Assembler v0.98+.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_NASM := Netwide Assembler v0.98+
+
+# Tool Specific Properties
+ifndef PATH_TOOL_NASM
+ PATH_TOOL_NASM := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/nasm/v*.*))
+ ifneq ($(PATH_TOOL_NASM),)
+  PATH_TOOL_NASM := $(call lastword,$(PATH_TOOL_NASM))
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_NASM := $(PATH_TOOL_NASM)
+endif
+
+ifneq ($(PATH_TOOL_NASM),)
+ TOOL_NASM_AS ?= $(PATH_TOOL_NASM)/nasm$(HOSTSUFF_EXE)
+else
+ TOOL_NASM_AS ?= nasm$(HOSTSUFF_EXE)
+endif
+
+# General Properties used by kBuild
+TOOL_NASM_ASFLAGS ?=
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_NASM_COMPILE_AS_OUTPUT = $(outbase).lst
+TOOL_NASM_COMPILE_AS_DEPEND =
+TOOL_NASM_COMPILE_AS_DEPORD =
+define TOOL_NASM_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_NASM_AS)\
+		$(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
+		-l $(outbase).lst\
+		-o $(obj)\
+		$(abspath $(source))
+	$(QUIET)$(REDIRECT) -wo $(dep) -- $(TOOL_NASM_AS)\
+		$(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
+		-l $(outbase).lst\
+		-o $(obj)\
+		$(abspath $(source)) \
+		-M
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/TAR.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/TAR.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/TAR.kmk	(revision 1780)
@@ -0,0 +1,75 @@
+# $Id$
+## @file
+# kBuild Tool Config - tar unpacker.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_TAR := tar unpacker.
+
+# Tool Specific Properties
+ifndef TOOL_TAR_TAR
+ TOOL_TAR_TAR := $(wildcard $(PATH_DEVTOOLS_BLD)/tar/v*/tar$(HOSTSUFF_EXE))
+ ifeq ($(TOOL_TAR_TAR),)
+  TOOL_TAR_TAR := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/tar$(HOSTSUFF_EXE))
+ endif
+ ifeq ($(TOOL_TAR_TAR),)
+  TOOL_TAR_TAR := $(lastword $(sort $(TOOL_TAR_TAR)))
+ else
+  TOOL_TAR_TAR := tar$(HOSTSUFF_EXE)
+ endif
+else
+ TOOL_TAR_TAR := $(TOOL_TAR_TAR)
+endif
+TOOL_TAR_UNPACK ?= $(TOOL_TAR_TAR)
+
+# General Properties used by kBuild
+TOOL_TAR_UNPACKFLAGS ?=
+
+## UNPACK one file.
+# @param    $(target)   Normalized main target name.
+# @param    $(archive)  The file to unpack.
+# @param    $(flags)    Flags.
+# @param	$(inst)		Where to unpack it.
+# @param	$(out)		Where to write the file list.
+TOOL_TAR_UNPACK_OUTPUT =
+TOOL_TAR_UNPACK_DEPEND =
+TOOL_TAR_UNPACK_DEPORD =
+ifeq ($(KBUILD_HOST),win) # hacking with buggy unxutils on windows. it doesn't like driver letters.
+define TOOL_TAR_UNPACK_CMDS
+	$(QUIET)$(TOOL_TAR_UNPACK) -x $(flags) -C $(subst G:,,$(inst)) -f $(archive)
+	$(QUIET)$(TOOL_TAR_UNPACK) -t $(flags) -f $(archive) > $(out)
+endef
+else
+define TOOL_TAR_UNPACK_CMDS
+	$(QUIET)$(TOOL_TAR_UNPACK) -x $(flags) -C $(inst) -f $(archive)
+	$(QUIET)$(TOOL_TAR_UNPACK) -t $(flags) -f $(archive) > $(out)
+endef
+endif
+
Index: /tags/kBuild-0.1.4/kBuild/tools/TARGZ.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/TARGZ.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/TARGZ.kmk	(revision 1780)
@@ -0,0 +1,72 @@
+# $Id$
+## @file
+# kBuild Tool Config - tar.gz unpacker.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_TARGZ := tar.gz unpacker.
+
+# Tool Specific Properties
+ifndef TOOL_TARGZ_TAR
+ TOOL_TARGZ_TAR := $(wildcard $(PATH_DEVTOOLS_BLD)/tar/v*/tar$(HOSTSUFF_EXE))
+ ifeq ($(TOOL_TARGZ_TAR),)
+  TOOL_TARGZ_TAR := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/tar$(HOSTSUFF_EXE))
+ endif
+ ifeq ($(TOOL_TARGZ_TAR),)
+  TOOL_TARGZ_TAR := $(TOOL_TAR_TAR)
+ endif
+ ifeq ($(TOOL_TARGZ_TAR),)
+  TOOL_TARGZ_TAR := $(lastword $(sort $(TOOL_TARGZ_TAR)))
+ else
+  TOOL_TARGZ_TAR := tar$(HOSTSUFF_EXE)
+ endif
+else
+ TOOL_TARGZ_TAR := $(TOOL_TARGZ_TAR)
+endif
+TOOL_TARGZ_UNPACK ?= $(TOOL_TARGZ_TAR)
+
+# General Properties used by kBuild
+TOOL_TARGZ_UNPACKFLAGS ?= -z
+
+## UNPACK one file.
+# @param    $(target)   Normalized main target name.
+# @param    $(archive)  The file to unpack.
+# @param    $(flags)    Flags.
+# @param	$(inst)		Where to unpack it.
+# @param	$(out)		Where to write the file list.
+TOOL_TARGZ_UNPACK_OUTPUT =
+TOOL_TARGZ_UNPACK_DEPEND =
+TOOL_TARGZ_UNPACK_DEPORD =
+define TOOL_TARGZ_UNPACK_CMDS
+	$(QUIET)$(TOOL_TARGZ_UNPACK) -x $(flags) -C $(inst) -f $(archive)
+	$(QUIET)$(TOOL_TARGZ_UNPACK) -t $(flags) -f $(archive) > $(out)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/VAC308.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/VAC308.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/VAC308.kmk	(revision 1780)
@@ -0,0 +1,286 @@
+# $Id$
+## @file
+# kBuild Tool Config - VisualAge for C++ v3.08.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_VAC308 := VisualAge for C++ v3.08
+
+TOOL_VAC308_ENV_SETUP ?=
+
+# Determin VAC308 location.
+ifndef PATH_TOOL_VAC308
+ PATH_TOOL_VAC308 := $(wildcard $(PATH_DEVTOOLS_BLD)/vac/v308*)
+ ifeq ($(PATH_TOOL_VAC308),)
+ PATH_TOOL_VAC308 := $(wildcard $(PATH_DEVTOOLS_TRG)/vac/v308*)
+ endif
+ ifeq ($(PATH_TOOL_VAC308),)
+  PATH_TOOL_VAC308 := $(lastword $(sort $(PATH_TOOL_VAC308)))
+ endif
+ # if not found, we'll enter 'pathless' mode.
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_VAC308 := $(PATH_TOOL_VAC308)
+endif
+ifneq ($(PATH_TOOL_VAC308),)
+ PATH_TOOL_VAC308_BIN ?= $(PATH_TOOL_VAC308)/bin
+ PATH_TOOL_VAC308_LIB ?= $(PATH_TOOL_VAC308)/lib
+ PATH_TOOL_VAC308_INC ?= $(PATH_TOOL_VAC308)/include
+
+ TOOL_VAC308_CC  ?= $(PATH_TOOL_VAC308_BIN)/icc$(HOSTSUFF_EXE)
+ TOOL_VAC308_CXX ?= $(PATH_TOOL_VAC308_BIN)/icc$(HOSTSUFF_EXE)
+ TOOL_VAC308_AR  ?= $(PATH_TOOL_VAC308_BIN)/ilib$(HOSTSUFF_EXE)
+ TOOL_VAC308_LD  ?= $(PATH_TOOL_VAC308_BIN)/icc$(HOSTSUFF_EXE)
+ TOOL_VAC308_RC  ?= $(PATH_TOOL_VAC308_BIN)/rc$(HOSTSUFF_EXE)
+
+else
+ # Pathless, relies on the environment.
+ TOOL_VAC308_CC  ?= icc$(HOSTSUFF_EXE)
+ TOOL_VAC308_CXX ?= icc$(HOSTSUFF_EXE)
+ TOOL_VAC308_AR  ?= ilib$(HOSTSUFF_EXE)
+ TOOL_VAC308_LD  ?= icc$(HOSTSUFF_EXE)
+ TOOL_VAC308_RC  ?= rc$(HOSTSUFF_EXE)
+
+endif
+
+# More tool specific properties.
+# Note: implib isn't really a part of VAC308.
+TOOL_VAC308_IMP              ?= implib$(HOSTSUFF_EXE)
+TOOL_VAC308_IMPFLAGS         ?= /nologo /noignorecase
+
+# General Properties used by kBuild
+TOOL_VAC308_COBJSUFF         ?= .obj
+TOOL_VAC308_CFLAGS           ?= -Q+
+TOOL_VAC308_CFLAGS.debug     ?= -Ti+
+TOOL_VAC308_CFLAGS.release   ?= -O
+TOOL_VAC308_CINCS            ?=
+TOOL_VAC308_CDEFS            ?=
+
+TOOL_VAC308_CXXOBJSUFF       ?= .obj
+TOOL_VAC308_CXXFLAGS         ?= -Q+
+TOOL_VAC308_CXXFLAGS.debug   ?= -Ti
+TOOL_VAC308_CXXFLAGS.release ?= -O
+TOOL_VAC308_CXXINCS          ?=
+TOOL_VAC308_CXXDEFS          ?=
+
+TOOL_VAC308_RCOBJSUFF        ?= .res
+TOOL_VAC308_RCFLAGS          ?= -n
+TOOL_VAC308_RCINCS           ?=
+TOOL_VAC308_RCDEFS           ?=
+
+TOOL_VAC308_ARFLAGS          ?= /nologo /noignorecase
+TOOL_VAC308_ARLIBSUFF        ?= .lib
+
+TOOL_VAC308_LDFLAGS          ?= -Q+
+TOOL_VAC308_LDFLAGS.debug    ?= -Ti+
+
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VAC308_COMPILE_C_DEPEND =
+TOOL_VAC308_COMPILE_C_DEPORD =
+TOOL_VAC308_COMPILE_C_OUTPUT =
+define TOOL_VAC308_COMPILE_C_CMDS
+	$(QUIET) $(TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fo$(obj)\
+		$(abspath $(source))
+	$(QUIET) $(TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CC) -P+ -Pd+ \
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		$(abspath $(source)) \
+		| $(DEP_PRE) -f -s -o $(dep) -t $(obj) -
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VAC308_COMPILE_CXX_DEPEND =
+TOOL_VAC308_COMPILE_CXX_DEPORD =
+TOOL_VAC308_COMPILE_CXX_OUTPUT =
+define TOOL_VAC308_COMPILE_CXX_CMDS
+	$(QUIET) $(TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fo$(obj)\
+		$(abspath $(source))
+	$(QUIET) $(TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CXX) -P+ -Pd+ \
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		$(abspath $(source)) \
+		| $(DEP_PRE) -f -s -o $(dep) -t $(obj) -
+endef
+
+
+## Compile resource source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VAC308_COMPILE_RC_OUTPUT =
+TOOL_VAC308_COMPILE_RC_DEPEND =
+TOOL_VAC308_COMPILE_RC_DEPORD =
+define TOOL_VAC308_COMPILE_RC_CMDS
+	$(QUIET) $(TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_RC) -r\
+		$(flags) $(addprefix -i, $(subst /,\\,$(incs))) $(addprefix -D, $(defs))\
+		$(subst /,\\,$(abspath $(source))) \
+		$(obj)
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VAC308_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_VAC308_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_VAC308_LINK_LIBRARY_DEPORD =
+define TOOL_VAC308_LINK_LIBRARY_CMDS
+	$(if $(strip $(othersrc)),\
+		$(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+		$(TOOL_VAC308_IMP) $(TOOL_VAC308_IMPFLAGS) $(subst /,\\,$(out)) $(subst /,\\,$(othersrc)) )
+	$(if $(strip $(objs)),$(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+		$(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+		$(TOOL_VAC308_AR) $(flags) $(subst /,\\,$(out)) $(foreach obj,$(subst /,\\,$(objs)),+"$(obj)") ";" )
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VAC308_LINK_PROGRAM_OUTPUT = $(outbase).map
+TOOL_VAC308_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VAC308_LINK_PROGRAM_DEPORD =
+define TOOL_VAC308_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+	$(if $(strip $(libpath)),LIB="$(subst ; ,;,$(foreach lp,$(libpath),$(lp);))$(LIB)") \
+		$(TOOL_VAC308_LD) $(flags) -Fe$(out) -Fm$(outbase).map $(filter-out %.res,$(objs)) $(libs) $(othersrc)
+	$(if $(filter %.res,$(objs)), $(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+		$(TOOL_VAC308_RC) $(filter %.res,$(objs)) $(out))
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VAC308_LINK_DLL_OUTPUT = $(outbase).map
+TOOL_VAC308_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VAC308_LINK_DLL_DEPORD =
+define TOOL_VAC308_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+	$(if $(strip $(libpath)),LIB="$(subst ; ,;,$(foreach lp,$(libpath),$(lp);))$(LIB)") \
+		$(TOOL_VAC308_LD) /B"/DLL" $(flags) -Fe$(out) -Fm$(outbase).map $(filter-out %.res,$(objs)) $(libs) $(othersrc)
+	$(if $(filter %.res,$(objs)), $(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+		$(TOOL_VAC308_RC) $(filter %.res,$(objs)) $(out))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VAC308_LINK_SYSMOD_OUTPUT = $(outbase).map
+TOOL_VAC308_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VAC308_LINK_SYSMOD_DEPORD =
+define TOOL_VAC308_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+	$(if $(strip $(libpath)),LIB="$(subst ; ,;,$(foreach lp,$(libpath),$(lp);))$(LIB)") \
+		$(TOOL_VAC308_LD) $(flags) -Fe$(out)  -Fm$(outbase).map $(filter-out %.res,$(objs)) $(libs) $(othersrc)
+	$(if $(filter %.res,$(objs)), $(QUIET)$(TOOL_VAC308_ENV_SETUP) \
+		$(TOOL_VAC308_RC) $(filter %.res,$(objs)) $(out))
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/VCC70.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/VCC70.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/VCC70.kmk	(revision 1780)
@@ -0,0 +1,346 @@
+# $Id$
+## @file
+# kBuild Tool Config - Visual C++ 7.0 (aka Visual Studio .NET), targeting x86.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_VCC70 := Visual C++ 7.0 (aka Visual Studio .NET), targeting x86.
+
+# Tool Specific Properties
+ifndef PATH_TOOL_VCC70
+ PATH_TOOL_VCC70 := $(firstword $(wildcard \
+	$(PATH_DEVTOOLS)/win.x86/vcc/v7 \
+	$(PATH_DEVTOOLS)/x86.win32/vcc/v7 \
+	$(PATH_DEVTOOLS)/x86.win32/vcc70) )
+ # if not found, we'll enter 'pathless' mode.
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_VCC70 := $(PATH_TOOL_VCC70)
+endif
+ifneq ($(PATH_TOOL_VCC70),)
+ PATH_TOOL_VCC70_BIN ?= $(PATH_TOOL_VCC70)/bin
+ PATH_TOOL_VCC70_LIB ?= $(PATH_TOOL_VCC70)/lib
+ PATH_TOOL_VCC70_INC ?= $(PATH_TOOL_VCC70)/include
+ PATH_TOOL_VCC70_ATLMFC ?= $(PATH_TOOL_VCC70)/atlmfc
+ PATH_TOOL_VCC70_ATLMFC_INC ?= $(PATH_TOOL_VCC70_ATLMFC)/include
+ PATH_TOOL_VCC70_ATLMFC_LIB ?= $(PATH_TOOL_VCC70_ATLMFC)/lib
+ TOOL_VCC70_CC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/cl.exe
+ TOOL_VCC70_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/cl.exe
+ TOOL_VCC70_AS  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/ml.exe
+ TOOL_VCC70_RC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/rc.exe
+ TOOL_VCC70_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/lib.exe
+ TOOL_VCC70_LD  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/link.exe
+else
+ # Pathless, relies on the environment.
+ TOOL_VCC70_CC  ?= $(EXEC_X86_WIN32) cl.exe
+ TOOL_VCC70_CXX ?= $(EXEC_X86_WIN32) cl.exe
+ TOOL_VCC70_AS  ?= $(EXEC_X86_WIN32) ml.exe
+ TOOL_VCC70_RC  ?= $(EXEC_X86_WIN32) rc.exe
+ TOOL_VCC70_AR  ?= $(EXEC_X86_WIN32) lib.exe
+ TOOL_VCC70_LD  ?= $(EXEC_X86_WIN32) link.exe
+endif
+## Disabled fast DEP_IDB based dependencies.
+#VCC70_OLD_DEPS = 1
+
+## Constructs the correct .pdb name (the name is lowercased).
+# @param    $(1)        Base name, no extention.
+# @param    $(2)        The extension.
+TOOL_VCC70_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2)
+
+# General Properties used by kBuild
+TOOL_VCC70_COBJSUFF         ?= .obj
+TOOL_VCC70_CFLAGS           ?= -TC -c -nologo
+TOOL_VCC70_CFLAGS.debug     ?= -Od -Zi
+TOOL_VCC70_CFLAGS.release   ?= -O2
+TOOL_VCC70_CFLAGS.profile   ?= -O2
+TOOL_VCC70_CINCS            ?= $(PATH_TOOL_VCC70_INC)
+TOOL_VCC70_CDEFS            ?=
+
+TOOL_VCC70_CXXOBJSUFF       ?= .obj
+TOOL_VCC70_CXXFLAGS         ?= -TP -c -nologo
+TOOL_VCC70_CXXFLAGS.debug   ?= -Od -Zi
+TOOL_VCC70_CXXFLAGS.release ?= -O2
+TOOL_VCC70_CXXFLAGS.profile ?= -O2
+TOOL_VCC70_CXXINCS          ?= $(PATH_TOOL_VCC70_INC) $(PATH_TOOL_VCC70_ATLMFC_INC)
+TOOL_VCC70_CXXDEFS          ?=
+
+TOOL_VCC70_ASOBJSUFF        ?= .obj
+
+TOOL_VCC70_RCOBJSUFF        ?= .res
+TOOL_VCC70_RCINCS           ?= $(PATH_TOOL_VCC70_INC) $(PATH_TOOL_VCC70_ATLMFC_INC)
+
+TOOL_VCC70_ARFLAGS          ?= -nologo
+TOOL_VCC70_ARLIBSUFF        ?= .lib
+
+TOOL_VCC70_LDFLAGS          ?= -nologo
+TOOL_VCC70_LDFLAGS.debug    ?= -debug
+TOOL_VCC70_LDFLAGS.release  ?=
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC70_COMPILE_C_DONT_PURGE_OUTPUT =
+TOOL_VCC70_COMPILE_C_DEPEND =
+TOOL_VCC70_COMPILE_C_DEPORD =
+#ifdef KBUILD_USE_KOBJCACHE
+#TOOL_VCC70_COMPILE_C_OUTPUT = $(call TOOL_VCC70_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC70_PDB, $(outbase)-obj,idb) $(outbase).i
+#TOOL_VCC70_COMPILE_C_USESES_KOBJCACHE = 1
+#define TOOL_VCC70_COMPILE_C_CMDS
+#	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -r --kObjCache-cpp $(outbase).i \
+#		$(TOOL_VCC70_CC) -E \
+#		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+#		$(subst /,\\,$(abspath $(source))) \
+#		--kObjCache-cc $(obj) \
+#		$(TOOL_VCC70_CC) -c -TC\
+#		$(flags) \
+#		-Fd$(outbase)-obj.pdb \
+#		-FD\
+#		-Fo$(obj)\
+#		$(subst /,\\,$(outbase).i)
+#	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC70_PDB,$(outbase)-obj,idb)
+#endef
+#else # !KBUILD_USE_KOBJCACHE
+TOOL_VCC70_COMPILE_C_OUTPUT = $(call TOOL_VCC70_PDB, $(outbase)-obj,idb)
+TOOL_VCC70_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC70_PDB, $(outbase)-obj,pdb)
+define TOOL_VCC70_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_VCC70_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-FD\
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC70_PDB,$(outbase)-obj,idb)
+endef
+#endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC70_COMPILE_CXX_DONT_PURGE_OUTPUT =
+TOOL_VCC70_COMPILE_CXX_DEPEND =
+TOOL_VCC70_COMPILE_CXX_DEPORD =
+#ifdef KBUILD_USE_KOBJCACHE
+#TOOL_VCC70_COMPILE_CXX_OUTPUT = $(call TOOL_VCC70_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC70_PDB, $(outbase)-obj,idb) $(outbase).ii
+#TOOL_VCC70_COMPILE_CXX_USES_KOBJCACHE = 1
+#define TOOL_VCC70_COMPILE_CXX_CMDS
+#	$(QUIET)$(KOBJCACHE) -f $(outbase).koc -r --kObjCache-cpp $(outbase).ii \
+#		$(TOOL_VCC70_CC) -E \
+#		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+#		$(subst /,\\,$(abspath $(source))) \
+#		--kObjCache-cc $(obj) \
+#		$(TOOL_VCC70_CC) -c -TP\
+#		$(flags) \
+#		-Fd$(outbase)-obj.pdb \
+#		-FD\
+#		-Fo$(obj)\
+#		$(subst /,\\,$(outbase).ii)
+#	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC70_PDB,$(outbase)-obj,idb)
+#endef
+#else # !KBUILD_USE_KOBJCACHE
+TOOL_VCC70_COMPILE_CXX_OUTPUT = $(call TOOL_VCC70_PDB, $(outbase)-obj,idb)
+TOOL_VCC70_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC70_PDB, $(outbase)-obj,pdb)
+define TOOL_VCC70_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC70_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-FD\
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC70_PDB,$(outbase)-obj,idb)
+endef
+#endif # !KBUILD_USE_KOBJCACHE
+
+
+## Compile resource source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC70_COMPILE_RC_OUTPUT =
+TOOL_VCC70_COMPILE_RC_DEPEND =
+TOOL_VCC70_COMPILE_RC_DEPORD =
+define TOOL_VCC70_COMPILE_RC_CMDS
+	$(QUIET)$(TOOL_VCC70_RC) \
+		$(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\
+		/fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_VCC70_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_VCC70_LINK_LIBRARY_DEPORD =
+TOOL_VCC70_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_VCC70_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb
+define TOOL_VCC70_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp \
+		$(foreach arg,\
+			$(subst /,\\,$(objs) \
+			$(filter-out %.def,$(othersrc))) \
+			$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC70_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+endef
+
+
+## Link program
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          Program name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+#
+TOOL_VCC70_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).pdb $(outbase).ilk
+TOOL_VCC70_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC70_LINK_PROGRAM_DEPORD =
+define TOOL_VCC70_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_VCC70_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO /MAPINFO:LINES \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+endef
+
+
+## Link DLL.
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      DLL name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC70_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp
+TOOL_VCC70_LINK_DLL_OUTPUT_MAYBE = $(outbase).pdb $(outbase).ilk $(PATH_LIB)/$(notdir $(outbase)).lib $(PATH_LIB)/$(notdir $(outbase)).exp
+TOOL_VCC70_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC70_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_LIB))
+define TOOL_VCC70_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_VCC70_LD) $(flags) \
+		/OUT:$(out) \
+		/IMPLIB:$(outbase).lib \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO /MAPINFO:LINES \
+		/MAP:$(outbase).map \
+		/DLL \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_LIB)/
+$(eval _DIRS += $(PATH_LIB))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          System module name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC70_LINK_SYSMOD_OUTPUT = $(outbase).map
+TOOL_VCC70_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).pdb $(outbase).ilk
+TOOL_VCC70_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC70_LINK_SYSMOD_DEPORD =
+define TOOL_VCC70_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_VCC70_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO /MAPINFO:LINES \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/VCC80.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/VCC80.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/VCC80.kmk	(revision 1780)
@@ -0,0 +1,343 @@
+# $Id$
+## @file
+# kBuild Tool Config - Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting $(KBUILD_TARGET).
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_VCC80 := Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting $(KBUILD_TARGET).
+
+# Tool Specific Properties
+ifndef PATH_TOOL_VCC80
+ PATH_TOOL_VCC80 := $(wildcard $(PATH_DEVTOOLS_TRG)/vcc/v8*)
+ ifeq ($(PATH_TOOL_VCC80),)
+  PATH_TOOL_VCC80 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v8*)
+ endif
+ ifeq ($(PATH_TOOL_VCC80),)
+  PATH_TOOL_VCC80 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/vcc/v8*)
+ endif
+ ifeq ($(PATH_TOOL_VCC80),)
+  PATH_TOOL_VCC80 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/vcc/v8*)
+ endif
+ ifeq ($(PATH_TOOL_VCC80),)
+  PATH_TOOL_VCC80 := $(lastword $(sort $(PATH_TOOL_VCC80)))
+ endif
+ # if not found, we'll enter 'pathless' mode.
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_VCC80 := $(PATH_TOOL_VCC80)
+endif
+ifneq ($(PATH_TOOL_VCC80),)
+ ifeq ($(KBUILD_HOST).$(KBUILD_HOST_ARCH),win.amd64)
+ PATH_TOOL_VCC80_BIN.amd64 ?= $(PATH_TOOL_VCC80)/bin/amd64
+ else
+ PATH_TOOL_VCC80_BIN.amd64 ?= $(PATH_TOOL_VCC80)/bin/x86_amd64
+ endif
+ PATH_TOOL_VCC80_BIN.x86   ?= $(PATH_TOOL_VCC80)/bin
+ PATH_TOOL_VCC80_BIN       ?= $(PATH_TOOL_VCC80_BIN.$(KBUILD_TARGET))
+ PATH_TOOL_VCC80_LIB.amd64 ?= $(PATH_TOOL_VCC80)/lib/amd64
+ PATH_TOOL_VCC80_LIB.x86   ?= $(PATH_TOOL_VCC80)/lib
+ PATH_TOOL_VCC80_LIB       ?= $(PATH_TOOL_VCC80_LIB.$(KBUILD_TARGET))
+ PATH_TOOL_VCC80_INC       ?= $(PATH_TOOL_VCC80)/include
+ PATH_TOOL_VCC80_ATLMFC    ?= $(PATH_TOOL_VCC80X86)/atlmfc
+ PATH_TOOL_VCC80_ATLMFC_INC       ?= $(PATH_TOOL_VCC80_ATLMFC)/include
+ PATH_TOOL_VCC80_ATLMFC_LIB.amd64 ?= $(PATH_TOOL_VCC80_ATLMFC)/lib
+ PATH_TOOL_VCC80_ATLMFC_LIB.x86   ?= $(PATH_TOOL_VCC80_ATLMFC)/lib/amd64
+ PATH_TOOL_VCC80_ATLMFC_LIB       ?= $(PATH_TOOL_VCC80_ATLMFC_LIB.$(KBUILD_TARGET))
+ TOOL_VCC80_CC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/cl.exe
+ TOOL_VCC80_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/cl.exe
+ TOOL_VCC80_AS  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/ml64.exe
+ TOOL_VCC80_RC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN.x86)/rc.exe
+ TOOL_VCC80_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/lib.exe
+ TOOL_VCC80_LD  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/link.exe
+ TOOL_VCC80_MT  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN.x86)/mt.exe
+else
+ # Pathless, relies on the environment.
+ TOOL_VCC80_CC  ?= $(EXEC_X86_WIN32) cl.exe
+ TOOL_VCC80_CXX ?= $(EXEC_X86_WIN32) cl.exe
+ TOOL_VCC80_AS  ?= $(EXEC_X86_WIN32) ml64.exe
+ TOOL_VCC80_RC  ?= $(EXEC_X86_WIN32) rc.exe
+ TOOL_VCC80_AR  ?= $(EXEC_X86_WIN32) lib.exe
+ TOOL_VCC80_LD  ?= $(EXEC_X86_WIN32) link.exe
+ TOOL_VCC80_MT  ?= $(EXEC_X86_WIN32) mt.exe
+endif
+## Disabled fast DEP_IDB based dependencies.
+#VCC80_OLD_DEPS = 1
+
+## Constructs the correct .pdb name (the name is lowercased).
+# @param    $(1)        Base name, no extention.
+# @param    $(2)        The extension.
+TOOL_VCC80_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2)
+
+TOOL_VCC80_COBJSUFF         ?= .obj
+TOOL_VCC80_CFLAGS           ?= -TC -c -nologo
+TOOL_VCC80_CFLAGS.debug     ?= -Od -Zi
+TOOL_VCC80_CFLAGS.release   ?= -O2
+TOOL_VCC80_CFLAGS.profile   ?= -O2
+TOOL_VCC80_CINCS            ?= $(PATH_TOOL_VCC80_INC)
+TOOL_VCC80_CDEFS            ?=
+
+TOOL_VCC80_CXXOBJSUFF       ?= .obj
+TOOL_VCC80_CXXFLAGS         ?= -TP -c -nologo
+TOOL_VCC80_CXXFLAGS.debug   ?= -Od -Zi
+TOOL_VCC80_CXXFLAGS.release ?= -O2
+TOOL_VCC80_CXXFLAGS.profile ?= -O2
+TOOL_VCC80_CXXINCS          ?= $(PATH_TOOL_VCC80_INC) $(PATH_TOOL_VCC80_ATLMFC_INC)
+TOOL_VCC80_CXXDEFS          ?=
+
+TOOL_VCC80_ASOBJSUFF        ?= .obj
+
+TOOL_VCC80_RCOBJSUFF        ?= .res
+TOOL_VCC80_RCINCS           ?= $(PATH_TOOL_VCC80_INC) $(PATH_TOOL_VCC80_ATLMFC_INC)
+
+TOOL_VCC80_ARFLAGS.amd64    ?= -machine:amd64
+TOOL_VCC80_ARFLAGS.x86      ?= -machine:x86
+TOOL_VCC80_ARFLAGS          ?= -nologo
+TOOL_VCC80_ARLIBSUFF        ?= .lib
+
+TOOL_VCC80_LDFLAGS.amd64    ?= -machine:amd64
+TOOL_VCC80_LDFLAGS.x86      ?= -machine:x86
+TOOL_VCC80_LDFLAGS          ?= -nologo
+TOOL_VCC80_LDFLAGS.debug    ?= -debug
+TOOL_VCC80_LDFLAGS.release  ?=
+TOOL_VCC80_LIBPATH.amd64    ?= $(PATH_TOOL_VCC80_LIB.amd64) $(PATH_TOOL_VCC80_ATLMFC_LIB.amd64)
+TOOL_VCC80_LIBPATH.x86      ?= $(PATH_TOOL_VCC80_LIB.x86) $(PATH_TOOL_VCC80_ATLMFC_LIB.x86)
+
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80_COMPILE_C_DEPEND =
+TOOL_VCC80_COMPILE_C_DEPORD =
+TOOL_VCC80_COMPILE_C_OUTPUT = $(call TOOL_VCC80_PDB, $(outbase)-obj,idb)
+TOOL_VCC80_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC80_PDB, $(outbase)-obj,pdb)
+define TOOL_VCC80_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_VCC80_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-FD\
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC80_PDB,$(outbase)-obj,idb)
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80_COMPILE_CXX_DEPEND =
+TOOL_VCC80_COMPILE_CXX_DEPORD =
+TOOL_VCC80_COMPILE_CXX_OUTPUT = $(call TOOL_VCC80_PDB, $(outbase)-obj,idb)
+TOOL_VCC80_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC80_PDB, $(outbase)-obj,pdb)
+define TOOL_VCC80_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC80_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-FD\
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC80_PDB,$(outbase)-obj,idb)
+endef
+
+
+## Compile resource source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80_COMPILE_RC_OUTPUT =
+TOOL_VCC80_COMPILE_RC_DEPEND =
+TOOL_VCC80_COMPILE_RC_DEPORD =
+define TOOL_VCC80_COMPILE_RC_CMDS
+	$(QUIET)$(TOOL_VCC80_RC) \
+		$(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\
+		/fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_VCC80_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_VCC80_LINK_LIBRARY_DEPORD =
+TOOL_VCC80_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_VCC80_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb
+define TOOL_VCC80_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp \
+		$(foreach arg,\
+			$(subst /,\\,$(objs) \
+			$(filter-out %.def,$(othersrc))) \
+			$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC80_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+endef
+
+
+
+
+## Link program
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          Program name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+#
+TOOL_VCC80_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80_LINK_PROGRAM_DEPORD =
+TOOL_VCC80_LINK_PROGRAM_OUTPUT = $(outbase).map
+TOOL_VCC80_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).pdb $(outbase).ilk $(out).manifest
+define TOOL_VCC80_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_VCC80_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out))
+endef
+
+
+## Link DLL.
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      DLL name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC80_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_LIB))
+TOOL_VCC80_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp
+TOOL_VCC80_LINK_DLL_OUTPUT_MAYBE = $(outbase).pdb $(outbase).ilk $(out).manifest $(PATH_LIB)/$(notdir $(outbase)).lib $(PATH_LIB)/$(notdir $(outbase)).exp
+define TOOL_VCC80_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_VCC80_LD) $(flags) \
+		/OUT:$(out) \
+		/IMPLIB:$(outbase).lib \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		/DLL \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+	$(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_LIB)/
+$(eval _DIRS += $(PATH_LIB))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          System module name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC80_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80_LINK_SYSMOD_DEPORD =
+TOOL_VCC80_LINK_SYSMOD_OUTPUT = $(outbase).map
+TOOL_VCC80_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).pdb $(outbase).ilk $(out).manifest
+define TOOL_VCC80_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_VCC80_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/VCC80AMD64.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/VCC80AMD64.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/VCC80AMD64.kmk	(revision 1780)
@@ -0,0 +1,320 @@
+# $Id$
+## @file
+# kBuild Tool Config - Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting AMD64.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_VCC80AMD64 := Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting AMD64.
+
+# Tool Specific Properties
+ifndef PATH_TOOL_VCC80AMD64
+ PATH_TOOL_VCC80AMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v8*)
+ ifeq ($(PATH_TOOL_VCC80AMD64),)
+  PATH_TOOL_VCC80AMD64 := $(PATH_TOOL_VCC80)
+ endif
+ ifeq ($(PATH_TOOL_VCC80AMD64),)
+  PATH_TOOL_VCC80AMD64 := $(PATH_TOOL_VCC80X86)
+ endif
+ ifeq ($(PATH_TOOL_VCC80AMD64),)
+  PATH_TOOL_VCC80AMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v8*)
+ endif
+ ifneq ($(PATH_TOOL_VCC80AMD64),)
+  PATH_TOOL_VCC80AMD64 := $(lastword $(sort $(PATH_TOOL_VCC80AMD64)))
+ else
+  $(warning kBuild: PATH_TOOL_VCC80AMD64 cannot be determined!)
+  PATH_TOOL_VCC80AMD64 := $(PATH_DEVTOOLS)/win.x86/vcc/v8
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_VCC80AMD64 := $(PATH_TOOL_VCC80AMD64)
+endif
+ifeq ($(KBUILD_HOST).$(KBUILD_HOST_ARCH),win.amd64)
+PATH_TOOL_VCC80AMD64_BIN ?= $(PATH_TOOL_VCC80AMD64)/bin/amd64
+else
+PATH_TOOL_VCC80AMD64_BIN ?= $(PATH_TOOL_VCC80AMD64)/bin/x86_amd64
+endif
+PATH_TOOL_VCC80AMD64_LIB ?= $(PATH_TOOL_VCC80AMD64)/lib/amd64
+PATH_TOOL_VCC80AMD64_INC ?= $(PATH_TOOL_VCC80AMD64)/include
+PATH_TOOL_VCC80AMD64_ATLMFC ?= $(PATH_TOOL_VCC80AMD64)/atlmfc
+PATH_TOOL_VCC80AMD64_ATLMFC_INC ?= $(PATH_TOOL_VCC80AMD64_ATLMFC)/include
+PATH_TOOL_VCC80AMD64_ATLMFC_LIB ?= $(PATH_TOOL_VCC80AMD64_ATLMFC)/lib/amd64
+TOOL_VCC80AMD64_CC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/cl.exe
+TOOL_VCC80AMD64_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/cl.exe
+TOOL_VCC80AMD64_AS  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/ml64.exe
+TOOL_VCC80AMD64_RC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/../rc.exe
+TOOL_VCC80AMD64_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/lib.exe
+TOOL_VCC80AMD64_LD  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/link.exe
+TOOL_VCC80AMD64_MT  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/../mt.exe
+## Disabled fast DEP_IDB based dependencies.
+#VCC80AMD64_OLD_DEPS = 1
+
+## Constructs the correct .pdb name (the name is lowercased).
+# @param    $(1)        Base name, no extention.
+# @param    $(2)        The extension.
+TOOL_VCC80AMD64_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2)
+
+TOOL_VCC80AMD64_COBJSUFF         ?= .obj
+TOOL_VCC80AMD64_CFLAGS           ?= -TC -c -nologo
+TOOL_VCC80AMD64_CFLAGS.debug     ?= -Od -Zi
+TOOL_VCC80AMD64_CFLAGS.release   ?= -O2
+TOOL_VCC80AMD64_CFLAGS.profile   ?= -O2
+TOOL_VCC80AMD64_CINCS            ?= $(PATH_TOOL_VCC80AMD64_INC)
+TOOL_VCC80AMD64_CDEFS            ?=
+
+TOOL_VCC80AMD64_CXXOBJSUFF       ?= .obj
+TOOL_VCC80AMD64_CXXFLAGS         ?= -TP -c -nologo
+TOOL_VCC80AMD64_CXXFLAGS.debug   ?= -Od -Zi
+TOOL_VCC80AMD64_CXXFLAGS.release ?= -O2
+TOOL_VCC80AMD64_CXXFLAGS.profile ?= -O2
+TOOL_VCC80AMD64_CXXINCS          ?= $(PATH_TOOL_VCC80AMD64_INC) $(PATH_TOOL_VCC80AMD64_ATLMFC_INC)
+TOOL_VCC80AMD64_CXXDEFS          ?=
+
+TOOL_VCC80AMD64_ASOBJSUFF        ?= .obj
+
+TOOL_VCC80AMD64_RCOBJSUFF        ?= .res
+TOOL_VCC80AMD64_RCINCS           ?= $(PATH_TOOL_VCC80AMD64_INC) $(PATH_TOOL_VCC80AMD64_ATLMFC_INC)
+
+TOOL_VCC80AMD64_ARFLAGS          ?= -nologo -machine:amd64
+TOOL_VCC80AMD64_ARLIBSUFF        ?= .lib
+
+TOOL_VCC80AMD64_LDFLAGS          ?= -nologo -machine:amd64
+TOOL_VCC80AMD64_LDFLAGS.debug    ?= -debug
+TOOL_VCC80AMD64_LDFLAGS.release  ?=
+
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80AMD64_COMPILE_C_DEPEND =
+TOOL_VCC80AMD64_COMPILE_C_DEPORD =
+TOOL_VCC80AMD64_COMPILE_C_OUTPUT = $(call TOOL_VCC80AMD64_PDB, $(outbase)-obj,idb)
+TOOL_VCC80AMD64_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC80AMD64_PDB, $(outbase)-obj,pdb)
+define TOOL_VCC80AMD64_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_VCC80AMD64_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-FD\
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC80AMD64_PDB,$(outbase)-obj,idb)
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80AMD64_COMPILE_CXX_DEPEND =
+TOOL_VCC80AMD64_COMPILE_CXX_DEPORD =
+TOOL_VCC80AMD64_COMPILE_CXX_OUTPUT = $(call TOOL_VCC80AMD64_PDB, $(outbase)-obj,idb)
+TOOL_VCC80AMD64_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC80AMD64_PDB, $(outbase)-obj,pdb)
+define TOOL_VCC80AMD64_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC80AMD64_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-FD\
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC80AMD64_PDB,$(outbase)-obj,idb)
+endef
+
+
+## Compile resource source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80AMD64_COMPILE_RC_DEPEND =
+TOOL_VCC80AMD64_COMPILE_RC_DEPORD =
+TOOL_VCC80AMD64_COMPILE_RC_OUTPUT =
+define TOOL_VCC80AMD64_COMPILE_RC_CMDS
+	$(QUIET)$(TOOL_VCC80AMD64_RC) \
+		$(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\
+		/fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_VCC80AMD64_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_VCC80AMD64_LINK_LIBRARY_DEPORD =
+TOOL_VCC80AMD64_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_VCC80AMD64_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb
+define TOOL_VCC80AMD64_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp \
+		$(foreach arg,\
+			$(subst /,\\,$(objs) \
+			$(filter-out %.def,$(othersrc))) \
+			$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC80AMD64_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+endef
+
+
+## Link program
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          Program name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+#
+TOOL_VCC80AMD64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80AMD64_LINK_PROGRAM_DEPORD =
+TOOL_VCC80AMD64_LINK_PROGRAM_OUTPUT = $(outbase).map
+TOOL_VCC80AMD64_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).pdb $(outbase).ilk $(out).manifest
+define TOOL_VCC80AMD64_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_VCC80AMD64_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80AMD64_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out))
+endef
+
+
+## Link DLL.
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      DLL name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC80AMD64_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80AMD64_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_LIB))
+TOOL_VCC80AMD64_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp
+TOOL_VCC80AMD64_LINK_DLL_OUTPUT_MAYBE = $(outbase).pdb $(outbase).ilk $(out).manifest $(PATH_LIB)/$(notdir $(outbase)).lib $(PATH_LIB)/$(notdir $(outbase)).exp
+define TOOL_VCC80AMD64_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_VCC80AMD64_LD) $(flags) \
+		/OUT:$(out) \
+		/IMPLIB:$(outbase).lib \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		/DLL \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80AMD64_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+	$(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_LIB)/
+$(eval _DIRS += $(PATH_LIB))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          System module name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC80AMD64_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80AMD64_LINK_SYSMOD_DEPORD =
+TOOL_VCC80AMD64_LINK_SYSMOD_OUTPUT = $(outbase).map
+TOOL_VCC80AMD64_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).pdb $(outbase).ilk $(out).manifest
+define TOOL_VCC80AMD64_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_VCC80AMD64_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80AMD64_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/VCC80X86.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/VCC80X86.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/VCC80X86.kmk	(revision 1780)
@@ -0,0 +1,321 @@
+# $Id$
+## @file
+# kBuild Tool Config - Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting x86.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_VCC80X86 := Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting x86.
+
+# Tool Specific Properties
+ifndef PATH_TOOL_VCC80X86
+ PATH_TOOL_VCC80X86 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v8*)
+ ifeq ($(PATH_TOOL_VCC80X86),)
+  PATH_TOOL_VCC80X86 := $(PATH_TOOL_VCC80)
+ endif
+ ifeq ($(PATH_TOOL_VCC80X86),)
+  PATH_TOOL_VCC80X86 := $(PATH_TOOL_VCC80AMD64)
+ endif
+ ifeq ($(PATH_TOOL_VCC80X86),)
+  PATH_TOOL_VCC80X86 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/vcc/v8*)
+ endif
+ ifeq ($(PATH_TOOL_VCC80X86),)
+  PATH_TOOL_VCC80X86 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/vcc/v8*)
+ endif
+ ifneq ($(PATH_TOOL_VCC80X86),)
+  PATH_TOOL_VCC80X86 := $(lastword $(sort $(PATH_TOOL_VCC80X86)))
+ else
+  $(warning kBuild: PATH_TOOL_VCC80X86 cannot be determined!)
+  PATH_TOOL_VCC80X86 := $(PATH_DEVTOOLS)/x86.win/vcc/v8
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_VCC80X86 := $(PATH_TOOL_VCC80X86)
+endif
+PATH_TOOL_VCC80X86_BIN    ?= $(PATH_TOOL_VCC80X86)/bin
+PATH_TOOL_VCC80X86_LIB    ?= $(PATH_TOOL_VCC80X86)/lib
+PATH_TOOL_VCC80X86_INC    ?= $(PATH_TOOL_VCC80X86)/include
+PATH_TOOL_VCC80X86_ATLMFC ?= $(PATH_TOOL_VCC80X86)/atlmfc
+PATH_TOOL_VCC80X86_ATLMFC_INC ?= $(PATH_TOOL_VCC80X86_ATLMFC)/include
+PATH_TOOL_VCC80X86_ATLMFC_LIB ?= $(PATH_TOOL_VCC80X86_ATLMFC)/lib
+TOOL_VCC80X86_CC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/cl.exe
+TOOL_VCC80X86_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/cl.exe
+TOOL_VCC80X86_AS  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/ml.exe
+TOOL_VCC80X86_RC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/rc.exe
+TOOL_VCC80X86_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/lib.exe
+TOOL_VCC80X86_LD  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/link.exe
+TOOL_VCC80X86_MT  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/mt.exe
+## Disabled fast DEP_IDB based dependencies.
+#VCC80X86_OLD_DEPS = 1
+
+## Constructs the correct .pdb name (the name is lowercased).
+# @param    $(1)        Base name, no extention.
+# @param    $(2)        The extension.
+TOOL_VCC80X86_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2)
+
+
+# General Properties used by kBuild
+TOOL_VCC80X86_COBJSUFF         ?= .obj
+TOOL_VCC80X86_CFLAGS           ?= -TC -c -nologo
+TOOL_VCC80X86_CFLAGS.debug     ?= -Zi
+TOOL_VCC80X86_CFLAGS.release   ?= -O2
+TOOL_VCC80X86_CFLAGS.profile   ?= -O2
+TOOL_VCC80X86_CINCS            ?= $(PATH_TOOL_VCC80X86_INC)
+TOOL_VCC80X86_CDEFS            ?=
+
+TOOL_VCC80X86_CXXOBJSUFF       ?= .obj
+TOOL_VCC80X86_CXXFLAGS         ?= -TP -c -nologo
+TOOL_VCC80X86_CXXFLAGS.debug   ?= -Zi
+TOOL_VCC80X86_CXXFLAGS.release ?= -O2
+TOOL_VCC80X86_CXXFLAGS.profile ?= -O2
+TOOL_VCC80X86_CXXINCS          ?= $(PATH_TOOL_VCC80X86_INC) $(PATH_TOOL_VCC80X86_ATLMFC_INC)
+TOOL_VCC80X86_CXXDEFS          ?=
+
+TOOL_VCC80X86_ASOBJSUFF        ?= .obj
+
+TOOL_VCC80X86_RCOBJSUFF        ?= .res
+TOOL_VCC80X86_RCINCS           ?= $(PATH_TOOL_VCC80X86_INC) $(PATH_TOOL_VCC80X86_ATLMFC_INC)
+
+TOOL_VCC80X86_ARFLAGS          ?= -nologo
+TOOL_VCC80X86_ARLIBSUFF        ?= .lib
+
+TOOL_VCC80X86_LDFLAGS          ?= -nologo -machine:x86
+TOOL_VCC80X86_LDFLAGS.debug    ?= -debug
+TOOL_VCC80X86_LDFLAGS.release  ?=
+
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80X86_COMPILE_C_DEPEND =
+TOOL_VCC80X86_COMPILE_C_DEPORD =
+TOOL_VCC80X86_COMPILE_C_OUTPUT = $(call TOOL_VCC80X86_PDB, $(outbase)-obj,idb)
+TOOL_VCC80X86_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC80X86_PDB, $(outbase)-obj,pdb)
+define TOOL_VCC80X86_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_VCC80X86_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-FD\
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC80X86_PDB,$(outbase)-obj,idb)
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80X86_COMPILE_CXX_DEPEND =
+TOOL_VCC80X86_COMPILE_CXX_DEPORD =
+TOOL_VCC80X86_COMPILE_CXX_OUTPUT = $(call TOOL_VCC80X86_PDB, $(outbase)-obj,idb)
+TOOL_VCC80X86_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC80X86_PDB, $(outbase)-obj,pdb)
+define TOOL_VCC80X86_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC80X86_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-FD\
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_IDB) -f -s -o $(dep) -t $(obj) $(call TOOL_VCC80X86_PDB,$(outbase)-obj,idb)
+endef
+
+## @todo configure the assembler template.
+
+## Compile resource source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC80X86_COMPILE_RC_DEPEND =
+TOOL_VCC80X86_COMPILE_RC_DEPORD =
+TOOL_VCC80X86_COMPILE_RC_OUTPUT =
+define TOOL_VCC80X86_COMPILE_RC_CMDS
+	$(QUIET)$(TOOL_VCC80X86_RC) \
+		$(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\
+		/fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_VCC80X86_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_VCC80X86_LINK_LIBRARY_DEPORD =
+TOOL_VCC80X86_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_VCC80X86_LINK_LIBRARY_OUTPUT_OUTPUT = $(outbase).lst $(outbase).exp $(outbase).pdb
+define TOOL_VCC80X86_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) -n $(outbase).rsp \
+		$(foreach arg,\
+			$(subst /,\\,$(objs) \
+			$(filter-out %.def,$(othersrc))) \
+			$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC80X86_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+endef
+
+
+## Link program
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          Program name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+#
+TOOL_VCC80X86_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80X86_LINK_PROGRAM_DEPORD =
+TOOL_VCC80X86_LINK_PROGRAM_OUTPUT = $(outbase).map
+TOOL_VCC80X86_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).pdb $(outbase).ilk $(out).manifest
+define TOOL_VCC80X86_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_VCC80X86_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80X86_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out))
+endef
+
+
+## Link DLL.
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      DLL name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC80X86_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80X86_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_LIB))
+TOOL_VCC80X86_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp 
+TOOL_VCC80X86_LINK_DLL_OUTPUT_MAYBE = $(outbase).pdb $(outbase).ilk $(out).manifest $(PATH_LIB)/$(notdir $(outbase)).lib $(PATH_LIB)/$(notdir $(outbase)).exp
+define TOOL_VCC80X86_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_VCC80X86_LD) $(flags) \
+		/OUT:$(out) \
+		/IMPLIB:$(outbase).lib \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		/DLL \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80X86_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+	$(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_LIB)/
+$(eval _DIRS += $(PATH_LIB))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          System module name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC80X86_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC80X86_LINK_SYSMOD_DEPORD =
+TOOL_VCC80X86_LINK_SYSMOD_OUTPUT = $(outbase).map
+TOOL_VCC80X86_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).pdb $(outbase).ilk $(out).manifest
+define TOOL_VCC80X86_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_VCC80X86_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		$(subst /,\\,$(objs)) \
+		$(subst /,\\,$(libs))
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC80X86_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/WGET.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/WGET.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/WGET.kmk	(revision 1780)
@@ -0,0 +1,67 @@
+# $Id$
+## @file
+# kBuild Tool Config - wget fetchers.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_WGET := wget fetcher.
+
+# Tool Specific Properties
+ifndef TOOL_WGET_FETCH
+ TOOL_WGET_FETCH := $(wildcard $(PATH_DEVTOOLS_BLD)/wget/v*/wget$(HOSTSUFF_EXE))
+ ifneq ($(TOOL_WGET_FETCH),)
+  TOOL_WGET_FETCH := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/wget$(HOSTSUFF_EXE))
+ endif
+ ifneq ($(TOOL_WGET_FETCH),)
+  TOOL_WGET_FETCH := $(lastword $(sort $(TOOL_WGET_FETCH)))
+ else
+  TOOL_WGET_FETCH := wget$(HOSTSUFF_EXE)
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ TOOL_WGET_FETCH := $(TOOL_WGET_FETCH)
+endif
+
+# General Properties used by kBuild
+TOOL_WGET_FETCHFLAGS ?= --passive-ftp -t 5 -T 60
+
+## Fetch one file.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   The URI of the file.
+# @param    $(flags)    Flags.
+# @param    $(out)   	The output file
+TOOL_WGET_FETCH_OUTPUT =
+TOOL_WGET_FETCH_DEPEND =
+TOOL_WGET_FETCH_DEPORD =
+define TOOL_WGET_FETCH_CMDS
+	$(QUIET)$(TOOL_WGET_FETCH) $(flags) -P $(dir $(out)) $(source)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/XGCCAMD64LINUX.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/XGCCAMD64LINUX.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/XGCCAMD64LINUX.kmk	(revision 1780)
@@ -0,0 +1,286 @@
+# $Id$
+## @file
+# kBuild Tool Config - GCC Cross compiler for AMD64+Linux.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_XGCCAMD64LINUX := GCC Cross compiler for AMD64+Linux.
+
+# Tool Specific Properties
+TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE ?= $(HOSTSUFF_EXE)
+ifeq ($(KBUILD_HOST).$(KBUILD_HOST_ARCH),linux.amd64)
+ # not x-compile, use the default gcc.
+ TOOL_XGCCAMD64LINUX_PREFIX := $(TOOL_XGCCAMD64LINUX_PREFIX)
+else # x-compile:
+ # find the latest xgcc build.
+ ifndef TOOL_XGCCAMD64LINUX_PREFIX
+  TOOL_XGCCAMD64LINUX_PREFIX := x86_64-unknown-linux-gnu-
+  ifndef PATH_TOOL_XGCCAMD64LINUX
+   PATH_TOOL_XGCCAMD64LINUX := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/x86_64-unknown-linux-gnu/*))
+   ifeq ($(PATH_TOOL_XGCCAMD64LINUX),)
+    ifeq ($(filter-out win.amd64,$(KBUILD_HOST).$(KBUILD_HOST_ARCH)),) # these can use the windows build.
+     TOOL_XGCCAMD64LINUX_EXEC_PREFIX ?= $(EXEC_X86_WIN32)
+     TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE := .exe
+     PATH_TOOL_XGCCAMD64LINUX := $(sort $(wildcard $(PATH_DEVTOOLS)/win.x86/x86_64-unknown-linux-gnu/*))
+     ifeq ($(PATH_TOOL_XGCCAMD64LINUX),)
+      PATH_TOOL_XGCCAMD64LINUX := $(sort $(wildcard $(PATH_DEVTOOLS)/x86.win32/x86_64-unknown-linux-gnu/*))
+     endif
+    endif
+   endif
+   ifneq ($(PATH_TOOL_XGCCAMD64LINUX),)
+    PATH_TOOL_XGCCAMD64LINUX := $(call lastword,$(PATH_TOOL_XGCCAMD64LINUX))
+   endif
+  endif # !PATH_TOOL_XGCCAMD64LINUX
+  ifneq ($(PATH_TOOL_XGCCAMD64LINUX),)
+   TOOL_XGCCAMD64LINUX_PREFIX := $(TOOL_XGCCAMD64LINUX_EXEC_PREFIX) $(PATH_TOOL_XGCCAMD64LINUX)/bin/$(TOOL_XGCCAMD64LINUX_PREFIX)
+  endif
+ else
+  # Resolve any fancy stuff once and for all.
+  TOOL_XGCCAMD64LINUX_PREFIX := $(TOOL_XGCCAMD64LINUX_PREFIX)
+ endif
+endif
+
+TOOL_XGCCAMD64LINUX_CC  ?= $(TOOL_XGCCAMD64LINUX_PREFIX)gcc$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE)
+TOOL_XGCCAMD64LINUX_CXX ?= $(TOOL_XGCCAMD64LINUX_PREFIX)g++$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE)
+TOOL_XGCCAMD64LINUX_AS  ?= $(TOOL_XGCCAMD64LINUX_PREFIX)gcc$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE)
+TOOL_XGCCAMD64LINUX_AR  ?= $(TOOL_XGCCAMD64LINUX_PREFIX)ar$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE)
+TOOL_XGCCAMD64LINUX_LD  ?= $(TOOL_XGCCAMD64LINUX_PREFIX)g++$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE)
+TOOL_XGCCAMD64LINUX_LD_SYSMOD ?= $(TOOL_XGCCAMD64LINUX_PREFIX)ld$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE)
+
+TOOL_XGCCAMD64LINUX_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
+TOOL_XGCCAMD64LINUX_LD_MAP ?= -Wl,-Map -Wl,$(1) -Wl,--cref
+TOOL_XGCCAMD64LINUX_LD_SYSMOD_MAP ?= -Map $(1) --cref
+TOOL_XGCCAMD64LINUX_LDFLAGS.dll ?= -shared
+TOOL_XGCCAMD64LINUX_LDFLAGS.sysmod ?= -r
+
+ifdef SLKRUNS
+TOOL_XGCCAMD64LINUX_CC  += -fmessage-length=0
+TOOL_XGCCAMD64LINUX_CXX += -fmessage-length=0
+endif
+
+# General Properties used by kBuild
+TOOL_XGCCAMD64LINUX_COBJSUFF         ?= .o
+TOOL_XGCCAMD64LINUX_CFLAGS           ?= -g
+TOOL_XGCCAMD64LINUX_CFLAGS.debug     ?= -O0
+TOOL_XGCCAMD64LINUX_CFLAGS.release   ?= -O2
+TOOL_XGCCAMD64LINUX_CFLAGS.profile   ?= -O2 #-pg
+TOOL_XGCCAMD64LINUX_CINCS            ?=
+TOOL_XGCCAMD64LINUX_CDEFS            ?=
+
+TOOL_XGCCAMD64LINUX_CXXOBJSUFF       ?= .o
+TOOL_XGCCAMD64LINUX_CXXOBJSUFF       ?= .o
+TOOL_XGCCAMD64LINUX_CXXFLAGS         ?= -g
+TOOL_XGCCAMD64LINUX_CXXFLAGS.debug   ?= -O0
+TOOL_XGCCAMD64LINUX_CXXFLAGS.release ?= -O2
+TOOL_XGCCAMD64LINUX_CXXFLAGS.profile ?= -O2 #-pg
+TOOL_XGCCAMD64LINUX_CXXINCS          ?=
+TOOL_XGCCAMD64LINUX_CXXDEFS          ?=
+
+TOOL_XGCCAMD64LINUX_ASFLAGS          ?= -g -x assembler-with-cpp
+TOOL_XGCCAMD64LINUX_ASOBJSUFF        ?= .o
+
+TOOL_XGCCAMD64LINUX_ARFLAGS          ?= cr
+TOOL_XGCCAMD64LINUX_ARLIBSUFF        ?= .a
+
+TOOL_XGCCAMD64LINUX_LDFLAGS          ?=
+TOOL_XGCCAMD64LINUX_LDFLAGS.debug    ?= -g
+TOOL_XGCCAMD64LINUX_LDFLAGS.release  ?= -s
+
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_XGCCAMD64LINUX_COMPILE_C_OUTPUT =
+TOOL_XGCCAMD64LINUX_COMPILE_C_DEPEND =
+TOOL_XGCCAMD64LINUX_COMPILE_C_DEPORD =
+define TOOL_XGCCAMD64LINUX_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_XGCCAMD64LINUX_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)	    Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_XGCCAMD64LINUX_COMPILE_CXX_OUTPUT =
+TOOL_XGCCAMD64LINUX_COMPILE_CXX_DEPEND =
+TOOL_XGCCAMD64LINUX_COMPILE_CXX_DEPORD =
+define TOOL_XGCCAMD64LINUX_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_XGCCAMD64LINUX_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_XGCCAMD64LINUX_COMPILE_AS_OUTPUT =
+TOOL_XGCCAMD64LINUX_COMPILE_AS_DEPEND =
+TOOL_XGCCAMD64LINUX_COMPILE_AS_DEPORD =
+define TOOL_XGCCAMD64LINUX_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_XGCCAMD64LINUX_AS) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\
+		-o $(obj)\
+		$(abspath $(source))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_XGCCAMD64LINUX_LINK_LIBRARY_OUTPUT = $(out).ar-script
+TOOL_XGCCAMD64LINUX_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_XGCCAMD64LINUX_LINK_LIBRARY_DEPORD =
+define TOOL_XGCCAMD64LINUX_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)'
+	$(QUIET)$(APPEND) -n $(out).ar-script \
+		$(foreach o,$(objs), 'ADDMOD $(o)') \
+		$(foreach o,$(othersrc), 'ADDLIB $(o)')
+	$(QUIET)$(APPEND) $(out).ar-script 'SAVE'
+	$(QUIET)$(APPEND) $(out).ar-script 'END'
+	$(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_XGCCAMD64LINUX_AR) -M
+endef
+
+
+## Link program
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_XGCCAMD64LINUX_LINK_PROGRAM_OUTPUT = $(outbase).map
+TOOL_XGCCAMD64LINUX_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_XGCCAMD64LINUX_LINK_PROGRAM_DEPORD =
+define TOOL_XGCCAMD64LINUX_LINK_PROGRAM_CMDS
+	$(QUIET)$(TOOL_XGCCAMD64LINUX_LD) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib)))\
+		$(call TOOL_XGCCAMD64LINUX_LD_MAP,$(outbase).map)
+endef
+
+
+## Link DLL
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		Program name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_XGCCAMD64LINUX_LINK_DLL_OUTPUT = $(outbase).map
+TOOL_XGCCAMD64LINUX_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_XGCCAMD64LINUX_LINK_DLL_DEPORD =
+define TOOL_XGCCAMD64LINUX_LINK_DLL_CMDS
+	$(QUIET)$(TOOL_XGCCAMD64LINUX_LD) $(TOOL_XGCCAMD64LINUX_LDFLAGS.dll) $(flags) -o $(out)\
+		$(if $(filter-out win32 os2, $(KBUILD_TARGET)),$(call TOOL_XGCCAMD64LINUX_LD_SONAME,$(target),$(out)))\
+		$(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib)))\
+		$(call TOOL_XGCCAMD64LINUX_LD_MAP,$(outbase).map)
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)   Normalized main target name.
+# @param    $(out)		System module name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)		Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_XGCCAMD64LINUX_LINK_SYSMOD_OUTPUT = $(outbase).map
+TOOL_XGCCAMD64LINUX_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))
+TOOL_XGCCAMD64LINUX_LINK_SYSMOD_DEPORD =
+define TOOL_XGCCAMD64LINUX_LINK_SYSMOD_CMDS
+	$(QUIET)$(TOOL_XGCCAMD64LINUX_LD_SYSMOD) $(TOOL_XGCCAMD64LINUX_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\
+		$(foreach p,$(libpath), -L$(p))\
+		$(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib)))\
+		$(call TOOL_XGCCAMD64LINUX_LD_SYSMOD_MAP,$(outbase).map)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/YASM.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/YASM.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/YASM.kmk	(revision 1780)
@@ -0,0 +1,84 @@
+# $Id$
+## @file
+# kBuild Tool Config - YASM 0.4.0 or later.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_YASM := YASM v0.4.0+
+
+# Tool Specific Properties
+ifndef PATH_TOOL_YASM
+ PATH_TOOL_YASM := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/yasm/v*.*))
+ ifneq ($(PATH_TOOL_YASM),)
+  PATH_TOOL_YASM := $(call lastword,$(PATH_TOOL_YASM))
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_YASM := $(PATH_TOOL_YASM)
+endif
+ifneq ($(PATH_TOOL_YASM),)
+ TOOL_YASM_AS ?= $(PATH_TOOL_YASM)/yasm$(HOSTSUFF_EXE)
+else
+ TOOL_YASM_AS ?= yasm$(HOSTSUFF_EXE)
+endif
+
+# General Properties used by kBuild
+TOOL_YASM_ASFLAGS ?=
+
+
+## Compile Assembly source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+#
+TOOL_YASM_COMPILE_AS_OUTPUT = $(outbase).lst
+TOOL_YASM_COMPILE_AS_DEPEND =
+TOOL_YASM_COMPILE_AS_DEPORD =
+define TOOL_YASM_COMPILE_AS_CMDS
+	$(QUIET)$(TOOL_YASM_AS)\
+		$(flags) $(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\
+		-l $(outbase).lst\
+		-o $(obj)\
+		$(abspath $(source))
+	$(QUIET)$(REDIRECT) -wo $(dep) -- $(TOOL_YASM_AS)\
+		$(flags) $(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\
+		-o $(obj) \
+		$(abspath $(source)) \
+		-M
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/tools/ZIP.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/tools/ZIP.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/tools/ZIP.kmk	(revision 1780)
@@ -0,0 +1,89 @@
+# $Id$
+## @file
+# kBuild Tool Config - The zip/unzip packer/unpacker.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_ZIP := The zip/unzip packer/unpacker.
+
+# Tool Specific Properties
+ifndef TOOL_ZIP_UNPACK
+ TOOL_ZIP_UNPACK := $(wildcard $(PATH_DEVTOOLS_BLD)/unzip/v*/unzip$(HOSTSUFF_EXE))
+ ifeq ($(TOOL_ZIP_UNPACK),)
+  TOOL_ZIP_UNPACK := $(wildcard $(PATH_DEVTOOLS_BLD)/zip/v*/unzip$(HOSTSUFF_EXE))
+ endif
+ ifeq ($(TOOL_ZIP_UNPACK),)
+  TOOL_ZIP_UNPACK := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/unzip$(HOSTSUFF_EXE))
+ endif
+ ifneq ($(TOOL_ZIP_UNPACK),)
+  TOOL_ZIP_UNPACK := $(lastword $(sort $(TOOL_ZIP_UNPACK)))
+ else
+  TOOL_ZIP_UNPACK := unzip$(HOSTSUFF_EXE)
+ endif
+else
+ TOOL_ZIP_UNPACK := $(TOOL_ZIP_UNPACK)
+endif
+#ifndef TOOL_ZIP_PACK
+# TOOL_ZIP_PACK := $(wildcard $(PATH_DEVTOOLS_BLD)/zip/v*/zip$(HOSTSUFF_EXE))
+# ifeq ($(TOOL_ZIP_PACK),)
+#  TOOL_ZIP_PACK := $(wildcard $(PATH_DEVTOOLS_BLD)/unzip/v*/zip$(HOSTSUFF_EXE))
+# endif
+# ifeq ($(TOOL_ZIP_PACK),)
+#  TOOL_ZIP_PACK := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/zip$(HOSTSUFF_EXE))
+# endif
+# ifneq ($(TOOL_ZIP_PACK),)
+#  TOOL_ZIP_PACK := $(lastword $(sort $(TOOL_ZIP_PACK)))
+# else
+#  TOOL_ZIP_PACK := zip$(HOSTSUFF_EXE)
+# endif
+#else
+# TOOL_ZIP_PACK := $(TOOL_ZIP_PACK)
+#endif
+
+# General Properties used by kBuild
+TOOL_ZIP_UNPACKFLAGS ?=
+
+## UNPACK one file.
+# @param $(zipget)   Normalized main zipget name.
+# @param $(archive)  The file to unpack.
+# @param $(flags)    Flags.
+# @param $(inst)     Where to unpack it.
+# @param $(out)      Where to write the file list.
+TOOL_ZIP_UNPACK_OUTPUT =
+TOOL_ZIP_UNPACK_DEPEND =
+TOOL_ZIP_UNPACK_DEPORD =
+define TOOL_ZIP_UNPACK_CMDS
+	$(QUIET)$(TOOL_ZIP_UNPACK) $(flags) $(archive) -d "$(inst)"
+	$(QUIET)$(TOOL_ZIP_UNPACK) -l $(archive) | $(SED) \
+		-e '/ [0-2][0-9]:[0-6][0-9]/!d' \
+		-e 's/^.* [0-2][0-9]:[0-6][0-9]   //' \
+		> $(out)
+endef
+
Index: /tags/kBuild-0.1.4/kBuild/units/lex.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/units/lex.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/units/lex.kmk	(revision 1780)
@@ -0,0 +1,127 @@
+# $Id$
+## @file
+# lex unit.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+UNIT_lex = lex
+
+# Add ourselves to the default source handlers.
+KBUILD_SRC_HANDLERS += \
+  .l:def_src_handler_lex
+
+
+## wrapper the compile command dependency check.
+ifndef NO_COMPILE_CMDS_DEPS
+ _DEP_LEX_CMDS = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_LEX_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _DEP_LEX_CMDS =
+endif
+
+
+##
+# Generates the rules for running flex on a specific source file.
+#
+# @param    $(obj)    The object file.
+# @param    lots more
+define def_lex_rule
+$(out) + $(output_extra) +| $(output_maybe) : \
+		$(deps) \
+		$(value _DEP_LEX_CMDS) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_COMPILE,$(target),$(source),$$@,$(type))
+	$$(QUIET)$$(RM) -f -- $(dep) $(out) $(output_extra) $(output_maybe)
+
+$(cmds)
+
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_LEX_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+# update globals
+_OUT_FILES += $(out) $(output_extra) $(output_maybe)
+$(target)_GEN_SOURCES_ += $(out)
+
+endef # def_lex_rule
+
+##
+# Handler for .l files listed in the SOURCES properties.
+#
+# .l files are transformed into .c files that then gets compiled by
+# the C compiler.
+#
+# @param    target      The target file.
+# @param    source      The source file.
+# @param    lots more
+# @returns  quite a bit.
+define def_src_handler_lex
+# Figure out all the props.
+local type := LEX
+local tmp := $(kb-src-tool tool)
+ifeq ($(tool),)
+$(error kBuild: $(target) / $(sources) does not a (lex) tool defined!)
+endif
+ifndef TOOL_$(tool)_LEX_CMDS
+$(error kBuild: TOOL_$(tool)_LEX_CMDS isn't defined! target=$(target) source=$(source) )
+endif
+local out := $(kb-obj-base outbase).c
+local tmp := $(kb-src-prop LEXFLAGS,flags,left-to-right,)
+local tmp := $(kb-src-prop DEPS,deps,left-to-right,$(defpath))
+local tmp := $(kb-src-prop ORDERDEPS,orderdeps,left-to-right,$(defpath))
+ifdef TOOL_$(tool)_LEX_OUT_FILE # .c/.cpp output depends on flags.
+ local out := $(strip $(TOOL_$(tool)_LEX_OUT_FILE))
+ ifeq ($(out),)
+  local out := $(outbase).c
+ endif
+endif
+local dirdep := $(call DIRDEP,$(dir $(out)))
+
+# Adjust paths if we got a default path.
+ifneq ($(defpath),)
+ local source := $(abspathex $(source),$(defpath))
+endif
+
+# dependency file.
+local dep := $(out)$(SUFF_DEP)
+ifndef NO_COMPILE_CMDS_DEPS
+ _DEPFILES_INCLUDED += $(dep)
+ $(eval includedep $(dep))
+endif
+
+# call the tool
+local cmds := $(TOOL_$(tool)_LEX_CMDS)
+local output_extra := $(TOOL_$(tool)_LEX_OUTPUT)
+local output_maybe := $(TOOL_$(tool)_LEX_OUTPUT_MAYBE)
+local deps += $(TOOL_$(tool)_LEX_DEPEND) $(source)
+local orderdeps += $(TOOL_$(tool)_LEX_DEPORD)
+
+# generate the rule.
+$(eval $(def_lex_rule))
+
+endef # def_src_handler_lex
+
+
Index: /tags/kBuild-0.1.4/kBuild/units/qt-Q_OBJECT.sed
===================================================================
--- /tags/kBuild-0.1.4/kBuild/units/qt-Q_OBJECT.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/units/qt-Q_OBJECT.sed	(revision 1780)
@@ -0,0 +1,36 @@
+# $Id$
+## @file
+# Qt unit - sed script for checking for Q_OBJECT in a file.
+#
+# This is not very sophisticated, but it helps avoid generating
+# files we don't need. It outputs '1' when Q_OBJECT is found
+# and then quits, allowing us to do $(if $(shell ...),moc_...).
+# is
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+/Q_OBJECT/!b skip
+s/^.*$/1/
+q 0
+:skip
+d
Index: /tags/kBuild-0.1.4/kBuild/units/qt3.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/units/qt3.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/units/qt3.kmk	(revision 1780)
@@ -0,0 +1,915 @@
+# $Id$
+## @file
+# Qt 3.3.x unit.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+ifdef UNIT_qt3
+ $(error kBuild: The qt3 unit was included twice!)
+endif
+UNIT_qt3 = qt3
+
+
+ifndef UNIT_qt4
+ # Add our target properties (same as qt4).
+ PROPS_SINGLE += QTTOOL MOCTOOL UICTOOL LRCTOOL QT_TRANSLATIONS_INST QT_TRANSLATIONS_TEMPLATE QT_PREFIX
+ PROPS_ACCUMULATE_R += MOCDEFS MOCFLAGS UICFLAGS LRCFLAGS QT_TRANSLATIONS QT_MOCSRCS QT_MOCHDRS
+endif
+PROPS_SINGLE +=
+PROPS_ACCUMULATE_R += QT_IMAGES
+
+
+#
+# The QT3 SDK.
+#
+# This is implemented here rather than in sdks/QT3.kmk to enforce the global USES.
+# It also makes things easier to develop, with fewer files I mean.
+#
+## @todo the SDK might actually not be necessary as it turns out... For now it servers
+# a purpose if the host differs from the target, in theory at least.
+SDK_QT3 = Qt3
+
+# SDK Specific Properties
+#       PATH_SDK_QT3           - the general location of the Qt3 SDK stuff.
+#       PATH_SDK_QT3_INC       - the Qt3 include directory.
+#       PATH_SDK_QT3_LIB       - the Qt3 library directory for KBUILD_TARGET.
+#       PATH_SDK_QT3_LIB.amd64 - the Qt3 library directory for AMD64.
+#       PATH_SDK_QT3_LIB.x86   - the Qt3 library directory for X86.
+ifndef PATH_SDK_QT3
+ PATH_SDK_QT3 := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/qt/v3*)))
+ ifeq ($(PATH_SDK_QT3),)
+  # If target == host, try look for Qt in the various platform specific places.
+  ifeq ($(KBUILD_TARGET),$(KBUILD_HOST))
+   ifeq ($(KBUILD_TARGET),darwin)
+    # No idea here yet...
+   else ifeq ($(KBUILD_TARGET),os2)
+    # No idea here yet...
+   else ifeq ($(KBUILD_TARGET),win)
+    # No idea here yet...
+   else
+    # The Unices. Includes and esp. libs are tricky, so override the PATH_SDK_QT3_LIB* stuff if it doesn't work.
+    # Try find the general location of the thing by looking for the qm2ts program, then try looking for
+    # the moc program in likely and unlikely places save /usr[/local]/bin to avoid mistaking it with Qt4.
+    PATH_SDK_QT3 := $(patsubst %/bin/qm2ts,%,$(firstword $(wildcard \
+	/usr/lib/qt-3.3/bin/qm2ts \
+	/usr/lib64/qt-3.3/bin/qm2ts \
+	/usr/qt/3/bin/qm2ts \
+	$(if $(QTDIR),$(QTDIR)/bin/qm2ts) \
+	/usr/bin/qm2ts \
+	/usr/local/bin/qm2ts \
+	/usr/share/qt3/bin/qm2ts \
+	)))
+    ifeq ($(PATH_SDK_QT3),) # Try with moc, but not in /usr/bin and /usr/local/bin.
+     PATH_SDK_QT3 := $(patsubst %/bin/moc,%,$(firstword $(wildcard \
+ 	/usr/lib/qt-3.3/bin/moc \
+ 	/usr/lib64/qt-3.3/bin/moc \
+ 	/usr/qt/3/bin/moc \
+ 	/usr/share/qt3/bin/moc \
+ 	$(if $(QTDIR),$(QTDIR)/bin/moc) \
+ 	)))
+    endif
+    ifneq ($(PATH_SDK_QT3),)
+     # Found something! Export the variable for the benefit of recursive make instances.
+     export PATH_SDK_QT3
+
+     # Determin the include directory.
+     ifeq ($(PATH_SDK_QT3_INC),)
+      PATH_SDK_QT3_INC := $(patsubst %/private/qfiledefs_p.h,%,$(firstword $(wildcard \
+	$(PATH_SDK_QT3)/include/private/qfiledefs_p.h \
+	$(PATH_SDK_QT3)/include/qt3/private/qfiledefs_p.h \
+	/usr/include/qt3/private/qfiledefs_p.h)))
+      ifneq ($(PATH_SDK_QT3_INC),)
+       export PATH_SDK_QT3_INC
+      endif
+     endif
+
+     # Determin the most likely x86 and AMD64 lib directories (only used for making PATH_SDK_QT3_LIB).
+     ifeq ($(PATH_SDK_QT3_LIB.x86),)
+      PATH_SDK_QT3_LIB.x86   := $(patsubst %/libqt-mt$(SUFF_DLL),%,$(firstword $(wildcard \
+	$(PATH_SDK_QT3)/lib32/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib32/qt3/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib32/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	/usr/lib32/libqt-mt$(SUFF_DLL) \
+	/usr/lib32/qt3/libqt-mt$(SUFF_DLL) \
+	/usr/lib32/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib32/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib32/qt3/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib32/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/qt3/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	)))
+      ifneq ($(PATH_SDK_QT3_LIB.x86),)
+       export PATH_SDK_QT3_LIB.x86
+      endif
+     endif
+     ifeq ($(PATH_SDK_QT3_LIB.amd64),)
+      PATH_SDK_QT3_LIB.amd64 := $(patsubst %/libqt-mt$(SUFF_DLL),%,$(firstword $(wildcard \
+	$(PATH_SDK_QT3)/lib64/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib64/qt3/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib64/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/amd64/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/64/libqt-mt$(SUFF_DLL) \
+	/usr/lib64/libqt-mt$(SUFF_DLL) \
+	/usr/lib64/qt3/libqt-mt$(SUFF_DLL) \
+	/usr/lib64/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	/usr/lib/amd64/libqt-mt$(SUFF_DLL) \
+	/usr/lib/64/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib64/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib64/qt3/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib64/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib/amd64/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib/64/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/qt3/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	)))
+      ifneq ($(PATH_SDK_QT3_LIB.amd64),)
+       export PATH_SDK_QT3_LIB.amd64
+      endif
+     endif
+
+     # Determin the KBUILD_TARGET lib directory.
+     ifeq ($(PATH_SDK_QT3_LIB),)
+      PATH_SDK_QT3_LIB := $(PATH_SDK_QT3_LIB.$(KBUILD_TARGET))
+      ifeq ($(PATH_SDK_QT3_LIB),)
+       PATH_SDK_QT3_LIB := $(patsubst %/libqt-mt$(SUFF_DLL),%,$(firstword $(wildcard \
+	$(PATH_SDK_QT3)/lib/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/qt3/libqt-mt$(SUFF_DLL) \
+	$(PATH_SDK_QT3)/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	/usr/lib/libqt-mt$(SUFF_DLL) \
+	/usr/lib/qt3/libqt-mt$(SUFF_DLL) \
+	/usr/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib/qt3/libqt-mt$(SUFF_DLL) \
+	/usr/local/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \
+	)))
+       ifneq ($(PATH_SDK_QT3_LIB),)
+        export PATH_SDK_QT3_LIB
+       endif
+      endif
+     endif
+
+    endif
+   endif # Unices
+  endif
+  # Found it?
+  ifeq ($(PATH_SDK_QT3),)
+   $(warning kBuild: Couldn't find the Qt3 headers and libaries...)
+   PATH_SDK_QT3 := $(PATH_DEVTOOLS_TRG)/qt/not-found
+  endif
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_QT3 := $(PATH_SDK_QT3)
+endif
+
+# Libraries can be in either Frameworks or lib depending on how you
+# build it on the mac. The .dmg installs into Frameworks but builds into lib.
+PATH_SDK_QT3_LIB ?= $(PATH_SDK_QT3)/lib
+PATH_SDK_QT3_INC ?= $(PATH_SDK_QT3)/include
+
+# The bits that kBuild picks up.
+#  (nothing here)
+
+
+#
+# The QT3 tool.
+#
+# This is implemented here rather than in tools/QT3.kmk to enforce the global USES.
+# It also makes things easier to develop, with fewer files I mean.
+#
+TOOL_QT3 = Qt3
+
+# Tool Specific Properties (PATH_TOOL_QT3_BIN and TOOL_QT3_BIN_SUFF)
+#       TOOL_QT3_BIN_SUFF - the '-qt3' bit found on debian.
+#       PATH_TOOL_QT3_BIN - the directory containing moc, uic, lrelease, lupdate and qm2ts.
+ifndef PATH_TOOL_QT3_BIN
+ PATH_TOOL_QT3_BIN := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/qt/v3*/bin)))
+ ifeq ($(PATH_TOOL_QT3_BIN),)
+  if1of ($(KBUILD_HOST), win os2)
+   # sorry, no joy here.
+  else
+   ifdef TOOL_QT3_BIN_SUFF
+    TOOL_QT3_BIN_SUFF := $(TOOL_QT3_BIN_SUFF)
+   endif
+    PATH_TOOL_QT3_BIN := $(patsubst %/qm2ts$(TOOL_QT3_BIN_SUFF),%,$(firstword $(wildcard \
+    	/usr/lib/qt-3.3/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \
+    	/usr/lib64/qt-3.3/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \
+    	/usr/qt/3/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \
+    	$(if $(QTDIR),$(QTDIR)/bin/qm2ts$(TOOL_QT3_BIN_SUFF)) \
+    	/usr/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \
+    	/usr/local/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \
+    	/usr/share/qt3/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \
+    	)))
+   ifeq ($(PATH_TOOL_QT3_BIN),)
+    # If we couldn't find the qt3 specific tool qm2ts, debian and other skip 
+    # this (thanks a bundle). Try with look for 'moc' with a '-qt3' extension,
+    # then for just moc. In the latter case don't search /usr[/local]/bin to 
+    # void finding the qt4 tools and messing up.
+    ifeq ($(TOOL_QT3_BIN_SUFF),)
+     PATH_TOOL_QT3_BIN := $(patsubst %/moc-qt3,%,$(firstword $(wildcard \
+     	/usr/bin/moc-qt3 \
+     	/usr/local/bin/moc-qt3 \
+     	/usr/lib/qt-3.3/bin/moc-qt3 \
+     	/usr/lib64/qt-3.3/bin/moc-qt3 \
+     	/usr/qt/3/bin/moc-qt3 \
+     	/usr/share/qt3/bin/moc-qt3 \
+     	$(if $(QTDIR),$(QTDIR)/bin/moc-qt3) \
+     	)))
+    endif
+    ifneq ($(PATH_TOOL_QT3_BIN),)
+     export TOOL_QT3_BIN_SUFF := -qt3
+    else
+     PATH_TOOL_QT3_BIN := $(patsubst %/moc$(TOOL_QT3_BIN_SUFF),%,$(firstword $(wildcard \
+    	/usr/lib/qt-3.3/bin/moc$(TOOL_QT3_BIN_SUFF) \
+    	/usr/lib64/qt-3.3/bin/moc$(TOOL_QT3_BIN_SUFF) \
+    	/usr/qt/3/bin/moc$(TOOL_QT3_BIN_SUFF) \
+    	/usr/share/qt3/bin/moc$(TOOL_QT3_BIN_SUFF) \
+    	$(if $(QTDIR),$(QTDIR)/bin/moc$(TOOL_QT3_BIN_SUFF)) \
+    	)))
+    endif
+   endif
+   ifneq ($(PATH_TOOL_QT3_BIN),)
+    export PATH_TOOL_QT3_BIN
+   endif
+  endif
+ endif
+ # If not found, we'll enter the 'pathless' mode.
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_QT3_BIN := $(PATH_TOOL_QT3_BIN)
+ TOOL_QT3_BIN_SUFF := $(TOOL_QT3_BIN_SUFF)
+endif
+ifneq ($(PATH_TOOL_QT3_BIN),)
+ TOOL_QT3_MOC       ?= $(PATH_TOOL_QT3_BIN)/moc$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT3_UIC       ?= $(PATH_TOOL_QT3_BIN)/uic$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT3_LRC       ?= $(PATH_TOOL_QT3_BIN)/lrelease$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT3_LUPDATE   ?= $(PATH_TOOL_QT3_BIN)/lupdate$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE)
+else
+ # Pathless, relies on the environment.
+ TOOL_QT3_MOC       ?= moc$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT3_UIC       ?= uic$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT3_LRC       ?= lrelease$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT3_LUPDATE   ?= lupdate$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE)
+endif
+
+# General Properties used by kBuild and/or units/qt.kmk
+TOOL_QT3_MOCFLAGS   ?=
+TOOL_QT3_UICFLAGS   ?=
+TOOL_QT3_LRCFLAGS   ?=
+
+
+## MOC a C++ source file.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_QT3_MOC_CPP_DEPEND =
+TOOL_QT3_MOC_CPP_DEPORD =
+TOOL_QT3_MOC_CPP_OUTPUT =
+TOOL_QT3_MOC_CPP_OUTPUT_MAYBE =
+define TOOL_QT3_MOC_CPP_CMDS
+	$(QUIET)$(TOOL_QT3_MOC)\
+		$(flags)\
+		-o $(out)\
+		-i \
+		$(source)
+endef
+
+## MOC a C++ header file.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_QT3_MOC_HPP_DEPEND =
+TOOL_QT3_MOC_HPP_DEPORD =
+TOOL_QT3_MOC_HPP_OUTPUT =
+TOOL_QT3_MOC_HPP_OUTPUT_MAYBE =
+define TOOL_QT3_MOC_HPP_CMDS
+	$(QUIET)$(TOOL_QT3_MOC)\
+		$(flags)\
+		-o $(out)\
+		$(source)
+endef
+
+## Compile a Qt user interface file (.ui).
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out.cpp)  The C++ source file to be generated.
+# @param    $(out.h)    The C++ header file to be generated.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_QT3_UIC_UI_DEPEND =
+TOOL_QT3_UIC_UI_DEPORD =
+TOOL_QT3_UIC_UI_OUTPUT =
+TOOL_QT3_UIC_UI_OUTPUT_MAYBE =
+define TOOL_QT3_UIC_UI_CMDS
+	$(QUIET)$(TOOL_QT3_UIC)\
+		$(flags)\
+		-o $(out.h)\
+		$(source)
+	$(QUIET)$(TOOL_QT3_UIC)\
+		$(flags)\
+		-i $(out.h) \
+		-o $(out.cpp)\
+		$(source)
+endef
+
+## Compile a Qt translation file (.ts).
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions.
+# @param    $(incs)     Includes.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_QT3_LRC_TS_DEPEND =
+TOOL_QT3_LRC_TS_DEPORD =
+TOOL_QT3_LRC_TS_OUTPUT =
+TOOL_QT3_LRC_TS_OUTPUT_MAYBE =
+define TOOL_QT3_LRC_TS_CMDS
+	$(QUIET)$(TOOL_QT3_LRC)\
+		$(flags)\
+		$(source)\
+		-qm $(out)
+endef
+
+
+
+#
+#
+# Back to the Qt3 unit.
+#
+#
+
+
+## wrapper for the lrelease (LRC) command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT3_LRC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT3_LRC_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _UNIT_QT3_LRC_CMDS_DEP =
+endif
+
+##
+# def_unit_qt3_target_pre_handle_translation helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt3_target_pre_handle_translation_dx
+
+$(out) + $(more_output) +| $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT3_LRC_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,lrelease,$(target),$(source),$$@)
+	$(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT3_LRC_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_OUT_FILES += $(out) $(more_output) $(maybe_output)
+$(target)-inst-nls_SOURCES += $(out)
+
+endef # def_unit_qt3_target_pre_handle_translation_dx
+
+##
+# Handle a source file listed in QT_TRANSLATIONS.
+#
+# The files listed in QT_TRANSLATIONS are translation files (.ts) which needs
+# to be translated into .qm files that are loadble by Qt.
+#
+# @remarks Invoked via $(evalvalctx ).
+define def_unit_qt3_target_pre_handle_translation
+local type      := LRC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local qtnlsdir  := $(PATH_$(target))/qtnls
+local outbase   := $(qtnlsdir)/$(notdir $(basename $(source)))
+local out       := $(outbase).qm
+local dep       := $(out).dep
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+local incs      := $(abspathex $(incs),$(defpath))
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_LRC_TS_CMDS
+ $(error kBuild: qt lrelease tool not found: TOOL_$(tool)_LRC_TS_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_LRC_TS_CMDS)
+local more_output  := $(TOOL_$(tool)_LRC_TS_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_LRC_TS_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_LRC_TS_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_LRC_TS_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt3_target_pre_handle_translation_dx))
+
+endef # def_unit_qt3_target_pre_handle_translation
+
+
+
+## wrapper for the UIC command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT3_UIC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT3_UIC_CMDS_PREV_),$$(commands $(out.h)),FORCE)
+else
+ _UNIT_QT3_UIC_CMDS_DEP =
+endif
+
+##
+# def_unit_qt3_src_handler_ui helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt3_target_pre_handle_ui_dx
+
+$(out.h) + $(out.cpp) +| $(realout.h) $(realout.cpp) $(more_output) $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT3_UIC_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,uic,$(target),$(source),$(out.h) $(out.cpp))
+	$(QUIET2)$(RM) -f $(out.h) $(out.cpp) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+	$(QUIET)$(CP) --changed -f $(out.h) $(realout.h)
+	$(QUIET)$(CP) --changed -f $(out.cpp) $(realout.cpp)
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT3_UIC_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out.h)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_INTERMEDIATES += $(realout.h)
+$(target)_GEN_SOURCES_ += $(realout.cpp)
+$(target)_OUT_FILES += $(out.h) $(out.cpp) $(realout.h) $(realout.cpp) $(more_output) $(maybe_output)
+
+endef # def_unit_qt3_target_pre_handle_ui_dx
+
+##
+# Source handler for .ui sources.
+#
+# @remarks $(evalvalctx me).
+define def_unit_qt3_src_handler_ui
+local type      := UIC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local qtuicdir  := $(PATH_$(target))/qtuic
+local outbase   := $(qtuicdir)/$(notdir $(basename $(source)))
+local out.h     := $(outbase).tmp.h
+local out.cpp   := $(outbase).tmp.cpp
+local realout.h := $(outbase).h
+local realout.cpp:=$(outbase).cpp
+local dep       := $(realout.h).dep
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+local incs      := $(abspathex $(incs),$(defpath))
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_UIC_UI_CMDS
+ $(error kBuild: qt uic tool not found: TOOL_$(tool)_UIC_UI_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_UIC_UI_CMDS)
+local more_output  := $(TOOL_$(tool)_UIC_UI_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_UIC_UI_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_UIC_UI_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_UIC_UI_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt3_target_pre_handle_ui_dx))
+
+endef # def_unit_qt3_src_handler_ui
+
+
+
+## wrapper for the MOC command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT3_MOC_HPP_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT3_MOC_HPP_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _UNIT_QT3_MOC_HPP_CMDS_DEP =
+endif
+
+##
+# def_unit_qt3_target_pre_handle_moc_hdr helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt3_target_pre_handle_moc_hdr_dx
+
+$(out) +| $(realout) $(more_output) $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT3_MOC_HPP_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,moc,$(target),$(source),$(realout))
+	$(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+	$(QUIET)$(CP) --changed -f $(out) $(realout)
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT3_MOC_HPP_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_INTERMEDIATES += $(realout)
+$(target)_GEN_SOURCES_ += $(realout)
+$(target)_OUT_FILES += $(out) $(realout) $(more_output) $(maybe_output)
+
+endef
+
+##
+# Handle a source file listed in QT_MOCHDRS.
+#
+# The files listed in QT_MOCHDRS uses the Q_OBJECT macro and we will
+# generate a .cpp file for each of them and add it to the generated
+# sources so that it's compiled and linked. (There is an alternative
+# way to do this where the .cpp file is included, this isn't currently
+# supported by this unit.)
+#
+# @remarks Invoked via $(evalvalctx ).
+define def_unit_qt3_target_pre_handle_moc_hdr
+local type      := MOC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local outbase   := $(qtmocdir)/$(notdir $(basename $(source)))
+local out       := $(outbase).tmp.cpp
+local realout   := $(outbase).cpp
+local dep       := $(realout).dep
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_MOC_HPP_CMDS
+ $(error kBuild: qt moc tool not found: TOOL_$(tool)_MOC_HPP_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_MOC_HPP_CMDS)
+local more_output  := $(TOOL_$(tool)_MOC_HPP_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_MOC_HPP_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_MOC_HPP_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_MOC_HPP_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt3_target_pre_handle_moc_hdr_dx))
+
+endef # def_unit_qt3_target_pre_handle_moc_hdr
+
+
+
+## wrapper for the MOC command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT3_MOC_CPP_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT3_MOC_CPP_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _UNIT_QT3_MOC_CPP_CMDS_DEP =
+endif
+
+##
+# def_unit_qt3_target_pre_handle_moc_src helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt3_target_pre_handle_moc_src_dx
+
+$(out) +| $(realout) $(more_output) $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT3_MOC_CPP_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,moc,$(target),$(source),$(realout))
+	$(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+	$(QUIET)$(CP) --changed -f $(out) $(realout)
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT3_MOC_CPP_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_INTERMEDIATES += $(realout)
+$(target)_OUT_FILES += $(out) $(realout) $(more_output) $(maybe_output)
+
+endef
+
+##
+# Handle a source file listed in QT_MOCSRCS.
+#
+# The files listed in QT_MOCSRCS uses the Q_OBJECT macro and will include
+# a .moc file that we're expected to generate here.
+#
+# @remarks Invoked via $(evalvalctx ).
+define def_unit_qt3_target_pre_handle_moc_src
+local type      := MOC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local outbase   := $(qtmocdir)/$(notdir $(basename $(source)))
+local out       := $(outbase).tmp.moc
+local realout   := $(outbase).moc
+local dep       := $(realout).dep
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+local incs      := $(abspathex $(incs),$(defpath))
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_MOC_CPP_CMDS
+ $(error kBuild: qt moc tool not found: TOOL_$(tool)_MOC_CPP_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_MOC_CPP_CMDS)
+local more_output  := $(TOOL_$(tool)_MOC_CPP_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_MOC_CPP_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_MOC_CPP_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_MOC_CPP_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt3_target_pre_handle_moc_src_dx))
+
+endef # def_unit_qt3_target_pre_handle_moc_src
+
+
+##
+# Adds sources containing Q_OBJECT to QT_MOCSRCS.
+define def_unit_qt3_target_pre_cpp_source
+ifneq ($(file-size $(source)),-1)
+ ifneq ($(strip $(shell $(SED) -f $(KBUILD_PATH)/units/qt-Q_OBJECT.sed $(source))),)
+  $(eval $(target)_QT_MOCSRCS += $(source))
+ endif
+endif
+endef # def_unit_qt3_target_pre_cpp_source
+
+
+##
+# Invoked early in the processing of a target that uses	the Qt unit.
+#
+# It will append the qt source handlers to the target (.h, .ui, .ts,
+# .png, .bmp, .gif).
+#
+# It will then check all the C++ sources and check which needs
+# a .moc files and generate rules and dependencies fofor these
+#
+define def_unit_qt3_target_pre
+
+# Make QTTOOL the default for the specific Qt tools instead of TOOL.
+ifneq ($($(target)_QTTOOL),)
+ ifeq ($($(target)_MOCTOOL),)
+  $(target)_MOCTOOL := $($(target)_QTTOOL)
+ endif
+ ifeq ($($(target)_UICTOOL),)
+  $(target)_UICTOOL := $($(target)_QTTOOL)
+ endif
+ ifeq ($($(target)_LRCTOOL),)
+  $(target)_LRCTOOL := $($(target)_QTTOOL)
+ endif
+endif
+
+# Deal with QT_MODULES and QT_PREFIX.
+local qt_prefix := $(firstword \
+	$($(target)_QT_PREFIX.$(bld_trg)) \
+ 	$($(target)_QT_PREFIX.$(bld_trg_arch)) \
+ 	$($(target)_QT_PREFIX.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_PREFIX.$(bld_trg_cpu)) \
+ 	$($(target)_QT_PREFIX.$(bld_type)) \
+ 	$($(target)_QT_PREFIX))
+ifeq ($(bld_trg),win)
+ local qt_lib := $(firstword $(wildcard \
+	$(PATH_SDK_QT3_LIB)/dynamic/$(qt_prefix)qt-mt3*$(SUFF_LIB) \
+	$(PATH_SDK_QT3_LIB)/$(qt_prefix)qt-mt3*$(SUFF_LIB) \
+	$(PATH_SDK_QT3_LIB)/dynamic/$(qt_prefix)qt-mt$(SUFF_LIB) \
+	$(PATH_SDK_QT3_LIB)/$(qt_prefix)qt-mt$(SUFF_LIB) \
+	$(PATH_SDK_QT3_LIB)/dynamic/$(qt_prefix)Qt3*$(SUFF_LIB) \
+	$(PATH_SDK_QT3_LIB)/$(qt_prefix)Qt3*$(SUFF_LIB) \
+	$(PATH_SDK_QT3_LIB)/dynamic/$(qt_prefix)Qt*$(SUFF_LIB) \
+	$(PATH_SDK_QT3_LIB)/$(qt_prefix)Qt*$(SUFF_LIB) \
+	) $(PATH_SDK_QT3_LIB)/$(qt_prefix)qt-mt$(SUFF_LIB) )
+ $(eval $(target)_LIBS    += $(qt_lib) )
+ ifeq ($(tool_do),LINK_PROGRAM)
+  local qt_main_lib := $(firstword $(wildcard \
+	$(PATH_SDK_QT3_LIB)/$(qt_prefix)qtmain$(SUFF_LIB) \
+	$(PATH_SDK_QT3_LIB)/qtmain$(SUFF_LIB) \
+	) $(PATH_SDK_QT3_LIB)/$(qt_prefix)qtmain$(SUFF_LIB) )
+  $(eval $(target)_LIBS   += $(qt_main_lib) )
+ endif
+else
+ local qt_lib := $(PATH_SDK_QT3_LIB)/lib$(qt_prefix)qt-mt$(SUFF_DLL)
+ $(eval $(target)_LIBS    += $(qt_lib) )
+endif
+$(eval $(target)_INCS     += $(PATH_SDK_QT3_INC) )
+
+# On Qt3 we will try pickup the QMAKE_PRL_DEFINES listed in the .prl file (in libs).
+local qt_prl := $(firstword $(wildcard \
+	$(patsubst %$(SUFF_DLL),%,$(patsubst %$(SUFF_LIB),%,$(qt_lib))).prl \
+	$(dir $(qt_lib))/$(qt_prefix)qt-mt.prl \
+	$(dir $(qt_lib))/*qt-mt*.prl \
+	$(dir $(qt_lib))/*qt*.prl \
+	))
+ifneq ($(qt_prl),)
+ include $(qt_prl)
+ $(eval $(target)_DEFS    += $(QMAKE_PRL_DEFINES))
+endif
+
+# Autodetect source files with Q_OBJECT references if QT_MOCSRCS is undefined. (slow)
+# Tip: Use target_QT_MOCSRCS = $(NO_SUCH_VARIABLE) to avoid this.
+ifndef $(target)_QT_MOCSRCS
+ $(foreach source, $(filter %.cxx %.CXX %.cpp %.CPP %.cc %.CC,\
+ 	$($(target)_SOURCES.$(bld_trg)) \
+ 	$($(target)_SOURCES.$(bld_trg_arch)) \
+ 	$($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_SOURCES.$(bld_trg_cpu)) \
+ 	$($(target)_SOURCES.$(bld_type)) \
+ 	$($(target)_SOURCES) \
+ 	), $(evalval def_unit_qt3_target_pre_cpp_source))
+endif
+
+# Install source handlers for .ui files.
+$(target)_SRC_HANDLERS += \
+	 .ui:def_unit_qt3_src_handler_ui \
+	 .UI:def_unit_qt3_src_handler_ui
+
+# Calc the MOC and UI output directories and add them to BLDDIRS and INCS.
+local qtmocdir := $(PATH_$(target))/qtmoc
+local qtuicdir := $(PATH_$(target))/qtuic
+local qtnlsdir := $(PATH_$(target))/qtnls
+$(eval $(target)_BLDDIRS += $(qtmocdir) $(qtuicdir) $(qtnlsdir) )
+$(eval $(target)_INCS    += $(qtmocdir) $(qtuicdir) )
+
+# Calc .ui sources so we can add them to the QT_MOCSRCS and QT_MOCHDRS.
+local ui_sources := $(notdir $(basename $(filter %.ui %.UI, \
+	$($(target)_SOURCES.$(bld_trg)) \
+ 	$($(target)_SOURCES.$(bld_trg_arch)) \
+ 	$($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_SOURCES.$(bld_trg_cpu)) \
+ 	$($(target)_SOURCES.$(bld_type)) \
+ 	$($(target)_SOURCES) \
+	)))
+#$(error ui_sources:=$(ui_sources))
+
+# Deal with QT_MOCSRCS.
+$(foreach source, \
+	$($(target)_QT_MOCSRCS.$(bld_trg)) \
+ 	$($(target)_QT_MOCSRCS.$(bld_trg_arch)) \
+ 	$($(target)_QT_MOCSRCS.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_MOCSRCS.$(bld_trg_cpu)) \
+ 	$($(target)_QT_MOCSRCS.$(bld_type)) \
+ 	$($(target)_QT_MOCSRCS) \
+	$(addsuffix .h,$(addprefix $(qtuicdir)/,$(notdir $(basename $(ui_sources))))) \
+	, $(evalvalctx def_unit_qt3_target_pre_handle_moc_src))
+
+# Deal with QT_MOCHDRS.
+$(foreach source, \
+	$($(target)_QT_MOCHDRS.$(bld_trg)) \
+ 	$($(target)_QT_MOCHDRS.$(bld_trg_arch)) \
+ 	$($(target)_QT_MOCHDRS.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_MOCHDRS.$(bld_trg_cpu)) \
+ 	$($(target)_QT_MOCHDRS.$(bld_type)) \
+ 	$($(target)_QT_MOCHDRS) \
+	$(addsuffix .h,$(addprefix $(qtuicdir)/,$(notdir $(basename $(ui_sources))))) \
+	, $(evalvalctx def_unit_qt3_target_pre_handle_moc_hdr))
+
+# Deal with QT_TRANSLATIONS.
+# ASSUMES (_ALL_)INSTALLS is processed after the targets using this unit.
+local translations := \
+	$($(target)_QT_TRANSLATIONS.$(bld_trg)) \
+ 	$($(target)_QT_TRANSLATIONS.$(bld_trg_arch)) \
+ 	$($(target)_QT_TRANSLATIONS.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_TRANSLATIONS.$(bld_trg_cpu)) \
+ 	$($(target)_QT_TRANSLATIONS.$(bld_type)) \
+ 	$($(target)_QT_TRANSLATIONS)
+ifneq ($(strip $(translations)),)
+ local expr := _ALL_INSTALLS += $(target)-inst-nls
+ $(eval $(expr))
+ ifdef $(target)_QT_TRANSLATIONS_TEMPLATE
+  $(target)-inst-nls_TEMPLATE := $($(target)_QT_TRANSLATIONS_TEMPLATE)
+ else
+  $(target)-inst-nls_MODE := 0644
+ endif
+ ifdef $(target)_QT_TRANSLATIONS_INST
+  $(target)-inst-nls_INST := $($(target)_QT_TRANSLATIONS_INST)
+ endif
+ $(target)-inst-nls_SOURCES :=
+ $(foreach source, $(translations)\
+	, $(evalvalctx def_unit_qt3_target_pre_handle_translation))
+endif
+
+endef # def_unit_qt3_target_pre
+
+
+#
+# Rule for debugging.
+#
+unit-qt3-show-vars:
+	@$(ECHO) 'The Qt3 SDK variables:'
+	@$(ECHO) '  PATH_SDK_QT3           = "$(PATH_SDK_QT3)"'
+	@$(ECHO) '  PATH_SDK_QT3_INC       = "$(PATH_SDK_QT3_INC)"'
+	@$(ECHO) '  PATH_SDK_QT3_LIB       = "$(PATH_SDK_QT3_LIB)"'
+	@$(ECHO) '  PATH_SDK_QT3_LIB.amd64 = "$(PATH_SDK_QT3_LIB.amd64)"'
+	@$(ECHO) '  PATH_SDK_QT3_LIB.x86   = "$(PATH_SDK_QT3_LIB.x86)"'
+	@$(ECHO) 'The Qt3 TOOL variables:'
+	@$(ECHO) '  PATH_TOOL_QT3_BIN      = "$(PATH_TOOL_QT3_BIN)"'
+	@$(ECHO) '  TOOL_QT3_BIN_SUFF      = "$(TOOL_QT3_BIN_SUFF)"'
+	@$(ECHO) '  TOOL_QT3_MOC           = "$(TOOL_QT3_MOC)"'
+	@$(ECHO) '  TOOL_QT3_UIC           = "$(TOOL_QT3_UIC)"'
+	@$(ECHO) '  TOOL_QT3_LRC           = "$(TOOL_QT3_LRC)"'
+	@$(ECHO) '  TOOL_QT3_LUPDATE       = "$(TOOL_QT3_LUPDATE)"'
+
Index: /tags/kBuild-0.1.4/kBuild/units/qt4.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/units/qt4.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/units/qt4.kmk	(revision 1780)
@@ -0,0 +1,1051 @@
+# $Id$
+## @file
+# Qt 4 unit.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+ifdef UNIT_qt4
+ $(error kBuild: The qt4 unit was included twice!)
+endif
+UNIT_qt4 = qt4
+
+
+ifndef UNIT_qt3
+ # Add our target properties (same as qt3).
+ PROPS_SINGLE += QTTOOL MOCTOOL UICTOOL LRCTOOL QT_TRANSLATIONS_INST QT_TRANSLATIONS_TEMPLATE QT_PREFIX
+ PROPS_ACCUMULATE_R += MOCDEFS MOCFLAGS UICFLAGS LRCFLAGS QT_TRANSLATIONS QT_MOCSRCS QT_MOCHDRS
+endif
+PROPS_SINGLE += RCCTOOL
+PROPS_ACCUMULATE_R += RCCFLAGS QT_MODULES
+
+
+## @todo use pkg-config?
+
+#
+# The QT4 SDK.
+#
+# This is implemented here rather than in sdks/QT4.kmk to enforce the global USES.
+# It also makes things easier to develop, with fewer files I mean.
+#
+## @todo the SDK might actually not be necessary as it turns out... For now it servers
+# a purpose if the host differs from the target, in theory at least.
+SDK_QT4 = Qt4
+
+# SDK Specific Properties
+#       PATH_SDK_QT4	       - The general Qt4 root directory.
+#       PATH_SDK_QT4_INC       - The include directory.
+#       PATH_SDK_QT4_LIB.amd64 - The lib directory for AMD64.
+#       PATH_SDK_QT4_LIB.x86   - The lib directory for X86.
+#       PATH_SDK_QT4_LIB       - The lib directory for KBUILD_TARGET.
+ifndef PATH_SDK_QT4
+ PATH_SDK_QT4 := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/qt/v4*)))
+ ifeq ($(PATH_SDK_QT4),)
+  # If target == host, try look for Qt in the various platform specific places.
+  ifeq ($(KBUILD_TARGET),$(KBUILD_HOST))
+   ifeq ($(KBUILD_TARGET),darwin)
+    PATH_SDK_QT4 := $(patsubst %/Frameworks/QtCore.framework/Versions/4,%,$(firstword $(wildcard /Library/Frameworks/QtCore.framework/Versions/4)))
+   else ifeq ($(KBUILD_TARGET),win)
+    # No idea here yet...
+   else ifeq ($(KBUILD_TARGET),ose)
+    # No port...
+   else
+    # The Unices. Includes and esp. libs are tricky, so override the PATH_SDK_QT4_LIB* stuff if it doesn't work.
+    # Try find the general root of thing by looking for the qt3to4 program, if not found, then look for rcc.
+    PATH_SDK_QT4 := $(patsubst %/bin/qt3to4,%,$(firstword $(wildcard \
+	/usr/bin/qt3to4 \
+    	/usr/local/bin/qt3to4 \
+	/usr/qt/4/bin/qt3to4 \
+	/usr/share/qt4/bin/qt3to4 \
+    	)))
+    ifeq ($(PATH_SDK_QT4),)
+     PATH_SDK_QT4 := $(patsubst %/bin/rcc,%,$(firstword $(wildcard \
+     	/usr/bin/rcc \
+	/usr/local/bin/rcc \
+     	/usr/qt/4/bin/rcc \
+     	/usr/share/qt4/bin/rcc \
+	)))
+    endif
+    ifneq ($(PATH_SDK_QT4),)
+     export PATH_SDK_QT4
+
+     # Locate the include files.
+     ifeq ($(PATH_SDK_QT4_INC),)
+      PATH_SDK_QT4_INC := $(patsubst %/QtCore/qglobal.h,%,$(firstword $(wildcard \
+	$(PATH_SDK_QT4)/include/QtCore/qglobal.h \
+	$(PATH_SDK_QT4)/include/qt4/QtCore/qglobal.h \
+	/usr/include/qt4/QtCore/qtglobal.h \
+	/usr/local/include/qt4/QtCore/qtglobal.h \
+	)))
+      ifneq ($(PATH_SDK_QT4_INC),)
+       export PATH_SDK_QT4_INC
+      endif
+     endif
+
+     # Now for the libraries (mostly for helping out finding the KBUILD_TARGET libs).
+     ifeq ($(PATH_SDK_QT4_LIB.x86),)
+      PATH_SDK_QT4_LIB.x86   := $(patsubst %/libQtCore$(SUFF_DLL),%,$(firstword $(wildcard \
+	$(PATH_SDK_QT4)/lib32/libQtCore$(SUFF_DLL) \
+	$(PATH_SDK_QT4)/lib32/qt4/libQtCore$(SUFF_DLL) \
+	/usr/lib32/libQtCore$(SUFF_DLL) \
+	/usr/lib32/qt4/libQtCore$(SUFF_DLL) \
+	/usr/local/lib32/libQtCore$(SUFF_DLL) \
+	/usr/local/lib32/qt4/libQtCore$(SUFF_DLL) \
+	$(PATH_SDK_QT4)/lib/libQtCore$(SUFF_DLL) \
+	$(PATH_SDK_QT4)/lib/qt4/libQtCore$(SUFF_DLL) \
+	)))
+      ifneq ($(PATH_SDK_QT4_LIB.x86),)
+       export PATH_SDK_QT4_LIB.x86
+      endif
+     endif
+     ifeq ($(PATH_SDK_QT4_LIB.amd64),)
+      PATH_SDK_QT4_LIB.amd64 := $(patsubst %/libQtCore$(SUFF_DLL),%,$(firstword $(wildcard \
+	$(PATH_SDK_QT4)/lib64/libQtCore$(SUFF_DLL) \
+	$(PATH_SDK_QT4)/lib64/qt4/libQtCore$(SUFF_DLL) \
+	$(PATH_SDK_QT4)/lib/amd64/libQtCore$(SUFF_DLL) \
+	/usr/lib64/libQtCore$(SUFF_DLL) \
+	/usr/lib64/qt4/libQtCore$(SUFF_DLL) \
+	/usr/lib/amd64/libQtCore$(SUFF_DLL) \
+	/usr/local/lib64/libQtCore$(SUFF_DLL) \
+	/usr/local/lib64/qt4/libQtCore$(SUFF_DLL) \
+	/usr/local/lib/amd64/libQtCore$(SUFF_DLL) \
+	$(PATH_SDK_QT4)/lib/libQtCore$(SUFF_DLL) \
+	$(PATH_SDK_QT4)/lib/qt4/libQtCore$(SUFF_DLL) \
+	)))
+      ifneq ($(PATH_SDK_QT4_LIB.amd64),)
+       export PATH_SDK_QT4_LIB.amd64
+      endif
+     endif
+
+     # And finally, the library path for KBUILD_TARGET.
+     ifeq ($(PATH_SDK_QT4_LIB),)
+      PATH_SDK_QT4_LIB := $(PATH_SDK_QT4_LIB.$(KBUILD_TARGET))
+      ifeq ($(PATH_SDK_QT4_LIB),)
+       PATH_SDK_QT4_LIB := $(patsubst %/libQtCore$(SUFF_DLL),%,$(firstword $(wildcard \
+       	$(PATH_SDK_QT4)/lib/libQtCore$(SUFF_DLL) \
+       	$(PATH_SDK_QT4)/lib/qt4/libQtCore$(SUFF_DLL) \
+       	/usr/lib/libQtCore$(SUFF_DLL) \
+       	/usr/lib/qt4/libQtCore$(SUFF_DLL) \
+       	/usr/local/lib/libQtCore$(SUFF_DLL) \
+       	/usr/local/lib/qt4/libQtCore$(SUFF_DLL) \
+       	)))
+      endif
+      ifneq ($(PATH_SDK_QT4_LIB),)
+       export PATH_SDK_QT4_LIB
+      endif
+     endif
+
+    endif
+   endif # Unices
+  endif
+  # Found it?
+  ifeq ($(PATH_SDK_QT4),)
+   $(warning kBuild: Couldn't find the Qt4 headers and libaries...)
+   PATH_SDK_QT4 := $(PATH_DEVTOOLS_TRG)/qt/not-found
+  endif
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_QT4 := $(PATH_SDK_QT4)
+endif
+
+# Libraries can be in either Frameworks or lib depending on how you
+# build it on the mac. The .dmg installs into Frameworks but builds into lib.
+ifeq ($(KBUILD_TARGET),darwin)
+ ifndef PATH_SDK_QT4_LIB
+  ifneq ($(wildcard $(PATH_SDK_QT4)/Frameworks),)
+   PATH_SDK_QT4_LIB ?= $(PATH_SDK_QT4)/Frameworks
+  else
+   PATH_SDK_QT4_LIB ?= $(PATH_SDK_QT4)/lib
+  endif
+ endif
+else
+ PATH_SDK_QT4_LIB ?= $(PATH_SDK_QT4)/lib
+ PATH_SDK_QT4_INC ?= $(PATH_SDK_QT4)/include
+endif
+
+# The bits that kBuild picks up.
+#  (nothing here)
+
+
+#
+# The QT4 tool.
+#
+# This is implemented here rather than in tools/QT4.kmk to enforce the global USES.
+# It also makes things easier to develop, with fewer files I mean.
+#
+TOOL_QT4 = Qt4
+
+# Tool Specific Properties
+#       PATH_TOOL_QT4     - Obsolete.
+#       PATH_TOOL_QT4_BIN - The
+#       TOOL_QT4_BIN_SUFF -
+if !defined(PATH_TOOL_QT4_BIN) && defined(PATH_TOOL_QT4)
+ PATH_TOOL_QT4_BIN := $(PATH_TOOL_QT4)/bin
+endif
+ifndef PATH_TOOL_QT4_BIN
+ PATH_TOOL_QT4_BIN := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/qt/v4*/bin)))
+ ifeq ($(PATH_TOOL_QT4_BIN),)
+  ifdef TOOL_QT4_BIN_SUFF
+   TOOL_QT4_BIN_SUFF := $(TOOL_QT4_BIN_SUFF)
+  endif
+  # Try looking for moc-qt4 / moc-$(suffix) first.
+  ifneq ($(TOOL_QT4_BIN_SUFF),)
+   PATH_TOOL_QT4_BIN := $(patsubst %/moc$(TOOL_QT4_BIN_SUFF),%,$(firstword $(wildcard \
+	 /usr/lib/qt4/bin/moc$(TOOL_QT4_BIN_SUFF) \
+	 /usr/qt/4/bin/moc$(TOOL_QT4_BIN_SUFF) \
+	 /usr/share/qt4/bin/moc$(TOOL_QT4_BIN_SUFF) \
+	 /usr/local/bin/moc$(TOOL_QT4_BIN_SUFF) \
+	 /usr/bin/moc$(TOOL_QT4_BIN_SUFF) \
+	 )))
+  else
+   PATH_TOOL_QT4_BIN := $(patsubst %/moc-qt4,%,$(firstword $(wildcard \
+	/usr/lib/qt4/bin/moc-qt4 \
+	/usr/qt/4/bin/moc-qt4 \
+	/usr/share/qt4/bin/moc-qt4 \
+	/usr/local/bin/moc-qt4 \
+	/usr/bin/moc-qt4 \
+	)))
+   ifneq ($(PATH_TOOL_QT4_BIN),)
+    TOOL_QT4_BIN_SUFF := -qt4
+   else
+    # If no luck, try looking for moc in the qt4 specific locations.
+    PATH_TOOL_QT4_BIN := $(patsubst %/moc,%,$(firstword $(wildcard \
+	/usr/lib/qt4/bin/moc \
+	/usr/qt/4/bin/moc \
+	/usr/share/qt4/bin/moc \
+	)))
+   endif
+  endif
+  # If still no go, try looking for qt3to4 and rcc.
+  ifeq ($(PATH_TOOL_QT4_BIN),)
+   PATH_TOOL_QT4_BIN := $(patsubst %/qt3to4,%,$(firstword $(wildcard \
+	/usr/lib/qt4/bin/qt3to4 \
+	/usr/qt/4/bin/qt3to4 \
+	/usr/share/qt4/bin/qt3to4 \
+	/usr/local/bin/qt3to4 \
+	/usr/bin/qt3to4 \
+	)))
+  endif
+  ifeq ($(PATH_TOOL_QT4_BIN),)
+   PATH_TOOL_QT4_BIN := $(patsubst %/rcc$(TOOL_QT4_BIN_SUFF),%,$(firstword $(wildcard \
+	/usr/lib/qt4/bin/rcc$(TOOL_QT4_BIN_SUFF) \
+	/usr/qt/4/bin/rcc$(TOOL_QT4_BIN_SUFF) \
+	/usr/share/qt4/bin/rcc$(TOOL_QT4_BIN_SUFF) \
+	/usr/local/bin/rcc$(TOOL_QT4_BIN_SUFF) \
+	/usr/bin/rcc$(TOOL_QT4_BIN_SUFF) \
+	)))
+  endif
+  if "$(PATH_TOOL_QT4_BIN)" == "" && "$(TOOL_QT4_BIN_SUFF)" != ""
+   PATH_TOOL_QT4_BIN := $(patsubst %/rcc,%,$(firstword $(wildcard \
+	/usr/lib/qt4/bin/rcc \
+	/usr/qt/4/bin/rcc \
+	/usr/share/qt4/bin/rcc \
+	/usr/local/bin/rcc \
+	/usr/bin/rcc \
+	)))
+  endif
+  ifneq ($(PATH_TOOL_QT4_BIN),)
+   export PATH_TOOL_QT4_BIN
+  endif
+ endif
+ # If not found, we'll enter the 'pathless' mode.
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_QT4_BIN := $(PATH_TOOL_QT4_BIN)
+endif
+ifneq ($(PATH_TOOL_QT4_BIN),)
+ TOOL_QT4_MOC       ?= $(PATH_TOOL_QT4_BIN)/moc$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT4_UIC       ?= $(PATH_TOOL_QT4_BIN)/uic$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+ ifndef TOOL_QT4_RCC
+  TOOL_QT4_RCC      := $(PATH_TOOL_QT4_BIN)/rcc$(HOST_SUFF_EXE)
+  ifeq ($(wildcard $(TOOL_QT4_RCC)),)
+   TOOL_QT4_RCC     := $(PATH_TOOL_QT4_BIN)/rcc$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+  endif
+ endif
+ TOOL_QT4_LRC       ?= $(PATH_TOOL_QT4_BIN)/lrelease$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT4_LUPDATE   ?= $(PATH_TOOL_QT4_BIN)/lupdate$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+else
+ # Pathless, relies on the environment.
+ TOOL_QT4_MOC       ?= moc$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT4_UIC       ?= uic$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT4_RCC       ?= rcc$(HOST_SUFF_EXE)
+ TOOL_QT4_LRC       ?= lrelease$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+ TOOL_QT4_LUPDATE   ?= lupdate$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE)
+endif
+
+# General Properties used by kBuild and/or units/qt.kmk
+TOOL_QT4_MOCFLAGS           ?=
+TOOL_QT4_MOCINCS            ?=
+TOOL_QT4_MOCDEFS            ?=
+TOOL_QT4_MOCDEFS.darwin     ?= __APPLE__ __GNUC__
+TOOL_QT4_MOCDEFS.solaris    ?= __sun
+TOOL_QT4_MOCDEFS.win.amd64  ?= WIN64
+TOOL_QT4_MOCDEFS.win.x86    ?= WIN32
+
+
+## MOC a C++ source file.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions.
+# @param    $(incs)     Includes.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_QT4_MOC_CPP_DEPEND =
+TOOL_QT4_MOC_CPP_DEPORD =
+TOOL_QT4_MOC_CPP_OUTPUT =
+TOOL_QT4_MOC_CPP_OUTPUT_MAYBE =
+define TOOL_QT4_MOC_CPP_CMDS
+	$(QUIET)$(TOOL_QT4_MOC)\
+		$(flags)\
+		$(addprefix -I, $(incs))\
+		$(addprefix -D, $(defs))\
+		-o $(out)\
+		$(source)
+endef
+
+## MOC a C++ header file.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions.
+# @param    $(incs)     Includes.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_QT4_MOC_HPP_DEPEND =
+TOOL_QT4_MOC_HPP_DEPORD =
+TOOL_QT4_MOC_HPP_OUTPUT =
+TOOL_QT4_MOC_HPP_OUTPUT_MAYBE =
+define TOOL_QT4_MOC_HPP_CMDS
+	$(QUIET)$(TOOL_QT4_MOC)\
+		$(flags)\
+		$(addprefix -I, $(incs))\
+		$(addprefix -D, $(defs))\
+		-o $(out)\
+		$(source)
+endef
+
+## Compile a Qt user interface file (.ui).
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions.
+# @param    $(incs)     Includes.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_QT4_UIC_UI_DEPEND =
+TOOL_QT4_UIC_UI_DEPORD =
+TOOL_QT4_UIC_UI_OUTPUT =
+TOOL_QT4_UIC_UI_OUTPUT_MAYBE =
+define TOOL_QT4_UIC_UI_CMDS
+	$(QUIET)$(TOOL_QT4_UIC)\
+		$(flags)\
+		-o $(out)\
+		$(source)
+endef
+
+## Compile a Qt resource file (.qrc).
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions.
+# @param    $(incs)     Includes.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+# @remarks  The sed script generating the dependency file is a bit naive.
+TOOL_QT4_RCC_QRC_DEPEND =
+TOOL_QT4_RCC_QRC_DEPORD =
+TOOL_QT4_RCC_QRC_OUTPUT =
+TOOL_QT4_RCC_QRC_OUTPUT_MAYBE =
+define TOOL_QT4_RCC_QRC_CMDS
+	$(QUIET)$(TOOL_QT4_RCC)\
+		$(flags)\
+		-o $(out)\
+		$(source)
+	$(APPEND) $(dep) '\'
+	$(APPEND) $(dep) '$(out): \'
+	$(APPEND) $(dep) '$(source) \'
+	$(SED) \
+		-e '/^[[:blank:]]*<file[[:blank:]][^>]*>/!d' \
+		-e 's/^.*<file[[:blank:]][^>]*>\([^<]*\)<\/file>.*$$$$/\1/' \
+		-e 's|^[^/]|$(abspathex $(dir $(source)),$(defpath))/&|' \
+		-e 's|$$$$| \\|' \
+		--append $(dep) \
+		$(source)
+	$(APPEND) $(dep)
+	$(SED) \
+		-e '/^[[:blank:]]*<file[[:blank:]][^>]*>/!d' \
+		-e 's/^.*<file[[:blank:]][^>]*>\([^<]*\)<\/file>.*$$$$/\1/' \
+		-e 's|^[^/]|$(abspathex $(dir $(source)),$(defpath))/&|' \
+		-e 's|$$$$|:\n|' \
+		--append $(dep) \
+		$(source)
+	$(APPEND) $(dep)
+endef
+
+## Compile a Qt translation file (.ts).
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(out)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This may be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions.
+# @param    $(incs)     Includes.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_QT4_LRC_TS_DEPEND =
+TOOL_QT4_LRC_TS_DEPORD =
+TOOL_QT4_LRC_TS_OUTPUT =
+TOOL_QT4_LRC_TS_OUTPUT_MAYBE =
+define TOOL_QT4_LRC_TS_CMDS
+	$(QUIET)$(TOOL_QT4_LRC)\
+		$(flags)\
+		$(source)\
+		-qm $(out)
+endef
+
+
+
+#
+#
+# Back to the Qt4 unit.
+#
+#
+
+
+## wrapper for the lrelease (LRC) command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT4_LRC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_LRC_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _UNIT_QT4_LRC_CMDS_DEP =
+endif
+
+##
+# def_unit_qt4_target_pre_handle_translation helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt4_target_pre_handle_translation_dx
+
+$(out) + $(more_output) +| $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT4_LRC_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,lrelease,$(target),$(source),$$@)
+	$(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_LRC_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_OUT_FILES += $(out) $(more_output) $(maybe_output)
+$(target)-inst-nls_SOURCES += $(out)
+
+endef # def_unit_qt4_target_pre_handle_translation_dx
+
+##
+# Handle a source file listed in QT_TRANSLATIONS.
+#
+# The files listed in QT_TRANSLATIONS are translation files (.ts) which needs
+# to be translated into .qm files that are loadble by Qt.
+#
+# @remarks Invoked via $(evalvalctx ).
+define def_unit_qt4_target_pre_handle_translation
+local type      := LRC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local qtnlsdir  := $(PATH_$(target))/qtnls
+local outbase   := $(qtnlsdir)/$(notdir $(basename $(source)))
+local out       := $(outbase).qm
+local dep       := $(out).dep
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+local incs      := $(abspathex $(incs),$(defpath))
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_LRC_TS_CMDS
+ $(error kBuild: qt lrelease tool not found: TOOL_$(tool)_LRC_TS_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_LRC_TS_CMDS)
+local more_output  := $(TOOL_$(tool)_LRC_TS_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_LRC_TS_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_LRC_TS_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_LRC_TS_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt4_target_pre_handle_translation_dx))
+
+endef # def_unit_qt4_target_pre_handle_translation
+
+
+
+## wrapper for the UIC command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT4_RCC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_RCC_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _UNIT_QT4_RCC_CMDS_DEP =
+endif
+
+##
+# def_unit_qt4_target_pre_handle_qrc helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt4_target_pre_handle_rcc_dx
+
+$(out) +| $(realout) $(more_output) $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT4_RCC_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,rcc,$(target),$(source),$$@)
+	$(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+	$(QUIET)$(CP) --changed -f $(out) $(realout)
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_RCC_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_INTERMEDIATES += $(realout)
+$(target)_GEN_SOURCES_ += $(realout)
+$(target)_OUT_FILES += $(out) $(realout) $(more_output) $(maybe_output)
+
+endef # def_unit_qt4_target_pre_handle_rcc_dx
+
+##
+# Source handler for .qrc sources (Qt resource files).
+#
+# @remarks $(evalvalctx me).
+define def_unit_qt4_src_handler_qrc
+local type      := RCC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local qtrccdir  := $(PATH_$(target))/qtrcc
+local outbase   := $(qtrccdir)/$(notdir $(basename $(source)))
+local out       := $(outbase).tmp.gen.cpp
+local realout   := $(outbase).gen.cpp
+local dep       := $(realout).dep
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+local incs      := $(abspathex $(incs),$(defpath))
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_RCC_QRC_CMDS
+ $(error kBuild: qt rcc tool not found: TOOL_$(tool)_RCC_QRC_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_RCC_QRC_CMDS)
+local more_output  := $(TOOL_$(tool)_RCC_QRC_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_RCC_QRC_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_RCC_QRC_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_RCC_QRC_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt4_target_pre_handle_rcc_dx))
+
+endef # def_unit_qt4_src_handler_qrc
+
+
+
+## wrapper for the UIC command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT4_UIC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_UIC_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _UNIT_QT4_UIC_CMDS_DEP =
+endif
+
+##
+# def_unit_qt4_src_handler_ui helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt4_target_pre_handle_ui_dx
+
+$(out) +| $(realout) $(more_output) $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT4_UIC_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,uic,$(target),$(source),$$@)
+	$(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+	$(QUIET)$(CP) --changed -f $(out) $(realout)
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_UIC_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_INTERMEDIATES += $(realout)
+$(target)_OUT_FILES += $(out) $(realout) $(more_output) $(maybe_output)
+
+endef # def_unit_qt4_target_pre_handle_ui_dx
+
+##
+# Source handler for .ui sources.
+#
+# @remarks $(evalvalctx me).
+define def_unit_qt4_src_handler_ui
+local type      := UIC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local qtuicdir  := $(PATH_$(target))/qtuic
+local outbase   := $(qtuicdir)/$(notdir $(basename $(source)))
+local out       := $(outbase).tmp.gen.h
+local realout   := $(outbase).gen.h
+local dep       := $(realout).dep
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+local incs      := $(abspathex $(incs),$(defpath))
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_UIC_UI_CMDS
+ $(error kBuild: qt uic tool not found: TOOL_$(tool)_UIC_UI_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_UIC_UI_CMDS)
+local more_output  := $(TOOL_$(tool)_UIC_UI_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_UIC_UI_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_UIC_UI_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_UIC_UI_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt4_target_pre_handle_ui_dx))
+
+endef # def_unit_qt4_src_handler_ui
+
+
+
+## wrapper for the MOC command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT4_MOC_HPP_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_MOC_HPP_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _UNIT_QT4_MOC_HPP_CMDS_DEP =
+endif
+
+##
+# def_unit_qt4_target_pre_handle_moc_hdr helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt4_target_pre_handle_moc_hdr_dx
+
+$(out) +| $(realout) $(more_output) $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT4_MOC_HPP_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,moc,$(target),$(source),$$@)
+	$(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+	$(QUIET)$(CP) --changed -f $(out) $(realout)
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_MOC_HPP_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_INTERMEDIATES += $(realout)
+$(target)_GEN_SOURCES_ += $(realout)
+$(target)_OUT_FILES += $(out) $(realout) $(more_output) $(maybe_output)
+
+endef
+
+##
+# Handle a source file listed in QT_MOCHDRS.
+#
+# The files listed in QT_MOCHDRS uses the Q_OBJECT macro and we will
+# generate a .cpp file for each of them and add it to the generated
+# sources so that it's compiled and linked. (There is an alternative
+# way to do this where the .cpp file is included, this isn't currently
+# supported by this unit.)
+#
+# @remarks Invoked via $(evalvalctx ).
+define def_unit_qt4_target_pre_handle_moc_hdr
+local type      := MOC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local outbase   := $(qtmocdir)/$(notdir $(basename $(source)))
+local out       := $(outbase).tmp.cpp
+local realout   := $(outbase).cpp
+local dep       := $(realout).dep
+local defs      := $(kb-src-prop DEFS,dummy_var,left-to-right)
+local incs      := $(kb-src-prop INCS,dummy_var,right-to-left)
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+local incs      := $(abspathex $(incs),$(defpath))
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_MOC_HPP_CMDS
+ $(error kBuild: qt moc tool not found: TOOL_$(tool)_MOC_HPP_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_MOC_HPP_CMDS)
+local more_output  := $(TOOL_$(tool)_MOC_HPP_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_MOC_HPP_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_MOC_HPP_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_MOC_HPP_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt4_target_pre_handle_moc_hdr_dx))
+
+endef # def_unit_qt4_target_pre_handle_moc_hdr
+
+
+## wrapper for the MOC command dependencies.
+ifndef NO_COMPILE_CMDS_DEPS
+ _UNIT_QT4_MOC_CPP_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_MOC_CPP_CMDS_PREV_),$$(commands $(out)),FORCE)
+else
+ _UNIT_QT4_MOC_CPP_CMDS_DEP =
+endif
+
+##
+# def_unit_qt4_target_pre_handle_moc_src helper that is expanded before evaluation.
+#
+# This is necessary to resolve reference to local variables before doing
+# assignments and setting up commands. They would otherwise be resolved
+# later in a different context and the result would be completely wrong.
+#
+define def_unit_qt4_target_pre_handle_moc_src_dx
+
+$(out) +| $(realout) $(more_output) $(maybe_output): \
+		$(deps) \
+		$(value _UNIT_QT4_MOC_CPP_CMDS_DEP) \
+		| \
+		$(orderdeps)
+	%$$(call MSG_TOOL,moc,$(target),$(source),$$@)
+	$(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep)
+
+$(cmds)
+
+	$(QUIET)$(CP) --changed -f $(out) $(realout)
+ifndef NO_COMPILE_CMDS_DEPS
+	%$$(QUIET2)$$(APPEND) '$(dep)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_MOC_CPP_CMDS_PREV_'
+	%$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)'
+	%$$(QUIET2)$$(APPEND) '$(dep)' 'endef'
+endif
+
+$(target)_INTERMEDIATES += $(realout)
+$(target)_OUT_FILES += $(out) $(realout) $(more_output) $(maybe_output)
+
+endef
+
+##
+# Handle a source file listed in QT_MOCSRCS.
+#
+# The files listed in QT_MOCSRCS uses the Q_OBJECT macro and will include
+# a .moc file that we're expected to generate here.
+#
+# @remarks Invoked via $(evalvalctx ).
+define def_unit_qt4_target_pre_handle_moc_src
+local type      := MOC
+
+# fetch the properties.
+local tool      := $(kb-src-tool dummy_var)
+local outbase   := $(qtmocdir)/$(notdir $(basename $(source)))
+local out       := $(outbase).tmp.moc
+local realout   := $(outbase).moc
+local dep       := $(realout).dep
+local defs      := $(kb-src-prop DEFS,dummy_var,left-to-right)
+local incs      := $(kb-src-prop INCS,dummy_var,right-to-left)
+local flags     := $(kb-src-prop FLAGS,dummy_var,right-to-left)
+local deps      := $(kb-src-prop DEPS,dummy_var,left-to-right)
+local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right)
+
+# default path + source dep.
+ifneq ($(defpath),)
+local source    := $(abspathex $(source),$(defpath))
+local deps      := $(abspathex $(deps),$(defpath)) $(source)
+local incs      := $(abspathex $(incs),$(defpath))
+else
+local deps      += $(source)
+endif
+
+# call the tool
+ifndef TOOL_$(tool)_MOC_CPP_CMDS
+ $(error kBuild: qt moc tool not found: TOOL_$(tool)_MOC_CPP_CMDS)
+endif
+local cmds         := $(TOOL_$(tool)_MOC_CPP_CMDS)
+local more_output  := $(TOOL_$(tool)_MOC_CPP_OUTPUT)
+local maybe_output := $(TOOL_$(tool)_MOC_CPP_OUTPUT_MAYBE)
+local deps         += $(TOOL_$(tool)_MOC_CPP_DEPEND)
+local orderdeps    += $(TOOL_$(tool)_MOC_CPP_DEPORD)
+
+# generate the link rule and update some source and target variables.
+ifndef NO_COMPILE_CMDS_DEPS
+ $(eval includedep $(dep))
+endif
+$(eval $(def_unit_qt4_target_pre_handle_moc_src_dx))
+
+endef # def_unit_qt4_target_pre_handle_moc_src
+
+
+##
+# Adds sources containing Q_OBJECT to QT_MOCSRCS.
+define def_unit_qt4_target_pre_cpp_source
+ifneq ($(file-size $(source)),-1)
+ ifneq ($(strip $(shell $(SED) -f $(KBUILD_PATH)/units/qt-Q_OBJECT.sed $(source))),)
+  $(eval $(target)_QT_MOCSRCS += $(source))
+ endif
+endif
+endef # def_unit_qt4_target_pre_cpp_source
+
+##
+# Invoked early in the processing of a target that uses	the Qt unit.
+#
+# It will append the qt source handlers to the target (.h, .ui, .ts,
+# .png, .bmp, .gif).
+#
+# It will then check all the C++ sources and check which needs
+# a .moc files and generate rules and dependencies fofor these
+#
+define def_unit_qt4_target_pre
+
+# Make QTTOOL the default for the specific Qt tools instead of TOOL.
+ifneq ($($(target)_QTTOOL),)
+ ifeq ($($(target)_MOCTOOL),)
+  $(target)_MOCTOOL := $($(target)_QTTOOL)
+ endif
+ ifeq ($($(target)_UICTOOL),)
+  $(target)_UICTOOL := $($(target)_QTTOOL)
+ endif
+ ifeq ($($(target)_RCCTOOL),)
+  $(target)_RCCTOOL := $($(target)_QTTOOL)
+ endif
+ ifeq ($($(target)_LRCTOOL),)
+  $(target)_LRCTOOL := $($(target)_QTTOOL)
+ endif
+endif
+
+# Deal with QT_MODULES and QT_PREFIX.
+local qt_modules := \
+	$($(target)_QT_MODULES.$(bld_trg)) \
+ 	$($(target)_QT_MODULES.$(bld_trg_arch)) \
+ 	$($(target)_QT_MODULES.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_MODULES.$(bld_trg_cpu)) \
+ 	$($(target)_QT_MODULES.$(bld_type)) \
+ 	$($(target)_QT_MODULES)
+local qt_prefix := $(firstword \
+	$($(target)_QT_PREFIX.$(bld_trg)) \
+ 	$($(target)_QT_PREFIX.$(bld_trg_arch)) \
+ 	$($(target)_QT_PREFIX.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_PREFIX.$(bld_trg_cpu)) \
+ 	$($(target)_QT_PREFIX.$(bld_type)) \
+ 	$($(target)_QT_PREFIX))
+ifeq ($(bld_trg),darwin)
+ # Adding -F to CXXFLAGS is necessary to make #include <QtCore/qstring.h> stuff work...
+ $(eval $(target)_CXXFLAGS += -F$(PATH_SDK_QT4_LIB) )
+ $(eval $(target)_LDFLAGS  += -F$(PATH_SDK_QT4_LIB) $(addprefix -framework Qt$(qt_prefix),$(qt_modules)) )
+ $(eval $(target)_INCS     += $(foreach module,$(qt_modules), $(PATH_SDK_QT4_LIB)/$(qt_prefix)Qt$(module).framework/Versions/4/Headers) )
+else
+ ifeq ($(bld_trg),win)
+  $(eval $(target)_LIBS    += $(foreach module,$(qt_modules), $(PATH_SDK_QT4_LIB)/$(qt_prefix)Qt$(module)4$(SUFF_LIB)) )
+  ifeq ($(tool_do),LINK_PROGRAM)
+   $(eval $(target)_LIBS   += $(PATH_SDK_QT4_LIB)/$(qt_prefix)qtmain$(SUFF_LIB) )
+  endif
+ else
+  $(eval $(target)_LIBS    += $(foreach module,$(qt_modules), $(PATH_SDK_QT4_LIB)/lib$(qt_prefix)Qt$(module)$(SUFF_DLL)) )
+ endif
+ $(eval $(target)_INCS     += $(addprefix $(PATH_SDK_QT4_INC)/Qt,$(qt_modules)) $(PATH_SDK_QT4_INC) )
+endif
+$(eval $(target)_DEFS      += $(foreach module,$(toupper $(qt_modules)), QT_$(module)_LIB) )
+
+
+# Autodetect source files with Q_OBJECT references if QT_MOCSRCS is undefined. (slow)
+# Tip: Use target_QT_MOCSRCS = $(NO_SUCH_VARIABLE) to avoid this.
+ifndef $(target)_QT_MOCSRCS
+ $(foreach source, $(filter %.cxx %.CXX %.cpp %.CPP %.cc %.CC,\
+ 	$($(target)_SOURCES.$(bld_trg)) \
+ 	$($(target)_SOURCES.$(bld_trg_arch)) \
+ 	$($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_SOURCES.$(bld_trg_cpu)) \
+ 	$($(target)_SOURCES.$(bld_type)) \
+ 	$($(target)_SOURCES) \
+ 	), $(evalval def_unit_qt4_target_pre_cpp_source))
+endif
+
+# Install source handlers for .ui files.
+$(target)_SRC_HANDLERS += \
+	 .ui:def_unit_qt4_src_handler_ui \
+	 .UI:def_unit_qt4_src_handler_ui \
+	.qrc:def_unit_qt4_src_handler_qrc \
+	.qrc:def_unit_qt4_src_handler_qrc
+
+# Calc the MOC and UI output directories and add them to BLDDIRS and INCS.
+local qtmocdir := $(PATH_$(target))/qtmoc
+local qtuicdir := $(PATH_$(target))/qtuic
+local qtrccdir := $(PATH_$(target))/qtrcc
+local qtnlsdir := $(PATH_$(target))/qtnls
+$(eval $(target)_BLDDIRS += $(qtmocdir) $(qtuicdir) $(qtrccdir) $(qtnlsdir))
+$(eval $(target)_INCS    += $(qtmocdir) $(qtuicdir))
+
+# Deal with QT_MOCSRCS.
+$(foreach source, \
+	$($(target)_QT_MOCSRCS.$(bld_trg)) \
+ 	$($(target)_QT_MOCSRCS.$(bld_trg_arch)) \
+ 	$($(target)_QT_MOCSRCS.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_MOCSRCS.$(bld_trg_cpu)) \
+ 	$($(target)_QT_MOCSRCS.$(bld_type)) \
+ 	$($(target)_QT_MOCSRCS) \
+	, $(evalvalctx def_unit_qt4_target_pre_handle_moc_src))
+
+# Deal with QT_MOCHDRS.
+$(foreach source, \
+	$($(target)_QT_MOCHDRS.$(bld_trg)) \
+ 	$($(target)_QT_MOCHDRS.$(bld_trg_arch)) \
+ 	$($(target)_QT_MOCHDRS.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_MOCHDRS.$(bld_trg_cpu)) \
+ 	$($(target)_QT_MOCHDRS.$(bld_type)) \
+ 	$($(target)_QT_MOCHDRS) \
+	, $(evalvalctx def_unit_qt4_target_pre_handle_moc_hdr))
+
+# Deal with QT_TRANSLATIONS.
+# ASSUMES (_ALL_)INSTALLS is processed after the targets using this unit.
+local translations := \
+	$($(target)_QT_TRANSLATIONS.$(bld_trg)) \
+ 	$($(target)_QT_TRANSLATIONS.$(bld_trg_arch)) \
+ 	$($(target)_QT_TRANSLATIONS.$(bld_trg).$(bld_trg_arch)) \
+ 	$($(target)_QT_TRANSLATIONS.$(bld_trg_cpu)) \
+ 	$($(target)_QT_TRANSLATIONS.$(bld_type)) \
+ 	$($(target)_QT_TRANSLATIONS)
+ifneq ($(strip $(translations)),)
+ local expr := _ALL_INSTALLS += $(target)-inst-nls
+ $(eval $(expr))
+ ifdef $(target)_QT_TRANSLATIONS_TEMPLATE
+  $(target)-inst-nls_TEMPLATE := $($(target)_QT_TRANSLATIONS_TEMPLATE)
+ else
+  $(target)-inst-nls_MODE := 0644
+ endif
+ ifdef $(target)_QT_TRANSLATIONS_INST
+  $(target)-inst-nls_INST := $($(target)_QT_TRANSLATIONS_INST)
+ endif
+ $(target)-inst-nls_SOURCES :=
+ $(foreach source, $(translations)\
+	, $(evalvalctx def_unit_qt4_target_pre_handle_translation))
+endif
+
+endef # def_unit_qt4_target_pre
+
+
+#
+# Rule for debugging.
+#
+unit-qt4-show-vars:
+	@$(ECHO) 'The Qt4 SDK variables:'
+	@$(ECHO) '  PATH_SDK_QT4           = "$(PATH_SDK_QT4)"'
+	@$(ECHO) '  PATH_SDK_QT4_INC       = "$(PATH_SDK_QT4_INC)"'
+	@$(ECHO) '  PATH_SDK_QT4_LIB       = "$(PATH_SDK_QT4_LIB)"'
+	@$(ECHO) '  PATH_SDK_QT4_LIB.amd64 = "$(PATH_SDK_QT4_LIB.amd64)"'
+	@$(ECHO) '  PATH_SDK_QT4_LIB.x86   = "$(PATH_SDK_QT4_LIB.x86)"'
+	@$(ECHO) 'The Qt4 TOOL variables:'
+	@$(ECHO) '  PATH_TOOL_QT4_BIN      = "$(PATH_TOOL_QT4_BIN)"'
+	@$(ECHO) '  TOOL_QT4_BIN_SUFF      = "$(TOOL_QT4_BIN_SUFF)"'
+	@$(ECHO) '  TOOL_QT4_MOC           = "$(TOOL_QT4_MOC)"'
+	@$(ECHO) '  TOOL_QT4_UIC           = "$(TOOL_QT4_UIC)"'
+	@$(ECHO) '  TOOL_QT4_RCC           = "$(TOOL_QT4_RCC)"'
+	@$(ECHO) '  TOOL_QT4_LRC           = "$(TOOL_QT4_LRC)"'
+	@$(ECHO) '  TOOL_QT4_LUPDATE       = "$(TOOL_QT4_LUPDATE)"'
+
Index: /tags/kBuild-0.1.4/kBuild/up.kmk
===================================================================
--- /tags/kBuild-0.1.4/kBuild/up.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/kBuild/up.kmk	(revision 1780)
@@ -0,0 +1,68 @@
+# $Id$
+## @file
+# kBuild - File included at top of a up forwarder makefile.
+#          This method is DEPRECATED. Use Makefile.kup files instead.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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 source of the License, or
+# (at your option) any later version.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite typetype0, Boston, MA  0sourcetargettargettarget-targettype07  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the 
+# resulting makefile, program or whatever to be covered by the GPL license. 
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+
+# include the header to get the right MAKE and to include config.kmk
+# files since these may contain global goals.
+include $(PATH_KBUILD)/header.kmk
+
+UP_TO ?= ..
+
+# typical kbuild goals.
+all_recursive \
+binaries \
+clean \
+dlls \
+libraries \
+needed \
+nothing \
+objects \
+others \
+packing \
+pass_binaries \
+pass_clean \
+pass_dlls \
+pass_needed \
+pass_nothing \
+pass_others \
+pass_packing \
+programs \
+rebuild \
+sysmods \
+target \
+	:
+	$(MAKE) -C $(UP_TO) $@
+
+# the syntax checkers.
+%.o %.obj:
+	$(MAKE) -C $(UP_TO) $@
+
Index: /tags/kBuild-0.1.4/src/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/Makefile.kmk	(revision 1780)
@@ -0,0 +1,40 @@
+# $Id$
+## @file
+# Sub-makefile for the source directory.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ..
+include $(KBUILD_PATH)/subheader.kmk
+
+include $(PATH_SUB_CURRENT)/lib/Makefile.kmk
+include $(PATH_SUB_CURRENT)/sed/Makefile.kmk
+include $(PATH_SUB_CURRENT)/kmk/Makefile.kmk
+ifneq ($(KBUILD_TARGET),win)
+ include $(PATH_SUB_CURRENT)/ash/Makefile.kmk
+endif
+include $(PATH_SUB_CURRENT)/kDepPre/Makefile.kmk
+include $(PATH_SUB_CURRENT)/kObjCache/Makefile.kmk
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
Index: /tags/kBuild-0.1.4/src/ash/Makefile
===================================================================
--- /tags/kBuild-0.1.4/src/ash/Makefile	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/Makefile	(revision 1780)
@@ -0,0 +1,79 @@
+#	$NetBSD: Makefile,v 1.80 2005/06/26 19:10:49 christos Exp $
+#	@(#)Makefile	8.4 (Berkeley) 5/5/95
+
+.include <bsd.own.mk>
+
+YHEADER=1
+PROG=	sh
+SHSRCS=	alias.c cd.c echo.c error.c eval.c exec.c expand.c \
+	histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
+	mystring.c options.c parser.c redir.c show.c trap.c output.c var.c \
+	test.c kill.c syntax.c
+GENSRCS=arith.c arith_lex.c builtins.c init.c nodes.c
+GENHDRS=arith.h builtins.h nodes.h token.h
+SRCS=	${SHSRCS} ${GENSRCS}
+
+DPSRCS+=${GENHDRS}
+
+LDADD+=	-ll -ledit -ltermcap
+DPADD+=	${LIBL} ${LIBEDIT} ${LIBTERMCAP}
+
+LFLAGS=	-8	# 8-bit lex scanner for arithmetic
+YFLAGS=	-d
+
+# The .depend file can get references to these temporary files
+.OPTIONAL: lex.yy.c y.tab.c
+
+.ifdef CRUNCHEDPROG
+LFLAGS+=-L
+YFLAGS+=-l
+.endif
+
+CPPFLAGS+=-DSHELL -I. -I${.CURDIR}
+#XXX: For testing only.
+#CPPFLAGS+=-DDEBUG=1
+#CFLAGS+=-funsigned-char
+#TARGET_CHARFLAG?= -DTARGET_CHAR="unsigned char" -funsigned-char
+
+.ifdef SMALLPROG
+CPPFLAGS+=-DSMALL
+.else
+SRCS+=printf.c
+.endif
+
+.PATH:	${.CURDIR}/bltin ${NETBSDSRCDIR}/bin/test \
+	${NETBSDSRCDIR}/usr.bin/printf \
+	${NETBSDSRCDIR}/bin/kill
+
+CLEANFILES+= ${GENSRCS} ${GENHDRS} y.tab.h
+CLEANFILES+= trace
+
+token.h: mktokens
+	${_MKTARGET_CREATE}
+	${HOST_SH} ${.ALLSRC}
+
+builtins.h: builtins.c
+	${_MKTARGET_CREATE}
+
+builtins.c: mkbuiltins shell.h builtins.def
+	${_MKTARGET_CREATE}
+	${HOST_SH} ${.ALLSRC} ${.OBJDIR}
+	[ -f builtins.h ]
+
+init.c: mkinit.sh ${SHSRCS}
+	${_MKTARGET_CREATE}
+	${HOST_SH} ${.ALLSRC}
+
+nodes.h: nodes.c
+
+nodes.c: mknodes.sh nodetypes nodes.c.pat
+	${_MKTARGET_CREATE}
+	${HOST_SH} ${.ALLSRC} ${.OBJDIR}
+	[ -f nodes.h ]
+
+.if ${USETOOLS} == "yes"
+COMPATOBJDIR!=	cd ${NETBSDSRCDIR}/tools/compat && ${PRINTOBJDIR}
+NBCOMPATLIB=	-L${COMPATOBJDIR} -lnbcompat
+.endif
+
+.include <bsd.prog.mk>
Index: /tags/kBuild-0.1.4/src/ash/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/ash/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/Makefile.kmk	(revision 1780)
@@ -0,0 +1,201 @@
+# $Id: Makefile.kmk 785 2007-01-24 22:21:56Z bird $
+## @file
+# Sub-makefile for kmk_ash.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#INSTALLS = ash.man
+
+PROGRAMS += kmk_ash
+kmk_ash_TEMPLATE = BIN
+kmk_ash_DEFS = lint SHELL SMALL KMK
+kmk_ash_DEFS.linux = BSD
+kmk_ash_DEFS.solaris = BSD
+kmk_ash_DEFS.win = \
+	BSD PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS PC_SLASHES
+kmk_ash_DEFS.os2 = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME \
+	EXEC_HASH_BANG_SCRIPT PC_OS2_LIBPATHS PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS PC_SLASHES
+kmk_ash_DEFS.darwin = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
+kmk_ash_DEFS.dragonfly = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
+kmk_ash_DEFS.freebsd = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
+kmk_ash_INCS = $(PATH_kmk_ash) . # (the last is because of error.h)
+kmk_ash_CFLAGS.win = -I. ## @todo kBuild bug?
+kmk_ash_INCS.win = win
+kmk_ash_SOURCES = \
+	alias.c \
+	cd.c \
+	error.c \
+	eval.c \
+	exec.c \
+	expand.c \
+	histedit.c \
+	input.c \
+	jobs.c \
+	mail.c \
+	main.c \
+	memalloc.c \
+	miscbltin.c \
+	mystring.c \
+	options.c \
+	output.c \
+	parser.c \
+	redir.c \
+	show.c \
+	syntax.c \
+	trap.c \
+	var.c \
+	bltin/echo.c \
+	bltin/kill.c \
+	bltin/test.c \
+	$(PATH_kmk_ash)/arith.c \
+	$(PATH_kmk_ash)/builtins.c \
+	$(PATH_kmk_ash)/init.c \
+	$(PATH_kmk_ash)/nodes.c
+kmk_ash_SOURCES.linux = \
+	sys_signame.c \
+	strlcpy.c \
+	setmode.c
+kmk_ash_SOURCES.win = \
+	win/mscfakes.c \
+	win/err.c \
+	win/dirent.c \
+	sys_signame.c \
+	strlcpy.c \
+	setmode.c
+kmk_ash_SOURCES.solaris = \
+	sys_signame.c \
+	strlcpy.c \
+	setmode.c
+
+kmk_ash_INTERMEDIATES = \
+	$(PATH_kmk_ash)/arith.h \
+	$(PATH_kmk_ash)/builtins.h \
+	$(PATH_kmk_ash)/nodes.h \
+	$(PATH_kmk_ash)/token.h
+kmk_ash_CLEAN = \
+	$(kmk_ash_INTERMEDIATES) \
+	$(PATH_kmk_ash)/arith.c \
+	$(PATH_kmk_ash)/arith_lex.c \
+	$(PATH_kmk_ash)/builtins.c \
+	$(PATH_kmk_ash)/init.c \
+	$(PATH_kmk_ash)/nodes.c
+
+kmk_ash.man_TEMPLATE = usr.bin.man
+kmk_ash.man_SOURCES = \
+	sh.1=>ash.1
+#ash.man_SYMLINKS = \
+#	ash.1.gz=>sh.1
+
+if1of ($(KBUILD_TARGET), win nt)
+#
+# Use the pregenerated code.
+#
+kmk_ash_DEPS :=
+kmk_ash_SOURCES += $(PATH_kmk_ash)/arith_lex.c
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
+define def_copy_generated
+$(PATH_kmk_ash)/$(src): generated/$(src)
+	$$(RM) -f $$@
+	$$(CP) -f $$^ $$@
+endef
+
+$(foreach src, arith.h arith.c arith_lex.c builtins.h builtins.c nodes.h nodes.c token.h init.c,\
+$(eval $(def_copy_generated)))
+
+
+else
+#
+# Generate the code on the fly.
+#
+
+ifeq (1,2) #disabled for now.
+kmk_ash_USES = lex #yacc
+kmk_ash_SOURCES += arith_lex.l
+kmk_ash_LEXTOOL = FLEX
+kmk_ash_LEXFLAGS = -8
+else
+kmk_ash_SOURCES += $(PATH_kmk_ash)/arith_lex.c
+endif
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
+#
+# ATTENTION! ATTENTION! ATTENTION!
+#
+# Older ash versions has trouble with some of these scripts, great.
+# Kudos to the NetBSD guys for this clever move. ;)
+#
+# So, when building for the frist time, setting BOOSTRAP_SHELL=/bin/bash is good idea.
+#
+BOOTSTRAP_SHELL ?= $(SHELL)
+ifndef YACC
+ YACC := $(firstword $(which byacc) $(which yacc) yacc)
+endif
+
+$(PATH_kmk_ash)/arith.h + $(PATH_kmk_ash)/arith.c: $(kmk_ash_PATH)/arith.y | $(call DIRDEP,$(PATH_kmk_ash))
+	$(YACC) -ld $^
+	$(MV) -f y.tab.c $(PATH_kmk_ash)/arith.c
+	$(MV) -f y.tab.h $(PATH_kmk_ash)/arith.h
+
+ifndef kmk_ash_LEXTOOL
+$(PATH_kmk_ash)/arith_lex.c: $(kmk_ash_PATH)/arith_lex.l | $(call DIRDEP,$(PATH_kmk_ash))
+	flex -8 -o$@ $^                     # 8-bit lex scanner for arithmetic
+endif
+
+$(PATH_kmk_ash)/builtins.h + $(PATH_kmk_ash)/builtins.c: \
+		$(kmk_ash_PATH)/mkbuiltins \
+		$(kmk_ash_PATH)/shell.h \
+		$(kmk_ash_PATH)/builtins.def \
+		| $(call DIRDEP,$(PATH_kmk_ash))
+	$(BOOTSTRAP_SHELL) $+ $(dir $@)
+	[ -f $(PATH_kmk_ash)/builtins.h ]
+
+$(PATH_kmk_ash)/nodes.h + $(PATH_kmk_ash)/nodes.c: \
+		$(kmk_ash_PATH)/mknodes.sh \
+		$(kmk_ash_PATH)/nodetypes \
+		$(kmk_ash_PATH)/nodes.c.pat \
+		| $(call DIRDEP,$(PATH_kmk_ash))
+	$(BOOTSTRAP_SHELL) $+ $(dir $@)
+	[ -f $(dir $@)/nodes.h ]
+
+$(PATH_kmk_ash)/token.h: $(kmk_ash_PATH)/mktokens | $(call DIRDEP,$(PATH_kmk_ash))
+	$(BOOTSTRAP_SHELL) $+
+	$(MV) token.h $@
+
+$(PATH_kmk_ash)/init.c: \
+		$(kmk_ash_PATH)/mkinit.sh \
+		$(abspathex $(filter-out $(PATH_kmk_ash)/%,$(kmk_ash_SOURCES)), $(kmk_ash_PATH)) \
+		| $(call DIRDEP,$(PATH_kmk_ash))
+	$(BOOTSTRAP_SHELL) $+
+	$(MV) init.c $@
+
+endif # generate on the fly
Index: /tags/kBuild-0.1.4/src/ash/TOUR
===================================================================
--- /tags/kBuild-0.1.4/src/ash/TOUR	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/TOUR	(revision 1780)
@@ -0,0 +1,357 @@
+#	$NetBSD: TOUR,v 1.8 1996/10/16 14:24:56 christos Exp $
+#	@(#)TOUR	8.1 (Berkeley) 5/31/93
+
+NOTE -- This is the original TOUR paper distributed with ash and
+does not represent the current state of the shell.  It is provided anyway
+since it provides helpful information for how the shell is structured,
+but be warned that things have changed -- the current shell is
+still under development.
+
+================================================================
+
+                       A Tour through Ash
+
+               Copyright 1989 by Kenneth Almquist.
+
+
+DIRECTORIES:  The subdirectory bltin contains commands which can
+be compiled stand-alone.  The rest of the source is in the main
+ash directory.
+
+SOURCE CODE GENERATORS:  Files whose names begin with "mk" are
+programs that generate source code.  A complete list of these
+programs is:
+
+        program         intput files        generates
+        -------         ------------        ---------
+        mkbuiltins      builtins            builtins.h builtins.c
+        mkinit          *.c                 init.c
+        mknodes         nodetypes           nodes.h nodes.c
+        mksignames          -               signames.h signames.c
+        mksyntax            -               syntax.h syntax.c
+        mktokens            -               token.h
+        bltin/mkexpr    unary_op binary_op  operators.h operators.c
+
+There are undoubtedly too many of these.  Mkinit searches all the
+C source files for entries looking like:
+
+        INIT {
+              x = 1;    /* executed during initialization */
+        }
+
+        RESET {
+              x = 2;    /* executed when the shell does a longjmp
+                           back to the main command loop */
+        }
+
+        SHELLPROC {
+              x = 3;    /* executed when the shell runs a shell procedure */
+        }
+
+It pulls this code out into routines which are when particular
+events occur.  The intent is to improve modularity by isolating
+the information about which modules need to be explicitly
+initialized/reset within the modules themselves.
+
+Mkinit recognizes several constructs for placing declarations in
+the init.c file.
+        INCLUDE "file.h"
+includes a file.  The storage class MKINIT makes a declaration
+available in the init.c file, for example:
+        MKINIT int funcnest;    /* depth of function calls */
+MKINIT alone on a line introduces a structure or union declara-
+tion:
+        MKINIT
+        struct redirtab {
+              short renamed[10];
+        };
+Preprocessor #define statements are copied to init.c without any
+special action to request this.
+
+INDENTATION:  The ash source is indented in multiples of six
+spaces.  The only study that I have heard of on the subject con-
+cluded that the optimal amount to indent is in the range of four
+to six spaces.  I use six spaces since it is not too big a jump
+from the widely used eight spaces.  If you really hate six space
+indentation, use the adjind (source included) program to change
+it to something else.
+
+EXCEPTIONS:  Code for dealing with exceptions appears in
+exceptions.c.  The C language doesn't include exception handling,
+so I implement it using setjmp and longjmp.  The global variable
+exception contains the type of exception.  EXERROR is raised by
+calling error.  EXINT is an interrupt.  EXSHELLPROC is an excep-
+tion which is raised when a shell procedure is invoked.  The pur-
+pose of EXSHELLPROC is to perform the cleanup actions associated
+with other exceptions.  After these cleanup actions, the shell
+can interpret a shell procedure itself without exec'ing a new
+copy of the shell.
+
+INTERRUPTS:  In an interactive shell, an interrupt will cause an
+EXINT exception to return to the main command loop.  (Exception:
+EXINT is not raised if the user traps interrupts using the trap
+command.)  The INTOFF and INTON macros (defined in exception.h)
+provide uninterruptable critical sections.  Between the execution
+of INTOFF and the execution of INTON, interrupt signals will be
+held for later delivery.  INTOFF and INTON can be nested.
+
+MEMALLOC.C:  Memalloc.c defines versions of malloc and realloc
+which call error when there is no memory left.  It also defines a
+stack oriented memory allocation scheme.  Allocating off a stack
+is probably more efficient than allocation using malloc, but the
+big advantage is that when an exception occurs all we have to do
+to free up the memory in use at the time of the exception is to
+restore the stack pointer.  The stack is implemented using a
+linked list of blocks.
+
+STPUTC:  If the stack were contiguous, it would be easy to store
+strings on the stack without knowing in advance how long the
+string was going to be:
+        p = stackptr;
+        *p++ = c;       /* repeated as many times as needed */
+        stackptr = p;
+The folloing three macros (defined in memalloc.h) perform these
+operations, but grow the stack if you run off the end:
+        STARTSTACKSTR(p);
+        STPUTC(c, p);   /* repeated as many times as needed */
+        grabstackstr(p);
+
+We now start a top-down look at the code:
+
+MAIN.C:  The main routine performs some initialization, executes
+the user's profile if necessary, and calls cmdloop.  Cmdloop is
+repeatedly parses and executes commands.
+
+OPTIONS.C:  This file contains the option processing code.  It is
+called from main to parse the shell arguments when the shell is
+invoked, and it also contains the set builtin.  The -i and -j op-
+tions (the latter turns on job control) require changes in signal
+handling.  The routines setjobctl (in jobs.c) and setinteractive
+(in trap.c) are called to handle changes to these options.
+
+PARSING:  The parser code is all in parser.c.  A recursive des-
+cent parser is used.  Syntax tables (generated by mksyntax) are
+used to classify characters during lexical analysis.  There are
+three tables:  one for normal use, one for use when inside single
+quotes, and one for use when inside double quotes.  The tables
+are machine dependent because they are indexed by character vari-
+ables and the range of a char varies from machine to machine.
+
+PARSE OUTPUT:  The output of the parser consists of a tree of
+nodes.  The various types of nodes are defined in the file node-
+types.
+
+Nodes of type NARG are used to represent both words and the con-
+tents of here documents.  An early version of ash kept the con-
+tents of here documents in temporary files, but keeping here do-
+cuments in memory typically results in significantly better per-
+formance.  It would have been nice to make it an option to use
+temporary files for here documents, for the benefit of small
+machines, but the code to keep track of when to delete the tem-
+porary files was complex and I never fixed all the bugs in it.
+(AT&T has been maintaining the Bourne shell for more than ten
+years, and to the best of my knowledge they still haven't gotten
+it to handle temporary files correctly in obscure cases.)
+
+The text field of a NARG structure points to the text of the
+word.  The text consists of ordinary characters and a number of
+special codes defined in parser.h.  The special codes are:
+
+        CTLVAR              Variable substitution
+        CTLENDVAR           End of variable substitution
+        CTLBACKQ            Command substitution
+        CTLBACKQ|CTLQUOTE   Command substitution inside double quotes
+        CTLESC              Escape next character
+
+A variable substitution contains the following elements:
+
+        CTLVAR type name '=' [ alternative-text CTLENDVAR ]
+
+The type field is a single character specifying the type of sub-
+stitution.  The possible types are:
+
+        VSNORMAL            $var
+        VSMINUS             ${var-text}
+        VSMINUS|VSNUL       ${var:-text}
+        VSPLUS              ${var+text}
+        VSPLUS|VSNUL        ${var:+text}
+        VSQUESTION          ${var?text}
+        VSQUESTION|VSNUL    ${var:?text}
+        VSASSIGN            ${var=text}
+        VSASSIGN|VSNUL      ${var=text}
+
+In addition, the type field will have the VSQUOTE flag set if the
+variable is enclosed in double quotes.  The name of the variable
+comes next, terminated by an equals sign.  If the type is not
+VSNORMAL, then the text field in the substitution follows, ter-
+minated by a CTLENDVAR byte.
+
+Commands in back quotes are parsed and stored in a linked list.
+The locations of these commands in the string are indicated by
+CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether
+the back quotes were enclosed in double quotes.
+
+The character CTLESC escapes the next character, so that in case
+any of the CTL characters mentioned above appear in the input,
+they can be passed through transparently.  CTLESC is also used to
+escape '*', '?', '[', and '!' characters which were quoted by the
+user and thus should not be used for file name generation.
+
+CTLESC characters have proved to be particularly tricky to get
+right.  In the case of here documents which are not subject to
+variable and command substitution, the parser doesn't insert any
+CTLESC characters to begin with (so the contents of the text
+field can be written without any processing).  Other here docu-
+ments, and words which are not subject to splitting and file name
+generation, have the CTLESC characters removed during the vari-
+able and command substitution phase.  Words which are subject
+splitting and file name generation have the CTLESC characters re-
+moved as part of the file name phase.
+
+EXECUTION:  Command execution is handled by the following files:
+        eval.c     The top level routines.
+        redir.c    Code to handle redirection of input and output.
+        jobs.c     Code to handle forking, waiting, and job control.
+        exec.c     Code to to path searches and the actual exec sys call.
+        expand.c   Code to evaluate arguments.
+        var.c      Maintains the variable symbol table.  Called from expand.c.
+
+EVAL.C:  Evaltree recursively executes a parse tree.  The exit
+status is returned in the global variable exitstatus.  The alter-
+native entry evalbackcmd is called to evaluate commands in back
+quotes.  It saves the result in memory if the command is a buil-
+tin; otherwise it forks off a child to execute the command and
+connects the standard output of the child to a pipe.
+
+JOBS.C:  To create a process, you call makejob to return a job
+structure, and then call forkshell (passing the job structure as
+an argument) to create the process.  Waitforjob waits for a job
+to complete.  These routines take care of process groups if job
+control is defined.
+
+REDIR.C:  Ash allows file descriptors to be redirected and then
+restored without forking off a child process.  This is accom-
+plished by duplicating the original file descriptors.  The redir-
+tab structure records where the file descriptors have be dupli-
+cated to.
+
+EXEC.C:  The routine find_command locates a command, and enters
+the command in the hash table if it is not already there.  The
+third argument specifies whether it is to print an error message
+if the command is not found.  (When a pipeline is set up,
+find_command is called for all the commands in the pipeline be-
+fore any forking is done, so to get the commands into the hash
+table of the parent process.  But to make command hashing as
+transparent as possible, we silently ignore errors at that point
+and only print error messages if the command cannot be found
+later.)
+
+The routine shellexec is the interface to the exec system call.
+
+EXPAND.C:  Arguments are processed in three passes.  The first
+(performed by the routine argstr) performs variable and command
+substitution.  The second (ifsbreakup) performs word splitting
+and the third (expandmeta) performs file name generation.  If the
+"/u" directory is simulated, then when "/u/username" is replaced
+by the user's home directory, the flag "didudir" is set.  This
+tells the cd command that it should print out the directory name,
+just as it would if the "/u" directory were implemented using
+symbolic links.
+
+VAR.C:  Variables are stored in a hash table.  Probably we should
+switch to extensible hashing.  The variable name is stored in the
+same string as the value (using the format "name=value") so that
+no string copying is needed to create the environment of a com-
+mand.  Variables which the shell references internally are preal-
+located so that the shell can reference the values of these vari-
+ables without doing a lookup.
+
+When a program is run, the code in eval.c sticks any environment
+variables which precede the command (as in "PATH=xxx command") in
+the variable table as the simplest way to strip duplicates, and
+then calls "environment" to get the value of the environment.
+There are two consequences of this.  First, if an assignment to
+PATH precedes the command, the value of PATH before the assign-
+ment must be remembered and passed to shellexec.  Second, if the
+program turns out to be a shell procedure, the strings from the
+environment variables which preceded the command must be pulled
+out of the table and replaced with strings obtained from malloc,
+since the former will automatically be freed when the stack (see
+the entry on memalloc.c) is emptied.
+
+BUILTIN COMMANDS:  The procedures for handling these are scat-
+tered throughout the code, depending on which location appears
+most appropriate.  They can be recognized because their names al-
+ways end in "cmd".  The mapping from names to procedures is
+specified in the file builtins, which is processed by the mkbuil-
+tins command.
+
+A builtin command is invoked with argc and argv set up like a
+normal program.  A builtin command is allowed to overwrite its
+arguments.  Builtin routines can call nextopt to do option pars-
+ing.  This is kind of like getopt, but you don't pass argc and
+argv to it.  Builtin routines can also call error.  This routine
+normally terminates the shell (or returns to the main command
+loop if the shell is interactive), but when called from a builtin
+command it causes the builtin command to terminate with an exit
+status of 2.
+
+The directory bltins contains commands which can be compiled in-
+dependently but can also be built into the shell for efficiency
+reasons.  The makefile in this directory compiles these programs
+in the normal fashion (so that they can be run regardless of
+whether the invoker is ash), but also creates a library named
+bltinlib.a which can be linked with ash.  The header file bltin.h
+takes care of most of the differences between the ash and the
+stand-alone environment.  The user should call the main routine
+"main", and #define main to be the name of the routine to use
+when the program is linked into ash.  This #define should appear
+before bltin.h is included; bltin.h will #undef main if the pro-
+gram is to be compiled stand-alone.
+
+CD.C:  This file defines the cd and pwd builtins.  The pwd com-
+mand runs /bin/pwd the first time it is invoked (unless the user
+has already done a cd to an absolute pathname), but then
+remembers the current directory and updates it when the cd com-
+mand is run, so subsequent pwd commands run very fast.  The main
+complication in the cd command is in the docd command, which
+resolves symbolic links into actual names and informs the user
+where the user ended up if he crossed a symbolic link.
+
+SIGNALS:  Trap.c implements the trap command.  The routine set-
+signal figures out what action should be taken when a signal is
+received and invokes the signal system call to set the signal ac-
+tion appropriately.  When a signal that a user has set a trap for
+is caught, the routine "onsig" sets a flag.  The routine dotrap
+is called at appropriate points to actually handle the signal.
+When an interrupt is caught and no trap has been set for that
+signal, the routine "onint" in error.c is called.
+
+OUTPUT:  Ash uses it's own output routines.  There are three out-
+put structures allocated.  "Output" represents the standard out-
+put, "errout" the standard error, and "memout" contains output
+which is to be stored in memory.  This last is used when a buil-
+tin command appears in backquotes, to allow its output to be col-
+lected without doing any I/O through the UNIX operating system.
+The variables out1 and out2 normally point to output and errout,
+respectively, but they are set to point to memout when appropri-
+ate inside backquotes.
+
+INPUT:  The basic input routine is pgetc, which reads from the
+current input file.  There is a stack of input files; the current
+input file is the top file on this stack.  The code allows the
+input to come from a string rather than a file.  (This is for the
+-c option and the "." and eval builtin commands.)  The global
+variable plinno is saved and restored when files are pushed and
+popped from the stack.  The parser routines store the number of
+the current line in this variable.
+
+DEBUGGING:  If DEBUG is defined in shell.h, then the shell will
+write debugging information to the file $HOME/trace.  Most of
+this is done using the TRACE macro, which takes a set of printf
+arguments inside two sets of parenthesis.  Example:
+"TRACE(("n=%d0, n))".  The double parenthesis are necessary be-
+cause the preprocessor can't handle functions with a variable
+number of arguments.  Defining DEBUG also causes the shell to
+generate a core dump if it is sent a quit signal.  The tracing
+code is in show.c.
Index: /tags/kBuild-0.1.4/src/ash/alias.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/alias.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/alias.c	(revision 1780)
@@ -0,0 +1,275 @@
+/*	$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)alias.c	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+#include "shell.h"
+#include "input.h"
+#include "output.h"
+#include "error.h"
+#include "memalloc.h"
+#include "mystring.h"
+#include "alias.h"
+#include "options.h"	/* XXX for argptr (should remove?) */
+#include "var.h"
+
+#define ATABSIZE 39
+
+struct alias *atab[ATABSIZE];
+
+STATIC void setalias(char *, char *);
+STATIC int unalias(char *);
+STATIC struct alias **hashalias(char *);
+
+STATIC
+void
+setalias(char *name, char *val)
+{
+	struct alias *ap, **app;
+
+	app = hashalias(name);
+	for (ap = *app; ap; ap = ap->next) {
+		if (equal(name, ap->name)) {
+			INTOFF;
+			ckfree(ap->val);
+			ap->val	= savestr(val);
+			INTON;
+			return;
+		}
+	}
+	/* not found */
+	INTOFF;
+	ap = ckmalloc(sizeof (struct alias));
+	ap->name = savestr(name);
+	/*
+	 * XXX - HACK: in order that the parser will not finish reading the
+	 * alias value off the input before processing the next alias, we
+	 * dummy up an extra space at the end of the alias.  This is a crock
+	 * and should be re-thought.  The idea (if you feel inclined to help)
+	 * is to avoid alias recursions.  The mechanism used is: when
+	 * expanding an alias, the value of the alias is pushed back on the
+	 * input as a string and a pointer to the alias is stored with the
+	 * string.  The alias is marked as being in use.  When the input
+	 * routine finishes reading the string, it markes the alias not
+	 * in use.  The problem is synchronization with the parser.  Since
+	 * it reads ahead, the alias is marked not in use before the
+	 * resulting token(s) is next checked for further alias sub.  The
+	 * H A C K is that we add a little fluff after the alias value
+	 * so that the string will not be exhausted.  This is a good
+	 * idea ------- ***NOT***
+	 */
+#ifdef notyet
+	ap->val = savestr(val);
+#else /* hack */
+	{
+	int len = strlen(val);
+	ap->val = ckmalloc(len + 2);
+	memcpy(ap->val, val, len);
+	ap->val[len] = ' ';	/* fluff */
+	ap->val[len+1] = '\0';
+	}
+#endif
+	ap->next = *app;
+	*app = ap;
+	INTON;
+}
+
+STATIC int
+unalias(char *name)
+{
+	struct alias *ap, **app;
+
+	app = hashalias(name);
+
+	for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
+		if (equal(name, ap->name)) {
+			/*
+			 * if the alias is currently in use (i.e. its
+			 * buffer is being used by the input routine) we
+			 * just null out the name instead of freeing it.
+			 * We could clear it out later, but this situation
+			 * is so rare that it hardly seems worth it.
+			 */
+			if (ap->flag & ALIASINUSE)
+				*ap->name = '\0';
+			else {
+				INTOFF;
+				*app = ap->next;
+				ckfree(ap->name);
+				ckfree(ap->val);
+				ckfree(ap);
+				INTON;
+			}
+			return (0);
+		}
+	}
+
+	return (1);
+}
+
+#ifdef mkinit
+MKINIT void rmaliases(void);
+
+SHELLPROC {
+	rmaliases();
+}
+#endif
+
+void
+rmaliases(void)
+{
+	struct alias *ap, *tmp;
+	int i;
+
+	INTOFF;
+	for (i = 0; i < ATABSIZE; i++) {
+		ap = atab[i];
+		atab[i] = NULL;
+		while (ap) {
+			ckfree(ap->name);
+			ckfree(ap->val);
+			tmp = ap;
+			ap = ap->next;
+			ckfree(tmp);
+		}
+	}
+	INTON;
+}
+
+struct alias *
+lookupalias(char *name, int check)
+{
+	struct alias *ap = *hashalias(name);
+
+	for (; ap; ap = ap->next) {
+		if (equal(name, ap->name)) {
+			if (check && (ap->flag & ALIASINUSE))
+				return (NULL);
+			return (ap);
+		}
+	}
+
+	return (NULL);
+}
+
+char *
+get_alias_text(char *name)
+{
+	struct alias *ap;
+
+	ap = lookupalias(name, 0);
+	if (ap == NULL)
+		return NULL;
+	return ap->val;
+}
+
+/*
+ * TODO - sort output
+ */
+int
+aliascmd(int argc, char **argv)
+{
+	char *n, *v;
+	int ret = 0;
+	struct alias *ap;
+
+	if (argc == 1) {
+		int i;
+
+		for (i = 0; i < ATABSIZE; i++)
+			for (ap = atab[i]; ap; ap = ap->next) {
+				if (*ap->name != '\0') {
+					out1fmt("alias %s=", ap->name);
+					print_quoted(ap->val);
+					out1c('\n');
+				}
+			}
+		return (0);
+	}
+	while ((n = *++argv) != NULL) {
+		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
+			if ((ap = lookupalias(n, 0)) == NULL) {
+				outfmt(out2, "alias: %s not found\n", n);
+				ret = 1;
+			} else {
+				out1fmt("alias %s=", n);
+				print_quoted(ap->val);
+				out1c('\n');
+			}
+		} else {
+			*v++ = '\0';
+			setalias(n, v);
+		}
+	}
+
+	return (ret);
+}
+
+int
+unaliascmd(int argc, char **argv)
+{
+	int i;
+
+	while ((i = nextopt("a")) != '\0') {
+		if (i == 'a') {
+			rmaliases();
+			return (0);
+		}
+	}
+	for (i = 0; *argptr; argptr++)
+		i = unalias(*argptr);
+
+	return (i);
+}
+
+STATIC struct alias **
+hashalias(char *p)
+{
+	unsigned int hashval;
+
+	hashval = *p << 4;
+	while (*p)
+		hashval+= *p++;
+	return &atab[hashval % ATABSIZE];
+}
Index: /tags/kBuild-0.1.4/src/ash/alias.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/alias.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/alias.h	(revision 1780)
@@ -0,0 +1,50 @@
+/*	$NetBSD: alias.h,v 1.6 2003/08/07 09:05:29 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)alias.h	8.2 (Berkeley) 5/4/95
+ */
+
+#define ALIASINUSE	1
+
+struct alias {
+	struct alias *next;
+	char *name;
+	char *val;
+	int flag;
+};
+
+struct alias *lookupalias(char *, int);
+char *get_alias_text(char *);
+int aliascmd(int, char **);
+int unaliascmd(int, char **);
+void rmaliases(void);
Index: /tags/kBuild-0.1.4/src/ash/arith.y
===================================================================
--- /tags/kBuild-0.1.4/src/ash/arith.y	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/arith.y	(revision 1780)
@@ -0,0 +1,202 @@
+%{
+/*	$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)arith.y	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+#include "expand.h"
+#include "shell.h"
+#include "error.h"
+#include "output.h"
+#include "memalloc.h"
+
+const char *arith_buf, *arith_startbuf;
+
+void yyerror(const char *);
+#ifdef TESTARITH
+int main(int , char *[]);
+int error(char *);
+#endif
+
+%}
+%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
+
+%left ARITH_OR
+%left ARITH_AND
+%left ARITH_BOR
+%left ARITH_BXOR
+%left ARITH_BAND
+%left ARITH_EQ ARITH_NE
+%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
+%left ARITH_LSHIFT ARITH_RSHIFT
+%left ARITH_ADD ARITH_SUB
+%left ARITH_MUL ARITH_DIV ARITH_REM
+%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
+%%
+
+exp:	expr {
+			return ($1);
+		}
+	;
+
+
+expr:	ARITH_LPAREN expr ARITH_RPAREN { $$ = $2; }
+	| expr ARITH_OR expr	{ $$ = $1 ? $1 : $3 ? $3 : 0; }
+	| expr ARITH_AND expr	{ $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
+	| expr ARITH_BOR expr	{ $$ = $1 | $3; }
+	| expr ARITH_BXOR expr	{ $$ = $1 ^ $3; }
+	| expr ARITH_BAND expr	{ $$ = $1 & $3; }
+	| expr ARITH_EQ expr	{ $$ = $1 == $3; }
+	| expr ARITH_GT expr	{ $$ = $1 > $3; }
+	| expr ARITH_GE expr	{ $$ = $1 >= $3; }
+	| expr ARITH_LT expr	{ $$ = $1 < $3; }
+	| expr ARITH_LE expr	{ $$ = $1 <= $3; }
+	| expr ARITH_NE expr	{ $$ = $1 != $3; }
+	| expr ARITH_LSHIFT expr { $$ = $1 << $3; }
+	| expr ARITH_RSHIFT expr { $$ = $1 >> $3; }
+	| expr ARITH_ADD expr	{ $$ = $1 + $3; }
+	| expr ARITH_SUB expr	{ $$ = $1 - $3; }
+	| expr ARITH_MUL expr	{ $$ = $1 * $3; }
+	| expr ARITH_DIV expr	{
+			if ($3 == 0)
+				yyerror("division by zero");
+			$$ = $1 / $3;
+			}
+	| expr ARITH_REM expr   {
+			if ($3 == 0)
+				yyerror("division by zero");
+			$$ = $1 % $3;
+			}
+	| ARITH_NOT expr	{ $$ = !($2); }
+	| ARITH_BNOT expr	{ $$ = ~($2); }
+	| ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); }
+	| ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; }
+	| ARITH_NUM
+	;
+%%
+int
+arith(s)
+	const char *s;
+{
+	long result;
+
+	arith_buf = arith_startbuf = s;
+
+	INTOFF;
+	result = yyparse();
+	arith_lex_reset();	/* reprime lex */
+	INTON;
+
+	return (result);
+}
+
+
+/*
+ *  The exp(1) builtin.
+ */
+int
+expcmd(argc, argv)
+	int argc;
+	char **argv;
+{
+	const char *p;
+	char *concat;
+	char **ap;
+	long i;
+
+	if (argc > 1) {
+		p = argv[1];
+		if (argc > 2) {
+			/*
+			 * concatenate arguments
+			 */
+			STARTSTACKSTR(concat);
+			ap = argv + 2;
+			for (;;) {
+				while (*p)
+					STPUTC(*p++, concat);
+				if ((p = *ap++) == NULL)
+					break;
+				STPUTC(' ', concat);
+			}
+			STPUTC('\0', concat);
+			p = grabstackstr(concat);
+		}
+	} else
+		p = "";
+
+	i = arith(p);
+
+	out1fmt("%ld\n", i);
+	return (! i);
+}
+
+/*************************/
+#ifdef TEST_ARITH
+#include <stdio.h>
+main(argc, argv)
+	char *argv[];
+{
+	printf("%d\n", exp(argv[1]));
+}
+error(s)
+	char *s;
+{
+	fprintf(stderr, "exp: %s\n", s);
+	exit(1);
+}
+#endif
+
+void
+yyerror(s)
+	const char *s;
+{
+#ifndef YYBISON /* yyerrok references yyerrstatus which is a local variable in yyparse().*/
+	yyerrok;
+#endif
+	yyclearin;
+	arith_lex_reset();	/* reprime lex */
+	error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
+	/* NOTREACHED */
+}
Index: /tags/kBuild-0.1.4/src/ash/arith_lex.l
===================================================================
--- /tags/kBuild-0.1.4/src/ash/arith_lex.l	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/arith_lex.l	(revision 1780)
@@ -0,0 +1,105 @@
+%option noyywrap
+%{
+/*	$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)arith_lex.l	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $");
+#endif
+#endif /* not lint */
+
+#include <unistd.h>
+#include "arith.h"
+#include "error.h"
+#include "expand.h"
+#include "var.h"
+
+extern int yylval;
+extern char *arith_buf, *arith_startbuf;
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max) \
+	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
+#define YY_NO_UNPUT
+%}
+
+%%
+[ \t\n]	{ ; }
+0x[0-9a-fA-F]+	{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+0[0-7]*		{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+[1-9][0-9]*	{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+[A-Za-z_][A-Za-z_0-9]*	{ char *v = lookupvar(yytext);
+			if (v) {
+				yylval = strtol(v, &v, 0);
+				if (*v == 0)
+					return ARITH_NUM;
+			}
+			error("arith: syntax error: \"%s\"", arith_startbuf);
+		}
+"("	{ return(ARITH_LPAREN); }
+")"	{ return(ARITH_RPAREN); }
+"||"	{ return(ARITH_OR); }
+"&&"	{ return(ARITH_AND); }
+"|"	{ return(ARITH_BOR); }
+"^"	{ return(ARITH_BXOR); }
+"&"	{ return(ARITH_BAND); }
+"=="	{ return(ARITH_EQ); }
+"!="	{ return(ARITH_NE); }
+">"	{ return(ARITH_GT); }
+">="	{ return(ARITH_GE); }
+"<"	{ return(ARITH_LT); }
+"<="	{ return(ARITH_LE); }
+"<<"	{ return(ARITH_LSHIFT); }
+">>"	{ return(ARITH_RSHIFT); }
+"*"	{ return(ARITH_MUL); }
+"/"	{ return(ARITH_DIV); }
+"%"	{ return(ARITH_REM); }
+"+"	{ return(ARITH_ADD); }
+"-"	{ return(ARITH_SUB); }
+"~"	{ return(ARITH_BNOT); }
+"!"	{ return(ARITH_NOT); }
+.	{ error("arith: syntax error: \"%s\"", arith_startbuf); }
+%%
+
+void
+arith_lex_reset() {
+#ifdef YY_NEW_FILE
+	YY_NEW_FILE;
+#endif
+}
Index: /tags/kBuild-0.1.4/src/ash/bltin/bltin.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/bltin/bltin.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/bltin/bltin.h	(revision 1780)
@@ -0,0 +1,94 @@
+/*	$NetBSD: bltin.h,v 1.11 2003/08/07 09:05:40 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)bltin.h	8.1 (Berkeley) 5/31/93
+ */
+
+/*
+ * This file is included by programs which are optionally built into the
+ * shell.  If SHELL is defined, we try to map the standard UNIX library
+ * routines to ash routines using defines.
+ */
+
+#include "../shell.h"
+#include "../mystring.h"
+#ifdef SHELL
+#include "../output.h"
+#include "../error.h"
+#undef stdout
+#undef stderr
+#undef putc
+#undef putchar
+#undef fileno
+#define stdout out1
+#define stderr out2
+#define printf out1fmt
+#define putc(c, file)	outc(c, file)
+#define putchar(c)	out1c(c)
+#define FILE struct output
+#define fprintf outfmt
+#define fputs outstr
+#define fflush flushout
+#define fileno(f) ((f)->fd)
+#define INITARGS(argv)
+#define	err sh_err
+#define	verr sh_verr
+#define	errx sh_errx
+#define	verrx sh_verrx
+#define	warn sh_warn
+#define	vwarn sh_vwarn
+#define	warnx sh_warnx
+#define	vwarnx sh_vwarnx
+#define exit sh_exit
+#define setprogname(s)
+#define getprogname() commandname
+#define setlocate(l,s) 0
+
+#define getenv(p) bltinlookup((p),0)
+
+#else
+#undef NULL
+#include <stdio.h>
+#undef main
+#define INITARGS(argv)	if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
+#endif
+
+pointer stalloc(int);
+void error(const char *, ...);
+void sh_warnx(const char *, ...);
+void sh_exit(int) __attribute__((__noreturn__));
+
+int echocmd(int, char **);
+
+
+extern const char *commandname;
Index: /tags/kBuild-0.1.4/src/ash/bltin/echo.1
===================================================================
--- /tags/kBuild-0.1.4/src/ash/bltin/echo.1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/bltin/echo.1	(revision 1780)
@@ -0,0 +1,109 @@
+.\"	$NetBSD: echo.1,v 1.13 2003/08/07 09:05:40 agc Exp $
+.\"
+.\" Copyright (c) 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Kenneth Almquist.
+.\" Copyright 1989 by Kenneth Almquist
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)echo.1	8.1 (Berkeley) 5/31/93
+.\"
+.Dd May 31, 1993
+.Dt ECHO 1
+.Os
+.Sh NAME
+.Nm echo
+.Nd produce message in a shell script
+.Sh SYNOPSIS
+.Nm
+.Op Fl n | Fl e
+.Ar args ...
+.Sh DESCRIPTION
+.Nm
+prints its arguments on the standard output, separated by spaces.
+Unless the
+.Fl n
+option is present, a newline is output following the arguments.
+The
+.Fl e
+option causes
+.Nm
+to treat the escape sequences specially, as described in the following
+paragraph.
+The
+.Fl e
+option is the default, and is provided solely for compatibility with
+other systems.
+Only one of the options
+.Fl n
+and
+.Fl e
+may be given.
+.Pp
+If any of the following sequences of characters is encountered during
+output, the sequence is not output.  Instead, the specified action is
+performed:
+.Bl -tag -width indent
+.It Li \eb
+A backspace character is output.
+.It Li \ec
+Subsequent output is suppressed.  This is normally used at the end of the
+last argument to suppress the trailing newline that
+.Nm
+would otherwise output.
+.It Li \ef
+Output a form feed.
+.It Li \en
+Output a newline character.
+.It Li \er
+Output a carriage return.
+.It Li \et
+Output a (horizontal) tab character.
+.It Li \ev
+Output a vertical tab.
+.It Li \e0 Ns Ar digits
+Output the character whose value is given by zero to three digits.
+If there are zero digits, a nul character is output.
+.It Li \e\e
+Output a backslash.
+.El
+.Sh HINTS
+Remember that backslash is special to the shell and needs to be escaped.
+To output a message to standard error, say
+.Pp
+.D1  echo message \*[Gt]\*[Am]2
+.Sh BUGS
+The octal character escape mechanism
+.Pq Li \e0 Ns Ar digits
+differs from the
+C language mechanism.
+.Pp
+There is no way to force
+.Nm
+to treat its arguments literally, rather than interpreting them as
+options and escape sequences.
Index: /tags/kBuild-0.1.4/src/ash/bltin/echo.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/bltin/echo.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/bltin/echo.c	(revision 1780)
@@ -0,0 +1,116 @@
+/*	$NetBSD: echo.c,v 1.12 2005/02/06 04:43:43 perry Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)echo.c	8.1 (Berkeley) 5/31/93
+ */
+
+/*
+ * Echo command.
+ *
+ * echo is steeped in tradition - several of them!
+ * netbsd has supported 'echo [-n | -e] args' in spite of -e not being
+ * documented anywhere.
+ * Posix requires that -n be supported, output from strings containing
+ * \ is implementation defined
+ * The Single Unix Spec requires that \ escapes be treated as if -e
+ * were set, but that -n not be treated as an option.
+ * (ksh supports 'echo [-eEn] args', but not -- so that it is actually
+ * impossible to actually output '-n')
+ *
+ * It is suggested that 'printf "%b" "string"' be used to get \ sequences
+ * expanded.  printf is now a builtin of netbsd's sh and csh.
+ */
+
+#define main echocmd
+
+#include "bltin.h"
+
+int
+main(int argc, char **argv)
+{
+	char **ap;
+	char *p;
+	char c;
+	int count;
+	int nflag = 0;
+	int eflag = 0;
+
+	ap = argv;
+	if (argc)
+		ap++;
+
+	if ((p = *ap) != NULL) {
+		if (equal(p, "-n")) {
+			nflag = 1;
+			ap++;
+		} else if (equal(p, "-e")) {
+			eflag = 1;
+			ap++;
+		}
+	}
+
+	while ((p = *ap++) != NULL) {
+		while ((c = *p++) != '\0') {
+			if (c == '\\' && eflag) {
+				switch (*p++) {
+				case 'a':  c = '\a';  break;	/* bell */
+				case 'b':  c = '\b';  break;
+				case 'c':  return 0;		/* exit */
+				case 'e':  c =  033;  break;	/* escape */
+				case 'f':  c = '\f';  break;
+				case 'n':  c = '\n';  break;
+				case 'r':  c = '\r';  break;
+				case 't':  c = '\t';  break;
+				case 'v':  c = '\v';  break;
+				case '\\':  break;		/* c = '\\' */
+				case '0':
+					c = 0;
+					count = 3;
+					while (--count >= 0 && (unsigned)(*p - '0') < 8)
+						c = (c << 3) + (*p++ - '0');
+					break;
+				default:
+					/* Output the '/' and char following */
+					p--;
+					break;
+				}
+			}
+			putchar(c);
+		}
+		if (*ap)
+			putchar(' ');
+	}
+	if (! nflag)
+		putchar('\n');
+	return 0;
+}
Index: /tags/kBuild-0.1.4/src/ash/bltin/kill.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/bltin/kill.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/bltin/kill.c	(revision 1780)
@@ -0,0 +1,266 @@
+/* $NetBSD: kill.c,v 1.23 2003/08/07 09:05:13 agc Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#if !defined(lint) && !defined(SHELL)
+__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)kill.c	8.4 (Berkeley) 4/28/95";
+#else
+__RCSID("$NetBSD: kill.c,v 1.23 2003/08/07 09:05:13 agc Exp $");
+#endif
+#endif /* not lint */
+
+#include <ctype.h>
+#ifndef __sun__
+#include <err.h>
+#endif
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <locale.h>
+#include <sys/ioctl.h>
+
+#ifndef HAVE_SYS_SIGNAME
+extern void init_sys_signame(void);
+extern char sys_signame[NSIG][16];
+#endif
+
+#ifdef SHELL            /* sh (aka ash) builtin */
+#define main killcmd
+#include "bltin/bltin.h"
+#endif /* SHELL */
+
+static void nosig(char *);
+static void printsignals(FILE *);
+static int signame_to_signum(char *);
+static void usage(void);
+int main(int, char *[]);
+
+int
+main(int argc, char *argv[])
+{
+	int errors, numsig, pid;
+	char *ep;
+
+	setprogname(argv[0]);
+	setlocale(LC_ALL, "");
+	if (argc < 2)
+		usage();
+
+	numsig = SIGTERM;
+
+	argc--, argv++;
+	if (strcmp(*argv, "-l") == 0) {
+		argc--, argv++;
+		if (argc > 1)
+			usage();
+		if (argc == 1) {
+			if (isdigit((unsigned char)**argv) == 0)
+				usage();
+			numsig = strtol(*argv, &ep, 10);
+			if (*ep != '\0') {
+				errx(EXIT_FAILURE, "illegal signal number: %s",
+						*argv);
+				/* NOTREACHED */
+			}
+			if (numsig >= 128)
+				numsig -= 128;
+			if (numsig <= 0 || numsig >= NSIG)
+				nosig(*argv);
+#ifndef HAVE_SYS_SIGNAME
+			init_sys_signame();
+#endif
+			printf("%s\n", sys_signame[numsig]);
+			exit(0);
+		}
+		printsignals(stdout);
+		exit(0);
+	}
+
+	if (!strcmp(*argv, "-s")) {
+		argc--, argv++;
+		if (argc < 1) {
+			warnx("option requires an argument -- s");
+			usage();
+		}
+		if (strcmp(*argv, "0")) {
+			if ((numsig = signame_to_signum(*argv)) < 0)
+				nosig(*argv);
+		} else
+			numsig = 0;
+		argc--, argv++;
+	} else if (**argv == '-') {
+		++*argv;
+		if (isalpha((unsigned char)**argv)) {
+			if ((numsig = signame_to_signum(*argv)) < 0)
+				nosig(*argv);
+		} else if (isdigit((unsigned char)**argv)) {
+			numsig = strtol(*argv, &ep, 10);
+			if (!*argv || *ep) {
+				errx(EXIT_FAILURE, "illegal signal number: %s",
+						*argv);
+				/* NOTREACHED */
+			}
+			if (numsig < 0 || numsig >= NSIG)
+				nosig(*argv);
+		} else
+			nosig(*argv);
+		argc--, argv++;
+	}
+
+	if (argc == 0)
+		usage();
+
+	for (errors = 0; argc; argc--, argv++) {
+#ifdef SHELL
+		extern int getjobpgrp(const char *);
+		if (*argv[0] == '%') {
+			pid = getjobpgrp(*argv);
+			if (pid == 0) {
+				warnx("illegal job id: %s", *argv);
+				errors = 1;
+				continue;
+			}
+		} else
+#endif
+		{
+			pid = strtol(*argv, &ep, 10);
+			if (!**argv || *ep) {
+				warnx("illegal process id: %s", *argv);
+				errors = 1;
+				continue;
+			}
+		}
+		if (kill(pid, numsig) == -1) {
+			warn("%s", *argv);
+			errors = 1;
+		}
+#ifdef SHELL
+		/* Wakeup the process if it was suspended, so it can
+		   exit without an explicit 'fg'. */
+		if (numsig == SIGTERM || numsig == SIGHUP)
+			kill(pid, SIGCONT);
+#endif
+	}
+
+	exit(errors);
+	/* NOTREACHED */
+}
+
+static int
+signame_to_signum(char *sig)
+{
+	int n;
+#ifndef HAVE_SYS_SIGNAME
+	init_sys_signame();
+#endif
+	if (strncasecmp(sig, "sig", 3) == 0)
+		sig += 3;
+	for (n = 1; n < NSIG; n++) {
+		if (!strcasecmp(sys_signame[n], sig))
+			return (n);
+	}
+	return (-1);
+}
+
+static void
+nosig(char *name)
+{
+
+	warnx("unknown signal %s; valid signals:", name);
+	printsignals(stderr);
+	exit(1);
+	/* NOTREACHED */
+}
+
+static void
+printsignals(FILE *fp)
+{
+	int sig;
+	int len, nl;
+	const char *name;
+	int termwidth = 80;
+
+#ifdef TIOCGWINSZ
+	if (isatty(fileno(fp))) {
+		struct winsize win;
+		if (ioctl(fileno(fp), TIOCGWINSZ, &win) == 0 && win.ws_col > 0)
+			termwidth = win.ws_col;
+	}
+#else
+#ifndef _MSC_VER
+#warning TIOCGWINSZ is not present.
+#endif
+#endif
+#ifndef HAVE_SYS_SIGNAME
+    init_sys_signame();
+#endif
+
+	for (len = 0, sig = 1; sig < NSIG; sig++) {
+		name = sys_signame[sig];
+		nl = 1 + strlen(name);
+
+		if (len + nl >= termwidth) {
+			fprintf(fp, "\n");
+			len = 0;
+		} else
+			if (len != 0)
+				fprintf(fp, " ");
+		len += nl;
+		fprintf(fp, "%s", name);
+	}
+	if (len != 0)
+		fprintf(fp, "\n");
+}
+
+static void
+usage(void)
+{
+
+	fprintf(stderr, "usage: %s [-s signal_name] pid ...\n"
+	    "       %s -l [exit_status]\n"
+	    "       %s -signal_name pid ...\n"
+	    "       %s -signal_number pid ...\n",
+	    getprogname(), getprogname(), getprogname(), getprogname());
+	exit(1);
+	/* NOTREACHED */
+}
Index: /tags/kBuild-0.1.4/src/ash/bltin/printf.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/bltin/printf.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/bltin/printf.c	(revision 1780)
@@ -0,0 +1,664 @@
+/*	$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if !defined(BUILTIN) && !defined(SHELL)
+__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n");
+#endif
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)printf.c	8.2 (Berkeley) 3/22/95";
+#else
+__RCSID("$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __GNUC__
+#define ESCAPE '\e'
+#else
+#define ESCAPE 033
+#endif
+
+static void	 conv_escape_str(char *, void (*)(int));
+static char	*conv_escape(char *, char *);
+static char	*conv_expand(const char *);
+static int	 getchr(void);
+static double	 getdouble(void);
+static int	 getwidth(void);
+static intmax_t	 getintmax(void);
+static uintmax_t getuintmax(void);
+static char	*getstr(void);
+static char	*mklong(const char *, int);
+static void      check_conversion(const char *, const char *);
+static void	 usage(void);
+
+static void	b_count(int);
+static void	b_output(int);
+static size_t	b_length;
+static char	*b_fmt;
+
+static int	rval;
+static char  **gargv;
+
+#ifdef BUILTIN		/* csh builtin */
+#define main progprintf
+#endif
+
+#ifdef SHELL		/* sh (aka ash) builtin */
+#define main printfcmd
+#include "../../bin/sh/bltin/bltin.h"
+#endif /* SHELL */
+
+#define PF(f, func) { \
+	if (fieldwidth != -1) { \
+		if (precision != -1) \
+			(void)printf(f, fieldwidth, precision, func); \
+		else \
+			(void)printf(f, fieldwidth, func); \
+	} else if (precision != -1) \
+		(void)printf(f, precision, func); \
+	else \
+		(void)printf(f, func); \
+}
+
+#define APF(cpp, f, func) { \
+	if (fieldwidth != -1) { \
+		if (precision != -1) \
+			(void)asprintf(cpp, f, fieldwidth, precision, func); \
+		else \
+			(void)asprintf(cpp, f, fieldwidth, func); \
+	} else if (precision != -1) \
+		(void)asprintf(cpp, f, precision, func); \
+	else \
+		(void)asprintf(cpp, f, func); \
+}
+
+int main(int, char **);
+int main(int argc, char *argv[])
+{
+	char *fmt, *start;
+	int fieldwidth, precision;
+	char nextch;
+	char *format;
+	int ch;
+
+#if !defined(SHELL) && !defined(BUILTIN)
+	(void)setlocale (LC_ALL, "");
+#endif
+
+	while ((ch = getopt(argc, argv, "")) != -1) {
+		switch (ch) {
+		case '?':
+		default:
+			usage();
+			return 1;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1) {
+		usage();
+		return 1;
+	}
+
+	format = *argv;
+	gargv = ++argv;
+
+#define SKIP1	"#-+ 0"
+#define SKIP2	"*0123456789"
+	do {
+		/*
+		 * Basic algorithm is to scan the format string for conversion
+		 * specifications -- once one is found, find out if the field
+		 * width or precision is a '*'; if it is, gather up value.
+		 * Note, format strings are reused as necessary to use up the
+		 * provided arguments, arguments of zero/null string are
+		 * provided to use up the format string.
+		 */
+
+		/* find next format specification */
+		for (fmt = format; (ch = *fmt++) != '\0';) {
+			if (ch == '\\') {
+				char c_ch;
+				fmt = conv_escape(fmt, &c_ch);
+				putchar(c_ch);
+				continue;
+			}
+			if (ch != '%' || (*fmt == '%' && ++fmt)) {
+				(void)putchar(ch);
+				continue;
+			}
+
+			/* Ok - we've found a format specification,
+			   Save its address for a later printf(). */
+			start = fmt - 1;
+
+			/* skip to field width */
+			fmt += strspn(fmt, SKIP1);
+			fieldwidth = *fmt == '*' ? getwidth() : -1;
+
+			/* skip to possible '.', get following precision */
+			fmt += strspn(fmt, SKIP2);
+			if (*fmt == '.')
+				++fmt;
+			precision = *fmt == '*' ? getwidth() : -1;
+
+			fmt += strspn(fmt, SKIP2);
+
+			ch = *fmt;
+			if (!ch) {
+				warnx("missing format character");
+				return (1);
+			}
+			/* null terminate format string to we can use it
+			   as an argument to printf. */
+			nextch = fmt[1];
+			fmt[1] = 0;
+			switch (ch) {
+
+			case 'B': {
+				const char *p = conv_expand(getstr());
+				*fmt = 's';
+				PF(start, p);
+				break;
+			}
+			case 'b': {
+				/* There has to be a better way to do this,
+				 * but the string we generate might have
+				 * embedded nulls. */
+				static char *a, *t;
+				char *cp = getstr();
+				/* Free on entry in case shell longjumped out */
+				if (a != NULL)
+					free(a);
+				a = NULL;
+				if (t != NULL)
+					free(t);
+				t = NULL;
+				/* Count number of bytes we want to output */
+				b_length = 0;
+				conv_escape_str(cp, b_count);
+				t = malloc(b_length + 1);
+				if (t == NULL)
+					break;
+				memset(t, 'x', b_length);
+				t[b_length] = 0;
+				/* Get printf to calculate the lengths */
+				*fmt = 's';
+				APF(&a, start, t);
+				b_fmt = a;
+				/* Output leading spaces and data bytes */
+				conv_escape_str(cp, b_output);
+				/* Add any trailing spaces */
+				printf("%s", b_fmt);
+				break;
+			}
+			case 'c': {
+				char p = getchr();
+				PF(start, p);
+				break;
+			}
+			case 's': {
+				char *p = getstr();
+				PF(start, p);
+				break;
+			}
+			case 'd':
+			case 'i': {
+				intmax_t p = getintmax();
+				char *f = mklong(start, ch);
+				PF(f, p);
+				break;
+			}
+			case 'o':
+			case 'u':
+			case 'x':
+			case 'X': {
+				uintmax_t p = getuintmax();
+				char *f = mklong(start, ch);
+				PF(f, p);
+				break;
+			}
+			case 'e':
+			case 'E':
+			case 'f':
+			case 'g':
+			case 'G': {
+				double p = getdouble();
+				PF(start, p);
+				break;
+			}
+			default:
+				warnx("%s: invalid directive", start);
+				return 1;
+			}
+			*fmt++ = ch;
+			*fmt = nextch;
+			/* escape if a \c was encountered */
+			if (rval & 0x100)
+				return rval & ~0x100;
+		}
+	} while (gargv != argv && *gargv);
+
+	return rval;
+}
+
+/* helper functions for conv_escape_str */
+
+static void
+/*ARGSUSED*/
+b_count(int ch)
+{
+	b_length++;
+}
+
+/* Output one converted character for every 'x' in the 'format' */
+
+static void
+b_output(int ch)
+{
+	for (;;) {
+		switch (*b_fmt++) {
+		case 0:
+			b_fmt--;
+			return;
+		case ' ':
+			putchar(' ');
+			break;
+		default:
+			putchar(ch);
+			return;
+		}
+	}
+}
+
+
+/*
+ * Print SysV echo(1) style escape string
+ *	Halts processing string if a \c escape is encountered.
+ */
+static void
+conv_escape_str(char *str, void (*do_putchar)(int))
+{
+	int value;
+	int ch;
+	char c;
+
+	while ((ch = *str++) != '\0') {
+		if (ch != '\\') {
+			do_putchar(ch);
+			continue;
+		}
+
+		ch = *str++;
+		if (ch == 'c') {
+			/* \c as in SYSV echo - abort all processing.... */
+			rval |= 0x100;
+			break;
+		}
+
+		/*
+		 * %b string octal constants are not like those in C.
+		 * They start with a \0, and are followed by 0, 1, 2,
+		 * or 3 octal digits.
+		 */
+		if (ch == '0') {
+			int octnum = 0, i;
+			for (i = 0; i < 3; i++) {
+				if (!isdigit((unsigned char)*str) || *str > '7')
+					break;
+				octnum = (octnum << 3) | (*str++ - '0');
+			}
+			do_putchar(octnum);
+			continue;
+		}
+
+		/* \[M][^|-]C as defined by vis(3) */
+		if (ch == 'M' && *str == '-') {
+			do_putchar(0200 | str[1]);
+			str += 2;
+			continue;
+		}
+		if (ch == 'M' && *str == '^') {
+			str++;
+			value = 0200;
+			ch = '^';
+		} else
+			value = 0;
+		if (ch == '^') {
+			ch = *str++;
+			if (ch == '?')
+				value |= 0177;
+			else
+				value |= ch & 037;
+			do_putchar(value);
+			continue;
+		}
+
+		/* Finally test for sequences valid in the format string */
+		str = conv_escape(str - 1, &c);
+		do_putchar(c);
+	}
+}
+
+/*
+ * Print "standard" escape characters
+ */
+static char *
+conv_escape(char *str, char *conv_ch)
+{
+	int value;
+	int ch;
+	char num_buf[4], *num_end;
+
+	ch = *str++;
+
+	switch (ch) {
+	case '0': case '1': case '2': case '3':
+	case '4': case '5': case '6': case '7':
+		num_buf[0] = ch;
+		ch = str[0];
+		num_buf[1] = ch;
+		num_buf[2] = ch ? str[1] : 0;
+		num_buf[3] = 0;
+		value = strtoul(num_buf, &num_end, 8);
+		str += num_end  - (num_buf + 1);
+		break;
+
+	case 'x':
+		/* Hexadecimal character constants are not required to be
+		   supported (by SuS v1) because there is no consistent
+		   way to detect the end of the constant.
+		   Supporting 2 byte constants is a compromise. */
+		ch = str[0];
+		num_buf[0] = ch;
+		num_buf[1] = ch ? str[1] : 0;
+		num_buf[2] = 0;
+		value = strtoul(num_buf, &num_end, 16);
+		str += num_end - num_buf;
+		break;
+
+	case '\\':	value = '\\';	break;	/* backslash */
+	case '\'':	value = '\'';	break;	/* single quote */
+	case '"':	value = '"';	break;	/* double quote */
+	case 'a':	value = '\a';	break;	/* alert */
+	case 'b':	value = '\b';	break;	/* backspace */
+	case 'e':	value = ESCAPE;	break;	/* escape */
+	case 'f':	value = '\f';	break;	/* form-feed */
+	case 'n':	value = '\n';	break;	/* newline */
+	case 'r':	value = '\r';	break;	/* carriage-return */
+	case 't':	value = '\t';	break;	/* tab */
+	case 'v':	value = '\v';	break;	/* vertical-tab */
+
+	default:
+		warnx("unknown escape sequence `\\%c'", ch);
+		rval = 1;
+		value = ch;
+		break;
+	}
+
+	*conv_ch = value;
+	return str;
+}
+
+/* expand a string so that everything is printable */
+
+static char *
+conv_expand(const char *str)
+{
+	static char *conv_str;
+	static char no_memory[] = "<no memory>";
+	char *cp;
+	int ch;
+
+	if (conv_str)
+		free(conv_str);
+	/* get a buffer that is definitely large enough.... */
+	conv_str = malloc(4 * strlen(str) + 1);
+	if (!conv_str)
+		return no_memory;
+	cp = conv_str;
+
+	while ((ch = *(const unsigned char *)str++) != '\0') {
+		switch (ch) {
+		/* Use C escapes for expected control characters */
+		case '\\':	ch = '\\';	break;	/* backslash */
+		case '\'':	ch = '\'';	break;	/* single quote */
+		case '"':	ch = '"';	break;	/* double quote */
+		case '\a':	ch = 'a';	break;	/* alert */
+		case '\b':	ch = 'b';	break;	/* backspace */
+		case ESCAPE:	ch = 'e';	break;	/* escape */
+		case '\f':	ch = 'f';	break;	/* form-feed */
+		case '\n':	ch = 'n';	break;	/* newline */
+		case '\r':	ch = 'r';	break;	/* carriage-return */
+		case '\t':	ch = 't';	break;	/* tab */
+		case '\v':	ch = 'v';	break;	/* vertical-tab */
+		default:
+			/* Copy anything printable */
+			if (isprint(ch)) {
+				*cp++ = ch;
+				continue;
+			}
+			/* Use vis(3) encodings for the rest */
+			*cp++ = '\\';
+			if (ch & 0200) {
+				*cp++ = 'M';
+				ch &= ~0200;
+			}
+			if (ch == 0177) {
+				*cp++ = '^';
+				*cp++ = '?';
+				continue;
+			}
+			if (ch < 040) {
+				*cp++ = '^';
+				*cp++ = ch | 0100;
+				continue;
+			}
+			*cp++ = '-';
+			*cp++ = ch;
+			continue;
+		}
+		*cp++ = '\\';
+		*cp++ = ch;
+	}
+
+	*cp = 0;
+	return conv_str;
+}
+
+static char *
+mklong(const char *str, int ch)
+{
+	static char copy[64];
+	size_t len;
+
+	len = strlen(str) + 2;
+	if (len > sizeof copy) {
+		warnx("format %s too complex\n", str);
+		len = 4;
+	}
+	(void)memmove(copy, str, len - 3);
+	copy[len - 3] = 'j';
+	copy[len - 2] = ch;
+	copy[len - 1] = '\0';
+	return copy;
+}
+
+static int
+getchr(void)
+{
+	if (!*gargv)
+		return 0;
+	return (int)**gargv++;
+}
+
+static char *
+getstr(void)
+{
+	static char empty[] = "";
+	if (!*gargv)
+		return empty;
+	return *gargv++;
+}
+
+static int
+getwidth(void)
+{
+	long val;
+	char *s, *ep;
+
+	s = *gargv;
+	if (!*gargv)
+		return (0);
+	gargv++;
+
+	errno = 0;
+	val = strtoul(s, &ep, 0);
+	check_conversion(s, ep);
+
+	/* Arbitrarily 'restrict' field widths to 1Mbyte */
+	if (val < 0 || val > 1 << 20) {
+		warnx("%s: invalid field width", s);
+		return 0;
+	}
+
+	return val;
+}
+
+static intmax_t
+getintmax(void)
+{
+	intmax_t val;
+	char *cp, *ep;
+
+	cp = *gargv;
+	if (cp == NULL)
+		return 0;
+	gargv++;
+
+	if (*cp == '\"' || *cp == '\'')
+		return *(cp+1);
+
+	errno = 0;
+	val = strtoimax(cp, &ep, 0);
+	check_conversion(cp, ep);
+	return val;
+}
+
+static uintmax_t
+getuintmax(void)
+{
+	uintmax_t val;
+	char *cp, *ep;
+
+	cp = *gargv;
+	if (cp == NULL)
+		return 0;
+	gargv++;
+
+	if (*cp == '\"' || *cp == '\'')
+		return *(cp + 1);
+
+	/* strtoumax won't error -ve values */
+	while (isspace(*(unsigned char *)cp))
+		cp++;
+	if (*cp == '-') {
+		warnx("%s: expected positive numeric value", cp);
+		rval = 1;
+		return 0;
+	}
+
+	errno = 0;
+	val = strtoumax(cp, &ep, 0);
+	check_conversion(cp, ep);
+	return val;
+}
+
+static double
+getdouble(void)
+{
+	double val;
+	char *ep;
+
+	if (!*gargv)
+		return (0.0);
+
+	if (**gargv == '\"' || **gargv == '\'')
+		return (double) *((*gargv++)+1);
+
+	errno = 0;
+	val = strtod(*gargv, &ep);
+	check_conversion(*gargv++, ep);
+	return val;
+}
+
+static void
+check_conversion(const char *s, const char *ep)
+{
+	if (*ep) {
+		if (ep == s)
+			warnx("%s: expected numeric value", s);
+		else
+			warnx("%s: not completely converted", s);
+		rval = 1;
+	} else if (errno == ERANGE) {
+		warnx("%s: %s", s, strerror(ERANGE));
+		rval = 1;
+	}
+}
+
+static void
+usage(void)
+{
+	(void)fprintf(stderr, "Usage: %s format [arg ...]\n", getprogname());
+}
Index: /tags/kBuild-0.1.4/src/ash/bltin/test.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/bltin/test.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/bltin/test.c	(revision 1780)
@@ -0,0 +1,509 @@
+/* $NetBSD: test.c,v 1.26 2005/02/10 06:56:55 simonb Exp $ */
+
+/*
+ * test(1); version 7-like  --  author Erik Baalbergen
+ * modified by Eric Gisin to be used as built-in.
+ * modified by Arnold Robbins to add SVR3 compatibility
+ * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
+ * modified by J.T. Conklin for NetBSD.
+ *
+ * This program is in the Public Domain.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+__RCSID("$NetBSD: test.c,v 1.26 2005/02/10 06:56:55 simonb Exp $");
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#ifndef __sun__
+#include <err.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+/* test(1) accepts the following grammar:
+	oexpr	::= aexpr | aexpr "-o" oexpr ;
+	aexpr	::= nexpr | nexpr "-a" aexpr ;
+	nexpr	::= primary | "!" primary
+	primary	::= unary-operator operand
+		| operand binary-operator operand
+		| operand
+		| "(" oexpr ")"
+		;
+	unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
+		"-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
+
+	binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
+			"-nt"|"-ot"|"-ef";
+	operand ::= <any legal UNIX file name>
+*/
+
+enum token {
+	EOI,
+	FILRD,
+	FILWR,
+	FILEX,
+	FILEXIST,
+	FILREG,
+	FILDIR,
+	FILCDEV,
+	FILBDEV,
+	FILFIFO,
+	FILSOCK,
+	FILSYM,
+	FILGZ,
+	FILTT,
+	FILSUID,
+	FILSGID,
+	FILSTCK,
+	FILNT,
+	FILOT,
+	FILEQ,
+	FILUID,
+	FILGID,
+	STREZ,
+	STRNZ,
+	STREQ,
+	STRNE,
+	STRLT,
+	STRGT,
+	INTEQ,
+	INTNE,
+	INTGE,
+	INTGT,
+	INTLE,
+	INTLT,
+	UNOT,
+	BAND,
+	BOR,
+	LPAREN,
+	RPAREN,
+	OPERAND
+};
+
+enum token_types {
+	UNOP,
+	BINOP,
+	BUNOP,
+	BBINOP,
+	PAREN
+};
+
+static struct t_op {
+	const char *op_text;
+	short op_num, op_type;
+} const ops [] = {
+	{"-r",	FILRD,	UNOP},
+	{"-w",	FILWR,	UNOP},
+	{"-x",	FILEX,	UNOP},
+	{"-e",	FILEXIST,UNOP},
+	{"-f",	FILREG,	UNOP},
+	{"-d",	FILDIR,	UNOP},
+	{"-c",	FILCDEV,UNOP},
+	{"-b",	FILBDEV,UNOP},
+	{"-p",	FILFIFO,UNOP},
+	{"-u",	FILSUID,UNOP},
+	{"-g",	FILSGID,UNOP},
+	{"-k",	FILSTCK,UNOP},
+	{"-s",	FILGZ,	UNOP},
+	{"-t",	FILTT,	UNOP},
+	{"-z",	STREZ,	UNOP},
+	{"-n",	STRNZ,	UNOP},
+	{"-h",	FILSYM,	UNOP},		/* for backwards compat */
+	{"-O",	FILUID,	UNOP},
+	{"-G",	FILGID,	UNOP},
+	{"-L",	FILSYM,	UNOP},
+	{"-S",	FILSOCK,UNOP},
+	{"=",	STREQ,	BINOP},
+	{"!=",	STRNE,	BINOP},
+	{"<",	STRLT,	BINOP},
+	{">",	STRGT,	BINOP},
+	{"-eq",	INTEQ,	BINOP},
+	{"-ne",	INTNE,	BINOP},
+	{"-ge",	INTGE,	BINOP},
+	{"-gt",	INTGT,	BINOP},
+	{"-le",	INTLE,	BINOP},
+	{"-lt",	INTLT,	BINOP},
+	{"-nt",	FILNT,	BINOP},
+	{"-ot",	FILOT,	BINOP},
+	{"-ef",	FILEQ,	BINOP},
+	{"!",	UNOT,	BUNOP},
+	{"-a",	BAND,	BBINOP},
+	{"-o",	BOR,	BBINOP},
+	{"(",	LPAREN,	PAREN},
+	{")",	RPAREN,	PAREN},
+	{0,	0,	0}
+};
+
+static char **t_wp;
+static struct t_op const *t_wp_op;
+
+static void syntax(const char *, const char *);
+static int oexpr(enum token);
+static int aexpr(enum token);
+static int nexpr(enum token);
+static int primary(enum token);
+static int binop(void);
+static int filstat(char *, enum token);
+static enum token t_lex(char *);
+static int isoperand(void);
+static int getn(const char *);
+static int newerf(const char *, const char *);
+static int olderf(const char *, const char *);
+static int equalf(const char *, const char *);
+
+#if defined(SHELL)
+extern void error(const char *, ...) __attribute__((__noreturn__));
+#else
+static void error(const char *, ...) __attribute__((__noreturn__));
+
+static void
+error(const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+	verrx(2, msg, ap);
+	/*NOTREACHED*/
+	va_end(ap);
+}
+#endif
+
+#ifdef SHELL
+int testcmd(int, char **);
+
+int
+testcmd(int argc, char **argv)
+#else
+int main(int, char *[]);
+
+int
+main(int argc, char *argv[])
+#endif
+{
+	int res;
+
+#ifdef HAVE_SETPROGNAME
+	setprogname(argv[0]);
+#endif
+	if (strcmp(argv[0], "[") == 0) {
+		if (strcmp(argv[--argc], "]"))
+			error("missing ]");
+		argv[argc] = NULL;
+	}
+
+	if (argc < 2)
+		return 1;
+
+	t_wp = &argv[1];
+	res = !oexpr(t_lex(*t_wp));
+
+	if (*t_wp != NULL && *++t_wp != NULL)
+		syntax(*t_wp, "unexpected operator");
+
+	return res;
+}
+
+static void
+syntax(const char *op, const char *msg)
+{
+
+	if (op && *op)
+		error("%s: %s", op, msg);
+	else
+		error("%s", msg);
+}
+
+static int
+oexpr(enum token n)
+{
+	int res;
+
+	res = aexpr(n);
+	if (t_lex(*++t_wp) == BOR)
+		return oexpr(t_lex(*++t_wp)) || res;
+	t_wp--;
+	return res;
+}
+
+static int
+aexpr(enum token n)
+{
+	int res;
+
+	res = nexpr(n);
+	if (t_lex(*++t_wp) == BAND)
+		return aexpr(t_lex(*++t_wp)) && res;
+	t_wp--;
+	return res;
+}
+
+static int
+nexpr(enum token n)
+{
+
+	if (n == UNOT)
+		return !nexpr(t_lex(*++t_wp));
+	return primary(n);
+}
+
+static int
+primary(enum token n)
+{
+	enum token nn;
+	int res;
+
+	if (n == EOI)
+		return 0;		/* missing expression */
+	if (n == LPAREN) {
+		if ((nn = t_lex(*++t_wp)) == RPAREN)
+			return 0;	/* missing expression */
+		res = oexpr(nn);
+		if (t_lex(*++t_wp) != RPAREN)
+			syntax(NULL, "closing paren expected");
+		return res;
+	}
+	if (t_wp_op && t_wp_op->op_type == UNOP) {
+		/* unary expression */
+		if (*++t_wp == NULL)
+			syntax(t_wp_op->op_text, "argument expected");
+		switch (n) {
+		case STREZ:
+			return strlen(*t_wp) == 0;
+		case STRNZ:
+			return strlen(*t_wp) != 0;
+		case FILTT:
+			return isatty(getn(*t_wp));
+		default:
+			return filstat(*t_wp, n);
+		}
+	}
+
+	if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
+		return binop();
+	}
+
+	return strlen(*t_wp) > 0;
+}
+
+static int
+binop(void)
+{
+	const char *opnd1, *opnd2;
+	struct t_op const *op;
+
+	opnd1 = *t_wp;
+	(void) t_lex(*++t_wp);
+	op = t_wp_op;
+
+	if ((opnd2 = *++t_wp) == NULL)
+		syntax(op->op_text, "argument expected");
+
+	switch (op->op_num) {
+	case STREQ:
+		return strcmp(opnd1, opnd2) == 0;
+	case STRNE:
+		return strcmp(opnd1, opnd2) != 0;
+	case STRLT:
+		return strcmp(opnd1, opnd2) < 0;
+	case STRGT:
+		return strcmp(opnd1, opnd2) > 0;
+	case INTEQ:
+		return getn(opnd1) == getn(opnd2);
+	case INTNE:
+		return getn(opnd1) != getn(opnd2);
+	case INTGE:
+		return getn(opnd1) >= getn(opnd2);
+	case INTGT:
+		return getn(opnd1) > getn(opnd2);
+	case INTLE:
+		return getn(opnd1) <= getn(opnd2);
+	case INTLT:
+		return getn(opnd1) < getn(opnd2);
+	case FILNT:
+		return newerf(opnd1, opnd2);
+	case FILOT:
+		return olderf(opnd1, opnd2);
+	case FILEQ:
+		return equalf(opnd1, opnd2);
+	default:
+		abort();
+		/* NOTREACHED */
+	}
+}
+
+static int
+filstat(char *nm, enum token mode)
+{
+	struct stat s;
+
+	if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s))
+		return 0;
+
+	switch (mode) {
+	case FILRD:
+		return access(nm, R_OK) == 0;
+	case FILWR:
+		return access(nm, W_OK) == 0;
+	case FILEX:
+		return access(nm, X_OK) == 0;
+	case FILEXIST:
+		return access(nm, F_OK) == 0;
+	case FILREG:
+		return S_ISREG(s.st_mode);
+	case FILDIR:
+		return S_ISDIR(s.st_mode);
+	case FILCDEV:
+#ifdef S_ISCHR
+		return S_ISCHR(s.st_mode);
+#else
+        return 0;
+#endif
+	case FILBDEV:
+#ifdef S_ISBLK
+		return S_ISBLK(s.st_mode);
+#else
+        return 0;
+#endif
+	case FILFIFO:
+#ifdef S_ISFIFO
+		return S_ISFIFO(s.st_mode);
+#else
+        return 0;
+#endif
+	case FILSOCK:
+#ifdef S_ISSOCK
+		return S_ISSOCK(s.st_mode);
+#else
+        return 0;
+#endif
+	case FILSYM:
+		return S_ISLNK(s.st_mode);
+	case FILSUID:
+		return (s.st_mode & S_ISUID) != 0;
+	case FILSGID:
+		return (s.st_mode & S_ISGID) != 0;
+	case FILSTCK:
+#ifdef S_ISVTX
+		return (s.st_mode & S_ISVTX) != 0;
+#else
+        return 0;
+#endif
+	case FILGZ:
+		return s.st_size > (off_t)0;
+	case FILUID:
+		return s.st_uid == geteuid();
+	case FILGID:
+		return s.st_gid == getegid();
+	default:
+		return 1;
+	}
+}
+
+static enum token
+t_lex(char *s)
+{
+	struct t_op const *op;
+
+	op = ops;
+
+	if (s == 0) {
+		t_wp_op = NULL;
+		return EOI;
+	}
+	while (op->op_text) {
+		if (strcmp(s, op->op_text) == 0) {
+			if ((op->op_type == UNOP && isoperand()) ||
+			    (op->op_num == LPAREN && *(t_wp+1) == 0))
+				break;
+			t_wp_op = op;
+			return op->op_num;
+		}
+		op++;
+	}
+	t_wp_op = NULL;
+	return OPERAND;
+}
+
+static int
+isoperand(void)
+{
+	struct t_op const *op;
+	char *s, *t;
+
+	op = ops;
+	if ((s  = *(t_wp+1)) == 0)
+		return 1;
+	if ((t = *(t_wp+2)) == 0)
+		return 0;
+	while (op->op_text) {
+		if (strcmp(s, op->op_text) == 0)
+	    		return op->op_type == BINOP &&
+	    		    (t[0] != ')' || t[1] != '\0');
+		op++;
+	}
+	return 0;
+}
+
+/* atoi with error detection */
+static int
+getn(const char *s)
+{
+	char *p;
+	long r;
+
+	errno = 0;
+	r = strtol(s, &p, 10);
+
+	if (errno != 0)
+	      error("%s: out of range", s);
+
+	while (isspace((unsigned char)*p))
+	      p++;
+
+	if (*p)
+	      error("%s: bad number", s);
+
+	return (int) r;
+}
+
+static int
+newerf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+		stat(f2, &b2) == 0 &&
+		b1.st_mtime > b2.st_mtime);
+}
+
+static int
+olderf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+		stat(f2, &b2) == 0 &&
+		b1.st_mtime < b2.st_mtime);
+}
+
+static int
+equalf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+		stat(f2, &b2) == 0 &&
+		b1.st_dev == b2.st_dev &&
+		b1.st_ino == b2.st_ino);
+}
Index: /tags/kBuild-0.1.4/src/ash/builtins.def
===================================================================
--- /tags/kBuild-0.1.4/src/ash/builtins.def	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/builtins.def	(revision 1780)
@@ -0,0 +1,92 @@
+#!/bin/sh -
+#	$NetBSD: builtins.def,v 1.21 2004/07/13 15:05:59 seb Exp $
+#
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)builtins.def	8.4 (Berkeley) 5/4/95
+
+#
+# This file lists all the builtin commands.  The first column is the name
+# of a C routine.
+# The -j flag specifies that this command is to be excluded from systems
+# without job control.
+# The -h flag specifies that this command is to be excluded from systems
+# based on the SMALL compile-time symbol.
+# The -s flag specifies that this is a posix 'special builtin' command.
+# The -u flag specifies that this is a posix 'standard utility'.
+# The rest of the line specifies the command name or names used to run
+# the command.
+
+bltincmd	-u command
+bgcmd -j	-u bg
+breakcmd	-s break -s continue
+cdcmd		-u cd chdir
+dotcmd		-s .
+echocmd		echo
+evalcmd		-s eval
+execcmd		-s exec
+exitcmd		-s exit
+expcmd		exp let
+exportcmd	-s export -s readonly
+falsecmd	-u false
+histcmd -h	-u fc
+inputrc		inputrc
+fgcmd -j	-u fg
+getoptscmd	-u getopts
+hashcmd		hash
+jobidcmd	jobid
+jobscmd		-u jobs
+localcmd	local
+#ifndef SMALL
+printfcmd	printf
+#endif
+pwdcmd		-u pwd
+readcmd		-u read
+returncmd	-s return
+setcmd		-s set
+setvarcmd	setvar
+shiftcmd	-s shift
+timescmd	-s times
+trapcmd		-s trap
+truecmd		-s : -u true
+typecmd		type
+umaskcmd	-u umask
+unaliascmd	-u unalias
+unsetcmd	-s unset
+waitcmd		-u wait
+aliascmd	-u alias
+ulimitcmd	ulimit
+testcmd		test [
+killcmd		-u kill		# mandated by posix for 'kill %job'
+wordexpcmd	wordexp
+#newgrp		-u newgrp	# optional command in posix
+
+#exprcmd	expr
Index: /tags/kBuild-0.1.4/src/ash/cd.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/cd.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/cd.c	(revision 1780)
@@ -0,0 +1,448 @@
+/*	$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cd.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+/*
+ * The cd and pwd commands.
+ */
+
+#include "shell.h"
+#include "var.h"
+#include "nodes.h"	/* for jobs.h */
+#include "jobs.h"
+#include "options.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "exec.h"
+#include "redir.h"
+#include "mystring.h"
+#include "show.h"
+#include "cd.h"
+
+STATIC int docd(char *, int);
+STATIC char *getcomponent(void);
+STATIC void updatepwd(char *);
+STATIC void find_curdir(int noerror);
+
+char *curdir = NULL;		/* current working directory */
+char *prevdir;			/* previous working directory */
+STATIC char *cdcomppath;
+
+int
+cdcmd(int argc, char **argv)
+{
+	const char *dest;
+	const char *path;
+	char *p, *d;
+	struct stat statb;
+	int print = cdprint;	/* set -cdprint to enable */
+
+	nextopt(nullstr);
+
+	/*
+	 * Try (quite hard) to have 'curdir' defined, nothing has set
+	 * it on entry to the shell, but we want 'cd fred; cd -' to work.
+	 */
+	getpwd(1);
+	dest = *argptr;
+	if (dest == NULL) {
+		dest = bltinlookup("HOME", 1);
+		if (dest == NULL)
+			error("HOME not set");
+	} else {
+		if (argptr[1]) {
+			/* Do 'ksh' style substitution */
+			if (!curdir)
+				error("PWD not set");
+			p = strstr(curdir, dest);
+			if (!p)
+				error("bad substitution");
+			d = stalloc(strlen(curdir) + strlen(argptr[1]) + 1);
+			memcpy(d, curdir, p - curdir);
+			strcpy(d + (p - curdir), argptr[1]);
+			strcat(d, p + strlen(dest));
+			dest = d;
+			print = 1;
+		}
+	}
+
+	if (dest[0] == '-' && dest[1] == '\0') {
+		dest = prevdir ? prevdir : curdir;
+		print = 1;
+	}
+	if (*dest == '\0')
+	        dest = ".";
+	if (IS_ROOT(dest) || (path = bltinlookup("CDPATH", 1)) == NULL)
+		path = nullstr;
+	while ((p = padvance(&path, dest)) != NULL) {
+		if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
+			if (!print) {
+				/*
+				 * XXX - rethink
+				 */
+				if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
+					p += 2;
+				print = strcmp(p, dest);
+			}
+			if (docd(p, print) >= 0)
+				return 0;
+
+		}
+	}
+	error("can't cd to %s", dest);
+	/* NOTREACHED */
+}
+
+
+/*
+ * Actually do the chdir.  In an interactive shell, print the
+ * directory name if "print" is nonzero.
+ */
+
+STATIC int
+docd(char *dest, int print)
+{
+	char *p;
+	char *q;
+	char *component;
+	struct stat statb;
+	int first;
+	int badstat;
+
+	TRACE(("docd(\"%s\", %d) called\n", dest, print));
+
+	/*
+	 *  Check each component of the path. If we find a symlink or
+	 *  something we can't stat, clear curdir to force a getcwd()
+	 *  next time we get the value of the current directory.
+	 */
+	badstat = 0;
+	cdcomppath = stalloc(strlen(dest) + 1);
+	scopy(dest, cdcomppath);
+	STARTSTACKSTR(p);
+	if (IS_ROOT(dest)) {
+		STPUTC('/', p);
+		cdcomppath++;
+	}
+	first = 1;
+	while ((q = getcomponent()) != NULL) {
+		if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
+			continue;
+		if (! first)
+			STPUTC('/', p);
+		first = 0;
+		component = q;
+		while (*q)
+			STPUTC(*q++, p);
+		if (equal(component, ".."))
+			continue;
+		STACKSTRNUL(p);
+		if ((lstat(stackblock(), &statb) < 0)
+		    || (S_ISLNK(statb.st_mode)))  {
+			/* print = 1; */
+			badstat = 1;
+			break;
+		}
+	}
+
+	INTOFF;
+	if (chdir(dest) < 0) {
+		INTON;
+		return -1;
+	}
+	updatepwd(badstat ? NULL : dest);
+	INTON;
+	if (print && iflag && curdir)
+		out1fmt("%s\n", curdir);
+	return 0;
+}
+
+
+/*
+ * Get the next component of the path name pointed to by cdcomppath.
+ * This routine overwrites the string pointed to by cdcomppath.
+ */
+
+STATIC char *
+getcomponent()
+{
+	char *p;
+	char *start;
+
+	if ((p = cdcomppath) == NULL)
+		return NULL;
+	start = cdcomppath;
+	while (*p != '/' && *p != '\0')
+		p++;
+	if (*p == '\0') {
+		cdcomppath = NULL;
+	} else {
+		*p++ = '\0';
+		cdcomppath = p;
+	}
+	return start;
+}
+
+
+
+/*
+ * Update curdir (the name of the current directory) in response to a
+ * cd command.  We also call hashcd to let the routines in exec.c know
+ * that the current directory has changed.
+ */
+
+STATIC void
+updatepwd(char *dir)
+{
+	char *new;
+	char *p;
+
+	hashcd();				/* update command hash table */
+
+	/*
+	 * If our argument is NULL, we don't know the current directory
+	 * any more because we traversed a symbolic link or something
+	 * we couldn't stat().
+	 */
+	if (dir == NULL || curdir == NULL)  {
+		if (prevdir)
+			ckfree(prevdir);
+		INTOFF;
+		prevdir = curdir;
+		curdir = NULL;
+		getpwd(1);
+		INTON;
+		if (curdir)
+			setvar("PWD", curdir, VEXPORT);
+		else
+			unsetvar("PWD", 0);
+		return;
+	}
+	cdcomppath = stalloc(strlen(dir) + 1);
+	scopy(dir, cdcomppath);
+	STARTSTACKSTR(new);
+	if (!IS_ROOT(dir)) {
+		p = curdir;
+		while (*p)
+			STPUTC(*p++, new);
+		if (p[-1] == '/')
+			STUNPUTC(new);
+	}
+	while ((p = getcomponent()) != NULL) {
+		if (equal(p, "..")) {
+			while (new > stackblock() && (STUNPUTC(new), *new) != '/');
+		} else if (*p != '\0' && ! equal(p, ".")) {
+			STPUTC('/', new);
+			while (*p)
+				STPUTC(*p++, new);
+		}
+	}
+	if (new == stackblock())
+		STPUTC('/', new);
+	STACKSTRNUL(new);
+	INTOFF;
+	if (prevdir)
+		ckfree(prevdir);
+	prevdir = curdir;
+	curdir = savestr(stackblock());
+	setvar("PWD", curdir, VEXPORT);
+	INTON;
+}
+
+/*
+ * Posix says the default should be 'pwd -L' (as below), however
+ * the 'cd' command (above) does something much nearer to the
+ * posix 'cd -P' (not the posix default of 'cd -L').
+ * If 'cd' is changed to support -P/L then the default here
+ * needs to be revisited if the historic behaviour is to be kept.
+ */
+
+int
+pwdcmd(int argc, char **argv)
+{
+	int i;
+	char opt = 'L';
+
+	while ((i = nextopt("LP")) != '\0')
+		opt = i;
+	if (*argptr)
+		error("unexpected argument");
+
+	if (opt == 'L')
+		getpwd(0);
+	else
+		find_curdir(0);
+
+	setvar("PWD", curdir, VEXPORT);
+	out1str(curdir);
+	out1c('\n');
+	return 0;
+}
+
+
+
+
+#define MAXPWD 256
+
+/*
+ * Find out what the current directory is. If we already know the current
+ * directory, this routine returns immediately.
+ */
+void
+getpwd(int noerror)
+{
+	char *pwd;
+	struct stat stdot, stpwd;
+	static int first = 1;
+
+	if (curdir)
+		return;
+
+	if (first) {
+		first = 0;
+		pwd = getenv("PWD");
+		if (pwd && IS_ROOT(pwd) && stat(".", &stdot) != -1 &&
+		    stat(pwd, &stpwd) != -1 &&
+		    stdot.st_dev == stpwd.st_dev &&
+		    stdot.st_ino == stpwd.st_ino) {
+			curdir = savestr(pwd);
+			return;
+		}
+	}
+
+	find_curdir(noerror);
+
+	return;
+}
+
+STATIC void
+find_curdir(int noerror)
+{
+	int i;
+	char *pwd;
+
+	/*
+	 * Things are a bit complicated here; we could have just used
+	 * getcwd, but traditionally getcwd is implemented using popen
+	 * to /bin/pwd. This creates a problem for us, since we cannot
+	 * keep track of the job if it is being ran behind our backs.
+	 * So we re-implement getcwd(), and we suppress interrupts
+	 * throughout the process. This is not completely safe, since
+	 * the user can still break out of it by killing the pwd program.
+	 * We still try to use getcwd for systems that we know have a
+	 * c implementation of getcwd, that does not open a pipe to
+	 * /bin/pwd.
+	 */
+#if defined(__NetBSD__) || defined(__SVR4) || defined(__INNOTEK_LIBC__) || 1 /* bird: nobody spawns pwd any more (we hope). */
+
+	for (i = MAXPWD;; i *= 2) {
+		pwd = stalloc(i);
+		if (getcwd(pwd, i) != NULL) {
+			curdir = savestr(pwd);
+			return;
+		}
+		stunalloc(pwd);
+		if (errno == ERANGE)
+			continue;
+		if (!noerror)
+			error("getcwd() failed: %s", strerror(errno));
+		return;
+	}
+#else
+	{
+		char *p;
+		int status;
+		struct job *jp;
+		int pip[2];
+
+		pwd = stalloc(MAXPWD);
+		INTOFF;
+		if (pipe(pip) < 0)
+			error("Pipe call failed");
+		jp = makejob((union node *)NULL, 1);
+		if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
+			(void) close(pip[0]);
+			if (pip[1] != 1) {
+				close(1);
+				copyfd(pip[1], 1);
+				close(pip[1]);
+			}
+			(void) execl("/bin/pwd", "pwd", (char *)0);
+			error("Cannot exec /bin/pwd");
+		}
+		(void) close(pip[1]);
+		pip[1] = -1;
+		p = pwd;
+		while ((i = read(pip[0], p, pwd + MAXPWD - p)) > 0
+		     || (i == -1 && errno == EINTR)) {
+			if (i > 0)
+				p += i;
+		}
+		(void) close(pip[0]);
+		pip[0] = -1;
+		status = waitforjob(jp);
+		if (status != 0)
+			error((char *)0);
+		if (i < 0 || p == pwd || p[-1] != '\n') {
+			if (noerror) {
+				INTON;
+				return;
+			}
+			error("pwd command failed");
+		}
+		p[-1] = '\0';
+		INTON;
+		curdir = savestr(pwd);
+		return;
+	}
+#endif
+}
Index: /tags/kBuild-0.1.4/src/ash/cd.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/cd.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/cd.h	(revision 1780)
@@ -0,0 +1,43 @@
+/*	$NetBSD: cd.h,v 1.4 2003/08/07 09:05:30 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+void	getpwd(int);
+int	cdcmd(int, char **);
+int	pwdcmd(int, char **);
+#ifdef PC_DRIVE_LETTERS
+#define IS_ROOT(path) (   *(path) == '/' \
+                       || *(path) == '\\' \
+                       ||  ( ((*(path) >= 'A' && *(path) <= 'Z') || (*(path) >= 'a' && *(path) <= 'z')) \
+                             && (path)[1] == ':') )
+#else
+#define IS_ROOT(path) ( *(path) == '/' )
+#endif
Index: /tags/kBuild-0.1.4/src/ash/error.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/error.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/error.c	(revision 1780)
@@ -0,0 +1,370 @@
+/*	$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Errors and exceptions.
+ */
+
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "shell.h"
+#include "main.h"
+#include "options.h"
+#include "output.h"
+#include "error.h"
+#include "show.h"
+
+
+/*
+ * Code to handle exceptions in C.
+ */
+
+struct jmploc *handler;
+int exception;
+volatile int suppressint;
+volatile int intpending;
+char *commandname;
+
+
+static void exverror(int, const char *, va_list)
+    __attribute__((__noreturn__));
+
+/*
+ * Called to raise an exception.  Since C doesn't include exceptions, we
+ * just do a longjmp to the exception handler.  The type of exception is
+ * stored in the global variable "exception".
+ */
+
+void
+exraise(int e)
+{
+	if (handler == NULL)
+		abort();
+	exception = e;
+	longjmp(handler->loc, 1);
+}
+
+
+/*
+ * Called from trap.c when a SIGINT is received.  (If the user specifies
+ * that SIGINT is to be trapped or ignored using the trap builtin, then
+ * this routine is not called.)  Suppressint is nonzero when interrupts
+ * are held using the INTOFF macro.  The call to _exit is necessary because
+ * there is a short period after a fork before the signal handlers are
+ * set to the appropriate value for the child.  (The test for iflag is
+ * just defensive programming.)
+ */
+
+void
+onint(void)
+{
+	sigset_t nsigset;
+
+	if (suppressint) {
+		intpending = 1;
+		return;
+	}
+	intpending = 0;
+	sigemptyset(&nsigset);
+	sigprocmask(SIG_SETMASK, &nsigset, NULL);
+	if (rootshell && iflag)
+		exraise(EXINT);
+	else {
+		signal(SIGINT, SIG_DFL);
+		raise(SIGINT);
+	}
+	/* NOTREACHED */
+}
+
+static void
+exvwarning(int sv_errno, const char *msg, va_list ap)
+{
+	/* Partially emulate line buffered output so that:
+	 *	printf '%d\n' 1 a 2
+	 * and
+	 *	printf '%d %d %d\n' 1 a 2
+	 * both generate sensible text when stdout and stderr are merged.
+	 */
+	if (output.nextc != output.buf && output.nextc[-1] == '\n')
+		flushout(&output);
+	if (commandname)
+		outfmt(&errout, "%s: ", commandname);
+	if (msg != NULL) {
+		doformat(&errout, msg, ap);
+		if (sv_errno >= 0)
+			outfmt(&errout, ": ");
+	}
+	if (sv_errno >= 0)
+		outfmt(&errout, "%s", strerror(sv_errno));
+	out2c('\n');
+	flushout(&errout);
+}
+
+/*
+ * Exverror is called to raise the error exception.  If the second argument
+ * is not NULL then error prints an error message using printf style
+ * formatting.  It then raises the error exception.
+ */
+static void
+exverror(int cond, const char *msg, va_list ap)
+{
+	CLEAR_PENDING_INT;
+	INTOFF;
+
+#ifdef DEBUG
+	if (msg) {
+		TRACE(("exverror(%d, \"", cond));
+		TRACEV((msg, ap));
+		TRACE(("\") pid=%d\n", getpid()));
+	} else
+		TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
+#endif
+	if (msg)
+		exvwarning(-1, msg, ap);
+
+	output_flushall();
+	exraise(cond);
+	/* NOTREACHED */
+}
+
+
+void
+error(const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+	exverror(EXERROR, msg, ap);
+	/* NOTREACHED */
+	va_end(ap);
+}
+
+
+void
+exerror(int cond, const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+	exverror(cond, msg, ap);
+	/* NOTREACHED */
+	va_end(ap);
+}
+
+/*
+ * error/warning routines for external builtins
+ */
+
+void
+sh_exit(int rval)
+{
+	exerrno = rval & 255;
+	exraise(EXEXEC);
+}
+
+void
+sh_err(int status, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(errno, fmt, ap);
+	va_end(ap);
+	sh_exit(status);
+}
+
+void
+sh_verr(int status, const char *fmt, va_list ap)
+{
+	exvwarning(errno, fmt, ap);
+	sh_exit(status);
+}
+
+void
+sh_errx(int status, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(-1, fmt, ap);
+	va_end(ap);
+	sh_exit(status);
+}
+
+void
+sh_verrx(int status, const char *fmt, va_list ap)
+{
+	exvwarning(-1, fmt, ap);
+	sh_exit(status);
+}
+
+void
+sh_warn(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(errno, fmt, ap);
+	va_end(ap);
+}
+
+void
+sh_vwarn(const char *fmt, va_list ap)
+{
+	exvwarning(errno, fmt, ap);
+}
+
+void
+sh_warnx(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(-1, fmt, ap);
+	va_end(ap);
+}
+
+void
+sh_vwarnx(const char *fmt, va_list ap)
+{
+	exvwarning(-1, fmt, ap);
+}
+
+
+/*
+ * Table of error messages.
+ */
+
+struct errname {
+	short errcode;		/* error number */
+	short action;		/* operation which encountered the error */
+	const char *msg;	/* text describing the error */
+};
+
+
+#define ALL (E_OPEN|E_CREAT|E_EXEC)
+
+STATIC const struct errname errormsg[] = {
+	{ EINTR,	ALL,	"interrupted" },
+	{ EACCES,	ALL,	"permission denied" },
+	{ EIO,		ALL,	"I/O error" },
+	{ EEXIST,	ALL,	"file exists" },
+	{ ENOENT,	E_OPEN,	"no such file" },
+	{ ENOENT,	E_CREAT,"directory nonexistent" },
+	{ ENOENT,	E_EXEC,	"not found" },
+	{ ENOTDIR,	E_OPEN,	"no such file" },
+	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
+	{ ENOTDIR,	E_EXEC,	"not found" },
+	{ EISDIR,	ALL,	"is a directory" },
+#ifdef EMFILE
+	{ EMFILE,	ALL,	"too many open files" },
+#endif
+	{ ENFILE,	ALL,	"file table overflow" },
+	{ ENOSPC,	ALL,	"file system full" },
+#ifdef EDQUOT
+	{ EDQUOT,	ALL,	"disk quota exceeded" },
+#endif
+#ifdef ENOSR
+	{ ENOSR,	ALL,	"no streams resources" },
+#endif
+	{ ENXIO,	ALL,	"no such device or address" },
+	{ EROFS,	ALL,	"read-only file system" },
+#ifdef ETXTBSY
+	{ ETXTBSY,	ALL,	"text busy" },
+#endif
+#ifdef EAGAIN
+	{ EAGAIN,	E_EXEC,	"not enough memory" },
+#endif
+	{ ENOMEM,	ALL,	"not enough memory" },
+#ifdef ENOLINK
+	{ ENOLINK,	ALL,	"remote access failed" },
+#endif
+#ifdef EMULTIHOP
+	{ EMULTIHOP,	ALL,	"remote access failed" },
+#endif
+#ifdef ECOMM
+	{ ECOMM,	ALL,	"remote access failed" },
+#endif
+#ifdef ESTALE
+	{ ESTALE,	ALL,	"remote access failed" },
+#endif
+#ifdef ETIMEDOUT
+	{ ETIMEDOUT,	ALL,	"remote access failed" },
+#endif
+#ifdef ELOOP
+	{ ELOOP,	ALL,	"symbolic link loop" },
+#endif
+	{ E2BIG,	E_EXEC,	"argument list too long" },
+#ifdef ELIBACC
+	{ ELIBACC,	E_EXEC,	"shared library missing" },
+#endif
+	{ 0,		0,	NULL },
+};
+
+
+/*
+ * Return a string describing an error.  The returned string may be a
+ * pointer to a static buffer that will be overwritten on the next call.
+ * Action describes the operation that got the error.
+ */
+
+const char *
+errmsg(int e, int action)
+{
+	struct errname const *ep;
+	static char buf[12];
+
+	for (ep = errormsg ; ep->errcode ; ep++) {
+		if (ep->errcode == e && (ep->action & action) != 0)
+			return ep->msg;
+	}
+	fmtstr(buf, sizeof buf, "error %d", e);
+	return buf;
+}
Index: /tags/kBuild-0.1.4/src/ash/error.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/error.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/error.h	(revision 1780)
@@ -0,0 +1,117 @@
+/*	$NetBSD: error.h,v 1.16 2003/08/07 09:05:30 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)error.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <stdarg.h>
+
+/*
+ * Types of operations (passed to the errmsg routine).
+ */
+
+#define E_OPEN 01	/* opening a file */
+#define E_CREAT 02	/* creating a file */
+#define E_EXEC 04	/* executing a program */
+
+
+/*
+ * We enclose jmp_buf in a structure so that we can declare pointers to
+ * jump locations.  The global variable handler contains the location to
+ * jump to when an exception occurs, and the global variable exception
+ * contains a code identifying the exeception.  To implement nested
+ * exception handlers, the user should save the value of handler on entry
+ * to an inner scope, set handler to point to a jmploc structure for the
+ * inner scope, and restore handler on exit from the scope.
+ */
+
+#include <setjmp.h>
+
+struct jmploc {
+	jmp_buf loc;
+};
+
+extern struct jmploc *handler;
+extern int exception;
+extern int exerrno;	/* error for EXEXEC */
+
+/* exceptions */
+#define EXINT 0		/* SIGINT received */
+#define EXERROR 1	/* a generic error */
+#define EXSHELLPROC 2	/* execute a shell procedure */
+#define EXEXEC 3	/* command execution failed */
+
+
+/*
+ * These macros allow the user to suspend the handling of interrupt signals
+ * over a period of time.  This is similar to SIGHOLD to or sigblock, but
+ * much more efficient and portable.  (But hacking the kernel is so much
+ * more fun than worrying about efficiency and portability. :-))
+ */
+
+extern volatile int suppressint;
+extern volatile int intpending;
+
+#define INTOFF suppressint++
+#define INTON { if (--suppressint == 0 && intpending) onint(); }
+#define FORCEINTON {suppressint = 0; if (intpending) onint();}
+#define CLEAR_PENDING_INT intpending = 0
+#define int_pending() intpending
+
+void exraise(int) __attribute__((__noreturn__));
+void onint(void);
+void error(const char *, ...) __attribute__((__noreturn__));
+void exerror(int, const char *, ...) __attribute__((__noreturn__));
+const char *errmsg(int, int);
+
+void sh_err(int, const char *, ...) __attribute__((__noreturn__));
+void sh_verr(int, const char *, va_list) __attribute__((__noreturn__));
+void sh_errx(int, const char *, ...) __attribute__((__noreturn__));
+void sh_verrx(int, const char *, va_list) __attribute__((__noreturn__));
+void sh_warn(const char *, ...);
+void sh_vwarn(const char *, va_list);
+void sh_warnx(const char *, ...);
+void sh_vwarnx(const char *, va_list);
+
+void sh_exit(int) __attribute__((__noreturn__));
+
+
+/*
+ * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
+ * so we use _setjmp instead.
+ */
+
+#if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__) && !defined(__KLIBC__) && !defined(_MSC_VER)
+#define setjmp(jmploc)	_setjmp(jmploc)
+#define longjmp(jmploc, val)	_longjmp(jmploc, val)
+#endif
Index: /tags/kBuild-0.1.4/src/ash/eval.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/eval.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/eval.c	(revision 1780)
@@ -0,0 +1,1272 @@
+/*	$NetBSD: eval.c,v 1.84 2005/06/23 23:05:29 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
+#else
+__RCSID("$NetBSD: eval.c,v 1.84 2005/06/23 23:05:29 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/times.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifdef HAVE_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#ifdef __sun__
+#include <iso/limits_iso.h>
+#endif
+
+/*
+ * Evaluate a command.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "syntax.h"
+#include "expand.h"
+#include "parser.h"
+#include "jobs.h"
+#include "eval.h"
+#include "builtins.h"
+#include "options.h"
+#include "exec.h"
+#include "redir.h"
+#include "input.h"
+#include "output.h"
+#include "trap.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "show.h"
+#include "mystring.h"
+#include "main.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+
+
+/* flags in argument to evaltree */
+#define EV_EXIT 01		/* exit after evaluating tree */
+#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
+#define EV_BACKCMD 04		/* command executing within back quotes */
+
+int evalskip;			/* set if we are skipping commands */
+STATIC int skipcount;		/* number of levels to skip */
+MKINIT int loopnest;		/* current loop nesting level */
+int funcnest;			/* depth of function calls */
+
+
+char *commandname;
+struct strlist *cmdenviron;
+int exitstatus;			/* exit status of last command */
+int back_exitstatus;		/* exit status of backquoted command */
+
+
+STATIC void evalloop(union node *, int);
+STATIC void evalfor(union node *, int);
+STATIC void evalcase(union node *, int);
+STATIC void evalsubshell(union node *, int);
+STATIC void expredir(union node *);
+STATIC void evalpipe(union node *);
+STATIC void evalcommand(union node *, int, struct backcmd *);
+STATIC void prehash(union node *);
+
+
+/*
+ * Called to reset things after an exception.
+ */
+
+#ifdef mkinit
+INCLUDE "eval.h"
+
+RESET {
+	evalskip = 0;
+	loopnest = 0;
+	funcnest = 0;
+}
+
+SHELLPROC {
+	exitstatus = 0;
+}
+#endif
+
+static int
+sh_pipe(int fds[2])
+{
+	int nfd;
+
+	if (pipe(fds))
+		return -1;
+
+	if (fds[0] < 3) {
+		nfd = fcntl(fds[0], F_DUPFD, 3);
+		if (nfd != -1) {
+			close(fds[0]);
+			fds[0] = nfd;
+		}
+	}
+
+	if (fds[1] < 3) {
+		nfd = fcntl(fds[1], F_DUPFD, 3);
+		if (nfd != -1) {
+			close(fds[1]);
+			fds[1] = nfd;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * The eval commmand.
+ */
+
+int
+evalcmd(int argc, char **argv)
+{
+        char *p;
+        char *concat;
+        char **ap;
+
+        if (argc > 1) {
+                p = argv[1];
+                if (argc > 2) {
+                        STARTSTACKSTR(concat);
+                        ap = argv + 2;
+                        for (;;) {
+                                while (*p)
+                                        STPUTC(*p++, concat);
+                                if ((p = *ap++) == NULL)
+                                        break;
+                                STPUTC(' ', concat);
+                        }
+                        STPUTC('\0', concat);
+                        p = grabstackstr(concat);
+                }
+                evalstring(p, EV_TESTED);
+        }
+        return exitstatus;
+}
+
+
+/*
+ * Execute a command or commands contained in a string.
+ */
+
+void
+evalstring(char *s, int flag)
+{
+	union node *n;
+	struct stackmark smark;
+
+	setstackmark(&smark);
+	setinputstring(s, 1);
+
+	while ((n = parsecmd(0)) != NEOF) {
+		evaltree(n, flag);
+		popstackmark(&smark);
+	}
+	popfile();
+	popstackmark(&smark);
+}
+
+
+
+/*
+ * Evaluate a parse tree.  The value is left in the global variable
+ * exitstatus.
+ */
+
+void
+evaltree(union node *n, int flags)
+{
+	if (n == NULL) {
+		TRACE(("evaltree(NULL) called\n"));
+		exitstatus = 0;
+		goto out;
+	}
+#ifndef SMALL
+	displayhist = 1;	/* show history substitutions done with fc */
+#endif
+	TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
+	    getpid(), n, n->type, flags));
+	switch (n->type) {
+	case NSEMI:
+		evaltree(n->nbinary.ch1, flags & EV_TESTED);
+		if (evalskip)
+			goto out;
+		evaltree(n->nbinary.ch2, flags);
+		break;
+	case NAND:
+		evaltree(n->nbinary.ch1, EV_TESTED);
+		if (evalskip || exitstatus != 0)
+			goto out;
+		evaltree(n->nbinary.ch2, flags);
+		break;
+	case NOR:
+		evaltree(n->nbinary.ch1, EV_TESTED);
+		if (evalskip || exitstatus == 0)
+			goto out;
+		evaltree(n->nbinary.ch2, flags);
+		break;
+	case NREDIR:
+		expredir(n->nredir.redirect);
+		redirect(n->nredir.redirect, REDIR_PUSH);
+		evaltree(n->nredir.n, flags);
+		popredir();
+		break;
+	case NSUBSHELL:
+		evalsubshell(n, flags);
+		break;
+	case NBACKGND:
+		evalsubshell(n, flags);
+		break;
+	case NIF: {
+		evaltree(n->nif.test, EV_TESTED);
+		if (evalskip)
+			goto out;
+		if (exitstatus == 0)
+			evaltree(n->nif.ifpart, flags);
+		else if (n->nif.elsepart)
+			evaltree(n->nif.elsepart, flags);
+		else
+			exitstatus = 0;
+		break;
+	}
+	case NWHILE:
+	case NUNTIL:
+		evalloop(n, flags);
+		break;
+	case NFOR:
+		evalfor(n, flags);
+		break;
+	case NCASE:
+		evalcase(n, flags);
+		break;
+	case NDEFUN:
+		defun(n->narg.text, n->narg.next);
+		exitstatus = 0;
+		break;
+	case NNOT:
+		evaltree(n->nnot.com, EV_TESTED);
+		exitstatus = !exitstatus;
+		break;
+	case NPIPE:
+		evalpipe(n);
+		break;
+	case NCMD:
+		evalcommand(n, flags, (struct backcmd *)NULL);
+		break;
+	default:
+		out1fmt("Node type = %d\n", n->type);
+		flushout(&output);
+		break;
+	}
+out:
+	if (pendingsigs)
+		dotrap();
+	if ((flags & EV_EXIT) != 0)
+		exitshell(exitstatus);
+}
+
+
+STATIC void
+evalloop(union node *n, int flags)
+{
+	int status;
+
+	loopnest++;
+	status = 0;
+	for (;;) {
+		evaltree(n->nbinary.ch1, EV_TESTED);
+		if (evalskip) {
+skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
+				evalskip = 0;
+				continue;
+			}
+			if (evalskip == SKIPBREAK && --skipcount <= 0)
+				evalskip = 0;
+			break;
+		}
+		if (n->type == NWHILE) {
+			if (exitstatus != 0)
+				break;
+		} else {
+			if (exitstatus == 0)
+				break;
+		}
+		evaltree(n->nbinary.ch2, flags & EV_TESTED);
+		status = exitstatus;
+		if (evalskip)
+			goto skipping;
+	}
+	loopnest--;
+	exitstatus = status;
+}
+
+
+
+STATIC void
+evalfor(union node *n, int flags)
+{
+	struct arglist arglist;
+	union node *argp;
+	struct strlist *sp;
+	struct stackmark smark;
+	int status = 0;
+
+	setstackmark(&smark);
+	arglist.lastp = &arglist.list;
+	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
+		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
+		if (evalskip)
+			goto out;
+	}
+	*arglist.lastp = NULL;
+
+	loopnest++;
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		setvar(n->nfor.var, sp->text, 0);
+		evaltree(n->nfor.body, flags & EV_TESTED);
+		status = exitstatus;
+		if (evalskip) {
+			if (evalskip == SKIPCONT && --skipcount <= 0) {
+				evalskip = 0;
+				continue;
+			}
+			if (evalskip == SKIPBREAK && --skipcount <= 0)
+				evalskip = 0;
+			break;
+		}
+	}
+	loopnest--;
+	exitstatus = status;
+out:
+	popstackmark(&smark);
+}
+
+
+
+STATIC void
+evalcase(union node *n, int flags)
+{
+	union node *cp;
+	union node *patp;
+	struct arglist arglist;
+	struct stackmark smark;
+	int status = 0;
+
+	setstackmark(&smark);
+	arglist.lastp = &arglist.list;
+	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
+	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
+		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
+			if (casematch(patp, arglist.list->text)) {
+				if (evalskip == 0) {
+					evaltree(cp->nclist.body, flags);
+					status = exitstatus;
+				}
+				goto out;
+			}
+		}
+	}
+out:
+	exitstatus = status;
+	popstackmark(&smark);
+}
+
+
+
+/*
+ * Kick off a subshell to evaluate a tree.
+ */
+
+STATIC void
+evalsubshell(union node *n, int flags)
+{
+	struct job *jp;
+	int backgnd = (n->type == NBACKGND);
+
+	expredir(n->nredir.redirect);
+	INTOFF;
+	jp = makejob(n, 1);
+	if (forkshell(jp, n, backgnd ? FORK_BG : FORK_FG) == 0) {
+		INTON;
+		if (backgnd)
+			flags &=~ EV_TESTED;
+		redirect(n->nredir.redirect, 0);
+		/* never returns */
+		evaltree(n->nredir.n, flags | EV_EXIT);
+	}
+	if (! backgnd)
+		exitstatus = waitforjob(jp);
+	INTON;
+}
+
+
+
+/*
+ * Compute the names of the files in a redirection list.
+ */
+
+STATIC void
+expredir(union node *n)
+{
+	union node *redir;
+
+	for (redir = n ; redir ; redir = redir->nfile.next) {
+		struct arglist fn;
+		fn.lastp = &fn.list;
+		switch (redir->type) {
+		case NFROMTO:
+		case NFROM:
+		case NTO:
+		case NCLOBBER:
+		case NAPPEND:
+			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+			redir->nfile.expfname = fn.list->text;
+			break;
+		case NFROMFD:
+		case NTOFD:
+			if (redir->ndup.vname) {
+				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
+				fixredir(redir, fn.list->text, 1);
+			}
+			break;
+		}
+	}
+}
+
+
+
+/*
+ * Evaluate a pipeline.  All the processes in the pipeline are children
+ * of the process creating the pipeline.  (This differs from some versions
+ * of the shell, which make the last process in a pipeline the parent
+ * of all the rest.)
+ */
+
+STATIC void
+evalpipe(union node *n)
+{
+	struct job *jp;
+	struct nodelist *lp;
+	int pipelen;
+	int prevfd;
+	int pip[2];
+
+	TRACE(("evalpipe(0x%lx) called\n", (long)n));
+	pipelen = 0;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
+		pipelen++;
+	INTOFF;
+	jp = makejob(n, pipelen);
+	prevfd = -1;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+		prehash(lp->n);
+		pip[1] = -1;
+		if (lp->next) {
+			if (sh_pipe(pip) < 0) {
+				close(prevfd);
+				error("Pipe call failed");
+			}
+		}
+		if (forkshell(jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) {
+			INTON;
+			if (prevfd > 0) {
+				close(0);
+				copyfd(prevfd, 0);
+				close(prevfd);
+			}
+			if (pip[1] >= 0) {
+				close(pip[0]);
+				if (pip[1] != 1) {
+					close(1);
+					copyfd(pip[1], 1);
+					close(pip[1]);
+				}
+			}
+			evaltree(lp->n, EV_EXIT);
+		}
+		if (prevfd >= 0)
+			close(prevfd);
+		prevfd = pip[0];
+		close(pip[1]);
+	}
+	if (n->npipe.backgnd == 0) {
+		exitstatus = waitforjob(jp);
+		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
+	}
+	INTON;
+}
+
+
+
+/*
+ * Execute a command inside back quotes.  If it's a builtin command, we
+ * want to save its output in a block obtained from malloc.  Otherwise
+ * we fork off a subprocess and get the output of the command via a pipe.
+ * Should be called with interrupts off.
+ */
+
+void
+evalbackcmd(union node *n, struct backcmd *result)
+{
+	int pip[2];
+	struct job *jp;
+	struct stackmark smark;		/* unnecessary */
+
+	setstackmark(&smark);
+	result->fd = -1;
+	result->buf = NULL;
+	result->nleft = 0;
+	result->jp = NULL;
+	if (n == NULL) {
+		goto out;
+	}
+#ifdef notyet
+	/*
+	 * For now we disable executing builtins in the same
+	 * context as the shell, because we are not keeping
+	 * enough state to recover from changes that are
+	 * supposed only to affect subshells. eg. echo "`cd /`"
+	 */
+	if (n->type == NCMD) {
+		exitstatus = oexitstatus;
+		evalcommand(n, EV_BACKCMD, result);
+	} else
+#endif
+	{
+		INTOFF;
+		if (sh_pipe(pip) < 0)
+			error("Pipe call failed");
+		jp = makejob(n, 1);
+		if (forkshell(jp, n, FORK_NOJOB) == 0) {
+			FORCEINTON;
+			close(pip[0]);
+			if (pip[1] != 1) {
+				close(1);
+				copyfd(pip[1], 1);
+				close(pip[1]);
+			}
+			eflag = 0;
+			evaltree(n, EV_EXIT);
+			/* NOTREACHED */
+		}
+		close(pip[1]);
+		result->fd = pip[0];
+		result->jp = jp;
+		INTON;
+	}
+out:
+	popstackmark(&smark);
+	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
+		result->fd, result->buf, result->nleft, result->jp));
+}
+
+static const char *
+syspath(void)
+{
+#ifdef CTL_USER
+	static char *sys_path = NULL;
+	static int mib[] = {CTL_USER, USER_CS_PATH};
+#endif
+#ifdef PC_PATH_SEP
+	static char def_path[] = "PATH=/usr/bin;/bin;/usr/sbin;/sbin";
+#else
+	static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin";
+#endif
+#ifdef CTL_USER
+	size_t len;
+
+	if (sys_path == NULL) {
+		if (sysctl(mib, 2, 0, &len, 0, 0) != -1 &&
+		    (sys_path = ckmalloc(len + 5)) != NULL &&
+		    sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) {
+			memcpy(sys_path, "PATH=", 5);
+		} else {
+			ckfree(sys_path);
+			/* something to keep things happy */
+			sys_path = def_path;
+		}
+	}
+	return sys_path;
+#else
+    return def_path;
+#endif
+}
+
+static int
+parse_command_args(int argc, char **argv, int *use_syspath)
+{
+	int sv_argc = argc;
+	char *cp, c;
+
+	*use_syspath = 0;
+
+	for (;;) {
+		argv++;
+		if (--argc == 0)
+			break;
+		cp = *argv;
+		if (*cp++ != '-')
+			break;
+		if (*cp == '-' && cp[1] == 0) {
+			argv++;
+			argc--;
+			break;
+		}
+		while ((c = *cp++)) {
+			switch (c) {
+			case 'p':
+				*use_syspath = 1;
+				break;
+			default:
+				/* run 'typecmd' for other options */
+				return 0;
+			}
+		}
+	}
+	return sv_argc - argc;
+}
+
+int vforked = 0;
+
+/*
+ * Execute a simple command.
+ */
+
+STATIC void
+evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
+{
+	struct stackmark smark;
+	union node *argp;
+	struct arglist arglist;
+	struct arglist varlist;
+	char **argv;
+	int argc;
+	char **envp;
+	int varflag;
+	struct strlist *sp;
+	int mode;
+	int pip[2];
+	struct cmdentry cmdentry;
+	struct job *jp;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	char *volatile savecmdname;
+	volatile struct shparam saveparam;
+	struct localvar *volatile savelocalvars;
+	volatile int e;
+	char *lastarg;
+	const char *path = pathval();
+	volatile int temp_path;
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &argv;
+	(void) &argc;
+	(void) &lastarg;
+	(void) &flags;
+#endif
+
+	vforked = 0;
+	/* First expand the arguments. */
+	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
+	setstackmark(&smark);
+	back_exitstatus = 0;
+
+	arglist.lastp = &arglist.list;
+	varflag = 1;
+	/* Expand arguments, ignoring the initial 'name=value' ones */
+	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
+		char *p = argp->narg.text;
+		if (varflag && is_name(*p)) {
+			do {
+				p++;
+			} while (is_in_name(*p));
+			if (*p == '=')
+				continue;
+		}
+		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
+		varflag = 0;
+	}
+	*arglist.lastp = NULL;
+
+	expredir(cmd->ncmd.redirect);
+
+	/* Now do the initial 'name=value' ones we skipped above */
+	varlist.lastp = &varlist.list;
+	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
+		char *p = argp->narg.text;
+		if (!is_name(*p))
+			break;
+		do
+			p++;
+		while (is_in_name(*p));
+		if (*p != '=')
+			break;
+		expandarg(argp, &varlist, EXP_VARTILDE);
+	}
+	*varlist.lastp = NULL;
+
+	argc = 0;
+	for (sp = arglist.list ; sp ; sp = sp->next)
+		argc++;
+	argv = stalloc(sizeof (char *) * (argc + 1));
+
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		TRACE(("evalcommand arg: %s\n", sp->text));
+		*argv++ = sp->text;
+	}
+	*argv = NULL;
+	lastarg = NULL;
+	if (iflag && funcnest == 0 && argc > 0)
+		lastarg = argv[-1];
+	argv -= argc;
+
+	/* Print the command if xflag is set. */
+	if (xflag) {
+		char sep = 0;
+		out2str(ps4val());
+		for (sp = varlist.list ; sp ; sp = sp->next) {
+			if (sep != 0)
+				outc(sep, &errout);
+			out2str(sp->text);
+			sep = ' ';
+		}
+		for (sp = arglist.list ; sp ; sp = sp->next) {
+			if (sep != 0)
+				outc(sep, &errout);
+			out2str(sp->text);
+			sep = ' ';
+		}
+		outc('\n', &errout);
+		flushout(&errout);
+	}
+
+	/* Now locate the command. */
+	if (argc == 0) {
+		cmdentry.cmdtype = CMDSPLBLTIN;
+		cmdentry.u.bltin = bltincmd;
+	} else {
+		static const char PATH[] = "PATH=";
+		int cmd_flags = DO_ERR;
+
+		/*
+		 * Modify the command lookup path, if a PATH= assignment
+		 * is present
+		 */
+		for (sp = varlist.list; sp; sp = sp->next)
+			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
+				path = sp->text + sizeof(PATH) - 1;
+
+		do {
+			int argsused, use_syspath;
+			find_command(argv[0], &cmdentry, cmd_flags, path);
+			if (cmdentry.cmdtype == CMDUNKNOWN) {
+				exitstatus = 127;
+				flushout(&errout);
+				goto out;
+			}
+
+			/* implement the 'command' builtin here */
+			if (cmdentry.cmdtype != CMDBUILTIN ||
+			    cmdentry.u.bltin != bltincmd)
+				break;
+			cmd_flags |= DO_NOFUNC;
+			argsused = parse_command_args(argc, argv, &use_syspath);
+			if (argsused == 0) {
+				/* use 'type' builting to display info */
+				cmdentry.u.bltin = typecmd;
+				break;
+			}
+			argc -= argsused;
+			argv += argsused;
+			if (use_syspath)
+				path = syspath() + 5;
+		} while (argc != 0);
+		if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC)
+			/* posix mandates that 'command <splbltin>' act as if
+			   <splbltin> was a normal builtin */
+			cmdentry.cmdtype = CMDBUILTIN;
+	}
+
+	/* Fork off a child process if necessary. */
+	if (cmd->ncmd.backgnd
+	 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
+	 || ((flags & EV_BACKCMD) != 0
+	    && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN)
+		 || cmdentry.u.bltin == dotcmd
+		 || cmdentry.u.bltin == evalcmd))) {
+		INTOFF;
+		jp = makejob(cmd, 1);
+		mode = cmd->ncmd.backgnd;
+		if (flags & EV_BACKCMD) {
+			mode = FORK_NOJOB;
+			if (sh_pipe(pip) < 0)
+				error("Pipe call failed");
+		}
+#ifdef DO_SHAREDVFORK
+		/* It is essential that if DO_SHAREDVFORK is defined that the
+		 * child's address space is actually shared with the parent as
+		 * we rely on this.
+		 */
+		if (cmdentry.cmdtype == CMDNORMAL) {
+			pid_t	pid;
+
+			savelocalvars = localvars;
+			localvars = NULL;
+			vforked = 1;
+			switch (pid = vfork()) {
+			case -1:
+				TRACE(("Vfork failed, errno=%d\n", errno));
+				INTON;
+				error("Cannot vfork");
+				break;
+			case 0:
+				/* Make sure that exceptions only unwind to
+				 * after the vfork(2)
+				 */
+				if (setjmp(jmploc.loc)) {
+					if (exception == EXSHELLPROC) {
+						/* We can't progress with the vfork,
+						 * so, set vforked = 2 so the parent
+						 * knows, and _exit();
+						 */
+						vforked = 2;
+						_exit(0);
+					} else {
+						_exit(exerrno);
+					}
+				}
+				savehandler = handler;
+				handler = &jmploc;
+				listmklocal(varlist.list, VEXPORT | VNOFUNC);
+				forkchild(jp, cmd, mode, vforked);
+				break;
+			default:
+				handler = savehandler;	/* restore from vfork(2) */
+				poplocalvars();
+				localvars = savelocalvars;
+				if (vforked == 2) {
+					vforked = 0;
+
+					(void)waitpid(pid, NULL, 0);
+					/* We need to progress in a normal fork fashion */
+					goto normal_fork;
+				}
+				vforked = 0;
+				forkparent(jp, cmd, mode, pid);
+				goto parent;
+			}
+		} else {
+normal_fork:
+#endif
+			if (forkshell(jp, cmd, mode) != 0)
+				goto parent;	/* at end of routine */
+			FORCEINTON;
+#ifdef DO_SHAREDVFORK
+		}
+#endif
+		if (flags & EV_BACKCMD) {
+			if (!vforked) {
+				FORCEINTON;
+			}
+			close(pip[0]);
+			if (pip[1] != 1) {
+				close(1);
+				copyfd(pip[1], 1);
+				close(pip[1]);
+			}
+		}
+		flags |= EV_EXIT;
+	}
+
+	/* This is the child process if a fork occurred. */
+	/* Execute the command. */
+	switch (cmdentry.cmdtype) {
+	case CMDFUNCTION:
+#ifdef DEBUG
+		trputs("Shell function:  ");  trargs(argv);
+#endif
+		redirect(cmd->ncmd.redirect, REDIR_PUSH);
+		saveparam = shellparam;
+		shellparam.malloc = 0;
+		shellparam.reset = 1;
+		shellparam.nparam = argc - 1;
+		shellparam.p = argv + 1;
+		shellparam.optnext = NULL;
+		INTOFF;
+		savelocalvars = localvars;
+		localvars = NULL;
+		INTON;
+		if (setjmp(jmploc.loc)) {
+			if (exception == EXSHELLPROC) {
+				freeparam((volatile struct shparam *)
+				    &saveparam);
+			} else {
+				freeparam(&shellparam);
+				shellparam = saveparam;
+			}
+			poplocalvars();
+			localvars = savelocalvars;
+			handler = savehandler;
+			longjmp(handler->loc, 1);
+		}
+		savehandler = handler;
+		handler = &jmploc;
+		listmklocal(varlist.list, 0);
+		/* stop shell blowing its stack */
+		if (++funcnest > 1000)
+			error("too many nested function calls");
+		evaltree(cmdentry.u.func, flags & EV_TESTED);
+		funcnest--;
+		INTOFF;
+		poplocalvars();
+		localvars = savelocalvars;
+		freeparam(&shellparam);
+		shellparam = saveparam;
+		handler = savehandler;
+		popredir();
+		INTON;
+		if (evalskip == SKIPFUNC) {
+			evalskip = 0;
+			skipcount = 0;
+		}
+		if (flags & EV_EXIT)
+			exitshell(exitstatus);
+		break;
+
+	case CMDBUILTIN:
+	case CMDSPLBLTIN:
+#ifdef DEBUG
+		trputs("builtin command:  ");  trargs(argv);
+#endif
+		mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH;
+		if (flags == EV_BACKCMD) {
+			memout.nleft = 0;
+			memout.nextc = memout.buf;
+			memout.bufsize = 64;
+			mode |= REDIR_BACKQ;
+		}
+		e = -1;
+		savehandler = handler;
+		savecmdname = commandname;
+		handler = &jmploc;
+		if (!setjmp(jmploc.loc)) {
+			/* We need to ensure the command hash table isn't
+			 * corruped by temporary PATH assignments.
+			 * However we must ensure the 'local' command works!
+			 */
+			if (path != pathval() && (cmdentry.u.bltin == hashcmd ||
+			    cmdentry.u.bltin == typecmd)) {
+				savelocalvars = localvars;
+				localvars = 0;
+				mklocal(path - 5 /* PATH= */, 0);
+				temp_path = 1;
+			} else
+				temp_path = 0;
+			redirect(cmd->ncmd.redirect, mode);
+
+			/* exec is a special builtin, but needs this list... */
+			cmdenviron = varlist.list;
+			/* we must check 'readonly' flag for all builtins */
+			listsetvar(varlist.list,
+				cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET);
+			commandname = argv[0];
+			/* initialize nextopt */
+			argptr = argv + 1;
+			optptr = NULL;
+			/* and getopt */
+#if defined(__FreeBSD__) || defined(__EMX__) || defined(__APPLE__)
+			optreset = 1;
+			optind = 1;
+#else
+			optind = 0; /* init */
+#endif
+
+			exitstatus = cmdentry.u.bltin(argc, argv);
+		} else {
+			e = exception;
+			exitstatus = e == EXINT ? SIGINT + 128 :
+					e == EXEXEC ? exerrno : 2;
+		}
+		handler = savehandler;
+		output_flushall();
+		out1 = &output;
+		out2 = &errout;
+		freestdout();
+		if (temp_path) {
+			poplocalvars();
+			localvars = savelocalvars;
+		}
+		cmdenviron = NULL;
+		if (e != EXSHELLPROC) {
+			commandname = savecmdname;
+			if (flags & EV_EXIT)
+				exitshell(exitstatus);
+		}
+		if (e != -1) {
+			if ((e != EXERROR && e != EXEXEC)
+			    || cmdentry.cmdtype == CMDSPLBLTIN)
+				exraise(e);
+			FORCEINTON;
+		}
+		if (cmdentry.u.bltin != execcmd)
+			popredir();
+		if (flags == EV_BACKCMD) {
+			backcmd->buf = memout.buf;
+			backcmd->nleft = memout.nextc - memout.buf;
+			memout.buf = NULL;
+		}
+		break;
+
+	default:
+#ifdef DEBUG
+		trputs("normal command:  ");  trargs(argv);
+#endif
+		clearredir(vforked);
+		redirect(cmd->ncmd.redirect, vforked ? REDIR_VFORK : 0);
+		if (!vforked)
+			for (sp = varlist.list ; sp ; sp = sp->next)
+				setvareq(sp->text, VEXPORT|VSTACK);
+		envp = environment();
+		shellexec(argv, envp, path, cmdentry.u.index, vforked);
+		break;
+	}
+	goto out;
+
+parent:	/* parent process gets here (if we forked) */
+	if (mode == FORK_FG) {	/* argument to fork */
+		exitstatus = waitforjob(jp);
+	} else if (mode == FORK_NOJOB) {
+		backcmd->fd = pip[0];
+		close(pip[1]);
+		backcmd->jp = jp;
+	}
+	FORCEINTON;
+
+out:
+	if (lastarg)
+		/* dsl: I think this is intended to be used to support
+		 * '_' in 'vi' command mode during line editing...
+		 * However I implemented that within libedit itself.
+		 */
+		setvar("_", lastarg, 0);
+	popstackmark(&smark);
+
+	if (eflag && exitstatus && !(flags & EV_TESTED))
+		exitshell(exitstatus);
+}
+
+
+/*
+ * Search for a command.  This is called before we fork so that the
+ * location of the command will be available in the parent as well as
+ * the child.  The check for "goodname" is an overly conservative
+ * check that the name will not be subject to expansion.
+ */
+
+STATIC void
+prehash(union node *n)
+{
+	struct cmdentry entry;
+
+	if (n->type == NCMD && n->ncmd.args)
+		if (goodname(n->ncmd.args->narg.text))
+			find_command(n->ncmd.args->narg.text, &entry, 0,
+				     pathval());
+}
+
+
+
+/*
+ * Builtin commands.  Builtin commands whose functions are closely
+ * tied to evaluation are implemented here.
+ */
+
+/*
+ * No command given.
+ */
+
+int
+bltincmd(int argc, char **argv)
+{
+	/*
+	 * Preserve exitstatus of a previous possible redirection
+	 * as POSIX mandates
+	 */
+	return back_exitstatus;
+}
+
+
+/*
+ * Handle break and continue commands.  Break, continue, and return are
+ * all handled by setting the evalskip flag.  The evaluation routines
+ * above all check this flag, and if it is set they start skipping
+ * commands rather than executing them.  The variable skipcount is
+ * the number of loops to break/continue, or the number of function
+ * levels to return.  (The latter is always 1.)  It should probably
+ * be an error to break out of more loops than exist, but it isn't
+ * in the standard shell so we don't make it one here.
+ */
+
+int
+breakcmd(int argc, char **argv)
+{
+	int n = argc > 1 ? number(argv[1]) : 1;
+
+	if (n > loopnest)
+		n = loopnest;
+	if (n > 0) {
+		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
+		skipcount = n;
+	}
+	return 0;
+}
+
+
+/*
+ * The return command.
+ */
+
+int
+returncmd(int argc, char **argv)
+{
+	int ret = argc > 1 ? number(argv[1]) : exitstatus;
+
+	if (funcnest) {
+		evalskip = SKIPFUNC;
+		skipcount = 1;
+		return ret;
+	}
+	else {
+		/* Do what ksh does; skip the rest of the file */
+		evalskip = SKIPFILE;
+		skipcount = 1;
+		return ret;
+	}
+}
+
+
+int
+falsecmd(int argc, char **argv)
+{
+	return 1;
+}
+
+
+int
+truecmd(int argc, char **argv)
+{
+	return 0;
+}
+
+
+int
+execcmd(int argc, char **argv)
+{
+	if (argc > 1) {
+		struct strlist *sp;
+
+		iflag = 0;		/* exit on error */
+		mflag = 0;
+		optschanged();
+		for (sp = cmdenviron; sp; sp = sp->next)
+			setvareq(sp->text, VEXPORT|VSTACK);
+		shellexec(argv + 1, environment(), pathval(), 0, 0);
+	}
+	return 0;
+}
+
+static int
+conv_time(clock_t ticks, char *seconds, size_t l)
+{
+	static clock_t tpm = 0;
+	clock_t mins;
+	int i;
+
+	if (!tpm)
+		tpm = sysconf(_SC_CLK_TCK) * 60;
+
+	mins = ticks / tpm;
+	snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm );
+
+	if (seconds[0] == '6' && seconds[1] == '0') {
+		/* 59.99995 got rounded up... */
+		mins++;
+		strlcpy(seconds, "0.0", l);
+		return mins;
+	}
+
+	/* suppress trailing zeros */
+	i = strlen(seconds) - 1;
+	for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--)
+		seconds[i] = 0;
+	return mins;
+}
+
+int
+timescmd(int argc, char **argv)
+{
+	struct tms tms;
+	int u, s, cu, cs;
+	char us[8], ss[8], cus[8], css[8];
+
+	nextopt("");
+
+	times(&tms);
+
+	u = conv_time(tms.tms_utime, us, sizeof(us));
+	s = conv_time(tms.tms_stime, ss, sizeof(ss));
+	cu = conv_time(tms.tms_cutime, cus, sizeof(cus));
+	cs = conv_time(tms.tms_cstime, css, sizeof(css));
+
+	outfmt(out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n",
+		u, us, s, ss, cu, cus, cs, css);
+
+	return 0;
+}
Index: /tags/kBuild-0.1.4/src/ash/eval.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/eval.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/eval.h	(revision 1780)
@@ -0,0 +1,64 @@
+/*	$NetBSD: eval.h,v 1.14 2003/08/07 09:05:31 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)eval.h	8.2 (Berkeley) 5/4/95
+ */
+
+extern char *commandname;	/* currently executing command */
+extern int exitstatus;		/* exit status of last command */
+extern int back_exitstatus;	/* exit status of backquoted command */
+extern struct strlist *cmdenviron;  /* environment for builtin command */
+
+
+struct backcmd {		/* result of evalbackcmd */
+	int fd;			/* file descriptor to read from */
+	char *buf;		/* buffer */
+	int nleft;		/* number of chars in buffer */
+	struct job *jp;		/* job structure for command */
+};
+
+void evalstring(char *, int);
+union node;	/* BLETCH for ansi C */
+void evaltree(union node *, int);
+void evalbackcmd(union node *, struct backcmd *);
+
+/* in_function returns nonzero if we are currently evaluating a function */
+#define in_function()	funcnest
+extern int funcnest;
+extern int evalskip;
+
+/* reasons for skipping commands (see comment on breakcmd routine) */
+#define SKIPBREAK	1
+#define SKIPCONT	2
+#define SKIPFUNC	3
+#define SKIPFILE	4
Index: /tags/kBuild-0.1.4/src/ash/exec.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/exec.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/exec.c	(revision 1780)
@@ -0,0 +1,1199 @@
+/*	$NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)exec.c	8.4 (Berkeley) 6/8/95";
+#else
+__RCSID("$NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * When commands are first encountered, they are entered in a hash table.
+ * This ensures that a full path search will not have to be done for them
+ * on each invocation.
+ *
+ * We should investigate converting to a linear search, even though that
+ * would make the command name "hash" a misnomer.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"
+#include "parser.h"
+#include "redir.h"
+#include "eval.h"
+#include "exec.h"
+#include "builtins.h"
+#include "var.h"
+#include "options.h"
+#include "input.h"
+#include "output.h"
+#include "syntax.h"
+#include "memalloc.h"
+#include "error.h"
+#include "init.h"
+#include "mystring.h"
+#include "show.h"
+#include "jobs.h"
+#include "alias.h"
+#ifdef __INNOTEK_LIBC__
+#include <InnoTekLIBC/backend.h>
+#endif
+
+
+#define CMDTABLESIZE 31		/* should be prime */
+#define ARB 1			/* actual size determined at run time */
+
+
+
+struct tblentry {
+	struct tblentry *next;	/* next entry in hash chain */
+	union param param;	/* definition of builtin function */
+	short cmdtype;		/* index identifying command */
+	char rehash;		/* if set, cd done since entry created */
+	char cmdname[ARB];	/* name of command */
+};
+
+
+STATIC struct tblentry *cmdtable[CMDTABLESIZE];
+STATIC int builtinloc = -1;		/* index in path of %builtin, or -1 */
+int exerrno = 0;			/* Last exec error */
+
+
+STATIC void tryexec(char *, char **, char **, int, int);
+STATIC void execinterp(char **, char **);
+STATIC void printentry(struct tblentry *, int);
+STATIC void clearcmdentry(int);
+STATIC struct tblentry *cmdlookup(const char *, int);
+STATIC void delete_cmd_entry(void);
+#ifdef PC_EXE_EXTS
+STATIC int stat_pc_exec_exts(char *fullname, struct stat *st, int has_ext);
+#endif
+
+
+extern char *const parsekwd[];
+
+/*
+ * Exec a program.  Never returns.  If you change this routine, you may
+ * have to change the find_command routine as well.
+ */
+
+void
+shellexec(char **argv, char **envp, const char *path, int idx, int vforked)
+{
+	char *cmdname;
+	int e;
+#ifdef PC_EXE_EXTS
+        int has_ext = strlen(argv[0]) - 4;
+        has_ext = has_ext > 0
+            && argv[0][has_ext] == '.'
+            /* use strstr and upper/lower permuated extensions to avoid multiple strcasecmp calls. */
+            && strstr("exe;" "Exe;" "EXe;" "EXE;" "ExE;" "eXe;" "eXE;" "exE;"
+                      "cmd;" "Cmd;" "CMd;" "CMD;" "CmD;" "cMd;" "cMD;" "cmD;"
+                      "com;" "Com;" "COm;" "COM;" "CoM;" "cOm;" "cOM;" "coM;"
+                      "bat;" "Bat;" "BAt;" "BAT;" "BaT;" "bAt;" "bAT;" "baT;"
+                      "btm;" "Btm;" "BTm;" "BTM;" "BtM;" "bTm;" "bTM;" "btM;",
+                      argv[0] + has_ext + 1)
+               != NULL;
+#else
+	const int has_ext = 1;
+#endif
+	TRACE(("shellexec: argv[0]=%s idx=%d\n", argv[0], idx));
+	if (strchr(argv[0], '/') != NULL) {
+		cmdname = stalloc(strlen(argv[0]) + 5);
+		strcpy(cmdname, argv[0]);
+		tryexec(cmdname, argv, envp, vforked, has_ext);
+		TRACE(("shellexec: cmdname=%s\n", cmdname));
+		stunalloc(cmdname);
+		e = errno;
+	} else {
+		e = ENOENT;
+		while ((cmdname = padvance(&path, argv[0])) != NULL) {
+			if (--idx < 0 && pathopt == NULL) {
+				tryexec(cmdname, argv, envp, vforked, has_ext);
+				if (errno != ENOENT && errno != ENOTDIR)
+					e = errno;
+			}
+			stunalloc(cmdname);
+		}
+	}
+
+	/* Map to POSIX errors */
+	switch (e) {
+	case EACCES:
+		exerrno = 126;
+		break;
+	case ENOENT:
+		exerrno = 127;
+		break;
+	default:
+		exerrno = 2;
+		break;
+	}
+	TRACE(("shellexec failed for '%s', errno %d, vforked %d, suppressint %d\n",
+		argv[0], e, vforked, suppressint ));
+	exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
+	/* NOTREACHED */
+}
+
+
+STATIC void
+tryexec(char *cmd, char **argv, char **envp, int vforked, int has_ext)
+{
+	int e;
+#ifdef EXEC_HASH_BANG_SCRIPT
+	char *p;
+#endif
+#ifdef PC_EXE_EXTS
+        /* exploit the effect of stat_pc_exec_exts which adds the
+         * correct extentions to the file.
+         */
+        struct stat st;
+        if (!has_ext)
+            stat_pc_exec_exts(cmd, &st, 0);
+#endif
+#if defined __INNOTEK_LIBC__ && defined EXEC_HASH_BANG_SCRIPT
+	__libc_Back_gfProcessHandleHashBangScripts = 0;
+#endif
+
+#ifdef SYSV
+	do {
+		execve(cmd, argv, envp);
+	} while (errno == EINTR);
+#else
+	execve(cmd, argv, envp);
+#endif
+	e = errno;
+	if (e == ENOEXEC) {
+		if (vforked) {
+			/* We are currently vfork(2)ed, so raise an
+			 * exception, and evalcommand will try again
+			 * with a normal fork(2).
+			 */
+			exraise(EXSHELLPROC);
+		}
+		initshellproc();
+		setinputfile(cmd, 0);
+		commandname = arg0 = savestr(argv[0]);
+#ifdef EXEC_HASH_BANG_SCRIPT
+		pgetc(); pungetc();		/* fill up input buffer */
+		p = parsenextc;
+		if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
+			argv[0] = cmd;
+			execinterp(argv, envp);
+		}
+#endif
+		setparam(argv + 1);
+		exraise(EXSHELLPROC);
+	}
+	errno = e;
+}
+
+
+#ifdef EXEC_HASH_BANG_SCRIPT
+/*
+ * Execute an interpreter introduced by "#!", for systems where this
+ * feature has not been built into the kernel.  If the interpreter is
+ * the shell, return (effectively ignoring the "#!").  If the execution
+ * of the interpreter fails, exit.
+ *
+ * This code peeks inside the input buffer in order to avoid actually
+ * reading any input.  It would benefit from a rewrite.
+ */
+
+#define NEWARGS 5
+
+STATIC void
+execinterp(char **argv, char **envp)
+{
+	int n;
+	char *inp;
+	char *outp;
+	char c;
+	char *p;
+	char **ap;
+	char *newargs[NEWARGS];
+	int i;
+	char **ap2;
+	char **new;
+
+	n = parsenleft - 2;
+	inp = parsenextc + 2;
+	ap = newargs;
+	for (;;) {
+		while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
+			inp++;
+		if (n < 0)
+			goto bad;
+		if ((c = *inp++) == '\n')
+			break;
+		if (ap == &newargs[NEWARGS])
+bad:		  error("Bad #! line");
+		STARTSTACKSTR(outp);
+		do {
+			STPUTC(c, outp);
+		} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
+		STPUTC('\0', outp);
+		n++, inp--;
+		*ap++ = grabstackstr(outp);
+	}
+	if (ap == newargs + 1) {	/* if no args, maybe no exec is needed */
+		p = newargs[0];
+		for (;;) {
+			if (equal(p, "sh") || equal(p, "ash")) {
+				TRACE(("hash bang self\n"));
+				return;
+			}
+			while (*p != '/') {
+				if (*p == '\0')
+					goto break2;
+				p++;
+			}
+			p++;
+		}
+break2:;
+	}
+	i = (char *)ap - (char *)newargs;		/* size in bytes */
+	if (i == 0)
+		error("Bad #! line");
+	for (ap2 = argv ; *ap2++ != NULL ; );
+	new = ckmalloc(i + ((char *)ap2 - (char *)argv));
+	ap = newargs, ap2 = new;
+	while ((i -= sizeof (char **)) >= 0)
+		*ap2++ = *ap++;
+	ap = argv;
+	while (*ap2++ = *ap++);
+	TRACE(("hash bang '%s'\n", new[0]));
+	shellexec(new, envp, pathval(), 0, 0);
+	/* NOTREACHED */
+}
+#endif
+
+
+
+/*
+ * Do a path search.  The variable path (passed by reference) should be
+ * set to the start of the path before the first call; padvance will update
+ * this value as it proceeds.  Successive calls to padvance will return
+ * the possible path expansions in sequence.  If an option (indicated by
+ * a percent sign) appears in the path entry then the global variable
+ * pathopt will be set to point to it; otherwise pathopt will be set to
+ * NULL.
+ */
+
+const char *pathopt;
+
+char *
+padvance(const char **path, const char *name)
+{
+	const char *p;
+	char *q;
+#ifdef PC_SLASHES
+	char *s;
+#endif
+	const char *start;
+	int len;
+
+	if (*path == NULL)
+		return NULL;
+	start = *path;
+#ifdef PC_PATH_SEP
+	for (p = start ; *p && *p != ';' && *p != '%' ; p++);
+#else
+	for (p = start ; *p && *p != ':' && *p != '%' ; p++);
+#endif
+	len = p - start + strlen(name) + 2;	/* "2" is for '/' and '\0' */
+#ifdef PC_EXE_EXTS
+        len += 4; /* "4" is for .exe/.com/.cmd/.bat/.btm */
+#endif
+	while (stackblocksize() < len)
+		growstackblock();
+#ifdef PC_SLASHES
+	s =
+#endif
+	q = stackblock();
+	if (p != start) {
+		memcpy(q, start, p - start);
+		q += p - start;
+		*q++ = '/';
+	}
+	strcpy(q, name);
+#ifdef PC_SLASHES
+	while ((s = strchr(s, '\\')) != NULL)
+		*s++ = '/';
+#endif
+	pathopt = NULL;
+	if (*p == '%') {
+		pathopt = ++p;
+#ifdef PC_PATH_SEP
+		while (*p && *p != ';')  p++;
+#else
+		while (*p && *p != ':')  p++;
+#endif
+	}
+#ifdef PC_PATH_SEP
+	if (*p == ';')
+#else
+	if (*p == ':')
+#endif
+		*path = p + 1;
+	else
+		*path = NULL;
+	return stalloc(len);
+}
+
+
+#ifdef PC_EXE_EXTS
+STATIC int stat_pc_exec_exts(char *fullname, struct stat *st, int has_ext)
+{
+    /* skip the SYSV crap */
+    if (stat(fullname, st) >= 0)
+        return 0;
+    if (!has_ext && errno == ENOENT)
+    {
+        char *psz = strchr(fullname, '\0');
+        memcpy(psz, ".exe", 5);
+        if (stat(fullname, st) >= 0)
+            return 0;
+        if (errno != ENOENT && errno != ENOTDIR)
+            return -1;
+
+        memcpy(psz, ".cmd", 5);
+        if (stat(fullname, st) >= 0)
+            return 0;
+        if (errno != ENOENT && errno != ENOTDIR)
+            return -1;
+
+        memcpy(psz, ".bat", 5);
+        if (stat(fullname, st) >= 0)
+            return 0;
+        if (errno != ENOENT && errno != ENOTDIR)
+            return -1;
+
+        memcpy(psz, ".com", 5);
+        if (stat(fullname, st) >= 0)
+            return 0;
+        if (errno != ENOENT && errno != ENOTDIR)
+            return -1;
+
+        memcpy(psz, ".btm", 5);
+        if (stat(fullname, st) >= 0)
+            return 0;
+        *psz = '\0';
+    }
+    return -1;
+}
+#endif /* PC_EXE_EXTS */
+
+
+
+/*** Command hashing code ***/
+
+
+int
+hashcmd(int argc, char **argv)
+{
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+	int c;
+	int verbose;
+	struct cmdentry entry;
+	char *name;
+
+	verbose = 0;
+	while ((c = nextopt("rv")) != '\0') {
+		if (c == 'r') {
+			clearcmdentry(0);
+		} else if (c == 'v') {
+			verbose++;
+		}
+	}
+	if (*argptr == NULL) {
+		for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+				if (verbose || cmdp->cmdtype == CMDNORMAL)
+					printentry(cmdp, verbose);
+			}
+		}
+		return 0;
+	}
+	while ((name = *argptr) != NULL) {
+		if ((cmdp = cmdlookup(name, 0)) != NULL
+		 && (cmdp->cmdtype == CMDNORMAL
+		     || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
+			delete_cmd_entry();
+		find_command(name, &entry, DO_ERR, pathval());
+		if (verbose) {
+			if (entry.cmdtype != CMDUNKNOWN) {	/* if no error msg */
+				cmdp = cmdlookup(name, 0);
+				printentry(cmdp, verbose);
+			}
+			output_flushall();
+		}
+		argptr++;
+	}
+	return 0;
+}
+
+
+STATIC void
+printentry(struct tblentry *cmdp, int verbose)
+{
+	int idx;
+	const char *path;
+	char *name;
+
+	switch (cmdp->cmdtype) {
+	case CMDNORMAL:
+		idx = cmdp->param.index;
+		path = pathval();
+		do {
+			name = padvance(&path, cmdp->cmdname);
+			stunalloc(name);
+		} while (--idx >= 0);
+		out1str(name);
+		break;
+	case CMDSPLBLTIN:
+		out1fmt("special builtin %s", cmdp->cmdname);
+		break;
+	case CMDBUILTIN:
+		out1fmt("builtin %s", cmdp->cmdname);
+		break;
+	case CMDFUNCTION:
+		out1fmt("function %s", cmdp->cmdname);
+		if (verbose) {
+			struct procstat ps;
+			INTOFF;
+			commandtext(&ps, cmdp->param.func);
+			INTON;
+			out1str("() { ");
+			out1str(ps.cmd);
+			out1str("; }");
+		}
+		break;
+	default:
+		error("internal error: %s cmdtype %d", cmdp->cmdname, cmdp->cmdtype);
+	}
+	if (cmdp->rehash)
+		out1c('*');
+	out1c('\n');
+}
+
+
+
+/*
+ * Resolve a command name.  If you change this routine, you may have to
+ * change the shellexec routine as well.
+ */
+
+void
+find_command(char *name, struct cmdentry *entry, int act, const char *path)
+{
+	struct tblentry *cmdp, loc_cmd;
+	int idx;
+	int prev;
+	char *fullname;
+	struct stat statb;
+	int e;
+	int (*bltin)(int,char **);
+
+#ifdef PC_EXE_EXTS
+        int has_ext = strlen(name) - 4;
+        has_ext = has_ext > 0
+            && name[has_ext] == '.'
+            /* use strstr and upper/lower permuated extensions to avoid multiple strcasecmp calls. */
+            && strstr("exe;" "Exe;" "EXe;" "EXE;" "ExE;" "eXe;" "eXE;" "exE;"
+                      "cmd;" "Cmd;" "CMd;" "CMD;" "CmD;" "cMd;" "cMD;" "cmD;"
+                      "com;" "Com;" "COm;" "COM;" "CoM;" "cOm;" "cOM;" "coM;"
+                      "bat;" "Bat;" "BAt;" "BAT;" "BaT;" "bAt;" "bAT;" "baT;"
+                      "btm;" "Btm;" "BTm;" "BTM;" "BtM;" "bTm;" "bTM;" "btM;",
+                      name + has_ext + 1)
+               != NULL;
+#endif
+
+	/* If name contains a slash, don't use PATH or hash table */
+	if (strchr(name, '/') != NULL) {
+		if (act & DO_ABS) {
+			while (stat(name, &statb) < 0) {
+#ifdef SYSV
+				if (errno == EINTR)
+					continue;
+#endif
+				if (errno != ENOENT && errno != ENOTDIR)
+					e = errno;
+				entry->cmdtype = CMDUNKNOWN;
+				entry->u.index = -1;
+				return;
+			}
+			entry->cmdtype = CMDNORMAL;
+			entry->u.index = -1;
+			return;
+		}
+		entry->cmdtype = CMDNORMAL;
+		entry->u.index = 0;
+		return;
+	}
+
+	if (path != pathval())
+		act |= DO_ALTPATH;
+
+	if (act & DO_ALTPATH && strstr(path, "%builtin") != NULL)
+		act |= DO_ALTBLTIN;
+
+	/* If name is in the table, check answer will be ok */
+	if ((cmdp = cmdlookup(name, 0)) != NULL) {
+		do {
+			switch (cmdp->cmdtype) {
+			case CMDNORMAL:
+				if (act & DO_ALTPATH) {
+					cmdp = NULL;
+					continue;
+				}
+				break;
+			case CMDFUNCTION:
+				if (act & DO_NOFUNC) {
+					cmdp = NULL;
+					continue;
+				}
+				break;
+			case CMDBUILTIN:
+				if ((act & DO_ALTBLTIN) || builtinloc >= 0) {
+					cmdp = NULL;
+					continue;
+				}
+				break;
+			}
+			/* if not invalidated by cd, we're done */
+			if (cmdp->rehash == 0)
+				goto success;
+		} while (0);
+	}
+
+	/* If %builtin not in path, check for builtin next */
+	if ((act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc < 0) &&
+	    (bltin = find_builtin(name)) != 0)
+		goto builtin_success;
+
+	/* We have to search path. */
+	prev = -1;		/* where to start */
+	if (cmdp) {		/* doing a rehash */
+		if (cmdp->cmdtype == CMDBUILTIN)
+			prev = builtinloc;
+		else
+			prev = cmdp->param.index;
+	}
+
+	e = ENOENT;
+	idx = -1;
+loop:
+	while ((fullname = padvance(&path, name)) != NULL) {
+		stunalloc(fullname);
+		idx++;
+		if (pathopt) {
+			if (prefix("builtin", pathopt)) {
+				if ((bltin = find_builtin(name)) == 0)
+					goto loop;
+				goto builtin_success;
+			} else if (prefix("func", pathopt)) {
+				/* handled below */
+			} else {
+				/* ignore unimplemented options */
+				goto loop;
+			}
+		}
+		/* if rehash, don't redo absolute path names */
+		if (fullname[0] == '/' && idx <= prev) {
+			if (idx < prev)
+				goto loop;
+			TRACE(("searchexec \"%s\": no change\n", name));
+			goto success;
+		}
+#ifdef PC_EXE_EXTS
+		while (stat_pc_exec_exts(fullname, &statb, has_ext) < 0) {
+#else
+		while (stat(fullname, &statb) < 0) {
+#endif
+#ifdef SYSV
+			if (errno == EINTR)
+				continue;
+#endif
+			if (errno != ENOENT && errno != ENOTDIR)
+				e = errno;
+
+			goto loop;
+		}
+		e = EACCES;	/* if we fail, this will be the error */
+		if (!S_ISREG(statb.st_mode))
+			goto loop;
+		if (pathopt) {		/* this is a %func directory */
+			if (act & DO_NOFUNC)
+				goto loop;
+			stalloc(strlen(fullname) + 1);
+			readcmdfile(fullname);
+			if ((cmdp = cmdlookup(name, 0)) == NULL ||
+			    cmdp->cmdtype != CMDFUNCTION)
+				error("%s not defined in %s", name, fullname);
+			stunalloc(fullname);
+			goto success;
+		}
+#ifdef notdef
+		/* XXX this code stops root executing stuff, and is buggy
+		   if you need a group from the group list. */
+		if (statb.st_uid == geteuid()) {
+			if ((statb.st_mode & 0100) == 0)
+				goto loop;
+		} else if (statb.st_gid == getegid()) {
+			if ((statb.st_mode & 010) == 0)
+				goto loop;
+		} else {
+			if ((statb.st_mode & 01) == 0)
+				goto loop;
+		}
+#endif
+		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
+		INTOFF;
+		if (act & DO_ALTPATH) {
+			stalloc(strlen(fullname) + 1);
+			cmdp = &loc_cmd;
+		} else
+			cmdp = cmdlookup(name, 1);
+		cmdp->cmdtype = CMDNORMAL;
+		cmdp->param.index = idx;
+		INTON;
+		goto success;
+	}
+
+	/* We failed.  If there was an entry for this command, delete it */
+	if (cmdp)
+		delete_cmd_entry();
+	if (act & DO_ERR)
+		outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
+	entry->cmdtype = CMDUNKNOWN;
+	return;
+
+builtin_success:
+	INTOFF;
+	if (act & DO_ALTPATH)
+		cmdp = &loc_cmd;
+	else
+		cmdp = cmdlookup(name, 1);
+	if (cmdp->cmdtype == CMDFUNCTION)
+		/* DO_NOFUNC must have been set */
+		cmdp = &loc_cmd;
+	cmdp->cmdtype = CMDBUILTIN;
+	cmdp->param.bltin = bltin;
+	INTON;
+success:
+	cmdp->rehash = 0;
+	entry->cmdtype = cmdp->cmdtype;
+	entry->u = cmdp->param;
+}
+
+
+
+/*
+ * Search the table of builtin commands.
+ */
+
+int
+(*find_builtin(name))(int, char **)
+	char *name;
+{
+	const struct builtincmd *bp;
+
+	for (bp = builtincmd ; bp->name ; bp++) {
+		if (*bp->name == *name && equal(bp->name, name))
+			return bp->builtin;
+	}
+	return 0;
+}
+
+int
+(*find_splbltin(name))(int, char **)
+	char *name;
+{
+	const struct builtincmd *bp;
+
+	for (bp = splbltincmd ; bp->name ; bp++) {
+		if (*bp->name == *name && equal(bp->name, name))
+			return bp->builtin;
+	}
+	return 0;
+}
+
+/*
+ * At shell startup put special builtins into hash table.
+ * ensures they are executed first (see posix).
+ * We stop functions being added with the same name
+ * (as they are impossible to call)
+ */
+
+void
+hash_special_builtins(void)
+{
+	const struct builtincmd *bp;
+	struct tblentry *cmdp;
+
+	for (bp = splbltincmd ; bp->name ; bp++) {
+		cmdp = cmdlookup(bp->name, 1);
+		cmdp->cmdtype = CMDSPLBLTIN;
+		cmdp->param.bltin = bp->builtin;
+	}
+}
+
+
+
+/*
+ * Called when a cd is done.  Marks all commands so the next time they
+ * are executed they will be rehashed.
+ */
+
+void
+hashcd(void)
+{
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+		for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+			if (cmdp->cmdtype == CMDNORMAL
+			 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
+				cmdp->rehash = 1;
+		}
+	}
+}
+
+
+
+/*
+ * Fix command hash table when PATH changed.
+ * Called before PATH is changed.  The argument is the new value of PATH;
+ * pathval() still returns the old value at this point.
+ * Called with interrupts off.
+ */
+
+void
+changepath(const char *newval)
+{
+	const char *old, *new;
+	int idx;
+	int firstchange;
+	int bltin;
+
+	old = pathval();
+	new = newval;
+	firstchange = 9999;	/* assume no change */
+	idx = 0;
+	bltin = -1;
+	for (;;) {
+		if (*old != *new) {
+			firstchange = idx;
+#ifdef PC_PATH_SEP
+			if ((*old == '\0' && *new == ';')
+			 || (*old == ';' && *new == '\0'))
+#else
+			if ((*old == '\0' && *new == ':')
+			 || (*old == ':' && *new == '\0'))
+#endif
+				firstchange++;
+			old = new;	/* ignore subsequent differences */
+		}
+		if (*new == '\0')
+			break;
+		if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
+			bltin = idx;
+#ifdef PC_PATH_SEP
+		if (*new == ';') {
+#else
+		if (*new == ':') {
+#endif
+			idx++;
+		}
+		new++, old++;
+	}
+	if (builtinloc < 0 && bltin >= 0)
+		builtinloc = bltin;		/* zap builtins */
+	if (builtinloc >= 0 && bltin < 0)
+		firstchange = 0;
+	clearcmdentry(firstchange);
+	builtinloc = bltin;
+}
+
+
+/*
+ * Clear out command entries.  The argument specifies the first entry in
+ * PATH which has changed.
+ */
+
+STATIC void
+clearcmdentry(int firstchange)
+{
+	struct tblentry **tblp;
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	INTOFF;
+	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
+		pp = tblp;
+		while ((cmdp = *pp) != NULL) {
+			if ((cmdp->cmdtype == CMDNORMAL &&
+			     cmdp->param.index >= firstchange)
+			 || (cmdp->cmdtype == CMDBUILTIN &&
+			     builtinloc >= firstchange)) {
+				*pp = cmdp->next;
+				ckfree(cmdp);
+			} else {
+				pp = &cmdp->next;
+			}
+		}
+	}
+	INTON;
+}
+
+
+/*
+ * Delete all functions.
+ */
+
+#ifdef mkinit
+MKINIT void deletefuncs(void);
+MKINIT void hash_special_builtins(void);
+
+INIT {
+	hash_special_builtins();
+}
+
+SHELLPROC {
+	deletefuncs();
+}
+#endif
+
+void
+deletefuncs(void)
+{
+	struct tblentry **tblp;
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	INTOFF;
+	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
+		pp = tblp;
+		while ((cmdp = *pp) != NULL) {
+			if (cmdp->cmdtype == CMDFUNCTION) {
+				*pp = cmdp->next;
+				freefunc(cmdp->param.func);
+				ckfree(cmdp);
+			} else {
+				pp = &cmdp->next;
+			}
+		}
+	}
+	INTON;
+}
+
+
+
+/*
+ * Locate a command in the command hash table.  If "add" is nonzero,
+ * add the command to the table if it is not already present.  The
+ * variable "lastcmdentry" is set to point to the address of the link
+ * pointing to the entry, so that delete_cmd_entry can delete the
+ * entry.
+ */
+
+struct tblentry **lastcmdentry;
+
+
+STATIC struct tblentry *
+cmdlookup(const char *name, int add)
+{
+	int hashval;
+	const char *p;
+	struct tblentry *cmdp;
+	struct tblentry **pp;
+
+	p = name;
+	hashval = *p << 4;
+	while (*p)
+		hashval += *p++;
+	hashval &= 0x7FFF;
+	pp = &cmdtable[hashval % CMDTABLESIZE];
+	for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+		if (equal(cmdp->cmdname, name))
+			break;
+		pp = &cmdp->next;
+	}
+	if (add && cmdp == NULL) {
+		INTOFF;
+		cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
+					+ strlen(name) + 1);
+		cmdp->next = NULL;
+		cmdp->cmdtype = CMDUNKNOWN;
+		cmdp->rehash = 0;
+		strcpy(cmdp->cmdname, name);
+		INTON;
+	}
+	lastcmdentry = pp;
+	return cmdp;
+}
+
+/*
+ * Delete the command entry returned on the last lookup.
+ */
+
+STATIC void
+delete_cmd_entry(void)
+{
+	struct tblentry *cmdp;
+
+	INTOFF;
+	cmdp = *lastcmdentry;
+	*lastcmdentry = cmdp->next;
+	ckfree(cmdp);
+	INTON;
+}
+
+
+
+#ifdef notdef
+void
+getcmdentry(char *name, struct cmdentry *entry)
+{
+	struct tblentry *cmdp = cmdlookup(name, 0);
+
+	if (cmdp) {
+		entry->u = cmdp->param;
+		entry->cmdtype = cmdp->cmdtype;
+	} else {
+		entry->cmdtype = CMDUNKNOWN;
+		entry->u.index = 0;
+	}
+}
+#endif
+
+
+/*
+ * Add a new command entry, replacing any existing command entry for
+ * the same name - except special builtins.
+ */
+
+STATIC void
+addcmdentry(char *name, struct cmdentry *entry)
+{
+	struct tblentry *cmdp;
+
+	INTOFF;
+	cmdp = cmdlookup(name, 1);
+	if (cmdp->cmdtype != CMDSPLBLTIN) {
+		if (cmdp->cmdtype == CMDFUNCTION) {
+			freefunc(cmdp->param.func);
+		}
+		cmdp->cmdtype = entry->cmdtype;
+		cmdp->param = entry->u;
+	}
+	INTON;
+}
+
+
+/*
+ * Define a shell function.
+ */
+
+void
+defun(char *name, union node *func)
+{
+	struct cmdentry entry;
+
+	INTOFF;
+	entry.cmdtype = CMDFUNCTION;
+	entry.u.func = copyfunc(func);
+	addcmdentry(name, &entry);
+	INTON;
+}
+
+
+/*
+ * Delete a function if it exists.
+ */
+
+int
+unsetfunc(char *name)
+{
+	struct tblentry *cmdp;
+
+	if ((cmdp = cmdlookup(name, 0)) != NULL &&
+	    cmdp->cmdtype == CMDFUNCTION) {
+		freefunc(cmdp->param.func);
+		delete_cmd_entry();
+		return (0);
+	}
+	return (1);
+}
+
+/*
+ * Locate and print what a word is...
+ * also used for 'command -[v|V]'
+ */
+
+int
+typecmd(int argc, char **argv)
+{
+	struct cmdentry entry;
+	struct tblentry *cmdp;
+	char * const *pp;
+	struct alias *ap;
+	int err = 0;
+	char *arg;
+	int c;
+	int V_flag = 0;
+	int v_flag = 0;
+	int p_flag = 0;
+
+	while ((c = nextopt("vVp")) != 0) {
+		switch (c) {
+		case 'v': v_flag = 1; break;
+		case 'V': V_flag = 1; break;
+		case 'p': p_flag = 1; break;
+		}
+	}
+
+	if (p_flag && (v_flag || V_flag))
+		error("cannot specify -p with -v or -V");
+
+	while ((arg = *argptr++)) {
+		if (!v_flag)
+			out1str(arg);
+		/* First look at the keywords */
+		for (pp = parsekwd; *pp; pp++)
+			if (**pp == *arg && equal(*pp, arg))
+				break;
+
+		if (*pp) {
+			if (v_flag)
+				err = 1;
+			else
+				out1str(" is a shell keyword\n");
+			continue;
+		}
+
+		/* Then look at the aliases */
+		if ((ap = lookupalias(arg, 1)) != NULL) {
+			if (!v_flag)
+				out1fmt(" is an alias for \n");
+			out1fmt("%s\n", ap->val);
+			continue;
+		}
+
+		/* Then check if it is a tracked alias */
+		if ((cmdp = cmdlookup(arg, 0)) != NULL) {
+			entry.cmdtype = cmdp->cmdtype;
+			entry.u = cmdp->param;
+		} else {
+			/* Finally use brute force */
+			find_command(arg, &entry, DO_ABS, pathval());
+		}
+
+		switch (entry.cmdtype) {
+		case CMDNORMAL: {
+			if (strchr(arg, '/') == NULL) {
+				const char *path = pathval();
+				char *name;
+				int j = entry.u.index;
+				do {
+					name = padvance(&path, arg);
+					stunalloc(name);
+				} while (--j >= 0);
+				if (!v_flag)
+					out1fmt(" is%s ",
+					    cmdp ? " a tracked alias for" : "");
+				out1fmt("%s\n", name);
+			} else {
+				if (access(arg, X_OK) == 0) {
+					if (!v_flag)
+						out1fmt(" is ");
+					out1fmt("%s\n", arg);
+				} else {
+					if (!v_flag)
+						out1fmt(": %s\n",
+						    strerror(errno));
+					else
+						err = 126;
+				}
+			}
+ 			break;
+		}
+		case CMDFUNCTION:
+			if (!v_flag)
+				out1str(" is a shell function\n");
+			else
+				out1fmt("%s\n", arg);
+			break;
+
+		case CMDBUILTIN:
+			if (!v_flag)
+				out1str(" is a shell builtin\n");
+			else
+				out1fmt("%s\n", arg);
+			break;
+
+		case CMDSPLBLTIN:
+			if (!v_flag)
+				out1str(" is a special shell builtin\n");
+			else
+				out1fmt("%s\n", arg);
+			break;
+
+		default:
+			if (!v_flag)
+				out1str(": not found\n");
+			err = 127;
+			break;
+		}
+	}
+	return err;
+}
Index: /tags/kBuild-0.1.4/src/ash/exec.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/exec.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/exec.h	(revision 1780)
@@ -0,0 +1,79 @@
+/*	$NetBSD: exec.h,v 1.21 2003/08/07 09:05:31 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)exec.h	8.3 (Berkeley) 6/8/95
+ */
+
+/* values of cmdtype */
+#define CMDUNKNOWN	-1	/* no entry in table for command */
+#define CMDNORMAL	0	/* command is an executable program */
+#define CMDFUNCTION	1	/* command is a shell function */
+#define CMDBUILTIN	2	/* command is a shell builtin */
+#define CMDSPLBLTIN	3	/* command is a special shell builtin */
+
+
+struct cmdentry {
+	int cmdtype;
+	union param {
+		int index;
+		int (*bltin)(int, char**);
+		union node *func;
+	} u;
+};
+
+
+/* action to find_command() */
+#define DO_ERR		0x01	/* prints errors */
+#define DO_ABS		0x02	/* checks absolute paths */
+#define DO_NOFUNC	0x04	/* don't return shell functions, for command */
+#define DO_ALTPATH	0x08	/* using alternate path */
+#define DO_ALTBLTIN	0x20	/* %builtin in alt. path */
+
+extern const char *pathopt;	/* set by padvance */
+
+void shellexec(char **, char **, const char *, int, int)
+    __attribute__((__noreturn__));
+char *padvance(const char **, const char *);
+int hashcmd(int, char **);
+void find_command(char *, struct cmdentry *, int, const char *);
+int (*find_builtin(char *))(int, char **);
+int (*find_splbltin(char *))(int, char **);
+void hashcd(void);
+void changepath(const char *);
+void deletefuncs(void);
+void getcmdentry(char *, struct cmdentry *);
+void addcmdentry(char *, struct cmdentry *);
+void defun(char *, union node *);
+int unsetfunc(char *);
+int typecmd(int, char **);
+void hash_special_builtins(void);
Index: /tags/kBuild-0.1.4/src/ash/expand.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/expand.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/expand.c	(revision 1780)
@@ -0,0 +1,1569 @@
+/*	$NetBSD: expand.c,v 1.71 2005/06/01 15:41:19 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)expand.c	8.5 (Berkeley) 5/15/95";
+#else
+__RCSID("$NetBSD: expand.c,v 1.71 2005/06/01 15:41:19 lukem Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef __sun__
+#include <iso/limits_iso.h>
+#endif
+
+/*
+ * Routines to expand arguments to commands.  We have to deal with
+ * backquotes, shell variables, and file metacharacters.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"
+#include "eval.h"
+#include "expand.h"
+#include "syntax.h"
+#include "parser.h"
+#include "jobs.h"
+#include "options.h"
+#include "var.h"
+#include "input.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "show.h"
+
+/*
+ * Structure specifying which parts of the string should be searched
+ * for IFS characters.
+ */
+
+struct ifsregion {
+	struct ifsregion *next;	/* next region in list */
+	int begoff;		/* offset of start of region */
+	int endoff;		/* offset of end of region */
+	int inquotes;		/* search for nul bytes only */
+};
+
+
+char *expdest;			/* output of current string */
+struct nodelist *argbackq;	/* list of back quote expressions */
+struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
+struct ifsregion *ifslastp;	/* last struct in list */
+struct arglist exparg;		/* holds expanded arg list */
+
+STATIC void argstr(char *, int);
+STATIC char *exptilde(char *, int);
+STATIC void expbackq(union node *, int, int);
+STATIC int subevalvar(char *, char *, int, int, int, int);
+STATIC char *evalvar(char *, int);
+STATIC int varisset(char *, int);
+STATIC void varvalue(char *, int, int, int);
+STATIC void recordregion(int, int, int);
+STATIC void removerecordregions(int);
+STATIC void ifsbreakup(char *, struct arglist *);
+STATIC void ifsfree(void);
+STATIC void expandmeta(struct strlist *, int);
+STATIC void expmeta(char *, char *);
+STATIC void addfname(char *);
+STATIC struct strlist *expsort(struct strlist *);
+STATIC struct strlist *msort(struct strlist *, int);
+STATIC int pmatch(char *, char *, int);
+STATIC char *cvtnum(int, char *);
+
+/*
+ * Expand shell variables and backquotes inside a here document.
+ */
+
+void
+expandhere(union node *arg, int fd)
+{
+	herefd = fd;
+	expandarg(arg, (struct arglist *)NULL, 0);
+	xwrite(fd, stackblock(), expdest - stackblock());
+}
+
+
+/*
+ * Perform variable substitution and command substitution on an argument,
+ * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
+ * perform splitting and file name expansion.  When arglist is NULL, perform
+ * here document expansion.
+ */
+
+void
+expandarg(union node *arg, struct arglist *arglist, int flag)
+{
+	struct strlist *sp;
+	char *p;
+
+	argbackq = arg->narg.backquote;
+	STARTSTACKSTR(expdest);
+	ifsfirst.next = NULL;
+	ifslastp = NULL;
+	argstr(arg->narg.text, flag);
+	if (arglist == NULL) {
+		return;			/* here document expanded */
+	}
+	STPUTC('\0', expdest);
+	p = grabstackstr(expdest);
+	exparg.lastp = &exparg.list;
+	/*
+	 * TODO - EXP_REDIR
+	 */
+	if (flag & EXP_FULL) {
+		ifsbreakup(p, &exparg);
+		*exparg.lastp = NULL;
+		exparg.lastp = &exparg.list;
+		expandmeta(exparg.list, flag);
+	} else {
+		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
+			rmescapes(p);
+		sp = (struct strlist *)stalloc(sizeof (struct strlist));
+		sp->text = p;
+		*exparg.lastp = sp;
+		exparg.lastp = &sp->next;
+	}
+	ifsfree();
+	*exparg.lastp = NULL;
+	if (exparg.list) {
+		*arglist->lastp = exparg.list;
+		arglist->lastp = exparg.lastp;
+	}
+}
+
+
+
+/*
+ * Perform variable and command substitution.
+ * If EXP_FULL is set, output CTLESC characters to allow for further processing.
+ * Otherwise treat $@ like $* since no splitting will be performed.
+ */
+
+STATIC void
+argstr(char *p, int flag)
+{
+	char c;
+	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
+	int firsteq = 1;
+	const char *ifs = NULL;
+	int ifs_split = EXP_IFS_SPLIT;
+
+	if (flag & EXP_IFS_SPLIT)
+		ifs = ifsset() ? ifsval() : " \t\n";
+
+	if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
+		p = exptilde(p, flag);
+	for (;;) {
+		switch (c = *p++) {
+		case '\0':
+		case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */
+			return;
+		case CTLQUOTEMARK:
+			/* "$@" syntax adherence hack */
+			if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
+				break;
+			if ((flag & EXP_FULL) != 0)
+				STPUTC(c, expdest);
+			ifs_split = 0;
+			break;
+		case CTLQUOTEEND:
+			ifs_split = EXP_IFS_SPLIT;
+			break;
+		case CTLESC:
+			if (quotes)
+				STPUTC(c, expdest);
+			c = *p++;
+			STPUTC(c, expdest);
+			break;
+		case CTLVAR:
+			p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split));
+			break;
+		case CTLBACKQ:
+		case CTLBACKQ|CTLQUOTE:
+			expbackq(argbackq->n, c & CTLQUOTE, flag);
+			argbackq = argbackq->next;
+			break;
+		case CTLENDARI:
+			expari(flag);
+			break;
+		case ':':
+		case '=':
+			/*
+			 * sort of a hack - expand tildes in variable
+			 * assignments (after the first '=' and after ':'s).
+			 */
+			STPUTC(c, expdest);
+			if (flag & EXP_VARTILDE && *p == '~') {
+				if (c == '=') {
+					if (firsteq)
+						firsteq = 0;
+					else
+						break;
+				}
+				p = exptilde(p, flag);
+			}
+			break;
+		default:
+			STPUTC(c, expdest);
+			if (flag & EXP_IFS_SPLIT & ifs_split && strchr(ifs, c) != NULL) {
+				/* We need to get the output split here... */
+				recordregion(expdest - stackblock() - 1,
+						expdest - stackblock(), 0);
+			}
+			break;
+		}
+	}
+}
+
+STATIC char *
+exptilde(char *p, int flag)
+{
+	char c, *startp = p;
+	struct passwd *pw;
+	const char *home;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+
+	while ((c = *p) != '\0') {
+		switch(c) {
+		case CTLESC:
+			return (startp);
+		case CTLQUOTEMARK:
+			return (startp);
+		case ':':
+			if (flag & EXP_VARTILDE)
+				goto done;
+			break;
+		case '/':
+			goto done;
+		}
+		p++;
+	}
+done:
+	*p = '\0';
+	if (*(startp+1) == '\0') {
+		if ((home = lookupvar("HOME")) == NULL)
+			goto lose;
+	} else {
+		if ((pw = getpwnam(startp+1)) == NULL)
+			goto lose;
+		home = pw->pw_dir;
+	}
+	if (*home == '\0')
+		goto lose;
+	*p = c;
+	while ((c = *home++) != '\0') {
+		if (quotes && SQSYNTAX[(int)c] == CCTL)
+			STPUTC(CTLESC, expdest);
+		STPUTC(c, expdest);
+	}
+	return (p);
+lose:
+	*p = c;
+	return (startp);
+}
+
+
+STATIC void
+removerecordregions(int endoff)
+{
+	if (ifslastp == NULL)
+		return;
+
+	if (ifsfirst.endoff > endoff) {
+		while (ifsfirst.next != NULL) {
+			struct ifsregion *ifsp;
+			INTOFF;
+			ifsp = ifsfirst.next->next;
+			ckfree(ifsfirst.next);
+			ifsfirst.next = ifsp;
+			INTON;
+		}
+		if (ifsfirst.begoff > endoff)
+			ifslastp = NULL;
+		else {
+			ifslastp = &ifsfirst;
+			ifsfirst.endoff = endoff;
+		}
+		return;
+	}
+
+	ifslastp = &ifsfirst;
+	while (ifslastp->next && ifslastp->next->begoff < endoff)
+		ifslastp=ifslastp->next;
+	while (ifslastp->next != NULL) {
+		struct ifsregion *ifsp;
+		INTOFF;
+		ifsp = ifslastp->next->next;
+		ckfree(ifslastp->next);
+		ifslastp->next = ifsp;
+		INTON;
+	}
+	if (ifslastp->endoff > endoff)
+		ifslastp->endoff = endoff;
+}
+
+
+/*
+ * Expand arithmetic expression.  Backup to start of expression,
+ * evaluate, place result in (backed up) result, adjust string position.
+ */
+void
+expari(int flag)
+{
+	char *p, *start;
+	int result;
+	int begoff;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+	int quoted;
+
+	/*	ifsfree(); */
+
+	/*
+	 * This routine is slightly over-complicated for
+	 * efficiency.  First we make sure there is
+	 * enough space for the result, which may be bigger
+	 * than the expression if we add exponentation.  Next we
+	 * scan backwards looking for the start of arithmetic.  If the
+	 * next previous character is a CTLESC character, then we
+	 * have to rescan starting from the beginning since CTLESC
+	 * characters have to be processed left to right.
+	 */
+#if INT_MAX / 1000000000 >= 10 || INT_MIN / 1000000000 <= -10
+#error "integers with more than 10 digits are not supported"
+#endif
+	CHECKSTRSPACE(12 - 2, expdest);
+	USTPUTC('\0', expdest);
+	start = stackblock();
+	p = expdest - 1;
+	while (*p != CTLARI && p >= start)
+		--p;
+	if (*p != CTLARI)
+		error("missing CTLARI (shouldn't happen)");
+	if (p > start && *(p-1) == CTLESC)
+		for (p = start; *p != CTLARI; p++)
+			if (*p == CTLESC)
+				p++;
+
+	if (p[1] == '"')
+		quoted=1;
+	else
+		quoted=0;
+	begoff = p - start;
+	removerecordregions(begoff);
+	if (quotes)
+		rmescapes(p+2);
+	result = arith(p+2);
+	fmtstr(p, 12, "%d", result);
+
+	while (*p++)
+		;
+
+	if (quoted == 0)
+		recordregion(begoff, p - 1 - start, 0);
+	result = expdest - p + 1;
+	STADJUST(-result, expdest);
+}
+
+
+/*
+ * Expand stuff in backwards quotes.
+ */
+
+STATIC void
+expbackq(union node *cmd, int quoted, int flag)
+{
+	struct backcmd in;
+	int i;
+	char buf[128];
+	char *p;
+	char *dest = expdest;
+	struct ifsregion saveifs, *savelastp;
+	struct nodelist *saveargbackq;
+	char lastc;
+	int startloc = dest - stackblock();
+	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
+	int saveherefd;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+
+	INTOFF;
+	saveifs = ifsfirst;
+	savelastp = ifslastp;
+	saveargbackq = argbackq;
+	saveherefd = herefd;
+	herefd = -1;
+	p = grabstackstr(dest);
+	evalbackcmd(cmd, &in);
+	ungrabstackstr(p, dest);
+	ifsfirst = saveifs;
+	ifslastp = savelastp;
+	argbackq = saveargbackq;
+	herefd = saveherefd;
+
+	p = in.buf;
+	lastc = '\0';
+	for (;;) {
+		if (--in.nleft < 0) {
+			if (in.fd < 0)
+				break;
+			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
+			TRACE(("expbackq: read returns %d\n", i));
+			if (i <= 0)
+				break;
+			p = buf;
+			in.nleft = i - 1;
+		}
+		lastc = *p++;
+		if (lastc != '\0') {
+			if (quotes && syntax[(int)lastc] == CCTL)
+				STPUTC(CTLESC, dest);
+			STPUTC(lastc, dest);
+		}
+	}
+
+	/* Eat all trailing newlines */
+	p = stackblock() + startloc;
+	while (dest > p && dest[-1] == '\n')
+		STUNPUTC(dest);
+
+	if (in.fd >= 0)
+		close(in.fd);
+	if (in.buf)
+		ckfree(in.buf);
+	if (in.jp)
+		back_exitstatus = waitforjob(in.jp);
+	if (quoted == 0)
+		recordregion(startloc, dest - stackblock(), 0);
+	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
+		(dest - stackblock()) - startloc,
+		(dest - stackblock()) - startloc,
+		stackblock() + startloc));
+	expdest = dest;
+	INTON;
+}
+
+
+
+STATIC int
+subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags)
+{
+	char *startp;
+	char *loc = NULL;
+	char *q;
+	int c = 0;
+	int saveherefd = herefd;
+	struct nodelist *saveargbackq = argbackq;
+	int amount;
+
+	herefd = -1;
+	argstr(p, 0);
+	STACKSTRNUL(expdest);
+	herefd = saveherefd;
+	argbackq = saveargbackq;
+	startp = stackblock() + startloc;
+	if (str == NULL)
+	    str = stackblock() + strloc;
+
+	switch (subtype) {
+	case VSASSIGN:
+		setvar(str, startp, 0);
+		amount = startp - expdest;
+		STADJUST(amount, expdest);
+		varflags &= ~VSNUL;
+		if (c != 0)
+			*loc = c;
+		return 1;
+
+	case VSQUESTION:
+		if (*p != CTLENDVAR) {
+			outfmt(&errout, "%s\n", startp);
+			error((char *)NULL);
+		}
+		error("%.*s: parameter %snot set", p - str - 1,
+		      str, (varflags & VSNUL) ? "null or "
+					      : nullstr);
+		/* NOTREACHED */
+
+	case VSTRIMLEFT:
+		for (loc = startp; loc < str; loc++) {
+			c = *loc;
+			*loc = '\0';
+			if (patmatch(str, startp, varflags & VSQUOTE))
+				goto recordleft;
+			*loc = c;
+			if ((varflags & VSQUOTE) && *loc == CTLESC)
+			        loc++;
+		}
+		return 0;
+
+	case VSTRIMLEFTMAX:
+		for (loc = str - 1; loc >= startp;) {
+			c = *loc;
+			*loc = '\0';
+			if (patmatch(str, startp, varflags & VSQUOTE))
+				goto recordleft;
+			*loc = c;
+			loc--;
+			if ((varflags & VSQUOTE) && loc > startp &&
+			    *(loc - 1) == CTLESC) {
+				for (q = startp; q < loc; q++)
+					if (*q == CTLESC)
+						q++;
+				if (q > loc)
+					loc--;
+			}
+		}
+		return 0;
+
+	case VSTRIMRIGHT:
+	        for (loc = str - 1; loc >= startp;) {
+			if (patmatch(str, loc, varflags & VSQUOTE))
+				goto recordright;
+			loc--;
+			if ((varflags & VSQUOTE) && loc > startp &&
+			    *(loc - 1) == CTLESC) {
+				for (q = startp; q < loc; q++)
+					if (*q == CTLESC)
+						q++;
+				if (q > loc)
+					loc--;
+			}
+		}
+		return 0;
+
+	case VSTRIMRIGHTMAX:
+		for (loc = startp; loc < str - 1; loc++) {
+			if (patmatch(str, loc, varflags & VSQUOTE))
+				goto recordright;
+			if ((varflags & VSQUOTE) && *loc == CTLESC)
+			        loc++;
+		}
+		return 0;
+
+	default:
+		abort();
+	}
+
+recordleft:
+	*loc = c;
+	amount = ((str - 1) - (loc - startp)) - expdest;
+	STADJUST(amount, expdest);
+	while (loc != str - 1)
+		*startp++ = *loc++;
+	return 1;
+
+recordright:
+	amount = loc - expdest;
+	STADJUST(amount, expdest);
+	STPUTC('\0', expdest);
+	STADJUST(-1, expdest);
+	return 1;
+}
+
+
+/*
+ * Expand a variable, and return a pointer to the next character in the
+ * input string.
+ */
+
+STATIC char *
+evalvar(char *p, int flag)
+{
+	int subtype;
+	int varflags;
+	char *var;
+	char *val;
+	int patloc;
+	int c;
+	int set;
+	int special;
+	int startloc;
+	int varlen;
+	int apply_ifs;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+
+	varflags = (unsigned char)*p++;
+	subtype = varflags & VSTYPE;
+	var = p;
+	special = !is_name(*p);
+	p = strchr(p, '=') + 1;
+
+again: /* jump here after setting a variable with ${var=text} */
+	if (special) {
+		set = varisset(var, varflags & VSNUL);
+		val = NULL;
+	} else {
+		val = lookupvar(var);
+		if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
+			val = NULL;
+			set = 0;
+		} else
+			set = 1;
+	}
+
+	varlen = 0;
+	startloc = expdest - stackblock();
+
+	if (!set && uflag) {
+		switch (subtype) {
+		case VSNORMAL:
+		case VSTRIMLEFT:
+		case VSTRIMLEFTMAX:
+		case VSTRIMRIGHT:
+		case VSTRIMRIGHTMAX:
+		case VSLENGTH:
+			error("%.*s: parameter not set", p - var - 1, var);
+			/* NOTREACHED */
+		}
+	}
+
+	if (set && subtype != VSPLUS) {
+		/* insert the value of the variable */
+		if (special) {
+			varvalue(var, varflags & VSQUOTE, subtype, flag);
+			if (subtype == VSLENGTH) {
+				varlen = expdest - stackblock() - startloc;
+				STADJUST(-varlen, expdest);
+			}
+		} else {
+			char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
+								  : BASESYNTAX;
+
+			if (subtype == VSLENGTH) {
+				for (;*val; val++)
+					varlen++;
+			} else {
+				while (*val) {
+					if (quotes && syntax[(int)*val] == CCTL)
+						STPUTC(CTLESC, expdest);
+					STPUTC(*val++, expdest);
+				}
+
+			}
+		}
+	}
+
+
+	apply_ifs = ((varflags & VSQUOTE) == 0 ||
+		(*var == '@' && shellparam.nparam != 1));
+
+	switch (subtype) {
+	case VSLENGTH:
+		expdest = cvtnum(varlen, expdest);
+		break;
+
+	case VSNORMAL:
+		break;
+
+	case VSPLUS:
+		set = !set;
+		/* FALLTHROUGH */
+	case VSMINUS:
+		if (!set) {
+		        argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0));
+			/*
+			 * ${x-a b c} doesn't get split, but removing the
+			 * 'apply_ifs = 0' apparantly breaks ${1+"$@"}..
+			 * ${x-'a b' c} should generate 2 args.
+			 */
+			/* We should have marked stuff already */
+			apply_ifs = 0;
+		}
+		break;
+
+	case VSTRIMLEFT:
+	case VSTRIMLEFTMAX:
+	case VSTRIMRIGHT:
+	case VSTRIMRIGHTMAX:
+		if (!set)
+			break;
+		/*
+		 * Terminate the string and start recording the pattern
+		 * right after it
+		 */
+		STPUTC('\0', expdest);
+		patloc = expdest - stackblock();
+		if (subevalvar(p, NULL, patloc, subtype,
+			       startloc, varflags) == 0) {
+			int amount = (expdest - stackblock() - patloc) + 1;
+			STADJUST(-amount, expdest);
+		}
+		/* Remove any recorded regions beyond start of variable */
+		removerecordregions(startloc);
+		apply_ifs = 1;
+		break;
+
+	case VSASSIGN:
+	case VSQUESTION:
+		if (set)
+			break;
+		if (subevalvar(p, var, 0, subtype, startloc, varflags)) {
+			varflags &= ~VSNUL;
+			/*
+			 * Remove any recorded regions beyond
+			 * start of variable
+			 */
+			removerecordregions(startloc);
+			goto again;
+		}
+		apply_ifs = 0;
+		break;
+
+	default:
+		abort();
+	}
+
+	if (apply_ifs)
+		recordregion(startloc, expdest - stackblock(),
+			     varflags & VSQUOTE);
+
+	if (subtype != VSNORMAL) {	/* skip to end of alternative */
+		int nesting = 1;
+		for (;;) {
+			if ((c = *p++) == CTLESC)
+				p++;
+			else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
+				if (set)
+					argbackq = argbackq->next;
+			} else if (c == CTLVAR) {
+				if ((*p++ & VSTYPE) != VSNORMAL)
+					nesting++;
+			} else if (c == CTLENDVAR) {
+				if (--nesting == 0)
+					break;
+			}
+		}
+	}
+	return p;
+}
+
+
+
+/*
+ * Test whether a specialized variable is set.
+ */
+
+STATIC int
+varisset(char *name, int nulok)
+{
+	if (*name == '!')
+		return backgndpid != -1;
+	else if (*name == '@' || *name == '*') {
+		if (*shellparam.p == NULL)
+			return 0;
+
+		if (nulok) {
+			char **av;
+
+			for (av = shellparam.p; *av; av++)
+				if (**av != '\0')
+					return 1;
+			return 0;
+		}
+	} else if (is_digit(*name)) {
+		char *ap;
+		int num = atoi(name);
+
+		if (num > shellparam.nparam)
+			return 0;
+
+		if (num == 0)
+			ap = arg0;
+		else
+			ap = shellparam.p[num - 1];
+
+		if (nulok && (ap == NULL || *ap == '\0'))
+			return 0;
+	}
+	return 1;
+}
+
+
+
+/*
+ * Add the value of a specialized variable to the stack string.
+ */
+
+STATIC void
+varvalue(char *name, int quoted, int subtype, int flag)
+{
+	int num;
+	char *p;
+	int i;
+	char sep;
+	char **ap;
+	char const *syntax;
+
+#define STRTODEST(p) \
+	do {\
+	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \
+		syntax = quoted? DQSYNTAX : BASESYNTAX; \
+		while (*p) { \
+			if (syntax[(int)*p] == CCTL) \
+				STPUTC(CTLESC, expdest); \
+			STPUTC(*p++, expdest); \
+		} \
+	} else \
+		while (*p) \
+			STPUTC(*p++, expdest); \
+	} while (0)
+
+
+	switch (*name) {
+	case '$':
+		num = rootpid;
+		goto numvar;
+	case '?':
+		num = exitstatus;
+		goto numvar;
+	case '#':
+		num = shellparam.nparam;
+		goto numvar;
+	case '!':
+		num = backgndpid;
+numvar:
+		expdest = cvtnum(num, expdest);
+		break;
+	case '-':
+		for (i = 0; optlist[i].name; i++) {
+			if (optlist[i].val)
+				STPUTC(optlist[i].letter, expdest);
+		}
+		break;
+	case '@':
+		if (flag & EXP_FULL && quoted) {
+			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
+				STRTODEST(p);
+				if (*ap)
+					STPUTC('\0', expdest);
+			}
+			break;
+		}
+		/* fall through */
+	case '*':
+		if (ifsset() != 0)
+			sep = ifsval()[0];
+		else
+			sep = ' ';
+		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
+			STRTODEST(p);
+			if (*ap && sep)
+				STPUTC(sep, expdest);
+		}
+		break;
+	case '0':
+		p = arg0;
+		STRTODEST(p);
+		break;
+	default:
+		if (is_digit(*name)) {
+			num = atoi(name);
+			if (num > 0 && num <= shellparam.nparam) {
+				p = shellparam.p[num - 1];
+				STRTODEST(p);
+			}
+		}
+		break;
+	}
+}
+
+
+
+/*
+ * Record the fact that we have to scan this region of the
+ * string for IFS characters.
+ */
+
+STATIC void
+recordregion(int start, int end, int inquotes)
+{
+	struct ifsregion *ifsp;
+
+	if (ifslastp == NULL) {
+		ifsp = &ifsfirst;
+	} else {
+		if (ifslastp->endoff == start
+		    && ifslastp->inquotes == inquotes) {
+			/* extend previous area */
+			ifslastp->endoff = end;
+			return;
+		}
+		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
+		ifslastp->next = ifsp;
+	}
+	ifslastp = ifsp;
+	ifslastp->next = NULL;
+	ifslastp->begoff = start;
+	ifslastp->endoff = end;
+	ifslastp->inquotes = inquotes;
+}
+
+
+
+/*
+ * Break the argument string into pieces based upon IFS and add the
+ * strings to the argument list.  The regions of the string to be
+ * searched for IFS characters have been stored by recordregion.
+ */
+STATIC void
+ifsbreakup(char *string, struct arglist *arglist)
+{
+	struct ifsregion *ifsp;
+	struct strlist *sp;
+	char *start;
+	char *p;
+	char *q;
+	const char *ifs;
+	const char *ifsspc;
+	int inquotes;
+
+	start = string;
+	ifsspc = NULL;
+	inquotes = 0;
+
+	if (ifslastp == NULL) {
+		/* Return entire argument, IFS doesn't apply to any of it */
+		sp = (struct strlist *)stalloc(sizeof *sp);
+		sp->text = start;
+		*arglist->lastp = sp;
+		arglist->lastp = &sp->next;
+		return;
+	}
+
+	ifs = ifsset() ? ifsval() : " \t\n";
+
+	for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
+		p = string + ifsp->begoff;
+		inquotes = ifsp->inquotes;
+		ifsspc = NULL;
+		while (p < string + ifsp->endoff) {
+			q = p;
+			if (*p == CTLESC)
+				p++;
+			if (inquotes) {
+				/* Only NULs (probably from "$@") end args */
+				if (*p != 0) {
+					p++;
+					continue;
+				}
+			} else {
+				if (!strchr(ifs, *p)) {
+					p++;
+					continue;
+				}
+				ifsspc = strchr(" \t\n", *p);
+
+				/* Ignore IFS whitespace at start */
+				if (q == start && ifsspc != NULL) {
+					p++;
+					start = p;
+					continue;
+				}
+			}
+
+			/* Save this argument... */
+			*q = '\0';
+			sp = (struct strlist *)stalloc(sizeof *sp);
+			sp->text = start;
+			*arglist->lastp = sp;
+			arglist->lastp = &sp->next;
+			p++;
+
+			if (ifsspc != NULL) {
+				/* Ignore further trailing IFS whitespace */
+				for (; p < string + ifsp->endoff; p++) {
+					q = p;
+					if (*p == CTLESC)
+						p++;
+					if (strchr(ifs, *p) == NULL) {
+						p = q;
+						break;
+					}
+					if (strchr(" \t\n", *p) == NULL) {
+						p++;
+						break;
+					}
+				}
+			}
+			start = p;
+		}
+	}
+
+	/*
+	 * Save anything left as an argument.
+	 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as
+	 * generating 2 arguments, the second of which is empty.
+	 * Some recent clarification of the Posix spec say that it
+	 * should only generate one....
+	 */
+	if (*start /* || (!ifsspc && start > string) */) {
+		sp = (struct strlist *)stalloc(sizeof *sp);
+		sp->text = start;
+		*arglist->lastp = sp;
+		arglist->lastp = &sp->next;
+	}
+}
+
+STATIC void
+ifsfree(void)
+{
+	while (ifsfirst.next != NULL) {
+		struct ifsregion *ifsp;
+		INTOFF;
+		ifsp = ifsfirst.next->next;
+		ckfree(ifsfirst.next);
+		ifsfirst.next = ifsp;
+		INTON;
+	}
+	ifslastp = NULL;
+	ifsfirst.next = NULL;
+}
+
+
+
+/*
+ * Expand shell metacharacters.  At this point, the only control characters
+ * should be escapes.  The results are stored in the list exparg.
+ */
+
+char *expdir;
+
+
+STATIC void
+expandmeta(struct strlist *str, int flag)
+{
+	char *p;
+	struct strlist **savelastp;
+	struct strlist *sp;
+	char c;
+	/* TODO - EXP_REDIR */
+
+	while (str) {
+		if (fflag)
+			goto nometa;
+		p = str->text;
+		for (;;) {			/* fast check for meta chars */
+			if ((c = *p++) == '\0')
+				goto nometa;
+			if (c == '*' || c == '?' || c == '[' || c == '!')
+				break;
+		}
+		savelastp = exparg.lastp;
+		INTOFF;
+		if (expdir == NULL) {
+			int i = strlen(str->text);
+			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
+		}
+
+		expmeta(expdir, str->text);
+		ckfree(expdir);
+		expdir = NULL;
+		INTON;
+		if (exparg.lastp == savelastp) {
+			/*
+			 * no matches
+			 */
+nometa:
+			*exparg.lastp = str;
+			rmescapes(str->text);
+			exparg.lastp = &str->next;
+		} else {
+			*exparg.lastp = NULL;
+			*savelastp = sp = expsort(*savelastp);
+			while (sp->next != NULL)
+				sp = sp->next;
+			exparg.lastp = &sp->next;
+		}
+		str = str->next;
+	}
+}
+
+
+/*
+ * Do metacharacter (i.e. *, ?, [...]) expansion.
+ */
+
+STATIC void
+expmeta(char *enddir, char *name)
+{
+	char *p;
+	const char *cp;
+	char *q;
+	char *start;
+	char *endname;
+	int metaflag;
+	struct stat statb;
+	DIR *dirp;
+	struct dirent *dp;
+	int atend;
+	int matchdot;
+
+	metaflag = 0;
+	start = name;
+	for (p = name ; ; p++) {
+		if (*p == '*' || *p == '?')
+			metaflag = 1;
+		else if (*p == '[') {
+			q = p + 1;
+			if (*q == '!')
+				q++;
+			for (;;) {
+				while (*q == CTLQUOTEMARK)
+					q++;
+				if (*q == CTLESC)
+					q++;
+				if (*q == '/' || *q == '\0')
+					break;
+				if (*++q == ']') {
+					metaflag = 1;
+					break;
+				}
+			}
+		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {
+			metaflag = 1;
+		} else if (*p == '\0')
+			break;
+		else if (*p == CTLQUOTEMARK)
+			continue;
+		else if (*p == CTLESC)
+			p++;
+		if (*p == '/') {
+			if (metaflag)
+				break;
+			start = p + 1;
+		}
+	}
+	if (metaflag == 0) {	/* we've reached the end of the file name */
+		if (enddir != expdir)
+			metaflag++;
+		for (p = name ; ; p++) {
+			if (*p == CTLQUOTEMARK)
+				continue;
+			if (*p == CTLESC)
+				p++;
+			*enddir++ = *p;
+			if (*p == '\0')
+				break;
+		}
+		if (metaflag == 0 || lstat(expdir, &statb) >= 0)
+			addfname(expdir);
+		return;
+	}
+	endname = p;
+	if (start != name) {
+		p = name;
+		while (p < start) {
+			while (*p == CTLQUOTEMARK)
+				p++;
+			if (*p == CTLESC)
+				p++;
+			*enddir++ = *p++;
+		}
+	}
+	if (enddir == expdir) {
+		cp = ".";
+	} else if (enddir == expdir + 1 && *expdir == '/') {
+		cp = "/";
+	} else {
+		cp = expdir;
+		enddir[-1] = '\0';
+	}
+	if ((dirp = opendir(cp)) == NULL)
+		return;
+	if (enddir != expdir)
+		enddir[-1] = '/';
+	if (*endname == 0) {
+		atend = 1;
+	} else {
+		atend = 0;
+		*endname++ = '\0';
+	}
+	matchdot = 0;
+	p = start;
+	while (*p == CTLQUOTEMARK)
+		p++;
+	if (*p == CTLESC)
+		p++;
+	if (*p == '.')
+		matchdot++;
+	while (! int_pending() && (dp = readdir(dirp)) != NULL) {
+		if (dp->d_name[0] == '.' && ! matchdot)
+			continue;
+		if (patmatch(start, dp->d_name, 0)) {
+			if (atend) {
+				scopy(dp->d_name, enddir);
+				addfname(expdir);
+			} else {
+				for (p = enddir, cp = dp->d_name;
+				     (*p++ = *cp++) != '\0';)
+					continue;
+				p[-1] = '/';
+				expmeta(p, endname);
+			}
+		}
+	}
+	closedir(dirp);
+	if (! atend)
+		endname[-1] = '/';
+}
+
+
+/*
+ * Add a file name to the list.
+ */
+
+STATIC void
+addfname(char *name)
+{
+	char *p;
+	struct strlist *sp;
+
+	p = stalloc(strlen(name) + 1);
+	scopy(name, p);
+	sp = (struct strlist *)stalloc(sizeof *sp);
+	sp->text = p;
+	*exparg.lastp = sp;
+	exparg.lastp = &sp->next;
+}
+
+
+/*
+ * Sort the results of file name expansion.  It calculates the number of
+ * strings to sort and then calls msort (short for merge sort) to do the
+ * work.
+ */
+
+STATIC struct strlist *
+expsort(struct strlist *str)
+{
+	int len;
+	struct strlist *sp;
+
+	len = 0;
+	for (sp = str ; sp ; sp = sp->next)
+		len++;
+	return msort(str, len);
+}
+
+
+STATIC struct strlist *
+msort(struct strlist *list, int len)
+{
+	struct strlist *p, *q = NULL;
+	struct strlist **lpp;
+	int half;
+	int n;
+
+	if (len <= 1)
+		return list;
+	half = len >> 1;
+	p = list;
+	for (n = half ; --n >= 0 ; ) {
+		q = p;
+		p = p->next;
+	}
+	q->next = NULL;			/* terminate first half of list */
+	q = msort(list, half);		/* sort first half of list */
+	p = msort(p, len - half);		/* sort second half */
+	lpp = &list;
+	for (;;) {
+		if (strcmp(p->text, q->text) < 0) {
+			*lpp = p;
+			lpp = &p->next;
+			if ((p = *lpp) == NULL) {
+				*lpp = q;
+				break;
+			}
+		} else {
+			*lpp = q;
+			lpp = &q->next;
+			if ((q = *lpp) == NULL) {
+				*lpp = p;
+				break;
+			}
+		}
+	}
+	return list;
+}
+
+
+
+/*
+ * Returns true if the pattern matches the string.
+ */
+
+int
+patmatch(char *pattern, char *string, int squoted)
+{
+#ifdef notdef
+	if (pattern[0] == '!' && pattern[1] == '!')
+		return 1 - pmatch(pattern + 2, string);
+	else
+#endif
+		return pmatch(pattern, string, squoted);
+}
+
+
+STATIC int
+pmatch(char *pattern, char *string, int squoted)
+{
+	char *p, *q;
+	char c;
+
+	p = pattern;
+	q = string;
+	for (;;) {
+		switch (c = *p++) {
+		case '\0':
+			goto breakloop;
+		case CTLESC:
+			if (squoted && *q == CTLESC)
+				q++;
+			if (*q++ != *p++)
+				return 0;
+			break;
+		case CTLQUOTEMARK:
+			continue;
+		case '?':
+			if (squoted && *q == CTLESC)
+				q++;
+			if (*q++ == '\0')
+				return 0;
+			break;
+		case '*':
+			c = *p;
+			while (c == CTLQUOTEMARK || c == '*')
+				c = *++p;
+			if (c != CTLESC &&  c != CTLQUOTEMARK &&
+			    c != '?' && c != '*' && c != '[') {
+				while (*q != c) {
+					if (squoted && *q == CTLESC &&
+					    q[1] == c)
+						break;
+					if (*q == '\0')
+						return 0;
+					if (squoted && *q == CTLESC)
+						q++;
+					q++;
+				}
+			}
+			do {
+				if (pmatch(p, q, squoted))
+					return 1;
+				if (squoted && *q == CTLESC)
+					q++;
+			} while (*q++ != '\0');
+			return 0;
+		case '[': {
+			char *endp;
+			int invert, found;
+			char chr;
+
+			endp = p;
+			if (*endp == '!')
+				endp++;
+			for (;;) {
+				while (*endp == CTLQUOTEMARK)
+					endp++;
+				if (*endp == '\0')
+					goto dft;		/* no matching ] */
+				if (*endp == CTLESC)
+					endp++;
+				if (*++endp == ']')
+					break;
+			}
+			invert = 0;
+			if (*p == '!') {
+				invert++;
+				p++;
+			}
+			found = 0;
+			chr = *q++;
+			if (squoted && chr == CTLESC)
+				chr = *q++;
+			if (chr == '\0')
+				return 0;
+			c = *p++;
+			do {
+				if (c == CTLQUOTEMARK)
+					continue;
+				if (c == CTLESC)
+					c = *p++;
+				if (*p == '-' && p[1] != ']') {
+					p++;
+					while (*p == CTLQUOTEMARK)
+						p++;
+					if (*p == CTLESC)
+						p++;
+					if (chr >= c && chr <= *p)
+						found = 1;
+					p++;
+				} else {
+					if (chr == c)
+						found = 1;
+				}
+			} while ((c = *p++) != ']');
+			if (found == invert)
+				return 0;
+			break;
+		}
+dft:	        default:
+			if (squoted && *q == CTLESC)
+				q++;
+			if (*q++ != c)
+				return 0;
+			break;
+		}
+	}
+breakloop:
+	if (*q != '\0')
+		return 0;
+	return 1;
+}
+
+
+
+/*
+ * Remove any CTLESC characters from a string.
+ */
+
+void
+rmescapes(char *str)
+{
+	char *p, *q;
+
+	p = str;
+	while (*p != CTLESC && *p != CTLQUOTEMARK) {
+		if (*p++ == '\0')
+			return;
+	}
+	q = p;
+	while (*p) {
+		if (*p == CTLQUOTEMARK) {
+			p++;
+			continue;
+		}
+		if (*p == CTLESC)
+			p++;
+		*q++ = *p++;
+	}
+	*q = '\0';
+}
+
+
+
+/*
+ * See if a pattern matches in a case statement.
+ */
+
+int
+casematch(union node *pattern, char *val)
+{
+	struct stackmark smark;
+	int result;
+	char *p;
+
+	setstackmark(&smark);
+	argbackq = pattern->narg.backquote;
+	STARTSTACKSTR(expdest);
+	ifslastp = NULL;
+	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
+	STPUTC('\0', expdest);
+	p = grabstackstr(expdest);
+	result = patmatch(p, val, 0);
+	popstackmark(&smark);
+	return result;
+}
+
+/*
+ * Our own itoa().
+ */
+
+STATIC char *
+cvtnum(int num, char *buf)
+{
+	char temp[32];
+	int neg = num < 0;
+	char *p = temp + 31;
+
+	temp[31] = '\0';
+
+	do {
+		*--p = num % 10 + '0';
+	} while ((num /= 10) != 0);
+
+	if (neg)
+		*--p = '-';
+
+	while (*p)
+		STPUTC(*p++, buf);
+	return buf;
+}
+
+/*
+ * Do most of the work for wordexp(3).
+ */
+
+int
+wordexpcmd(int argc, char **argv)
+{
+	size_t len;
+	int i;
+
+	out1fmt("%d", argc - 1);
+	out1c('\0');
+	for (i = 1, len = 0; i < argc; i++)
+		len += strlen(argv[i]);
+	out1fmt("%zd", len);
+	out1c('\0');
+	for (i = 1; i < argc; i++) {
+		out1str(argv[i]);
+		out1c('\0');
+	}
+	return (0);
+}
Index: /tags/kBuild-0.1.4/src/ash/expand.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/expand.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/expand.h	(revision 1780)
@@ -0,0 +1,72 @@
+/*	$NetBSD: expand.h,v 1.16 2004/07/13 15:05:59 seb Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)expand.h	8.2 (Berkeley) 5/4/95
+ */
+
+struct strlist {
+	struct strlist *next;
+	char *text;
+};
+
+
+struct arglist {
+	struct strlist *list;
+	struct strlist **lastp;
+};
+
+/*
+ * expandarg() flags
+ */
+#define EXP_FULL	0x1	/* perform word splitting & file globbing */
+#define EXP_TILDE	0x2	/* do normal tilde expansion */
+#define	EXP_VARTILDE	0x4	/* expand tildes in an assignment */
+#define	EXP_REDIR	0x8	/* file glob for a redirection (1 match only) */
+#define EXP_CASE	0x10	/* keeps quotes around for CASE pattern */
+#define EXP_IFS_SPLIT	0x20	/* need to record arguments for ifs breakup */
+
+
+union node;
+void expandhere(union node *, int);
+void expandarg(union node *, struct arglist *, int);
+void expari(int);
+int patmatch(char *, char *, int);
+void rmescapes(char *);
+int casematch(union node *, char *);
+int wordexpcmd(int, char **);
+
+/* From arith.y */
+int arith(const char *);
+int expcmd(int , char **);
+void arith_lex_reset(void);
+int yylex(void);
Index: /tags/kBuild-0.1.4/src/ash/funcs/cmv
===================================================================
--- /tags/kBuild-0.1.4/src/ash/funcs/cmv	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/funcs/cmv	(revision 1780)
@@ -0,0 +1,50 @@
+#	$NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)cmv	8.2 (Berkeley) 5/4/95
+
+# Conditional move--don't replace an existing file.
+
+cmv() {
+	if test $# != 2
+	then	echo "cmv: arg count"
+		return 2
+	fi
+	if test -f "$2" -o -w "$2"
+	then	echo "$2 exists"
+		return 2
+	fi
+	/bin/mv "$1" "$2"
+}
Index: /tags/kBuild-0.1.4/src/ash/funcs/dirs
===================================================================
--- /tags/kBuild-0.1.4/src/ash/funcs/dirs	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/funcs/dirs	(revision 1780)
@@ -0,0 +1,74 @@
+#	$NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)dirs	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /tags/kBuild-0.1.4/src/ash/funcs/kill
===================================================================
--- /tags/kBuild-0.1.4/src/ash/funcs/kill	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/funcs/kill	(revision 1780)
@@ -0,0 +1,50 @@
+#	$NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)kill	8.2 (Berkeley) 5/4/95
+
+# Convert job names to process ids and then run /bin/kill.
+
+kill() {
+	local args x
+	args=
+	for x in "$@"
+	do	case $x in
+		%*)	x=`jobid "$x"` ;;
+		esac
+		args="$args $x"
+	done
+	/bin/kill $args
+}
Index: /tags/kBuild-0.1.4/src/ash/funcs/login
===================================================================
--- /tags/kBuild-0.1.4/src/ash/funcs/login	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/funcs/login	(revision 1780)
@@ -0,0 +1,39 @@
+#	$NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)login	8.2 (Berkeley) 5/4/95
+
+# replaces the login builtin in the BSD shell
+login () exec login "$@"
Index: /tags/kBuild-0.1.4/src/ash/funcs/newgrp
===================================================================
--- /tags/kBuild-0.1.4/src/ash/funcs/newgrp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/funcs/newgrp	(revision 1780)
@@ -0,0 +1,38 @@
+#	$NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)newgrp	8.2 (Berkeley) 5/4/95
+
+newgrp() exec newgrp "$@"
Index: /tags/kBuild-0.1.4/src/ash/funcs/popd
===================================================================
--- /tags/kBuild-0.1.4/src/ash/funcs/popd	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/funcs/popd	(revision 1780)
@@ -0,0 +1,74 @@
+#	$NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)popd	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /tags/kBuild-0.1.4/src/ash/funcs/pushd
===================================================================
--- /tags/kBuild-0.1.4/src/ash/funcs/pushd	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/funcs/pushd	(revision 1780)
@@ -0,0 +1,74 @@
+#	$NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)pushd	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /tags/kBuild-0.1.4/src/ash/funcs/suspend
===================================================================
--- /tags/kBuild-0.1.4/src/ash/funcs/suspend	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/funcs/suspend	(revision 1780)
@@ -0,0 +1,42 @@
+#	$NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)suspend	8.2 (Berkeley) 5/4/95
+
+suspend() {
+	local -
+	set +j
+	kill -TSTP 0
+}
Index: /tags/kBuild-0.1.4/src/ash/generated/arith.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/arith.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/arith.c	(revision 1780)
@@ -0,0 +1,666 @@
+#ifndef lint
+/*static char yysccsid[] = "from: @(#)yaccpar	1.9 (Berkeley) 02/21/93";*/
+static char yyrcsid[] = "$Id: skeleton.c,v 1.2 1997/06/23 02:51:17 tdukes Exp $";
+#endif
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define yyclearin (yychar=(-1))
+#define yyerrok (yyerrflag=0)
+#define YYRECOVERING (yyerrflag!=0)
+#define YYPREFIX "yy"
+/*	$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)arith.y	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+#include "expand.h"
+#include "shell.h"
+#include "error.h"
+#include "output.h"
+#include "memalloc.h"
+
+const char *arith_buf, *arith_startbuf;
+
+void yyerror(const char *);
+#ifdef TESTARITH
+int main(int , char *[]);
+int error(char *);
+#endif
+
+#define ARITH_NUM 257
+#define ARITH_LPAREN 258
+#define ARITH_RPAREN 259
+#define ARITH_OR 260
+#define ARITH_AND 261
+#define ARITH_BOR 262
+#define ARITH_BXOR 263
+#define ARITH_BAND 264
+#define ARITH_EQ 265
+#define ARITH_NE 266
+#define ARITH_LT 267
+#define ARITH_GT 268
+#define ARITH_GE 269
+#define ARITH_LE 270
+#define ARITH_LSHIFT 271
+#define ARITH_RSHIFT 272
+#define ARITH_ADD 273
+#define ARITH_SUB 274
+#define ARITH_MUL 275
+#define ARITH_DIV 276
+#define ARITH_REM 277
+#define ARITH_UNARYMINUS 278
+#define ARITH_UNARYPLUS 279
+#define ARITH_NOT 280
+#define ARITH_BNOT 281
+#define YYERRCODE 256
+short yylhs[] = {                                        -1,
+    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,
+};
+short yylen[] = {                                         2,
+    1,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+    3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+    2,    2,    2,    2,    1,
+};
+short yydefred[] = {                                      0,
+   25,    0,    0,    0,    0,    0,    0,    0,    0,   24,
+   23,   21,   22,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    2,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,   18,   19,   20,
+};
+short yydgoto[] = {                                       7,
+    8,
+};
+short yysindex[] = {                                   -255,
+    0, -255, -255, -255, -255, -255,    0,  -67,  -85,    0,
+    0,    0,    0, -255, -255, -255, -255, -255, -255, -255,
+ -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+ -255,    0,  -50,  -34,  -19,  141, -261, -233, -233, -223,
+ -223, -223, -223, -253, -253, -248, -248,    0,    0,    0,
+};
+short yyrindex[] = {                                      0,
+    0,    0,    0,    0,    0,    0,    0,   30,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,  143,  140,  136,  131,  125,  109,  117,   61,
+   73,   85,   97,   33,   47,    1,   17,    0,    0,    0,
+};
+short yygindex[] = {                                      0,
+  142,
+};
+#define YYTABLESIZE 418
+short yytable[] = {                                       0,
+   16,    1,    2,   19,   20,   21,   22,   23,   24,   25,
+   26,   27,   28,   29,   30,   31,   17,    3,    4,   27,
+   28,   29,   30,   31,    5,    6,   29,   30,   31,    1,
+    0,    0,   14,   21,   22,   23,   24,   25,   26,   27,
+   28,   29,   30,   31,    0,    0,   15,   25,   26,   27,
+   28,   29,   30,   31,    0,    0,    0,    0,    0,    0,
+   11,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    9,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,   10,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   12,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    8,    0,
+    0,    0,    0,    0,    0,    0,   13,    0,    0,    0,
+    0,    0,    0,    0,    7,    0,    0,    0,    0,    0,
+    6,    0,    0,    0,    0,    5,    0,    0,    0,    4,
+    0,    0,    3,    9,   10,   11,   12,   13,    0,    0,
+    0,    0,    0,    0,    0,   33,   34,   35,   36,   37,
+   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,
+   48,   49,   50,   32,   14,   15,   16,   17,   18,   19,
+   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,
+   30,   31,   14,   15,   16,   17,   18,   19,   20,   21,
+   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,
+   15,   16,   17,   18,   19,   20,   21,   22,   23,   24,
+   25,   26,   27,   28,   29,   30,   31,   16,   17,   18,
+   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+   29,   30,   31,   17,   18,   19,   20,   21,   22,   23,
+   24,   25,   26,   27,   28,   29,   30,   31,    0,   16,
+   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+   16,   16,   16,   16,   16,   17,   17,   17,   17,   17,
+   17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+   17,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+   14,   14,   14,   14,   14,   15,   15,   15,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   11,
+   11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+   11,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+    9,    9,    9,   10,   10,   10,   10,   10,   10,   10,
+   10,   10,   10,   10,   10,   12,   12,   12,   12,   12,
+   12,   12,   12,   12,   12,   12,   12,    8,    8,    8,
+    8,    8,    8,    8,    8,   13,   13,   13,   13,   13,
+   13,   13,   13,    7,    7,    7,    7,    7,    7,    6,
+    6,    6,    6,    6,    5,    5,    5,    5,    4,    4,
+    4,    3,    3,    0,   18,   19,   20,   21,   22,   23,
+   24,   25,   26,   27,   28,   29,   30,   31,
+};
+short yycheck[] = {                                      -1,
+    0,  257,  258,  265,  266,  267,  268,  269,  270,  271,
+  272,  273,  274,  275,  276,  277,    0,  273,  274,  273,
+  274,  275,  276,  277,  280,  281,  275,  276,  277,    0,
+   -1,   -1,    0,  267,  268,  269,  270,  271,  272,  273,
+  274,  275,  276,  277,   -1,   -1,    0,  271,  272,  273,
+  274,  275,  276,  277,   -1,   -1,   -1,   -1,   -1,   -1,
+    0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,
+    0,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,    0,
+   -1,   -1,    0,    2,    3,    4,    5,    6,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   14,   15,   16,   17,   18,
+   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+   29,   30,   31,  259,  260,  261,  262,  263,  264,  265,
+  266,  267,  268,  269,  270,  271,  272,  273,  274,  275,
+  276,  277,  260,  261,  262,  263,  264,  265,  266,  267,
+  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,
+  261,  262,  263,  264,  265,  266,  267,  268,  269,  270,
+  271,  272,  273,  274,  275,  276,  277,  262,  263,  264,
+  265,  266,  267,  268,  269,  270,  271,  272,  273,  274,
+  275,  276,  277,  263,  264,  265,  266,  267,  268,  269,
+  270,  271,  272,  273,  274,  275,  276,  277,   -1,  259,
+  260,  261,  262,  263,  264,  265,  266,  267,  268,  269,
+  270,  271,  272,  273,  274,  259,  260,  261,  262,  263,
+  264,  265,  266,  267,  268,  269,  270,  271,  272,  273,
+  274,  259,  260,  261,  262,  263,  264,  265,  266,  267,
+  268,  269,  270,  271,  272,  259,  260,  261,  262,  263,
+  264,  265,  266,  267,  268,  269,  270,  271,  272,  259,
+  260,  261,  262,  263,  264,  265,  266,  267,  268,  269,
+  270,  259,  260,  261,  262,  263,  264,  265,  266,  267,
+  268,  269,  270,  259,  260,  261,  262,  263,  264,  265,
+  266,  267,  268,  269,  270,  259,  260,  261,  262,  263,
+  264,  265,  266,  267,  268,  269,  270,  259,  260,  261,
+  262,  263,  264,  265,  266,  259,  260,  261,  262,  263,
+  264,  265,  266,  259,  260,  261,  262,  263,  264,  259,
+  260,  261,  262,  263,  259,  260,  261,  262,  259,  260,
+  261,  259,  260,   -1,  264,  265,  266,  267,  268,  269,
+  270,  271,  272,  273,  274,  275,  276,  277,
+};
+#define YYFINAL 7
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 281
+#if YYDEBUG
+char *yyname[] = {
+"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"ARITH_NUM","ARITH_LPAREN",
+"ARITH_RPAREN","ARITH_OR","ARITH_AND","ARITH_BOR","ARITH_BXOR","ARITH_BAND",
+"ARITH_EQ","ARITH_NE","ARITH_LT","ARITH_GT","ARITH_GE","ARITH_LE",
+"ARITH_LSHIFT","ARITH_RSHIFT","ARITH_ADD","ARITH_SUB","ARITH_MUL","ARITH_DIV",
+"ARITH_REM","ARITH_UNARYMINUS","ARITH_UNARYPLUS","ARITH_NOT","ARITH_BNOT",
+};
+char *yyrule[] = {
+"$accept : exp",
+"exp : expr",
+"expr : ARITH_LPAREN expr ARITH_RPAREN",
+"expr : expr ARITH_OR expr",
+"expr : expr ARITH_AND expr",
+"expr : expr ARITH_BOR expr",
+"expr : expr ARITH_BXOR expr",
+"expr : expr ARITH_BAND expr",
+"expr : expr ARITH_EQ expr",
+"expr : expr ARITH_GT expr",
+"expr : expr ARITH_GE expr",
+"expr : expr ARITH_LT expr",
+"expr : expr ARITH_LE expr",
+"expr : expr ARITH_NE expr",
+"expr : expr ARITH_LSHIFT expr",
+"expr : expr ARITH_RSHIFT expr",
+"expr : expr ARITH_ADD expr",
+"expr : expr ARITH_SUB expr",
+"expr : expr ARITH_MUL expr",
+"expr : expr ARITH_DIV expr",
+"expr : expr ARITH_REM expr",
+"expr : ARITH_NOT expr",
+"expr : ARITH_BNOT expr",
+"expr : ARITH_SUB expr",
+"expr : ARITH_ADD expr",
+"expr : ARITH_NUM",
+};
+#endif
+#ifndef YYSTYPE
+typedef int YYSTYPE;
+#endif
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 500
+#define YYMAXDEPTH 500
+#endif
+#endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+short yyss[YYSTACKSIZE];
+YYSTYPE yyvs[YYSTACKSIZE];
+#define yystacksize YYSTACKSIZE
+int
+arith(s)
+	const char *s;
+{
+	long result;
+
+	arith_buf = arith_startbuf = s;
+
+	INTOFF;
+	result = yyparse();
+	arith_lex_reset();	/* reprime lex */
+	INTON;
+
+	return (result);
+}
+
+
+/*
+ *  The exp(1) builtin.
+ */
+int
+expcmd(argc, argv)
+	int argc;
+	char **argv;
+{
+	const char *p;
+	char *concat;
+	char **ap;
+	long i;
+
+	if (argc > 1) {
+		p = argv[1];
+		if (argc > 2) {
+			/*
+			 * concatenate arguments
+			 */
+			STARTSTACKSTR(concat);
+			ap = argv + 2;
+			for (;;) {
+				while (*p)
+					STPUTC(*p++, concat);
+				if ((p = *ap++) == NULL)
+					break;
+				STPUTC(' ', concat);
+			}
+			STPUTC('\0', concat);
+			p = grabstackstr(concat);
+		}
+	} else
+		p = "";
+
+	i = arith(p);
+
+	out1fmt("%ld\n", i);
+	return (! i);
+}
+
+/*************************/
+#ifdef TEST_ARITH
+#include <stdio.h>
+main(argc, argv)
+	char *argv[];
+{
+	printf("%d\n", exp(argv[1]));
+}
+error(s)
+	char *s;
+{
+	fprintf(stderr, "exp: %s\n", s);
+	exit(1);
+}
+#endif
+
+void
+yyerror(s)
+	const char *s;
+{
+
+	yyerrok;
+	yyclearin;
+	arith_lex_reset();	/* reprime lex */
+	error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
+	/* NOTREACHED */
+}
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+#ifdef __cplusplus
+extern "C" { 
+char * getenv();
+int yylex();
+int yyparse();
+}
+
+#endif
+int
+#if defined(__STDC__)
+yyparse(void)
+#else
+yyparse()
+#endif
+{
+    register int yym, yyn, yystate;
+#if YYDEBUG
+    register char *yys;
+#ifndef __cplusplus
+    extern char *getenv();
+#endif
+
+    if (yys = getenv("YYDEBUG"))
+    {
+        yyn = *yys;
+        if (yyn >= '0' && yyn <= '9')
+            yydebug = yyn - '0';
+    }
+#endif
+
+    yynerrs = 0;
+    yyerrflag = 0;
+    yychar = (-1);
+
+    yyssp = yyss;
+    yyvsp = yyvs;
+    *yyssp = yystate = 0;
+
+yyloop:
+    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+    if (yychar < 0)
+    {
+        if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, reading %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+    }
+    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: state %d, shifting to state %d\n",
+                    YYPREFIX, yystate, yytable[yyn]);
+#endif
+        if (yyssp >= yyss + yystacksize - 1)
+        {
+            goto yyoverflow;
+        }
+        *++yyssp = yystate = yytable[yyn];
+        *++yyvsp = yylval;
+        yychar = (-1);
+        if (yyerrflag > 0)  --yyerrflag;
+        goto yyloop;
+    }
+    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+        yyn = yytable[yyn];
+        goto yyreduce;
+    }
+    if (yyerrflag) goto yyinrecovery;
+    yyerror("syntax error");
+#ifdef lint
+    goto yyerrlab;
+#endif
+yyerrlab:
+    ++yynerrs;
+yyinrecovery:
+    if (yyerrflag < 3)
+    {
+        yyerrflag = 3;
+        for (;;)
+        {
+            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+                if (yyssp >= yyss + yystacksize - 1)
+                {
+                    goto yyoverflow;
+                }
+                *++yyssp = yystate = yytable[yyn];
+                *++yyvsp = yylval;
+                goto yyloop;
+            }
+            else
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: error recovery discarding state %d\n",
+                            YYPREFIX, *yyssp);
+#endif
+                if (yyssp <= yyss) goto yyabort;
+                --yyssp;
+                --yyvsp;
+            }
+        }
+    }
+    else
+    {
+        if (yychar == 0) goto yyabort;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+        yychar = (-1);
+        goto yyloop;
+    }
+yyreduce:
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+                YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+    yym = yylen[yyn];
+    yyval = yyvsp[1-yym];
+    switch (yyn)
+    {
+case 1:
+{
+			return (yyvsp[0]);
+		}
+break;
+case 2:
+{ yyval = yyvsp[-1]; }
+break;
+case 3:
+{ yyval = yyvsp[-2] ? yyvsp[-2] : yyvsp[0] ? yyvsp[0] : 0; }
+break;
+case 4:
+{ yyval = yyvsp[-2] ? ( yyvsp[0] ? yyvsp[0] : 0 ) : 0; }
+break;
+case 5:
+{ yyval = yyvsp[-2] | yyvsp[0]; }
+break;
+case 6:
+{ yyval = yyvsp[-2] ^ yyvsp[0]; }
+break;
+case 7:
+{ yyval = yyvsp[-2] & yyvsp[0]; }
+break;
+case 8:
+{ yyval = yyvsp[-2] == yyvsp[0]; }
+break;
+case 9:
+{ yyval = yyvsp[-2] > yyvsp[0]; }
+break;
+case 10:
+{ yyval = yyvsp[-2] >= yyvsp[0]; }
+break;
+case 11:
+{ yyval = yyvsp[-2] < yyvsp[0]; }
+break;
+case 12:
+{ yyval = yyvsp[-2] <= yyvsp[0]; }
+break;
+case 13:
+{ yyval = yyvsp[-2] != yyvsp[0]; }
+break;
+case 14:
+{ yyval = yyvsp[-2] << yyvsp[0]; }
+break;
+case 15:
+{ yyval = yyvsp[-2] >> yyvsp[0]; }
+break;
+case 16:
+{ yyval = yyvsp[-2] + yyvsp[0]; }
+break;
+case 17:
+{ yyval = yyvsp[-2] - yyvsp[0]; }
+break;
+case 18:
+{ yyval = yyvsp[-2] * yyvsp[0]; }
+break;
+case 19:
+{
+			if (yyvsp[0] == 0)
+				yyerror("division by zero");
+			yyval = yyvsp[-2] / yyvsp[0];
+			}
+break;
+case 20:
+{
+			if (yyvsp[0] == 0)
+				yyerror("division by zero");
+			yyval = yyvsp[-2] % yyvsp[0];
+			}
+break;
+case 21:
+{ yyval = !(yyvsp[0]); }
+break;
+case 22:
+{ yyval = ~(yyvsp[0]); }
+break;
+case 23:
+{ yyval = -(yyvsp[0]); }
+break;
+case 24:
+{ yyval = yyvsp[0]; }
+break;
+    }
+    yyssp -= yym;
+    yystate = *yyssp;
+    yyvsp -= yym;
+    yym = yylhs[yyn];
+    if (yystate == 0 && yym == 0)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+        yystate = YYFINAL;
+        *++yyssp = YYFINAL;
+        *++yyvsp = yyval;
+        if (yychar < 0)
+        {
+            if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+            if (yydebug)
+            {
+                yys = 0;
+                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+                if (!yys) yys = "illegal-symbol";
+                printf("%sdebug: state %d, reading %d (%s)\n",
+                        YYPREFIX, YYFINAL, yychar, yys);
+            }
+#endif
+        }
+        if (yychar == 0) goto yyaccept;
+        goto yyloop;
+    }
+    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+        yystate = yytable[yyn];
+    else
+        yystate = yydgoto[yym];
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
+#endif
+    if (yyssp >= yyss + yystacksize - 1)
+    {
+        goto yyoverflow;
+    }
+    *++yyssp = yystate;
+    *++yyvsp = yyval;
+    goto yyloop;
+yyoverflow:
+    yyerror("yacc stack overflow");
+yyabort:
+    return (1);
+yyaccept:
+    return (0);
+}
Index: /tags/kBuild-0.1.4/src/ash/generated/arith.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/arith.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/arith.h	(revision 1780)
@@ -0,0 +1,25 @@
+#define ARITH_NUM 257
+#define ARITH_LPAREN 258
+#define ARITH_RPAREN 259
+#define ARITH_OR 260
+#define ARITH_AND 261
+#define ARITH_BOR 262
+#define ARITH_BXOR 263
+#define ARITH_BAND 264
+#define ARITH_EQ 265
+#define ARITH_NE 266
+#define ARITH_LT 267
+#define ARITH_GT 268
+#define ARITH_GE 269
+#define ARITH_LE 270
+#define ARITH_LSHIFT 271
+#define ARITH_RSHIFT 272
+#define ARITH_ADD 273
+#define ARITH_SUB 274
+#define ARITH_MUL 275
+#define ARITH_DIV 276
+#define ARITH_REM 277
+#define ARITH_UNARYMINUS 278
+#define ARITH_UNARYPLUS 279
+#define ARITH_NOT 280
+#define ARITH_BNOT 281
Index: /tags/kBuild-0.1.4/src/ash/generated/arith_lex.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/arith_lex.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/arith_lex.c	(revision 1780)
@@ -0,0 +1,1724 @@
+#line 2 "/home/bird/Coding/kBuild/svn/trunk/out/linux.x86/debug/obj/src/ash/arith_lex.c"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ * 	if ( condition_holds )
+ *		yyless( 5 );
+ *	else
+ *		do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		*yy_cp = yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+	};
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yytext_ptr = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 29
+#define YY_END_OF_BUFFER 30
+static yyconst short int yy_accept[39] =
+    {   0,
+        0,    0,   30,   28,    1,    1,   27,   23,   12,    6,
+        7,   21,   24,   25,   22,    3,    4,   17,   28,   15,
+        5,   11,   10,   26,   14,    9,    3,    0,    4,   19,
+       18,   13,   16,   20,    5,    8,    2,    0
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    1,    1,    1,    5,    6,    1,    7,
+        8,    9,   10,    1,   11,    1,   12,   13,   14,   14,
+       14,   14,   14,   14,   14,   15,   15,    1,    1,   16,
+       17,   18,    1,    1,   19,   19,   19,   19,   19,   19,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+        1,    1,    1,   21,   20,    1,   19,   19,   19,   19,
+
+       19,   19,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   22,
+       20,   20,    1,   23,    1,   24,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[25] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    2,    2,    2,    1,    1,    1,    2,    3,
+        1,    3,    1,    1
+    } ;
+
+static yyconst short int yy_base[41] =
+    {   0,
+        0,    0,   47,   48,   48,   48,   29,   48,   39,   48,
+       48,   48,   48,   48,   48,   12,   14,   14,   27,   15,
+        0,   48,   20,   48,   48,   48,   22,    0,   24,   48,
+       48,   48,   48,   48,    0,   48,    0,   48,   38,   40
+    } ;
+
+static yyconst short int yy_def[41] =
+    {   0,
+       38,    1,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       39,   38,   38,   38,   38,   38,   38,   40,   38,   38,
+       38,   38,   38,   38,   39,   38,   40,    0,   38,   38
+    } ;
+
+static yyconst short int yy_nxt[73] =
+    {   0,
+        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
+       14,   15,   16,   17,   17,   18,   19,   20,   21,   21,
+       22,   21,   23,   24,   27,   27,   29,   29,   29,   30,
+       31,   33,   34,   28,   27,   27,   29,   29,   29,   35,
+       35,   37,   36,   32,   26,   25,   38,    3,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38
+    } ;
+
+static yyconst short int yy_chk[73] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,   16,   16,   17,   17,   17,   18,
+       18,   20,   20,   16,   27,   27,   29,   29,   29,   39,
+       39,   40,   23,   19,    9,    7,    3,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "arith_lex.l"
+#define INITIAL 0
+#line 3 "arith_lex.l"
+/*	$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)arith_lex.l	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $");
+#endif
+#endif /* not lint */
+
+#include <unistd.h>
+#include "arith.h"
+#include "error.h"
+#include "expand.h"
+#include "var.h"
+
+extern int yylval;
+extern char *arith_buf, *arith_startbuf;
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max) \
+	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
+#define YY_NO_UNPUT
+#line 448 "/home/bird/Coding/kBuild/svn/trunk/out/linux.x86/debug/obj/src/ash/arith_lex.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( yy_current_buffer->yy_is_interactive ) \
+		{ \
+		int c = '*', n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+		  && ferror( yyin ) ) \
+		YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+YY_DECL
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp = NULL, *yy_bp = NULL;
+	register int yy_act;
+
+#line 60 "arith_lex.l"
+
+#line 601 "/home/bird/Coding/kBuild/svn/trunk/out/linux.x86/debug/obj/src/ash/arith_lex.c"
+
+	if ( yy_init )
+		{
+		yy_init = 0;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yy_start )
+			yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! yy_current_buffer )
+			yy_current_buffer =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+
+		yy_load_buffer_state();
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yy_last_accepting_state = yy_current_state;
+				yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 39 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 48 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = yy_last_accepting_cpos;
+			yy_current_state = yy_last_accepting_state;
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+
+do_action:	/* This label is used only to access EOF actions. */
+
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yy_hold_char;
+			yy_cp = yy_last_accepting_cpos;
+			yy_current_state = yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 61 "arith_lex.l"
+{ ; }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 62 "arith_lex.l"
+{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 63 "arith_lex.l"
+{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 64 "arith_lex.l"
+{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 65 "arith_lex.l"
+{ char *v = lookupvar(yytext);
+			if (v) {
+				yylval = strtol(v, &v, 0);
+				if (*v == 0)
+					return ARITH_NUM;
+			}
+			error("arith: syntax error: \"%s\"", arith_startbuf);
+		}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 73 "arith_lex.l"
+{ return(ARITH_LPAREN); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 74 "arith_lex.l"
+{ return(ARITH_RPAREN); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 75 "arith_lex.l"
+{ return(ARITH_OR); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 76 "arith_lex.l"
+{ return(ARITH_AND); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 77 "arith_lex.l"
+{ return(ARITH_BOR); }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 78 "arith_lex.l"
+{ return(ARITH_BXOR); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 79 "arith_lex.l"
+{ return(ARITH_BAND); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 80 "arith_lex.l"
+{ return(ARITH_EQ); }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 81 "arith_lex.l"
+{ return(ARITH_NE); }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 82 "arith_lex.l"
+{ return(ARITH_GT); }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 83 "arith_lex.l"
+{ return(ARITH_GE); }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 84 "arith_lex.l"
+{ return(ARITH_LT); }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 85 "arith_lex.l"
+{ return(ARITH_LE); }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 86 "arith_lex.l"
+{ return(ARITH_LSHIFT); }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 87 "arith_lex.l"
+{ return(ARITH_RSHIFT); }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 88 "arith_lex.l"
+{ return(ARITH_MUL); }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 89 "arith_lex.l"
+{ return(ARITH_DIV); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 90 "arith_lex.l"
+{ return(ARITH_REM); }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 91 "arith_lex.l"
+{ return(ARITH_ADD); }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 92 "arith_lex.l"
+{ return(ARITH_SUB); }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 93 "arith_lex.l"
+{ return(ARITH_BNOT); }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 94 "arith_lex.l"
+{ return(ARITH_NOT); }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 95 "arith_lex.l"
+{ error("arith: syntax error: \"%s\"", arith_startbuf); }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 96 "arith_lex.l"
+ECHO;
+	YY_BREAK
+#line 836 "/home/bird/Coding/kBuild/svn/trunk/out/linux.x86/debug/obj/src/ash/arith_lex.c"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between yy_current_buffer and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yy_n_chars = yy_current_buffer->yy_n_chars;
+			yy_current_buffer->yy_input_file = yyin;
+			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state();
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer() )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap() )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yy_c_buf_p =
+					yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yy_c_buf_p =
+				&yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+	{
+	register char *dest = yy_current_buffer->yy_ch_buf;
+	register char *source = yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( yy_current_buffer->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+	else
+		{
+		int num_to_read =
+			yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+			YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = yy_current_buffer;
+
+			int yy_c_buf_p_offset =
+				(int) (yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yy_flex_realloc( (void *) b->yy_ch_buf,
+							 b->yy_buf_size + 2 );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = yy_current_buffer->yy_buf_size -
+						number_to_move - 1;
+#endif
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+			yy_n_chars, num_to_read );
+
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	if ( yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			yy_current_buffer->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	yy_n_chars += number_to_move;
+	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+	return ret_val;
+	}
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+
+	yy_current_state = yy_start;
+
+	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yy_last_accepting_state = yy_current_state;
+			yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 39 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+	}
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+	{
+	register int yy_is_jam;
+	register char *yy_cp = yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yy_last_accepting_state = yy_current_state;
+		yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 39 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 38);
+
+	return yy_is_jam ? 0 : yy_current_state;
+	}
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+	{
+	register char *yy_cp = yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yy_hold_char;
+
+	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = yy_n_chars + 2;
+		register char *dest = &yy_current_buffer->yy_ch_buf[
+					yy_current_buffer->yy_buf_size + 2];
+		register char *source =
+				&yy_current_buffer->yy_ch_buf[number_to_move];
+
+		while ( source > yy_current_buffer->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		yy_current_buffer->yy_n_chars =
+			yy_n_chars = yy_current_buffer->yy_buf_size;
+
+		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+
+	yytext_ptr = yy_bp;
+	yy_hold_char = *yy_cp;
+	yy_c_buf_p = yy_cp;
+	}
+#endif	/* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+	{
+	int c;
+
+	*yy_c_buf_p = yy_hold_char;
+
+	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			/* This was really a NUL. */
+			*yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yy_c_buf_p - yytext_ptr;
+			++yy_c_buf_p;
+
+			switch ( yy_get_next_buffer() )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/* fall through */
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap() )
+						return EOF;
+
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yy_c_buf_p = yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
+	*yy_c_buf_p = '\0';	/* preserve yytext */
+	yy_hold_char = *++yy_c_buf_p;
+
+
+	return c;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+	{
+	if ( ! yy_current_buffer )
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+	yy_init_buffer( yy_current_buffer, input_file );
+	yy_load_buffer_state();
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+	{
+	if ( yy_current_buffer == new_buffer )
+		return;
+
+	if ( yy_current_buffer )
+		{
+		/* Flush out information for old buffer. */
+		*yy_c_buf_p = yy_hold_char;
+		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	yy_current_buffer = new_buffer;
+	yy_load_buffer_state();
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yy_did_buffer_switch_on_eof = 1;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+	{
+	yy_n_chars = yy_current_buffer->yy_n_chars;
+	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+	yyin = yy_current_buffer->yy_input_file;
+	yy_hold_char = *yy_c_buf_p;
+	}
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+	{
+	if ( ! b )
+		return;
+
+	if ( b == yy_current_buffer )
+		yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yy_flex_free( (void *) b->yy_ch_buf );
+
+	yy_flex_free( (void *) b );
+	}
+
+
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+	{
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+	b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+	b->yy_is_interactive = 0;
+#else
+	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+	{
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == yy_current_buffer )
+		yy_load_buffer_state();
+	}
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer( b );
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+	{
+	int len;
+	for ( len = 0; yy_str[len]; ++len )
+		;
+
+	return yy_scan_bytes( yy_str, len );
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+	{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = len + 2;
+	buf = (char *) yy_flex_alloc( n );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < len; ++i )
+		buf[i] = bytes[i];
+
+	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer( buf, n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+	{
+	if ( yy_start_stack_ptr >= yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yy_start_stack_depth * sizeof( int );
+
+		if ( ! yy_start_stack )
+			yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+		else
+			yy_start_stack = (int *) yy_flex_realloc(
+					(void *) yy_start_stack, new_size );
+
+		if ( ! yy_start_stack )
+			YY_FATAL_ERROR(
+			"out of memory expanding start-condition stack" );
+		}
+
+	yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+	}
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+	{
+	if ( --yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yy_start_stack[yy_start_stack_ptr]);
+	}
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+	{
+	return yy_start_stack[yy_start_stack_ptr - 1];
+	}
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+	{
+	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+	}
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		yytext[yyleng] = yy_hold_char; \
+		yy_c_buf_p = yytext + n; \
+		yy_hold_char = *yy_c_buf_p; \
+		*yy_c_buf_p = '\0'; \
+		yyleng = n; \
+		} \
+	while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+	{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+	}
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+	{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+	}
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+	{
+	return (void *) malloc( size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+	{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+	{
+	free( ptr );
+	}
+
+#if YY_MAIN
+int main()
+	{
+	yylex();
+	return 0;
+	}
+#endif
+#line 96 "arith_lex.l"
+
+
+void
+arith_lex_reset() {
+#ifdef YY_NEW_FILE
+	YY_NEW_FILE;
+#endif
+}
Index: /tags/kBuild-0.1.4/src/ash/generated/builtins.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/builtins.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/builtins.c	(revision 1780)
@@ -0,0 +1,63 @@
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include "shell.h"
+#include "builtins.h"
+
+const struct builtincmd builtincmd[] = {
+
+	{ "command",	bltincmd },
+	{ "bg",	bgcmd },
+	{ "cd",	cdcmd },
+	{ "chdir",	cdcmd },
+	{ "echo",	echocmd },
+	{ "exp",	expcmd },
+	{ "let",	expcmd },
+	{ "false",	falsecmd },
+	{ "fc",	histcmd },
+	{ "inputrc",	inputrc },
+	{ "fg",	fgcmd },
+	{ "getopts",	getoptscmd },
+	{ "hash",	hashcmd },
+	{ "jobid",	jobidcmd },
+	{ "jobs",	jobscmd },
+	{ "local",	localcmd },
+#ifndef SMALL
+	{ "printf",	printfcmd },
+#endif
+	{ "pwd",	pwdcmd },
+	{ "read",	readcmd },
+	{ "setvar",	setvarcmd },
+	{ "true",	truecmd },
+	{ "type",	typecmd },
+	{ "umask",	umaskcmd },
+	{ "unalias",	unaliascmd },
+	{ "wait",	waitcmd },
+	{ "alias",	aliascmd },
+	{ "ulimit",	ulimitcmd },
+	{ "test",	testcmd },
+	{ "[",	testcmd },
+	{ "kill",	killcmd },
+	{ "wordexp",	wordexpcmd },
+	{ 0, 0 },
+};
+
+const struct builtincmd splbltincmd[] = {
+	{ "break",	breakcmd },
+	{ "continue",	breakcmd },
+	{ ".",	dotcmd },
+	{ "eval",	evalcmd },
+	{ "exec",	execcmd },
+	{ "exit",	exitcmd },
+	{ "export",	exportcmd },
+	{ "readonly",	exportcmd },
+	{ "return",	returncmd },
+	{ "set",	setcmd },
+	{ "shift",	shiftcmd },
+	{ "times",	timescmd },
+	{ "trap",	trapcmd },
+	{ ":",	truecmd },
+	{ "unset",	unsetcmd },
+	{ 0, 0 },
+};
Index: /tags/kBuild-0.1.4/src/ash/generated/builtins.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/builtins.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/builtins.h	(revision 1780)
@@ -0,0 +1,57 @@
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include <sys/cdefs.h>
+
+struct builtincmd {
+      const char *name;
+      int (*builtin)(int, char **);
+};
+
+extern const struct builtincmd builtincmd[];
+extern const struct builtincmd splbltincmd[];
+
+
+int bltincmd(int, char **);
+int bgcmd(int, char **);
+int breakcmd(int, char **);
+int cdcmd(int, char **);
+int dotcmd(int, char **);
+int echocmd(int, char **);
+int evalcmd(int, char **);
+int execcmd(int, char **);
+int exitcmd(int, char **);
+int expcmd(int, char **);
+int exportcmd(int, char **);
+int falsecmd(int, char **);
+int histcmd(int, char **);
+int inputrc(int, char **);
+int fgcmd(int, char **);
+int getoptscmd(int, char **);
+int hashcmd(int, char **);
+int jobidcmd(int, char **);
+int jobscmd(int, char **);
+int localcmd(int, char **);
+#ifndef SMALL
+int printfcmd(int, char **);
+#endif
+int pwdcmd(int, char **);
+int readcmd(int, char **);
+int returncmd(int, char **);
+int setcmd(int, char **);
+int setvarcmd(int, char **);
+int shiftcmd(int, char **);
+int timescmd(int, char **);
+int trapcmd(int, char **);
+int truecmd(int, char **);
+int typecmd(int, char **);
+int umaskcmd(int, char **);
+int unaliascmd(int, char **);
+int unsetcmd(int, char **);
+int waitcmd(int, char **);
+int aliascmd(int, char **);
+int ulimitcmd(int, char **);
+int testcmd(int, char **);
+int killcmd(int, char **);
+int wordexpcmd(int, char **);
Index: /tags/kBuild-0.1.4/src/ash/generated/init.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/init.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/init.c	(revision 1780)
@@ -0,0 +1,314 @@
+/*
+ * This file was generated by the mkinit program.
+ */
+
+#include "shell.h"
+#include "mystring.h"
+#include "init.h"
+#include "eval.h"
+#include <stdio.h>
+#include "input.h"
+#include "error.h"
+#include <stdlib.h>
+#include "options.h"
+#include "output.h"
+#include "memalloc.h"
+#include "redir.h"
+#include <signal.h>
+#include "trap.h"
+#include "var.h"
+
+
+
+#undef  ATABSIZE
+#define ATABSIZE 39
+#undef  MAXPWD
+#define MAXPWD 256
+#undef  ALL
+#define ALL (E_OPEN|E_CREAT|E_EXEC)
+#undef  EV_EXIT
+#define EV_EXIT 01		/* exit after evaluating tree */
+#undef  EV_TESTED
+#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
+#undef  EV_BACKCMD
+#define EV_BACKCMD 04		/* command executing within back quotes */
+#undef  CMDTABLESIZE
+#define CMDTABLESIZE 31		/* should be prime */
+#undef  ARB
+#define ARB 1			/* actual size determined at run time */
+#undef  NEWARGS
+#define NEWARGS 5
+#undef  MAXHISTLOOPS
+#define MAXHISTLOOPS	4	/* max recursions through fc */
+#undef  DEFEDITOR
+#define DEFEDITOR	"ed"	/* default editor *should* be $EDITOR */
+#undef  editing
+#define editing (Eflag || Vflag)
+#undef  EOF_NLEFT
+#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
+#undef  MAXMBOXES
+#define MAXMBOXES 10
+#undef  PROFILE
+#define PROFILE 0
+#undef  SIGSSIZE
+#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
+#undef  MINSIZE
+#define MINSIZE 504		/* minimum size of a block */
+#undef  DEFINE_OPTIONS
+#define DEFINE_OPTIONS
+#undef  OUTBUFSIZ
+#define OUTBUFSIZ BUFSIZ
+#undef  BLOCK_OUT
+#define BLOCK_OUT -2		/* output to a fixed block of memory */
+#undef  MEM_OUT
+#define MEM_OUT -3		/* output to dynamically allocated memory */
+#undef  OUTPUT_ERR
+#define OUTPUT_ERR 01		/* error occurred on output */
+#undef  TEMPSIZE
+#define TEMPSIZE 24
+#undef  HAVE_VASPRINTF
+#define HAVE_VASPRINTF 1
+#undef  EOFMARKLEN
+#define EOFMARKLEN 79
+#undef  OPENBRACE
+#define OPENBRACE '{'
+#undef  CLOSEBRACE
+#define CLOSEBRACE '}'
+#undef  EMPTY
+#define EMPTY -2		/* marks an unused slot in redirtab */
+#undef  S_DFL
+#define S_DFL 1			/* default signal handling (SIG_DFL) */
+#undef  S_CATCH
+#define S_CATCH 2		/* signal is caught */
+#undef  S_IGN
+#define S_IGN 3			/* signal is ignored (SIG_IGN) */
+#undef  S_HARD_IGN
+#define S_HARD_IGN 4		/* signal is ignored permenantly */
+#undef  S_RESET
+#define S_RESET 5		/* temporary - to reset a hard ignored sig */
+#undef  INCL_BASE
+#define INCL_BASE
+#undef  LIBPATHSTRICT
+#define LIBPATHSTRICT 3
+#undef  QHINF_EXEINFO
+#define QHINF_EXEINFO       1 /* NE exeinfo. */
+#undef  QHINF_READRSRCTBL
+#define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
+#undef  QHINF_READFILE
+#define QHINF_READFILE      3 /* Reads from the executable file. */
+#undef  QHINF_LIBPATHLENGTH
+#define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
+#undef  QHINF_LIBPATH
+#define QHINF_LIBPATH       5 /* Gets the entire libpath. */
+#undef  QHINF_FIXENTRY
+#define QHINF_FIXENTRY      6 /* NE only */
+#undef  QHINF_STE
+#define QHINF_STE           7 /* NE only */
+#undef  QHINF_MAPSEL
+#define QHINF_MAPSEL        8 /* NE only */
+#undef  VTABSIZE
+#define VTABSIZE 39
+#undef  VTABSIZE
+#define VTABSIZE 517
+#undef  main
+#define main echocmd
+#undef  main
+#define main killcmd
+
+
+
+extern void rmaliases(void);
+
+extern int loopnest;		/* current loop nesting level */
+
+extern void deletefuncs(void);
+extern void hash_special_builtins(void);
+
+struct strpush {
+	struct strpush *prev;	/* preceding string on stack */
+	char *prevstring;
+	int prevnleft;
+	int prevlleft;
+	struct alias *ap;	/* if push was associated with an alias */
+};
+
+struct parsefile {
+	struct parsefile *prev;	/* preceding file on stack */
+	int linno;		/* current line */
+	int fd;			/* file descriptor (or -1 if string) */
+	int nleft;		/* number of chars left in this line */
+	int lleft;		/* number of chars left in this buffer */
+	char *nextc;		/* next char in buffer */
+	char *buf;		/* input buffer */
+	struct strpush *strpush; /* for pushing strings at this level */
+	struct strpush basestrpush; /* so pushing one is fast */
+};
+
+extern int parselleft;		/* copy of parsefile->lleft */
+extern struct parsefile basepf;	/* top level input file */
+extern char basebuf[BUFSIZ];	/* buffer for top level input file */
+
+extern pid_t backgndpid;	/* pid of last background process */
+extern int jobctl;
+
+extern int tokpushback;		/* last token pushed back */
+extern int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
+
+struct redirtab {
+	struct redirtab *next;
+	short renamed[10];
+};
+
+extern struct redirtab *redirlist;
+
+extern char sigmode[NSIG];	/* current value of signal */
+
+extern char **environ;
+
+
+
+/*
+ * Initialization code.
+ */
+
+void
+init() {
+
+      /* from exec.c: */
+      {
+	      hash_special_builtins();
+      }
+
+      /* from input.c: */
+      {
+	      basepf.nextc = basepf.buf = basebuf;
+      }
+
+      /* from var.c: */
+      {
+	      char **envp;
+
+	      initvar();
+	      for (envp = environ ; *envp ; envp++) {
+		      if (strchr(*envp, '=')) {
+			      setvareq(*envp, VEXPORT|VTEXTFIXED);
+		      }
+	      }
+      }
+}
+
+
+
+/*
+ * This routine is called when an error or an interrupt occurs in an
+ * interactive shell and control is returned to the main command loop.
+ */
+
+void
+reset() {
+
+      /* from eval.c: */
+      {
+	      evalskip = 0;
+	      loopnest = 0;
+	      funcnest = 0;
+      }
+
+      /* from input.c: */
+      {
+	      if (exception != EXSHELLPROC)
+		      parselleft = parsenleft = 0;	/* clear input buffer */
+	      popallfiles();
+      }
+
+      /* from output.c: */
+      {
+	      out1 = &output;
+	      out2 = &errout;
+	      if (memout.buf != NULL) {
+		      ckfree(memout.buf);
+		      memout.buf = NULL;
+	      }
+      }
+
+      /* from parser.c: */
+      {
+	      tokpushback = 0;
+	      checkkwd = 0;
+      }
+
+      /* from redir.c: */
+      {
+	      while (redirlist)
+		      popredir();
+      }
+}
+
+
+
+/*
+ * This routine is called to initialize the shell to run a shell procedure.
+ */
+
+void
+initshellproc() {
+
+      /* from alias.c: */
+      {
+	      rmaliases();
+      }
+
+      /* from eval.c: */
+      {
+	      exitstatus = 0;
+      }
+
+      /* from exec.c: */
+      {
+	      deletefuncs();
+      }
+
+      /* from input.c: */
+      {
+	      popallfiles();
+      }
+
+      /* from jobs.c: */
+      {
+	      backgndpid = -1;
+#if JOBS
+	      jobctl = 0;
+#endif
+      }
+
+      /* from options.c: */
+      {
+	      int i;
+
+	      for (i = 0; optlist[i].name; i++)
+		      optlist[i].val = 0;
+	      optschanged();
+
+      }
+
+      /* from redir.c: */
+      {
+	      clearredir(0);
+      }
+
+      /* from trap.c: */
+      {
+	      char *sm;
+
+	      clear_traps(0);
+	      for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
+		      if (*sm == S_IGN)
+			      *sm = S_HARD_IGN;
+	      }
+      }
+
+      /* from var.c: */
+      {
+	      shprocvar();
+      }
+}
Index: /tags/kBuild-0.1.4/src/ash/generated/nodes.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/nodes.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/nodes.c	(revision 1780)
@@ -0,0 +1,347 @@
+/*
+ * This file was generated by mknodes.sh
+ */
+
+/*	$NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
+ */
+
+#include <stdlib.h>
+/*
+ * Routine for dealing with parsed shell commands.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "memalloc.h"
+#include "machdep.h"
+#include "mystring.h"
+
+
+int     funcblocksize;		/* size of structures in function */
+int     funcstringsize;		/* size of strings in node */
+pointer funcblock;		/* block to allocate function from */
+char   *funcstring;		/* block to allocate strings from */
+
+static const short nodesize[26] = {
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct ncmd)),
+      SHELL_ALIGN(sizeof (struct npipe)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nif)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nfor)),
+      SHELL_ALIGN(sizeof (struct ncase)),
+      SHELL_ALIGN(sizeof (struct nclist)),
+      SHELL_ALIGN(sizeof (struct narg)),
+      SHELL_ALIGN(sizeof (struct narg)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct ndup)),
+      SHELL_ALIGN(sizeof (struct ndup)),
+      SHELL_ALIGN(sizeof (struct nhere)),
+      SHELL_ALIGN(sizeof (struct nhere)),
+      SHELL_ALIGN(sizeof (struct nnot)),
+};
+
+
+STATIC void calcsize(union node *);
+STATIC void sizenodelist(struct nodelist *);
+STATIC union node *copynode(union node *);
+STATIC struct nodelist *copynodelist(struct nodelist *);
+STATIC char *nodesavestr(char *);
+
+
+
+/*
+ * Make a copy of a parse tree.
+ */
+
+union node *
+copyfunc(n)
+	union node *n;
+{
+	if (n == NULL)
+		return NULL;
+	funcblocksize = 0;
+	funcstringsize = 0;
+	calcsize(n);
+	funcblock = ckmalloc(funcblocksize + funcstringsize);
+	funcstring = (char *) funcblock + funcblocksize;
+	return copynode(n);
+}
+
+
+
+STATIC void
+calcsize(n)
+	union node *n;
+{
+      if (n == NULL)
+	    return;
+      funcblocksize += nodesize[n->type];
+      switch (n->type) {
+      case NSEMI:
+      case NAND:
+      case NOR:
+      case NWHILE:
+      case NUNTIL:
+	    calcsize(n->nbinary.ch2);
+	    calcsize(n->nbinary.ch1);
+	    break;
+      case NCMD:
+	    calcsize(n->ncmd.redirect);
+	    calcsize(n->ncmd.args);
+	    break;
+      case NPIPE:
+	    sizenodelist(n->npipe.cmdlist);
+	    break;
+      case NREDIR:
+      case NBACKGND:
+      case NSUBSHELL:
+	    calcsize(n->nredir.redirect);
+	    calcsize(n->nredir.n);
+	    break;
+      case NIF:
+	    calcsize(n->nif.elsepart);
+	    calcsize(n->nif.ifpart);
+	    calcsize(n->nif.test);
+	    break;
+      case NFOR:
+	    funcstringsize += strlen(n->nfor.var) + 1;
+	    calcsize(n->nfor.body);
+	    calcsize(n->nfor.args);
+	    break;
+      case NCASE:
+	    calcsize(n->ncase.cases);
+	    calcsize(n->ncase.expr);
+	    break;
+      case NCLIST:
+	    calcsize(n->nclist.body);
+	    calcsize(n->nclist.pattern);
+	    calcsize(n->nclist.next);
+	    break;
+      case NDEFUN:
+      case NARG:
+	    sizenodelist(n->narg.backquote);
+	    funcstringsize += strlen(n->narg.text) + 1;
+	    calcsize(n->narg.next);
+	    break;
+      case NTO:
+      case NCLOBBER:
+      case NFROM:
+      case NFROMTO:
+      case NAPPEND:
+	    calcsize(n->nfile.fname);
+	    calcsize(n->nfile.next);
+	    break;
+      case NTOFD:
+      case NFROMFD:
+	    calcsize(n->ndup.vname);
+	    calcsize(n->ndup.next);
+	    break;
+      case NHERE:
+      case NXHERE:
+	    calcsize(n->nhere.doc);
+	    calcsize(n->nhere.next);
+	    break;
+      case NNOT:
+	    calcsize(n->nnot.com);
+	    break;
+      };
+}
+
+
+
+STATIC void
+sizenodelist(lp)
+	struct nodelist *lp;
+{
+	while (lp) {
+		funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
+		calcsize(lp->n);
+		lp = lp->next;
+	}
+}
+
+
+
+STATIC union node *
+copynode(n)
+	union node *n;
+{
+	union node *new;
+
+      if (n == NULL)
+	    return NULL;
+      new = funcblock;
+      funcblock = (char *) funcblock + nodesize[n->type];
+      switch (n->type) {
+      case NSEMI:
+      case NAND:
+      case NOR:
+      case NWHILE:
+      case NUNTIL:
+	    new->nbinary.ch2 = copynode(n->nbinary.ch2);
+	    new->nbinary.ch1 = copynode(n->nbinary.ch1);
+	    break;
+      case NCMD:
+	    new->ncmd.redirect = copynode(n->ncmd.redirect);
+	    new->ncmd.args = copynode(n->ncmd.args);
+	    new->ncmd.backgnd = n->ncmd.backgnd;
+	    break;
+      case NPIPE:
+	    new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
+	    new->npipe.backgnd = n->npipe.backgnd;
+	    break;
+      case NREDIR:
+      case NBACKGND:
+      case NSUBSHELL:
+	    new->nredir.redirect = copynode(n->nredir.redirect);
+	    new->nredir.n = copynode(n->nredir.n);
+	    break;
+      case NIF:
+	    new->nif.elsepart = copynode(n->nif.elsepart);
+	    new->nif.ifpart = copynode(n->nif.ifpart);
+	    new->nif.test = copynode(n->nif.test);
+	    break;
+      case NFOR:
+	    new->nfor.var = nodesavestr(n->nfor.var);
+	    new->nfor.body = copynode(n->nfor.body);
+	    new->nfor.args = copynode(n->nfor.args);
+	    break;
+      case NCASE:
+	    new->ncase.cases = copynode(n->ncase.cases);
+	    new->ncase.expr = copynode(n->ncase.expr);
+	    break;
+      case NCLIST:
+	    new->nclist.body = copynode(n->nclist.body);
+	    new->nclist.pattern = copynode(n->nclist.pattern);
+	    new->nclist.next = copynode(n->nclist.next);
+	    break;
+      case NDEFUN:
+      case NARG:
+	    new->narg.backquote = copynodelist(n->narg.backquote);
+	    new->narg.text = nodesavestr(n->narg.text);
+	    new->narg.next = copynode(n->narg.next);
+	    break;
+      case NTO:
+      case NCLOBBER:
+      case NFROM:
+      case NFROMTO:
+      case NAPPEND:
+	    new->nfile.fname = copynode(n->nfile.fname);
+	    new->nfile.fd = n->nfile.fd;
+	    new->nfile.next = copynode(n->nfile.next);
+	    break;
+      case NTOFD:
+      case NFROMFD:
+	    new->ndup.vname = copynode(n->ndup.vname);
+	    new->ndup.dupfd = n->ndup.dupfd;
+	    new->ndup.fd = n->ndup.fd;
+	    new->ndup.next = copynode(n->ndup.next);
+	    break;
+      case NHERE:
+      case NXHERE:
+	    new->nhere.doc = copynode(n->nhere.doc);
+	    new->nhere.fd = n->nhere.fd;
+	    new->nhere.next = copynode(n->nhere.next);
+	    break;
+      case NNOT:
+	    new->nnot.com = copynode(n->nnot.com);
+	    break;
+      };
+      new->type = n->type;
+	return new;
+}
+
+
+STATIC struct nodelist *
+copynodelist(lp)
+	struct nodelist *lp;
+{
+	struct nodelist *start;
+	struct nodelist **lpp;
+
+	lpp = &start;
+	while (lp) {
+		*lpp = funcblock;
+		funcblock = (char *) funcblock +
+		    SHELL_ALIGN(sizeof(struct nodelist));
+		(*lpp)->n = copynode(lp->n);
+		lp = lp->next;
+		lpp = &(*lpp)->next;
+	}
+	*lpp = NULL;
+	return start;
+}
+
+
+
+STATIC char *
+nodesavestr(s)
+	char   *s;
+{
+	register char *p = s;
+	register char *q = funcstring;
+	char   *rtn = funcstring;
+
+	while ((*q++ = *p++) != 0)
+		continue;
+	funcstring = q;
+	return rtn;
+}
+
+
+
+/*
+ * Free a parse tree.
+ */
+
+void
+freefunc(n)
+	union node *n;
+{
+	if (n)
+		ckfree(n);
+}
Index: /tags/kBuild-0.1.4/src/ash/generated/nodes.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/nodes.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/nodes.h	(revision 1780)
@@ -0,0 +1,159 @@
+/*
+ * This file was generated by mknodes.sh
+ */
+
+#define NSEMI 0
+#define NCMD 1
+#define NPIPE 2
+#define NREDIR 3
+#define NBACKGND 4
+#define NSUBSHELL 5
+#define NAND 6
+#define NOR 7
+#define NIF 8
+#define NWHILE 9
+#define NUNTIL 10
+#define NFOR 11
+#define NCASE 12
+#define NCLIST 13
+#define NDEFUN 14
+#define NARG 15
+#define NTO 16
+#define NCLOBBER 17
+#define NFROM 18
+#define NFROMTO 19
+#define NAPPEND 20
+#define NTOFD 21
+#define NFROMFD 22
+#define NHERE 23
+#define NXHERE 24
+#define NNOT 25
+
+
+
+struct nbinary {
+      int type;
+      union node *ch1;
+      union node *ch2;
+};
+
+
+struct ncmd {
+      int type;
+      int backgnd;
+      union node *args;
+      union node *redirect;
+};
+
+
+struct npipe {
+      int type;
+      int backgnd;
+      struct nodelist *cmdlist;
+};
+
+
+struct nredir {
+      int type;
+      union node *n;
+      union node *redirect;
+};
+
+
+struct nif {
+      int type;
+      union node *test;
+      union node *ifpart;
+      union node *elsepart;
+};
+
+
+struct nfor {
+      int type;
+      union node *args;
+      union node *body;
+      char *var;
+};
+
+
+struct ncase {
+      int type;
+      union node *expr;
+      union node *cases;
+};
+
+
+struct nclist {
+      int type;
+      union node *next;
+      union node *pattern;
+      union node *body;
+};
+
+
+struct narg {
+      int type;
+      union node *next;
+      char *text;
+      struct nodelist *backquote;
+};
+
+
+struct nfile {
+      int type;
+      union node *next;
+      int fd;
+      union node *fname;
+      char *expfname;
+};
+
+
+struct ndup {
+      int type;
+      union node *next;
+      int fd;
+      int dupfd;
+      union node *vname;
+};
+
+
+struct nhere {
+      int type;
+      union node *next;
+      int fd;
+      union node *doc;
+};
+
+
+struct nnot {
+      int type;
+      union node *com;
+};
+
+
+union node {
+      int type;
+      struct nbinary nbinary;
+      struct ncmd ncmd;
+      struct npipe npipe;
+      struct nredir nredir;
+      struct nif nif;
+      struct nfor nfor;
+      struct ncase ncase;
+      struct nclist nclist;
+      struct narg narg;
+      struct nfile nfile;
+      struct ndup ndup;
+      struct nhere nhere;
+      struct nnot nnot;
+};
+
+
+struct nodelist {
+	struct nodelist *next;
+	union node *n;
+};
+
+
+union node *copyfunc(union node *);
+void freefunc(union node *);
Index: /tags/kBuild-0.1.4/src/ash/generated/token.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/generated/token.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/generated/token.h	(revision 1780)
@@ -0,0 +1,112 @@
+#define TEOF 0
+#define TNL 1
+#define TSEMI 2
+#define TBACKGND 3
+#define TAND 4
+#define TOR 5
+#define TPIPE 6
+#define TLP 7
+#define TRP 8
+#define TENDCASE 9
+#define TENDBQUOTE 10
+#define TREDIR 11
+#define TWORD 12
+#define TIF 13
+#define TTHEN 14
+#define TELSE 15
+#define TELIF 16
+#define TFI 17
+#define TWHILE 18
+#define TUNTIL 19
+#define TFOR 20
+#define TDO 21
+#define TDONE 22
+#define TBEGIN 23
+#define TEND 24
+#define TCASE 25
+#define TESAC 26
+#define TNOT 27
+
+/* Array indicating which tokens mark the end of a list */
+const char tokendlist[] = {
+	1,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	1,
+	1,
+	1,
+	0,
+	0,
+	0,
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	0,
+	1,
+	1,
+	0,
+	1,
+	0,
+	1,
+	0,
+};
+
+const char *const tokname[] = {
+	"end of file",
+	"newline",
+	"\";\"",
+	"\"&\"",
+	"\"&&\"",
+	"\"||\"",
+	"\"|\"",
+	"\"(\"",
+	"\")\"",
+	"\";;\"",
+	"\"`\"",
+	"redirection",
+	"word",
+	"\"if\"",
+	"\"then\"",
+	"\"else\"",
+	"\"elif\"",
+	"\"fi\"",
+	"\"while\"",
+	"\"until\"",
+	"\"for\"",
+	"\"do\"",
+	"\"done\"",
+	"\"{\"",
+	"\"}\"",
+	"\"case\"",
+	"\"esac\"",
+	"\"!\"",
+};
+
+#define KWDOFFSET 13
+
+const char *const parsekwd[] = {
+	"if",
+	"then",
+	"else",
+	"elif",
+	"fi",
+	"while",
+	"until",
+	"for",
+	"do",
+	"done",
+	"{",
+	"}",
+	"case",
+	"esac",
+	"!",
+	0
+};
Index: /tags/kBuild-0.1.4/src/ash/histedit.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/histedit.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/histedit.c	(revision 1780)
@@ -0,0 +1,550 @@
+/*	$NetBSD: histedit.c,v 1.36 2005/05/09 11:35:19 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)histedit.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: histedit.c,v 1.36 2005/05/09 11:35:19 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#ifndef __sun__
+#include <paths.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+/*
+ * Editline and history functions (and glue).
+ */
+#include "shell.h"
+#include "parser.h"
+#include "var.h"
+#include "options.h"
+#include "main.h"
+#include "output.h"
+#include "mystring.h"
+#include "myhistedit.h"
+#include "error.h"
+#ifndef SMALL
+#include "eval.h"
+#include "memalloc.h"
+
+#define MAXHISTLOOPS	4	/* max recursions through fc */
+#define DEFEDITOR	"ed"	/* default editor *should* be $EDITOR */
+
+History *hist;	/* history cookie */
+EditLine *el;	/* editline cookie */
+int displayhist;
+static FILE *el_in, *el_out;
+unsigned char _el_fn_complete(EditLine *, int);
+
+STATIC const char *fc_replace(const char *, char *, char *);
+
+#ifdef DEBUG
+extern FILE *tracefile;
+#endif
+
+/*
+ * Set history and editing status.  Called whenever the status may
+ * have changed (figures out what to do).
+ */
+void
+histedit(void)
+{
+	FILE *el_err;
+
+#define editing (Eflag || Vflag)
+
+	if (iflag) {
+		if (!hist) {
+			/*
+			 * turn history on
+			 */
+			INTOFF;
+			hist = history_init();
+			INTON;
+
+			if (hist != NULL)
+				sethistsize(histsizeval());
+			else
+				out2str("sh: can't initialize history\n");
+		}
+		if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
+			/*
+			 * turn editing on
+			 */
+			char *term, *shname;
+
+			INTOFF;
+			if (el_in == NULL)
+				el_in = fdopen(0, "r");
+			if (el_out == NULL)
+				el_out = fdopen(2, "w");
+			if (el_in == NULL || el_out == NULL)
+				goto bad;
+			el_err = el_out;
+#if DEBUG
+			if (tracefile)
+				el_err = tracefile;
+#endif
+			term = lookupvar("TERM");
+			if (term)
+				setenv("TERM", term, 1);
+			else
+				unsetenv("TERM");
+			shname = arg0;
+			if (shname[0] == '-')
+				shname++;
+			el = el_init(shname, el_in, el_out, el_err);
+			if (el != NULL) {
+				if (hist)
+					el_set(el, EL_HIST, history, hist);
+				el_set(el, EL_PROMPT, getprompt);
+				el_set(el, EL_SIGNAL, 1);
+				el_set(el, EL_ADDFN, "rl-complete",
+				    "ReadLine compatible completion function",
+				    _el_fn_complete);
+			} else {
+bad:
+				out2str("sh: can't initialize editing\n");
+			}
+			INTON;
+		} else if (!editing && el) {
+			INTOFF;
+			el_end(el);
+			el = NULL;
+			INTON;
+		}
+		if (el) {
+			if (Vflag)
+				el_set(el, EL_EDITOR, "vi");
+			else if (Eflag)
+				el_set(el, EL_EDITOR, "emacs");
+			el_set(el, EL_BIND, "^I",
+			    tabcomplete ? "rl-complete" : "ed-insert", NULL);
+			el_source(el, NULL);
+		}
+	} else {
+		INTOFF;
+		if (el) {	/* no editing if not interactive */
+			el_end(el);
+			el = NULL;
+		}
+		if (hist) {
+			history_end(hist);
+			hist = NULL;
+		}
+		INTON;
+	}
+}
+
+
+void
+sethistsize(const char *hs)
+{
+	int histsize;
+	HistEvent he;
+
+	if (hist != NULL) {
+		if (hs == NULL || *hs == '\0' ||
+		   (histsize = atoi(hs)) < 0)
+			histsize = 100;
+		history(hist, &he, H_SETSIZE, histsize);
+	}
+}
+
+void
+setterm(const char *term)
+{
+	if (el != NULL && term != NULL)
+		if (el_set(el, EL_TERMINAL, term) != 0) {
+			outfmt(out2, "sh: Can't set terminal type %s\n", term);
+			outfmt(out2, "sh: Using dumb terminal settings.\n");
+		}
+}
+
+int
+inputrc(argc, argv)
+	int argc;
+	char **argv;
+{
+	if (argc != 2) {
+		out2str("usage: inputrc file\n");
+		return 1;
+	}
+	if (el != NULL) {
+		if (el_source(el, argv[1])) {
+			out2str("inputrc: failed\n");
+			return 1;
+		} else
+			return 0;
+	} else {
+		out2str("sh: inputrc ignored, not editing\n");
+		return 1;
+	}
+}
+
+/*
+ *  This command is provided since POSIX decided to standardize
+ *  the Korn shell fc command.  Oh well...
+ */
+int
+histcmd(int argc, char **argv)
+{
+	int ch;
+	const char *editor = NULL;
+	HistEvent he;
+	int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
+	int i, retval;
+	const char *firststr, *laststr;
+	int first, last, direction;
+	char *pat = NULL, *repl;	/* ksh "fc old=new" crap */
+	static int active = 0;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	char editfile[MAXPATHLEN + 1];
+	FILE *efp;
+#ifdef __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &editor;
+	(void) &lflg;
+	(void) &nflg;
+	(void) &rflg;
+	(void) &sflg;
+	(void) &firststr;
+	(void) &laststr;
+	(void) &pat;
+	(void) &repl;
+	(void) &efp;
+	(void) &argc;
+	(void) &argv;
+#endif
+
+	if (hist == NULL)
+		error("history not active");
+
+	if (argc == 1)
+		error("missing history argument");
+
+	optreset = 1; optind = 1; /* initialize getopt */
+	while (not_fcnumber(argv[optind]) &&
+	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
+		switch ((char)ch) {
+		case 'e':
+			editor = optionarg;
+			break;
+		case 'l':
+			lflg = 1;
+			break;
+		case 'n':
+			nflg = 1;
+			break;
+		case 'r':
+			rflg = 1;
+			break;
+		case 's':
+			sflg = 1;
+			break;
+		case ':':
+			error("option -%c expects argument", optopt);
+			/* NOTREACHED */
+		case '?':
+		default:
+			error("unknown option: -%c", optopt);
+			/* NOTREACHED */
+		}
+	argc -= optind, argv += optind;
+
+	/*
+	 * If executing...
+	 */
+	if (lflg == 0 || editor || sflg) {
+		lflg = 0;	/* ignore */
+		editfile[0] = '\0';
+		/*
+		 * Catch interrupts to reset active counter and
+		 * cleanup temp files.
+		 */
+		if (setjmp(jmploc.loc)) {
+			active = 0;
+			if (*editfile)
+				unlink(editfile);
+			handler = savehandler;
+			longjmp(handler->loc, 1);
+		}
+		savehandler = handler;
+		handler = &jmploc;
+		if (++active > MAXHISTLOOPS) {
+			active = 0;
+			displayhist = 0;
+			error("called recursively too many times");
+		}
+		/*
+		 * Set editor.
+		 */
+		if (sflg == 0) {
+			if (editor == NULL &&
+			    (editor = bltinlookup("FCEDIT", 1)) == NULL &&
+			    (editor = bltinlookup("EDITOR", 1)) == NULL)
+				editor = DEFEDITOR;
+			if (editor[0] == '-' && editor[1] == '\0') {
+				sflg = 1;	/* no edit */
+				editor = NULL;
+			}
+		}
+	}
+
+	/*
+	 * If executing, parse [old=new] now
+	 */
+	if (lflg == 0 && argc > 0 &&
+	     ((repl = strchr(argv[0], '=')) != NULL)) {
+		pat = argv[0];
+		*repl++ = '\0';
+		argc--, argv++;
+	}
+	/*
+	 * determine [first] and [last]
+	 */
+	switch (argc) {
+	case 0:
+		firststr = lflg ? "-16" : "-1";
+		laststr = "-1";
+		break;
+	case 1:
+		firststr = argv[0];
+		laststr = lflg ? "-1" : argv[0];
+		break;
+	case 2:
+		firststr = argv[0];
+		laststr = argv[1];
+		break;
+	default:
+		error("too many args");
+		/* NOTREACHED */
+	}
+	/*
+	 * Turn into event numbers.
+	 */
+	first = str_to_event(firststr, 0);
+	last = str_to_event(laststr, 1);
+
+	if (rflg) {
+		i = last;
+		last = first;
+		first = i;
+	}
+	/*
+	 * XXX - this should not depend on the event numbers
+	 * always increasing.  Add sequence numbers or offset
+	 * to the history element in next (diskbased) release.
+	 */
+	direction = first < last ? H_PREV : H_NEXT;
+
+	/*
+	 * If editing, grab a temp file.
+	 */
+	if (editor) {
+		int fd;
+		INTOFF;		/* easier */
+		snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP);
+		if ((fd = mkstemp(editfile)) < 0)
+			error("can't create temporary file %s", editfile);
+		if ((efp = fdopen(fd, "w")) == NULL) {
+			close(fd);
+			error("can't allocate stdio buffer for temp");
+		}
+	}
+
+	/*
+	 * Loop through selected history events.  If listing or executing,
+	 * do it now.  Otherwise, put into temp file and call the editor
+	 * after.
+	 *
+	 * The history interface needs rethinking, as the following
+	 * convolutions will demonstrate.
+	 */
+	history(hist, &he, H_FIRST);
+	retval = history(hist, &he, H_NEXT_EVENT, first);
+	for (;retval != -1; retval = history(hist, &he, direction)) {
+		if (lflg) {
+			if (!nflg)
+				out1fmt("%5d ", he.num);
+			out1str(he.str);
+		} else {
+			const char *s = pat ?
+			   fc_replace(he.str, pat, repl) : he.str;
+
+			if (sflg) {
+				if (displayhist) {
+					out2str(s);
+				}
+
+				evalstring(strcpy(stalloc(strlen(s) + 1), s), 0);
+				if (displayhist && hist) {
+					/*
+					 *  XXX what about recursive and
+					 *  relative histnums.
+					 */
+					history(hist, &he, H_ENTER, s);
+				}
+			} else
+				fputs(s, efp);
+		}
+		/*
+		 * At end?  (if we were to lose last, we'd sure be
+		 * messed up).
+		 */
+		if (he.num == last)
+			break;
+	}
+	if (editor) {
+		char *editcmd;
+
+		fclose(efp);
+		editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
+		sprintf(editcmd, "%s %s", editor, editfile);
+		evalstring(editcmd, 0);	/* XXX - should use no JC command */
+		INTON;
+		readcmdfile(editfile);	/* XXX - should read back - quick tst */
+		unlink(editfile);
+	}
+
+	if (lflg == 0 && active > 0)
+		--active;
+	if (displayhist)
+		displayhist = 0;
+	return 0;
+}
+
+STATIC const char *
+fc_replace(const char *s, char *p, char *r)
+{
+	char *dest;
+	int plen = strlen(p);
+
+	STARTSTACKSTR(dest);
+	while (*s) {
+		if (*s == *p && strncmp(s, p, plen) == 0) {
+			while (*r)
+				STPUTC(*r++, dest);
+			s += plen;
+			*p = '\0';	/* so no more matches */
+		} else
+			STPUTC(*s++, dest);
+	}
+	STACKSTRNUL(dest);
+	dest = grabstackstr(dest);
+
+	return (dest);
+}
+
+int
+not_fcnumber(char *s)
+{
+	if (s == NULL)
+		return 0;
+        if (*s == '-')
+                s++;
+	return (!is_number(s));
+}
+
+int
+str_to_event(const char *str, int last)
+{
+	HistEvent he;
+	const char *s = str;
+	int relative = 0;
+	int i, retval;
+
+	retval = history(hist, &he, H_FIRST);
+	switch (*s) {
+	case '-':
+		relative = 1;
+		/*FALLTHROUGH*/
+	case '+':
+		s++;
+	}
+	if (is_number(s)) {
+		i = atoi(s);
+		if (relative) {
+			while (retval != -1 && i--) {
+				retval = history(hist, &he, H_NEXT);
+			}
+			if (retval == -1)
+				retval = history(hist, &he, H_LAST);
+		} else {
+			retval = history(hist, &he, H_NEXT_EVENT, i);
+			if (retval == -1) {
+				/*
+				 * the notion of first and last is
+				 * backwards to that of the history package
+				 */
+				retval = history(hist, &he,
+						last ? H_FIRST : H_LAST);
+			}
+		}
+		if (retval == -1)
+			error("history number %s not found (internal error)",
+			       str);
+	} else {
+		/*
+		 * pattern
+		 */
+		retval = history(hist, &he, H_PREV_STR, str);
+		if (retval == -1)
+			error("history pattern not found: %s", str);
+	}
+	return (he.num);
+}
+#else
+int
+histcmd(int argc, char **argv)
+{
+	error("not compiled with history support");
+	/* NOTREACHED */
+}
+int
+inputrc(int argc, char **argv)
+{
+	error("not compiled with history support");
+	/* NOTREACHED */
+}
+#endif
Index: /tags/kBuild-0.1.4/src/ash/init.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/init.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/init.h	(revision 1780)
@@ -0,0 +1,39 @@
+/*	$NetBSD: init.h,v 1.10 2003/08/07 09:05:32 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)init.h	8.2 (Berkeley) 5/4/95
+ */
+
+void init(void);
+void reset(void);
+void initshellproc(void);
Index: /tags/kBuild-0.1.4/src/ash/input.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/input.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/input.c	(revision 1780)
@@ -0,0 +1,536 @@
+/*	$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
+#else
+__RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>	/* defines BUFSIZ */
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __sun__
+#include <iso/limits_iso.h>
+#endif
+
+/*
+ * This file implements the input routines used by the parser.
+ */
+
+#include "shell.h"
+#include "redir.h"
+#include "syntax.h"
+#include "input.h"
+#include "output.h"
+#include "options.h"
+#include "memalloc.h"
+#include "error.h"
+#include "alias.h"
+#include "parser.h"
+#include "myhistedit.h"
+
+#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
+
+MKINIT
+struct strpush {
+	struct strpush *prev;	/* preceding string on stack */
+	char *prevstring;
+	int prevnleft;
+	int prevlleft;
+	struct alias *ap;	/* if push was associated with an alias */
+};
+
+/*
+ * The parsefile structure pointed to by the global variable parsefile
+ * contains information about the current file being read.
+ */
+
+MKINIT
+struct parsefile {
+	struct parsefile *prev;	/* preceding file on stack */
+	int linno;		/* current line */
+	int fd;			/* file descriptor (or -1 if string) */
+	int nleft;		/* number of chars left in this line */
+	int lleft;		/* number of chars left in this buffer */
+	char *nextc;		/* next char in buffer */
+	char *buf;		/* input buffer */
+	struct strpush *strpush; /* for pushing strings at this level */
+	struct strpush basestrpush; /* so pushing one is fast */
+};
+
+
+int plinno = 1;			/* input line number */
+int parsenleft;			/* copy of parsefile->nleft */
+MKINIT int parselleft;		/* copy of parsefile->lleft */
+char *parsenextc;		/* copy of parsefile->nextc */
+MKINIT struct parsefile basepf;	/* top level input file */
+MKINIT char basebuf[BUFSIZ];	/* buffer for top level input file */
+struct parsefile *parsefile = &basepf;	/* current input file */
+int init_editline = 0;		/* editline library initialized? */
+int whichprompt;		/* 1 == PS1, 2 == PS2 */
+
+#ifndef SMALL
+EditLine *el;			/* cookie for editline package */
+#endif
+
+STATIC void pushfile(void);
+static int preadfd(void);
+
+#ifdef mkinit
+INCLUDE <stdio.h>
+INCLUDE "input.h"
+INCLUDE "error.h"
+
+INIT {
+	basepf.nextc = basepf.buf = basebuf;
+}
+
+RESET {
+	if (exception != EXSHELLPROC)
+		parselleft = parsenleft = 0;	/* clear input buffer */
+	popallfiles();
+}
+
+SHELLPROC {
+	popallfiles();
+}
+#endif
+
+
+/*
+ * Read a line from the script.
+ */
+
+char *
+pfgets(char *line, int len)
+{
+	char *p = line;
+	int nleft = len;
+	int c;
+
+	while (--nleft > 0) {
+		c = pgetc_macro();
+		if (c == PEOF) {
+			if (p == line)
+				return NULL;
+			break;
+		}
+		*p++ = c;
+		if (c == '\n')
+			break;
+	}
+	*p = '\0';
+	return line;
+}
+
+
+
+/*
+ * Read a character from the script, returning PEOF on end of file.
+ * Nul characters in the input are silently discarded.
+ */
+
+int
+pgetc(void)
+{
+	return pgetc_macro();
+}
+
+
+static int
+preadfd(void)
+{
+	int nr;
+	char *buf =  parsefile->buf;
+	parsenextc = buf;
+
+retry:
+#ifndef SMALL
+	if (parsefile->fd == 0 && el) {
+		static const char *rl_cp;
+		static int el_len;
+
+		if (rl_cp == NULL)
+			rl_cp = el_gets(el, &el_len);
+		if (rl_cp == NULL)
+			nr = 0;
+		else {
+			nr = el_len;
+			if (nr > BUFSIZ - 8)
+				nr = BUFSIZ - 8;
+			memcpy(buf, rl_cp, nr);
+			if (nr != el_len) {
+				el_len -= nr;
+				rl_cp += nr;
+			} else
+				rl_cp = 0;
+		}
+
+	} else
+#endif
+		nr = read(parsefile->fd, buf, BUFSIZ - 8);
+
+
+	if (nr <= 0) {
+                if (nr < 0) {
+                        if (errno == EINTR)
+                                goto retry;
+                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
+                                int flags = fcntl(0, F_GETFL, 0);
+                                if (flags >= 0 && flags & O_NONBLOCK) {
+                                        flags &=~ O_NONBLOCK;
+                                        if (fcntl(0, F_SETFL, flags) >= 0) {
+						out2str("sh: turning off NDELAY mode\n");
+                                                goto retry;
+                                        }
+                                }
+                        }
+                }
+                nr = -1;
+	}
+	return nr;
+}
+
+/*
+ * Refill the input buffer and return the next input character:
+ *
+ * 1) If a string was pushed back on the input, pop it;
+ * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
+ *    from a string so we can't refill the buffer, return EOF.
+ * 3) If the is more stuff in this buffer, use it else call read to fill it.
+ * 4) Process input up to the next newline, deleting nul characters.
+ */
+
+int
+preadbuffer(void)
+{
+	char *p, *q;
+	int more;
+	int something;
+	char savec;
+
+	if (parsefile->strpush) {
+		popstring();
+		if (--parsenleft >= 0)
+			return (*parsenextc++);
+	}
+	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
+		return PEOF;
+	flushout(&output);
+	flushout(&errout);
+
+again:
+	if (parselleft <= 0) {
+		if ((parselleft = preadfd()) == -1) {
+			parselleft = parsenleft = EOF_NLEFT;
+			return PEOF;
+		}
+	}
+
+	q = p = parsenextc;
+
+	/* delete nul characters */
+	something = 0;
+	for (more = 1; more;) {
+		switch (*p) {
+		case '\0':
+			p++;	/* Skip nul */
+			goto check;
+
+		case '\t':
+		case ' ':
+			break;
+
+		case '\n':
+			parsenleft = q - parsenextc;
+			more = 0; /* Stop processing here */
+			break;
+
+		default:
+			something = 1;
+			break;
+		}
+
+		*q++ = *p++;
+check:
+		if (--parselleft <= 0) {
+			parsenleft = q - parsenextc - 1;
+			if (parsenleft < 0)
+				goto again;
+			*q = '\0';
+			more = 0;
+		}
+	}
+
+	savec = *q;
+	*q = '\0';
+
+#ifndef SMALL
+	if (parsefile->fd == 0 && hist && something) {
+		HistEvent he;
+		INTOFF;
+		history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
+		    parsenextc);
+		INTON;
+	}
+#endif
+
+	if (vflag) {
+		out2str(parsenextc);
+		flushout(out2);
+	}
+
+	*q = savec;
+
+	return *parsenextc++;
+}
+
+/*
+ * Undo the last call to pgetc.  Only one character may be pushed back.
+ * PEOF may be pushed back.
+ */
+
+void
+pungetc(void)
+{
+	parsenleft++;
+	parsenextc--;
+}
+
+/*
+ * Push a string back onto the input at this current parsefile level.
+ * We handle aliases this way.
+ */
+void
+pushstring(char *s, int len, void *ap)
+{
+	struct strpush *sp;
+
+	INTOFF;
+/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
+	if (parsefile->strpush) {
+		sp = ckmalloc(sizeof (struct strpush));
+		sp->prev = parsefile->strpush;
+		parsefile->strpush = sp;
+	} else
+		sp = parsefile->strpush = &(parsefile->basestrpush);
+	sp->prevstring = parsenextc;
+	sp->prevnleft = parsenleft;
+	sp->prevlleft = parselleft;
+	sp->ap = (struct alias *)ap;
+	if (ap)
+		((struct alias *)ap)->flag |= ALIASINUSE;
+	parsenextc = s;
+	parsenleft = len;
+	INTON;
+}
+
+void
+popstring(void)
+{
+	struct strpush *sp = parsefile->strpush;
+
+	INTOFF;
+	parsenextc = sp->prevstring;
+	parsenleft = sp->prevnleft;
+	parselleft = sp->prevlleft;
+/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
+	if (sp->ap)
+		sp->ap->flag &= ~ALIASINUSE;
+	parsefile->strpush = sp->prev;
+	if (sp != &(parsefile->basestrpush))
+		ckfree(sp);
+	INTON;
+}
+
+/*
+ * Set the input to take input from a file.  If push is set, push the
+ * old input onto the stack first.
+ */
+
+void
+setinputfile(const char *fname, int push)
+{
+	int fd;
+	int fd2;
+
+	INTOFF;
+	if ((fd = open(fname, O_RDONLY)) < 0)
+		error("Can't open %s", fname);
+	if (fd < 10) {
+		fd2 = copyfd(fd, 10);
+		close(fd);
+		if (fd2 < 0)
+			error("Out of file descriptors");
+		fd = fd2;
+	}
+	setinputfd(fd, push);
+	INTON;
+}
+
+
+/*
+ * Like setinputfile, but takes an open file descriptor.  Call this with
+ * interrupts off.
+ */
+
+void
+setinputfd(int fd, int push)
+{
+	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+	if (push) {
+		pushfile();
+		parsefile->buf = ckmalloc(BUFSIZ);
+	}
+	if (parsefile->fd > 0)
+		close(parsefile->fd);
+	parsefile->fd = fd;
+	if (parsefile->buf == NULL)
+		parsefile->buf = ckmalloc(BUFSIZ);
+	parselleft = parsenleft = 0;
+	plinno = 1;
+}
+
+
+/*
+ * Like setinputfile, but takes input from a string.
+ */
+
+void
+setinputstring(char *string, int push)
+{
+	INTOFF;
+	if (push)
+		pushfile();
+	parsenextc = string;
+	parselleft = parsenleft = strlen(string);
+	parsefile->buf = NULL;
+	plinno = 1;
+	INTON;
+}
+
+
+
+/*
+ * To handle the "." command, a stack of input files is used.  Pushfile
+ * adds a new entry to the stack and popfile restores the previous level.
+ */
+
+STATIC void
+pushfile(void)
+{
+	struct parsefile *pf;
+
+	parsefile->nleft = parsenleft;
+	parsefile->lleft = parselleft;
+	parsefile->nextc = parsenextc;
+	parsefile->linno = plinno;
+	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
+	pf->prev = parsefile;
+	pf->fd = -1;
+	pf->strpush = NULL;
+	pf->basestrpush.prev = NULL;
+	parsefile = pf;
+}
+
+
+void
+popfile(void)
+{
+	struct parsefile *pf = parsefile;
+
+	INTOFF;
+	if (pf->fd >= 0)
+		close(pf->fd);
+	if (pf->buf)
+		ckfree(pf->buf);
+	while (pf->strpush)
+		popstring();
+	parsefile = pf->prev;
+	ckfree(pf);
+	parsenleft = parsefile->nleft;
+	parselleft = parsefile->lleft;
+	parsenextc = parsefile->nextc;
+	plinno = parsefile->linno;
+	INTON;
+}
+
+
+/*
+ * Return to top level.
+ */
+
+void
+popallfiles(void)
+{
+	while (parsefile != &basepf)
+		popfile();
+}
+
+
+
+/*
+ * Close the file(s) that the shell is reading commands from.  Called
+ * after a fork is done.
+ *
+ * Takes one arg, vfork, which tells it to not modify its global vars
+ * as it is still running in the parent.
+ *
+ * This code is (probably) unnecessary as the 'close on exec' flag is
+ * set and should be enough.  In the vfork case it is definitely wrong
+ * to close the fds as another fork() may be done later to feed data
+ * from a 'here' document into a pipe and we don't want to close the
+ * pipe!
+ */
+
+void
+closescript(int vforked)
+{
+	if (vforked)
+		return;
+	popallfiles();
+	if (parsefile->fd > 0) {
+		close(parsefile->fd);
+		parsefile->fd = 0;
+	}
+}
Index: /tags/kBuild-0.1.4/src/ash/input.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/input.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/input.h	(revision 1780)
@@ -0,0 +1,62 @@
+/*	$NetBSD: input.h,v 1.15 2003/08/07 09:05:33 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)input.h	8.2 (Berkeley) 5/4/95
+ */
+
+/* PEOF (the end of file marker) is defined in syntax.h */
+
+/*
+ * The input line number.  Input.c just defines this variable, and saves
+ * and restores it when files are pushed and popped.  The user of this
+ * package must set its value.
+ */
+extern int plinno;
+extern int parsenleft;		/* number of characters left in input buffer */
+extern char *parsenextc;	/* next character in input buffer */
+extern int init_editline;	/* 0 == not setup, 1 == OK, -1 == failed */
+
+char *pfgets(char *, int);
+int pgetc(void);
+int preadbuffer(void);
+void pungetc(void);
+void pushstring(char *, int, void *);
+void popstring(void);
+void setinputfile(const char *, int);
+void setinputfd(int, int);
+void setinputstring(char *, int);
+void popfile(void);
+void popallfiles(void);
+void closescript(int);
+
+#define pgetc_macro()	(--parsenleft >= 0? *parsenextc++ : preadbuffer())
Index: /tags/kBuild-0.1.4/src/ash/jobs.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/jobs.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/jobs.c	(revision 1780)
@@ -0,0 +1,1484 @@
+/*	$NetBSD: jobs.c,v 1.63 2005/06/01 15:41:19 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#else
+#define _PATH_DEVNULL "/dev/null"
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: jobs.c,v 1.63 2005/06/01 15:41:19 lukem Exp $");
+#endif
+#endif /* not lint */
+
+#include <fcntl.h>
+#ifdef __sun__
+#define sys_siglist _sys_siglist
+#endif
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifndef __sun__
+#include <paths.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#if defined(BSD) || defined(__sun__)
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+#include <sys/ioctl.h>
+
+#include "shell.h"
+#if JOBS
+#if OLD_TTY_DRIVER
+#include "sgtty.h"
+#else
+#include <termios.h>
+#endif
+#undef CEOF			/* syntax.h redefines this */
+#endif
+#include "redir.h"
+#include "show.h"
+#include "main.h"
+#include "parser.h"
+#include "nodes.h"
+#include "jobs.h"
+#include "options.h"
+#include "trap.h"
+#include "syntax.h"
+#include "input.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+
+
+static struct job *jobtab;		/* array of jobs */
+static int njobs;			/* size of array */
+static int jobs_invalid;		/* set in child */
+MKINIT pid_t backgndpid = -1;	/* pid of last background process */
+#if JOBS
+int initialpgrp;		/* pgrp of shell on invocation */
+static int curjob = -1;		/* current job */
+#endif
+static int ttyfd = -1;
+
+STATIC void restartjob(struct job *);
+STATIC void freejob(struct job *);
+STATIC struct job *getjob(const char *, int);
+STATIC int dowait(int, struct job *);
+STATIC int onsigchild(void);
+STATIC int waitproc(int, struct job *, int *);
+STATIC void cmdtxt(union node *);
+STATIC void cmdlist(union node *, int);
+STATIC void cmdputs(const char *);
+
+#ifdef OLD_TTY_DRIVER
+static pid_t tcgetpgrp(int fd);
+static int tcsetpgrp(int fd, pid_t pgrp);
+
+static pid_t
+tcgetpgrp(int fd)
+{
+	pid_t pgrp;
+	if (ioctl(fd, TIOCGPGRP, (char *)&pgrp) == -1)
+		return -1;
+	else
+		return pgrp;
+}
+
+static int
+tcsetpgrp(int fd, pid_tpgrp)
+{
+	return ioctl(fd, TIOCSPGRP, (char *)&pgrp);
+}
+#endif
+
+/*
+ * Turn job control on and off.
+ *
+ * Note:  This code assumes that the third arg to ioctl is a character
+ * pointer, which is true on Berkeley systems but not System V.  Since
+ * System V doesn't have job control yet, this isn't a problem now.
+ */
+
+MKINIT int jobctl;
+
+void
+setjobctl(int on)
+{
+#ifdef OLD_TTY_DRIVER
+	int ldisc;
+#endif
+
+	if (on == jobctl || rootshell == 0)
+		return;
+	if (on) {
+#if defined(FIOCLEX) || defined(FD_CLOEXEC)
+		int err;
+		int i;
+		if (ttyfd != -1)
+			close(ttyfd);
+		if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) {
+			for (i = 0; i < 3; i++) {
+				if (isatty(i) && (ttyfd = dup(i)) != -1)
+					break;
+			}
+			if (i == 3)
+				goto out;
+		}
+		/* Move to a high fd */
+		for (i = 10; i > 2; i--) {
+			if ((err = fcntl(ttyfd, F_DUPFD, (1 << i) - 1)) != -1)
+				break;
+		}
+		if (err != -1) {
+			close(ttyfd);
+			ttyfd = err;
+		}
+#ifdef FIOCLEX
+		err = ioctl(ttyfd, FIOCLEX, 0);
+#elif FD_CLOEXEC
+		err = fcntl(ttyfd, F_SETFD,
+		    fcntl(ttyfd, F_GETFD, 0) | FD_CLOEXEC);
+#endif
+		if (err == -1) {
+			close(ttyfd);
+			ttyfd = -1;
+			goto out;
+		}
+#else
+		out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control");
+		goto out;
+#endif
+		do { /* while we are in the background */
+			if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) {
+out:
+				out2str("sh: can't access tty; job control turned off\n");
+				mflag = 0;
+				return;
+			}
+			if (initialpgrp == -1)
+				initialpgrp = getpgrp();
+			else if (initialpgrp != getpgrp()) {
+				killpg(0, SIGTTIN);
+				continue;
+			}
+		} while (0);
+
+#ifdef OLD_TTY_DRIVER
+		if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0
+		    || ldisc != NTTYDISC) {
+			out2str("sh: need new tty driver to run job control; job control turned off\n");
+			mflag = 0;
+			return;
+		}
+#endif
+		setsignal(SIGTSTP, 0);
+		setsignal(SIGTTOU, 0);
+		setsignal(SIGTTIN, 0);
+		if (getpgid(0) != rootpid && setpgid(0, rootpid) == -1)
+			error("Cannot set process group (%s) at %d",
+			    strerror(errno), __LINE__);
+		if (tcsetpgrp(ttyfd, rootpid) == -1)
+			error("Cannot set tty process group (%s) at %d",
+			    strerror(errno), __LINE__);
+	} else { /* turning job control off */
+		if (getpgid(0) != initialpgrp && setpgid(0, initialpgrp) == -1)
+			error("Cannot set process group (%s) at %d",
+			    strerror(errno), __LINE__);
+		if (tcsetpgrp(ttyfd, initialpgrp) == -1)
+			error("Cannot set tty process group (%s) at %d",
+			    strerror(errno), __LINE__);
+		close(ttyfd);
+		ttyfd = -1;
+		setsignal(SIGTSTP, 0);
+		setsignal(SIGTTOU, 0);
+		setsignal(SIGTTIN, 0);
+	}
+	jobctl = on;
+}
+
+
+#ifdef mkinit
+INCLUDE <stdlib.h>
+
+SHELLPROC {
+	backgndpid = -1;
+#if JOBS
+	jobctl = 0;
+#endif
+}
+
+#endif
+
+
+
+#if JOBS
+int
+fgcmd(int argc, char **argv)
+{
+	struct job *jp;
+	int i;
+	int status;
+
+	nextopt("");
+	jp = getjob(*argptr, 0);
+	if (jp->jobctl == 0)
+		error("job not created under job control");
+	out1fmt("%s", jp->ps[0].cmd);
+	for (i = 1; i < jp->nprocs; i++)
+		out1fmt(" | %s", jp->ps[i].cmd );
+	out1c('\n');
+	output_flushall();
+
+	for (i = 0; i < jp->nprocs; i++)
+	    if (tcsetpgrp(ttyfd, jp->ps[i].pid) != -1)
+		    break;
+
+	if (i >= jp->nprocs) {
+		error("Cannot set tty process group (%s) at %d",
+		    strerror(errno), __LINE__);
+	}
+	restartjob(jp);
+	INTOFF;
+	status = waitforjob(jp);
+	INTON;
+	return status;
+}
+
+static void
+set_curjob(struct job *jp, int mode)
+{
+	struct job *jp1, *jp2;
+	int i, ji;
+
+	ji = jp - jobtab;
+
+	/* first remove from list */
+	if (ji == curjob)
+		curjob = jp->prev_job;
+	else {
+		for (i = 0; i < njobs; i++) {
+			if (jobtab[i].prev_job != ji)
+				continue;
+			jobtab[i].prev_job = jp->prev_job;
+			break;
+		}
+	}
+
+	/* Then re-insert in correct position */
+	switch (mode) {
+	case 0:	/* job being deleted */
+		jp->prev_job = -1;
+		break;
+	case 1:	/* newly created job or backgrounded job,
+		   put after all stopped jobs. */
+		if (curjob != -1 && jobtab[curjob].state == JOBSTOPPED) {
+			for (jp1 = jobtab + curjob; ; jp1 = jp2) {
+				if (jp1->prev_job == -1)
+					break;
+				jp2 = jobtab + jp1->prev_job;
+				if (jp2->state != JOBSTOPPED)
+					break;
+			}
+			jp->prev_job = jp1->prev_job;
+			jp1->prev_job = ji;
+			break;
+		}
+		/* FALLTHROUGH */
+	case 2:	/* newly stopped job - becomes curjob */
+		jp->prev_job = curjob;
+		curjob = ji;
+		break;
+	}
+}
+
+int
+bgcmd(int argc, char **argv)
+{
+	struct job *jp;
+	int i;
+
+	nextopt("");
+	do {
+		jp = getjob(*argptr, 0);
+		if (jp->jobctl == 0)
+			error("job not created under job control");
+		set_curjob(jp, 1);
+		out1fmt("[%ld] %s", (long)(jp - jobtab + 1), jp->ps[0].cmd);
+		for (i = 1; i < jp->nprocs; i++)
+			out1fmt(" | %s", jp->ps[i].cmd );
+		out1c('\n');
+		output_flushall();
+		restartjob(jp);
+	} while (*argptr && *++argptr);
+	return 0;
+}
+
+
+STATIC void
+restartjob(struct job *jp)
+{
+	struct procstat *ps;
+	int i;
+
+	if (jp->state == JOBDONE)
+		return;
+	INTOFF;
+	for (i = 0; i < jp->nprocs; i++)
+		if (killpg(jp->ps[i].pid, SIGCONT) != -1)
+			break;
+	if (i >= jp->nprocs)
+		error("Cannot continue job (%s)", strerror(errno));
+	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
+		if (WIFSTOPPED(ps->status)) {
+			ps->status = -1;
+			jp->state = JOBRUNNING;
+		}
+	}
+	INTON;
+}
+#endif
+
+static void
+showjob(struct output *out, struct job *jp, int mode)
+{
+	int procno;
+	int st;
+	struct procstat *ps;
+	int col;
+	char s[64];
+
+#if JOBS
+	if (mode & SHOW_PGID) {
+		/* just output process (group) id of pipeline */
+		outfmt(out, "%ld\n", (long)jp->ps->pid);
+		return;
+	}
+#endif
+
+	procno = jp->nprocs;
+	if (!procno)
+		return;
+
+	if (mode & SHOW_PID)
+		mode |= SHOW_MULTILINE;
+
+	if ((procno > 1 && !(mode & SHOW_MULTILINE))
+	    || (mode & SHOW_SIGNALLED)) {
+		/* See if we have more than one status to report */
+		ps = jp->ps;
+		st = ps->status;
+		do {
+			int st1 = ps->status;
+			if (st1 != st)
+				/* yes - need multi-line output */
+				mode |= SHOW_MULTILINE;
+			if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1))
+				continue;
+			if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f)
+			    && st1 != SIGINT && st1 != SIGPIPE))
+				mode |= SHOW_ISSIG;
+
+		} while (ps++, --procno);
+		procno = jp->nprocs;
+	}
+
+	if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) {
+		if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) {
+			TRACE(("showjob: freeing job %d\n", jp - jobtab + 1));
+			freejob(jp);
+		}
+		return;
+	}
+
+	for (ps = jp->ps; --procno >= 0; ps++) {	/* for each process */
+		if (ps == jp->ps)
+			fmtstr(s, 16, "[%ld] %c ",
+				(long)(jp - jobtab + 1),
+#if JOBS
+				jp == jobtab + curjob ? '+' :
+				curjob != -1 && jp == jobtab +
+					    jobtab[curjob].prev_job ? '-' :
+#endif
+				' ');
+		else
+			fmtstr(s, 16, "      " );
+		col = strlen(s);
+		if (mode & SHOW_PID) {
+			fmtstr(s + col, 16, "%ld ", (long)ps->pid);
+			     col += strlen(s + col);
+		}
+		if (ps->status == -1) {
+			scopy("Running", s + col);
+		} else if (WIFEXITED(ps->status)) {
+			st = WEXITSTATUS(ps->status);
+			if (st)
+				fmtstr(s + col, 16, "Done(%d)", st);
+			else
+				fmtstr(s + col, 16, "Done");
+		} else {
+#if JOBS
+			if (WIFSTOPPED(ps->status))
+				st = WSTOPSIG(ps->status);
+			else /* WIFSIGNALED(ps->status) */
+#endif
+				st = WTERMSIG(ps->status);
+			st &= 0x7f;
+			if (st < NSIG && sys_siglist[st])
+				scopyn(sys_siglist[st], s + col, 32);
+			else
+				fmtstr(s + col, 16, "Signal %d", st);
+			if (WCOREDUMP(ps->status)) {
+				col += strlen(s + col);
+				scopyn(" (core dumped)", s + col,  64 - col);
+			}
+		}
+		col += strlen(s + col);
+		outstr(s, out);
+		do {
+			outc(' ', out);
+			col++;
+		} while (col < 30);
+		outstr(ps->cmd, out);
+		if (mode & SHOW_MULTILINE) {
+			if (procno > 0) {
+				outc(' ', out);
+				outc('|', out);
+			}
+		} else {
+			while (--procno >= 0)
+				outfmt(out, " | %s", (++ps)->cmd );
+		}
+		outc('\n', out);
+	}
+	flushout(out);
+	jp->changed = 0;
+	if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE))
+		freejob(jp);
+}
+
+
+int
+jobscmd(int argc, char **argv)
+{
+	int mode, m;
+	int sv = jobs_invalid;
+
+	jobs_invalid = 0;
+	mode = 0;
+	while ((m = nextopt("lp")))
+		if (m == 'l')
+			mode = SHOW_PID;
+		else
+			mode = SHOW_PGID;
+	if (*argptr)
+		do
+			showjob(out1, getjob(*argptr,0), mode);
+		while (*++argptr);
+	else
+		showjobs(out1, mode);
+	jobs_invalid = sv;
+	return 0;
+}
+
+
+/*
+ * Print a list of jobs.  If "change" is nonzero, only print jobs whose
+ * statuses have changed since the last call to showjobs.
+ *
+ * If the shell is interrupted in the process of creating a job, the
+ * result may be a job structure containing zero processes.  Such structures
+ * will be freed here.
+ */
+
+void
+showjobs(struct output *out, int mode)
+{
+	int jobno;
+	struct job *jp;
+	int silent = 0, gotpid;
+
+	TRACE(("showjobs(%x) called\n", mode));
+
+	/* If not even one one job changed, there is nothing to do */
+	gotpid = dowait(0, NULL);
+	while (dowait(0, NULL) > 0)
+		continue;
+#ifdef JOBS
+	/*
+	 * Check if we are not in our foreground group, and if not
+	 * put us in it.
+	 */
+	if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) {
+		if (tcsetpgrp(ttyfd, getpid()) == -1)
+			error("Cannot set tty process group (%s) at %d",
+			    strerror(errno), __LINE__);
+		TRACE(("repaired tty process group\n"));
+		silent = 1;
+	}
+#endif
+	if (jobs_invalid)
+		return;
+
+	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
+		if (!jp->used)
+			continue;
+		if (jp->nprocs == 0) {
+			freejob(jp);
+			continue;
+		}
+		if ((mode & SHOW_CHANGED) && !jp->changed)
+			continue;
+		if (silent && jp->changed) {
+			jp->changed = 0;
+			continue;
+		}
+		showjob(out, jp, mode);
+	}
+}
+
+/*
+ * Mark a job structure as unused.
+ */
+
+STATIC void
+freejob(struct job *jp)
+{
+	INTOFF;
+	if (jp->ps != &jp->ps0) {
+		ckfree(jp->ps);
+		jp->ps = &jp->ps0;
+	}
+	jp->nprocs = 0;
+	jp->used = 0;
+#if JOBS
+	set_curjob(jp, 0);
+#endif
+	INTON;
+}
+
+
+
+int
+waitcmd(int argc, char **argv)
+{
+	struct job *job;
+	int status, retval;
+	struct job *jp;
+
+	nextopt("");
+
+	if (!*argptr) {
+		/* wait for all jobs */
+		jp = jobtab;
+		if (jobs_invalid)
+			return 0;
+		for (;;) {
+			if (jp >= jobtab + njobs) {
+				/* no running procs */
+				return 0;
+			}
+			if (!jp->used || jp->state != JOBRUNNING) {
+				jp++;
+				continue;
+			}
+			if (dowait(1, (struct job *)NULL) == -1)
+			       return 128 + SIGINT;
+			jp = jobtab;
+		}
+	}
+
+	retval = 127;		/* XXXGCC: -Wuninitialized */
+	for (; *argptr; argptr++) {
+		job = getjob(*argptr, 1);
+		if (!job) {
+			retval = 127;
+			continue;
+		}
+		/* loop until process terminated or stopped */
+		while (job->state == JOBRUNNING) {
+			if (dowait(1, (struct job *)NULL) == -1)
+			       return 128 + SIGINT;
+		}
+		status = job->ps[job->nprocs].status;
+		if (WIFEXITED(status))
+			retval = WEXITSTATUS(status);
+#if JOBS
+		else if (WIFSTOPPED(status))
+			retval = WSTOPSIG(status) + 128;
+#endif
+		else {
+			/* XXX: limits number of signals */
+			retval = WTERMSIG(status) + 128;
+		}
+		if (!iflag)
+			freejob(job);
+	}
+	return retval;
+}
+
+
+
+int
+jobidcmd(int argc, char **argv)
+{
+	struct job *jp;
+	int i;
+
+	nextopt("");
+	jp = getjob(*argptr, 0);
+	for (i = 0 ; i < jp->nprocs ; ) {
+		out1fmt("%ld", (long)jp->ps[i].pid);
+		out1c(++i < jp->nprocs ? ' ' : '\n');
+	}
+	return 0;
+}
+
+int
+getjobpgrp(const char *name)
+{
+	struct job *jp;
+
+	jp = getjob(name, 1);
+	if (jp == 0)
+		return 0;
+	return -jp->ps[0].pid;
+}
+
+/*
+ * Convert a job name to a job structure.
+ */
+
+STATIC struct job *
+getjob(const char *name, int noerror)
+{
+	int jobno = -1;
+	struct job *jp;
+	int pid;
+	int i;
+	const char *err_msg = "No such job: %s";
+
+	if (name == NULL) {
+#if JOBS
+		jobno = curjob;
+#endif
+		err_msg = "No current job";
+	} else if (name[0] == '%') {
+		if (is_number(name + 1)) {
+			jobno = number(name + 1) - 1;
+		} else if (!name[2]) {
+			switch (name[1]) {
+#if JOBS
+			case 0:
+			case '+':
+			case '%':
+				jobno = curjob;
+				err_msg = "No current job";
+				break;
+			case '-':
+				jobno = curjob;
+				if (jobno != -1)
+					jobno = jobtab[jobno].prev_job;
+				err_msg = "No previous job";
+				break;
+#endif
+			default:
+				goto check_pattern;
+			}
+		} else {
+			struct job *found;
+    check_pattern:
+			found = NULL;
+			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
+				if (!jp->used || jp->nprocs <= 0)
+					continue;
+				if ((name[1] == '?'
+					&& strstr(jp->ps[0].cmd, name + 2))
+				    || prefix(name + 1, jp->ps[0].cmd)) {
+					if (found) {
+						err_msg = "%s: ambiguous";
+						found = 0;
+						break;
+					}
+					found = jp;
+				}
+			}
+			if (found)
+				return found;
+		}
+
+	} else if (is_number(name)) {
+		pid = number(name);
+		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
+			if (jp->used && jp->nprocs > 0
+			 && jp->ps[jp->nprocs - 1].pid == pid)
+				return jp;
+		}
+	}
+
+	if (!jobs_invalid && jobno >= 0 && jobno < njobs) {
+		jp = jobtab + jobno;
+		if (jp->used)
+			return jp;
+	}
+	if (!noerror)
+		error(err_msg, name);
+	return 0;
+}
+
+
+
+/*
+ * Return a new job structure,
+ */
+
+struct job *
+makejob(union node *node, int nprocs)
+{
+	int i;
+	struct job *jp;
+
+	if (jobs_invalid) {
+		for (i = njobs, jp = jobtab ; --i >= 0 ; jp++) {
+			if (jp->used)
+				freejob(jp);
+		}
+		jobs_invalid = 0;
+	}
+
+	for (i = njobs, jp = jobtab ; ; jp++) {
+		if (--i < 0) {
+			INTOFF;
+			if (njobs == 0) {
+				jobtab = ckmalloc(4 * sizeof jobtab[0]);
+			} else {
+				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
+				memcpy(jp, jobtab, njobs * sizeof jp[0]);
+				/* Relocate `ps' pointers */
+				for (i = 0; i < njobs; i++)
+					if (jp[i].ps == &jobtab[i].ps0)
+						jp[i].ps = &jp[i].ps0;
+				ckfree(jobtab);
+				jobtab = jp;
+			}
+			jp = jobtab + njobs;
+			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
+			INTON;
+			break;
+		}
+		if (jp->used == 0)
+			break;
+	}
+	INTOFF;
+	jp->state = JOBRUNNING;
+	jp->used = 1;
+	jp->changed = 0;
+	jp->nprocs = 0;
+#if JOBS
+	jp->jobctl = jobctl;
+	set_curjob(jp, 1);
+#endif
+	if (nprocs > 1) {
+		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
+	} else {
+		jp->ps = &jp->ps0;
+	}
+	INTON;
+	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
+	    jp - jobtab + 1));
+	return jp;
+}
+
+
+/*
+ * Fork off a subshell.  If we are doing job control, give the subshell its
+ * own process group.  Jp is a job structure that the job is to be added to.
+ * N is the command that will be evaluated by the child.  Both jp and n may
+ * be NULL.  The mode parameter can be one of the following:
+ *	FORK_FG - Fork off a foreground process.
+ *	FORK_BG - Fork off a background process.
+ *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
+ *		     process group even if job control is on.
+ *
+ * When job control is turned off, background processes have their standard
+ * input redirected to /dev/null (except for the second and later processes
+ * in a pipeline).
+ */
+
+int
+forkshell(struct job *jp, union node *n, int mode)
+{
+	int pid;
+
+	TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, n, mode));
+	switch ((pid = fork())) {
+	case -1:
+		TRACE(("Fork failed, errno=%d\n", errno));
+		INTON;
+		error("Cannot fork");
+		break;
+	case 0:
+		forkchild(jp, n, mode, 0);
+		return 0;
+	default:
+		return forkparent(jp, n, mode, pid);
+	}
+}
+
+int
+forkparent(struct job *jp, union node *n, int mode, pid_t pid)
+{
+	int pgrp;
+
+	if (rootshell && mode != FORK_NOJOB && mflag) {
+		if (jp == NULL || jp->nprocs == 0)
+			pgrp = pid;
+		else
+			pgrp = jp->ps[0].pid;
+		/* This can fail because we are doing it in the child also */
+		(void)setpgid(pid, pgrp);
+	}
+	if (mode == FORK_BG)
+		backgndpid = pid;		/* set $! */
+	if (jp) {
+		struct procstat *ps = &jp->ps[jp->nprocs++];
+		ps->pid = pid;
+		ps->status = -1;
+		ps->cmd[0] = 0;
+		if (/* iflag && rootshell && */ n)
+			commandtext(ps, n);
+	}
+	TRACE(("In parent shell:  child = %d\n", pid));
+	return pid;
+}
+
+void
+forkchild(struct job *jp, union node *n, int mode, int vforked)
+{
+	int wasroot;
+	int pgrp;
+	const char *devnull = _PATH_DEVNULL;
+	const char *nullerr = "Can't open %s";
+
+	wasroot = rootshell;
+	TRACE(("Child shell %d\n", getpid()));
+	if (!vforked)
+		rootshell = 0;
+
+	closescript(vforked);
+	clear_traps(vforked);
+#if JOBS
+	if (!vforked)
+		jobctl = 0;		/* do job control only in root shell */
+	if (wasroot && mode != FORK_NOJOB && mflag) {
+		if (jp == NULL || jp->nprocs == 0)
+			pgrp = getpid();
+		else
+			pgrp = jp->ps[0].pid;
+		/* This can fail because we are doing it in the parent also */
+		(void)setpgid(0, pgrp);
+		if (mode == FORK_FG) {
+			if (tcsetpgrp(ttyfd, pgrp) == -1)
+				error("Cannot set tty process group (%s) at %d",
+				    strerror(errno), __LINE__);
+		}
+		setsignal(SIGTSTP, vforked);
+		setsignal(SIGTTOU, vforked);
+	} else if (mode == FORK_BG) {
+		ignoresig(SIGINT, vforked);
+		ignoresig(SIGQUIT, vforked);
+		if ((jp == NULL || jp->nprocs == 0) &&
+		    ! fd0_redirected_p ()) {
+			close(0);
+			if (open(devnull, O_RDONLY) != 0)
+				error(nullerr, devnull);
+		}
+	}
+#else
+	if (mode == FORK_BG) {
+		ignoresig(SIGINT, vforked);
+		ignoresig(SIGQUIT, vforked);
+		if ((jp == NULL || jp->nprocs == 0) &&
+		    ! fd0_redirected_p ()) {
+			close(0);
+			if (open(devnull, O_RDONLY) != 0)
+				error(nullerr, devnull);
+		}
+	}
+#endif
+	if (wasroot && iflag) {
+		setsignal(SIGINT, vforked);
+		setsignal(SIGQUIT, vforked);
+		setsignal(SIGTERM, vforked);
+	}
+
+	if (!vforked)
+		jobs_invalid = 1;
+}
+
+/*
+ * Wait for job to finish.
+ *
+ * Under job control we have the problem that while a child process is
+ * running interrupts generated by the user are sent to the child but not
+ * to the shell.  This means that an infinite loop started by an inter-
+ * active user may be hard to kill.  With job control turned off, an
+ * interactive user may place an interactive program inside a loop.  If
+ * the interactive program catches interrupts, the user doesn't want
+ * these interrupts to also abort the loop.  The approach we take here
+ * is to have the shell ignore interrupt signals while waiting for a
+ * forground process to terminate, and then send itself an interrupt
+ * signal if the child process was terminated by an interrupt signal.
+ * Unfortunately, some programs want to do a bit of cleanup and then
+ * exit on interrupt; unless these processes terminate themselves by
+ * sending a signal to themselves (instead of calling exit) they will
+ * confuse this approach.
+ */
+
+int
+waitforjob(struct job *jp)
+{
+#if JOBS
+	int mypgrp = getpgrp();
+#endif
+	int status;
+	int st;
+
+	INTOFF;
+	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
+	while (jp->state == JOBRUNNING) {
+		dowait(1, jp);
+	}
+#if JOBS
+	if (jp->jobctl) {
+		if (tcsetpgrp(ttyfd, mypgrp) == -1)
+			error("Cannot set tty process group (%s) at %d",
+			    strerror(errno), __LINE__);
+	}
+	if (jp->state == JOBSTOPPED && curjob != jp - jobtab)
+		set_curjob(jp, 2);
+#endif
+	status = jp->ps[jp->nprocs - 1].status;
+	/* convert to 8 bits */
+	if (WIFEXITED(status))
+		st = WEXITSTATUS(status);
+#if JOBS
+	else if (WIFSTOPPED(status))
+		st = WSTOPSIG(status) + 128;
+#endif
+	else
+		st = WTERMSIG(status) + 128;
+	TRACE(("waitforjob: job %d, nproc %d, status %x, st %x\n",
+		jp - jobtab + 1, jp->nprocs, status, st ));
+#if JOBS
+	if (jp->jobctl) {
+		/*
+		 * This is truly gross.
+		 * If we're doing job control, then we did a TIOCSPGRP which
+		 * caused us (the shell) to no longer be in the controlling
+		 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
+		 * intuit from the subprocess exit status whether a SIGINT
+		 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
+		 */
+		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
+			raise(SIGINT);
+	}
+#endif
+	if (! JOBS || jp->state == JOBDONE)
+		freejob(jp);
+	INTON;
+	return st;
+}
+
+
+
+/*
+ * Wait for a process to terminate.
+ */
+
+STATIC int
+dowait(int block, struct job *job)
+{
+	int pid;
+	int status;
+	struct procstat *sp;
+	struct job *jp;
+	struct job *thisjob;
+	int done;
+	int stopped;
+	extern volatile char gotsig[];
+
+	TRACE(("dowait(%d) called\n", block));
+	do {
+		pid = waitproc(block, job, &status);
+		TRACE(("wait returns pid %d, status %d\n", pid, status));
+	} while (pid == -1 && errno == EINTR && gotsig[SIGINT - 1] == 0);
+	if (pid <= 0)
+		return pid;
+	INTOFF;
+	thisjob = NULL;
+	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
+		if (jp->used) {
+			done = 1;
+			stopped = 1;
+			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
+				if (sp->pid == -1)
+					continue;
+				if (sp->pid == pid) {
+					TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - jobtab + 1, pid, sp->status, status));
+					sp->status = status;
+					thisjob = jp;
+				}
+				if (sp->status == -1)
+					stopped = 0;
+				else if (WIFSTOPPED(sp->status))
+					done = 0;
+			}
+			if (stopped) {		/* stopped or done */
+				int state = done ? JOBDONE : JOBSTOPPED;
+				if (jp->state != state) {
+					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
+					jp->state = state;
+#if JOBS
+					if (done)
+						set_curjob(jp, 0);
+#endif
+				}
+			}
+		}
+	}
+
+	if (thisjob && thisjob->state != JOBRUNNING) {
+		int mode = 0;
+		if (!rootshell || !iflag)
+			mode = SHOW_SIGNALLED;
+		if (job == thisjob)
+			mode = SHOW_SIGNALLED | SHOW_NO_FREE;
+		if (mode)
+			showjob(out2, thisjob, mode);
+		else {
+			TRACE(("Not printing status, rootshell=%d, job=%p\n",
+				rootshell, job));
+			thisjob->changed = 1;
+		}
+	}
+
+	INTON;
+	return pid;
+}
+
+
+
+/*
+ * Do a wait system call.  If job control is compiled in, we accept
+ * stopped processes.  If block is zero, we return a value of zero
+ * rather than blocking.
+ *
+ * System V doesn't have a non-blocking wait system call.  It does
+ * have a SIGCLD signal that is sent to a process when one of it's
+ * children dies.  The obvious way to use SIGCLD would be to install
+ * a handler for SIGCLD which simply bumped a counter when a SIGCLD
+ * was received, and have waitproc bump another counter when it got
+ * the status of a process.  Waitproc would then know that a wait
+ * system call would not block if the two counters were different.
+ * This approach doesn't work because if a process has children that
+ * have not been waited for, System V will send it a SIGCLD when it
+ * installs a signal handler for SIGCLD.  What this means is that when
+ * a child exits, the shell will be sent SIGCLD signals continuously
+ * until is runs out of stack space, unless it does a wait call before
+ * restoring the signal handler.  The code below takes advantage of
+ * this (mis)feature by installing a signal handler for SIGCLD and
+ * then checking to see whether it was called.  If there are any
+ * children to be waited for, it will be.
+ *
+ * If neither SYSV nor BSD is defined, we don't implement nonblocking
+ * waits at all.  In this case, the user will not be informed when
+ * a background process until the next time she runs a real program
+ * (as opposed to running a builtin command or just typing return),
+ * and the jobs command may give out of date information.
+ */
+
+#ifdef SYSV
+STATIC int gotsigchild;
+
+STATIC int onsigchild() {
+	gotsigchild = 1;
+}
+#endif
+
+
+STATIC int
+waitproc(int block, struct job *jp, int *status)
+{
+#ifdef BSD
+	int flags = 0;
+
+#if JOBS
+	if (jp != NULL && jp->jobctl)
+		flags |= WUNTRACED;
+#endif
+	if (block == 0)
+		flags |= WNOHANG;
+	return wait3(status, flags, (struct rusage *)NULL);
+#else
+#ifdef SYSV
+	int (*save)();
+
+	if (block == 0) {
+		gotsigchild = 0;
+		save = signal(SIGCLD, onsigchild);
+		signal(SIGCLD, save);
+		if (gotsigchild == 0)
+			return 0;
+	}
+	return wait(status);
+#else
+	if (block == 0)
+		return 0;
+	return wait(status);
+#endif
+#endif
+}
+
+/*
+ * return 1 if there are stopped jobs, otherwise 0
+ */
+int job_warning = 0;
+int
+stoppedjobs(void)
+{
+	int jobno;
+	struct job *jp;
+
+	if (job_warning || jobs_invalid)
+		return (0);
+	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
+		if (jp->used == 0)
+			continue;
+		if (jp->state == JOBSTOPPED) {
+			out2str("You have stopped jobs.\n");
+			job_warning = 2;
+			return (1);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Return a string identifying a command (to be printed by the
+ * jobs command).
+ */
+
+STATIC char *cmdnextc;
+STATIC int cmdnleft;
+
+void
+commandtext(struct procstat *ps, union node *n)
+{
+	int len;
+
+	cmdnextc = ps->cmd;
+	if (iflag || mflag || sizeof ps->cmd < 100)
+		len = sizeof(ps->cmd);
+	else
+		len = sizeof(ps->cmd) / 10;
+	cmdnleft = len;
+	cmdtxt(n);
+	if (cmdnleft <= 0) {
+		char *p = ps->cmd + len - 4;
+		p[0] = '.';
+		p[1] = '.';
+		p[2] = '.';
+		p[3] = 0;
+	} else
+		*cmdnextc = '\0';
+	TRACE(("commandtext: ps->cmd %x, end %x, left %d\n\t\"%s\"\n",
+		ps->cmd, cmdnextc, cmdnleft, ps->cmd));
+}
+
+
+STATIC void
+cmdtxt(union node *n)
+{
+	union node *np;
+	struct nodelist *lp;
+	const char *p;
+	int i;
+	char s[2];
+
+	if (n == NULL || cmdnleft <= 0)
+		return;
+	switch (n->type) {
+	case NSEMI:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs("; ");
+		cmdtxt(n->nbinary.ch2);
+		break;
+	case NAND:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs(" && ");
+		cmdtxt(n->nbinary.ch2);
+		break;
+	case NOR:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs(" || ");
+		cmdtxt(n->nbinary.ch2);
+		break;
+	case NPIPE:
+		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+			cmdtxt(lp->n);
+			if (lp->next)
+				cmdputs(" | ");
+		}
+		break;
+	case NSUBSHELL:
+		cmdputs("(");
+		cmdtxt(n->nredir.n);
+		cmdputs(")");
+		break;
+	case NREDIR:
+	case NBACKGND:
+		cmdtxt(n->nredir.n);
+		break;
+	case NIF:
+		cmdputs("if ");
+		cmdtxt(n->nif.test);
+		cmdputs("; then ");
+		cmdtxt(n->nif.ifpart);
+		if (n->nif.elsepart) {
+			cmdputs("; else ");
+			cmdtxt(n->nif.elsepart);
+		}
+		cmdputs("; fi");
+		break;
+	case NWHILE:
+		cmdputs("while ");
+		goto until;
+	case NUNTIL:
+		cmdputs("until ");
+until:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs("; do ");
+		cmdtxt(n->nbinary.ch2);
+		cmdputs("; done");
+		break;
+	case NFOR:
+		cmdputs("for ");
+		cmdputs(n->nfor.var);
+		cmdputs(" in ");
+		cmdlist(n->nfor.args, 1);
+		cmdputs("; do ");
+		cmdtxt(n->nfor.body);
+		cmdputs("; done");
+		break;
+	case NCASE:
+		cmdputs("case ");
+		cmdputs(n->ncase.expr->narg.text);
+		cmdputs(" in ");
+		for (np = n->ncase.cases; np; np = np->nclist.next) {
+			cmdtxt(np->nclist.pattern);
+			cmdputs(") ");
+			cmdtxt(np->nclist.body);
+			cmdputs(";; ");
+		}
+		cmdputs("esac");
+		break;
+	case NDEFUN:
+		cmdputs(n->narg.text);
+		cmdputs("() { ... }");
+		break;
+	case NCMD:
+		cmdlist(n->ncmd.args, 1);
+		cmdlist(n->ncmd.redirect, 0);
+		break;
+	case NARG:
+		cmdputs(n->narg.text);
+		break;
+	case NTO:
+		p = ">";  i = 1;  goto redir;
+	case NCLOBBER:
+		p = ">|";  i = 1;  goto redir;
+	case NAPPEND:
+		p = ">>";  i = 1;  goto redir;
+	case NTOFD:
+		p = ">&";  i = 1;  goto redir;
+	case NFROM:
+		p = "<";  i = 0;  goto redir;
+	case NFROMFD:
+		p = "<&";  i = 0;  goto redir;
+	case NFROMTO:
+		p = "<>";  i = 0;  goto redir;
+redir:
+		if (n->nfile.fd != i) {
+			s[0] = n->nfile.fd + '0';
+			s[1] = '\0';
+			cmdputs(s);
+		}
+		cmdputs(p);
+		if (n->type == NTOFD || n->type == NFROMFD) {
+			s[0] = n->ndup.dupfd + '0';
+			s[1] = '\0';
+			cmdputs(s);
+		} else {
+			cmdtxt(n->nfile.fname);
+		}
+		break;
+	case NHERE:
+	case NXHERE:
+		cmdputs("<<...");
+		break;
+	default:
+		cmdputs("???");
+		break;
+	}
+}
+
+STATIC void
+cmdlist(union node *np, int sep)
+{
+	for (; np; np = np->narg.next) {
+		if (!sep)
+			cmdputs(" ");
+		cmdtxt(np);
+		if (sep && np->narg.next)
+			cmdputs(" ");
+	}
+}
+
+
+STATIC void
+cmdputs(const char *s)
+{
+	const char *p, *str = 0;
+	char c, cc[2] = " ";
+	char *nextc;
+	int nleft;
+	int subtype = 0;
+	int quoted = 0;
+	static char vstype[16][4] = { "", "}", "-", "+", "?", "=",
+					"#", "##", "%", "%%" };
+
+	p = s;
+	nextc = cmdnextc;
+	nleft = cmdnleft;
+	while (nleft > 0 && (c = *p++) != 0) {
+		switch (c) {
+		case CTLESC:
+			c = *p++;
+			break;
+		case CTLVAR:
+			subtype = *p++;
+			if ((subtype & VSTYPE) == VSLENGTH)
+				str = "${#";
+			else
+				str = "${";
+			if (!(subtype & VSQUOTE) != !(quoted & 1)) {
+				quoted ^= 1;
+				c = '"';
+			} else
+				c = *str++;
+			break;
+		case CTLENDVAR:
+			if (quoted & 1) {
+				c = '"';
+				str = "}";
+			} else
+				c = '}';
+			quoted >>= 1;
+			subtype = 0;
+			break;
+		case CTLBACKQ:
+			c = '$';
+			str = "(...)";
+			break;
+		case CTLBACKQ+CTLQUOTE:
+			c = '"';
+			str = "$(...)\"";
+			break;
+		case CTLARI:
+			c = '$';
+			str = "((";
+			break;
+		case CTLENDARI:
+			c = ')';
+			str = ")";
+			break;
+		case CTLQUOTEMARK:
+			quoted ^= 1;
+			c = '"';
+			break;
+		case '=':
+			if (subtype == 0)
+				break;
+			str = vstype[subtype & VSTYPE];
+			if (subtype & VSNUL)
+				c = ':';
+			else
+				c = *str++;
+			if (c != '}')
+				quoted <<= 1;
+			break;
+		case '\'':
+		case '\\':
+		case '"':
+		case '$':
+			/* These can only happen inside quotes */
+			cc[0] = c;
+			str = cc;
+			c = '\\';
+			break;
+		default:
+			break;
+		}
+		do {
+			*nextc++ = c;
+		} while (--nleft > 0 && str && (c = *str++));
+		str = 0;
+	}
+	if ((quoted & 1) && nleft) {
+		*nextc++ = '"';
+		nleft--;
+	}
+	cmdnleft = nleft;
+	cmdnextc = nextc;
+}
Index: /tags/kBuild-0.1.4/src/ash/jobs.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/jobs.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/jobs.h	(revision 1780)
@@ -0,0 +1,106 @@
+/*	$NetBSD: jobs.h,v 1.19 2003/11/27 21:16:14 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include "output.h"
+
+/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
+#define FORK_FG 0
+#define FORK_BG 1
+#define FORK_NOJOB 2
+
+/* mode flags for showjob(s) */
+#define	SHOW_PGID	0x01	/* only show pgid - for jobs -p */
+#define	SHOW_MULTILINE	0x02	/* one line per process */
+#define	SHOW_PID	0x04	/* include process pid */
+#define	SHOW_CHANGED	0x08	/* only jobs whose state has changed */
+#define	SHOW_SIGNALLED	0x10	/* only if stopped/exited on signal */
+#define	SHOW_ISSIG	0x20	/* job was signalled */
+#define	SHOW_NO_FREE	0x40	/* do not free job */
+
+
+/*
+ * A job structure contains information about a job.  A job is either a
+ * single process or a set of processes contained in a pipeline.  In the
+ * latter case, pidlist will be non-NULL, and will point to a -1 terminated
+ * array of pids.
+ */
+#define	MAXCMDTEXT	200
+
+struct procstat {
+	pid_t	pid;		/* process id */
+ 	int	status;		/* last process status from wait() */
+ 	char	cmd[MAXCMDTEXT];/* text of command being run */
+};
+
+struct job {
+	struct procstat ps0;	/* status of process */
+	struct procstat *ps;	/* status or processes when more than one */
+	int	nprocs;		/* number of processes */
+	pid_t	pgrp;		/* process group of this job */
+	char	state;
+#define	JOBRUNNING	0	/* at least one proc running */
+#define	JOBSTOPPED	1	/* all procs are stopped */
+#define	JOBDONE		2	/* all procs are completed */
+	char	used;		/* true if this entry is in used */
+	char	changed;	/* true if status has changed */
+#if JOBS
+	char 	jobctl;		/* job running under job control */
+	int	prev_job;	/* previous job index */
+#endif
+};
+
+extern pid_t backgndpid;	/* pid of last background process */
+extern int job_warning;		/* user was warned about stopped jobs */
+
+void setjobctl(int);
+int fgcmd(int, char **);
+int bgcmd(int, char **);
+int jobscmd(int, char **);
+void showjobs(struct output *, int);
+int waitcmd(int, char **);
+int jobidcmd(int, char **);
+struct job *makejob(union node *, int);
+int forkshell(struct job *, union node *, int);
+void forkchild(struct job *, union node *, int, int);
+int forkparent(struct job *, union node *, int, pid_t);
+int waitforjob(struct job *);
+int stoppedjobs(void);
+void commandtext(struct procstat *, union node *);
+int getjobpgrp(const char *);
+
+#if ! JOBS
+#define setjobctl(on)	/* do nothing */
+#endif
Index: /tags/kBuild-0.1.4/src/ash/machdep.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/machdep.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/machdep.h	(revision 1780)
@@ -0,0 +1,47 @@
+/*	$NetBSD: machdep.h,v 1.11 2003/08/07 09:05:33 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)machdep.h	8.2 (Berkeley) 5/4/95
+ */
+
+/*
+ * Most machines require the value returned from malloc to be aligned
+ * in some way.  The following macro will get this right on many machines.
+ */
+
+#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
+/*
+ * It appears that grabstackstr() will barf with such alignments
+ * because stalloc() will return a string allocated in a new stackblock.
+ */
+#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
Index: /tags/kBuild-0.1.4/src/ash/mail.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/mail.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/mail.c	(revision 1780)
@@ -0,0 +1,122 @@
+/*	$NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mail.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Routines to check for mail.  (Perhaps make part of main.c?)
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "exec.h"	/* defines padvance() */
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mail.h"
+
+
+#define MAXMBOXES 10
+
+
+STATIC int nmboxes;			/* number of mailboxes */
+STATIC time_t mailtime[MAXMBOXES];	/* times of mailboxes */
+
+
+
+/*
+ * Print appropriate message(s) if mail has arrived.  If the argument is
+ * nozero, then the value of MAIL has changed, so we just update the
+ * values.
+ */
+
+void
+chkmail(int silent)
+{
+	int i;
+	const char *mpath;
+	char *p;
+	char *q;
+	struct stackmark smark;
+	struct stat statb;
+
+	if (silent)
+		nmboxes = 10;
+	if (nmboxes == 0)
+		return;
+	setstackmark(&smark);
+	mpath = mpathset() ? mpathval() : mailval();
+	for (i = 0 ; i < nmboxes ; i++) {
+		p = padvance(&mpath, nullstr);
+		if (p == NULL)
+			break;
+		if (*p == '\0')
+			continue;
+		for (q = p ; *q ; q++);
+		if (q[-1] != '/')
+			abort();
+		q[-1] = '\0';			/* delete trailing '/' */
+#ifdef notdef /* this is what the System V shell claims to do (it lies) */
+		if (stat(p, &statb) < 0)
+			statb.st_mtime = 0;
+		if (statb.st_mtime > mailtime[i] && ! silent) {
+			out2str(pathopt ? pathopt : "you have mail");
+			out2c('\n');
+		}
+		mailtime[i] = statb.st_mtime;
+#else /* this is what it should do */
+		if (stat(p, &statb) < 0)
+			statb.st_size = 0;
+		if (statb.st_size > mailtime[i] && ! silent) {
+			out2str(pathopt ? pathopt : "you have mail");
+			out2c('\n');
+		}
+		mailtime[i] = statb.st_size;
+#endif
+	}
+	nmboxes = i;
+	popstackmark(&smark);
+}
Index: /tags/kBuild-0.1.4/src/ash/mail.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/mail.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/mail.h	(revision 1780)
@@ -0,0 +1,37 @@
+/*	$NetBSD: mail.h,v 1.10 2003/08/07 09:05:34 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)mail.h	8.2 (Berkeley) 5/4/95
+ */
+
+void chkmail(int);
Index: /tags/kBuild-0.1.4/src/ash/main.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/main.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/main.c	(revision 1780)
@@ -0,0 +1,441 @@
+/*	$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)main.c	8.7 (Berkeley) 7/19/95";
+#else
+__RCSID("$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $");
+#endif
+#endif /* not lint */
+
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <locale.h>
+#include <fcntl.h>
+
+
+#include "shell.h"
+#include "main.h"
+#include "mail.h"
+#include "options.h"
+#include "output.h"
+#include "parser.h"
+#include "nodes.h"
+#include "expand.h"
+#include "eval.h"
+#include "jobs.h"
+#include "input.h"
+#include "trap.h"
+#include "var.h"
+#include "show.h"
+#include "memalloc.h"
+#include "error.h"
+#include "init.h"
+#include "mystring.h"
+#include "exec.h"
+#include "cd.h"
+
+#define PROFILE 0
+
+int rootpid;
+int rootshell;
+STATIC union node *curcmd;
+STATIC union node *prevcmd;
+#if PROFILE
+short profile_buf[16384];
+extern int etext();
+#endif
+
+#ifndef KMK
+#error "Huh? KMK isn't defined!"
+STATIC void read_profile(const char *);
+#endif
+STATIC char *find_dot_file(char *);
+int main(int, char **);
+
+/*
+ * Main routine.  We initialize things, parse the arguments, execute
+ * profiles if we're a login shell, and then call cmdloop to execute
+ * commands.  The setjmp call sets up the location to jump to when an
+ * exception occurs.  When an exception occurs the variable "state"
+ * is used to figure out how far we had gotten.
+ */
+
+int
+main(int argc, char **argv)
+{
+	struct jmploc jmploc;
+	struct stackmark smark;
+	volatile int state;
+	char *shinit;
+
+	setlocale(LC_ALL, "");
+
+	/* Just a --version for show. */
+	if (argc > 1
+	 && argv[1][0] == '-'
+	 && argv[1][1] == '-') {
+		if (!strcmp(&argv[1][2], "version")) {
+			printf("kmk_ash - kBuild version %d.%d.%d\n",
+				   KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH);
+			return 0;
+		}
+		if (!strcmp(&argv[1][2], "help")) {
+			printf("usage: kmk_ash [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+				   "               [+o option_name] [command_file [argument ...]]\n"
+				   "   or: kmk_ash -c [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+				   "               [+o option_name] command_string [command_name [argument ...]]\n"
+				   "   or: kmk_ash -s [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+				   "               [+o option_name] [argument ...]\n"
+				   "   or: kmk_ash --help\n"
+				   "   or: kmk_ash --version\n",
+				   argv[0], argv[0], argv[0], argv[0], argv[0]);
+			return 0;
+		}
+	}
+
+#if PROFILE
+	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
+#endif
+	state = 0;
+	if (setjmp(jmploc.loc)) {
+		/*
+		 * When a shell procedure is executed, we raise the
+		 * exception EXSHELLPROC to clean up before executing
+		 * the shell procedure.
+		 */
+		switch (exception) {
+		case EXSHELLPROC:
+			rootpid = getpid();
+			rootshell = 1;
+			minusc = NULL;
+			state = 3;
+			break;
+
+		case EXEXEC:
+			exitstatus = exerrno;
+			break;
+
+		case EXERROR:
+			exitstatus = 2;
+			break;
+
+		default:
+			break;
+		}
+
+		if (exception != EXSHELLPROC) {
+			if (state == 0 || iflag == 0 || ! rootshell)
+				exitshell(exitstatus);
+		}
+		reset();
+		if (exception == EXINT
+#if ATTY
+		 && (! attyset() || equal(termval(), "emacs"))
+#endif
+		 ) {
+			out2c('\n');
+			flushout(&errout);
+		}
+		popstackmark(&smark);
+		FORCEINTON;				/* enable interrupts */
+		if (state == 1)
+			goto state1;
+		else if (state == 2)
+			goto state2;
+		else if (state == 3)
+			goto state3;
+		else
+			goto state4;
+	}
+	handler = &jmploc;
+#ifdef DEBUG
+#if DEBUG == 2
+	debug = 1;
+#endif
+	opentrace();
+	trputs("Shell args:  ");  trargs(argv);
+#endif
+	rootpid = getpid();
+	rootshell = 1;
+#ifdef _MSC_VER
+    {
+        extern void init_syntax(void);
+        init_syntax();
+    }
+#endif
+	init();
+	setstackmark(&smark);
+	procargs(argc, argv);
+	if (argv[0] && argv[0][0] == '-') {
+		state = 1;
+#ifndef KMK
+		read_profile("/etc/profile");
+#endif
+state1:
+		state = 2;
+#ifndef KMK
+		read_profile(".profile");
+#endif
+	}
+state2:
+	state = 3;
+#ifndef KMK
+	if (getuid() == geteuid() && getgid() == getegid()) {
+		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
+			state = 3;
+			read_profile(shinit);
+		}
+	}
+#endif
+state3:
+	state = 4;
+	if (sflag == 0 || minusc) {
+		static int sigs[] =  {
+		    SIGINT, SIGQUIT, SIGHUP,
+#ifdef SIGTSTP
+		    SIGTSTP,
+#endif
+		    SIGPIPE
+		};
+#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
+		int i;
+
+		for (i = 0; i < SIGSSIZE; i++)
+		    setsignal(sigs[i], 0);
+	}
+
+	if (minusc)
+		evalstring(minusc, 0);
+
+	if (sflag || minusc == NULL) {
+state4:	/* XXX ??? - why isn't this before the "if" statement */
+		cmdloop(1);
+	}
+#if PROFILE
+	monitor(0);
+#endif
+	exitshell(exitstatus);
+	/* NOTREACHED */
+}
+
+
+/*
+ * Read and execute commands.  "Top" is nonzero for the top level command
+ * loop; it turns on prompting if the shell is interactive.
+ */
+
+void
+cmdloop(int top)
+{
+	union node *n;
+	struct stackmark smark;
+	int inter;
+	int numeof = 0;
+
+	TRACE(("cmdloop(%d) called\n", top));
+	setstackmark(&smark);
+	for (;;) {
+		if (pendingsigs)
+			dotrap();
+		inter = 0;
+		if (iflag && top) {
+			inter = 1;
+			showjobs(out2, SHOW_CHANGED);
+			chkmail(0);
+			flushout(&errout);
+		}
+		n = parsecmd(inter);
+		/* showtree(n); DEBUG */
+		if (n == NEOF) {
+			if (!top || numeof >= 50)
+				break;
+			if (!stoppedjobs()) {
+				if (!Iflag)
+					break;
+				out2str("\nUse \"exit\" to leave shell.\n");
+			}
+			numeof++;
+		} else if (n != NULL && nflag == 0) {
+			job_warning = (job_warning == 2) ? 1 : 0;
+			numeof = 0;
+			evaltree(n, 0);
+		}
+		popstackmark(&smark);
+		setstackmark(&smark);
+		if (evalskip == SKIPFILE) {
+			evalskip = 0;
+			break;
+		}
+	}
+	popstackmark(&smark);
+}
+
+
+
+#ifndef KMK
+/*
+ * Read /etc/profile or .profile.  Return on error.
+ */
+
+STATIC void
+read_profile(const char *name)
+{
+	int fd;
+	int xflag_set = 0;
+	int vflag_set = 0;
+
+	INTOFF;
+	if ((fd = open(name, O_RDONLY)) >= 0)
+		setinputfd(fd, 1);
+	INTON;
+	if (fd < 0)
+		return;
+	/* -q turns off -x and -v just when executing init files */
+	if (qflag)  {
+	    if (xflag)
+		    xflag = 0, xflag_set = 1;
+	    if (vflag)
+		    vflag = 0, vflag_set = 1;
+	}
+	cmdloop(0);
+	if (qflag)  {
+	    if (xflag_set)
+		    xflag = 1;
+	    if (vflag_set)
+		    vflag = 1;
+	}
+	popfile();
+}
+#endif /* !KMK */
+
+
+
+/*
+ * Read a file containing shell functions.
+ */
+
+void
+readcmdfile(char *name)
+{
+	int fd;
+
+	INTOFF;
+	if ((fd = open(name, O_RDONLY)) >= 0)
+		setinputfd(fd, 1);
+	else
+		error("Can't open %s", name);
+	INTON;
+	cmdloop(0);
+	popfile();
+}
+
+
+
+/*
+ * Take commands from a file.  To be compatible we should do a path
+ * search for the file, which is necessary to find sub-commands.
+ */
+
+
+STATIC char *
+find_dot_file(char *basename)
+{
+	char *fullname;
+	const char *path = pathval();
+	struct stat statb;
+
+	/* don't try this for absolute or relative paths */
+	if (strchr(basename, '/'))
+		return basename;
+
+	while ((fullname = padvance(&path, basename)) != NULL) {
+		if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
+			/*
+			 * Don't bother freeing here, since it will
+			 * be freed by the caller.
+			 */
+			return fullname;
+		}
+		stunalloc(fullname);
+	}
+
+	/* not found in the PATH */
+	error("%s: not found", basename);
+	/* NOTREACHED */
+}
+
+int
+dotcmd(int argc, char **argv)
+{
+	exitstatus = 0;
+
+	if (argc >= 2) {		/* That's what SVR2 does */
+		char *fullname;
+		struct stackmark smark;
+
+		setstackmark(&smark);
+		fullname = find_dot_file(argv[1]);
+		setinputfile(fullname, 1);
+		commandname = fullname;
+		cmdloop(0);
+		popfile();
+		popstackmark(&smark);
+	}
+	return exitstatus;
+}
+
+
+int
+exitcmd(int argc, char **argv)
+{
+	if (stoppedjobs())
+		return 0;
+	if (argc > 1)
+		exitstatus = number(argv[1]);
+	exitshell(exitstatus);
+	/* NOTREACHED */
+}
Index: /tags/kBuild-0.1.4/src/ash/main.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/main.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/main.h	(revision 1780)
@@ -0,0 +1,43 @@
+/*	$NetBSD: main.h,v 1.10 2003/08/07 09:05:34 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)main.h	8.2 (Berkeley) 5/4/95
+ */
+
+extern int rootpid;	/* pid of main shell */
+extern int rootshell;	/* true if we aren't a child of the main shell */
+
+void readcmdfile(char *);
+void cmdloop(int);
+int dotcmd(int, char **);
+int exitcmd(int, char **);
Index: /tags/kBuild-0.1.4/src/ash/memalloc.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/memalloc.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/memalloc.c	(revision 1780)
@@ -0,0 +1,309 @@
+/*	$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)memalloc.c	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "shell.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "machdep.h"
+#include "mystring.h"
+
+/*
+ * Like malloc, but returns an error when out of space.
+ */
+
+pointer
+ckmalloc(int nbytes)
+{
+	pointer p;
+
+	p = malloc(nbytes);
+	if (p == NULL)
+		error("Out of space");
+	return p;
+}
+
+
+/*
+ * Same for realloc.
+ */
+
+pointer
+ckrealloc(pointer p, int nbytes)
+{
+	p = realloc(p, nbytes);
+	if (p == NULL)
+		error("Out of space");
+	return p;
+}
+
+
+/*
+ * Make a copy of a string in safe storage.
+ */
+
+char *
+savestr(const char *s)
+{
+	char *p;
+
+	p = ckmalloc(strlen(s) + 1);
+	scopy(s, p);
+	return p;
+}
+
+
+/*
+ * Parse trees for commands are allocated in lifo order, so we use a stack
+ * to make this more efficient, and also to avoid all sorts of exception
+ * handling code to handle interrupts in the middle of a parse.
+ *
+ * The size 504 was chosen because the Ultrix malloc handles that size
+ * well.
+ */
+
+#define MINSIZE 504		/* minimum size of a block */
+
+struct stack_block {
+	struct stack_block *prev;
+	char space[MINSIZE];
+};
+
+struct stack_block stackbase;
+struct stack_block *stackp = &stackbase;
+struct stackmark *markp;
+char *stacknxt = stackbase.space;
+int stacknleft = MINSIZE;
+int sstrnleft;
+int herefd = -1;
+
+pointer
+stalloc(int nbytes)
+{
+	char *p;
+
+	nbytes = SHELL_ALIGN(nbytes);
+	if (nbytes > stacknleft) {
+		int blocksize;
+		struct stack_block *sp;
+
+		blocksize = nbytes;
+		if (blocksize < MINSIZE)
+			blocksize = MINSIZE;
+		INTOFF;
+		sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
+		sp->prev = stackp;
+		stacknxt = sp->space;
+		stacknleft = blocksize;
+		stackp = sp;
+		INTON;
+	}
+	p = stacknxt;
+	stacknxt += nbytes;
+	stacknleft -= nbytes;
+	return p;
+}
+
+
+void
+stunalloc(pointer p)
+{
+	if (p == NULL) {		/*DEBUG */
+		write(2, "stunalloc\n", 10);
+		abort();
+	}
+	stacknleft += stacknxt - (char *)p;
+	stacknxt = p;
+}
+
+
+
+void
+setstackmark(struct stackmark *mark)
+{
+	mark->stackp = stackp;
+	mark->stacknxt = stacknxt;
+	mark->stacknleft = stacknleft;
+	mark->marknext = markp;
+	markp = mark;
+}
+
+
+void
+popstackmark(struct stackmark *mark)
+{
+	struct stack_block *sp;
+
+	INTOFF;
+	markp = mark->marknext;
+	while (stackp != mark->stackp) {
+		sp = stackp;
+		stackp = sp->prev;
+		ckfree(sp);
+	}
+	stacknxt = mark->stacknxt;
+	stacknleft = mark->stacknleft;
+	INTON;
+}
+
+
+/*
+ * When the parser reads in a string, it wants to stick the string on the
+ * stack and only adjust the stack pointer when it knows how big the
+ * string is.  Stackblock (defined in stack.h) returns a pointer to a block
+ * of space on top of the stack and stackblocklen returns the length of
+ * this block.  Growstackblock will grow this space by at least one byte,
+ * possibly moving it (like realloc).  Grabstackblock actually allocates the
+ * part of the block that has been used.
+ */
+
+void
+growstackblock(void)
+{
+	int newlen = SHELL_ALIGN(stacknleft * 2 + 100);
+
+	if (stacknxt == stackp->space && stackp != &stackbase) {
+		struct stack_block *oldstackp;
+		struct stackmark *xmark;
+		struct stack_block *sp;
+
+		INTOFF;
+		oldstackp = stackp;
+		sp = stackp;
+		stackp = sp->prev;
+		sp = ckrealloc((pointer)sp,
+		    sizeof(struct stack_block) - MINSIZE + newlen);
+		sp->prev = stackp;
+		stackp = sp;
+		stacknxt = sp->space;
+		stacknleft = newlen;
+
+		/*
+		 * Stack marks pointing to the start of the old block
+		 * must be relocated to point to the new block
+		 */
+		xmark = markp;
+		while (xmark != NULL && xmark->stackp == oldstackp) {
+			xmark->stackp = stackp;
+			xmark->stacknxt = stacknxt;
+			xmark->stacknleft = stacknleft;
+			xmark = xmark->marknext;
+		}
+		INTON;
+	} else {
+		char *oldspace = stacknxt;
+		int oldlen = stacknleft;
+		char *p = stalloc(newlen);
+
+		(void)memcpy(p, oldspace, oldlen);
+		stacknxt = p;			/* free the space */
+		stacknleft += newlen;		/* we just allocated */
+	}
+}
+
+void
+grabstackblock(int len)
+{
+	len = SHELL_ALIGN(len);
+	stacknxt += len;
+	stacknleft -= len;
+}
+
+/*
+ * The following routines are somewhat easier to use than the above.
+ * The user declares a variable of type STACKSTR, which may be declared
+ * to be a register.  The macro STARTSTACKSTR initializes things.  Then
+ * the user uses the macro STPUTC to add characters to the string.  In
+ * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
+ * grown as necessary.  When the user is done, she can just leave the
+ * string there and refer to it using stackblock().  Or she can allocate
+ * the space for it using grabstackstr().  If it is necessary to allow
+ * someone else to use the stack temporarily and then continue to grow
+ * the string, the user should use grabstack to allocate the space, and
+ * then call ungrabstr(p) to return to the previous mode of operation.
+ *
+ * USTPUTC is like STPUTC except that it doesn't check for overflow.
+ * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
+ * is space for at least one character.
+ */
+
+char *
+growstackstr(void)
+{
+	int len = stackblocksize();
+	if (herefd >= 0 && len >= 1024) {
+		xwrite(herefd, stackblock(), len);
+		sstrnleft = len - 1;
+		return stackblock();
+	}
+	growstackblock();
+	sstrnleft = stackblocksize() - len - 1;
+	return stackblock() + len;
+}
+
+/*
+ * Called from CHECKSTRSPACE.
+ */
+
+char *
+makestrspace(void)
+{
+	int len = stackblocksize() - sstrnleft;
+	growstackblock();
+	sstrnleft = stackblocksize() - len;
+	return stackblock() + len;
+}
+
+void
+ungrabstackstr(char *s, char *p)
+{
+	stacknleft += stacknxt - s;
+	stacknxt = s;
+	sstrnleft = stacknleft - (p - s);
+
+}
Index: /tags/kBuild-0.1.4/src/ash/memalloc.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/memalloc.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/memalloc.h	(revision 1780)
@@ -0,0 +1,77 @@
+/*	$NetBSD: memalloc.h,v 1.14 2003/08/07 09:05:34 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
+ */
+
+struct stackmark {
+	struct stack_block *stackp;
+	char *stacknxt;
+	int stacknleft;
+	struct stackmark *marknext;
+};
+
+
+extern char *stacknxt;
+extern int stacknleft;
+extern int sstrnleft;
+extern int herefd;
+
+pointer ckmalloc(int);
+pointer ckrealloc(pointer, int);
+char *savestr(const char *);
+pointer stalloc(int);
+void stunalloc(pointer);
+void setstackmark(struct stackmark *);
+void popstackmark(struct stackmark *);
+void growstackblock(void);
+void grabstackblock(int);
+char *growstackstr(void);
+char *makestrspace(void);
+void ungrabstackstr(char *, char *);
+
+
+
+#define stackblock() stacknxt
+#define stackblocksize() stacknleft
+#define STARTSTACKSTR(p)	p = stackblock(), sstrnleft = stackblocksize()
+#define STPUTC(c, p)	(--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
+#define CHECKSTRSPACE(n, p)	{ if (sstrnleft < n) p = makestrspace(); }
+#define USTPUTC(c, p)	(--sstrnleft, *p++ = (c))
+#define STACKSTRNUL(p)	(sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
+#define STUNPUTC(p)	(++sstrnleft, --p)
+#define STTOPC(p)	p[-1]
+#define STADJUST(amount, p)	(p += (amount), sstrnleft -= (amount))
+#define grabstackstr(p)	stalloc(stackblocksize() - sstrnleft)
+
+#define ckfree(p)	free((pointer)(p))
Index: /tags/kBuild-0.1.4/src/ash/miscbltin.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/miscbltin.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/miscbltin.c	(revision 1780)
@@ -0,0 +1,461 @@
+/*	$NetBSD: miscbltin.c,v 1.35 2005/03/19 14:22:50 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)miscbltin.c	8.4 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: miscbltin.c,v 1.35 2005/03/19 14:22:50 dsl Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Miscelaneous builtins.
+ */
+
+#include <sys/types.h>		/* quad_t */
+#include <sys/param.h>		/* BSD4_4 */
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "shell.h"
+#include "options.h"
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "miscbltin.h"
+#include "mystring.h"
+
+#undef rflag
+
+
+
+/*
+ * The read builtin.
+ * Backslahes escape the next char unless -r is specified.
+ *
+ * This uses unbuffered input, which may be avoidable in some cases.
+ *
+ * Note that if IFS=' :' then read x y should work so that:
+ * 'a b'	x='a', y='b'
+ * ' a b '	x='a', y='b'
+ * ':b'		x='',  y='b'
+ * ':'		x='',  y=''
+ * '::'		x='',  y=''
+ * ': :'	x='',  y=''
+ * ':::'	x='',  y='::'
+ * ':b c:'	x='',  y='b c:'
+ */
+
+int
+readcmd(int argc, char **argv)
+{
+	char **ap;
+	char c;
+	int rflag;
+	char *prompt;
+	const char *ifs;
+	char *p;
+	int startword;
+	int status;
+	int i;
+	int is_ifs;
+	int saveall = 0;
+
+	rflag = 0;
+	prompt = NULL;
+	while ((i = nextopt("p:r")) != '\0') {
+		if (i == 'p')
+			prompt = optionarg;
+		else
+			rflag = 1;
+	}
+
+	if (prompt && isatty(0)) {
+		out2str(prompt);
+		output_flushall();
+	}
+
+	if (*(ap = argptr) == NULL)
+		error("arg count");
+
+	if ((ifs = bltinlookup("IFS", 1)) == NULL)
+		ifs = " \t\n";
+
+	status = 0;
+	startword = 2;
+	STARTSTACKSTR(p);
+	for (;;) {
+		if (read(0, &c, 1) != 1) {
+			status = 1;
+			break;
+		}
+		if (c == '\0')
+			continue;
+		if (c == '\\' && !rflag) {
+			if (read(0, &c, 1) != 1) {
+				status = 1;
+				break;
+			}
+			if (c != '\n')
+				STPUTC(c, p);
+			continue;
+		}
+		if (c == '\n')
+			break;
+		if (strchr(ifs, c))
+			is_ifs = strchr(" \t\n", c) ? 1 : 2;
+		else
+			is_ifs = 0;
+
+		if (startword != 0) {
+			if (is_ifs == 1) {
+				/* Ignore leading IFS whitespace */
+				if (saveall)
+					STPUTC(c, p);
+				continue;
+			}
+			if (is_ifs == 2 && startword == 1) {
+				/* Only one non-whitespace IFS per word */
+				startword = 2;
+				if (saveall)
+					STPUTC(c, p);
+				continue;
+			}
+		}
+
+		if (is_ifs == 0) {
+			/* append this character to the current variable */
+			startword = 0;
+			if (saveall)
+				/* Not just a spare terminator */
+				saveall++;
+			STPUTC(c, p);
+			continue;
+		}
+
+		/* end of variable... */
+		startword = is_ifs;
+
+		if (ap[1] == NULL) {
+			/* Last variable needs all IFS chars */
+			saveall++;
+			STPUTC(c, p);
+			continue;
+		}
+
+		STACKSTRNUL(p);
+		setvar(*ap, stackblock(), 0);
+		ap++;
+		STARTSTACKSTR(p);
+	}
+	STACKSTRNUL(p);
+
+	/* Remove trailing IFS chars */
+	for (; stackblock() <= --p; *p = 0) {
+		if (!strchr(ifs, *p))
+			break;
+		if (strchr(" \t\n", *p))
+			/* Always remove whitespace */
+			continue;
+		if (saveall > 1)
+			/* Don't remove non-whitespace unless it was naked */
+			break;
+	}
+	setvar(*ap, stackblock(), 0);
+
+	/* Set any remaining args to "" */
+	while (*++ap != NULL)
+		setvar(*ap, nullstr, 0);
+	return status;
+}
+
+
+
+int
+umaskcmd(int argc, char **argv)
+{
+	char *ap;
+	int mask;
+	int i;
+	int symbolic_mode = 0;
+
+	while ((i = nextopt("S")) != '\0') {
+		symbolic_mode = 1;
+	}
+
+	INTOFF;
+	mask = umask(0);
+	umask(mask);
+	INTON;
+
+	if ((ap = *argptr) == NULL) {
+		if (symbolic_mode) {
+			char u[4], g[4], o[4];
+
+			i = 0;
+			if ((mask & S_IRUSR) == 0)
+				u[i++] = 'r';
+			if ((mask & S_IWUSR) == 0)
+				u[i++] = 'w';
+			if ((mask & S_IXUSR) == 0)
+				u[i++] = 'x';
+			u[i] = '\0';
+
+			i = 0;
+			if ((mask & S_IRGRP) == 0)
+				g[i++] = 'r';
+			if ((mask & S_IWGRP) == 0)
+				g[i++] = 'w';
+			if ((mask & S_IXGRP) == 0)
+				g[i++] = 'x';
+			g[i] = '\0';
+
+			i = 0;
+			if ((mask & S_IROTH) == 0)
+				o[i++] = 'r';
+			if ((mask & S_IWOTH) == 0)
+				o[i++] = 'w';
+			if ((mask & S_IXOTH) == 0)
+				o[i++] = 'x';
+			o[i] = '\0';
+
+			out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
+		} else {
+			out1fmt("%.4o\n", mask);
+		}
+	} else {
+		if (isdigit((unsigned char)*ap)) {
+			mask = 0;
+			do {
+				if (*ap >= '8' || *ap < '0')
+					error("Illegal number: %s", argv[1]);
+				mask = (mask << 3) + (*ap - '0');
+			} while (*++ap != '\0');
+			umask(mask);
+		} else {
+			void *set;
+
+			INTOFF;
+#ifdef __INNOTEK_LIBC__
+			if ((set = bsd_setmode(ap)) != 0) {
+#else
+			if ((set = setmode(ap)) != 0) {
+#endif
+				mask = getmode(set, ~mask & 0777);
+				ckfree(set);
+			}
+			INTON;
+			if (!set)
+				error("Illegal mode: %s", ap);
+
+			umask(~mask & 0777);
+		}
+	}
+	return 0;
+}
+
+/*
+ * ulimit builtin
+ *
+ * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
+ * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
+ * ash by J.T. Conklin.
+ *
+ * Public domain.
+ */
+
+struct limits {
+	const char *name;
+	int	cmd;
+	int	factor;	/* multiply by to get rlim_{cur,max} values */
+	char	option;
+};
+
+static const struct limits limits[] = {
+#ifdef RLIMIT_CPU
+	{ "time(seconds)",		RLIMIT_CPU,	   1, 't' },
+#endif
+#ifdef RLIMIT_FSIZE
+	{ "file(blocks)",		RLIMIT_FSIZE,	 512, 'f' },
+#endif
+#ifdef RLIMIT_DATA
+	{ "data(kbytes)",		RLIMIT_DATA,	1024, 'd' },
+#endif
+#ifdef RLIMIT_STACK
+	{ "stack(kbytes)",		RLIMIT_STACK,	1024, 's' },
+#endif
+#ifdef  RLIMIT_CORE
+	{ "coredump(blocks)",		RLIMIT_CORE,	 512, 'c' },
+#endif
+#ifdef RLIMIT_RSS
+	{ "memory(kbytes)",		RLIMIT_RSS,	1024, 'm' },
+#endif
+#ifdef RLIMIT_MEMLOCK
+	{ "locked memory(kbytes)",	RLIMIT_MEMLOCK, 1024, 'l' },
+#endif
+#ifdef RLIMIT_NPROC
+	{ "process(processes)",		RLIMIT_NPROC,      1, 'p' },
+#endif
+#ifdef RLIMIT_NOFILE
+	{ "nofiles(descriptors)",	RLIMIT_NOFILE,     1, 'n' },
+#endif
+#ifdef RLIMIT_VMEM
+	{ "vmemory(kbytes)",		RLIMIT_VMEM,	1024, 'v' },
+#endif
+#ifdef RLIMIT_SWAP
+	{ "swap(kbytes)",		RLIMIT_SWAP,	1024, 'w' },
+#endif
+#ifdef RLIMIT_SBSIZE
+	{ "sbsize(bytes)",		RLIMIT_SBSIZE,	   1, 'b' },
+#endif
+	{ (char *) 0,			0,		   0,  '\0' }
+};
+
+int
+ulimitcmd(int argc, char **argv)
+{
+	int	c;
+	rlim_t val = 0;
+	enum { SOFT = 0x1, HARD = 0x2 }
+			how = SOFT | HARD;
+	const struct limits	*l;
+	int		set, all = 0;
+	int		optc, what;
+	struct rlimit	limit;
+
+	what = 'f';
+	while ((optc = nextopt("HSabtfdsmcnpl")) != '\0')
+		switch (optc) {
+		case 'H':
+			how = HARD;
+			break;
+		case 'S':
+			how = SOFT;
+			break;
+		case 'a':
+			all = 1;
+			break;
+		default:
+			what = optc;
+		}
+
+	for (l = limits; l->name && l->option != what; l++)
+		;
+	if (!l->name)
+		error("internal error (%c)", what);
+
+	set = *argptr ? 1 : 0;
+	if (set) {
+		char *p = *argptr;
+
+		if (all || argptr[1])
+			error("too many arguments");
+		if (strcmp(p, "unlimited") == 0)
+			val = RLIM_INFINITY;
+		else {
+			val = (rlim_t) 0;
+
+			while ((c = *p++) >= '0' && c <= '9')
+			{
+				val = (val * 10) + (long)(c - '0');
+				if (val < (rlim_t) 0)
+					break;
+			}
+			if (c)
+				error("bad number");
+			val *= l->factor;
+		}
+	}
+	if (all) {
+		for (l = limits; l->name; l++) {
+			getrlimit(l->cmd, &limit);
+			if (how & SOFT)
+				val = limit.rlim_cur;
+			else if (how & HARD)
+				val = limit.rlim_max;
+
+			out1fmt("%-20s ", l->name);
+			if (val == RLIM_INFINITY)
+				out1fmt("unlimited\n");
+			else
+			{
+				val /= l->factor;
+#ifdef BSD4_4
+				out1fmt("%lld\n", (long long) val);
+#else
+				out1fmt("%ld\n", (long) val);
+#endif
+			}
+		}
+		return 0;
+	}
+
+	getrlimit(l->cmd, &limit);
+	if (set) {
+		if (how & HARD)
+			limit.rlim_max = val;
+		if (how & SOFT)
+			limit.rlim_cur = val;
+		if (setrlimit(l->cmd, &limit) < 0)
+			error("error setting limit (%s)", strerror(errno));
+	} else {
+		if (how & SOFT)
+			val = limit.rlim_cur;
+		else if (how & HARD)
+			val = limit.rlim_max;
+
+		if (val == RLIM_INFINITY)
+			out1fmt("unlimited\n");
+		else
+		{
+			val /= l->factor;
+#ifdef BSD4_4
+			out1fmt("%lld\n", (long long) val);
+#else
+			out1fmt("%ld\n", (long) val);
+#endif
+		}
+	}
+	return 0;
+}
Index: /tags/kBuild-0.1.4/src/ash/miscbltin.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/miscbltin.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/miscbltin.h	(revision 1780)
@@ -0,0 +1,31 @@
+/*	$NetBSD: miscbltin.h,v 1.3 2003/08/21 17:57:53 christos Exp $	*/
+
+/*
+ * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+int readcmd(int, char **);
+int umaskcmd(int, char **);
+int ulimitcmd(int, char **);
Index: /tags/kBuild-0.1.4/src/ash/mkbuiltins
===================================================================
--- /tags/kBuild-0.1.4/src/ash/mkbuiltins	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/mkbuiltins	(revision 1780)
@@ -0,0 +1,138 @@
+#!/bin/sh -
+#	$NetBSD: mkbuiltins,v 1.21 2004/06/06 07:03:11 christos Exp $
+#
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)mkbuiltins	8.2 (Berkeley) 5/4/95
+
+havehist=1
+if [ "X$1" = "X-h" ]; then
+	havehist=0
+	shift
+fi
+
+shell=$1
+builtins=$2
+objdir=$3
+
+havejobs=0
+if grep '^#define JOBS[	 ]*1' ${shell} > /dev/null
+then
+	havejobs=1
+fi
+
+exec <$builtins 3> ${objdir}/builtins.c 4> ${objdir}/builtins.h
+
+echo '/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include "shell.h"
+#include "builtins.h"
+
+const struct builtincmd builtincmd[] = {
+' >&3
+
+echo '/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+struct builtincmd {
+      const char *name;
+      int (*builtin)(int, char **);
+};
+
+extern const struct builtincmd builtincmd[];
+extern const struct builtincmd splbltincmd[];
+
+' >&4
+
+specials=
+
+while read line
+do
+	set -- $line
+	[ -z "$1" ] && continue
+	case "$1" in
+	\#if*|\#def*|\#end*)
+		echo $line >&3
+		echo $line >&4
+		continue
+		;;
+	esac
+	l1="${line###}"
+	[ "$l1" != "$line" ] && continue
+
+
+	func=$1
+	shift
+	[ x"$1" = x'-j' ] && {
+		[ $havejobs = 0 ] && continue
+		shift
+	}
+	[ x"$1" = x'-h' ] && {
+		[ $havehist = 0 ] && continue
+		shift
+	}
+	echo 'int '"$func"'(int, char **);' >&4
+	while
+		[ $# != 0 -a "$1" != '#' ]
+	do
+		[ "$1" = '-s' ] && {
+			specials="$specials $2 $func"
+			shift 2
+			continue;
+		}
+		[ "$1" = '-u' ] && shift
+		echo '	{ "'$1'",	'"$func"' },' >&3
+		shift
+	done
+done
+
+echo '	{ 0, 0 },' >&3
+echo '};' >&3
+echo >&3
+echo 'const struct builtincmd splbltincmd[] = {' >&3
+
+set -- $specials
+while
+	[ $# != 0 ]
+do
+	echo '	{ "'$1'",	'"$2"' },' >&3
+	shift 2
+done
+
+echo '	{ 0, 0 },' >&3
+echo "};" >&3
Index: /tags/kBuild-0.1.4/src/ash/mkinit.sh
===================================================================
--- /tags/kBuild-0.1.4/src/ash/mkinit.sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/mkinit.sh	(revision 1780)
@@ -0,0 +1,197 @@
+#! /bin/sh
+#	$NetBSD: mkinit.sh,v 1.2 2004/06/15 23:09:54 dsl Exp $
+
+# Copyright (c) 2003 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by David Laight.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of The NetBSD Foundation nor the names of its
+#    contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+srcs="$*"
+
+nl='
+'
+openparen='('
+backslash='\'
+
+includes=' "shell.h" "mystring.h" "init.h" '
+defines=
+decles=
+event_init=
+event_reset=
+event_shellproc=
+
+for src in $srcs; do
+	exec <$src
+	decnl="$nl"
+	while IFS=; read -r line; do
+		[ "$line" = x ]
+		case "$line " in
+		INIT["{ 	"]* ) event=init;;
+		RESET["{ 	"]* ) event=reset;;
+		SHELLPROC["{ 	"]* ) event=shellproc;;
+		INCLUDE[\ \	]* )
+			IFS=' 	'
+			set -- $line
+			# ignore duplicates
+			[ "${includes}" != "${includes%* $2 }" ] && continue
+			includes="$includes$2 "
+			continue
+			;;
+		MKINIT\  )
+			# struct declaration
+			decles="$decles$nl"
+			while
+				read -r line
+				decles="${decles}${line}${nl}"
+				[ "$line" != "};" ]
+			do
+				:
+			done
+			decnl="$nl"
+			continue
+			;;
+		MKINIT["{ 	"]* )
+			# strip initialiser
+			def=${line#MKINIT}
+			comment="${def#*;}"
+			def="${def%;$comment}"
+			def="${def%%=*}"
+			def="${def% }"
+			decles="${decles}${decnl}extern${def};${comment}${nl}"
+			decnl=
+			continue
+			;;
+		\#define[\ \	]* )
+			IFS=' 	'
+			set -- $line
+			# Ignore those with arguments
+			[ "$2" = "${2##*$openparen}" ] || continue
+			# and multiline definitions
+			[ "$line" = "${line%$backslash}" ] || continue
+			defines="${defines}#undef  $2${nl}${line}${nl}"
+			continue
+			;;
+		* ) continue;;
+		esac
+		# code for events
+		ev="${nl}      /* from $src: */${nl}      {${nl}"
+		while
+			read -r line
+			[ "$line" != "}" ]
+		do
+			# The C program indented by an extra 6 chars using
+			# tabs then spaces. I need to compare the output :-(
+			indent=6
+			while
+				l=${line#	}
+				[ "$l" != "$line" ]
+			do
+				indent=$(($indent + 8))
+				line="$l"
+			done
+			while
+				l=${line# }
+				[ "$l" != "$line" ]
+			do
+				indent=$(($indent + 1))
+				line="$l"
+			done
+			[ -z "$line" -o "$line" != "${line###}" ] && indent=0
+			while
+				[ $indent -ge 8 ]
+			do
+				ev="$ev	"
+				indent="$(($indent - 8))"
+			done
+			while
+				[ $indent -gt 0 ]
+			do
+				ev="$ev "
+				indent="$(($indent - 1))"
+			done
+			ev="${ev}${line}${nl}"
+		done
+		ev="${ev}      }${nl}"
+		eval event_$event=\"\$event_$event\$ev\"
+	done
+done
+
+exec >init.c.tmp
+
+echo "/*"
+echo " * This file was generated by the mkinit program."
+echo " */"
+echo
+
+IFS=' '
+for f in $includes; do
+	echo "#include $f"
+done
+
+echo
+echo
+echo
+echo "$defines"
+echo
+echo "$decles"
+echo
+echo
+echo "/*"
+echo " * Initialization code."
+echo " */"
+echo
+echo "void"
+echo "init() {"
+echo "${event_init%$nl}"
+echo "}"
+echo
+echo
+echo
+echo "/*"
+echo " * This routine is called when an error or an interrupt occurs in an"
+echo " * interactive shell and control is returned to the main command loop."
+echo " */"
+echo
+echo "void"
+echo "reset() {"
+echo "${event_reset%$nl}"
+echo "}"
+echo
+echo
+echo
+echo "/*"
+echo " * This routine is called to initialize the shell to run a shell procedure."
+echo " */"
+echo
+echo "void"
+echo "initshellproc() {"
+echo "${event_shellproc%$nl}"
+echo "}"
+
+exec >&-
+mv init.c.tmp init.c
Index: /tags/kBuild-0.1.4/src/ash/mknodes.sh
===================================================================
--- /tags/kBuild-0.1.4/src/ash/mknodes.sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/mknodes.sh	(revision 1780)
@@ -0,0 +1,217 @@
+#! /bin/sh
+#	$NetBSD: mknodes.sh,v 1.1 2004/01/16 23:24:38 dsl Exp $
+
+# Copyright (c) 2003 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by David Laight.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of The NetBSD Foundation nor the names of its
+#    contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+nodetypes=$1
+nodes_pat=$2
+objdir="$3"
+
+exec <$nodetypes
+exec >$objdir/nodes.h.tmp
+
+echo "/*"
+echo " * This file was generated by mknodes.sh"
+echo " */"
+echo
+
+tagno=0
+while IFS=; read -r line; do
+	line="${line%%#*}"
+	IFS=' 	'
+	set -- $line
+	IFS=
+	[ -z "$2" ] && continue
+	case "$line" in
+	[" 	"]* )
+		IFS=' '
+		[ $field = 0 ] && struct_list="$struct_list $struct"
+		eval field_${struct}_$field=\"\$*\"
+		eval numfld_$struct=\$field
+		field=$(($field + 1))
+		;;
+	* )
+		define=$1
+		struct=$2
+		echo "#define $define $tagno"
+		tagno=$(($tagno + 1))
+		eval define_$struct=\"\$define_$struct \$define\"
+		struct_define="$struct_define $struct"
+		field=0
+		;;
+	esac
+done
+
+echo
+
+IFS=' '
+for struct in $struct_list; do
+	echo
+	echo
+	echo "struct $struct {"
+	field=0
+	while
+		eval line=\"\$field_${struct}_$field\"
+		field=$(($field + 1))
+		[ -n "$line" ]
+	do
+		IFS=' '
+		set -- $line
+		name=$1
+		case $2 in
+		nodeptr ) type="union node *";;
+		nodelist ) type="struct nodelist *";;
+		string ) type="char *";;
+		int ) type="int ";;
+		* ) name=; shift 2; type="$*";;
+		esac
+		echo "      $type$name;"
+	done
+	echo "};"
+done
+
+echo
+echo
+echo "union node {"
+echo "      int type;"
+for struct in $struct_list; do
+	echo "      struct $struct $struct;"
+done
+echo "};"
+echo
+echo
+echo "struct nodelist {"
+echo "	struct nodelist *next;"
+echo "	union node *n;"
+echo "};"
+echo
+echo
+echo "union node *copyfunc(union node *);"
+echo "void freefunc(union node *);"
+
+exec <$nodes_pat
+exec >$objdir/nodes.c.tmp
+mv -f $objdir/nodes.h.tmp $objdir/nodes.h || exit 1
+
+echo "/*"
+echo " * This file was generated by mknodes.sh"
+echo " */"
+echo
+
+while IFS=; read -r line; do
+	IFS=' 	'
+	set -- $line
+	IFS=
+	case "$1" in
+	'%SIZES' )
+		echo "static const short nodesize[$tagno] = {"
+		IFS=' '
+		for struct in $struct_define; do
+			echo "      SHELL_ALIGN(sizeof (struct $struct)),"
+		done
+		echo "};"
+		;;
+	'%CALCSIZE' )
+		echo "      if (n == NULL)"
+		echo "	    return;"
+		echo "      funcblocksize += nodesize[n->type];"
+		echo "      switch (n->type) {"
+		IFS=' '
+		for struct in $struct_list; do
+			eval defines=\"\$define_$struct\"
+			for define in $defines; do
+				echo "      case $define:"
+			done
+			eval field=\$numfld_$struct
+			while
+				[ $field != 0 ]
+			do
+				eval line=\"\$field_${struct}_$field\"
+				field=$(($field - 1))
+				IFS=' '
+				set -- $line
+				name=$1
+				cl=")"
+				case $2 in
+				nodeptr ) fn=calcsize;;
+				nodelist ) fn=sizenodelist;;
+				string ) fn="funcstringsize += strlen"
+					cl=") + 1";;
+				* ) continue;;
+				esac
+				echo "	    ${fn}(n->$struct.$name${cl};"
+			done
+			echo "	    break;"
+		done
+		echo "      };"
+		;;
+	'%COPY' )
+		echo "      if (n == NULL)"
+		echo "	    return NULL;"
+		echo "      new = funcblock;"
+		echo "      funcblock = (char *) funcblock + nodesize[n->type];"
+		echo "      switch (n->type) {"
+		IFS=' '
+		for struct in $struct_list; do
+			eval defines=\"\$define_$struct\"
+			for define in $defines; do
+				echo "      case $define:"
+			done
+			eval field=\$numfld_$struct
+			while
+				[ $field != 0 ]
+			do
+				eval line=\"\$field_${struct}_$field\"
+				field=$(($field - 1))
+				IFS=' '
+				set -- $line
+				name=$1
+				case $2 in
+				nodeptr ) fn="copynode(";;
+				nodelist ) fn="copynodelist(";;
+				string ) fn="nodesavestr(";;
+				int ) fn=;;
+				* ) continue;;
+				esac
+				f="$struct.$name"
+				echo "	    new->$f = ${fn}n->$f${fn:+)};"
+			done
+			echo "	    break;"
+		done
+		echo "      };"
+		echo "      new->type = n->type;"
+		;;
+	* ) echo "$line";;
+	esac
+done
+
+exec >/dev/null
+mv -f $objdir/nodes.c.tmp $objdir/nodes.c || exit 1
Index: /tags/kBuild-0.1.4/src/ash/mktokens
===================================================================
--- /tags/kBuild-0.1.4/src/ash/mktokens	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/mktokens	(revision 1780)
@@ -0,0 +1,98 @@
+#!/bin/sh -
+#	$NetBSD: mktokens,v 1.10 2003/08/22 11:22:23 agc Exp $
+#
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)mktokens	8.1 (Berkeley) 5/31/93
+
+# The following is a list of tokens.  The second column is nonzero if the
+# token marks the end of a list.  The third column is the name to print in
+# error messages.
+
+if [ -z "$TMPDIR" ]; then
+    TMPDIR="/tmp"
+    export TMPDIR
+fi
+F="$TMPDIR/ka$$"
+echo $F
+cat > $F <<\!
+TEOF	1	end of file
+TNL	0	newline
+TSEMI	0	";"
+TBACKGND 0	"&"
+TAND	0	"&&"
+TOR	0	"||"
+TPIPE	0	"|"
+TLP	0	"("
+TRP	1	")"
+TENDCASE 1	";;"
+TENDBQUOTE 1	"`"
+TREDIR	0	redirection
+TWORD	0	word
+TIF	0	"if"
+TTHEN	1	"then"
+TELSE	1	"else"
+TELIF	1	"elif"
+TFI	1	"fi"
+TWHILE	0	"while"
+TUNTIL	0	"until"
+TFOR	0	"for"
+TDO	1	"do"
+TDONE	1	"done"
+TBEGIN	0	"{"
+TEND	1	"}"
+TCASE	0	"case"
+TESAC	1	"esac"
+TNOT	0	"!"
+!
+nl=`wc -l $F`
+exec > token.h
+awk '{print "#define " $1 " " NR-1}' $F
+echo '
+/* Array indicating which tokens mark the end of a list */
+const char tokendlist[] = {'
+awk '{print "\t" $2 ","}' $F
+echo '};
+
+const char *const tokname[] = {'
+sed -e 's/"/\\"/g' \
+    -e 's/[^	 ]*[	 ][	 ]*[^	 ]*[	 ][	 ]*\(.*\)/	"\1",/' \
+    $F
+echo '};
+'
+sed 's/"//g' $F | awk '
+/TIF/{print "#define KWDOFFSET " NR-1; print "";
+      print "const char *const parsekwd[] = {"}
+/TIF/,/neverfound/{print "	\"" $3 "\","}'
+echo '	0
+};'
+
+rm $F
Index: /tags/kBuild-0.1.4/src/ash/myhistedit.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/myhistedit.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/myhistedit.h	(revision 1780)
@@ -0,0 +1,49 @@
+/*	$NetBSD: myhistedit.h,v 1.10 2003/08/07 09:05:35 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)myhistedit.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef SMALL
+#include <histedit.h>
+
+extern History *hist;
+extern EditLine *el;
+#endif
+extern int displayhist;
+
+void histedit(void);
+void sethistsize(const char *);
+void setterm(const char *);
+int histcmd(int, char **);
+int inputrc(int, char **);
+int not_fcnumber(char *);
+int str_to_event(const char *, int);
+
Index: /tags/kBuild-0.1.4/src/ash/mystring.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/mystring.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/mystring.c	(revision 1780)
@@ -0,0 +1,135 @@
+/*	$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mystring.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * String functions.
+ *
+ *	equal(s1, s2)		Return true if strings are equal.
+ *	scopy(from, to)		Copy a string.
+ *	scopyn(from, to, n)	Like scopy, but checks for overflow.
+ *	number(s)		Convert a string of digits to an integer.
+ *	is_number(s)		Return true if s is a string of digits.
+ */
+
+#include <stdlib.h>
+#include "shell.h"
+#include "syntax.h"
+#include "error.h"
+#include "mystring.h"
+
+
+char nullstr[1];		/* zero length string */
+
+/*
+ * equal - #defined in mystring.h
+ */
+
+/*
+ * scopy - #defined in mystring.h
+ */
+
+
+/*
+ * scopyn - copy a string from "from" to "to", truncating the string
+ *		if necessary.  "To" is always nul terminated, even if
+ *		truncation is performed.  "Size" is the size of "to".
+ */
+
+void
+scopyn(const char *from, char *to, int size)
+{
+
+	while (--size > 0) {
+		if ((*to++ = *from++) == '\0')
+			return;
+	}
+	*to = '\0';
+}
+
+
+/*
+ * prefix -- see if pfx is a prefix of string.
+ */
+
+int
+prefix(const char *pfx, const char *string)
+{
+	while (*pfx) {
+		if (*pfx++ != *string++)
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Convert a string of digits to an integer, printing an error message on
+ * failure.
+ */
+
+int
+number(const char *s)
+{
+
+	if (! is_number(s))
+		error("Illegal number: %s", s);
+	return atoi(s);
+}
+
+
+
+/*
+ * Check for a valid number.  This should be elsewhere.
+ */
+
+int
+is_number(const char *p)
+{
+	do {
+		if (! is_digit(*p))
+			return 0;
+	} while (*++p != '\0');
+	return 1;
+}
Index: /tags/kBuild-0.1.4/src/ash/mystring.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/mystring.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/mystring.h	(revision 1780)
@@ -0,0 +1,45 @@
+/*	$NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)mystring.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <string.h>
+
+void scopyn(const char *, char *, int);
+int prefix(const char *, const char *);
+int number(const char *);
+int is_number(const char *);
+
+#define equal(s1, s2)	(strcmp(s1, s2) == 0)
+#define scopy(s1, s2)	((void)strcpy(s2, s1))
Index: /tags/kBuild-0.1.4/src/ash/nodes.c.pat
===================================================================
--- /tags/kBuild-0.1.4/src/ash/nodes.c.pat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/nodes.c.pat	(revision 1780)
@@ -0,0 +1,166 @@
+/*	$NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
+ */
+
+#include <stdlib.h>
+/*
+ * Routine for dealing with parsed shell commands.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "memalloc.h"
+#include "machdep.h"
+#include "mystring.h"
+
+
+int     funcblocksize;		/* size of structures in function */
+int     funcstringsize;		/* size of strings in node */
+pointer funcblock;		/* block to allocate function from */
+char   *funcstring;		/* block to allocate strings from */
+
+%SIZES
+
+
+STATIC void calcsize(union node *);
+STATIC void sizenodelist(struct nodelist *);
+STATIC union node *copynode(union node *);
+STATIC struct nodelist *copynodelist(struct nodelist *);
+STATIC char *nodesavestr(char *);
+
+
+
+/*
+ * Make a copy of a parse tree.
+ */
+
+union node *
+copyfunc(n)
+	union node *n;
+{
+	if (n == NULL)
+		return NULL;
+	funcblocksize = 0;
+	funcstringsize = 0;
+	calcsize(n);
+	funcblock = ckmalloc(funcblocksize + funcstringsize);
+	funcstring = (char *) funcblock + funcblocksize;
+	return copynode(n);
+}
+
+
+
+STATIC void
+calcsize(n)
+	union node *n;
+{
+	%CALCSIZE
+}
+
+
+
+STATIC void
+sizenodelist(lp)
+	struct nodelist *lp;
+{
+	while (lp) {
+		funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
+		calcsize(lp->n);
+		lp = lp->next;
+	}
+}
+
+
+
+STATIC union node *
+copynode(n)
+	union node *n;
+{
+	union node *new;
+
+	%COPY
+	return new;
+}
+
+
+STATIC struct nodelist *
+copynodelist(lp)
+	struct nodelist *lp;
+{
+	struct nodelist *start;
+	struct nodelist **lpp;
+
+	lpp = &start;
+	while (lp) {
+		*lpp = funcblock;
+		funcblock = (char *) funcblock +
+		    SHELL_ALIGN(sizeof(struct nodelist));
+		(*lpp)->n = copynode(lp->n);
+		lp = lp->next;
+		lpp = &(*lpp)->next;
+	}
+	*lpp = NULL;
+	return start;
+}
+
+
+
+STATIC char *
+nodesavestr(s)
+	char   *s;
+{
+	register char *p = s;
+	register char *q = funcstring;
+	char   *rtn = funcstring;
+
+	while ((*q++ = *p++) != 0)
+		continue;
+	funcstring = q;
+	return rtn;
+}
+
+
+
+/*
+ * Free a parse tree.
+ */
+
+void
+freefunc(n)
+	union node *n;
+{
+	if (n)
+		ckfree(n);
+}
Index: /tags/kBuild-0.1.4/src/ash/nodetypes
===================================================================
--- /tags/kBuild-0.1.4/src/ash/nodetypes	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/nodetypes	(revision 1780)
@@ -0,0 +1,143 @@
+#	$NetBSD: nodetypes,v 1.12 2003/08/22 11:22:23 agc Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)nodetypes	8.2 (Berkeley) 5/4/95
+
+# This file describes the nodes used in parse trees.  Unindented lines
+# contain a node type followed by a structure tag.  Subsequent indented
+# lines specify the fields of the structure.  Several node types can share
+# the same structure, in which case the fields of the structure should be
+# specified only once.
+#
+# A field of a structure is described by the name of the field followed
+# by a type.  The currently implemented types are:
+#	nodeptr - a pointer to a node
+#	nodelist - a pointer to a list of nodes
+#	string - a pointer to a nul terminated string
+#	int - an integer
+#	other - any type that can be copied by assignment
+#	temp - a field that doesn't have to be copied when the node is copied
+# The last two types should be followed by the text of a C declaration for
+# the field.
+
+NSEMI nbinary			# two commands separated by a semicolon
+	type	  int
+	ch1	  nodeptr		# the first child
+	ch2	  nodeptr		# the second child
+
+NCMD ncmd			# a simple command
+	type	  int
+	backgnd	  int			# set to run command in background
+	args	  nodeptr		# the arguments
+	redirect  nodeptr		# list of file redirections
+
+NPIPE npipe			# a pipeline
+	type	  int
+	backgnd	  int			# set to run pipeline in background
+	cmdlist	  nodelist		# the commands in the pipeline
+
+NREDIR nredir			# redirection (of a complex command)
+	type	  int
+	n	  nodeptr		# the command
+	redirect  nodeptr		# list of file redirections
+
+NBACKGND nredir			# run command in background
+NSUBSHELL nredir		# run command in a subshell
+
+NAND nbinary			# the && operator
+NOR nbinary			# the || operator
+
+NIF nif				# the if statement.  Elif clauses are handled
+	type	  int		    # using multiple if nodes.
+	test	  nodeptr		# if test
+	ifpart	  nodeptr		# then ifpart
+	elsepart  nodeptr		# else elsepart
+
+NWHILE nbinary			# the while statement.  First child is the test
+NUNTIL nbinary			# the until statement
+
+NFOR nfor			# the for statement
+	type	  int
+	args	  nodeptr		# for var in args
+	body	  nodeptr		# do body; done
+	var	  string		# the for variable
+
+NCASE ncase			# a case statement
+	type	  int
+	expr	  nodeptr		# the word to switch on
+	cases	  nodeptr		# the list of cases (NCLIST nodes)
+
+NCLIST nclist			# a case
+	type	  int
+	next	  nodeptr		# the next case in list
+	pattern	  nodeptr		# list of patterns for this case
+	body	  nodeptr		# code to execute for this case
+
+
+NDEFUN narg			# define a function.  The "next" field contains
+				# the body of the function.
+
+NARG narg			# represents a word
+	type	  int
+	next	  nodeptr		# next word in list
+	text	  string		# the text of the word
+	backquote nodelist		# list of commands in back quotes
+
+NTO nfile			# fd> fname
+NCLOBBER nfile			# fd>| fname
+NFROM nfile			# fd< fname
+NFROMTO nfile			# fd<> fname
+NAPPEND nfile			# fd>> fname
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	fname	  nodeptr		# file name, in a NARG node
+	expfname  temp	char *expfname	# actual file name
+
+NTOFD ndup			# fd<&dupfd
+NFROMFD ndup			# fd>&dupfd
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	dupfd	  int			# file descriptor to duplicate
+	vname	  nodeptr		# file name if fd>&$var
+
+
+NHERE nhere			# fd<<\!
+NXHERE nhere			# fd<<!
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	doc	  nodeptr		# input to command (NARG node)
+
+NNOT nnot			# ! command  (actually pipeline)
+	type	int
+	com	nodeptr
Index: /tags/kBuild-0.1.4/src/ash/options.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/options.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/options.c	(revision 1780)
@@ -0,0 +1,533 @@
+/*	$NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $");
+#endif
+#endif /* not lint */
+
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#define DEFINE_OPTIONS
+#include "options.h"
+#undef DEFINE_OPTIONS
+#include "nodes.h"	/* for other header files */
+#include "eval.h"
+#include "jobs.h"
+#include "input.h"
+#include "output.h"
+#include "trap.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+#include "show.h"
+
+char *arg0;			/* value of $0 */
+struct shparam shellparam;	/* current positional parameters */
+char **argptr;			/* argument list for builtin commands */
+char *optionarg;		/* set by nextopt (like getopt) */
+char *optptr;			/* used by nextopt */
+
+char *minusc;			/* argument to -c option */
+
+
+STATIC void options(int);
+STATIC void minus_o(char *, int);
+STATIC void setoption(int, int);
+STATIC int getopts(char *, char *, char **, char ***, char **);
+
+
+/*
+ * Process the shell command line arguments.
+ */
+
+void
+procargs(int argc, char **argv)
+{
+	int i;
+
+	argptr = argv;
+	if (argc > 0)
+		argptr++;
+	for (i = 0; i < NOPTS; i++)
+		optlist[i].val = 2;
+	options(1);
+	if (*argptr == NULL && minusc == NULL)
+		sflag = 1;
+	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
+		iflag = 1;
+	if (mflag == 2)
+		mflag = iflag;
+	for (i = 0; i < NOPTS; i++)
+		if (optlist[i].val == 2)
+			optlist[i].val = 0;
+#if DEBUG == 2
+	debug = 1;
+#endif
+	arg0 = argv[0];
+	if (sflag == 0 && minusc == NULL) {
+		commandname = argv[0];
+		arg0 = *argptr++;
+		setinputfile(arg0, 0);
+		commandname = arg0;
+	}
+	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
+	if (minusc != NULL) {
+		if (argptr == NULL || *argptr == NULL)
+			error("Bad -c option");
+		minusc = *argptr++;
+		if (*argptr != 0)
+			arg0 = *argptr++;
+	}
+
+	shellparam.p = argptr;
+	shellparam.reset = 1;
+	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
+	while (*argptr) {
+		shellparam.nparam++;
+		argptr++;
+	}
+	optschanged();
+}
+
+
+void
+optschanged(void)
+{
+	setinteractive(iflag);
+#ifndef SMALL
+	histedit();
+#endif
+	setjobctl(mflag);
+}
+
+/*
+ * Process shell options.  The global variable argptr contains a pointer
+ * to the argument list; we advance it past the options.
+ */
+
+STATIC void
+options(int cmdline)
+{
+	static char empty[] = "";
+	char *p;
+	int val;
+	int c;
+
+	if (cmdline)
+		minusc = NULL;
+	while ((p = *argptr) != NULL) {
+		argptr++;
+		if ((c = *p++) == '-') {
+			val = 1;
+                        if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
+                                if (!cmdline) {
+                                        /* "-" means turn off -x and -v */
+                                        if (p[0] == '\0')
+                                                xflag = vflag = 0;
+                                        /* "--" means reset params */
+                                        else if (*argptr == NULL)
+						setparam(argptr);
+                                }
+				break;	  /* "-" or  "--" terminates options */
+			}
+		} else if (c == '+') {
+			val = 0;
+		} else {
+			argptr--;
+			break;
+		}
+		while ((c = *p++) != '\0') {
+			if (c == 'c' && cmdline) {
+				/* command is after shell args*/
+				minusc = empty;
+			} else if (c == 'o') {
+				minus_o(*argptr, val);
+				if (*argptr)
+					argptr++;
+			} else {
+				setoption(c, val);
+			}
+		}
+	}
+}
+
+static void
+set_opt_val(int i, int val)
+{
+	int j;
+	int flag;
+
+	if (val && (flag = optlist[i].opt_set)) {
+		/* some options (eg vi/emacs) are mutually exclusive */
+		for (j = 0; j < NOPTS; j++)
+		    if (optlist[j].opt_set == flag)
+			optlist[j].val = 0;
+	}
+	optlist[i].val = val;
+#ifdef DEBUG
+	if (&optlist[i].val == &debug)
+		opentrace();
+#endif
+}
+
+STATIC void
+minus_o(char *name, int val)
+{
+	int i;
+
+	if (name == NULL) {
+		out1str("Current option settings\n");
+		for (i = 0; i < NOPTS; i++)
+			out1fmt("%-16s%s\n", optlist[i].name,
+				optlist[i].val ? "on" : "off");
+	} else {
+		for (i = 0; i < NOPTS; i++)
+			if (equal(name, optlist[i].name)) {
+				set_opt_val(i, val);
+				return;
+			}
+		error("Illegal option -o %s", name);
+	}
+}
+
+
+STATIC void
+setoption(int flag, int val)
+{
+	int i;
+
+	for (i = 0; i < NOPTS; i++)
+		if (optlist[i].letter == flag) {
+			set_opt_val( i, val );
+			return;
+		}
+	error("Illegal option -%c", flag);
+	/* NOTREACHED */
+}
+
+
+
+#ifdef mkinit
+INCLUDE "options.h"
+
+SHELLPROC {
+	int i;
+
+	for (i = 0; optlist[i].name; i++)
+		optlist[i].val = 0;
+	optschanged();
+
+}
+#endif
+
+
+/*
+ * Set the shell parameters.
+ */
+
+void
+setparam(char **argv)
+{
+	char **newparam;
+	char **ap;
+	int nparam;
+
+	for (nparam = 0 ; argv[nparam] ; nparam++)
+		continue;
+	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
+	while (*argv) {
+		*ap++ = savestr(*argv++);
+	}
+	*ap = NULL;
+	freeparam(&shellparam);
+	shellparam.malloc = 1;
+	shellparam.nparam = nparam;
+	shellparam.p = newparam;
+	shellparam.optnext = NULL;
+}
+
+
+/*
+ * Free the list of positional parameters.
+ */
+
+void
+freeparam(volatile struct shparam *param)
+{
+	char **ap;
+
+	if (param->malloc) {
+		for (ap = param->p ; *ap ; ap++)
+			ckfree(*ap);
+		ckfree(param->p);
+	}
+}
+
+
+
+/*
+ * The shift builtin command.
+ */
+
+int
+shiftcmd(int argc, char **argv)
+{
+	int n;
+	char **ap1, **ap2;
+
+	n = 1;
+	if (argc > 1)
+		n = number(argv[1]);
+	if (n > shellparam.nparam)
+		error("can't shift that many");
+	INTOFF;
+	shellparam.nparam -= n;
+	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
+		if (shellparam.malloc)
+			ckfree(*ap1);
+	}
+	ap2 = shellparam.p;
+	while ((*ap2++ = *ap1++) != NULL);
+	shellparam.optnext = NULL;
+	INTON;
+	return 0;
+}
+
+
+
+/*
+ * The set command builtin.
+ */
+
+int
+setcmd(int argc, char **argv)
+{
+	if (argc == 1)
+		return showvars(0, 0, 1);
+	INTOFF;
+	options(0);
+	optschanged();
+	if (*argptr != NULL) {
+		setparam(argptr);
+	}
+	INTON;
+	return 0;
+}
+
+
+void
+getoptsreset(value)
+	const char *value;
+{
+	if (number(value) == 1) {
+		shellparam.optnext = NULL;
+		shellparam.reset = 1;
+	}
+}
+
+/*
+ * The getopts builtin.  Shellparam.optnext points to the next argument
+ * to be processed.  Shellparam.optptr points to the next character to
+ * be processed in the current argument.  If shellparam.optnext is NULL,
+ * then it's the first time getopts has been called.
+ */
+
+int
+getoptscmd(int argc, char **argv)
+{
+	char **optbase;
+
+	if (argc < 3)
+		error("usage: getopts optstring var [arg]");
+	else if (argc == 3)
+		optbase = shellparam.p;
+	else
+		optbase = &argv[3];
+
+	if (shellparam.reset == 1) {
+		shellparam.optnext = optbase;
+		shellparam.optptr = NULL;
+		shellparam.reset = 0;
+	}
+
+	return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
+		       &shellparam.optptr);
+}
+
+STATIC int
+getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
+{
+	char *p, *q;
+	char c = '?';
+	int done = 0;
+	int ind = 0;
+	int err = 0;
+	char s[12];
+
+	if ((p = *optpptr) == NULL || *p == '\0') {
+		/* Current word is done, advance */
+		if (*optnext == NULL)
+			return 1;
+		p = **optnext;
+		if (p == NULL || *p != '-' || *++p == '\0') {
+atend:
+			ind = *optnext - optfirst + 1;
+			*optnext = NULL;
+			p = NULL;
+			done = 1;
+			goto out;
+		}
+		(*optnext)++;
+		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+			goto atend;
+	}
+
+	c = *p++;
+	for (q = optstr; *q != c; ) {
+		if (*q == '\0') {
+			if (optstr[0] == ':') {
+				s[0] = c;
+				s[1] = '\0';
+				err |= setvarsafe("OPTARG", s, 0);
+			} else {
+				outfmt(&errout, "Illegal option -%c\n", c);
+				(void) unsetvar("OPTARG", 0);
+			}
+			c = '?';
+			goto bad;
+		}
+		if (*++q == ':')
+			q++;
+	}
+
+	if (*++q == ':') {
+		if (*p == '\0' && (p = **optnext) == NULL) {
+			if (optstr[0] == ':') {
+				s[0] = c;
+				s[1] = '\0';
+				err |= setvarsafe("OPTARG", s, 0);
+				c = ':';
+			} else {
+				outfmt(&errout, "No arg for -%c option\n", c);
+				(void) unsetvar("OPTARG", 0);
+				c = '?';
+			}
+			goto bad;
+		}
+
+		if (p == **optnext)
+			(*optnext)++;
+		err |= setvarsafe("OPTARG", p, 0);
+		p = NULL;
+	} else
+		err |= setvarsafe("OPTARG", "", 0);
+	ind = *optnext - optfirst + 1;
+	goto out;
+
+bad:
+	ind = 1;
+	*optnext = NULL;
+	p = NULL;
+out:
+	*optpptr = p;
+	fmtstr(s, sizeof(s), "%d", ind);
+	err |= setvarsafe("OPTIND", s, VNOFUNC);
+	s[0] = c;
+	s[1] = '\0';
+	err |= setvarsafe(optvar, s, 0);
+	if (err) {
+		*optnext = NULL;
+		*optpptr = NULL;
+		output_flushall();
+		exraise(EXERROR);
+	}
+	return done;
+}
+
+/*
+ * XXX - should get rid of.  have all builtins use getopt(3).  the
+ * library getopt must have the BSD extension static variable "optreset"
+ * otherwise it can't be used within the shell safely.
+ *
+ * Standard option processing (a la getopt) for builtin routines.  The
+ * only argument that is passed to nextopt is the option string; the
+ * other arguments are unnecessary.  It return the character, or '\0' on
+ * end of input.
+ */
+
+int
+nextopt(const char *optstring)
+{
+	char *p;
+	const char *q;
+	char c;
+
+	if ((p = optptr) == NULL || *p == '\0') {
+		p = *argptr;
+		if (p == NULL || *p != '-' || *++p == '\0')
+			return '\0';
+		argptr++;
+		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+			return '\0';
+	}
+	c = *p++;
+	for (q = optstring ; *q != c ; ) {
+		if (*q == '\0')
+			error("Illegal option -%c", c);
+		if (*++q == ':')
+			q++;
+	}
+	if (*++q == ':') {
+		if (*p == '\0' && (p = *argptr++) == NULL)
+			error("No arg for -%c option", c);
+		optionarg = p;
+		p = NULL;
+	}
+	optptr = p;
+	return c;
+}
Index: /tags/kBuild-0.1.4/src/ash/options.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/options.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/options.h	(revision 1780)
@@ -0,0 +1,133 @@
+/*	$NetBSD: options.h,v 1.18 2005/05/07 19:52:17 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)options.h	8.2 (Berkeley) 5/4/95
+ */
+
+struct shparam {
+	int nparam;		/* # of positional parameters (without $0) */
+	unsigned char malloc;	/* if parameter list dynamically allocated */
+	unsigned char reset;	/* if getopts has been reset */
+	char **p;		/* parameter list */
+	char **optnext;		/* next parameter to be processed by getopts */
+	char *optptr;		/* used by getopts */
+};
+
+
+struct optent {
+	const char *name;		/* for set -o <name> */
+	const char letter;		/* set [+/-]<letter> and $- */
+	const char opt_set;		/* mutually exclusive option set */
+	char val;			/* value of <letter>flag */
+};
+
+/* Those marked [U] are required by posix, but have no effect! */
+
+#ifdef DEFINE_OPTIONS
+#define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0},
+struct optent optlist[] = {
+#else
+#define DEF_OPTS(name, letter, opt_set)
+#endif
+#define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0)
+
+DEF_OPT( "errexit",	'e' )	/* exit on error */
+#define eflag optlist[0].val
+DEF_OPT( "noglob",	'f' )	/* no pathname expansion */
+#define fflag optlist[1].val
+DEF_OPT( "ignoreeof",	'I' )	/* do not exit on EOF */
+#define Iflag optlist[2].val
+DEF_OPT( "interactive",'i' )	/* interactive shell */
+#define iflag optlist[3].val
+DEF_OPT( "monitor",	'm' )	/* job control */
+#define mflag optlist[4].val
+DEF_OPT( "noexec",	'n' )	/* [U] do not exec commands */
+#define nflag optlist[5].val
+DEF_OPT( "stdin",	's' )	/* read from stdin */
+#define sflag optlist[6].val
+DEF_OPT( "xtrace",	'x' )	/* trace after expansion */
+#define xflag optlist[7].val
+DEF_OPT( "verbose",	'v' )	/* trace read input */
+#define vflag optlist[8].val
+DEF_OPTS( "vi",		'V', 'V' )	/* vi style editing */
+#define Vflag optlist[9].val
+DEF_OPTS( "emacs",	'E', 'V' )	/* emacs style editing */
+#define	Eflag optlist[10].val
+DEF_OPT( "noclobber",	'C' )	/* do not overwrite files with > */
+#define	Cflag optlist[11].val
+DEF_OPT( "allexport",	'a' )	/* export all variables */
+#define	aflag optlist[12].val
+DEF_OPT( "notify",	'b' )	/* [U] report completion of background jobs */
+#define	bflag optlist[13].val
+DEF_OPT( "nounset",	'u' )	/* error expansion of unset variables */
+#define	uflag optlist[14].val
+DEF_OPT( "quietprofile", 'q' )
+#define	qflag optlist[15].val
+DEF_OPT( "nolog",	0 )	/* [U] no functon defs in command history */
+#define	nolog optlist[16].val
+DEF_OPT( "cdprint",	0 )	/* always print result of cd */
+#define	cdprint optlist[17].val
+DEF_OPT( "tabcomplete",	0 )	/* <tab> causes filename expansion */
+#define	tabcomplete optlist[18].val
+#ifdef DEBUG
+DEF_OPT( "debug",	0 )	/* enable debug prints */
+#define	debug optlist[19].val
+#endif
+
+#ifdef DEFINE_OPTIONS
+	{ 0, 0, 0, 0 },
+};
+#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)
+int sizeof_optlist = sizeof optlist;
+#else
+extern struct optent optlist[];
+extern int sizeof_optlist;
+#endif
+
+
+extern char *minusc;		/* argument to -c option */
+extern char *arg0;		/* $0 */
+extern struct shparam shellparam;  /* $@ */
+extern char **argptr;		/* argument list for builtin commands */
+extern char *optionarg;		/* set by nextopt */
+extern char *optptr;		/* used by nextopt */
+
+void procargs(int, char **);
+void optschanged(void);
+void setparam(char **);
+void freeparam(volatile struct shparam *);
+int shiftcmd(int, char **);
+int setcmd(int, char **);
+int getoptscmd(int, char **);
+int nextopt(const char *);
+void getoptsreset(const char *);
Index: /tags/kBuild-0.1.4/src/ash/output.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/output.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/output.c	(revision 1780)
@@ -0,0 +1,518 @@
+/*	$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Shell output routines.  We use our own output routines because:
+ *	When a builtin command is interrupted we have to discard
+ *		any pending output.
+ *	When a builtin command appears in back quotes, we want to
+ *		save the output of the command in a region obtained
+ *		via malloc, rather than doing a fork and reading the
+ *		output of the command via a pipe.
+ *	Our output routines may be smaller than the stdio routines.
+ */
+
+#include <sys/types.h>		/* quad_t */
+#include <sys/param.h>		/* BSD4_4 */
+#include <sys/ioctl.h>
+
+#include <stdio.h>	/* defines BUFSIZ */
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "syntax.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+
+
+#define OUTBUFSIZ BUFSIZ
+#define BLOCK_OUT -2		/* output to a fixed block of memory */
+#define MEM_OUT -3		/* output to dynamically allocated memory */
+#define OUTPUT_ERR 01		/* error occurred on output */
+
+
+struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
+struct output errout = {NULL, 0, NULL, 100, 2, 0};
+struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
+struct output *out1 = &output;
+struct output *out2 = &errout;
+
+
+
+#ifdef mkinit
+
+INCLUDE "output.h"
+INCLUDE "memalloc.h"
+
+RESET {
+	out1 = &output;
+	out2 = &errout;
+	if (memout.buf != NULL) {
+		ckfree(memout.buf);
+		memout.buf = NULL;
+	}
+}
+
+#endif
+
+
+#ifdef notdef	/* no longer used */
+/*
+ * Set up an output file to write to memory rather than a file.
+ */
+
+void
+open_mem(char *block, int length, struct output *file)
+{
+	file->nextc = block;
+	file->nleft = --length;
+	file->fd = BLOCK_OUT;
+	file->flags = 0;
+}
+#endif
+
+
+void
+out1str(const char *p)
+{
+	outstr(p, out1);
+}
+
+
+void
+out2str(const char *p)
+{
+	outstr(p, out2);
+}
+
+
+void
+outstr(const char *p, struct output *file)
+{
+	while (*p)
+		outc(*p++, file);
+	if (file == out2)
+		flushout(file);
+}
+
+
+char out_junk[16];
+
+
+void
+emptyoutbuf(struct output *dest)
+{
+	int offset;
+
+	if (dest->fd == BLOCK_OUT) {
+		dest->nextc = out_junk;
+		dest->nleft = sizeof out_junk;
+		dest->flags |= OUTPUT_ERR;
+	} else if (dest->buf == NULL) {
+		INTOFF;
+		dest->buf = ckmalloc(dest->bufsize);
+		dest->nextc = dest->buf;
+		dest->nleft = dest->bufsize;
+		INTON;
+	} else if (dest->fd == MEM_OUT) {
+		offset = dest->bufsize;
+		INTOFF;
+		dest->bufsize <<= 1;
+		dest->buf = ckrealloc(dest->buf, dest->bufsize);
+		dest->nleft = dest->bufsize - offset;
+		dest->nextc = dest->buf + offset;
+		INTON;
+	} else {
+		flushout(dest);
+	}
+	dest->nleft--;
+}
+
+
+void
+output_flushall(void)
+{
+	flushout(&output);
+	flushout(&errout);
+}
+
+
+void
+flushout(struct output *dest)
+{
+
+	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
+		return;
+	if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
+		dest->flags |= OUTPUT_ERR;
+	dest->nextc = dest->buf;
+	dest->nleft = dest->bufsize;
+}
+
+
+void
+freestdout(void)
+{
+	INTOFF;
+	if (output.buf) {
+		ckfree(output.buf);
+		output.buf = NULL;
+		output.nleft = 0;
+	}
+	INTON;
+}
+
+
+void
+outfmt(struct output *file, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(file, fmt, ap);
+	va_end(ap);
+}
+
+
+void
+out1fmt(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(out1, fmt, ap);
+	va_end(ap);
+}
+
+void
+dprintf(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(out2, fmt, ap);
+	va_end(ap);
+	flushout(out2);
+}
+
+void
+fmtstr(char *outbuf, size_t length, const char *fmt, ...)
+{
+	va_list ap;
+	struct output strout;
+
+	va_start(ap, fmt);
+	strout.nextc = outbuf;
+	strout.nleft = length;
+	strout.fd = BLOCK_OUT;
+	strout.flags = 0;
+	doformat(&strout, fmt, ap);
+	outc('\0', &strout);
+	if (strout.flags & OUTPUT_ERR)
+		outbuf[length - 1] = '\0';
+	va_end(ap);
+}
+
+/*
+ * Formatted output.  This routine handles a subset of the printf formats:
+ * - Formats supported: d, u, o, p, X, s, and c.
+ * - The x format is also accepted but is treated like X.
+ * - The l, ll and q modifiers are accepted.
+ * - The - and # flags are accepted; # only works with the o format.
+ * - Width and precision may be specified with any format except c.
+ * - An * may be given for the width or precision.
+ * - The obsolete practice of preceding the width with a zero to get
+ *   zero padding is not supported; use the precision field.
+ * - A % may be printed by writing %% in the format string.
+ */
+
+#define TEMPSIZE 24
+
+#ifdef BSD4_4
+#define HAVE_VASPRINTF 1
+#endif
+
+void
+doformat(struct output *dest, const char *f, va_list ap)
+{
+#if	HAVE_VASPRINTF
+	char *s;
+
+	vasprintf(&s, f, ap);
+	outstr(s, dest);
+	free(s);
+#else	/* !HAVE_VASPRINTF */
+	static const char digit[] = "0123456789ABCDEF";
+	char c;
+	char temp[TEMPSIZE];
+	int flushleft;
+	int sharp;
+	int width;
+	int prec;
+	int islong;
+	int isquad;
+	char *p;
+	int sign;
+#ifdef BSD4_4
+	quad_t l;
+	u_quad_t num;
+#else
+	long l;
+	u_long num;
+#endif
+	unsigned base;
+	int len;
+	int size;
+	int pad;
+
+	while ((c = *f++) != '\0') {
+		if (c != '%') {
+			outc(c, dest);
+			continue;
+		}
+		flushleft = 0;
+		sharp = 0;
+		width = 0;
+		prec = -1;
+		islong = 0;
+		isquad = 0;
+		for (;;) {
+			if (*f == '-')
+				flushleft++;
+			else if (*f == '#')
+				sharp++;
+			else
+				break;
+			f++;
+		}
+		if (*f == '*') {
+			width = va_arg(ap, int);
+			f++;
+		} else {
+			while (is_digit(*f)) {
+				width = 10 * width + digit_val(*f++);
+			}
+		}
+		if (*f == '.') {
+			if (*++f == '*') {
+				prec = va_arg(ap, int);
+				f++;
+			} else {
+				prec = 0;
+				while (is_digit(*f)) {
+					prec = 10 * prec + digit_val(*f++);
+				}
+			}
+		}
+		if (*f == 'l') {
+			f++;
+			if (*f == 'l') {
+				isquad++;
+				f++;
+			} else
+				islong++;
+		} else if (*f == 'q') {
+			isquad++;
+			f++;
+		}
+		switch (*f) {
+		case 'd':
+#ifdef BSD4_4
+			if (isquad)
+				l = va_arg(ap, quad_t);
+			else
+#endif
+			if (islong)
+				l = va_arg(ap, long);
+			else
+				l = va_arg(ap, int);
+			sign = 0;
+			num = l;
+			if (l < 0) {
+				num = -l;
+				sign = 1;
+			}
+			base = 10;
+			goto number;
+		case 'u':
+			base = 10;
+			goto uns_number;
+		case 'o':
+			base = 8;
+			goto uns_number;
+		case 'p':
+			outc('0', dest);
+			outc('x', dest);
+			/*FALLTHROUGH*/
+		case 'x':
+			/* we don't implement 'x'; treat like 'X' */
+		case 'X':
+			base = 16;
+uns_number:	  /* an unsigned number */
+			sign = 0;
+#ifdef BSD4_4
+			if (isquad)
+				num = va_arg(ap, u_quad_t);
+			else
+#endif
+			if (islong)
+				num = va_arg(ap, unsigned long);
+			else
+				num = va_arg(ap, unsigned int);
+number:		  /* process a number */
+			p = temp + TEMPSIZE - 1;
+			*p = '\0';
+			while (num) {
+				*--p = digit[num % base];
+				num /= base;
+			}
+			len = (temp + TEMPSIZE - 1) - p;
+			if (prec < 0)
+				prec = 1;
+			if (sharp && *f == 'o' && prec <= len)
+				prec = len + 1;
+			pad = 0;
+			if (width) {
+				size = len;
+				if (size < prec)
+					size = prec;
+				size += sign;
+				pad = width - size;
+				if (flushleft == 0) {
+					while (--pad >= 0)
+						outc(' ', dest);
+				}
+			}
+			if (sign)
+				outc('-', dest);
+			prec -= len;
+			while (--prec >= 0)
+				outc('0', dest);
+			while (*p)
+				outc(*p++, dest);
+			while (--pad >= 0)
+				outc(' ', dest);
+			break;
+		case 's':
+			p = va_arg(ap, char *);
+			pad = 0;
+			if (width) {
+				len = strlen(p);
+				if (prec >= 0 && len > prec)
+					len = prec;
+				pad = width - len;
+				if (flushleft == 0) {
+					while (--pad >= 0)
+						outc(' ', dest);
+				}
+			}
+			prec++;
+			while (--prec != 0 && *p)
+				outc(*p++, dest);
+			while (--pad >= 0)
+				outc(' ', dest);
+			break;
+		case 'c':
+			c = va_arg(ap, int);
+			outc(c, dest);
+			break;
+		default:
+			outc(*f, dest);
+			break;
+		}
+		f++;
+	}
+#endif	/* !HAVE_VASPRINTF */
+}
+
+
+
+/*
+ * Version of write which resumes after a signal is caught.
+ */
+
+int
+xwrite(int fd, char *buf, int nbytes)
+{
+	int ntry;
+	int i;
+	int n;
+
+	n = nbytes;
+	ntry = 0;
+	for (;;) {
+		i = write(fd, buf, n);
+		if (i > 0) {
+			if ((n -= i) <= 0)
+				return nbytes;
+			buf += i;
+			ntry = 0;
+		} else if (i == 0) {
+			if (++ntry > 10)
+				return nbytes - n;
+		} else if (errno != EINTR) {
+			return -1;
+		}
+	}
+}
+
+
+/*
+ * Version of ioctl that retries after a signal is caught.
+ * XXX unused function
+ */
+
+int
+xioctl(int fd, unsigned long request, char *arg)
+{
+	int i;
+
+	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
+	return i;
+}
Index: /tags/kBuild-0.1.4/src/ash/output.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/output.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/output.h	(revision 1780)
@@ -0,0 +1,81 @@
+/*	$NetBSD: output.h,v 1.17 2003/08/07 09:05:36 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)output.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef OUTPUT_INCL
+
+#include <stdarg.h>
+
+struct output {
+	char *nextc;
+	int nleft;
+	char *buf;
+	int bufsize;
+	short fd;
+	short flags;
+};
+
+extern struct output output;
+extern struct output errout;
+extern struct output memout;
+extern struct output *out1;
+extern struct output *out2;
+
+void open_mem(char *, int, struct output *);
+void out1str(const char *);
+void out2str(const char *);
+void outstr(const char *, struct output *);
+void emptyoutbuf(struct output *);
+void output_flushall(void);
+void flushout(struct output *);
+void freestdout(void);
+void outfmt(struct output *, const char *, ...)
+    __attribute__((__format__(__printf__,2,3)));
+void out1fmt(const char *, ...)
+    __attribute__((__format__(__printf__,1,2)));
+void dprintf(const char *, ...)
+    __attribute__((__format__(__printf__,1,2)));
+void fmtstr(char *, size_t, const char *, ...)
+    __attribute__((__format__(__printf__,3,4)));
+void doformat(struct output *, const char *, va_list);
+int xwrite(int, char *, int);
+int xioctl(int, unsigned long, char *);
+
+#define outc(c, file)	(--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
+#define out1c(c)	outc(c, out1);
+#define out2c(c)	outc(c, out2);
+
+#define OUTPUT_INCL
+#endif
Index: /tags/kBuild-0.1.4/src/ash/parser.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/parser.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/parser.c	(revision 1780)
@@ -0,0 +1,1656 @@
+/*	$NetBSD: parser.c,v 1.59 2005/03/21 20:10:29 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)parser.c	8.7 (Berkeley) 5/16/95";
+#else
+__RCSID("$NetBSD: parser.c,v 1.59 2005/03/21 20:10:29 dsl Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+#ifdef __sun__
+#include <iso/limits_iso.h>
+#endif
+
+#include "shell.h"
+#include "parser.h"
+#include "nodes.h"
+#include "expand.h"	/* defines rmescapes() */
+#include "eval.h"	/* defines commandname */
+#include "redir.h"	/* defines copyfd() */
+#include "syntax.h"
+#include "options.h"
+#include "input.h"
+#include "output.h"
+#include "var.h"
+#include "error.h"
+#include "memalloc.h"
+#include "mystring.h"
+#include "alias.h"
+#include "show.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+
+/*
+ * Shell command parser.
+ */
+
+#define EOFMARKLEN 79
+
+/* values returned by readtoken */
+#include "token.h"
+
+#define OPENBRACE '{'
+#define CLOSEBRACE '}'
+
+
+struct heredoc {
+	struct heredoc *next;	/* next here document in list */
+	union node *here;		/* redirection node */
+	char *eofmark;		/* string indicating end of input */
+	int striptabs;		/* if set, strip leading tabs */
+};
+
+
+
+static int noalias = 0;		/* when set, don't handle aliases */
+struct heredoc *heredoclist;	/* list of here documents to read */
+int parsebackquote;		/* nonzero if we are inside backquotes */
+int doprompt;			/* if set, prompt the user */
+int needprompt;			/* true if interactive and at start of line */
+int lasttoken;			/* last token read */
+MKINIT int tokpushback;		/* last token pushed back */
+char *wordtext;			/* text of last word returned by readtoken */
+MKINIT int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
+struct nodelist *backquotelist;
+union node *redirnode;
+struct heredoc *heredoc;
+int quoteflag;			/* set if (part of) last token was quoted */
+int startlinno;			/* line # where last token started */
+
+
+STATIC union node *list(int);
+STATIC union node *andor(void);
+STATIC union node *pipeline(void);
+STATIC union node *command(void);
+STATIC union node *simplecmd(union node **, union node *);
+STATIC union node *makename(void);
+STATIC void parsefname(void);
+STATIC void parseheredoc(void);
+STATIC int peektoken(void);
+STATIC int readtoken(void);
+STATIC int xxreadtoken(void);
+STATIC int readtoken1(int, char const *, char *, int);
+STATIC int noexpand(char *);
+STATIC void synexpect(int) __attribute__((__noreturn__));
+STATIC void synerror(const char *) __attribute__((__noreturn__));
+STATIC void setprompt(int);
+
+
+/*
+ * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
+ * valid parse tree indicating a blank line.)
+ */
+
+union node *
+parsecmd(int interact)
+{
+	int t;
+
+	tokpushback = 0;
+	doprompt = interact;
+	if (doprompt)
+		setprompt(1);
+	else
+		setprompt(0);
+	needprompt = 0;
+	t = readtoken();
+	if (t == TEOF)
+		return NEOF;
+	if (t == TNL)
+		return NULL;
+	tokpushback++;
+	return list(1);
+}
+
+
+STATIC union node *
+list(int nlflag)
+{
+	union node *n1, *n2, *n3;
+	int tok;
+
+	checkkwd = 2;
+	if (nlflag == 0 && tokendlist[peektoken()])
+		return NULL;
+	n1 = NULL;
+	for (;;) {
+		n2 = andor();
+		tok = readtoken();
+		if (tok == TBACKGND) {
+			if (n2->type == NCMD || n2->type == NPIPE) {
+				n2->ncmd.backgnd = 1;
+			} else if (n2->type == NREDIR) {
+				n2->type = NBACKGND;
+			} else {
+				n3 = (union node *)stalloc(sizeof (struct nredir));
+				n3->type = NBACKGND;
+				n3->nredir.n = n2;
+				n3->nredir.redirect = NULL;
+				n2 = n3;
+			}
+		}
+		if (n1 == NULL) {
+			n1 = n2;
+		}
+		else {
+			n3 = (union node *)stalloc(sizeof (struct nbinary));
+			n3->type = NSEMI;
+			n3->nbinary.ch1 = n1;
+			n3->nbinary.ch2 = n2;
+			n1 = n3;
+		}
+		switch (tok) {
+		case TBACKGND:
+		case TSEMI:
+			tok = readtoken();
+			/* fall through */
+		case TNL:
+			if (tok == TNL) {
+				parseheredoc();
+				if (nlflag)
+					return n1;
+			} else {
+				tokpushback++;
+			}
+			checkkwd = 2;
+			if (tokendlist[peektoken()])
+				return n1;
+			break;
+		case TEOF:
+			if (heredoclist)
+				parseheredoc();
+			else
+				pungetc();		/* push back EOF on input */
+			return n1;
+		default:
+			if (nlflag)
+				synexpect(-1);
+			tokpushback++;
+			return n1;
+		}
+	}
+}
+
+
+
+STATIC union node *
+andor(void)
+{
+	union node *n1, *n2, *n3;
+	int t;
+
+	n1 = pipeline();
+	for (;;) {
+		if ((t = readtoken()) == TAND) {
+			t = NAND;
+		} else if (t == TOR) {
+			t = NOR;
+		} else {
+			tokpushback++;
+			return n1;
+		}
+		n2 = pipeline();
+		n3 = (union node *)stalloc(sizeof (struct nbinary));
+		n3->type = t;
+		n3->nbinary.ch1 = n1;
+		n3->nbinary.ch2 = n2;
+		n1 = n3;
+	}
+}
+
+
+
+STATIC union node *
+pipeline(void)
+{
+	union node *n1, *n2, *pipenode;
+	struct nodelist *lp, *prev;
+	int negate;
+
+	negate = 0;
+	TRACE(("pipeline: entered\n"));
+	while (readtoken() == TNOT)
+		negate = !negate;
+	tokpushback++;
+	n1 = command();
+	if (readtoken() == TPIPE) {
+		pipenode = (union node *)stalloc(sizeof (struct npipe));
+		pipenode->type = NPIPE;
+		pipenode->npipe.backgnd = 0;
+		lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+		pipenode->npipe.cmdlist = lp;
+		lp->n = n1;
+		do {
+			prev = lp;
+			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+			lp->n = command();
+			prev->next = lp;
+		} while (readtoken() == TPIPE);
+		lp->next = NULL;
+		n1 = pipenode;
+	}
+	tokpushback++;
+	if (negate) {
+		n2 = (union node *)stalloc(sizeof (struct nnot));
+		n2->type = NNOT;
+		n2->nnot.com = n1;
+		return n2;
+	} else
+		return n1;
+}
+
+
+
+STATIC union node *
+command(void)
+{
+	union node *n1, *n2;
+	union node *ap, **app;
+	union node *cp, **cpp;
+	union node *redir, **rpp;
+	int t, negate = 0;
+
+	checkkwd = 2;
+	redir = NULL;
+	n1 = NULL;
+	rpp = &redir;
+
+	/* Check for redirection which may precede command */
+	while (readtoken() == TREDIR) {
+		*rpp = n2 = redirnode;
+		rpp = &n2->nfile.next;
+		parsefname();
+	}
+	tokpushback++;
+
+	while (readtoken() == TNOT) {
+		TRACE(("command: TNOT recognized\n"));
+		negate = !negate;
+	}
+	tokpushback++;
+
+	switch (readtoken()) {
+	case TIF:
+		n1 = (union node *)stalloc(sizeof (struct nif));
+		n1->type = NIF;
+		n1->nif.test = list(0);
+		if (readtoken() != TTHEN)
+			synexpect(TTHEN);
+		n1->nif.ifpart = list(0);
+		n2 = n1;
+		while (readtoken() == TELIF) {
+			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
+			n2 = n2->nif.elsepart;
+			n2->type = NIF;
+			n2->nif.test = list(0);
+			if (readtoken() != TTHEN)
+				synexpect(TTHEN);
+			n2->nif.ifpart = list(0);
+		}
+		if (lasttoken == TELSE)
+			n2->nif.elsepart = list(0);
+		else {
+			n2->nif.elsepart = NULL;
+			tokpushback++;
+		}
+		if (readtoken() != TFI)
+			synexpect(TFI);
+		checkkwd = 1;
+		break;
+	case TWHILE:
+	case TUNTIL: {
+		int got;
+		n1 = (union node *)stalloc(sizeof (struct nbinary));
+		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
+		n1->nbinary.ch1 = list(0);
+		if ((got=readtoken()) != TDO) {
+TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
+			synexpect(TDO);
+		}
+		n1->nbinary.ch2 = list(0);
+		if (readtoken() != TDONE)
+			synexpect(TDONE);
+		checkkwd = 1;
+		break;
+	}
+	case TFOR:
+		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
+			synerror("Bad for loop variable");
+		n1 = (union node *)stalloc(sizeof (struct nfor));
+		n1->type = NFOR;
+		n1->nfor.var = wordtext;
+		if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
+			app = &ap;
+			while (readtoken() == TWORD) {
+				n2 = (union node *)stalloc(sizeof (struct narg));
+				n2->type = NARG;
+				n2->narg.text = wordtext;
+				n2->narg.backquote = backquotelist;
+				*app = n2;
+				app = &n2->narg.next;
+			}
+			*app = NULL;
+			n1->nfor.args = ap;
+			if (lasttoken != TNL && lasttoken != TSEMI)
+				synexpect(-1);
+		} else {
+			static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
+								   '@', '=', '\0'};
+			n2 = (union node *)stalloc(sizeof (struct narg));
+			n2->type = NARG;
+			n2->narg.text = argvars;
+			n2->narg.backquote = NULL;
+			n2->narg.next = NULL;
+			n1->nfor.args = n2;
+			/*
+			 * Newline or semicolon here is optional (but note
+			 * that the original Bourne shell only allowed NL).
+			 */
+			if (lasttoken != TNL && lasttoken != TSEMI)
+				tokpushback++;
+		}
+		checkkwd = 2;
+		if ((t = readtoken()) == TDO)
+			t = TDONE;
+		else if (t == TBEGIN)
+			t = TEND;
+		else
+			synexpect(-1);
+		n1->nfor.body = list(0);
+		if (readtoken() != t)
+			synexpect(t);
+		checkkwd = 1;
+		break;
+	case TCASE:
+		n1 = (union node *)stalloc(sizeof (struct ncase));
+		n1->type = NCASE;
+		if (readtoken() != TWORD)
+			synexpect(TWORD);
+		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
+		n2->type = NARG;
+		n2->narg.text = wordtext;
+		n2->narg.backquote = backquotelist;
+		n2->narg.next = NULL;
+		while (readtoken() == TNL);
+		if (lasttoken != TWORD || ! equal(wordtext, "in"))
+			synerror("expecting \"in\"");
+		cpp = &n1->ncase.cases;
+		noalias = 1;
+		checkkwd = 2, readtoken();
+		do {
+			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
+			cp->type = NCLIST;
+			app = &cp->nclist.pattern;
+			for (;;) {
+				*app = ap = (union node *)stalloc(sizeof (struct narg));
+				ap->type = NARG;
+				ap->narg.text = wordtext;
+				ap->narg.backquote = backquotelist;
+				if (checkkwd = 2, readtoken() != TPIPE)
+					break;
+				app = &ap->narg.next;
+				readtoken();
+			}
+			ap->narg.next = NULL;
+			noalias = 0;
+			if (lasttoken != TRP) {
+				synexpect(TRP);
+			}
+			cp->nclist.body = list(0);
+
+			checkkwd = 2;
+			if ((t = readtoken()) != TESAC) {
+				if (t != TENDCASE) {
+					noalias = 0;
+					synexpect(TENDCASE);
+				} else {
+					noalias = 1;
+					checkkwd = 2;
+					readtoken();
+				}
+			}
+			cpp = &cp->nclist.next;
+		} while(lasttoken != TESAC);
+		noalias = 0;
+		*cpp = NULL;
+		checkkwd = 1;
+		break;
+	case TLP:
+		n1 = (union node *)stalloc(sizeof (struct nredir));
+		n1->type = NSUBSHELL;
+		n1->nredir.n = list(0);
+		n1->nredir.redirect = NULL;
+		if (readtoken() != TRP)
+			synexpect(TRP);
+		checkkwd = 1;
+		break;
+	case TBEGIN:
+		n1 = list(0);
+		if (readtoken() != TEND)
+			synexpect(TEND);
+		checkkwd = 1;
+		break;
+	/* Handle an empty command like other simple commands.  */
+	case TSEMI:
+		/*
+		 * An empty command before a ; doesn't make much sense, and
+		 * should certainly be disallowed in the case of `if ;'.
+		 */
+		if (!redir)
+			synexpect(-1);
+	case TAND:
+	case TOR:
+	case TNL:
+	case TEOF:
+	case TWORD:
+	case TRP:
+		tokpushback++;
+		n1 = simplecmd(rpp, redir);
+		goto checkneg;
+	default:
+		synexpect(-1);
+		/* NOTREACHED */
+	}
+
+	/* Now check for redirection which may follow command */
+	while (readtoken() == TREDIR) {
+		*rpp = n2 = redirnode;
+		rpp = &n2->nfile.next;
+		parsefname();
+	}
+	tokpushback++;
+	*rpp = NULL;
+	if (redir) {
+		if (n1->type != NSUBSHELL) {
+			n2 = (union node *)stalloc(sizeof (struct nredir));
+			n2->type = NREDIR;
+			n2->nredir.n = n1;
+			n1 = n2;
+		}
+		n1->nredir.redirect = redir;
+	}
+
+checkneg:
+	if (negate) {
+		n2 = (union node *)stalloc(sizeof (struct nnot));
+		n2->type = NNOT;
+		n2->nnot.com = n1;
+		return n2;
+	}
+	else
+		return n1;
+}
+
+
+STATIC union node *
+simplecmd(union node **rpp, union node *redir)
+{
+	union node *args, **app;
+	union node **orig_rpp = rpp;
+	union node *n = NULL, *n2;
+	int negate = 0;
+
+	/* If we don't have any redirections already, then we must reset */
+	/* rpp to be the address of the local redir variable.  */
+	if (redir == 0)
+		rpp = &redir;
+
+	args = NULL;
+	app = &args;
+	/*
+	 * We save the incoming value, because we need this for shell
+	 * functions.  There can not be a redirect or an argument between
+	 * the function name and the open parenthesis.
+	 */
+	orig_rpp = rpp;
+
+	while (readtoken() == TNOT) {
+		TRACE(("command: TNOT recognized\n"));
+		negate = !negate;
+	}
+	tokpushback++;
+
+	for (;;) {
+		if (readtoken() == TWORD) {
+			n = (union node *)stalloc(sizeof (struct narg));
+			n->type = NARG;
+			n->narg.text = wordtext;
+			n->narg.backquote = backquotelist;
+			*app = n;
+			app = &n->narg.next;
+		} else if (lasttoken == TREDIR) {
+			*rpp = n = redirnode;
+			rpp = &n->nfile.next;
+			parsefname();	/* read name of redirection file */
+		} else if (lasttoken == TLP && app == &args->narg.next
+					    && rpp == orig_rpp) {
+			/* We have a function */
+			if (readtoken() != TRP)
+				synexpect(TRP);
+#ifdef notdef
+			if (! goodname(n->narg.text))
+				synerror("Bad function name");
+#endif
+			n->type = NDEFUN;
+			n->narg.next = command();
+			goto checkneg;
+		} else {
+			tokpushback++;
+			break;
+		}
+	}
+	*app = NULL;
+	*rpp = NULL;
+	n = (union node *)stalloc(sizeof (struct ncmd));
+	n->type = NCMD;
+	n->ncmd.backgnd = 0;
+	n->ncmd.args = args;
+	n->ncmd.redirect = redir;
+
+checkneg:
+	if (negate) {
+		n2 = (union node *)stalloc(sizeof (struct nnot));
+		n2->type = NNOT;
+		n2->nnot.com = n;
+		return n2;
+	}
+	else
+		return n;
+}
+
+STATIC union node *
+makename(void)
+{
+	union node *n;
+
+	n = (union node *)stalloc(sizeof (struct narg));
+	n->type = NARG;
+	n->narg.next = NULL;
+	n->narg.text = wordtext;
+	n->narg.backquote = backquotelist;
+	return n;
+}
+
+void fixredir(union node *n, const char *text, int err)
+	{
+	TRACE(("Fix redir %s %d\n", text, err));
+	if (!err)
+		n->ndup.vname = NULL;
+
+	if (is_digit(text[0]) && text[1] == '\0')
+		n->ndup.dupfd = digit_val(text[0]);
+	else if (text[0] == '-' && text[1] == '\0')
+		n->ndup.dupfd = -1;
+	else {
+
+		if (err)
+			synerror("Bad fd number");
+		else
+			n->ndup.vname = makename();
+	}
+}
+
+
+STATIC void
+parsefname(void)
+{
+	union node *n = redirnode;
+
+	if (readtoken() != TWORD)
+		synexpect(-1);
+	if (n->type == NHERE) {
+		struct heredoc *here = heredoc;
+		struct heredoc *p;
+		int i;
+
+		if (quoteflag == 0)
+			n->type = NXHERE;
+		TRACE(("Here document %d\n", n->type));
+		if (here->striptabs) {
+			while (*wordtext == '\t')
+				wordtext++;
+		}
+		if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
+			synerror("Illegal eof marker for << redirection");
+		rmescapes(wordtext);
+		here->eofmark = wordtext;
+		here->next = NULL;
+		if (heredoclist == NULL)
+			heredoclist = here;
+		else {
+			for (p = heredoclist ; p->next ; p = p->next);
+			p->next = here;
+		}
+	} else if (n->type == NTOFD || n->type == NFROMFD) {
+		fixredir(n, wordtext, 0);
+	} else {
+		n->nfile.fname = makename();
+	}
+}
+
+
+/*
+ * Input any here documents.
+ */
+
+STATIC void
+parseheredoc(void)
+{
+	struct heredoc *here;
+	union node *n;
+
+	while (heredoclist) {
+		here = heredoclist;
+		heredoclist = here->next;
+		if (needprompt) {
+			setprompt(2);
+			needprompt = 0;
+		}
+		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
+				here->eofmark, here->striptabs);
+		n = (union node *)stalloc(sizeof (struct narg));
+		n->narg.type = NARG;
+		n->narg.next = NULL;
+		n->narg.text = wordtext;
+		n->narg.backquote = backquotelist;
+		here->here->nhere.doc = n;
+	}
+}
+
+STATIC int
+peektoken(void)
+{
+	int t;
+
+	t = readtoken();
+	tokpushback++;
+	return (t);
+}
+
+STATIC int
+readtoken(void)
+{
+	int t;
+	int savecheckkwd = checkkwd;
+#ifdef DEBUG
+	int alreadyseen = tokpushback;
+#endif
+	struct alias *ap;
+
+	top:
+	t = xxreadtoken();
+
+	if (checkkwd) {
+		/*
+		 * eat newlines
+		 */
+		if (checkkwd == 2) {
+			checkkwd = 0;
+			while (t == TNL) {
+				parseheredoc();
+				t = xxreadtoken();
+			}
+		} else
+			checkkwd = 0;
+		/*
+		 * check for keywords and aliases
+		 */
+		if (t == TWORD && !quoteflag)
+		{
+			const char *const *pp;
+
+			for (pp = parsekwd; *pp; pp++) {
+				if (**pp == *wordtext && equal(*pp, wordtext))
+				{
+					lasttoken = t = pp -
+					    parsekwd + KWDOFFSET;
+					TRACE(("keyword %s recognized\n", tokname[t]));
+					goto out;
+				}
+			}
+			if(!noalias &&
+			    (ap = lookupalias(wordtext, 1)) != NULL) {
+				pushstring(ap->val, strlen(ap->val), ap);
+				checkkwd = savecheckkwd;
+				goto top;
+			}
+		}
+out:
+		checkkwd = (t == TNOT) ? savecheckkwd : 0;
+	}
+#ifdef DEBUG
+	if (!alreadyseen)
+	    TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
+	else
+	    TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
+#endif
+	return (t);
+}
+
+
+/*
+ * Read the next input token.
+ * If the token is a word, we set backquotelist to the list of cmds in
+ *	backquotes.  We set quoteflag to true if any part of the word was
+ *	quoted.
+ * If the token is TREDIR, then we set redirnode to a structure containing
+ *	the redirection.
+ * In all cases, the variable startlinno is set to the number of the line
+ *	on which the token starts.
+ *
+ * [Change comment:  here documents and internal procedures]
+ * [Readtoken shouldn't have any arguments.  Perhaps we should make the
+ *  word parsing code into a separate routine.  In this case, readtoken
+ *  doesn't need to have any internal procedures, but parseword does.
+ *  We could also make parseoperator in essence the main routine, and
+ *  have parseword (readtoken1?) handle both words and redirection.]
+ */
+
+#define RETURN(token)	return lasttoken = token
+
+STATIC int
+xxreadtoken(void)
+{
+	int c;
+
+	if (tokpushback) {
+		tokpushback = 0;
+		return lasttoken;
+	}
+	if (needprompt) {
+		setprompt(2);
+		needprompt = 0;
+	}
+	startlinno = plinno;
+	for (;;) {	/* until token or start of word found */
+		c = pgetc_macro();
+		if (c == ' ' || c == '\t')
+			continue;		/* quick check for white space first */
+		switch (c) {
+		case ' ': case '\t':
+			continue;
+		case '#':
+			while ((c = pgetc()) != '\n' && c != PEOF);
+			pungetc();
+			continue;
+		case '\\':
+			if (pgetc() == '\n') {
+				startlinno = ++plinno;
+				if (doprompt)
+					setprompt(2);
+				else
+					setprompt(0);
+				continue;
+			}
+			pungetc();
+			goto breakloop;
+		case '\n':
+			plinno++;
+			needprompt = doprompt;
+			RETURN(TNL);
+		case PEOF:
+			RETURN(TEOF);
+		case '&':
+			if (pgetc() == '&')
+				RETURN(TAND);
+			pungetc();
+			RETURN(TBACKGND);
+		case '|':
+			if (pgetc() == '|')
+				RETURN(TOR);
+			pungetc();
+			RETURN(TPIPE);
+		case ';':
+			if (pgetc() == ';')
+				RETURN(TENDCASE);
+			pungetc();
+			RETURN(TSEMI);
+		case '(':
+			RETURN(TLP);
+		case ')':
+			RETURN(TRP);
+		default:
+			goto breakloop;
+		}
+	}
+breakloop:
+	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
+#undef RETURN
+}
+
+
+
+/*
+ * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
+ * is not NULL, read a here document.  In the latter case, eofmark is the
+ * word which marks the end of the document and striptabs is true if
+ * leading tabs should be stripped from the document.  The argument firstc
+ * is the first character of the input token or document.
+ *
+ * Because C does not have internal subroutines, I have simulated them
+ * using goto's to implement the subroutine linkage.  The following macros
+ * will run code that appears at the end of readtoken1.
+ */
+
+#define CHECKEND()	{goto checkend; checkend_return:;}
+#define PARSEREDIR()	{goto parseredir; parseredir_return:;}
+#define PARSESUB()	{goto parsesub; parsesub_return:;}
+#define PARSEBACKQOLD()	{oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
+#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
+#define	PARSEARITH()	{goto parsearith; parsearith_return:;}
+
+/*
+ * Keep track of nested doublequotes in dblquote and doublequotep.
+ * We use dblquote for the first 32 levels, and we expand to a malloc'ed
+ * region for levels above that. Usually we never need to malloc.
+ * This code assumes that an int is 32 bits. We don't use uint32_t,
+ * because the rest of the code does not.
+ */
+#define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \
+    (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32))))
+
+#define SETDBLQUOTE() \
+    if (varnest < 32) \
+	dblquote |= (1 << varnest); \
+    else \
+	dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32))
+
+#define CLRDBLQUOTE() \
+    if (varnest < 32) \
+	dblquote &= ~(1 << varnest); \
+    else \
+	dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32))
+
+STATIC int
+readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
+{
+	int c = firstc;
+	char *out;
+	int len;
+	char line[EOFMARKLEN + 1];
+	struct nodelist *bqlist;
+	int quotef;
+	int *dblquotep = NULL;
+	size_t maxnest = 32;
+	int dblquote;
+	int varnest;	/* levels of variables expansion */
+	int arinest;	/* levels of arithmetic expansion */
+	int parenlevel;	/* levels of parens in arithmetic */
+	int oldstyle;
+	char const *prevsyntax;	/* syntax before arithmetic */
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &maxnest;
+	(void) &dblquotep;
+	(void) &out;
+	(void) &quotef;
+	(void) &dblquote;
+	(void) &varnest;
+	(void) &arinest;
+	(void) &parenlevel;
+	(void) &oldstyle;
+	(void) &prevsyntax;
+	(void) &syntax;
+#endif
+
+	startlinno = plinno;
+	dblquote = 0;
+	varnest = 0;
+	if (syntax == DQSYNTAX) {
+		SETDBLQUOTE();
+	}
+	quotef = 0;
+	bqlist = NULL;
+	arinest = 0;
+	parenlevel = 0;
+
+	STARTSTACKSTR(out);
+	loop: {	/* for each line, until end of word */
+#if ATTY
+		if (c == '\034' && doprompt
+		 && attyset() && ! equal(termval(), "emacs")) {
+			attyline();
+			if (syntax == BASESYNTAX)
+				return readtoken();
+			c = pgetc();
+			goto loop;
+		}
+#endif
+		CHECKEND();	/* set c to PEOF if at end of here document */
+		for (;;) {	/* until end of line or end of word */
+			CHECKSTRSPACE(4, out);	/* permit 4 calls to USTPUTC */
+			switch(syntax[c]) {
+			case CNL:	/* '\n' */
+				if (syntax == BASESYNTAX)
+					goto endword;	/* exit outer loop */
+				USTPUTC(c, out);
+				plinno++;
+				if (doprompt)
+					setprompt(2);
+				else
+					setprompt(0);
+				c = pgetc();
+				goto loop;		/* continue outer loop */
+			case CWORD:
+				USTPUTC(c, out);
+				break;
+			case CCTL:
+				if (eofmark == NULL || ISDBLQUOTE())
+					USTPUTC(CTLESC, out);
+				USTPUTC(c, out);
+				break;
+			case CBACK:	/* backslash */
+				c = pgetc();
+				if (c == PEOF) {
+					USTPUTC('\\', out);
+					pungetc();
+					break;
+				}
+				if (c == '\n') {
+					if (doprompt)
+						setprompt(2);
+					else
+						setprompt(0);
+					break;
+				}
+				quotef = 1;
+				if (ISDBLQUOTE() && c != '\\' &&
+				    c != '`' && c != '$' &&
+				    (c != '"' || eofmark != NULL))
+					USTPUTC('\\', out);
+				if (SQSYNTAX[c] == CCTL)
+					USTPUTC(CTLESC, out);
+				else if (eofmark == NULL) {
+					USTPUTC(CTLQUOTEMARK, out);
+					USTPUTC(c, out);
+					if (varnest != 0)
+						USTPUTC(CTLQUOTEEND, out);
+					break;
+				}
+				USTPUTC(c, out);
+				break;
+			case CSQUOTE:
+				if (syntax != SQSYNTAX) {
+					if (eofmark == NULL)
+						USTPUTC(CTLQUOTEMARK, out);
+					quotef = 1;
+					syntax = SQSYNTAX;
+					break;
+				}
+				if (eofmark != NULL && arinest == 0 &&
+				    varnest == 0) {
+					/* Ignore inside quoted here document */
+					USTPUTC(c, out);
+					break;
+				}
+				/* End of single quotes... */
+				if (arinest)
+					syntax = ARISYNTAX;
+				else {
+					syntax = BASESYNTAX;
+					if (varnest != 0)
+						USTPUTC(CTLQUOTEEND, out);
+				}
+				break;
+			case CDQUOTE:
+				if (eofmark != NULL && arinest == 0 &&
+				    varnest == 0) {
+					/* Ignore inside here document */
+					USTPUTC(c, out);
+					break;
+				}
+				quotef = 1;
+				if (arinest) {
+					if (ISDBLQUOTE()) {
+						syntax = ARISYNTAX;
+						CLRDBLQUOTE();
+					} else {
+						syntax = DQSYNTAX;
+						SETDBLQUOTE();
+						USTPUTC(CTLQUOTEMARK, out);
+					}
+					break;
+				}
+				if (eofmark != NULL)
+					break;
+				if (ISDBLQUOTE()) {
+					if (varnest != 0)
+						USTPUTC(CTLQUOTEEND, out);
+					syntax = BASESYNTAX;
+					CLRDBLQUOTE();
+				} else {
+					syntax = DQSYNTAX;
+					SETDBLQUOTE();
+					USTPUTC(CTLQUOTEMARK, out);
+				}
+				break;
+			case CVAR:	/* '$' */
+				PARSESUB();		/* parse substitution */
+				break;
+			case CENDVAR:	/* CLOSEBRACE */
+				if (varnest > 0 && !ISDBLQUOTE()) {
+					varnest--;
+					USTPUTC(CTLENDVAR, out);
+				} else {
+					USTPUTC(c, out);
+				}
+				break;
+			case CLP:	/* '(' in arithmetic */
+				parenlevel++;
+				USTPUTC(c, out);
+				break;
+			case CRP:	/* ')' in arithmetic */
+				if (parenlevel > 0) {
+					USTPUTC(c, out);
+					--parenlevel;
+				} else {
+					if (pgetc() == ')') {
+						if (--arinest == 0) {
+							USTPUTC(CTLENDARI, out);
+							syntax = prevsyntax;
+							if (syntax == DQSYNTAX)
+								SETDBLQUOTE();
+							else
+								CLRDBLQUOTE();
+						} else
+							USTPUTC(')', out);
+					} else {
+						/*
+						 * unbalanced parens
+						 *  (don't 2nd guess - no error)
+						 */
+						pungetc();
+						USTPUTC(')', out);
+					}
+				}
+				break;
+			case CBQUOTE:	/* '`' */
+				PARSEBACKQOLD();
+				break;
+			case CEOF:
+				goto endword;		/* exit outer loop */
+			default:
+				if (varnest == 0)
+					goto endword;	/* exit outer loop */
+				USTPUTC(c, out);
+			}
+			c = pgetc_macro();
+		}
+	}
+endword:
+	if (syntax == ARISYNTAX)
+		synerror("Missing '))'");
+	if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
+		synerror("Unterminated quoted string");
+	if (varnest != 0) {
+		startlinno = plinno;
+		/* { */
+		synerror("Missing '}'");
+	}
+	USTPUTC('\0', out);
+	len = out - stackblock();
+	out = stackblock();
+	if (eofmark == NULL) {
+		if ((c == '>' || c == '<')
+		 && quotef == 0
+		 && len <= 2
+		 && (*out == '\0' || is_digit(*out))) {
+			PARSEREDIR();
+			return lasttoken = TREDIR;
+		} else {
+			pungetc();
+		}
+	}
+	quoteflag = quotef;
+	backquotelist = bqlist;
+	grabstackblock(len);
+	wordtext = out;
+	if (dblquotep != NULL)
+	    ckfree(dblquotep);
+	return lasttoken = TWORD;
+/* end of readtoken routine */
+
+
+
+/*
+ * Check to see whether we are at the end of the here document.  When this
+ * is called, c is set to the first character of the next input line.  If
+ * we are at the end of the here document, this routine sets the c to PEOF.
+ */
+
+checkend: {
+	if (eofmark) {
+		if (striptabs) {
+			while (c == '\t')
+				c = pgetc();
+		}
+		if (c == *eofmark) {
+			if (pfgets(line, sizeof line) != NULL) {
+				char *p, *q;
+
+				p = line;
+				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
+				if (*p == '\n' && *q == '\0') {
+					c = PEOF;
+					plinno++;
+					needprompt = doprompt;
+				} else {
+					pushstring(line, strlen(line), NULL);
+				}
+			}
+		}
+	}
+	goto checkend_return;
+}
+
+
+/*
+ * Parse a redirection operator.  The variable "out" points to a string
+ * specifying the fd to be redirected.  The variable "c" contains the
+ * first character of the redirection operator.
+ */
+
+parseredir: {
+	char fd = *out;
+	union node *np;
+
+	np = (union node *)stalloc(sizeof (struct nfile));
+	if (c == '>') {
+		np->nfile.fd = 1;
+		c = pgetc();
+		if (c == '>')
+			np->type = NAPPEND;
+		else if (c == '|')
+			np->type = NCLOBBER;
+		else if (c == '&')
+			np->type = NTOFD;
+		else {
+			np->type = NTO;
+			pungetc();
+		}
+	} else {	/* c == '<' */
+		np->nfile.fd = 0;
+		switch (c = pgetc()) {
+		case '<':
+			if (sizeof (struct nfile) != sizeof (struct nhere)) {
+				np = (union node *)stalloc(sizeof (struct nhere));
+				np->nfile.fd = 0;
+			}
+			np->type = NHERE;
+			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
+			heredoc->here = np;
+			if ((c = pgetc()) == '-') {
+				heredoc->striptabs = 1;
+			} else {
+				heredoc->striptabs = 0;
+				pungetc();
+			}
+			break;
+
+		case '&':
+			np->type = NFROMFD;
+			break;
+
+		case '>':
+			np->type = NFROMTO;
+			break;
+
+		default:
+			np->type = NFROM;
+			pungetc();
+			break;
+		}
+	}
+	if (fd != '\0')
+		np->nfile.fd = digit_val(fd);
+	redirnode = np;
+	goto parseredir_return;
+}
+
+
+/*
+ * Parse a substitution.  At this point, we have read the dollar sign
+ * and nothing else.
+ */
+
+parsesub: {
+	int subtype;
+	int typeloc;
+	int flags;
+	char *p;
+	static const char types[] = "}-+?=";
+
+	c = pgetc();
+	if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
+		USTPUTC('$', out);
+		pungetc();
+	} else if (c == '(') {	/* $(command) or $((arith)) */
+		if (pgetc() == '(') {
+			PARSEARITH();
+		} else {
+			pungetc();
+			PARSEBACKQNEW();
+		}
+	} else {
+		USTPUTC(CTLVAR, out);
+		typeloc = out - stackblock();
+		USTPUTC(VSNORMAL, out);
+		subtype = VSNORMAL;
+		if (c == OPENBRACE) {
+			c = pgetc();
+			if (c == '#') {
+				if ((c = pgetc()) == CLOSEBRACE)
+					c = '#';
+				else
+					subtype = VSLENGTH;
+			}
+			else
+				subtype = 0;
+		}
+		if (is_name(c)) {
+			do {
+				STPUTC(c, out);
+				c = pgetc();
+			} while (is_in_name(c));
+		} else if (is_digit(c)) {
+			do {
+				USTPUTC(c, out);
+				c = pgetc();
+			} while (is_digit(c));
+		}
+		else if (is_special(c)) {
+			USTPUTC(c, out);
+			c = pgetc();
+		}
+		else
+badsub:			synerror("Bad substitution");
+
+		STPUTC('=', out);
+		flags = 0;
+		if (subtype == 0) {
+			switch (c) {
+			case ':':
+				flags = VSNUL;
+				c = pgetc();
+				/*FALLTHROUGH*/
+			default:
+				p = strchr(types, c);
+				if (p == NULL)
+					goto badsub;
+				subtype = p - types + VSNORMAL;
+				break;
+			case '%':
+			case '#':
+				{
+					int cc = c;
+					subtype = c == '#' ? VSTRIMLEFT :
+							     VSTRIMRIGHT;
+					c = pgetc();
+					if (c == cc)
+						subtype++;
+					else
+						pungetc();
+					break;
+				}
+			}
+		} else {
+			pungetc();
+		}
+		if (ISDBLQUOTE() || arinest)
+			flags |= VSQUOTE;
+		*(stackblock() + typeloc) = subtype | flags;
+		if (subtype != VSNORMAL) {
+			varnest++;
+			if (varnest >= maxnest) {
+				dblquotep = ckrealloc(dblquotep, maxnest / 8);
+				dblquotep[(maxnest / 32) - 1] = 0;
+				maxnest += 32;
+			}
+		}
+	}
+	goto parsesub_return;
+}
+
+
+/*
+ * Called to parse command substitutions.  Newstyle is set if the command
+ * is enclosed inside $(...); nlpp is a pointer to the head of the linked
+ * list of commands (passed by reference), and savelen is the number of
+ * characters on the top of the stack which must be preserved.
+ */
+
+parsebackq: {
+	struct nodelist **nlpp;
+	int savepbq;
+	union node *n;
+	char *volatile str;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	int savelen;
+	int saveprompt;
+#ifdef __GNUC__
+	(void) &saveprompt;
+#endif
+
+	savepbq = parsebackquote;
+	if (setjmp(jmploc.loc)) {
+		if (str)
+			ckfree(str);
+		parsebackquote = 0;
+		handler = savehandler;
+		longjmp(handler->loc, 1);
+	}
+	INTOFF;
+	str = NULL;
+	savelen = out - stackblock();
+	if (savelen > 0) {
+		str = ckmalloc(savelen);
+		memcpy(str, stackblock(), savelen);
+	}
+	savehandler = handler;
+	handler = &jmploc;
+	INTON;
+        if (oldstyle) {
+                /* We must read until the closing backquote, giving special
+                   treatment to some slashes, and then push the string and
+                   reread it as input, interpreting it normally.  */
+                char *pout;
+                int pc;
+                int psavelen;
+                char *pstr;
+
+
+                STARTSTACKSTR(pout);
+		for (;;) {
+			if (needprompt) {
+				setprompt(2);
+				needprompt = 0;
+			}
+			switch (pc = pgetc()) {
+			case '`':
+				goto done;
+
+			case '\\':
+                                if ((pc = pgetc()) == '\n') {
+					plinno++;
+					if (doprompt)
+						setprompt(2);
+					else
+						setprompt(0);
+					/*
+					 * If eating a newline, avoid putting
+					 * the newline into the new character
+					 * stream (via the STPUTC after the
+					 * switch).
+					 */
+					continue;
+				}
+                                if (pc != '\\' && pc != '`' && pc != '$'
+                                    && (!ISDBLQUOTE() || pc != '"'))
+                                        STPUTC('\\', pout);
+				break;
+
+			case '\n':
+				plinno++;
+				needprompt = doprompt;
+				break;
+
+			case PEOF:
+			        startlinno = plinno;
+				synerror("EOF in backquote substitution");
+ 				break;
+
+			default:
+				break;
+			}
+			STPUTC(pc, pout);
+                }
+done:
+                STPUTC('\0', pout);
+                psavelen = pout - stackblock();
+                if (psavelen > 0) {
+			pstr = grabstackstr(pout);
+			setinputstring(pstr, 1);
+                }
+        }
+	nlpp = &bqlist;
+	while (*nlpp)
+		nlpp = &(*nlpp)->next;
+	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+	(*nlpp)->next = NULL;
+	parsebackquote = oldstyle;
+
+	if (oldstyle) {
+		saveprompt = doprompt;
+		doprompt = 0;
+	}
+
+	n = list(0);
+
+	if (oldstyle)
+		doprompt = saveprompt;
+	else {
+		if (readtoken() != TRP)
+			synexpect(TRP);
+	}
+
+	(*nlpp)->n = n;
+        if (oldstyle) {
+		/*
+		 * Start reading from old file again, ignoring any pushed back
+		 * tokens left from the backquote parsing
+		 */
+                popfile();
+		tokpushback = 0;
+	}
+	while (stackblocksize() <= savelen)
+		growstackblock();
+	STARTSTACKSTR(out);
+	if (str) {
+		memcpy(out, str, savelen);
+		STADJUST(savelen, out);
+		INTOFF;
+		ckfree(str);
+		str = NULL;
+		INTON;
+	}
+	parsebackquote = savepbq;
+	handler = savehandler;
+	if (arinest || ISDBLQUOTE())
+		USTPUTC(CTLBACKQ | CTLQUOTE, out);
+	else
+		USTPUTC(CTLBACKQ, out);
+	if (oldstyle)
+		goto parsebackq_oldreturn;
+	else
+		goto parsebackq_newreturn;
+}
+
+/*
+ * Parse an arithmetic expansion (indicate start of one and set state)
+ */
+parsearith: {
+
+	if (++arinest == 1) {
+		prevsyntax = syntax;
+		syntax = ARISYNTAX;
+		USTPUTC(CTLARI, out);
+		if (ISDBLQUOTE())
+			USTPUTC('"',out);
+		else
+			USTPUTC(' ',out);
+	} else {
+		/*
+		 * we collapse embedded arithmetic expansion to
+		 * parenthesis, which should be equivalent
+		 */
+		USTPUTC('(', out);
+	}
+	goto parsearith_return;
+}
+
+} /* end of readtoken */
+
+
+
+#ifdef mkinit
+RESET {
+	tokpushback = 0;
+	checkkwd = 0;
+}
+#endif
+
+/*
+ * Returns true if the text contains nothing to expand (no dollar signs
+ * or backquotes).
+ */
+
+STATIC int
+noexpand(char *text)
+{
+	char *p;
+	char c;
+
+	p = text;
+	while ((c = *p++) != '\0') {
+		if (c == CTLQUOTEMARK)
+			continue;
+		if (c == CTLESC)
+			p++;
+		else if (BASESYNTAX[(int)c] == CCTL)
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Return true if the argument is a legal variable name (a letter or
+ * underscore followed by zero or more letters, underscores, and digits).
+ */
+
+int
+goodname(char *name)
+	{
+	char *p;
+
+	p = name;
+	if (! is_name(*p))
+		return 0;
+	while (*++p) {
+		if (! is_in_name(*p))
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Called when an unexpected token is read during the parse.  The argument
+ * is the token that is expected, or -1 if more than one type of token can
+ * occur at this point.
+ */
+
+STATIC void
+synexpect(int token)
+{
+	char msg[64];
+
+	if (token >= 0) {
+		fmtstr(msg, 64, "%s unexpected (expecting %s)",
+			tokname[lasttoken], tokname[token]);
+	} else {
+		fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
+	}
+	synerror(msg);
+	/* NOTREACHED */
+}
+
+
+STATIC void
+synerror(const char *msg)
+{
+	if (commandname)
+		outfmt(&errout, "%s: %d: ", commandname, startlinno);
+	outfmt(&errout, "Syntax error: %s\n", msg);
+	error((char *)NULL);
+	/* NOTREACHED */
+}
+
+STATIC void
+setprompt(int which)
+{
+	whichprompt = which;
+
+#ifndef SMALL
+	if (!el)
+#endif
+		out2str(getprompt(NULL));
+}
+
+/*
+ * called by editline -- any expansions to the prompt
+ *    should be added here.
+ */
+const char *
+getprompt(void *unused)
+	{
+	switch (whichprompt) {
+	case 0:
+		return "";
+	case 1:
+		return ps1val();
+	case 2:
+		return ps2val();
+	default:
+		return "<internal prompt error>";
+	}
+}
Index: /tags/kBuild-0.1.4/src/ash/parser.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/parser.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/parser.h	(revision 1780)
@@ -0,0 +1,82 @@
+/*	$NetBSD: parser.h,v 1.17 2004/06/26 22:09:49 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)parser.h	8.3 (Berkeley) 5/4/95
+ */
+
+/* control characters in argument strings */
+#define CTL_FIRST '\201'	/* first 'special' character */
+#define CTLESC '\201'		/* escape next character */
+#define CTLVAR '\202'		/* variable defn */
+#define CTLENDVAR '\203'
+#define CTLBACKQ '\204'
+#define CTLQUOTE 01		/* ored with CTLBACKQ code if in quotes */
+/*	CTLBACKQ | CTLQUOTE == '\205' */
+#define	CTLARI	'\206'		/* arithmetic expression */
+#define	CTLENDARI '\207'
+#define	CTLQUOTEMARK '\210'
+#define	CTLQUOTEEND '\211'	/* only inside ${...} */
+#define	CTL_LAST '\211'		/* last 'special' character */
+
+/* variable substitution byte (follows CTLVAR) */
+#define VSTYPE	0x0f		/* type of variable substitution */
+#define VSNUL	0x10		/* colon--treat the empty string as unset */
+#define VSQUOTE 0x80		/* inside double quotes--suppress splitting */
+
+/* values of VSTYPE field */
+#define VSNORMAL	0x1		/* normal variable:  $var or ${var} */
+#define VSMINUS		0x2		/* ${var-text} */
+#define VSPLUS		0x3		/* ${var+text} */
+#define VSQUESTION	0x4		/* ${var?message} */
+#define VSASSIGN	0x5		/* ${var=text} */
+#define VSTRIMLEFT	0x6		/* ${var#pattern} */
+#define VSTRIMLEFTMAX	0x7		/* ${var##pattern} */
+#define VSTRIMRIGHT	0x8		/* ${var%pattern} */
+#define VSTRIMRIGHTMAX 	0x9		/* ${var%%pattern} */
+#define VSLENGTH	0xa		/* ${#var} */
+
+
+/*
+ * NEOF is returned by parsecmd when it encounters an end of file.  It
+ * must be distinct from NULL, so we use the address of a variable that
+ * happens to be handy.
+ */
+extern int tokpushback;
+#define NEOF ((union node *)&tokpushback)
+extern int whichprompt;		/* 1 == PS1, 2 == PS2 */
+
+
+union node *parsecmd(int);
+void fixredir(union node *, const char *, int);
+int goodname(char *);
+const char *getprompt(void *);
Index: /tags/kBuild-0.1.4/src/ash/redir.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/redir.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/redir.c	(revision 1780)
@@ -0,0 +1,390 @@
+/*	$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)redir.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>	/* PIPE_BUF */
+#include <signal.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/*
+ * Code for dealing with input/output redirection.
+ */
+
+#include "main.h"
+#include "shell.h"
+#include "nodes.h"
+#include "jobs.h"
+#include "options.h"
+#include "expand.h"
+#include "redir.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+
+
+#define EMPTY -2		/* marks an unused slot in redirtab */
+#ifndef PIPE_BUF
+# define PIPESIZE 4096		/* amount of buffering in a pipe */
+#else
+# define PIPESIZE PIPE_BUF
+#endif
+
+
+MKINIT
+struct redirtab {
+	struct redirtab *next;
+	short renamed[10];
+};
+
+
+MKINIT struct redirtab *redirlist;
+
+/*
+ * We keep track of whether or not fd0 has been redirected.  This is for
+ * background commands, where we want to redirect fd0 to /dev/null only
+ * if it hasn't already been redirected.
+*/
+int fd0_redirected = 0;
+
+STATIC void openredirect(union node *, char[10], int);
+STATIC int openhere(union node *);
+
+
+/*
+ * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
+ * old file descriptors are stashed away so that the redirection can be
+ * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
+ * standard output, and the standard error if it becomes a duplicate of
+ * stdout, is saved in memory.
+ */
+
+void
+redirect(union node *redir, int flags)
+{
+	union node *n;
+	struct redirtab *sv = NULL;
+	int i;
+	int fd;
+	int try;
+	char memory[10];	/* file descriptors to write to memory */
+
+	for (i = 10 ; --i >= 0 ; )
+		memory[i] = 0;
+	memory[1] = flags & REDIR_BACKQ;
+	if (flags & REDIR_PUSH) {
+		/* We don't have to worry about REDIR_VFORK here, as
+		 * flags & REDIR_PUSH is never true if REDIR_VFORK is set.
+		 */
+		sv = ckmalloc(sizeof (struct redirtab));
+		for (i = 0 ; i < 10 ; i++)
+			sv->renamed[i] = EMPTY;
+		sv->next = redirlist;
+		redirlist = sv;
+	}
+	for (n = redir ; n ; n = n->nfile.next) {
+		fd = n->nfile.fd;
+		try = 0;
+		if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
+		    n->ndup.dupfd == fd)
+			continue; /* redirect from/to same file descriptor */
+
+		if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
+			INTOFF;
+again:
+			if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
+				switch (errno) {
+				case EBADF:
+					if (!try) {
+						openredirect(n, memory, flags);
+						try++;
+						goto again;
+					}
+					/* FALLTHROUGH*/
+				default:
+					INTON;
+					error("%d: %s", fd, strerror(errno));
+					/* NOTREACHED */
+				}
+			}
+			if (!try) {
+				sv->renamed[fd] = i;
+				close(fd);
+			}
+			INTON;
+		} else {
+			close(fd);
+		}
+                if (fd == 0)
+                        fd0_redirected++;
+		if (!try)
+			openredirect(n, memory, flags);
+	}
+	if (memory[1])
+		out1 = &memout;
+	if (memory[2])
+		out2 = &memout;
+}
+
+
+STATIC void
+openredirect(union node *redir, char memory[10], int flags)
+{
+	int fd = redir->nfile.fd;
+	char *fname;
+	int f;
+	int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags;
+
+	/*
+	 * We suppress interrupts so that we won't leave open file
+	 * descriptors around.  This may not be such a good idea because
+	 * an open of a device or a fifo can block indefinitely.
+	 */
+	INTOFF;
+	memory[fd] = 0;
+	switch (redir->nfile.type) {
+	case NFROM:
+		fname = redir->nfile.expfname;
+		if (flags & REDIR_VFORK)
+			eflags = O_NONBLOCK;
+		else
+			eflags = 0;
+		if ((f = open(fname, O_RDONLY|eflags)) < 0)
+			goto eopen;
+		if (eflags)
+			(void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags);
+		break;
+	case NFROMTO:
+		fname = redir->nfile.expfname;
+		if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NTO:
+		if (Cflag)
+			oflags |= O_EXCL;
+		/* FALLTHROUGH */
+	case NCLOBBER:
+		fname = redir->nfile.expfname;
+		if ((f = open(fname, oflags, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NAPPEND:
+		fname = redir->nfile.expfname;
+		if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NTOFD:
+	case NFROMFD:
+		if (redir->ndup.dupfd >= 0) {	/* if not ">&-" */
+			if (memory[redir->ndup.dupfd])
+				memory[fd] = 1;
+			else
+				copyfd(redir->ndup.dupfd, fd);
+		}
+		INTON;
+		return;
+	case NHERE:
+	case NXHERE:
+		f = openhere(redir);
+		break;
+	default:
+		abort();
+	}
+
+	if (f != fd) {
+		copyfd(f, fd);
+		close(f);
+	}
+	INTON;
+	return;
+ecreate:
+	error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
+eopen:
+	error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
+}
+
+
+/*
+ * Handle here documents.  Normally we fork off a process to write the
+ * data to a pipe.  If the document is short, we can stuff the data in
+ * the pipe without forking.
+ */
+
+STATIC int
+openhere(union node *redir)
+{
+	int pip[2];
+	int len = 0;
+
+	if (pipe(pip) < 0)
+		error("Pipe call failed");
+	if (redir->type == NHERE) {
+		len = strlen(redir->nhere.doc->narg.text);
+		if (len <= PIPESIZE) {
+			xwrite(pip[1], redir->nhere.doc->narg.text, len);
+			goto out;
+		}
+	}
+	if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
+		close(pip[0]);
+		signal(SIGINT, SIG_IGN);
+		signal(SIGQUIT, SIG_IGN);
+		signal(SIGHUP, SIG_IGN);
+#ifdef SIGTSTP
+		signal(SIGTSTP, SIG_IGN);
+#endif
+		signal(SIGPIPE, SIG_DFL);
+		if (redir->type == NHERE)
+			xwrite(pip[1], redir->nhere.doc->narg.text, len);
+		else
+			expandhere(redir->nhere.doc, pip[1]);
+		_exit(0);
+	}
+out:
+	close(pip[1]);
+	return pip[0];
+}
+
+
+
+/*
+ * Undo the effects of the last redirection.
+ */
+
+void
+popredir(void)
+{
+	struct redirtab *rp = redirlist;
+	int i;
+
+	for (i = 0 ; i < 10 ; i++) {
+		if (rp->renamed[i] != EMPTY) {
+                        if (i == 0)
+                                fd0_redirected--;
+			close(i);
+			if (rp->renamed[i] >= 0) {
+				copyfd(rp->renamed[i], i);
+				close(rp->renamed[i]);
+			}
+		}
+	}
+	INTOFF;
+	redirlist = rp->next;
+	ckfree(rp);
+	INTON;
+}
+
+/*
+ * Undo all redirections.  Called on error or interrupt.
+ */
+
+#ifdef mkinit
+
+INCLUDE "redir.h"
+
+RESET {
+	while (redirlist)
+		popredir();
+}
+
+SHELLPROC {
+	clearredir(0);
+}
+
+#endif
+
+/* Return true if fd 0 has already been redirected at least once.  */
+int
+fd0_redirected_p () {
+        return fd0_redirected != 0;
+}
+
+/*
+ * Discard all saved file descriptors.
+ */
+
+void
+clearredir(vforked)
+	int vforked;
+{
+	struct redirtab *rp;
+	int i;
+
+	for (rp = redirlist ; rp ; rp = rp->next) {
+		for (i = 0 ; i < 10 ; i++) {
+			if (rp->renamed[i] >= 0) {
+				close(rp->renamed[i]);
+			}
+			if (!vforked)
+				rp->renamed[i] = EMPTY;
+		}
+	}
+}
+
+
+
+/*
+ * Copy a file descriptor to be >= to.  Returns -1
+ * if the source file descriptor is closed, EMPTY if there are no unused
+ * file descriptors left.
+ */
+
+int
+copyfd(int from, int to)
+{
+	int newfd;
+
+	newfd = fcntl(from, F_DUPFD, to);
+	if (newfd < 0) {
+		if (errno == EMFILE)
+			return EMPTY;
+		else
+			error("%d: %s", from, strerror(errno));
+	}
+	return newfd;
+}
Index: /tags/kBuild-0.1.4/src/ash/redir.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/redir.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/redir.h	(revision 1780)
@@ -0,0 +1,48 @@
+/*	$NetBSD: redir.h,v 1.15 2003/08/07 09:05:37 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)redir.h	8.2 (Berkeley) 5/4/95
+ */
+
+/* flags passed to redirect */
+#define REDIR_PUSH 01		/* save previous values of file descriptors */
+#define REDIR_BACKQ 02		/* save the command output in memory */
+#define REDIR_VFORK 04		/* running under vfork(2), be careful */
+
+union node;
+void redirect(union node *, int);
+void popredir(void);
+int fd0_redirected_p(void);
+void clearredir(int);
+int copyfd(int, int);
+
Index: /tags/kBuild-0.1.4/src/ash/setmode.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/setmode.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/setmode.c	(revision 1780)
@@ -0,0 +1,501 @@
+/*	$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Dave Borman at Cray Research, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>*/
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)setmode.c	8.2 (Berkeley) 3/25/94";
+#else
+__RCSID("$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*#include "namespace.h"*/
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#else
+#include "mscfakes.h"
+#endif 
+
+#ifdef SETMODE_DEBUG
+#include <stdio.h>
+#endif
+
+/*#ifdef __weak_alias
+__weak_alias(getmode,_getmode)
+__weak_alias(setmode,_setmode)
+#endif*/
+
+#define	SET_LEN	6		/* initial # of bitcmd struct to malloc */
+#define	SET_LEN_INCR 4		/* # of bitcmd structs to add as needed */
+
+typedef struct bitcmd {
+	char	cmd;
+	char	cmd2;
+	mode_t	bits;
+} BITCMD;
+
+#define	CMD2_CLR	0x01
+#define	CMD2_SET	0x02
+#define	CMD2_GBITS	0x04
+#define	CMD2_OBITS	0x08
+#define	CMD2_UBITS	0x10
+
+static BITCMD	*addcmd(BITCMD *, int, int, int, u_int);
+static void	 compress_mode(BITCMD *);
+#ifdef SETMODE_DEBUG
+static void	 dumpmode(BITCMD *);
+#endif
+
+#ifndef _DIAGASSERT
+# define _DIAGASSERT assert
+#endif 
+
+#ifndef S_ISTXT
+# ifdef S_ISVTX
+#  define S_ISTXT S_ISVTX
+# else
+#  define S_ISTXT 0
+# endif
+#endif /* !S_ISTXT */
+
+/*
+ * Given the old mode and an array of bitcmd structures, apply the operations
+ * described in the bitcmd structures to the old mode, and return the new mode.
+ * Note that there is no '=' command; a strict assignment is just a '-' (clear
+ * bits) followed by a '+' (set bits).
+ */
+mode_t
+getmode(bbox, omode)
+	const void *bbox;
+	mode_t omode;
+{
+	const BITCMD *set;
+	mode_t clrval, newmode, value;
+
+	_DIAGASSERT(bbox != NULL);
+
+	set = (const BITCMD *)bbox;
+	newmode = omode;
+	for (value = 0;; set++)
+		switch(set->cmd) {
+		/*
+		 * When copying the user, group or other bits around, we "know"
+		 * where the bits are in the mode so that we can do shifts to
+		 * copy them around.  If we don't use shifts, it gets real
+		 * grundgy with lots of single bit checks and bit sets.
+		 */
+		case 'u':
+			value = (newmode & S_IRWXU) >> 6;
+			goto common;
+
+		case 'g':
+			value = (newmode & S_IRWXG) >> 3;
+			goto common;
+
+		case 'o':
+			value = newmode & S_IRWXO;
+common:			if (set->cmd2 & CMD2_CLR) {
+				clrval =
+				    (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
+				if (set->cmd2 & CMD2_UBITS)
+					newmode &= ~((clrval<<6) & set->bits);
+				if (set->cmd2 & CMD2_GBITS)
+					newmode &= ~((clrval<<3) & set->bits);
+				if (set->cmd2 & CMD2_OBITS)
+					newmode &= ~(clrval & set->bits);
+			}
+			if (set->cmd2 & CMD2_SET) {
+				if (set->cmd2 & CMD2_UBITS)
+					newmode |= (value<<6) & set->bits;
+				if (set->cmd2 & CMD2_GBITS)
+					newmode |= (value<<3) & set->bits;
+				if (set->cmd2 & CMD2_OBITS)
+					newmode |= value & set->bits;
+			}
+			break;
+
+		case '+':
+			newmode |= set->bits;
+			break;
+
+		case '-':
+			newmode &= ~set->bits;
+			break;
+
+		case 'X':
+			if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
+				newmode |= set->bits;
+			break;
+
+		case '\0':
+		default:
+#ifdef SETMODE_DEBUG
+			(void)printf("getmode:%04o -> %04o\n", omode, newmode);
+#endif
+			return (newmode);
+		}
+}
+
+#define	ADDCMD(a, b, c, d) do {						\
+	if (set >= endset) {						\
+		BITCMD *newset;						\
+		setlen += SET_LEN_INCR;					\
+		newset = realloc(saveset, sizeof(BITCMD) * setlen);	\
+		if (newset == NULL) {					\
+			free(saveset);					\
+			return (NULL);					\
+		}							\
+		set = newset + (set - saveset);				\
+		saveset = newset;					\
+		endset = newset + (setlen - 2);				\
+	}								\
+	set = addcmd(set, (a), (b), (c), (d));				\
+} while (/*CONSTCOND*/0)
+
+#define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+
+void *
+setmode(p)
+	const char *p;
+{
+	int perm, who;
+	char op, *ep;
+	BITCMD *set, *saveset, *endset;
+#ifndef _MSC_VER
+	sigset_t signset, sigoset;
+#endif
+	mode_t mask;
+	int equalopdone = 0;	/* pacify gcc */
+	int permXbits, setlen;
+
+	if (!*p)
+		return (NULL);
+
+	/*
+	 * Get a copy of the mask for the permissions that are mask relative.
+	 * Flip the bits, we want what's not set.  Since it's possible that
+	 * the caller is opening files inside a signal handler, protect them
+	 * as best we can.
+	 */
+#ifndef _MSC_VER
+	sigfillset(&signset);
+	(void)sigprocmask(SIG_BLOCK, &signset, &sigoset);
+#endif 
+	(void)umask(mask = umask(0));
+	mask = ~mask;
+#ifndef _MSC_VER
+	(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
+#endif
+
+	setlen = SET_LEN + 2;
+	
+	if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
+		return (NULL);
+	saveset = set;
+	endset = set + (setlen - 2);
+
+	/*
+	 * If an absolute number, get it and return; disallow non-octal digits
+	 * or illegal bits.
+	 */
+	if (isdigit((unsigned char)*p)) {
+		perm = (mode_t)strtol(p, &ep, 8);
+		if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
+			free(saveset);
+			return (NULL);
+		}
+		ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
+		set->cmd = 0;
+		return (saveset);
+	}
+
+	/*
+	 * Build list of structures to set/clear/copy bits as described by
+	 * each clause of the symbolic mode.
+	 */
+	for (;;) {
+		/* First, find out which bits might be modified. */
+		for (who = 0;; ++p) {
+			switch (*p) {
+			case 'a':
+				who |= STANDARD_BITS;
+				break;
+			case 'u':
+				who |= S_ISUID|S_IRWXU;
+				break;
+			case 'g':
+				who |= S_ISGID|S_IRWXG;
+				break;
+			case 'o':
+				who |= S_IRWXO;
+				break;
+			default:
+				goto getop;
+			}
+		}
+
+getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
+			free(saveset);
+			return (NULL);
+		}
+		if (op == '=')
+			equalopdone = 0;
+
+		who &= ~S_ISTXT;
+		for (perm = 0, permXbits = 0;; ++p) {
+			switch (*p) {
+			case 'r':
+				perm |= S_IRUSR|S_IRGRP|S_IROTH;
+				break;
+			case 's':
+				/*
+				 * If specific bits where requested and 
+				 * only "other" bits ignore set-id. 
+				 */
+				if (who == 0 || (who & ~S_IRWXO))
+					perm |= S_ISUID|S_ISGID;
+				break;
+			case 't':
+				/*
+				 * If specific bits where requested and 
+				 * only "other" bits ignore set-id. 
+				 */
+				if (who == 0 || (who & ~S_IRWXO)) {
+					who |= S_ISTXT;
+					perm |= S_ISTXT;
+				}
+				break;
+			case 'w':
+				perm |= S_IWUSR|S_IWGRP|S_IWOTH;
+				break;
+			case 'X':
+				permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
+				break;
+			case 'x':
+				perm |= S_IXUSR|S_IXGRP|S_IXOTH;
+				break;
+			case 'u':
+			case 'g':
+			case 'o':
+				/*
+				 * When ever we hit 'u', 'g', or 'o', we have
+				 * to flush out any partial mode that we have,
+				 * and then do the copying of the mode bits.
+				 */
+				if (perm) {
+					ADDCMD(op, who, perm, mask);
+					perm = 0;
+				}
+				if (op == '=')
+					equalopdone = 1;
+				if (op == '+' && permXbits) {
+					ADDCMD('X', who, permXbits, mask);
+					permXbits = 0;
+				}
+				ADDCMD(*p, who, op, mask);
+				break;
+
+			default:
+				/*
+				 * Add any permissions that we haven't already
+				 * done.
+				 */
+				if (perm || (op == '=' && !equalopdone)) {
+					if (op == '=')
+						equalopdone = 1;
+					ADDCMD(op, who, perm, mask);
+					perm = 0;
+				}
+				if (permXbits) {
+					ADDCMD('X', who, permXbits, mask);
+					permXbits = 0;
+				}
+				goto apply;
+			}
+		}
+
+apply:		if (!*p)
+			break;
+		if (*p != ',')
+			goto getop;
+		++p;
+	}
+	set->cmd = 0;
+#ifdef SETMODE_DEBUG
+	(void)printf("Before compress_mode()\n");
+	dumpmode(saveset);
+#endif
+	compress_mode(saveset);
+#ifdef SETMODE_DEBUG
+	(void)printf("After compress_mode()\n");
+	dumpmode(saveset);
+#endif
+	return (saveset);
+}
+
+static BITCMD *
+addcmd(set, op, who, oparg, mask)
+	BITCMD *set;
+	int oparg, who;
+	int op;
+	u_int mask;
+{
+
+	_DIAGASSERT(set != NULL);
+
+	switch (op) {
+	case '=':
+		set->cmd = '-';
+		set->bits = who ? who : STANDARD_BITS;
+		set++;
+
+		op = '+';
+		/* FALLTHROUGH */
+	case '+':
+	case '-':
+	case 'X':
+		set->cmd = op;
+		set->bits = (who ? who : mask) & oparg;
+		break;
+
+	case 'u':
+	case 'g':
+	case 'o':
+		set->cmd = op;
+		if (who) {
+			set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
+				    ((who & S_IRGRP) ? CMD2_GBITS : 0) |
+				    ((who & S_IROTH) ? CMD2_OBITS : 0);
+			set->bits = (mode_t)~0;
+		} else {
+			set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
+			set->bits = mask;
+		}
+	
+		if (oparg == '+')
+			set->cmd2 |= CMD2_SET;
+		else if (oparg == '-')
+			set->cmd2 |= CMD2_CLR;
+		else if (oparg == '=')
+			set->cmd2 |= CMD2_SET|CMD2_CLR;
+		break;
+	}
+	return (set + 1);
+}
+
+#ifdef SETMODE_DEBUG
+static void
+dumpmode(set)
+	BITCMD *set;
+{
+
+	_DIAGASSERT(set != NULL);
+
+	for (; set->cmd; ++set)
+		(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
+		    set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
+		    set->cmd2 & CMD2_CLR ? " CLR" : "",
+		    set->cmd2 & CMD2_SET ? " SET" : "",
+		    set->cmd2 & CMD2_UBITS ? " UBITS" : "",
+		    set->cmd2 & CMD2_GBITS ? " GBITS" : "",
+		    set->cmd2 & CMD2_OBITS ? " OBITS" : "");
+}
+#endif
+
+/*
+ * Given an array of bitcmd structures, compress by compacting consecutive
+ * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
+ * 'g' and 'o' commands continue to be separate.  They could probably be 
+ * compacted, but it's not worth the effort.
+ */
+static void
+compress_mode(set)
+	BITCMD *set;
+{
+	BITCMD *nset;
+	int setbits, clrbits, Xbits, op;
+
+	_DIAGASSERT(set != NULL);
+
+	for (nset = set;;) {
+		/* Copy over any 'u', 'g' and 'o' commands. */
+		while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
+			*set++ = *nset++;
+			if (!op)
+				return;
+		}
+
+		for (setbits = clrbits = Xbits = 0;; nset++) {
+			if ((op = nset->cmd) == '-') {
+				clrbits |= nset->bits;
+				setbits &= ~nset->bits;
+				Xbits &= ~nset->bits;
+			} else if (op == '+') {
+				setbits |= nset->bits;
+				clrbits &= ~nset->bits;
+				Xbits &= ~nset->bits;
+			} else if (op == 'X')
+				Xbits |= nset->bits & ~setbits;
+			else
+				break;
+		}
+		if (clrbits) {
+			set->cmd = '-';
+			set->cmd2 = 0;
+			set->bits = clrbits;
+			set++;
+		}
+		if (setbits) {
+			set->cmd = '+';
+			set->cmd2 = 0;
+			set->bits = setbits;
+			set++;
+		}
+		if (Xbits) {
+			set->cmd = 'X';
+			set->cmd2 = 0;
+			set->bits = Xbits;
+			set++;
+		}
+	}
+}
Index: /tags/kBuild-0.1.4/src/ash/sh.1
===================================================================
--- /tags/kBuild-0.1.4/src/ash/sh.1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/sh.1	(revision 1780)
@@ -0,0 +1,1949 @@
+.\"	$NetBSD: sh.1,v 1.80 2005/05/24 00:03:52 wiz Exp $
+.\" Copyright (c) 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Kenneth Almquist.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)sh.1	8.6 (Berkeley) 5/4/95
+.\"
+.Dd May 7, 2005
+.Os
+.Dt SH 1
+.Sh NAME
+.Nm sh
+.Nd command interpreter (shell)
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Op Ar command_file Oo Ar argument ... Oc
+.Ek
+.Nm
+.Fl c
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Ar command_string
+.Op Ar command_name Oo Ar argument ... Oc
+.Ek
+.Nm
+.Fl s
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Op Ar argument ...
+.Ek
+.Sh DESCRIPTION
+.Nm
+is the standard command interpreter for the system.
+The current version of
+.Nm
+is in the process of being changed to conform with the
+.Tn POSIX
+1003.2 and 1003.2a specifications for the shell.
+This version has many
+features which make it appear similar in some respects to the Korn shell,
+but it is not a Korn shell clone (see
+.Xr ksh 1 ) .
+Only features designated by
+.Tn POSIX ,
+plus a few Berkeley extensions, are being incorporated into this shell.
+.\" We expect
+.\" .Tn POSIX
+.\" conformance by the time 4.4 BSD is released.
+This man page is not intended
+to be a tutorial or a complete specification of the shell.
+.Ss Overview
+The shell is a command that reads lines from either a file or the
+terminal, interprets them, and generally executes other commands.
+It is the program that is running when a user logs into the system
+(although a user can select a different shell with the
+.Xr chsh 1
+command).
+The shell implements a language that has flow control
+constructs, a macro facility that provides a variety of features in
+addition to data storage, along with built in history and line editing
+capabilities.
+It incorporates many features to aid interactive use and
+has the advantage that the interpretative language is common to both
+interactive and non-interactive use (shell scripts).
+That is, commands
+can be typed directly to the running shell or can be put into a file and
+the file can be executed directly by the shell.
+.Ss Invocation
+If no args are present and if the standard input of the shell
+is connected to a terminal (or if the
+.Fl i
+flag is set),
+and the
+.Fl c
+option is not present, the shell is considered an interactive shell.
+An interactive shell generally prompts before each command and handles
+programming and command errors differently (as described below).
+When first starting,
+the shell inspects argument 0, and if it begins with a dash
+.Sq - ,
+the shell is also considered
+a login shell.
+This is normally done automatically by the system
+when the user first logs in.
+A login shell first reads commands
+from the files
+.Pa /etc/profile
+and
+.Pa .profile
+if they exist.
+If the environment variable
+.Ev ENV
+is set on entry to a shell, or is set in the
+.Pa .profile
+of a login shell, the shell next reads
+commands from the file named in
+.Ev ENV .
+Therefore, a user should place commands that are to be executed only at
+login time in the
+.Pa .profile
+file, and commands that are executed for every shell inside the
+.Ev ENV
+file.
+To set the
+.Ev ENV
+variable to some file, place the following line in your
+.Pa .profile
+of your home directory
+.Pp
+.Dl ENV=$HOME/.shinit; export ENV
+.Pp
+substituting for
+.Dq .shinit
+any filename you wish.
+Since the
+.Ev ENV
+file is read for every invocation of the shell, including shell scripts
+and non-interactive shells, the following paradigm is useful for
+restricting commands in the
+.Ev ENV
+file to interactive invocations.
+Place commands within the
+.Dq case
+and
+.Dq esac
+below (these commands are described later):
+.Pp
+.Bl -item -compact -offset indent
+.It
+.Li case $- in *i*)
+.Bl -item -compact -offset indent
+.It
+.Li # commands for interactive use only
+.It
+.Li ...
+.El
+.It
+.Li esac
+.El
+.Pp
+If command line arguments besides the options have been specified, then
+the shell treats the first argument as the name of a file from which to
+read commands (a shell script), and the remaining arguments are set as the
+positional parameters of the shell ($1, $2, etc).
+Otherwise, the shell
+reads commands from its standard input.
+.Ss Argument List Processing
+All of the single letter options have a corresponding name that can be
+used as an argument to the
+.Fl o
+option.
+The set
+.Fl o
+name is provided next to the single letter option in
+the description below.
+Specifying a dash
+.Dq -
+turns the option on, while using a plus
+.Dq +
+disables the option.
+The following options can be set from the command line or
+with the
+.Ic set
+builtin (described later).
+.Bl -tag -width aaaallexportfoo -offset indent
+.It Fl a Em allexport
+Export all variables assigned to.
+.It Fl c
+Read commands from the
+.Ar command_string
+operand instead of from the standard input.
+Special parameter 0 will be set from the
+.Ar command_name
+operand and the positional parameters ($1, $2, etc.)
+set from the remaining argument operands.
+.It Fl C Em noclobber
+Don't overwrite existing files with
+.Dq \*[Gt] .
+.It Fl e Em errexit
+If not interactive, exit immediately if any untested command fails.
+The exit status of a command is considered to be
+explicitly tested if the command is used to control an
+.Ic if ,
+.Ic elif ,
+.Ic while ,
+or
+.Ic until ;
+or if the command is the left hand operand of an
+.Dq \*[Am]\*[Am]
+or
+.Dq ||
+operator.
+.It Fl f Em noglob
+Disable pathname expansion.
+.It Fl n Em noexec
+If not interactive, read commands but do not execute them.
+This is useful for checking the syntax of shell scripts.
+.It Fl u Em nounset
+Write a message to standard error when attempting to expand a variable
+that is not set, and if the shell is not interactive, exit immediately.
+.It Fl v Em verbose
+The shell writes its input to standard error as it is read.
+Useful for debugging.
+.It Fl x Em xtrace
+Write each command to standard error (preceded by a
+.Sq +\  )
+before it is executed.
+Useful for debugging.
+.It Fl q Em quietprofile
+If the
+.Fl v
+or
+.Fl x
+options have been set, do not apply them when reading
+initialization files, these being
+.Pa /etc/profile ,
+.Pa .profile ,
+and the file specified by the
+.Ev ENV
+environment variable.
+.It Fl I Em ignoreeof
+Ignore EOF's from input when interactive.
+.It Fl i Em interactive
+Force the shell to behave interactively.
+.It Fl m Em monitor
+Turn on job control (set automatically when interactive).
+.It Fl s Em stdin
+Read commands from standard input (set automatically if no file arguments
+are present).
+This option has no effect when set after the shell has
+already started running (i.e. with
+.Ic set ) .
+.It Fl V Em vi
+Enable the built-in
+.Xr vi 1
+command line editor (disables
+.Fl E
+if it has been set).
+(See the
+.Sx Command Line Editing
+section below.)
+.It Fl E Em emacs
+Enable the built-in emacs style
+command line editor (disables
+.Fl V
+if it has been set).
+(See the
+.Sx Command Line Editing
+section below.)
+.It Fl b Em notify
+Enable asynchronous notification of background job completion.
+(UNIMPLEMENTED for 4.4alpha)
+.It "\ \ " Em cdprint
+Make an interactive shell always print the new directory name when
+changed by the
+.Ic cd
+command.
+.It "\ \ " Em tabcomplete
+Enables filename completion in the command line editor.
+Typing a tab character will extend the current input word to match a
+filename.
+If more than one filename matches it is only extended to be the common prefix.
+Typing a second tab character will list all the matching names.
+.El
+.Ss Lexical Structure
+The shell reads input in terms of lines from a file and breaks it up into
+words at whitespace (blanks and tabs), and at certain sequences of
+characters that are special to the shell called
+.Dq operators .
+There are two types of operators: control operators and redirection
+operators (their meaning is discussed later).
+Following is a list of operators:
+.Bl -ohang -offset indent
+.It "Control operators:"
+.Dl \*[Am]  \*[Am]\*[Am]  \&(  \&)  \&;  ;; | || \*[Lt]newline\*[Gt]
+.It "Redirection operators:"
+.Dl \*[Lt]  \*[Gt]  \*[Gt]|  \*[Lt]\*[Lt]  \*[Gt]\*[Gt]  \*[Lt]\*[Am]  \*[Gt]\*[Am]  \*[Lt]\*[Lt]-  \*[Lt]\*[Gt]
+.El
+.Ss Quoting
+Quoting is used to remove the special meaning of certain characters or
+words to the shell, such as operators, whitespace, or keywords.
+There are three types of quoting: matched single quotes,
+matched double quotes, and backslash.
+.Ss Backslash
+A backslash preserves the literal meaning of the following
+character, with the exception of
+.Aq newline .
+A backslash preceding a
+.Aq newline
+is treated as a line continuation.
+.Ss Single Quotes
+Enclosing characters in single quotes preserves the literal meaning of all
+the characters (except single quotes, making it impossible to put
+single-quotes in a single-quoted string).
+.Ss Double Quotes
+Enclosing characters within double quotes preserves the literal
+meaning of all characters except dollarsign
+.Pq $ ,
+backquote
+.Pq ` ,
+and backslash
+.Pq \e .
+The backslash inside double quotes is historically weird, and serves to
+quote only the following characters:
+.Dl $  `  \*q  \e  \*[Lt]newline\*[Gt] .
+Otherwise it remains literal.
+.Ss Reserved Words
+Reserved words are words that have special meaning to the
+shell and are recognized at the beginning of a line and
+after a control operator.
+The following are reserved words:
+.Bl -column while while while while while -offset indent
+.It ! Ta elif Ta fi Ta while Ta case
+.It else Ta for Ta then Ta { Ta }
+.It do Ta done Ta until Ta if Ta esac
+.El
+.Pp
+Their meaning is discussed later.
+.Ss Aliases
+An alias is a name and corresponding value set using the
+.Ic alias
+builtin command.
+Whenever a reserved word may occur (see above),
+and after checking for reserved words, the shell
+checks the word to see if it matches an alias.
+If it does, it replaces it in the input stream with its value.
+For example, if there is an alias called
+.Dq lf
+with the value
+.Dq "ls -F" ,
+then the input:
+.Pp
+.Dl lf foobar Aq return
+.Pp
+would become
+.Pp
+.Dl ls -F foobar Aq return
+.Pp
+Aliases provide a convenient way for naive users to create shorthands for
+commands without having to learn how to create functions with arguments.
+They can also be used to create lexically obscure code.
+This use is discouraged.
+.Ss Commands
+The shell interprets the words it reads according to a language, the
+specification of which is outside the scope of this man page (refer to the
+BNF in the
+.Tn POSIX
+1003.2 document).
+Essentially though, a line is read and if the first
+word of the line (or after a control operator) is not a reserved word,
+then the shell has recognized a simple command.
+Otherwise, a complex
+command or some other special construct may have been recognized.
+.Ss Simple Commands
+If a simple command has been recognized, the shell performs
+the following actions:
+.Bl -enum -offset indent
+.It
+Leading words of the form
+.Dq name=value
+are stripped off and assigned to the environment of the simple command.
+Redirection operators and their arguments (as described below) are
+stripped off and saved for processing.
+.It
+The remaining words are expanded as described in
+the section called
+.Dq Expansions ,
+and the first remaining word is considered the command name and the
+command is located.
+The remaining words are considered the arguments of the command.
+If no command name resulted, then the
+.Dq name=value
+variable assignments recognized in item 1 affect the current shell.
+.It
+Redirections are performed as described in the next section.
+.El
+.Ss Redirections
+Redirections are used to change where a command reads its input or sends
+its output.
+In general, redirections open, close, or duplicate an
+existing reference to a file.
+The overall format used for redirection is:
+.Pp
+.Dl [n] Va redir-op Ar file
+.Pp
+where
+.Va redir-op
+is one of the redirection operators mentioned previously.
+Following is a list of the possible redirections.
+The
+.Bq n
+is an optional number, as in
+.Sq 3
+(not
+.Sq Bq 3 ) ,
+that refers to a file descriptor.
+.Bl -tag -width aaabsfiles -offset indent
+.It [n] Ns \*[Gt] file
+Redirect standard output (or n) to file.
+.It [n] Ns \*[Gt]| file
+Same, but override the
+.Fl C
+option.
+.It [n] Ns \*[Gt]\*[Gt] file
+Append standard output (or n) to file.
+.It [n] Ns \*[Lt] file
+Redirect standard input (or n) from file.
+.It [n1] Ns \*[Lt]\*[Am] Ns n2
+Duplicate standard input (or n1) from file descriptor n2.
+.It [n] Ns \*[Lt]\*[Am]-
+Close standard input (or n).
+.It [n1] Ns \*[Gt]\*[Am] Ns n2
+Duplicate standard output (or n1) to n2.
+.It [n] Ns \*[Gt]\*[Am]-
+Close standard output (or n).
+.It [n] Ns \*[Lt]\*[Gt] file
+Open file for reading and writing on standard input (or n).
+.El
+.Pp
+The following redirection is often called a
+.Dq here-document .
+.Bl -item -offset indent
+.It
+.Li [n]\*[Lt]\*[Lt] delimiter
+.Dl here-doc-text ...
+.Li delimiter
+.El
+.Pp
+All the text on successive lines up to the delimiter is saved away and
+made available to the command on standard input, or file descriptor n if
+it is specified.
+If the delimiter as specified on the initial line is
+quoted, then the here-doc-text is treated literally, otherwise the text is
+subjected to parameter expansion, command substitution, and arithmetic
+expansion (as described in the section on
+.Dq Expansions ) .
+If the operator is
+.Dq \*[Lt]\*[Lt]-
+instead of
+.Dq \*[Lt]\*[Lt] ,
+then leading tabs in the here-doc-text are stripped.
+.Ss Search and Execution
+There are three types of commands: shell functions, builtin commands, and
+normal programs -- and the command is searched for (by name) in that order.
+They each are executed in a different way.
+.Pp
+When a shell function is executed, all of the shell positional parameters
+(except $0, which remains unchanged) are set to the arguments of the shell
+function.
+The variables which are explicitly placed in the environment of
+the command (by placing assignments to them before the function name) are
+made local to the function and are set to the values given.
+Then the command given in the function definition is executed.
+The positional parameters are restored to their original values
+when the command completes.
+This all occurs within the current shell.
+.Pp
+Shell builtins are executed internally to the shell, without spawning a
+new process.
+.Pp
+Otherwise, if the command name doesn't match a function or builtin, the
+command is searched for as a normal program in the file system (as
+described in the next section).
+When a normal program is executed, the shell runs the program,
+passing the arguments and the environment to the program.
+If the program is not a normal executable file (i.e., if it does
+not begin with the "magic number" whose
+.Tn ASCII
+representation is "#!", so
+.Xr execve 2
+returns
+.Er ENOEXEC
+then) the shell will interpret the program in a subshell.
+The child shell will reinitialize itself in this case,
+so that the effect will be as if a
+new shell had been invoked to handle the ad-hoc shell script, except that
+the location of hashed commands located in the parent shell will be
+remembered by the child.
+.Pp
+Note that previous versions of this document and the source code itself
+misleadingly and sporadically refer to a shell script without a magic
+number as a "shell procedure".
+.Ss Path Search
+When locating a command, the shell first looks to see if it has a shell
+function by that name.
+Then it looks for a builtin command by that name.
+If a builtin command is not found, one of two things happen:
+.Bl -enum
+.It
+Command names containing a slash are simply executed without performing
+any searches.
+.It
+The shell searches each entry in
+.Ev PATH
+in turn for the command.
+The value of the
+.Ev PATH
+variable should be a series of entries separated by colons.
+Each entry consists of a directory name.
+The current directory may be indicated
+implicitly by an empty directory name, or explicitly by a single period.
+.El
+.Ss Command Exit Status
+Each command has an exit status that can influence the behavior
+of other shell commands.
+The paradigm is that a command exits
+with zero for normal or success, and non-zero for failure,
+error, or a false indication.
+The man page for each command
+should indicate the various exit codes and what they mean.
+Additionally, the builtin commands return exit codes, as does
+an executed shell function.
+.Pp
+If a command consists entirely of variable assignments then the
+exit status of the command is that of the last command substitution
+if any, otherwise 0.
+.Ss Complex Commands
+Complex commands are combinations of simple commands with control
+operators or reserved words, together creating a larger complex command.
+More generally, a command is one of the following:
+.Bl -bullet
+.It
+simple command
+.It
+pipeline
+.It
+list or compound-list
+.It
+compound command
+.It
+function definition
+.El
+.Pp
+Unless otherwise stated, the exit status of a command is that of the last
+simple command executed by the command.
+.Ss Pipelines
+A pipeline is a sequence of one or more commands separated
+by the control operator |.
+The standard output of all but
+the last command is connected to the standard input
+of the next command.
+The standard output of the last
+command is inherited from the shell, as usual.
+.Pp
+The format for a pipeline is:
+.Pp
+.Dl [!] command1 [ | command2 ...]
+.Pp
+The standard output of command1 is connected to the standard input of
+command2.
+The standard input, standard output, or both of a command is
+considered to be assigned by the pipeline before any redirection specified
+by redirection operators that are part of the command.
+.Pp
+If the pipeline is not in the background (discussed later), the shell
+waits for all commands to complete.
+.Pp
+If the reserved word ! does not precede the pipeline, the exit status is
+the exit status of the last command specified in the pipeline.
+Otherwise, the exit status is the logical NOT of the exit status of the
+last command.
+That is, if the last command returns zero, the exit status
+is 1; if the last command returns greater than zero, the exit status is
+zero.
+.Pp
+Because pipeline assignment of standard input or standard output or both
+takes place before redirection, it can be modified by redirection.
+For example:
+.Pp
+.Dl $ command1 2\*[Gt]\*[Am]1 | command2
+.Pp
+sends both the standard output and standard error of command1
+to the standard input of command2.
+.Pp
+A ; or
+.Aq newline
+terminator causes the preceding AND-OR-list (described
+next) to be executed sequentially; a \*[Am] causes asynchronous execution of
+the preceding AND-OR-list.
+.Pp
+Note that unlike some other shells, each process in the pipeline is a
+child of the invoking shell (unless it is a shell builtin, in which case
+it executes in the current shell -- but any effect it has on the
+environment is wiped).
+.Ss Background Commands -- \*[Am]
+If a command is terminated by the control operator ampersand (\*[Am]), the
+shell executes the command asynchronously -- that is, the shell does not
+wait for the command to finish before executing the next command.
+.Pp
+The format for running a command in background is:
+.Pp
+.Dl command1 \*[Am] [command2 \*[Am] ...]
+.Pp
+If the shell is not interactive, the standard input of an asynchronous
+command is set to
+.Pa /dev/null .
+.Ss Lists -- Generally Speaking
+A list is a sequence of zero or more commands separated by newlines,
+semicolons, or ampersands, and optionally terminated by one of these three
+characters.
+The commands in a list are executed in the order they are written.
+If command is followed by an ampersand, the shell starts the
+command and immediately proceed onto the next command; otherwise it waits
+for the command to terminate before proceeding to the next one.
+.Ss Short-Circuit List Operators
+.Dq \*[Am]\*[Am]
+and
+.Dq ||
+are AND-OR list operators.
+.Dq \*[Am]\*[Am]
+executes the first command, and then executes the second command if and only
+if the exit status of the first command is zero.
+.Dq ||
+is similar, but executes the second command if and only if the exit status
+of the first command is nonzero.
+.Dq \*[Am]\*[Am]
+and
+.Dq ||
+both have the same priority.
+Note that these operators are left-associative, so
+.Dq true || echo bar && echo baz
+writes
+.Dq baz
+and nothing else.
+This is not the way it works in C.
+.Ss Flow-Control Constructs -- if, while, for, case
+The syntax of the if command is
+.Bd -literal -offset indent
+if list
+then list
+[ elif list
+then    list ] ...
+[ else list ]
+fi
+.Ed
+.Pp
+The syntax of the while command is
+.Bd -literal -offset indent
+while list
+do   list
+done
+.Ed
+.Pp
+The two lists are executed repeatedly while the exit status of the
+first list is zero.
+The until command is similar, but has the word
+until in place of while, which causes it to
+repeat until the exit status of the first list is zero.
+.Pp
+The syntax of the for command is
+.Bd -literal -offset indent
+for variable in word ...
+do   list
+done
+.Ed
+.Pp
+The words are expanded, and then the list is executed repeatedly with the
+variable set to each word in turn.
+do and done may be replaced with
+.Dq {
+and
+.Dq } .
+.Pp
+The syntax of the break and continue command is
+.Bd -literal -offset indent
+break [ num ]
+continue [ num ]
+.Ed
+.Pp
+Break terminates the num innermost for or while loops.
+Continue continues with the next iteration of the innermost loop.
+These are implemented as builtin commands.
+.Pp
+The syntax of the case command is
+.Bd -literal -offset indent
+case word in
+pattern) list ;;
+\&...
+esac
+.Ed
+.Pp
+The pattern can actually be one or more patterns (see
+.Sx Shell Patterns
+described later), separated by
+.Dq \*(Ba
+characters.
+.Ss Grouping Commands Together
+Commands may be grouped by writing either
+.Pp
+.Dl (list)
+.Pp
+or
+.Pp
+.Dl { list; }
+.Pp
+The first of these executes the commands in a subshell.
+Builtin commands grouped into a (list) will not affect the current shell.
+The second form does not fork another shell so is slightly more efficient.
+Grouping commands together this way allows you to redirect
+their output as though they were one program:
+.Pp
+.Bd -literal -offset indent
+{ echo -n \*q hello \*q ; echo \*q world" ; } \*[Gt] greeting
+.Ed
+.Pp
+Note that
+.Dq }
+must follow a control operator (here,
+.Dq \&; )
+so that it is recognized as a reserved word and not as another command argument.
+.Ss Functions
+The syntax of a function definition is
+.Pp
+.Dl name ( ) command
+.Pp
+A function definition is an executable statement; when executed it
+installs a function named name and returns an exit status of zero.
+The command is normally a list enclosed between
+.Dq {
+and
+.Dq } .
+.Pp
+Variables may be declared to be local to a function by using a local
+command.
+This should appear as the first statement of a function, and the syntax is
+.Pp
+.Dl local [ variable | - ] ...
+.Pp
+Local is implemented as a builtin command.
+.Pp
+When a variable is made local, it inherits the initial value and exported
+and readonly flags from the variable with the same name in the surrounding
+scope, if there is one.
+Otherwise, the variable is initially unset.
+The shell uses dynamic scoping, so that if you make the variable x local to
+function f, which then calls function g, references to the variable x made
+inside g will refer to the variable x declared inside f, not to the global
+variable named x.
+.Pp
+The only special parameter that can be made local is
+.Dq - .
+Making
+.Dq -
+local any shell options that are changed via the set command inside the
+function to be restored to their original values when the function
+returns.
+.Pp
+The syntax of the return command is
+.Pp
+.Dl return [ exitstatus ]
+.Pp
+It terminates the currently executing function.
+Return is implemented as a builtin command.
+.Ss Variables and Parameters
+The shell maintains a set of parameters.
+A parameter denoted by a name is called a variable.
+When starting up, the shell turns all the environment
+variables into shell variables.
+New variables can be set using the form
+.Pp
+.Dl name=value
+.Pp
+Variables set by the user must have a name consisting solely of
+alphabetics, numerics, and underscores - the first of which must not be
+numeric.
+A parameter can also be denoted by a number or a special
+character as explained below.
+.Ss Positional Parameters
+A positional parameter is a parameter denoted by a number (n \*[Gt] 0).
+The shell sets these initially to the values of its command line arguments
+that follow the name of the shell script.
+The
+.Ic set
+builtin can also be used to set or reset them.
+.Ss Special Parameters
+A special parameter is a parameter denoted by one of the following special
+characters.
+The value of the parameter is listed next to its character.
+.Bl -tag -width thinhyphena
+.It *
+Expands to the positional parameters, starting from one.
+When the
+expansion occurs within a double-quoted string it expands to a single
+field with the value of each parameter separated by the first character of
+the
+.Ev IFS
+variable, or by a
+.Aq space
+if
+.Ev IFS
+is unset.
+.It @
+Expands to the positional parameters, starting from one.
+When the expansion occurs within double-quotes, each positional
+parameter expands as a separate argument.
+If there are no positional parameters, the
+expansion of @ generates zero arguments, even when @ is
+double-quoted.
+What this basically means, for example, is
+if $1 is
+.Dq abc
+and $2 is
+.Dq def ghi ,
+then
+.Qq $@
+expands to
+the two arguments:
+.Pp
+.Sm off
+.Dl \*q abc \*q \  \*q def\ ghi \*q
+.Sm on
+.It #
+Expands to the number of positional parameters.
+.It \&?
+Expands to the exit status of the most recent pipeline.
+.It - (Hyphen.)
+Expands to the current option flags (the single-letter
+option names concatenated into a string) as specified on
+invocation, by the set builtin command, or implicitly
+by the shell.
+.It $
+Expands to the process ID of the invoked shell.
+A subshell retains the same value of $ as its parent.
+.It \&!
+Expands to the process ID of the most recent background
+command executed from the current shell.
+For a pipeline, the process ID is that of the last command in the pipeline.
+.It 0 (Zero.)
+Expands to the name of the shell or shell script.
+.El
+.Ss Word Expansions
+This clause describes the various expansions that are performed on words.
+Not all expansions are performed on every word, as explained later.
+.Pp
+Tilde expansions, parameter expansions, command substitutions, arithmetic
+expansions, and quote removals that occur within a single word expand to a
+single field.
+It is only field splitting or pathname expansion that can
+create multiple fields from a single word.
+The single exception to this
+rule is the expansion of the special parameter @ within double-quotes, as
+was described above.
+.Pp
+The order of word expansion is:
+.Bl -enum
+.It
+Tilde Expansion, Parameter Expansion, Command Substitution,
+Arithmetic Expansion (these all occur at the same time).
+.It
+Field Splitting is performed on fields
+generated by step (1) unless the
+.Ev IFS
+variable is null.
+.It
+Pathname Expansion (unless set
+.Fl f
+is in effect).
+.It
+Quote Removal.
+.El
+.Pp
+The $ character is used to introduce parameter expansion, command
+substitution, or arithmetic evaluation.
+.Ss Tilde Expansion (substituting a user's home directory)
+A word beginning with an unquoted tilde character (~) is
+subjected to tilde expansion.
+All the characters up to
+a slash (/) or the end of the word are treated as a username
+and are replaced with the user's home directory.
+If the username is missing (as in
+.Pa ~/foobar ) ,
+the tilde is replaced with the value of the
+.Va HOME
+variable (the current user's home directory).
+.Ss Parameter Expansion
+The format for parameter expansion is as follows:
+.Pp
+.Dl ${expression}
+.Pp
+where expression consists of all characters until the matching
+.Dq } .
+Any
+.Dq }
+escaped by a backslash or within a quoted string, and characters in
+embedded arithmetic expansions, command substitutions, and variable
+expansions, are not examined in determining the matching
+.Dq } .
+.Pp
+The simplest form for parameter expansion is:
+.Pp
+.Dl ${parameter}
+.Pp
+The value, if any, of parameter is substituted.
+.Pp
+The parameter name or symbol can be enclosed in braces, which are
+optional except for positional parameters with more than one digit or
+when parameter is followed by a character that could be interpreted as
+part of the name.
+If a parameter expansion occurs inside double-quotes:
+.Bl -enum
+.It
+Pathname expansion is not performed on the results of the expansion.
+.It
+Field splitting is not performed on the results of the
+expansion, with the exception of the special rules for @.
+.El
+.Pp
+In addition, a parameter expansion can be modified by using one of the
+following formats.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${parameter:-word}
+Use Default Values.
+If parameter is unset or null, the expansion of word
+is substituted; otherwise, the value of parameter is substituted.
+.It ${parameter:=word}
+Assign Default Values.
+If parameter is unset or null, the expansion of
+word is assigned to parameter.
+In all cases, the final value of parameter is substituted.
+Only variables, not positional parameters or special
+parameters, can be assigned in this way.
+.It ${parameter:?[word]}
+Indicate Error if Null or Unset.
+If parameter is unset or null, the
+expansion of word (or a message indicating it is unset if word is omitted)
+is written to standard error and the shell exits with a nonzero exit status.
+Otherwise, the value of parameter is substituted.
+An interactive shell need not exit.
+.It ${parameter:+word}
+Use Alternative Value.
+If parameter is unset or null, null is
+substituted; otherwise, the expansion of word is substituted.
+.El
+.Pp
+In the parameter expansions shown previously, use of the colon in the
+format results in a test for a parameter that is unset or null; omission
+of the colon results in a test for a parameter that is only unset.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${#parameter}
+String Length.
+The length in characters of the value of parameter.
+.El
+.Pp
+The following four varieties of parameter expansion provide for substring
+processing.
+In each case, pattern matching notation (see
+.Sx Shell Patterns ) ,
+rather than regular expression notation, is used to evaluate the patterns.
+If parameter is * or @, the result of the expansion is unspecified.
+Enclosing the full parameter expansion string in double-quotes does not
+cause the following four varieties of pattern characters to be quoted,
+whereas quoting characters within the braces has this effect.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${parameter%word}
+Remove Smallest Suffix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the
+smallest portion of the suffix matched by the pattern deleted.
+.It ${parameter%%word}
+Remove Largest Suffix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the largest
+portion of the suffix matched by the pattern deleted.
+.It ${parameter#word}
+Remove Smallest Prefix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the
+smallest portion of the prefix matched by the pattern deleted.
+.It ${parameter##word}
+Remove Largest Prefix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the largest
+portion of the prefix matched by the pattern deleted.
+.El
+.Ss Command Substitution
+Command substitution allows the output of a command to be substituted in
+place of the command name itself.
+Command substitution occurs when the command is enclosed as follows:
+.Pp
+.Dl $(command)
+.Pp
+or
+.Po
+.Dq backquoted
+version
+.Pc :
+.Pp
+.Dl `command`
+.Pp
+The shell expands the command substitution by executing command in a
+subshell environment and replacing the command substitution with the
+standard output of the command, removing sequences of one or more
+.Ao newline Ac Ns s
+at the end of the substitution.
+(Embedded
+.Ao newline Ac Ns s
+before
+the end of the output are not removed; however, during field splitting,
+they may be translated into
+.Ao space Ac Ns s ,
+depending on the value of
+.Ev IFS
+and quoting that is in effect.)
+.Ss Arithmetic Expansion
+Arithmetic expansion provides a mechanism for evaluating an arithmetic
+expression and substituting its value.
+The format for arithmetic expansion is as follows:
+.Pp
+.Dl $((expression))
+.Pp
+The expression is treated as if it were in double-quotes, except
+that a double-quote inside the expression is not treated specially.
+The shell expands all tokens in the expression for parameter expansion,
+command substitution, and quote removal.
+.Pp
+Next, the shell treats this as an arithmetic expression and
+substitutes the value of the expression.
+.Ss White Space Splitting (Field Splitting)
+After parameter expansion, command substitution, and
+arithmetic expansion the shell scans the results of
+expansions and substitutions that did not occur in double-quotes for
+field splitting and multiple fields can result.
+.Pp
+The shell treats each character of the
+.Ev IFS
+as a delimiter and use the delimiters to split the results of parameter
+expansion and command substitution into fields.
+.Pp
+Non-whitespace characters in
+.Ev IFS
+are treated strictly as parameter terminators.
+So adjacent non-whitespace
+.Ev IFS
+characters will produce empty parameters.
+.Pp
+If
+.Ev IFS
+is unset it is assumed to contain space, tab, and newline.
+.Ss Pathname Expansion (File Name Generation)
+Unless the
+.Fl f
+flag is set, file name generation is performed after word splitting is
+complete.
+Each word is viewed as a series of patterns, separated by slashes.
+The process of expansion replaces the word with the names of all
+existing files whose names can be formed by replacing each pattern with a
+string that matches the specified pattern.
+There are two restrictions on
+this: first, a pattern cannot match a string containing a slash, and
+second, a pattern cannot match a string starting with a period unless the
+first character of the pattern is a period.
+The next section describes the
+patterns used for both Pathname Expansion and the
+.Ic case
+command.
+.Ss Shell Patterns
+A pattern consists of normal characters, which match themselves,
+and meta-characters.
+The meta-characters are
+.Dq \&! ,
+.Dq * ,
+.Dq \&? ,
+and
+.Dq \&[ .
+These characters lose their special meanings if they are quoted.
+When command or variable substitution is performed
+and the dollar sign or back quotes are not double quoted,
+the value of the variable or the output of
+the command is scanned for these characters and they are turned into
+meta-characters.
+.Pp
+An asterisk
+.Pq Dq *
+matches any string of characters.
+A question mark matches any single character.
+A left bracket
+.Pq Dq \&[
+introduces a character class.
+The end of the character class is indicated by a
+.Pq Dq \&] ;
+if the
+.Dq \&]
+is missing then the
+.Dq \&[
+matches a
+.Dq \&[
+rather than introducing a character class.
+A character class matches any of the characters between the square brackets.
+A range of characters may be specified using a minus sign.
+The character class may be complemented
+by making an exclamation point the first character of the character class.
+.Pp
+To include a
+.Dq \&]
+in a character class, make it the first character listed (after the
+.Dq \&! ,
+if any).
+To include a minus sign, make it the first or last character listed.
+.Ss Builtins
+This section lists the builtin commands which are builtin because they
+need to perform some operation that can't be performed by a separate
+process.
+In addition to these, there are several other commands that may
+be builtin for efficiency (e.g.
+.Xr printf 1 ,
+.Xr echo 1 ,
+.Xr test 1 ,
+etc).
+.Bl -tag -width 5n
+.It :
+A null command that returns a 0 (true) exit value.
+.It \&. file
+The commands in the specified file are read and executed by the shell.
+.It alias Op Ar name Ns Op Ar "=string ..."
+If
+.Ar name=string
+is specified, the shell defines the alias
+.Ar name
+with value
+.Ar string .
+If just
+.Ar name
+is specified, the value of the alias
+.Ar name
+is printed.
+With no arguments, the
+.Ic alias
+builtin prints the
+names and values of all defined aliases (see
+.Ic unalias ) .
+.It bg [ Ar job ] ...
+Continue the specified jobs (or the current job if no
+jobs are given) in the background.
+.It Xo command
+.Op Fl p
+.Op Fl v
+.Op Fl V
+.Ar command
+.Op Ar arg ...
+.Xc
+Execute the specified command but ignore shell functions when searching
+for it.
+(This is useful when you
+have a shell function with the same name as a builtin command.)
+.Bl -tag -width 5n
+.It Fl p
+search for command using a
+.Ev PATH
+that guarantees to find all the standard utilities.
+.It Fl V
+Do not execute the command but
+search for the command and print the resolution of the
+command search.
+This is the same as the type builtin.
+.It Fl v
+Do not execute the command but
+search for the command and print the absolute pathname
+of utilities, the name for builtins or the expansion of aliases.
+.El
+.It cd Op Ar directory Op Ar replace
+Switch to the specified directory (default
+.Ev $HOME ) .
+If
+.Ar replace
+is specified, then the new directory name is generated by replacing
+the first occurrence of
+.Ar directory
+in the current directory name with
+.Ar replace .
+Otherwise if an entry for
+.Ev CDPATH
+appears in the environment of the
+.Ic cd
+command or the shell variable
+.Ev CDPATH
+is set and the directory name does not begin with a slash, then the
+directories listed in
+.Ev CDPATH
+will be searched for the specified directory.
+The format of
+.Ev CDPATH
+is the same as that of
+.Ev PATH .
+In an interactive shell, the
+.Ic cd
+command will print out the name of the
+directory that it actually switched to if this is different from the name
+that the user gave.
+These may be different either because the
+.Ev CDPATH
+mechanism was used or because a symbolic link was crossed.
+.It eval Ar string ...
+Concatenate all the arguments with spaces.
+Then re-parse and execute the command.
+.It exec Op Ar command arg ...
+Unless command is omitted, the shell process is replaced with the
+specified program (which must be a real program, not a shell builtin or
+function).
+Any redirections on the
+.Ic exec
+command are marked as permanent, so that they are not undone when the
+.Ic exec
+command finishes.
+.It exit Op Ar exitstatus
+Terminate the shell process.
+If
+.Ar exitstatus
+is given it is used as the exit status of the shell; otherwise the
+exit status of the preceding command is used.
+.It export Ar name ...
+.It export Fl p
+The specified names are exported so that they will appear in the
+environment of subsequent commands.
+The only way to un-export a variable is to unset it.
+The shell allows the value of a variable to be set at the
+same time it is exported by writing
+.Pp
+.Dl export name=value
+.Pp
+With no arguments the export command lists the names of all exported variables.
+With the
+.Fl p
+option specified the output will be formatted suitably for non-interactive use.
+.It Xo fc Op Fl e Ar editor
+.Op Ar first Op Ar last
+.Xc
+.It Xo fc Fl l
+.Op Fl nr
+.Op Ar first Op Ar last
+.Xc
+.It Xo fc Fl s Op Ar old=new
+.Op Ar first
+.Xc
+The
+.Ic fc
+builtin lists, or edits and re-executes, commands previously entered
+to an interactive shell.
+.Bl -tag -width 5n
+.It Fl e No editor
+Use the editor named by editor to edit the commands.
+The editor string is a command name, subject to search via the
+.Ev PATH
+variable.
+The value in the
+.Ev FCEDIT
+variable is used as a default when
+.Fl e
+is not specified.
+If
+.Ev FCEDIT
+is null or unset, the value of the
+.Ev EDITOR
+variable is used.
+If
+.Ev EDITOR
+is null or unset,
+.Xr ed 1
+is used as the editor.
+.It Fl l No (ell)
+List the commands rather than invoking an editor on them.
+The commands are written in the sequence indicated by
+the first and last operands, as affected by
+.Fl r ,
+with each command preceded by the command number.
+.It Fl n
+Suppress command numbers when listing with -l.
+.It Fl r
+Reverse the order of the commands listed (with
+.Fl l )
+or edited (with neither
+.Fl l
+nor
+.Fl s ) .
+.It Fl s
+Re-execute the command without invoking an editor.
+.It first
+.It last
+Select the commands to list or edit.
+The number of previous commands that
+can be accessed are determined by the value of the
+.Ev HISTSIZE
+variable.
+The value of first or last or both are one of the following:
+.Bl -tag -width 5n
+.It [+]number
+A positive number representing a command number; command numbers can be
+displayed with the
+.Fl l
+option.
+.It Fl number
+A negative decimal number representing the command that was executed
+number of commands previously.
+For example, \-1 is the immediately previous command.
+.El
+.It string
+A string indicating the most recently entered command that begins with
+that string.
+If the old=new operand is not also specified with
+.Fl s ,
+the string form of the first operand cannot contain an embedded equal sign.
+.El
+.Pp
+The following environment variables affect the execution of fc:
+.Bl -tag -width HISTSIZE
+.It Ev FCEDIT
+Name of the editor to use.
+.It Ev HISTSIZE
+The number of previous commands that are accessible.
+.El
+.It fg Op Ar job
+Move the specified job or the current job to the foreground.
+.It getopts Ar optstring var
+The
+.Tn POSIX
+.Ic getopts
+command, not to be confused with the
+.Em Bell Labs
+-derived
+.Xr getopt 1 .
+.Pp
+The first argument should be a series of letters, each of which may be
+optionally followed by a colon to indicate that the option requires an
+argument.
+The variable specified is set to the parsed option.
+.Pp
+The
+.Ic getopts
+command deprecates the older
+.Xr getopt 1
+utility due to its handling of arguments containing whitespace.
+.Pp
+The
+.Ic getopts
+builtin may be used to obtain options and their arguments
+from a list of parameters.
+When invoked,
+.Ic getopts
+places the value of the next option from the option string in the list in
+the shell variable specified by
+.Va var
+and its index in the shell variable
+.Ev OPTIND .
+When the shell is invoked,
+.Ev OPTIND
+is initialized to 1.
+For each option that requires an argument, the
+.Ic getopts
+builtin will place it in the shell variable
+.Ev OPTARG .
+If an option is not allowed for in the
+.Va optstring ,
+then
+.Ev OPTARG
+will be unset.
+.Pp
+.Va optstring
+is a string of recognized option letters (see
+.Xr getopt 3 ) .
+If a letter is followed by a colon, the option is expected to have an
+argument which may or may not be separated from it by whitespace.
+If an option character is not found where expected,
+.Ic getopts
+will set the variable
+.Va var
+to a
+.Dq \&? ;
+.Ic getopts
+will then unset
+.Ev OPTARG
+and write output to standard error.
+By specifying a colon as the first character of
+.Va optstring
+all errors will be ignored.
+.Pp
+A nonzero value is returned when the last option is reached.
+If there are no remaining arguments,
+.Ic getopts
+will set
+.Va var
+to the special option,
+.Dq -- ,
+otherwise, it will set
+.Va var
+to
+.Dq \&? .
+.Pp
+The following code fragment shows how one might process the arguments
+for a command that can take the options
+.Op a
+and
+.Op b ,
+and the option
+.Op c ,
+which requires an argument.
+.Pp
+.Bd -literal -offset indent
+while getopts abc: f
+do
+	case $f in
+	a | b)	flag=$f;;
+	c)	carg=$OPTARG;;
+	\\?)	echo $USAGE; exit 1;;
+	esac
+done
+shift `expr $OPTIND - 1`
+.Ed
+.Pp
+This code will accept any of the following as equivalent:
+.Pp
+.Bd -literal -offset indent
+cmd \-acarg file file
+cmd \-a \-c arg file file
+cmd \-carg -a file file
+cmd \-a \-carg \-\- file file
+.Ed
+.It hash Fl rv Ar command ...
+The shell maintains a hash table which remembers the
+locations of commands.
+With no arguments whatsoever,
+the
+.Ic hash
+command prints out the contents of this table.
+Entries which have not been looked at since the last
+.Ic cd
+command are marked with an asterisk; it is possible for these entries
+to be invalid.
+.Pp
+With arguments, the
+.Ic hash
+command removes the specified commands from the hash table (unless
+they are functions) and then locates them.
+With the
+.Fl v
+option, hash prints the locations of the commands as it finds them.
+The
+.Fl r
+option causes the hash command to delete all the entries in the hash table
+except for functions.
+.It inputrc Ar file
+Read the
+.Va file
+to set keybindings as defined by
+.Xr editrc 5 .
+.It jobid Op Ar job
+Print the process id's of the processes in the job.
+If the
+.Ar job
+argument is omitted, the current job is used.
+.It jobs
+This command lists out all the background processes
+which are children of the current shell process.
+.It pwd Op Fl LP
+Print the current directory.
+If 
+.Fl L
+is specified the cached value (initially set from
+.Ev PWD )
+is checked to see if it refers to the current directory, if it does
+the value is printed.
+Otherwise the current directory name is found using
+.Xr getcwd(3) .
+The environment variable
+.Ev PWD
+is set to printed value.
+.Pp
+The default is
+.Ic pwd
+.Fl L ,
+but note that the builtin
+.Ic cd
+command doesn't currently support
+.Fl L
+or
+.Fl P
+and will cache (almost) the absolute path.
+If
+.Ic cd
+is changed,
+.Ic pwd
+may be changed to default to
+.Ic pwd
+.Fl P .
+.Pp
+If the current directory is renamed and replaced by a symlink to the
+same directory, or the initial
+.Ev PWD
+value followed a symbolic link, then the cached value may not
+be the absolute path.
+.Pp
+The builtin command may differ from the program of the same name because
+the program will use
+.Ev PWD
+and the builtin uses a separately cached value.
+.It Xo read Op Fl p Ar prompt
+.Op Fl r
+.Ar variable
+.Op Ar ...
+.Xc
+The prompt is printed if the
+.Fl p
+option is specified and the standard input is a terminal.
+Then a line is read from the standard input.
+The trailing newline is deleted from the
+line and the line is split as described in the section on word splitting
+above, and the pieces are assigned to the variables in order.
+If there are more pieces than variables, the remaining pieces
+(along with the characters in
+.Ev IFS
+that separated them) are assigned to the last variable.
+If there are more variables than pieces,
+the remaining variables are assigned the null string.
+The
+.Ic read
+builtin will indicate success unless EOF is encountered on input, in
+which case failure is returned.
+.Pp
+By default, unless the
+.Fl r
+option is specified, the backslash
+.Dq \e
+acts as an escape character, causing the following character to be treated
+literally.
+If a backslash is followed by a newline, the backslash and the
+newline will be deleted.
+.It readonly Ar name ...
+.It readonly Fl p
+The specified names are marked as read only, so that they cannot be
+subsequently modified or unset.
+The shell allows the value of a variable
+to be set at the same time it is marked read only by writing
+.Pp
+.Dl readonly name=value
+.Pp
+With no arguments the readonly command lists the names of all read only
+variables.
+With the
+.Fl p
+option specified the output will be formatted suitably for non-interactive use.
+.Pp
+.It Xo set
+.Oo {
+.Fl options | Cm +options | Cm -- }
+.Oc Ar arg ...
+.Xc
+The
+.Ic set
+command performs three different functions.
+.Pp
+With no arguments, it lists the values of all shell variables.
+.Pp
+If options are given, it sets the specified option
+flags, or clears them as described in the section called
+.Sx Argument List Processing .
+.Pp
+The third use of the set command is to set the values of the shell's
+positional parameters to the specified args.
+To change the positional
+parameters without changing any options, use
+.Dq --
+as the first argument to set.
+If no args are present, the set command
+will clear all the positional parameters (equivalent to executing
+.Dq shift $# . )
+.It setvar Ar variable Ar value
+Assigns value to variable.
+(In general it is better to write
+variable=value rather than using
+.Ic setvar .
+.Ic setvar
+is intended to be used in
+functions that assign values to variables whose names are passed as
+parameters.)
+.It shift Op Ar n
+Shift the positional parameters n times.
+A
+.Ic shift
+sets the value of
+.Va $1
+to the value of
+.Va $2 ,
+the value of
+.Va $2
+to the value of
+.Va $3 ,
+and so on, decreasing
+the value of
+.Va $#
+by one.
+If there are zero positional parameters,
+.Ic shift
+does nothing.
+.It Xo trap
+.Op Fl l
+.Xc
+.It Xo trap
+.Op Ar action
+.Ar signal ...
+.Xc
+Cause the shell to parse and execute action when any of the specified
+signals are received.
+The signals are specified by signal number or as the name of the signal.
+If
+.Ar signal
+is
+.Li 0 ,
+the action is executed when the shell exits.
+.Ar action
+may be null, which cause the specified signals to be ignored.
+With
+.Ar action
+omitted or set to `-' the specified signals are set to their default action.
+When the shell forks off a subshell, it resets trapped (but not ignored)
+signals to the default action.
+The
+.Ic trap
+command has no effect on signals that were
+ignored on entry to the shell.
+Issuing
+.Ic trap
+with option
+.Ar -l
+will print a list of valid signal names.
+.Ic trap
+without any arguments cause it to write a list of signals and their
+associated action to the standard output in a format that is suitable
+as an input to the shell that achieves the same trapping results.
+.Pp
+Examples:
+.Pp
+.Dl trap
+.Pp
+List trapped signals and their corresponding action
+.Pp
+.Dl trap -l
+.Pp
+Print a list of valid signals
+.Pp
+.Dl trap '' INT QUIT tstp 30
+.Pp
+Ignore signals INT QUIT TSTP USR1
+.Pp
+.Dl trap date INT
+.Pp
+Print date upon receiving signal INT
+.It type Op Ar name ...
+Interpret each name as a command and print the resolution of the command
+search.
+Possible resolutions are:
+shell keyword, alias, shell builtin,
+command, tracked alias and not found.
+For aliases the alias expansion is
+printed; for commands and tracked aliases the complete pathname of the
+command is printed.
+.It ulimit Xo
+.Op Fl H \*(Ba Fl S
+.Op Fl a \*(Ba Fl tfdscmlpn Op Ar value
+.Xc
+Inquire about or set the hard or soft limits on processes or set new
+limits.
+The choice between hard limit (which no process is allowed to
+violate, and which may not be raised once it has been lowered) and soft
+limit (which causes processes to be signaled but not necessarily killed,
+and which may be raised) is made with these flags:
+.Bl -tag -width Fl
+.It Fl H
+set or inquire about hard limits
+.It Fl S
+set or inquire about soft limits.
+If neither
+.Fl H
+nor
+.Fl S
+is specified, the soft limit is displayed or both limits are set.
+If both are specified, the last one wins.
+.El
+.Pp
+.Bl -tag -width Fl
+The limit to be interrogated or set, then, is chosen by specifying
+any one of these flags:
+.It Fl a
+show all the current limits
+.It Fl b
+show or set the limit on the socket buffer size of a process (in bytes)
+.It Fl t
+show or set the limit on CPU time (in seconds)
+.It Fl f
+show or set the limit on the largest file that can be created
+(in 512-byte blocks)
+.It Fl d
+show or set the limit on the data segment size of a process (in kilobytes)
+.It Fl s
+show or set the limit on the stack size of a process (in kilobytes)
+.It Fl c
+show or set the limit on the largest core dump size that can be produced
+(in 512-byte blocks)
+.It Fl m
+show or set the limit on the total physical memory that can be
+in use by a process (in kilobytes)
+.It Fl l
+show or set the limit on how much memory a process can lock with
+.Xr mlock 2
+(in kilobytes)
+.It Fl p
+show or set the limit on the number of processes this user can
+have at one time
+.It Fl n
+show or set the limit on the number of files a process can have open at once
+.El
+.Pp
+If none of these is specified, it is the limit on file size that is shown
+or set.
+If value is specified, the limit is set to that number; otherwise
+the current limit is displayed.
+.Pp
+Limits of an arbitrary process can be displayed or set using the
+.Xr sysctl 8
+utility.
+.Pp
+.It umask Op Ar mask
+Set the value of umask (see
+.Xr umask 2 )
+to the specified octal value.
+If the argument is omitted, the umask value is printed.
+.It unalias Xo
+.Op Fl a
+.Op Ar name
+.Xc
+If
+.Ar name
+is specified, the shell removes that alias.
+If
+.Fl a
+is specified, all aliases are removed.
+.It unset Ar name ...
+The specified variables and functions are unset and unexported.
+If a given name corresponds to both a variable and a function, both
+the variable and the function are unset.
+.It wait Op Ar job
+Wait for the specified job to complete and return the exit status of the
+last process in the job.
+If the argument is omitted, wait for all jobs to
+complete and then return an exit status of zero.
+.El
+.Ss Command Line Editing
+When
+.Nm
+is being used interactively from a terminal, the current command
+and the command history (see
+.Ic fc
+in
+.Sx Builtins )
+can be edited using emacs-mode or vi-mode command-line editing.
+The command
+.Ql set -o emacs
+enables emacs-mode editing.
+The command
+.Ql set -o vi
+enables vi-mode editing and places sh into vi insert mode.
+(See the
+.Sx Argument List Processing
+section above.)
+.Pp
+The vi mode uses commands similar to a subset of those described in the
+.Xr vi 1
+man page.
+With vi-mode
+enabled, sh can be switched between insert mode and command mode.
+It's similar to vi: typing
+.Aq ESC
+will throw you into command VI command mode.
+Hitting
+.Aq return
+while in command mode will pass the line to the shell.
+.Pp
+The emacs mode uses commands similar to a subset available in
+the emacs editor.
+With emacs-mode enabled, special keys can be used to modify the text
+in the buffer using the control key.
+.Pp
+.Nm
+uses the
+.Xr editline 3
+library.
+.Sh EXIT STATUS
+Errors that are detected by the shell, such as a syntax error, will cause the
+shell to exit with a non-zero exit status.
+If the shell is not an
+interactive shell, the execution of the shell file will be aborted.
+Otherwise
+the shell will return the exit status of the last command executed, or
+if the exit builtin is used with a numeric argument, it will return the
+argument.
+.Sh ENVIRONMENT
+.Bl -tag -width MAILCHECK
+.It Ev HOME
+Set automatically by
+.Xr login 1
+from the user's login directory in the password file
+.Pq Xr passwd 5 .
+This environment variable also functions as the default argument for the
+cd builtin.
+.It Ev PATH
+The default search path for executables.
+See the above section
+.Sx Path Search .
+.It Ev CDPATH
+The search path used with the cd builtin.
+.It Ev LANG
+The string used to specify localization information that allows users
+to work with different culture-specific and language conventions.
+See
+.Xr nls 7 .
+.It Ev MAIL
+The name of a mail file, that will be checked for the arrival of new mail.
+Overridden by
+.Ev MAILPATH .
+.It Ev MAILCHECK
+The frequency in seconds that the shell checks for the arrival of mail
+in the files specified by the
+.Ev MAILPATH
+or the
+.Ev MAIL
+file.
+If set to 0, the check will occur at each prompt.
+.It Ev MAILPATH
+A colon
+.Dq \&:
+separated list of file names, for the shell to check for incoming mail.
+This environment setting overrides the
+.Ev MAIL
+setting.
+There is a maximum of 10 mailboxes that can be monitored at once.
+.It Ev PS1
+The primary prompt string, which defaults to
+.Dq $ \  ,
+unless you are the superuser, in which case it defaults to
+.Dq # \  .
+.It Ev PS2
+The secondary prompt string, which defaults to
+.Dq \*[Gt] \  .
+.It Ev PS4
+Output before each line when execution trace (set -x) is enabled,
+defaults to
+.Dq + \  .
+.It Ev IFS
+Input Field Separators.
+This is normally set to
+.Aq space ,
+.Aq tab ,
+and
+.Aq newline .
+See the
+.Sx White Space Splitting
+section for more details.
+.It Ev TERM
+The default terminal setting for the shell.
+This is inherited by
+children of the shell, and is used in the history editing modes.
+.It Ev HISTSIZE
+The number of lines in the history buffer for the shell.
+.El
+.Sh FILES
+.Bl -item -width HOMEprofilexxxx
+.It
+.Pa $HOME/.profile
+.It
+.Pa /etc/profile
+.El
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr echo 1 ,
+.Xr getopt 1 ,
+.Xr ksh 1 ,
+.Xr login 1 ,
+.Xr printf 1 ,
+.Xr test 1 ,
+.Xr editline 3 ,
+.Xr getopt 3 ,
+.\" .Xr profile 4 ,
+.Xr editrc 5 ,
+.Xr passwd 5 ,
+.Xr environ 7 ,
+.Xr nls 7 ,
+.Xr sysctl 8
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
+It was, however, unmaintainable so we wrote this one.
+.Sh BUGS
+Setuid shell scripts should be avoided at all costs, as they are a
+significant security risk.
+.Pp
+PS1, PS2, and PS4 should be subject to parameter expansion before
+being displayed.
+.Pp
+The characters generated by filename completion should probably be quoted
+to ensure that the filename is still valid after the input line has been
+processed.
Index: /tags/kBuild-0.1.4/src/ash/shell.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/shell.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/shell.h	(revision 1780)
@@ -0,0 +1,85 @@
+/*	$NetBSD: shell.h,v 1.17 2003/08/07 09:05:38 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)shell.h	8.2 (Berkeley) 5/4/95
+ */
+
+/*
+ * The follow should be set to reflect the type of system you have:
+ *	JOBS -> 1 if you have Berkeley job control, 0 otherwise.
+ *	SHORTNAMES -> 1 if your linker cannot handle long names.
+ *	define BSD if you are running 4.2 BSD or later.
+ *	define SYSV if you are running under System V.
+ *	define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
+ *	define DEBUG=2 to compile in and turn on debugging.
+ *	define DO_SHAREDVFORK to indicate that vfork(2) shares its address
+ *	       with its parent.
+ *
+ * When debugging is on, debugging info will be written to ./trace and
+ * a quit signal will generate a core dump.
+ */
+
+#include <sys/param.h>
+
+#define JOBS 1
+#ifndef BSD
+#define BSD 1
+#endif
+
+#ifndef DO_SHAREDVFORK
+#if __NetBSD_Version__ >= 104000000
+#define DO_SHAREDVFORK
+#endif
+#endif
+
+typedef void *pointer;
+#ifndef NULL
+#define NULL (void *)0
+#endif
+#define STATIC	/* empty */
+#define MKINIT	/* empty */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+extern char nullstr[1];		/* null string */
+
+
+#ifdef DEBUG
+#define TRACE(param)	trace param
+#define TRACEV(param)	tracev param
+#else
+#define TRACE(param)
+#define TRACEV(param)
+#endif
Index: /tags/kBuild-0.1.4/src/ash/show.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/show.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/show.c	(revision 1780)
@@ -0,0 +1,429 @@
+/*	$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "parser.h"
+#include "nodes.h"
+#include "mystring.h"
+#include "show.h"
+#include "options.h"
+
+
+#ifdef DEBUG
+static void shtree(union node *, int, char *, FILE*);
+static void shcmd(union node *, FILE *);
+static void sharg(union node *, FILE *);
+static void indent(int, char *, FILE *);
+static void trstring(char *);
+
+
+void
+showtree(union node *n)
+{
+	trputs("showtree called\n");
+	shtree(n, 1, NULL, stdout);
+}
+
+
+static void
+shtree(union node *n, int ind, char *pfx, FILE *fp)
+{
+	struct nodelist *lp;
+	const char *s;
+
+	if (n == NULL)
+		return;
+
+	indent(ind, pfx, fp);
+	switch(n->type) {
+	case NSEMI:
+		s = "; ";
+		goto binop;
+	case NAND:
+		s = " && ";
+		goto binop;
+	case NOR:
+		s = " || ";
+binop:
+		shtree(n->nbinary.ch1, ind, NULL, fp);
+	   /*    if (ind < 0) */
+			fputs(s, fp);
+		shtree(n->nbinary.ch2, ind, NULL, fp);
+		break;
+	case NCMD:
+		shcmd(n, fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	case NPIPE:
+		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+			shcmd(lp->n, fp);
+			if (lp->next)
+				fputs(" | ", fp);
+		}
+		if (n->npipe.backgnd)
+			fputs(" &", fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	default:
+		fprintf(fp, "<node type %d>", n->type);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	}
+}
+
+
+
+static void
+shcmd(union node *cmd, FILE *fp)
+{
+	union node *np;
+	int first;
+	const char *s;
+	int dftfd;
+
+	first = 1;
+	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
+		if (! first)
+			putchar(' ');
+		sharg(np, fp);
+		first = 0;
+	}
+	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
+		if (! first)
+			putchar(' ');
+		switch (np->nfile.type) {
+			case NTO:	s = ">";  dftfd = 1; break;
+			case NCLOBBER:	s = ">|"; dftfd = 1; break;
+			case NAPPEND:	s = ">>"; dftfd = 1; break;
+			case NTOFD:	s = ">&"; dftfd = 1; break;
+			case NFROM:	s = "<";  dftfd = 0; break;
+			case NFROMFD:	s = "<&"; dftfd = 0; break;
+			case NFROMTO:	s = "<>"; dftfd = 0; break;
+			default:  	s = "*error*"; dftfd = 0; break;
+		}
+		if (np->nfile.fd != dftfd)
+			fprintf(fp, "%d", np->nfile.fd);
+		fputs(s, fp);
+		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
+			fprintf(fp, "%d", np->ndup.dupfd);
+		} else {
+			sharg(np->nfile.fname, fp);
+		}
+		first = 0;
+	}
+}
+
+
+
+static void
+sharg(union node *arg, FILE *fp)
+{
+	char *p;
+	struct nodelist *bqlist;
+	int subtype;
+
+	if (arg->type != NARG) {
+		printf("<node type %d>\n", arg->type);
+		abort();
+	}
+	bqlist = arg->narg.backquote;
+	for (p = arg->narg.text ; *p ; p++) {
+		switch (*p) {
+		case CTLESC:
+			putc(*++p, fp);
+			break;
+		case CTLVAR:
+			putc('$', fp);
+			putc('{', fp);
+			subtype = *++p;
+			if (subtype == VSLENGTH)
+				putc('#', fp);
+
+			while (*p != '=')
+				putc(*p++, fp);
+
+			if (subtype & VSNUL)
+				putc(':', fp);
+
+			switch (subtype & VSTYPE) {
+			case VSNORMAL:
+				putc('}', fp);
+				break;
+			case VSMINUS:
+				putc('-', fp);
+				break;
+			case VSPLUS:
+				putc('+', fp);
+				break;
+			case VSQUESTION:
+				putc('?', fp);
+				break;
+			case VSASSIGN:
+				putc('=', fp);
+				break;
+			case VSTRIMLEFT:
+				putc('#', fp);
+				break;
+			case VSTRIMLEFTMAX:
+				putc('#', fp);
+				putc('#', fp);
+				break;
+			case VSTRIMRIGHT:
+				putc('%', fp);
+				break;
+			case VSTRIMRIGHTMAX:
+				putc('%', fp);
+				putc('%', fp);
+				break;
+			case VSLENGTH:
+				break;
+			default:
+				printf("<subtype %d>", subtype);
+			}
+			break;
+		case CTLENDVAR:
+		     putc('}', fp);
+		     break;
+		case CTLBACKQ:
+		case CTLBACKQ|CTLQUOTE:
+			putc('$', fp);
+			putc('(', fp);
+			shtree(bqlist->n, -1, NULL, fp);
+			putc(')', fp);
+			break;
+		default:
+			putc(*p, fp);
+			break;
+		}
+	}
+}
+
+
+static void
+indent(int amount, char *pfx, FILE *fp)
+{
+	int i;
+
+	for (i = 0 ; i < amount ; i++) {
+		if (pfx && i == amount - 1)
+			fputs(pfx, fp);
+		putc('\t', fp);
+	}
+}
+#endif
+
+
+
+/*
+ * Debugging stuff.
+ */
+
+
+FILE *tracefile;
+
+
+#ifdef DEBUG
+void
+trputc(int c)
+{
+	if (debug != 1)
+		return;
+	putc(c, tracefile);
+}
+#endif
+
+void
+trace(const char *fmt, ...)
+{
+#ifdef DEBUG
+	va_list va;
+
+	if (debug != 1)
+		return;
+        fprintf(tracefile, "[%d] ", getpid());
+	va_start(va, fmt);
+	(void) vfprintf(tracefile, fmt, va);
+	va_end(va);
+#endif
+}
+
+void
+tracev(const char *fmt, va_list va)
+{
+#ifdef DEBUG
+	if (debug != 1)
+		return;
+        fprintf(tracefile, "[%d] ", getpid());
+	(void) vfprintf(tracefile, fmt, va);
+#endif
+}
+
+
+#ifdef DEBUG
+void
+trputs(const char *s)
+{
+	if (debug != 1)
+		return;
+	fputs(s, tracefile);
+}
+
+
+static void
+trstring(char *s)
+{
+	char *p;
+	char c;
+
+	if (debug != 1)
+		return;
+	putc('"', tracefile);
+	for (p = s ; *p ; p++) {
+		switch (*p) {
+		case '\n':  c = 'n';  goto backslash;
+		case '\t':  c = 't';  goto backslash;
+		case '\r':  c = 'r';  goto backslash;
+		case '"':  c = '"';  goto backslash;
+		case '\\':  c = '\\';  goto backslash;
+		case CTLESC:  c = 'e';  goto backslash;
+		case CTLVAR:  c = 'v';  goto backslash;
+		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
+		case CTLBACKQ:  c = 'q';  goto backslash;
+		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
+backslash:	  putc('\\', tracefile);
+			putc(c, tracefile);
+			break;
+		default:
+			if (*p >= ' ' && *p <= '~')
+				putc(*p, tracefile);
+			else {
+				putc('\\', tracefile);
+				putc(*p >> 6 & 03, tracefile);
+				putc(*p >> 3 & 07, tracefile);
+				putc(*p & 07, tracefile);
+			}
+			break;
+		}
+	}
+	putc('"', tracefile);
+}
+#endif
+
+
+void
+trargs(char **ap)
+{
+#ifdef DEBUG
+	if (debug != 1)
+		return;
+	while (*ap) {
+		trstring(*ap++);
+		if (*ap)
+			putc(' ', tracefile);
+		else
+			putc('\n', tracefile);
+	}
+#endif
+}
+
+
+#ifdef DEBUG
+void
+opentrace(void)
+{
+	char s[100];
+#ifdef O_APPEND
+	int flags;
+#endif
+
+	if (debug != 1) {
+		if (tracefile)
+			fflush(tracefile);
+		/* leave open because libedit might be using it */
+		return;
+	}
+#ifdef not_this_way
+	{
+		char *p;
+		if ((p = getenv("HOME")) == NULL) {
+			if (geteuid() == 0)
+				p = "/";
+			else
+				p = "/tmp";
+		}
+		scopy(p, s);
+		strcat(s, "/trace");
+	}
+#else
+	scopy("./trace", s);
+#endif /* not_this_way */
+	if (tracefile) {
+		if (!freopen(s, "a", tracefile)) {
+			fprintf(stderr, "Can't re-open %s\n", s);
+			debug = 0;
+			return;
+		}
+	} else {
+		if ((tracefile = fopen(s, "a")) == NULL) {
+			fprintf(stderr, "Can't open %s\n", s);
+			debug = 0;
+			return;
+		}
+	}
+#ifdef O_APPEND
+	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
+		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
+#endif
+	setlinebuf(tracefile);
+	fputs("\nTracing started.\n", tracefile);
+}
+#endif /* DEBUG */
Index: /tags/kBuild-0.1.4/src/ash/show.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/show.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/show.h	(revision 1780)
@@ -0,0 +1,45 @@
+/*	$NetBSD: show.h,v 1.7 2003/08/07 09:05:38 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1995
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)show.h	1.1 (Berkeley) 5/4/95
+ */
+
+#include <stdarg.h>
+
+union node;
+void showtree(union node *);
+void trace(const char *, ...);
+void tracev(const char *, va_list);
+void trargs(char **);
+#ifdef DEBUG
+void trputc(int);
+void trputs(const char *);
+void opentrace(void);
+#endif
Index: /tags/kBuild-0.1.4/src/ash/strlcpy.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/strlcpy.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/strlcpy.c	(revision 1780)
@@ -0,0 +1,70 @@
+/*	$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $");
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.7 2003/05/01 19:03:14 nectar Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t strlcpy(dst, src, siz)
+	char *dst;
+	const char *src;
+	size_t siz;
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
Index: /tags/kBuild-0.1.4/src/ash/syntax.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/syntax.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/syntax.c	(revision 1780)
@@ -0,0 +1,206 @@
+/*	$NetBSD: syntax.c,v 1.1 2004/01/17 17:38:12 dsl Exp $	*/
+
+#ifdef __sun__
+#include <stdio.h>
+#include <iso/limits_iso.h>
+#endif
+
+#include "shell.h"
+#include "syntax.h"
+#include "parser.h"
+
+#ifdef _MSC_VER /* doesn't implement the fancy initializers I think... */
+
+char basesyntax[257] = {CEOF};
+char dqsyntax[257] = {CEOF};
+char sqsyntax[257] = {CEOF};
+char arisyntax[257] = {CEOF};
+char is_type[257] = {0};
+
+void init_syntax(void)
+{
+    char *tab;
+    int i;
+
+#define ndx(ch) (ch + 1 - CHAR_MIN)
+#define set(ch, val) tab[ndx(ch)] = val
+#define set_range(s, e, val) for (i = ndx(s); i <= ndx(e); i++) tab[i] = val
+
+    /*basesyntax*/
+    tab = basesyntax;
+    set_range(CTL_FIRST, CTL_LAST, CCTL);
+    set('\n', CNL);
+    set('\\', CBACK);
+    set('\'', CSQUOTE);
+    set('"', CDQUOTE);
+    set('`', CBQUOTE);
+    set('$', CVAR);
+    set('}', CENDVAR);
+    set('<', CSPCL);
+    set('>', CSPCL);
+    set('(', CSPCL);
+    set(')', CSPCL);
+    set(';', CSPCL);
+    set('&', CSPCL);
+    set('|', CSPCL);
+    set(' ', CSPCL);
+    set('\t', CSPCL);
+
+    tab = dqsyntax;
+    set_range(CTL_FIRST, CTL_LAST, CCTL);
+    set('\n', CNL);
+    set('\\', CBACK);
+    set('"', CDQUOTE);
+    set('`', CBQUOTE);
+    set('$', CVAR);
+    set('}', CENDVAR);
+    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+    set('!', CCTL);
+    set('*', CCTL);
+    set('?', CCTL);
+    set('[', CCTL);
+    set('=', CCTL);
+    set('~', CCTL);
+    set(':', CCTL);
+    set('/', CCTL);
+    set('-', CCTL);
+
+    tab = sqsyntax;
+    set_range(CTL_FIRST, CTL_LAST, CCTL);
+    set('\n', CNL);
+    set('\'', CSQUOTE);
+    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+    set('!', CCTL);
+    set('*', CCTL) ;
+    set('?', CCTL);
+    set('[', CCTL);
+    set('=', CCTL);
+    set('~', CCTL);
+    set(':', CCTL);
+    set('/', CCTL);
+    set('-', CCTL);
+
+    tab = arisyntax;
+    set_range(CTL_FIRST, CTL_LAST, CCTL);
+    set('\n', CNL);
+    set('\\', CBACK);
+    set('`', CBQUOTE);
+    set('\'', CSQUOTE);
+    set('"', CDQUOTE);
+    set('$', CVAR);
+    set('}', CENDVAR);
+    set('(', CLP);
+    set(')', CRP);
+
+    tab = is_type;
+    set_range('0', '9', ISDIGIT);
+    set_range('a', 'z', ISLOWER);
+    set_range('A', 'Z', ISUPPER);
+    set('_', ISUNDER);
+    set('#', ISSPECL);
+    set('?', ISSPECL);
+    set('$', ISSPECL);
+    set('!', ISSPECL);
+    set('-', ISSPECL);
+    set('*', ISSPECL);
+    set('@', ISSPECL);
+}
+
+#else /* !_MSC_VER */
+
+#if CWORD != 0
+#error initialisation assumes 'CWORD' is zero
+#endif
+
+#define ndx(ch) (ch + 1 - CHAR_MIN)
+#define set(ch, val) [ndx(ch)] = val,
+#define set_range(s, e, val) [ndx(s) ... ndx(e)] = val,
+
+/* syntax table used when not in quotes */
+const char basesyntax[257] = { CEOF,
+    set_range(CTL_FIRST, CTL_LAST, CCTL)
+    set('\n', CNL)
+    set('\\', CBACK)
+    set('\'', CSQUOTE)
+    set('"', CDQUOTE)
+    set('`', CBQUOTE)
+    set('$', CVAR)
+    set('}', CENDVAR)
+    set('<', CSPCL)
+    set('>', CSPCL)
+    set('(', CSPCL)
+    set(')', CSPCL)
+    set(';', CSPCL)
+    set('&', CSPCL)
+    set('|', CSPCL)
+    set(' ', CSPCL)
+    set('\t', CSPCL)
+};
+
+/* syntax table used when in double quotes */
+const char dqsyntax[257] = { CEOF,
+    set_range(CTL_FIRST, CTL_LAST, CCTL)
+    set('\n', CNL)
+    set('\\', CBACK)
+    set('"', CDQUOTE)
+    set('`', CBQUOTE)
+    set('$', CVAR)
+    set('}', CENDVAR)
+    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+    set('!', CCTL)
+    set('*', CCTL)
+    set('?', CCTL)
+    set('[', CCTL)
+    set('=', CCTL)
+    set('~', CCTL)
+    set(':', CCTL)
+    set('/', CCTL)
+    set('-', CCTL)
+};
+
+/* syntax table used when in single quotes */
+const char sqsyntax[257] = { CEOF,
+    set_range(CTL_FIRST, CTL_LAST, CCTL)
+    set('\n', CNL)
+    set('\'', CSQUOTE)
+    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+    set('!', CCTL)
+    set('*', CCTL)
+    set('?', CCTL)
+    set('[', CCTL)
+    set('=', CCTL)
+    set('~', CCTL)
+    set(':', CCTL)
+    set('/', CCTL)
+    set('-', CCTL)
+};
+
+/* syntax table used when in arithmetic */
+const char arisyntax[257] = { CEOF,
+    set_range(CTL_FIRST, CTL_LAST, CCTL)
+    set('\n', CNL)
+    set('\\', CBACK)
+    set('`', CBQUOTE)
+    set('\'', CSQUOTE)
+    set('"', CDQUOTE)
+    set('$', CVAR)
+    set('}', CENDVAR)
+    set('(', CLP)
+    set(')', CRP)
+};
+
+/* character classification table */
+const char is_type[257] = { 0,
+    set_range('0', '9', ISDIGIT)
+    set_range('a', 'z', ISLOWER)
+    set_range('A', 'Z', ISUPPER)
+    set('_', ISUNDER)
+    set('#', ISSPECL)
+    set('?', ISSPECL)
+    set('$', ISSPECL)
+    set('!', ISSPECL)
+    set('-', ISSPECL)
+    set('*', ISSPECL)
+    set('@', ISSPECL)
+};
+#endif /* !_MSC_VER */
Index: /tags/kBuild-0.1.4/src/ash/syntax.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/syntax.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/syntax.h	(revision 1780)
@@ -0,0 +1,93 @@
+/*	$NetBSD: syntax.h,v 1.2 2004/01/17 17:38:12 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#include <ctype.h>
+
+/* Syntax classes */
+#define CWORD 0			/* character is nothing special */
+#define CNL 1			/* newline character */
+#define CBACK 2			/* a backslash character */
+#define CSQUOTE 3		/* single quote */
+#define CDQUOTE 4		/* double quote */
+#define CBQUOTE 5		/* backwards single quote */
+#define CVAR 6			/* a dollar sign */
+#define CENDVAR 7		/* a '}' character */
+#define CLP 8			/* a left paren in arithmetic */
+#define CRP 9			/* a right paren in arithmetic */
+#define CEOF 10			/* end of file */
+#define CCTL 11			/* like CWORD, except it must be escaped */
+#define CSPCL 12		/* these terminate a word */
+
+/* Syntax classes for is_ functions */
+#define ISDIGIT 01		/* a digit */
+#define ISUPPER 02		/* an upper case letter */
+#define ISLOWER 04		/* a lower case letter */
+#define ISUNDER 010		/* an underscore */
+#define ISSPECL 020		/* the name of a special parameter */
+
+#define PEOF (CHAR_MIN - 1)
+#define SYNBASE (-PEOF)
+/* XXX UPEOF is CHAR_MAX, so is a valid 'char' value... */
+#define UPEOF ((char)PEOF)
+
+
+#define BASESYNTAX (basesyntax + SYNBASE)
+#define DQSYNTAX (dqsyntax + SYNBASE)
+#define SQSYNTAX (sqsyntax + SYNBASE)
+#define ARISYNTAX (arisyntax + SYNBASE)
+
+/* These defines assume that the digits are contiguous */
+#define is_digit(c)	((unsigned)((c) - '0') <= 9)
+#define is_alpha(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char)(c)))
+#define is_name(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char)(c))))
+#define is_in_name(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char)(c))))
+#define is_special(c)	((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
+#define digit_val(c)	((c) - '0')
+
+#ifdef _MSC_VER
+extern char basesyntax[];
+extern char dqsyntax[];
+extern char sqsyntax[];
+extern char arisyntax[];
+extern char is_type[];
+#else
+extern const char basesyntax[];
+extern const char dqsyntax[];
+extern const char sqsyntax[];
+extern const char arisyntax[];
+extern const char is_type[];
+#endif
Index: /tags/kBuild-0.1.4/src/ash/sys_signame.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/sys_signame.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/sys_signame.c	(revision 1780)
@@ -0,0 +1,121 @@
+/*
+ * Fake sys_signame.  
+ */
+
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+
+static char sys_signame_initialized = 0;
+char sys_signame[NSIG][16];
+              
+void init_sys_signame(void)
+{
+    unsigned i;
+	if (sys_signame_initialized)
+        return;
+    for (i = 0; i < NSIG; ++i)
+        sprintf(sys_signame[i], "%d", i);
+#define SET_SIG_STR(sig) strcpy(sys_signame[SIG##sig], #sig);
+#ifdef SIGHUP
+    SET_SIG_STR(HUP);
+#endif 
+#ifdef SIGINT
+    SET_SIG_STR(INT);
+#endif 
+#ifdef SIGQUIT
+    SET_SIG_STR(QUIT);
+#endif 
+#ifdef SIGILL
+    SET_SIG_STR(ILL);
+#endif 
+#ifdef SIGTRAP
+    SET_SIG_STR(TRAP);
+#endif 
+#ifdef SIGABRT
+    SET_SIG_STR(ABRT);
+#endif 
+#ifdef SIGIOT
+    SET_SIG_STR(IOT);
+#endif 
+#ifdef SIGBUS
+    SET_SIG_STR(BUS);
+#endif 
+#ifdef SIGFPE
+    SET_SIG_STR(FPE);
+#endif 
+#ifdef SIGKILL
+    SET_SIG_STR(KILL);
+#endif 
+#ifdef SIGUSR1
+    SET_SIG_STR(USR1);
+#endif 
+#ifdef SIGSEGV
+    SET_SIG_STR(SEGV);
+#endif 
+#ifdef SIGUSR2
+    SET_SIG_STR(USR2);
+#endif 
+#ifdef SIGPIPE
+    SET_SIG_STR(PIPE);
+#endif 
+#ifdef SIGALRM
+    SET_SIG_STR(ALRM);
+#endif 
+#ifdef SIGTERM
+    SET_SIG_STR(TERM);
+#endif 
+#ifdef SIGSTKFLT
+    SET_SIG_STR(STKFLT);
+#endif 
+#ifdef SIGCHLD
+    SET_SIG_STR(CHLD);
+#endif 
+#ifdef SIGCONT
+    SET_SIG_STR(CONT);
+#endif 
+#ifdef SIGSTOP
+    SET_SIG_STR(STOP);
+#endif 
+#ifdef SIGTSTP
+    SET_SIG_STR(TSTP);
+#endif 
+#ifdef SIGTTIN
+    SET_SIG_STR(TTIN);
+#endif 
+#ifdef SIGTTOU
+    SET_SIG_STR(TTOU);
+#endif 
+#ifdef SIGURG
+    SET_SIG_STR(URG);
+#endif 
+#ifdef SIGXCPU
+    SET_SIG_STR(XCPU);
+#endif 
+#ifdef SIGXFSZ
+    SET_SIG_STR(XFSZ);
+#endif 
+#ifdef SIGVTALRM
+    SET_SIG_STR(VTALRM);
+#endif 
+#ifdef SIGPROF
+    SET_SIG_STR(PROF);
+#endif 
+#ifdef SIGWINCH
+    SET_SIG_STR(WINCH);
+#endif 
+#ifdef SIGIO
+    SET_SIG_STR(IO);
+#endif 
+#ifdef SIGPWR
+    SET_SIG_STR(PWR);
+#endif 
+#ifdef SIGSYS
+    SET_SIG_STR(SYS);
+#endif 
+#ifdef SIGBREAK
+    SET_SIG_STR(BREAK);
+#endif 
+#undef SET_SIG_STR
+    sys_signame_initialized = 1;
+}
Index: /tags/kBuild-0.1.4/src/ash/trap.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/trap.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/trap.c	(revision 1780)
@@ -0,0 +1,468 @@
+/*	$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)trap.c	8.5 (Berkeley) 6/5/95";
+#else
+__RCSID("$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"	/* for other headers */
+#include "eval.h"
+#include "jobs.h"
+#include "show.h"
+#include "options.h"
+#include "syntax.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "trap.h"
+#include "mystring.h"
+#include "var.h"
+
+#ifndef HAVE_SYS_SIGNAME
+extern void init_sys_signame(void);
+extern char sys_signame[NSIG][16];
+#endif
+
+/*
+ * Sigmode records the current value of the signal handlers for the various
+ * modes.  A value of zero means that the current handler is not known.
+ * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
+ */
+
+#define S_DFL 1			/* default signal handling (SIG_DFL) */
+#define S_CATCH 2		/* signal is caught */
+#define S_IGN 3			/* signal is ignored (SIG_IGN) */
+#define S_HARD_IGN 4		/* signal is ignored permenantly */
+#define S_RESET 5		/* temporary - to reset a hard ignored sig */
+
+
+char *trap[NSIG+1];		/* trap handler commands */
+MKINIT char sigmode[NSIG];	/* current value of signal */
+char gotsig[NSIG];		/* indicates specified signal received */
+int pendingsigs;		/* indicates some signal received */
+
+#ifdef __sun__
+typedef void (*sig_t) (int);
+#endif
+static int getsigaction(int, sig_t *);
+
+/*
+ * return the signal number described by `p' (as a number or a name)
+ * or -1 if it isn't one
+ */
+
+static int
+signame_to_signum(const char *p)
+{
+	int i;
+
+	if (is_number(p))
+		return number(p);
+
+	if (strcasecmp(p, "exit") == 0 )
+		return 0;
+
+	if (strncasecmp(p, "sig", 3) == 0)
+		p += 3;
+
+#ifndef HAVE_SYS_SIGNAME
+	init_sys_signame();
+#endif
+	for (i = 0; i < NSIG; ++i)
+		if (strcasecmp (p, sys_signame[i]) == 0)
+			return i;
+	return -1;
+}
+
+/*
+ * Print a list of valid signal names
+ */
+static void
+printsignals(void)
+{
+	int n;
+
+	out1str("EXIT ");
+#ifndef HAVE_SYS_SIGNAME
+	init_sys_signame();
+#endif
+
+	for (n = 1; n < NSIG; n++) {
+		out1fmt("%s", sys_signame[n]);
+		if ((n == NSIG/2) ||  n == (NSIG - 1))
+			out1str("\n");
+		else
+			out1c(' ');
+	}
+}
+
+/*
+ * The trap builtin.
+ */
+
+int
+trapcmd(int argc, char **argv)
+{
+	char *action;
+	char **ap;
+	int signo;
+#ifndef HAVE_SYS_SIGNAME
+	init_sys_signame();
+#endif
+
+	if (argc <= 1) {
+		for (signo = 0 ; signo <= NSIG ; signo++)
+			if (trap[signo] != NULL) {
+				out1fmt("trap -- ");
+				print_quoted(trap[signo]);
+				out1fmt(" %s\n",
+				    (signo) ? sys_signame[signo] : "EXIT");
+			}
+		return 0;
+	}
+	ap = argv + 1;
+
+	action = NULL;
+
+	if (strcmp(*ap, "--") == 0)
+		if (*++ap == NULL)
+			return 0;
+
+	if (signame_to_signum(*ap) == -1) {
+		if ((*ap)[0] == '-') {
+			if ((*ap)[1] == '\0')
+				ap++;
+			else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') {
+				printsignals();
+				return 0;
+			}
+			else
+				error("bad option %s\n", *ap);
+		}
+		else
+			action = *ap++;
+	}
+
+	while (*ap) {
+		if (is_number(*ap))
+			signo = number(*ap);
+		else
+			signo = signame_to_signum(*ap);
+
+		if (signo < 0 || signo > NSIG)
+			error("%s: bad trap", *ap);
+
+		INTOFF;
+		if (action)
+			action = savestr(action);
+
+		if (trap[signo])
+			ckfree(trap[signo]);
+
+		trap[signo] = action;
+
+		if (signo != 0)
+			setsignal(signo, 0);
+		INTON;
+		ap++;
+	}
+	return 0;
+}
+
+
+
+/*
+ * Clear traps on a fork or vfork.
+ * Takes one arg vfork, to tell it to not be destructive of
+ * the parents variables.
+ */
+
+void
+clear_traps(int vforked)
+{
+	char **tp;
+
+	for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
+		if (*tp && **tp) {	/* trap not NULL or SIG_IGN */
+			INTOFF;
+			if (!vforked) {
+				ckfree(*tp);
+				*tp = NULL;
+			}
+			if (tp != &trap[0])
+				setsignal(tp - trap, vforked);
+			INTON;
+		}
+	}
+}
+
+
+
+/*
+ * Set the signal handler for the specified signal.  The routine figures
+ * out what it should be set to.
+ */
+
+long
+setsignal(int signo, int vforked)
+{
+	int action;
+	sig_t sigact = SIG_DFL;
+	char *t, tsig;
+
+	if ((t = trap[signo]) == NULL)
+		action = S_DFL;
+	else if (*t != '\0')
+		action = S_CATCH;
+	else
+		action = S_IGN;
+	if (rootshell && !vforked && action == S_DFL) {
+		switch (signo) {
+		case SIGINT:
+			if (iflag || minusc || sflag == 0)
+				action = S_CATCH;
+			break;
+		case SIGQUIT:
+#ifdef DEBUG
+			if (debug)
+				break;
+#endif
+			/* FALLTHROUGH */
+		case SIGTERM:
+			if (iflag)
+				action = S_IGN;
+			break;
+#if JOBS
+		case SIGTSTP:
+		case SIGTTOU:
+			if (mflag)
+				action = S_IGN;
+			break;
+#endif
+		}
+	}
+
+	t = &sigmode[signo - 1];
+	tsig = *t;
+	if (tsig == 0) {
+		/*
+		 * current setting unknown
+		 */
+		if (!getsigaction(signo, &sigact)) {
+			/*
+			 * Pretend it worked; maybe we should give a warning
+			 * here, but other shells don't. We don't alter
+			 * sigmode, so that we retry every time.
+			 */
+			return 0;
+		}
+		if (sigact == SIG_IGN) {
+			if (mflag && (signo == SIGTSTP ||
+			     signo == SIGTTIN || signo == SIGTTOU)) {
+				tsig = S_IGN;	/* don't hard ignore these */
+			} else
+				tsig = S_HARD_IGN;
+		} else {
+			tsig = S_RESET;	/* force to be set */
+		}
+	}
+	if (tsig == S_HARD_IGN || tsig == action)
+		return 0;
+	switch (action) {
+		case S_DFL:	sigact = SIG_DFL;	break;
+		case S_CATCH:  	sigact = onsig;		break;
+		case S_IGN:	sigact = SIG_IGN;	break;
+	}
+	if (!vforked)
+		*t = action;
+	siginterrupt(signo, 1);
+	return (long)signal(signo, sigact);
+}
+
+/*
+ * Return the current setting for sig w/o changing it.
+ */
+static int
+getsigaction(int signo, sig_t *sigact)
+{
+	struct sigaction sa;
+
+	if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
+		return 0;
+	*sigact = (sig_t) sa.sa_handler;
+	return 1;
+}
+
+/*
+ * Ignore a signal.
+ */
+
+void
+ignoresig(int signo, int vforked)
+{
+	if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
+		signal(signo, SIG_IGN);
+	}
+	if (!vforked)
+		sigmode[signo - 1] = S_HARD_IGN;
+}
+
+
+#ifdef mkinit
+INCLUDE <signal.h>
+INCLUDE "trap.h"
+
+SHELLPROC {
+	char *sm;
+
+	clear_traps(0);
+	for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
+		if (*sm == S_IGN)
+			*sm = S_HARD_IGN;
+	}
+}
+#endif
+
+
+
+/*
+ * Signal handler.
+ */
+
+void
+onsig(int signo)
+{
+	signal(signo, onsig);
+	if (signo == SIGINT && trap[SIGINT] == NULL) {
+		onint();
+		return;
+	}
+	gotsig[signo - 1] = 1;
+	pendingsigs++;
+}
+
+
+
+/*
+ * Called to execute a trap.  Perhaps we should avoid entering new trap
+ * handlers while we are executing a trap handler.
+ */
+
+void
+dotrap(void)
+{
+	int i;
+	int savestatus;
+
+	for (;;) {
+		for (i = 1 ; ; i++) {
+			if (gotsig[i - 1])
+				break;
+			if (i >= NSIG)
+				goto done;
+		}
+		gotsig[i - 1] = 0;
+		savestatus=exitstatus;
+		evalstring(trap[i], 0);
+		exitstatus=savestatus;
+	}
+done:
+	pendingsigs = 0;
+}
+
+
+
+/*
+ * Controls whether the shell is interactive or not.
+ */
+
+
+void
+setinteractive(int on)
+{
+	static int is_interactive;
+
+	if (on == is_interactive)
+		return;
+	setsignal(SIGINT, 0);
+	setsignal(SIGQUIT, 0);
+	setsignal(SIGTERM, 0);
+	is_interactive = on;
+}
+
+
+
+/*
+ * Called to exit the shell.
+ */
+
+void
+exitshell(int status)
+{
+	struct jmploc loc1, loc2;
+	char *p;
+
+	TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
+	if (setjmp(loc1.loc)) {
+		goto l1;
+	}
+	if (setjmp(loc2.loc)) {
+		goto l2;
+	}
+	handler = &loc1;
+	if ((p = trap[0]) != NULL && *p != '\0') {
+		trap[0] = NULL;
+		evalstring(p, 0);
+	}
+l1:   handler = &loc2;			/* probably unnecessary */
+	output_flushall();
+#if JOBS
+	setjobctl(0);
+#endif
+l2:   _exit(status);
+	/* NOTREACHED */
+}
Index: /tags/kBuild-0.1.4/src/ash/trap.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/trap.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/trap.h	(revision 1780)
@@ -0,0 +1,46 @@
+/*	$NetBSD: trap.h,v 1.17 2003/08/07 09:05:39 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)trap.h	8.3 (Berkeley) 6/5/95
+ */
+
+extern int pendingsigs;
+
+int trapcmd(int, char **);
+void clear_traps(int);
+long setsignal(int, int);
+void ignoresig(int, int);
+void onsig(int);
+void dotrap(void);
+void setinteractive(int);
+void exitshell(int) __attribute__((__noreturn__));
Index: /tags/kBuild-0.1.4/src/ash/var.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/var.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/var.c	(revision 1780)
@@ -0,0 +1,933 @@
+/*	$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $");
+#endif
+#endif /* not lint */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <strings.h>
+#ifndef __sun__
+#include <paths.h>
+#else
+#define _PATH_DEFPATH        "/usr/bin:/usr/sbin"
+#include <iso/limits_iso.h>
+#endif
+
+#ifdef PC_OS2_LIBPATHS
+#define INCL_BASE
+#include <os2.h>
+
+#ifndef LIBPATHSTRICT
+#define LIBPATHSTRICT 3
+#endif
+
+extern APIRET
+#ifdef APIENTRY
+    APIENTRY
+#endif
+    DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
+#define QHINF_EXEINFO       1 /* NE exeinfo. */
+#define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
+#define QHINF_READFILE      3 /* Reads from the executable file. */
+#define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
+#define QHINF_LIBPATH       5 /* Gets the entire libpath. */
+#define QHINF_FIXENTRY      6 /* NE only */
+#define QHINF_STE           7 /* NE only */
+#define QHINF_MAPSEL        8 /* NE only */
+
+#endif
+
+
+/*
+ * Shell variables.
+ */
+
+#include "shell.h"
+#include "output.h"
+#include "expand.h"
+#include "nodes.h"	/* for other headers */
+#include "eval.h"	/* defines cmdenviron */
+#include "exec.h"
+#include "syntax.h"
+#include "options.h"
+#include "mail.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "parser.h"
+#include "show.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+
+#ifdef SMALL
+#define VTABSIZE 39
+#else
+#define VTABSIZE 517
+#endif
+
+
+struct varinit {
+	struct var *var;
+	int flags;
+	const char *text;
+	void (*func)(const char *);
+};
+
+
+#if ATTY
+struct var vatty;
+#endif
+#ifndef SMALL
+struct var vhistsize;
+struct var vterm;
+#endif
+struct var vifs;
+struct var vmail;
+struct var vmpath;
+struct var vpath;
+#ifdef _MSC_VER
+struct var vpath2;
+#endif
+struct var vps1;
+struct var vps2;
+struct var vps4;
+struct var vvers;
+struct var voptind;
+
+#ifdef PC_OS2_LIBPATHS
+static struct var libpath_vars[4];
+static const char *libpath_envs[4] = {"LIBPATH=", "BEGINLIBPATH=", "ENDLIBPATH=", "LIBPATHSTRICT="};
+#endif
+
+const struct varinit varinit[] = {
+#if ATTY
+	{ &vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",
+	  NULL },
+#endif
+#ifndef SMALL
+	{ &vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",
+	  sethistsize },
+#endif
+	{ &vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n",
+	  NULL },
+	{ &vmail,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL=",
+	  NULL },
+	{ &vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",
+	  NULL },
+	{ &vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=" _PATH_DEFPATH,
+	  changepath },
+#ifdef _MSC_VER
+	{ &vpath2,	VSTRFIXED|VTEXTFIXED,		"Path=",
+	  changepath },
+#endif
+	/*
+	 * vps1 depends on uid
+	 */
+	{ &vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",
+	  NULL },
+	{ &vps4,	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",
+	  NULL },
+#ifndef SMALL
+	{ &vterm,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM=",
+	  setterm },
+#endif
+	{ &voptind,	VSTRFIXED|VTEXTFIXED|VNOFUNC,	"OPTIND=1",
+	  getoptsreset },
+	{ NULL,	0,				NULL,
+	  NULL }
+};
+
+struct var *vartab[VTABSIZE];
+
+STATIC int strequal(const char *, const char *);
+STATIC struct var *find_var(const char *, struct var ***, int *);
+
+/*
+ * Initialize the varable symbol tables and import the environment
+ */
+
+#ifdef mkinit
+INCLUDE "var.h"
+MKINIT char **environ;
+INIT {
+	char **envp;
+
+	initvar();
+	for (envp = environ ; *envp ; envp++) {
+		if (strchr(*envp, '=')) {
+			setvareq(*envp, VEXPORT|VTEXTFIXED);
+		}
+	}
+}
+#endif
+
+
+/*
+ * This routine initializes the builtin variables.  It is called when the
+ * shell is initialized and again when a shell procedure is spawned.
+ */
+
+void
+initvar(void)
+{
+	const struct varinit *ip;
+	struct var *vp;
+	struct var **vpp;
+
+#ifdef PC_OS2_LIBPATHS
+        char *psz = ckmalloc(2048);
+        int rc;
+        int i;
+        for (i = 0; i < 4; i++)
+        {
+            libpath_vars[i].flags = VSTRFIXED | VOS2LIBPATH;
+            libpath_vars[i].func = NULL;
+
+            if (i > 0)
+            {
+                psz[0] = psz[1] = psz[2] = psz[3] = '\0'; 
+                rc = DosQueryExtLIBPATH(psz, i);
+            }
+            else
+            {
+                rc = DosQueryHeaderInfo(NULLHANDLE, 0, psz, 2048, QHINF_LIBPATH);
+                libpath_vars[i].flags |= VREADONLY;
+            }
+            if (!rc && *psz)
+            {
+                int cch1 = strlen(libpath_envs[i]);
+                int cch2 = strlen(psz) + 1;
+                libpath_vars[i].text = ckmalloc(cch1 + cch2);
+                memcpy(libpath_vars[i].text, libpath_envs[i], cch1);
+                memcpy(libpath_vars[i].text + cch1, psz, cch2);
+            }
+            else
+            {
+                libpath_vars[i].flags |= VUNSET | VTEXTFIXED;
+                libpath_vars[i].text = (char*)libpath_envs[i];
+            }
+            if (find_var(libpath_vars[i].text, &vpp, &libpath_vars[i].name_len) != NULL)
+                    continue;
+            libpath_vars[i].next = *vpp;
+            *vpp = &libpath_vars[i];
+        }
+        free(psz);
+#endif
+
+	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
+		if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
+			continue;
+		vp->next = *vpp;
+		*vpp = vp;
+		vp->text = strdup(ip->text);
+		vp->flags = ip->flags;
+		vp->func = ip->func;
+	}
+	/*
+	 * PS1 depends on uid
+	 */
+	if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {
+		vps1.next = *vpp;
+		*vpp = &vps1;
+		vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
+		vps1.flags = VSTRFIXED|VTEXTFIXED;
+	}
+}
+
+/*
+ * Safe version of setvar, returns 1 on success 0 on failure.
+ */
+
+int
+setvarsafe(const char *name, const char *val, int flags)
+{
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler = handler;
+	int err = 0;
+#ifdef __GNUC__
+	(void) &err;
+#endif
+
+	if (setjmp(jmploc.loc))
+		err = 1;
+	else {
+		handler = &jmploc;
+		setvar(name, val, flags);
+	}
+	handler = savehandler;
+	return err;
+}
+
+/*
+ * Set the value of a variable.  The flags argument is ored with the
+ * flags of the variable.  If val is NULL, the variable is unset.
+ */
+
+void
+setvar(const char *name, const char *val, int flags)
+{
+	const char *p;
+	const char *q;
+	char *d;
+	int len;
+	int namelen;
+	char *nameeq;
+	int isbad;
+
+	isbad = 0;
+	p = name;
+	if (! is_name(*p))
+		isbad = 1;
+	p++;
+	for (;;) {
+		if (! is_in_name(*p)) {
+			if (*p == '\0' || *p == '=')
+				break;
+			isbad = 1;
+		}
+		p++;
+	}
+	namelen = p - name;
+	if (isbad)
+		error("%.*s: bad variable name", namelen, name);
+	len = namelen + 2;		/* 2 is space for '=' and '\0' */
+	if (val == NULL) {
+		flags |= VUNSET;
+	} else {
+		len += strlen(val);
+	}
+	d = nameeq = ckmalloc(len);
+	q = name;
+	while (--namelen >= 0)
+		*d++ = *q++;
+	*d++ = '=';
+	*d = '\0';
+	if (val)
+		scopy(val, d);
+	setvareq(nameeq, flags);
+}
+
+
+
+/*
+ * Same as setvar except that the variable and value are passed in
+ * the first argument as name=value.  Since the first argument will
+ * be actually stored in the table, it should not be a string that
+ * will go away.
+ */
+
+void
+setvareq(char *s, int flags)
+{
+	struct var *vp, **vpp;
+	int nlen;
+
+	if (aflag)
+		flags |= VEXPORT;
+	vp = find_var(s, &vpp, &nlen);
+	if (vp != NULL) {
+		if (vp->flags & VREADONLY)
+			error("%.*s: is read only", vp->name_len, s);
+		if (flags & VNOSET)
+			return;
+		INTOFF;
+
+		if (vp->func && (flags & VNOFUNC) == 0)
+			(*vp->func)(s + vp->name_len + 1);
+
+		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
+			ckfree(vp->text);
+
+		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
+		vp->flags |= flags & ~VNOFUNC;
+		vp->text = s;
+#ifdef PC_OS2_LIBPATHS
+                if ((vp->flags & VOS2LIBPATH) && (vp->flags & VEXPORT))
+                    vp->flags &= ~VEXPORT;
+#endif
+
+		/*
+		 * We could roll this to a function, to handle it as
+		 * a regular variable function callback, but why bother?
+		 */
+		if (vp == &vmpath || (vp == &vmail && ! mpathset()))
+			chkmail(1);
+		INTON;
+		return;
+	}
+	/* not found */
+	if (flags & VNOSET)
+		return;
+	vp = ckmalloc(sizeof (*vp));
+	vp->flags = flags & ~VNOFUNC;
+	vp->text = s;
+	vp->name_len = nlen;
+	vp->next = *vpp;
+	vp->func = NULL;
+	*vpp = vp;
+}
+
+
+
+/*
+ * Process a linked list of variable assignments.
+ */
+
+void
+listsetvar(struct strlist *list, int flags)
+{
+	struct strlist *lp;
+
+	INTOFF;
+	for (lp = list ; lp ; lp = lp->next) {
+		setvareq(savestr(lp->text), flags);
+	}
+	INTON;
+}
+
+void
+listmklocal(struct strlist *list, int flags)
+{
+	struct strlist *lp;
+
+	for (lp = list ; lp ; lp = lp->next)
+		mklocal(lp->text, flags);
+}
+
+
+/*
+ * Find the value of a variable.  Returns NULL if not set.
+ */
+
+char *
+lookupvar(const char *name)
+{
+	struct var *v;
+
+	v = find_var(name, NULL, NULL);
+	if (v == NULL || v->flags & VUNSET)
+		return NULL;
+	return v->text + v->name_len + 1;
+}
+
+
+
+/*
+ * Search the environment of a builtin command.  If the second argument
+ * is nonzero, return the value of a variable even if it hasn't been
+ * exported.
+ */
+
+char *
+bltinlookup(const char *name, int doall)
+{
+	struct strlist *sp;
+	struct var *v;
+
+	for (sp = cmdenviron ; sp ; sp = sp->next) {
+		if (strequal(sp->text, name))
+			return strchr(sp->text, '=') + 1;
+	}
+
+	v = find_var(name, NULL, NULL);
+
+	if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT)))
+		return NULL;
+	return v->text + v->name_len + 1;
+}
+
+
+
+/*
+ * Generate a list of exported variables.  This routine is used to construct
+ * the third argument to execve when executing a program.
+ */
+
+char **
+environment(void)
+{
+	int nenv;
+	struct var **vpp;
+	struct var *vp;
+	char **env;
+	char **ep;
+
+	nenv = 0;
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next)
+			if (vp->flags & VEXPORT)
+				nenv++;
+	}
+	ep = env = stalloc((nenv + 1) * sizeof *env);
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next)
+			if (vp->flags & VEXPORT)
+				*ep++ = vp->text;
+	}
+	*ep = NULL;
+
+#ifdef PC_OS2_LIBPATHS
+        /*
+         * Set the libpaths now as this is exec() time.
+         */
+        for (nenv = 0; nenv < 3; nenv++)
+            DosSetExtLIBPATH(strchr(libpath_vars[nenv].text, '=') + 1, nenv);
+#endif
+
+	return env;
+}
+
+
+/*
+ * Called when a shell procedure is invoked to clear out nonexported
+ * variables.  It is also necessary to reallocate variables of with
+ * VSTACK set since these are currently allocated on the stack.
+ */
+
+#ifdef mkinit
+void shprocvar(void);
+
+SHELLPROC {
+	shprocvar();
+}
+#endif
+
+void
+shprocvar(void)
+{
+	struct var **vpp;
+	struct var *vp, **prev;
+
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (prev = vpp ; (vp = *prev) != NULL ; ) {
+			if ((vp->flags & VEXPORT) == 0) {
+				*prev = vp->next;
+				if ((vp->flags & VTEXTFIXED) == 0)
+					ckfree(vp->text);
+				if ((vp->flags & VSTRFIXED) == 0)
+					ckfree(vp);
+			} else {
+				if (vp->flags & VSTACK) {
+					vp->text = savestr(vp->text);
+					vp->flags &=~ VSTACK;
+				}
+				prev = &vp->next;
+			}
+		}
+	}
+	initvar();
+}
+
+
+
+/*
+ * Command to list all variables which are set.  Currently this command
+ * is invoked from the set command when the set command is called without
+ * any variables.
+ */
+
+void
+print_quoted(const char *p)
+{
+	const char *q;
+
+	if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) {
+		out1fmt("%s", p);
+		return;
+	}
+	while (*p) {
+		if (*p == '\'') {
+			out1fmt("\\'");
+			p++;
+			continue;
+		}
+		q = index(p, '\'');
+		if (!q) {
+			out1fmt("'%s'", p );
+			return;
+		}
+		out1fmt("'%.*s'", (int)(q - p), p );
+		p = q;
+	}
+}
+
+static int
+sort_var(const void *v_v1, const void *v_v2)
+{
+	const struct var * const *v1 = v_v1;
+	const struct var * const *v2 = v_v2;
+
+	/* XXX Will anyone notice we include the '=' of the shorter name? */
+	return strcoll((*v1)->text, (*v2)->text);
+}
+
+/*
+ * POSIX requires that 'set' (but not export or readonly) output the
+ * variables in lexicographic order - by the locale's collating order (sigh).
+ * Maybe we could keep them in an ordered balanced binary tree
+ * instead of hashed lists.
+ * For now just roll 'em through qsort for printing...
+ */
+
+int
+showvars(const char *name, int flag, int show_value)
+{
+	struct var **vpp;
+	struct var *vp;
+	const char *p;
+
+	static struct var **list;	/* static in case we are interrupted */
+	static int list_len;
+	int count = 0;
+
+	if (!list) {
+		list_len = 32;
+		list = ckmalloc(list_len * sizeof *list);
+	}
+
+	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next) {
+			if (flag && !(vp->flags & flag))
+				continue;
+			if (vp->flags & VUNSET && !(show_value & 2))
+				continue;
+			if (count >= list_len) {
+				list = ckrealloc(list,
+					(list_len << 1) * sizeof *list);
+				list_len <<= 1;
+			}
+			list[count++] = vp;
+		}
+	}
+
+	qsort(list, count, sizeof *list, sort_var);
+
+	for (vpp = list; count--; vpp++) {
+		vp = *vpp;
+		if (name)
+			out1fmt("%s ", name);
+		for (p = vp->text ; *p != '=' ; p++)
+			out1c(*p);
+		if (!(vp->flags & VUNSET) && show_value) {
+			out1fmt("=");
+			print_quoted(++p);
+		}
+		out1c('\n');
+	}
+	return 0;
+}
+
+
+
+/*
+ * The export and readonly commands.
+ */
+
+int
+exportcmd(int argc, char **argv)
+{
+	struct var *vp;
+	char *name;
+	const char *p;
+	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
+	int pflag;
+
+	pflag = nextopt("p") == 'p' ? 3 : 0;
+	if (argc <= 1 || pflag) {
+		showvars( pflag ? argv[0] : 0, flag, pflag );
+		return 0;
+	}
+
+	while ((name = *argptr++) != NULL) {
+		if ((p = strchr(name, '=')) != NULL) {
+			p++;
+		} else {
+			vp = find_var(name, NULL, NULL);
+			if (vp != NULL) {
+				vp->flags |= flag;
+				continue;
+			}
+		}
+		setvar(name, p, flag);
+	}
+	return 0;
+}
+
+
+/*
+ * The "local" command.
+ */
+
+int
+localcmd(int argc, char **argv)
+{
+	char *name;
+
+	if (! in_function())
+		error("Not in a function");
+	while ((name = *argptr++) != NULL) {
+		mklocal(name, 0);
+	}
+	return 0;
+}
+
+
+/*
+ * Make a variable a local variable.  When a variable is made local, it's
+ * value and flags are saved in a localvar structure.  The saved values
+ * will be restored when the shell function returns.  We handle the name
+ * "-" as a special case.
+ */
+
+void
+mklocal(const char *name, int flags)
+{
+	struct localvar *lvp;
+	struct var **vpp;
+	struct var *vp;
+
+	INTOFF;
+	lvp = ckmalloc(sizeof (struct localvar));
+	if (name[0] == '-' && name[1] == '\0') {
+		char *p;
+		p = ckmalloc(sizeof_optlist);
+		lvp->text = memcpy(p, optlist, sizeof_optlist);
+		vp = NULL;
+	} else {
+		vp = find_var(name, &vpp, NULL);
+		if (vp == NULL) {
+			if (strchr(name, '='))
+				setvareq(savestr(name), VSTRFIXED|flags);
+			else
+				setvar(name, NULL, VSTRFIXED|flags);
+			vp = *vpp;	/* the new variable */
+			lvp->text = NULL;
+			lvp->flags = VUNSET;
+		} else {
+			lvp->text = vp->text;
+			lvp->flags = vp->flags;
+			vp->flags |= VSTRFIXED|VTEXTFIXED;
+			if (name[vp->name_len] == '=')
+				setvareq(savestr(name), flags);
+		}
+	}
+	lvp->vp = vp;
+	lvp->next = localvars;
+	localvars = lvp;
+	INTON;
+}
+
+
+/*
+ * Called after a function returns.
+ */
+
+void
+poplocalvars(void)
+{
+	struct localvar *lvp;
+	struct var *vp;
+
+	while ((lvp = localvars) != NULL) {
+		localvars = lvp->next;
+		vp = lvp->vp;
+		TRACE(("poplocalvar %s", vp ? vp->text : "-"));
+		if (vp == NULL) {	/* $- saved */
+			memcpy(optlist, lvp->text, sizeof_optlist);
+			ckfree(lvp->text);
+		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
+			(void)unsetvar(vp->text, 0);
+		} else {
+			if (vp->func && (vp->flags & VNOFUNC) == 0)
+				(*vp->func)(lvp->text + vp->name_len + 1);
+			if ((vp->flags & VTEXTFIXED) == 0)
+				ckfree(vp->text);
+			vp->flags = lvp->flags;
+			vp->text = lvp->text;
+		}
+		ckfree(lvp);
+	}
+}
+
+
+int
+setvarcmd(int argc, char **argv)
+{
+	if (argc <= 2)
+		return unsetcmd(argc, argv);
+	else if (argc == 3)
+		setvar(argv[1], argv[2], 0);
+	else
+		error("List assignment not implemented");
+	return 0;
+}
+
+
+/*
+ * The unset builtin command.  We unset the function before we unset the
+ * variable to allow a function to be unset when there is a readonly variable
+ * with the same name.
+ */
+
+int
+unsetcmd(int argc, char **argv)
+{
+	char **ap;
+	int i;
+	int flg_func = 0;
+	int flg_var = 0;
+	int ret = 0;
+
+	while ((i = nextopt("evf")) != '\0') {
+		if (i == 'f')
+			flg_func = 1;
+		else
+			flg_var = i;
+	}
+	if (flg_func == 0 && flg_var == 0)
+		flg_var = 1;
+
+	for (ap = argptr; *ap ; ap++) {
+		if (flg_func)
+			ret |= unsetfunc(*ap);
+		if (flg_var)
+			ret |= unsetvar(*ap, flg_var == 'e');
+	}
+	return ret;
+}
+
+
+/*
+ * Unset the specified variable.
+ */
+
+int
+unsetvar(const char *s, int unexport)
+{
+	struct var **vpp;
+	struct var *vp;
+
+	vp = find_var(s, &vpp, NULL);
+	if (vp == NULL)
+		return 1;
+
+	if (vp->flags & VREADONLY)
+		return (1);
+
+	INTOFF;
+	if (unexport) {
+		vp->flags &= ~VEXPORT;
+	} else {
+		if (vp->text[vp->name_len + 1] != '\0')
+			setvar(s, nullstr, 0);
+		vp->flags &= ~VEXPORT;
+		vp->flags |= VUNSET;
+		if ((vp->flags & VSTRFIXED) == 0) {
+			if ((vp->flags & VTEXTFIXED) == 0)
+				ckfree(vp->text);
+			*vpp = vp->next;
+			ckfree(vp);
+		}
+	}
+	INTON;
+	return 0;
+}
+
+
+/*
+ * Returns true if the two strings specify the same varable.  The first
+ * variable name is terminated by '='; the second may be terminated by
+ * either '=' or '\0'.
+ */
+
+STATIC int
+strequal(const char *p, const char *q)
+{
+	while (*p == *q++) {
+		if (*p++ == '=')
+			return 1;
+	}
+	if (*p == '=' && *(q - 1) == '\0')
+		return 1;
+	return 0;
+}
+
+/*
+ * Search for a variable.
+ * 'name' may be terminated by '=' or a NUL.
+ * vppp is set to the pointer to vp, or the list head if vp isn't found
+ * lenp is set to the number of charactets in 'name'
+ */
+
+STATIC struct var *
+find_var(const char *name, struct var ***vppp, int *lenp)
+{
+	unsigned int hashval;
+	int len;
+	struct var *vp, **vpp;
+	const char *p = name;
+
+	hashval = 0;
+	while (*p && *p != '=')
+		hashval = 2 * hashval + (unsigned char)*p++;
+	len = p - name;
+
+	if (lenp)
+		*lenp = len;
+	vpp = &vartab[hashval % VTABSIZE];
+	if (vppp)
+		*vppp = vpp;
+
+	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
+		if (vp->name_len != len)
+			continue;
+		if (memcmp(vp->text, name, len) != 0)
+			continue;
+		if (vppp)
+			*vppp = vpp;
+		return vp;
+	}
+	return NULL;
+}
Index: /tags/kBuild-0.1.4/src/ash/var.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/var.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/var.h	(revision 1780)
@@ -0,0 +1,143 @@
+/*	$NetBSD: var.h,v 1.23 2004/10/02 12:16:53 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)var.h	8.2 (Berkeley) 5/4/95
+ */
+
+/*
+ * Shell variables.
+ */
+
+/* flags */
+#define VEXPORT		0x01	/* variable is exported */
+#define VREADONLY	0x02	/* variable cannot be modified */
+#define VSTRFIXED	0x04	/* variable struct is statically allocated */
+#define VTEXTFIXED	0x08	/* text is statically allocated */
+#define VSTACK		0x10	/* text is allocated on the stack */
+#define VUNSET		0x20	/* the variable is not set */
+#define VNOFUNC		0x40	/* don't call the callback function */
+#define VNOSET		0x80	/* do not set variable - just readonly test */
+#ifdef PC_OS2_LIBPATHS
+#define VOS2LIBPATH     0x8000  /* OS/2 LIBPATH related variable. */
+#endif
+
+
+struct var {
+	struct var *next;		/* next entry in hash list */
+	int flags;			/* flags are defined above */
+	char *text;			/* name=value */
+	int name_len;			/* length of name */
+	void (*func)(const char *);
+					/* function to be called when  */
+					/* the variable gets set/unset */
+};
+
+
+struct localvar {
+	struct localvar *next;		/* next local variable in list */
+	struct var *vp;			/* the variable that was made local */
+	int flags;			/* saved flags */
+	char *text;			/* saved text */
+};
+
+
+struct localvar *localvars;
+
+#if ATTY
+extern struct var vatty;
+#endif
+extern struct var vifs;
+extern struct var vmail;
+extern struct var vmpath;
+extern struct var vpath;
+#ifdef _MSC_VER
+extern struct var vpath2;
+#endif 
+extern struct var vps1;
+extern struct var vps2;
+extern struct var vps4;
+#ifndef SMALL
+extern struct var vterm;
+extern struct var vtermcap;
+extern struct var vhistsize;
+#endif
+
+/*
+ * The following macros access the values of the above variables.
+ * They have to skip over the name.  They return the null string
+ * for unset variables.
+ */
+
+#define ifsval()	(vifs.text + 4)
+#define ifsset()	((vifs.flags & VUNSET) == 0)
+#define mailval()	(vmail.text + 5)
+#define mpathval()	(vmpath.text + 9)
+#ifdef _MSC_VER
+#define pathval()	(vpath.text[5] ? &vpath.text[5] : &vpath2.text[5])
+#else
+#define pathval()	(vpath.text + 5)
+#endif
+#define ps1val()	(vps1.text + 4)
+#define ps2val()	(vps2.text + 4)
+#define ps4val()	(vps4.text + 4)
+#define optindval()	(voptind.text + 7)
+#ifndef SMALL
+#define histsizeval()	(vhistsize.text + 9)
+#define termval()	(vterm.text + 5)
+#endif
+
+#if ATTY
+#define attyset()	((vatty.flags & VUNSET) == 0)
+#endif
+#define mpathset()	((vmpath.flags & VUNSET) == 0)
+
+void initvar(void);
+void setvar(const char *, const char *, int);
+void setvareq(char *, int);
+struct strlist;
+void listsetvar(struct strlist *, int);
+char *lookupvar(const char *);
+char *bltinlookup(const char *, int);
+char **environment(void);
+void shprocvar(void);
+int showvars(const char *, int, int);
+int exportcmd(int, char **);
+int localcmd(int, char **);
+void mklocal(const char *, int);
+void listmklocal(struct strlist *, int);
+void poplocalvars(void);
+int setvarcmd(int, char **);
+int unsetcmd(int, char **);
+int unsetvar(const char *, int);
+int setvarsafe(const char *, const char *, int);
+void print_quoted(const char *);
Index: /tags/kBuild-0.1.4/src/ash/win/dirent.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/dirent.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/dirent.c	(revision 1780)
@@ -0,0 +1,206 @@
+/* Directory entry code for Window platforms.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "dirent.h"
+
+
+DIR*
+opendir(const char* pDirName)
+{
+	struct stat sb;
+	DIR*	pDir;
+	char*	pEndDirName;
+	int	nBufferLen;
+
+	/* sanity checks */
+	if (!pDirName) {
+		errno = EINVAL;
+		return NULL;
+	}
+	if (stat(pDirName, &sb) != 0) {
+		errno = ENOENT;
+		return NULL;
+	}
+	if ((sb.st_mode & S_IFMT) != S_IFDIR) {
+		errno = ENOTDIR;
+		return NULL;
+	}
+
+	/* allocate a DIR structure to return */
+	pDir = (DIR *) malloc(sizeof (DIR));
+
+	if (!pDir)
+		return NULL;
+
+	/* input directory name length */
+	nBufferLen = strlen(pDirName);
+
+	/* copy input directory name to DIR buffer */
+	strcpy(pDir->dir_pDirectoryName, pDirName);
+
+	/* point to end of the copied directory name */
+	pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];
+
+	/* if directory name did not end in '/' or '\', add '/' */
+	if ((*pEndDirName != '/') && (*pEndDirName != '\\')) {
+		pEndDirName++;
+		*pEndDirName = '/';
+	}
+
+	/* now append the wildcard character to the buffer */
+	pEndDirName++;
+	*pEndDirName = '*';
+	pEndDirName++;
+	*pEndDirName = '\0';
+
+	/* other values defaulted */
+	pDir->dir_nNumFiles = 0;
+	pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
+	pDir->dir_ulCookie = __DIRENT_COOKIE;
+
+	return pDir;
+}
+
+void
+closedir(DIR *pDir)
+{
+	/* got a valid pointer? */
+	if (!pDir) {
+		errno = EINVAL;
+		return;
+	}
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
+		errno = EINVAL;
+		return;
+	}
+
+	/* close the WINDOWS32 directory handle */
+	if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
+		FindClose(pDir->dir_hDirHandle);
+
+	free(pDir);
+
+	return;
+}
+
+struct dirent *
+readdir(DIR* pDir)
+{
+	WIN32_FIND_DATA wfdFindData;
+
+	if (!pDir) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (pDir->dir_nNumFiles == 0) {
+		pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);
+		if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)
+			return NULL;
+	} else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))
+			return NULL;
+
+	/* bump count for next call to readdir() or telldir() */
+	pDir->dir_nNumFiles++;
+
+	/* fill in struct dirent values */
+	pDir->dir_sdReturn.d_ino = -1;
+	strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
+
+	return &pDir->dir_sdReturn;
+}
+
+void
+rewinddir(DIR* pDir)
+{
+	if (!pDir) {
+		errno = EINVAL;
+		return;
+	}
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
+		errno = EINVAL;
+		return;
+	}
+
+	/* close the WINDOWS32 directory handle */
+	if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
+		if (!FindClose(pDir->dir_hDirHandle))
+			errno = EBADF;
+
+	/* reset members which control readdir() */
+	pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
+	pDir->dir_nNumFiles = 0;
+
+	return;
+}
+
+int
+telldir(DIR* pDir)
+{
+	if (!pDir) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* return number of times readdir() called */
+	return pDir->dir_nNumFiles;
+}
+
+void
+seekdir(DIR* pDir, long nPosition)
+{
+	if (!pDir)
+		return;
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE)
+		return;
+
+	/* go back to beginning of directory */
+	rewinddir(pDir);
+
+	/* loop until we have found position we care about */
+	for (--nPosition; nPosition && readdir(pDir); nPosition--);
+
+	/* flag invalid nPosition value */
+	if (nPosition)
+		errno = EINVAL;
+
+	return;
+}
Index: /tags/kBuild-0.1.4/src/ash/win/err.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/err.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/err.c	(revision 1780)
@@ -0,0 +1,85 @@
+/* $Id$ */
+/** @file
+ *
+ * Override err.h so we get the program name right.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include "err.h"
+
+
+/** The current program name. */
+const char *g_progname = "kmk";
+
+
+int err(int eval, const char *fmt, ...)
+{
+    va_list args;
+    int error = errno;
+    fprintf(stderr, "%s: ", g_progname);
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, ": %s\n", strerror(error));
+
+    return eval;
+}
+
+
+int errx(int eval, const char *fmt, ...)
+{
+    va_list args;
+    fprintf(stderr, "%s: ", g_progname);
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, "\n");
+
+    return eval;
+}
+
+void warn(const char *fmt, ...)
+{
+    int error = errno;
+    va_list args;
+    fprintf(stderr, "%s: ", g_progname);
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, ": %s\n", strerror(error));
+}
+
+void warnx(const char *fmt, ...)
+{
+    int err = errno;
+    va_list args;
+    fprintf(stderr, "%s: ", g_progname);
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, "\n");
+}
+
Index: /tags/kBuild-0.1.4/src/ash/win/err.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/err.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/err.h	(revision 1780)
@@ -0,0 +1,35 @@
+/* $Id$ */
+/** @file
+ *
+ * Override err.h stuff so we get the program names right.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+#ifndef __err_h__
+#define __err_h__
+
+extern const char *g_progname;
+int err(int eval, const char *fmt, ...);
+int errx(int eval, const char *fmt, ...);
+void warn(const char *fmt, ...);
+void warnx(const char *fmt, ...);
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/ash/win/getopt.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/getopt.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/getopt.h	(revision 1780)
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument 	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define	no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+		        const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind,
+			     int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* getopt.h */
Index: /tags/kBuild-0.1.4/src/ash/win/mscfakes.c
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/mscfakes.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/mscfakes.c	(revision 1780)
@@ -0,0 +1,340 @@
+/* $Id$ */
+/** @file
+ *
+ * Fake Unix stuff for MSC.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys/times.h>
+#include "err.h"
+#include "mscfakes.h"
+#undef mkdir
+
+
+int optind = 1;
+
+
+char *dirname(char *path)
+{
+    /** @todo later */
+    return path;
+}
+
+
+int link(const char *pszDst, const char *pszLink)
+{
+    errno = ENOSYS;
+    err(1, "link() is not implemented on windows!");
+    return -1;
+}
+
+
+int mkdir_msc(const char *path, mode_t mode)
+{
+    int rc = mkdir(path);
+    if (rc)
+    {
+        int len = strlen(path);
+        if (len > 0 && (path[len - 1] == '/' || path[len - 1] == '\\'))
+        {
+            char *str = strdup(path);
+            while (len > 0 && (str[len - 1] == '/' || str[len - 1] == '\\'))
+                str[--len] = '\0';
+            rc = mkdir(str);
+            free(str);
+        }
+    }
+    return rc;
+}
+
+
+static int doname(char *pszX, char *pszEnd)
+{
+    static char s_szChars[] = "Xabcdefghijklmnopqrstuwvxyz1234567890";
+    int rc = 0;
+    do
+    {
+        char ch;
+
+        pszEnd++;
+        ch = *(strchr(s_szChars, *pszEnd) + 1);
+        if (ch)
+        {
+            *pszEnd = ch;
+            return 0;
+        }
+        *pszEnd = 'a';
+    } while (pszEnd != pszX);
+    return 1;
+}
+
+
+int mkstemp(char *temp)
+{
+    char *pszX = strchr(temp, 'X');
+    char *pszEnd = strchr(pszX, '\0');
+    int cTries = 1000;
+    while (--cTries > 0)
+    {
+        int fd;
+        if (doname(pszX, pszEnd))
+            return -1;
+        fd = open(temp, _O_EXCL | _O_CREAT | _O_BINARY | _O_RDWR, 0777);
+        if (fd >= 0)
+            return fd;
+    }
+    return -1;
+}
+
+
+int symlink(const char *pszDst, const char *pszLink)
+{
+    errno = ENOSYS;
+    err(1, "symlink() is not implemented on windows!");
+    return -1;
+}
+
+
+#if _MSC_VER < 1400
+int snprintf(char *buf, size_t size, const char *fmt, ...)
+{
+    int cch;
+    va_list args;
+    va_start(args, fmt);
+    cch = vsprintf(buf, fmt, args);
+    va_end(args);
+    return cch;
+}
+#endif
+
+
+int utimes(const char *pszPath, const struct timeval *paTimes)
+{
+    /** @todo implement me! */
+    return 0;
+}
+
+
+int writev(int fd, const struct iovec *vector, int count)
+{
+    int size = 0;
+    int i;
+    for (i = 0; i < count; i++)
+    {
+        int cb = write(fd, vector[i].iov_base, vector[i].iov_len);
+        if (cb < 0)
+            return -1;
+        size += cb;
+    }
+    return size;
+}
+
+
+int fcntl(int fd, int iCmd, ...)
+{
+    fprintf(stderr, "fcntl(%d, %d,..)\n", fd, iCmd);
+    return 0;
+}
+
+int ioctl(int fd, unsigned long iCmd, ...)
+{
+    fprintf(stderr, "ioctl(%d, %d,..)\n", fd, iCmd);
+    return 0;
+}
+
+int tcsetpgrp(int fd, pid_t pgrp)
+{
+    fprintf(stderr, "tcgetpgrp(%d, %d)\n", fd, pgrp);
+    return 0;
+}
+
+pid_t tcgetpgrp(int fd)
+{
+    fprintf(stderr, "tcgetpgrp(%d)\n", fd);
+    return 0;
+}
+
+pid_t getpgrp(void)
+{
+    fprintf(stderr, "getpgrp\n");
+    return _getpid();
+}
+
+uid_t getuid(void)
+{
+    fprintf(stderr, "getuid\n");
+    return 0;
+}
+
+gid_t getgid(void)
+{
+    fprintf(stderr, "getgid\n");
+    return 0;
+}
+
+gid_t getegid(void)
+{
+    fprintf(stderr, "getegid\n");
+    return 0;
+}
+
+int setpgid(pid_t pid, pid_t pgid)
+{
+    fprintf(stderr, "setpgid(%d,%d)\n", pid, pgid);
+    return 0;
+}
+
+pid_t getpgid(pid_t pid)
+{
+    fprintf(stderr, "getpgid(%d)\n", pid);
+    return 0;
+}
+
+long sysconf(int name)
+{
+    fprintf(stderr, "sysconf(%d)\n", name);
+    return 0;
+}
+
+clock_t times(struct tms *pBuf)
+{
+    struct timeval tv = {0};
+    if (pBuf)
+    {
+        pBuf->tms_utime = clock();  /* clock () * HZ / CLOCKS_PER_SEC */
+        pBuf->tms_stime = pBuf->tms_cutime = pBuf->tms_cstime = 0;
+    }
+/*
+    gettimeofday(&tv, NULL); */
+    fprintf(stderr, "times(%p)\n", pBuf);
+    return CLK_TCK * tv.tv_sec + (CLK_TCK * tv.tv_usec) / 1000000;
+}
+
+struct passwd *getpwnam(const char *pszName)
+{
+    printf("getpwnam(%s)\n",  pszName);
+    return NULL;
+}
+
+int setrlimit(int iResId, const struct rlimit *pLimit)
+{
+    printf("setrlimit(%d,  %p)\n", iResId, pLimit);
+    return -1;
+}
+
+int getrlimit(int iResId, struct rlimit *pLimit)
+{
+    printf("getrlimit(%d,  %p)\n", iResId, pLimit);
+    return -1;
+}
+
+
+pid_t fork(void)
+{
+    fprintf(stderr, "fork()\n");
+    return -1;
+}
+
+pid_t wait3(int *piStatus, int fOptions, struct rusage *pRUsage)
+{
+    fprintf(stderr, "wait3()\n");
+    return -1;
+}
+
+
+/* signal stuff */
+
+int	sigprocmask(int iOperation, const sigset_t *pNew, sigset_t *pOld)
+{
+    fprintf(stderr, "sigprocmask(%d, %p, %p)\n", iOperation, pNew, pOld);
+    return 0;
+}
+
+int	sigemptyset(sigset_t *pSet)
+{
+    pSet->__bitmap[0] = 0;
+    return 0;
+}
+
+int siginterrupt(int iSignalNo, int fFlag)
+{
+    fprintf(stderr, "siginterrupt(%d, %#x)\n", iSignalNo, fFlag);
+    return 0;
+}
+
+int sigaction(int iSignalNo, const struct sigaction *pSigAct, struct sigaction *pSigActOld)
+{
+    fprintf(stderr, "sigaction(%d, %p, %p)\n", iSignalNo, pSigAct, pSigActOld);
+    return 0;
+}
+
+int kill(pid_t pid, int iSignalNo)
+{
+    fprintf(stderr, "kill(%d, %d)\n", pid, iSignalNo);
+    return 0;
+}
+
+int killpg(pid_t pgrp, int iSignalNo)
+{
+    if (pgrp < 0)
+    {
+        errno = EINVAL;
+        return -1;
+    }
+    return kill(-pgrp, iSignalNo);
+}
+
+const char * const  sys_siglist[NSIG] =
+{
+    "0",
+    "1",
+    "2",
+    "3",
+    "4",
+    "5",
+    "6",
+    "7",
+    "8",
+    "9",
+    "10",
+    "11",
+    "12",
+    "13",
+    "14",
+    "15",
+    "16",
+    "17",
+    "18",
+    "19",
+    "20",
+    "21",
+    "22"
+};
+
+
+/* */
Index: /tags/kBuild-0.1.4/src/ash/win/mscfakes.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/mscfakes.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/mscfakes.h	(revision 1780)
@@ -0,0 +1,203 @@
+/* $Id$ */
+/** @file
+ *
+ * Unix fakes for MSC.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+#ifndef __mscfakes_h__
+#define __mscfakes_h__
+#ifdef _MSC_VER
+
+#define setmode setmode_msc
+#include <sys/cdefs.h>
+#include <io.h>
+#include <direct.h>
+#include <time.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <process.h>
+#undef setmode
+//#include "getopt.h"
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+#define __attribute__(a)
+#endif
+
+#define S_ISDIR(m)  (((m) & _S_IFMT) == _S_IFDIR)
+#define S_ISREG(m)  (((m) & _S_IFMT) == _S_IFREG)
+#define S_ISLNK(m)  0
+#define	S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC)
+#define	S_IXUSR _S_IEXEC
+#define	S_IWUSR _S_IWRITE
+#define	S_IRUSR _S_IREAD
+#define S_IRWXG 0000070
+#define S_IRGRP	0000040
+#define S_IWGRP	0000020
+#define S_IXGRP 0000010
+#define S_IRWXO 0000007
+#define S_IROTH	0000004
+#define S_IWOTH	0000002
+#define S_IXOTH 0000001
+#define	S_ISUID 0004000
+#define	S_ISGID 0002000
+#define ALLPERMS 0000777
+
+#define PATH_MAX _MAX_PATH
+#define MAXPATHLEN _MAX_PATH
+
+#define EX_OK 0
+#define EX_OSERR 1
+#define EX_NOUSER 1
+#define EX_USAGE 1
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+#define F_OK 0
+#define X_OK 1
+#define W_OK 2
+#define R_OK 4
+
+#define EFTYPE EINVAL
+
+#define _PATH_DEVNULL "/dev/null"
+
+#define MAX(a,b) ((a) >= (b) ? (a) : (b))
+
+typedef int mode_t;
+typedef unsigned short nlink_t;
+typedef long ssize_t;
+typedef unsigned long u_long;
+typedef unsigned int u_int;
+typedef unsigned short u_short;
+
+#ifndef timerisset
+struct timeval
+{
+    long tv_sec;
+    long tv_usec;
+};
+#endif
+
+struct iovec
+{
+    char *iov_base;
+    size_t iov_len;
+};
+
+
+#define chown(path, uid, gid) 0         /** @todo implement fchmod! */
+char *dirname(char *path);
+#define fsync(fd)  0
+#define fchown(fd,uid,gid) 0
+#define fchmod(fd, mode) 0              /** @todo implement fchmod! */
+#define geteuid()  0
+#define lstat(path, s) stat(path, s)
+#define lchmod(path, mod) chmod(path, mod)
+#define lchown(path, uid, gid) chown(path, uid, gid)
+#define lutimes(path, tvs) utimes(path, tvs)
+int link(const char *pszDst, const char *pszLink);
+int mkdir_msc(const char *path, mode_t mode);
+#define mkdir(path, mode) mkdir_msc(path, mode)
+#define mkfifo(path, mode) -1
+#define mknod(path, mode, devno) -1
+#define pipe(v) _pipe(v,0,0)
+int mkstemp(char *temp);
+#define readlink(link, buf, size) -1
+#define reallocf(old, size) realloc(old, size)
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#if _MSC_VER < 1400
+int snprintf(char *buf, size_t size, const char *fmt, ...);
+#else
+#define snprintf _snprintf
+#endif
+size_t strlcpy(char *, const char *, size_t);
+int symlink(const char *pszDst, const char *pszLink);
+int utimes(const char *pszPath, const struct timeval *paTimes);
+int writev(int fd, const struct iovec *vector, int count);
+#define	F_DUPFD	0
+#define F_GETFD 1
+#define F_SETFD 2
+#define F_GETFL 3
+#define F_SETFL 4
+#define	FD_CLOEXEC 1
+#define O_NONBLOCK 0 /// @todo
+#define EWOULDBLOCK 512
+int fcntl(int, int, ...);
+int ioctl(int, unsigned long, ...);
+pid_t tcgetpgrp(int fd);
+
+
+/* signal hacks */
+#include <signal.h>
+typedef struct sigset
+{
+    unsigned long __bitmap[1];
+} sigset_t;
+typedef void __sighandler_t(int);
+typedef	void __siginfohandler_t(int, struct __siginfo *, void *);
+typedef __sighandler_t *sig_t; /** BSD 4.4 type. */
+struct sigaction
+{
+    union
+    {
+        __siginfohandler_t *__sa_sigaction;
+        __sighandler_t     *__sa_handler;
+    }  __sigaction_u;
+    sigset_t    sa_mask;
+    int         sa_flags;
+};
+#define sa_handler      __sigaction_u.__sa_handler
+#define sa_sigaction    __sigaction_u.__sa_sigaction
+
+int	sigprocmask(int, const sigset_t *, sigset_t *);
+#define SIG_BLOCK           1
+#define SIG_UNBLOCK         2
+#define SIG_SETMASK         3
+
+#define SIGTTIN 19
+#define SIGTSTP 18
+#define SIGTTOU 17
+#define SIGCONT 20
+#define SIGPIPE 12
+#define SIGQUIT 9
+#define SIGHUP  5
+
+extern const char *const sys_siglist[NSIG]; /* NSIG == 23 */
+
+int	kill(pid_t, int);
+int	sigaction(int, const struct sigaction *, struct sigaction *);
+//int	sigaddset(sigset_t *, int);
+//int	sigdelset(sigset_t *, int);
+int	sigemptyset(sigset_t *);
+//int	sigfillset(sigset_t *);
+//int	sigismember(const sigset_t *, int);
+//int	sigpending(sigset_t *);
+//int	sigsuspend(const sigset_t *);
+//int	sigwait(const sigset_t *, int *);
+int	siginterrupt(int, int);
+
+#endif /* _MSC_VER */
+#endif
+
Index: /tags/kBuild-0.1.4/src/ash/win/paths.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/paths.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/paths.h	(revision 1780)
@@ -0,0 +1,2 @@
+#include "mscfakes.h"
+#define _PATH_DEFPATH ""
Index: /tags/kBuild-0.1.4/src/ash/win/pwd.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/pwd.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/pwd.h	(revision 1780)
@@ -0,0 +1,23 @@
+#ifndef __pwd_h__
+#define __pwd_h__
+#include <time.h>
+
+struct passwd {
+	char	*pw_name;		/* user name */
+	char	*pw_passwd;		/* encrypted password */
+	int	pw_uid;			/* user uid */
+	int	pw_gid;			/* user gid */
+	time_t	pw_change;		/* password change time */
+	char	*pw_class;		/* user access class */
+	char	*pw_gecos;		/* Honeywell login info */
+	char	*pw_dir;		/* home directory */
+	char	*pw_shell;		/* default shell */
+	time_t	pw_expire;		/* account expiration */
+	int	pw_fields;		/* internal: fields filled in */
+};
+
+struct passwd	*getpwnam(const char *);
+struct passwd	*getpwuid(int);
+
+
+#endif
Index: /tags/kBuild-0.1.4/src/ash/win/strings.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/strings.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/strings.h	(revision 1780)
@@ -0,0 +1,4 @@
+#include <string.h>
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#define index(str, ch) strchr((str), (ch))
Index: /tags/kBuild-0.1.4/src/ash/win/sys/cdefs.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/sys/cdefs.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/sys/cdefs.h	(revision 1780)
@@ -0,0 +1,9 @@
+#ifndef __sys_cdefs_h__
+#define __sys_cdefs_h__
+
+#define __attribute__(a)
+typedef int pid_t;
+typedef unsigned short uid_t;
+typedef unsigned short gid_t;
+
+#endif
Index: /tags/kBuild-0.1.4/src/ash/win/sys/fcntl.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/sys/fcntl.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/sys/fcntl.h	(revision 1780)
@@ -0,0 +1,1 @@
+#include "../mscfakes.h"
Index: /tags/kBuild-0.1.4/src/ash/win/sys/ioctl.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/sys/ioctl.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/sys/ioctl.h	(revision 1780)
@@ -0,0 +1,1 @@
+/* */
Index: /tags/kBuild-0.1.4/src/ash/win/sys/param.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/sys/param.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/sys/param.h	(revision 1780)
@@ -0,0 +1,2 @@
+#include <limits.h>
+
Index: /tags/kBuild-0.1.4/src/ash/win/sys/resource.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/sys/resource.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/sys/resource.h	(revision 1780)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)resource.h	8.4 (Berkeley) 1/9/95
+ * $FreeBSD: src/sys/sys/resource.h,v 1.23 2004/06/13 22:07:58 das Exp $
+ */
+
+/** @file
+ * FreeBSD 5.3
+ * @changed bird: get/setpriority takes id_t not int according to SuS.
+ * @changed bird: include sys/types.h to get id_t.
+ */
+
+#ifndef _SYS_RESOURCE_H_
+#define	_SYS_RESOURCE_H_
+
+#include <sys/cdefs.h>
+#include "mscfakes.h"
+
+
+/*
+ * Process priority specifications to get/setpriority.
+ */
+#define	PRIO_MIN	-20
+#define	PRIO_MAX	20
+
+#define	PRIO_PROCESS	0
+#define	PRIO_PGRP	1
+#define	PRIO_USER	2
+
+/*
+ * Resource utilization information.
+ */
+
+#define	RUSAGE_SELF	0
+#define	RUSAGE_CHILDREN	-1
+
+struct rusage {
+	struct timeval ru_utime;	/* user time used */
+	struct timeval ru_stime;	/* system time used */
+	long	ru_maxrss;		/* max resident set size */
+#define	ru_first	ru_ixrss
+	long	ru_ixrss;		/* integral shared memory size */
+	long	ru_idrss;		/* integral unshared data " */
+	long	ru_isrss;		/* integral unshared stack " */
+	long	ru_minflt;		/* page reclaims */
+	long	ru_majflt;		/* page faults */
+	long	ru_nswap;		/* swaps */
+	long	ru_inblock;		/* block input operations */
+	long	ru_oublock;		/* block output operations */
+	long	ru_msgsnd;		/* messages sent */
+	long	ru_msgrcv;		/* messages received */
+	long	ru_nsignals;		/* signals received */
+	long	ru_nvcsw;		/* voluntary context switches */
+	long	ru_nivcsw;		/* involuntary " */
+#define	ru_last		ru_nivcsw
+};
+
+/*
+ * Resource limits
+ */
+#define	RLIMIT_CPU	0		/* cpu time in milliseconds */
+#define	RLIMIT_FSIZE	1		/* maximum file size */
+#define	RLIMIT_DATA	2		/* data size */
+#define	RLIMIT_STACK	3		/* stack size */
+#define	RLIMIT_CORE	4		/* core file size */
+#define	RLIMIT_RSS	5		/* resident set size */
+#define	RLIMIT_MEMLOCK	6		/* locked-in-memory address space */
+#define	RLIMIT_NPROC	7		/* number of processes */
+#define	RLIMIT_NOFILE	8		/* number of open files */
+#define	RLIMIT_SBSIZE	9		/* maximum size of all socket buffers */
+#define RLIMIT_VMEM	10		/* virtual process size (inclusive of mmap) */
+#define	RLIMIT_AS	RLIMIT_VMEM	/* standard name for RLIMIT_VMEM */
+#define RLIMIT_OBJREST  11		/* bird: size left in the top heap object. kLIBC specific. */
+
+#define	RLIM_NLIMITS	12		/* number of resource limits */ /* bird: was 11 */
+
+#define	RLIM_INFINITY	(((rlim_t)1 << 63) - 1)
+/* XXX Missing: RLIM_SAVED_MAX, RLIM_SAVED_CUR */
+
+
+/*
+ * Resource limit string identifiers
+ */
+
+#ifdef _RLIMIT_IDENT
+static char *rlimit_ident[] = {
+	"cpu",
+	"fsize",
+	"data",
+	"stack",
+	"core",
+	"rss",
+	"memlock",
+	"nproc",
+	"nofile",
+	"sbsize",
+	"vmem",
+};
+#endif
+
+typedef	__int64	rlim_t;
+
+struct rlimit {
+	rlim_t	rlim_cur;		/* current (soft) limit */
+	rlim_t	rlim_max;		/* maximum value for rlim_cur */
+};
+
+
+/* XXX 2nd arg to [gs]etpriority() should be an id_t */
+//int	getpriority(int, /*int*/ id_t);         /* bird: SuS uses id_t */
+//int	getrlimit(int, struct rlimit *);
+int	getrusage(int, struct rusage *);
+//int	setpriority(int, /*int*/ id_t, int);    /* bird: SuS uses id_t */
+int	setrlimit(int, const struct rlimit *);
+
+#endif	/* !_SYS_RESOURCE_H_ */
+
Index: /tags/kBuild-0.1.4/src/ash/win/sys/time.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/sys/time.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/sys/time.h	(revision 1780)
@@ -0,0 +1,1 @@
+#include <time.h>
Index: /tags/kBuild-0.1.4/src/ash/win/sys/times.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/sys/times.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/sys/times.h	(revision 1780)
@@ -0,0 +1,15 @@
+#ifndef __sys_times_h__
+#define __sys_times_h__
+#include <time.h>
+
+struct tms
+{
+    clock_t tms_utime;      /**< User mode CPU time. */
+    clock_t tms_stime;      /**< Kernel mode CPU time. */
+    clock_t tms_cutime;     /**< User mode CPU time for waited for children. */
+    clock_t tms_cstime;     /**< Kernel mode CPU time for waited for children. */
+};
+
+clock_t times(struct tms *);
+
+#endif 
Index: /tags/kBuild-0.1.4/src/ash/win/sys/wait.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/sys/wait.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/sys/wait.h	(revision 1780)
@@ -0,0 +1,25 @@
+#ifndef __sys_wait_h__
+#define __sys_wait_h__
+
+#include "mscfakes.h"
+
+#define	WNOHANG		1	/* Don't hang in wait. */
+#define	WUNTRACED	2	/* Tell about stopped, untraced children. */
+#define	WCONTINUED	4	/* Report a job control continued process. */
+#define	_W_INT(w)	(*(int *)&(w))	/* Convert union wait to int. */
+#define	WCOREFLAG	0200
+
+#define	_WSTATUS(x)	(_W_INT(x) & 0177)
+#define	_WSTOPPED	0177		/* _WSTATUS if process is stopped */
+#define	WIFSTOPPED(x)	(_WSTATUS(x) == _WSTOPPED)
+#define	WSTOPSIG(x)	(_W_INT(x) >> 8)
+#define	WIFSIGNALED(x)	(_WSTATUS(x) != 0 && !WIFSTOPPED(x) && !WIFCONTINUED(x)) /* bird: made GLIBC tests happy. */
+#define	WTERMSIG(x)	(_WSTATUS(x))
+#define	WIFEXITED(x)	(_WSTATUS(x) == 0)
+#define	WEXITSTATUS(x)	(_W_INT(x) >> 8)
+#define	WIFCONTINUED(x)	(x == 0x13)	/* 0x13 == SIGCONT */
+#define	WCOREDUMP(x)	(_W_INT(x) & WCOREFLAG)
+#define	W_EXITCODE(ret, sig)	((ret) << 8 | (sig))
+#define	W_STOPCODE(sig)		((sig) << 8 | _WSTOPPED)
+
+#endif 
Index: /tags/kBuild-0.1.4/src/ash/win/termios.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/termios.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/termios.h	(revision 1780)
@@ -0,0 +1,1 @@
+/* */
Index: /tags/kBuild-0.1.4/src/ash/win/unistd.h
===================================================================
--- /tags/kBuild-0.1.4/src/ash/win/unistd.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/ash/win/unistd.h	(revision 1780)
@@ -0,0 +1,9 @@
+#include "mscfakes.h"
+#include "getopt.h"
+#include "process.h"
+
+#define _SC_CLK_TCK 0x101
+long _sysconf(int);
+pid_t fork(void);
+pid_t getpid(void);
+
Index: /tags/kBuild-0.1.4/src/fastdep/Makefile
===================================================================
--- /tags/kBuild-0.1.4/src/fastdep/Makefile	(revision 1780)
+++ /tags/kBuild-0.1.4/src/fastdep/Makefile	(revision 1780)
@@ -0,0 +1,121 @@
+# $Id$
+
+#
+# Odin32 API
+#
+#   Makefile for the Quick-and-Dirty dependency utility. (FastDep)
+#
+#   Copyright (c) 1999-2002 knut st. osmundsen (bird-kBuild-spam@anduin.net)
+#
+#   GPL
+#
+
+
+!ifdef BUILD_SETUP_MAK
+
+
+#
+# Setup config
+#
+ALL_NO_DBGMEM = 1
+PATH_ROOT = ..\..
+!include $(PATH_ROOT)\$(BUILD_SETUP_MAK)
+
+#
+# Target config
+#
+TARGET_NAME = fastdep
+TARGET_MODE = EXE
+TARGET_NEEDED = 1
+TARGET_PUB_BASE = $(PATH_TOOLS)
+
+TARGET_OBJS =\
+$(PATH_TARGET)\fastdep.$(EXT_OBJ)\
+$(PATH_TARGET)\avl.$(EXT_OBJ)\
+
+TARGET_LIBS =\
+$(LIB_OS)\
+$(LIB_C_OBJ)
+
+#
+# Rules config
+#
+RULES_FORWARD =
+!include $(MAKE_INCLUDE_PROCESS)
+
+
+!else
+#
+# Directory macro.
+#
+ODIN32_BIN     = $(ODIN32_TOOLS)
+
+
+#
+# Tell buildenvironment that we're making an VIO .exe.
+# Tell buildenvironment that we like to use static linked CRT.
+# Tell buildenvironment that we should not copy this into /bin.
+#
+EXETARGET = 1
+VIO = 1
+STATIC_CRT = 1
+NO_MAIN_BIN_COPY = 1
+
+
+#
+# include common definitions
+#
+!include ../../makefile.inc
+
+
+#
+# Addjust common definitions
+#
+!if "$(VAC3)" == "1" || "$(VAC36)" == "1"
+CFLAGS   = $(CFLAGS) -W3 -Wall+ppt-ppc-inl-cnv-gnr-vft-gen-uni-ext- \
+!ifdef DEBUG
+        -O+ -Tm-
+!endif
+!endif
+
+
+#
+# Object files. Prefix with OBJDIR and one space before the '\'.
+#
+OBJS = \
+$(OBJDIR)\fastdep.obj \
+$(OBJDIR)\avl.obj
+
+
+#
+# Libraries. One space before the '\'.
+#
+LIBS = \
+$(RTLLIB) \
+os2386.lib
+
+
+#
+# Target name - name of the exe without extention and path.
+#
+TARGET = FastDep
+
+
+#
+# Includes the common rules.
+#
+!include $(ODIN32_POST_INC)
+
+
+#
+# We need all.
+#
+needed: all
+!endif
+
+
+#
+# NT version using Watcom C/C++.
+#
+fastdepnt.exe:
+    wcl386 -bt=nt -l=nt -d2 /hc /"option map" -DOS2FAKE=1 -I$(WATCOM)\h\nt fastdep.c avl.c os2fake-win.c /Fe=$@ kernel32.lib
Index: /tags/kBuild-0.1.4/src/fastdep/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/fastdep/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/fastdep/Makefile.kmk	(revision 1780)
@@ -0,0 +1,58 @@
+# $Id: Makefile.kmk 785 2007-01-24 22:21:56Z bird $
+## @file
+# Sub-makefile for testing the VAC308 tool / ancient dependency generator.
+#
+
+#
+# Copyright (c) 2007-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../..
+include $(KBUILD_PATH)/subheader.kmk
+
+
+#
+# The base package.
+#
+PROGRAMS += fastdep
+fastdep_TOOL = VAC308
+fastdep_SOURCES = avl.c fastdep.c
+fastdep_INCS = f:/toolkit/v4.52/h
+fastdep_LIBPATH = f:/toolkit/v4.52/lib
+
+
+LIBRARIES += libfastdep
+libfastdep_TOOL = VAC308
+libfastdep_SOURCES = avl.c fastdep.c
+libfastdep_INCS = f:/toolkit/v4.52/h
+
+LIBRARIES += libfastdll
+libfastdll_TOOL = VAC308
+libfastdll_SOURCES = fastdll.def
+
+DLLS += fastdll
+fastdll_TOOL = VAC308
+fastdll_SOURCES = fastdll.def avl.c fastdep.c
+fastdll_INCS = f:/toolkit/v4.52/h
+fastdll_LIBPATH = f:/toolkit/v4.52/lib
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
Index: /tags/kBuild-0.1.4/src/fastdep/avl.c
===================================================================
--- /tags/kBuild-0.1.4/src/fastdep/avl.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/fastdep/avl.c	(revision 1780)
@@ -0,0 +1,823 @@
+/* $Id$
+ *
+ * AVL-Tree (lookalike) implementation.
+ *
+ * Copyright (c) 1999 knut st. osmundsen
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+
+/*
+ * AVL helper macros.
+ */
+#define AVL_HEIGHTOF(pNode) ((unsigned char)((pNode) != NULL ? pNode->uchHeight : 0))
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+
+#ifndef INLINE
+#   if defined(__IBMC__)
+#       define INLINE _Inline
+#   elif defined(__IBMCPP__)
+#       define INLINE inline
+#   elif defined(__WATCOMC__)
+#       define INLINE __inline
+#   elif defined(__WATCOM_CPLUSPLUS__)
+#       define INLINE inline
+#   else
+#       error message("unknown compiler - inline keyword unknown!")
+#   endif
+#endif
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+#include <os2.h>
+#include "avl.h"
+#if defined(RING0) || defined(RING3)
+    #include "dev32.h"
+#else
+    #define SSToDS(a) (a)
+#endif
+#include "string.h"
+
+#if defined(__IBMCPP__) || defined(__IBMC__)
+#include <builtin.h>
+#define assert(a) ((a) ? (void)0 : __interrupt(3) )
+#else
+#include <assert.h>
+#endif
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/*
+ * A stack used to avoid recursive calls...
+ */
+typedef struct _AVLStack
+{
+    unsigned     cEntries;
+    PPAVLNODECORE aEntries[AVL_MAX_HEIGHT];
+} AVLSTACK, *PAVLSTACK;
+typedef struct _AVLStack2
+{
+    unsigned     cEntries;
+    PAVLNODECORE aEntries[AVL_MAX_HEIGHT];
+    char         achFlags[AVL_MAX_HEIGHT];
+} AVLSTACK2, *PAVLSTACK2;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+INLINE void AVLRebalance(PAVLSTACK pStack);
+
+
+/**
+ * Inserts a node into the AVL-tree.
+ * @returns   TRUE if inserted.
+ *            FALSE if node exists in tree.
+ * @param     ppTree  Pointer to the AVL-tree root node pointer.
+ * @param     pNode   Pointer to the node which is to be added.
+ * @sketch    Find the location of the node (using binary three algorithm.):
+ *            LOOP until NULL leaf pointer
+ *            BEGIN
+ *                Add node pointer pointer to the AVL-stack.
+ *                IF new-node-key < node key THEN
+ *                    left
+ *                ELSE
+ *                    right
+ *            END
+ *            Fill in leaf node and insert it.
+ *            Rebalance the tree.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+BOOL AVLInsert(PPAVLNODECORE ppTree, PAVLNODECORE pNode)
+{
+    AVLSTACK                AVLStack;
+    PPAVLNODECORE           ppCurNode = ppTree;
+    register AVLKEY         Key = pNode->Key;
+    register PAVLNODECORE   pCurNode;
+
+    AVLStack.cEntries = 0;
+
+    while ((pCurNode = *ppCurNode) != NULL)
+    {
+        assert(AVLStack.cEntries < AVL_MAX_HEIGHT);
+        assert(pNode != pCurNode);
+        AVLStack.aEntries[AVLStack.cEntries++] = ppCurNode;
+        #ifdef AVL_MAY_TRY_INSERT_EQUAL
+        /* check if equal */
+        if (AVL_E(pCurNode->Key, Key))
+            return FALSE;
+        #endif
+        if (AVL_G(pCurNode->Key, Key))
+            ppCurNode = &pCurNode->pLeft;
+        else
+            ppCurNode = &pCurNode->pRight;
+    }
+
+    pNode->pLeft = pNode->pRight = NULL;
+    pNode->uchHeight = 1;
+    *ppCurNode = pNode;
+
+    AVLRebalance(SSToDS(&AVLStack));
+    return TRUE;
+}
+
+
+/**
+ * Removes a node from the AVL-tree.
+ * @returns   Pointer to the node.
+ * @param     ppTree  Pointer to the AVL-tree root node pointer.
+ * @param     Key     Key value of the node which is to be removed.
+ * @sketch    Find the node which is to be removed:
+ *            LOOP until not found
+ *            BEGIN
+ *                Add node pointer pointer to the AVL-stack.
+ *                IF the keys matches THEN break!
+ *                IF remove key < node key THEN
+ *                    left
+ *                ELSE
+ *                    right
+ *            END
+ *            IF found THEN
+ *            BEGIN
+ *                IF left node not empty THEN
+ *                BEGIN
+ *                    Find the right most node in the left tree while adding the pointer to the pointer to it's parent to the stack:
+ *                    Start at left node.
+ *                    LOOP until right node is empty
+ *                    BEGIN
+ *                        Add to stack.
+ *                        go right.
+ *                    END
+ *                    Link out the found node.
+ *                    Replace the node which is to be removed with the found node.
+ *                    Correct the stack entry for the pointer to the left tree.
+ *                END
+ *                ELSE
+ *                BEGIN
+ *                    Move up right node.
+ *                    Remove last stack entry.
+ *                END
+ *                Balance tree using stack.
+ *            END
+ *            return pointer to the removed node (if found).
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+PAVLNODECORE AVLRemove(PPAVLNODECORE ppTree, AVLKEY Key)
+{
+    AVLSTACK                AVLStack;
+    PPAVLNODECORE           ppDeleteNode = ppTree;
+    register PAVLNODECORE   pDeleteNode;
+
+    AVLStack.cEntries = 0;
+
+    while ((pDeleteNode = *ppDeleteNode) != NULL)
+    {
+        assert(AVLStack.cEntries < AVL_MAX_HEIGHT);
+        AVLStack.aEntries[AVLStack.cEntries++] = ppDeleteNode;
+        #ifndef AVL_CMP
+        if (AVL_E(pDeleteNode->Key, Key))
+            break;
+
+        if (AVL_G(pDeleteNode->Key, Key))
+            ppDeleteNode = &pDeleteNode->pLeft;
+        else
+            ppDeleteNode = &pDeleteNode->pRight;
+        #else
+        {
+        int register iDiff;
+        if ((iDiff = AVL_CMP(pDeleteNode->Key, Key)) == 0)
+            break;
+
+        if (iDiff > 0)
+            ppDeleteNode = &pDeleteNode->pLeft;
+        else
+            ppDeleteNode = &pDeleteNode->pRight;
+        }
+        #endif
+    }
+
+    if (pDeleteNode != NULL)
+    {
+        if (pDeleteNode->pLeft != NULL)
+        {
+            unsigned                iStackEntry = AVLStack.cEntries;
+            PPAVLNODECORE           ppLeftLeast = &pDeleteNode->pLeft;
+            register PAVLNODECORE   pLeftLeast;
+
+            while ((pLeftLeast = *ppLeftLeast)->pRight != NULL) /* Left most node. */
+            {
+                assert(AVLStack.cEntries < AVL_MAX_HEIGHT);
+                AVLStack.aEntries[AVLStack.cEntries++] = ppLeftLeast;
+                ppLeftLeast = &pLeftLeast->pRight;
+                pLeftLeast  = pLeftLeast->pRight;
+            }
+
+            /* link out pLeftLeast */
+            *ppLeftLeast = pLeftLeast->pLeft;
+
+            /* link in place of the delete node. */
+            pLeftLeast->pLeft = pDeleteNode->pLeft;
+            pLeftLeast->pRight = pDeleteNode->pRight;
+            pLeftLeast->uchHeight = pDeleteNode->uchHeight;
+            *ppDeleteNode = pLeftLeast;
+            AVLStack.aEntries[iStackEntry] = &pLeftLeast->pLeft;
+        }
+        else
+        {
+            *ppDeleteNode = pDeleteNode->pRight;
+            AVLStack.cEntries--;
+        }
+
+        AVLRebalance(SSToDS(&AVLStack));
+    }
+
+    return pDeleteNode;
+}
+
+
+/**
+ * Gets a node from the tree (does not remove it!)
+ * @returns   Pointer to the node holding the given key.
+ * @param     ppTree  Pointer to the AVL-tree root node pointer.
+ * @param     Key     Key value of the node which is to be found.
+ * @sketch
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+PAVLNODECORE AVLGet(PPAVLNODECORE ppTree, AVLKEY Key)
+{
+    #ifndef AVL_CMP
+    register PAVLNODECORE   pNode = *ppTree;
+
+    while (pNode != NULL && AVL_NE(pNode->Key, Key))
+    {
+        if (AVL_G(pNode->Key, Key))
+            pNode = pNode->pLeft;
+        else
+            pNode = pNode->pRight;
+    }
+
+    #else
+
+    register int            iDiff;
+    register PAVLNODECORE   pNode = *ppTree;
+
+    while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)
+    {
+        if (iDiff > 0)
+            pNode = pNode->pLeft;
+        else
+            pNode = pNode->pRight;
+    }
+
+    #endif
+
+    return pNode;
+}
+
+
+/**
+ * Gets a node from the tree and its parent node (if any) (does not remove any nodes!)
+ * @returns   Pointer to the node holding the given key.
+ * @param     ppTree    Pointer to the AVL-tree root node pointer.
+ * @param     ppParent  Pointer to a variable which will hold the pointer to the partent node on
+ *                      return. When no node is found, this will hold the last searched node.
+ * @param     Key       Key value of the node which is to be found.
+ * @sketch
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+PAVLNODECORE    AVLGetWithParent(PPAVLNODECORE ppTree, PPAVLNODECORE ppParent, AVLKEY Key)
+{
+    #ifndef AVL_CMP
+
+    register PAVLNODECORE   pNode = *ppTree;
+    register PAVLNODECORE   pParent = NULL;
+
+    while (pNode != NULL && AVL_NE(pNode->Key, Key))
+    {
+        pParent = pNode;
+        if (AVL_G(pNode->Key, Key))
+            pNode = pNode->pLeft;
+        else
+            pNode = pNode->pRight;
+    }
+
+    #else
+
+    register PAVLNODECORE   pNode = *ppTree;
+    register PAVLNODECORE   pParent = NULL;
+    register int            iDiff;
+
+    while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)
+    {
+        pParent = pNode;
+        if (iDiff > 0)
+            pNode = pNode->pLeft;
+        else
+            pNode = pNode->pRight;
+    }
+
+    #endif
+
+    *ppParent = pParent;
+    return pNode;
+}
+
+
+
+/**
+ * Gets node from the tree (does not remove it!) and it's adjecent (by key value) nodes.
+ * @returns   Pointer to the node holding the given key.
+ * @param     ppTree   Pointer to the AVL-tree root node pointer.
+ * @param     Key      Key value of the node which is to be found.
+ * @param     ppLeft   Pointer to left node pointer.
+ * @param     ppRight  Pointer to right node pointer.
+ * @sketch    Find node with the given key, record search path on the stack.
+ *            IF found THEN
+ *            BEGIN
+ *                Find the right-most node in the left subtree.
+ *                Find the left-most node in the right subtree.
+ *                Rewind the stack while searching for more adjecent nodes.
+ *            END
+ *            return node with adjecent nodes.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+PAVLNODECORE AVLGetWithAdjecentNodes(PPAVLNODECORE ppTree, AVLKEY Key, PPAVLNODECORE ppLeft, PPAVLNODECORE ppRight)
+{
+    AVLSTACK        AVLStack;
+    PPAVLNODECORE   ppNode = ppTree;
+    PAVLNODECORE    pNode;
+    #ifdef AVL_CMP
+    int     iDiff;
+    #endif
+
+    AVLStack.cEntries = 0;
+
+    #ifndef AVL_CMP
+    while ((pNode = *ppNode) != NULL && AVL_NE(pNode->Key, Key))
+    #else
+    while ((pNode = *ppNode) != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)
+    #endif
+    {
+        assert(AVLStack.cEntries < AVL_MAX_HEIGHT);
+        AVLStack.aEntries[AVLStack.cEntries++] = ppNode;
+        #ifndef AVL_CMP
+        if (AVL_G(pNode->Key, Key))
+        #else
+        if (iDiff > 0)
+        #endif
+            ppNode = &pNode->pLeft;
+        else
+            ppNode = &pNode->pRight;
+    }
+
+    if (pNode != NULL)
+    {
+        PAVLNODECORE    pCurNode;
+
+        /* find rigth-most node in left subtree. */
+        pCurNode = pNode->pLeft;
+        if (pCurNode != NULL)
+            while (pCurNode->pRight != NULL)
+                pCurNode = pCurNode->pRight;
+        *ppLeft = pCurNode;
+
+        /* find left-most node in right subtree. */
+        pCurNode = pNode->pRight;
+        if (pCurNode != NULL)
+            while (pCurNode->pLeft != NULL)
+                pCurNode = pCurNode->pLeft;
+        *ppRight = pCurNode;
+
+        /* rewind stack */
+        while (AVLStack.cEntries-- > 0)
+        {
+            pCurNode = *AVLStack.aEntries[AVLStack.cEntries];
+            #ifndef AVL_CMP
+            if (AVL_L(pCurNode->Key, Key) && (*ppLeft == NULL || AVL_G(pCurNode->Key, (*ppLeft)->Key)))
+                *ppLeft = pCurNode;
+            else if (AVL_G(pCurNode->Key, Key) && (*ppRight == NULL || AVL_L(pCurNode->Key, (*ppRight)->Key)))
+                *ppRight = pCurNode;
+            #else
+            if ((iDiff = AVL_CMP(pCurNode->Key, Key)) < 0 && (*ppLeft == NULL || AVL_G(pCurNode->Key, (*ppLeft)->Key)))
+                *ppLeft = pCurNode;
+            else if (iDiff > 0 && (*ppRight == NULL || AVL_L(pCurNode->Key, (*ppRight)->Key)))
+                *ppRight = pCurNode;
+            #endif
+        }
+    }
+    else
+        *ppLeft = *ppRight = NULL;
+
+    return pNode;
+}
+
+
+/**
+ * Iterates tru all nodes in the given tree.
+ * @returns   0 on success. Return from callback on failiure.
+ * @param     ppTree   Pointer to the AVL-tree root node pointer.
+ * @param     fFromLeft    TRUE:  Left to right.
+ *                         FALSE: Right to left.
+ * @param     pfnCallBack  Pointer to callback function.
+ * @param     pvParam      Userparameter passed on to the callback function.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+unsigned AVLDoWithAll(PPAVLNODECORE ppTree, int fFromLeft, PAVLCALLBACK pfnCallBack, void *pvParam)
+{
+    AVLSTACK2       AVLStack;
+    PAVLNODECORE    pNode;
+    unsigned        rc;
+
+    if (*ppTree == NULL)
+        return 0;
+
+    AVLStack.cEntries = 1;
+    AVLStack.achFlags[0] = 0;
+    AVLStack.aEntries[0] = *ppTree;
+
+    if (fFromLeft)
+    {   /* from left */
+        while (AVLStack.cEntries > 0)
+        {
+            pNode = AVLStack.aEntries[AVLStack.cEntries - 1];
+
+            /* left */
+            if (!AVLStack.achFlags[AVLStack.cEntries - 1]++)
+            {
+                if (pNode->pLeft != NULL)
+                {
+                    AVLStack.achFlags[AVLStack.cEntries] = 0; /* 0 first, 1 last */
+                    AVLStack.aEntries[AVLStack.cEntries++] = pNode->pLeft;
+                    continue;
+                }
+            }
+
+            /* center */
+            rc = pfnCallBack(pNode, pvParam);
+            if (rc != 0)
+                return rc;
+
+            /* right */
+            AVLStack.cEntries--;
+            if (pNode->pRight != NULL)
+            {
+                AVLStack.achFlags[AVLStack.cEntries] = 0;
+                AVLStack.aEntries[AVLStack.cEntries++] = pNode->pRight;
+            }
+        } /* while */
+    }
+    else
+    {   /* from right */
+        while (AVLStack.cEntries > 0)
+        {
+            pNode = AVLStack.aEntries[AVLStack.cEntries - 1];
+
+
+            /* right */
+            if (!AVLStack.achFlags[AVLStack.cEntries - 1]++)
+            {
+                if (pNode->pRight != NULL)
+                {
+                    AVLStack.achFlags[AVLStack.cEntries] = 0;  /* 0 first, 1 last */
+                    AVLStack.aEntries[AVLStack.cEntries++] = pNode->pRight;
+                    continue;
+                }
+            }
+
+            /* center */
+            rc = pfnCallBack(pNode, pvParam);
+            if (rc != 0)
+                return rc;
+
+            /* left */
+            AVLStack.cEntries--;
+            if (pNode->pLeft != NULL)
+            {
+                AVLStack.achFlags[AVLStack.cEntries] = 0;
+                AVLStack.aEntries[AVLStack.cEntries++] = pNode->pLeft;
+            }
+        } /* while */
+    }
+
+    return 0;
+}
+
+
+/**
+ * Starts an enumeration of all nodes in the given AVL tree.
+ * @returns   Pointer to the first node in the tree.
+ * @param     ppTree     Pointer to the AVL-tree root node pointer.
+ * @param     pEnumData  Pointer to enumeration control data.
+ * @param     fFromLeft  TRUE:  Left to right.
+ *                       FALSE: Right to left.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+PAVLNODECORE AVLBeginEnumTree(PPAVLNODECORE ppTree, PAVLENUMDATA pEnumData, int fFromLeft)
+{
+    if (*ppTree != NULL)
+    {
+        pEnumData->fFromLeft = (char)fFromLeft;
+        pEnumData->cEntries = 1;
+        pEnumData->aEntries[0] = *ppTree;
+        pEnumData->achFlags[0] = 0;
+    }
+    else
+        pEnumData->cEntries = 0;
+
+    return AVLGetNextNode(pEnumData);
+}
+
+
+/**
+ * Get the next node in the tree enumeration.
+ * @returns   Pointer to the first node in the tree.
+ * @param     pEnumData  Pointer to enumeration control data.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+PAVLNODECORE AVLGetNextNode(PAVLENUMDATA pEnumData)
+{
+    PAVLNODECORE    pNode;
+
+    if (pEnumData->fFromLeft)
+    {   /* from left */
+        while (pEnumData->cEntries > 0)
+        {
+            pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
+
+            /* left */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                if (pNode->pLeft != NULL)
+                {
+                    pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 left, 1 center, 2 right */
+                    pEnumData->aEntries[pEnumData->cEntries++] = pNode->pLeft;
+                    continue;
+                }
+            }
+
+            /* center */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                return pNode;
+            }
+
+            /* right */
+            pEnumData->cEntries--;
+            if (pNode->pRight != NULL)
+            {
+                pEnumData->achFlags[pEnumData->cEntries] = 0;
+                pEnumData->aEntries[pEnumData->cEntries++] = pNode->pRight;
+            }
+        } /* while */
+    }
+    else
+    {   /* from right */
+        while (pEnumData->cEntries > 0)
+        {
+            pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
+
+
+            /* right */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                if (pNode->pRight != NULL)
+                {
+                    pEnumData->achFlags[pEnumData->cEntries] = 0;  /* 0 right, 1 center, 2 left */
+                    pEnumData->aEntries[pEnumData->cEntries++] = pNode->pRight;
+                    continue;
+                }
+            }
+
+            /* center */
+            if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1)
+            {
+                pEnumData->achFlags[pEnumData->cEntries - 1]++;
+                return pNode;
+            }
+
+            /* left */
+            pEnumData->cEntries--;
+            if (pNode->pLeft != NULL)
+            {
+                pEnumData->achFlags[pEnumData->cEntries] = 0;
+                pEnumData->aEntries[pEnumData->cEntries++] = pNode->pLeft;
+            }
+        } /* while */
+    }
+
+    return NULL;
+
+}
+
+
+
+
+/**
+ * Finds the best fitting node in the tree for the given Key value.
+ * @returns   Pointer to the best fitting node found.
+ * @param     ppTree  Pointer to Pointer to the tree root node.
+ * @param     Key     The Key of which is to be found a best fitting match for..
+ * @param     fAbove  TRUE:  Returned node is have the closest key to Key from above.
+ *                    FALSE: Returned node is have the closest key to Key from below.
+ * @status    completely implemented.
+ * @sketch    The best fitting node is always located in the searchpath above you.
+ *            >= (above): The node where you last turned left.
+ *            <= (below): the node where you last turned right.
+ * @author    knut st. osmundsen
+ */
+PAVLNODECORE    AVLGetBestFit(PPAVLNODECORE ppTree, AVLKEY Key, int fAbove)
+{
+    #ifdef AVL_CMP
+    register int            iDiff;
+    #endif
+    register PAVLNODECORE   pNode = *ppTree;
+    PAVLNODECORE            pNodeLast = NULL;
+
+    if (fAbove)
+    {   /* pNode->Key >= Key */
+        #ifndef AVL_CMP
+        while (pNode != NULL && AVL_NE(pNode->Key, Key))
+        #else
+        while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)
+        #endif
+        {
+            #ifndef AVL_CMP
+            if (AVL_G(pNode->Key, Key))
+            #else
+            if (iDiff > 0)
+            #endif
+            {
+                pNodeLast = pNode;
+                pNode = pNode->pLeft;
+            }
+            else
+                pNode = pNode->pRight;
+        }
+    }
+    else
+    {   /* pNode->Key <= Key */
+        #ifndef AVL_CMP
+        while (pNode != NULL && AVL_NE(pNode->Key, Key))
+        #else
+        while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)
+        #endif
+        {
+            #ifndef AVL_CMP
+            if (AVL_L(pNode->Key, Key))
+            #else
+            if (iDiff < 0)
+            #endif
+            {
+                pNodeLast = pNode;
+                pNode = pNode->pRight;
+            }
+            else
+                pNode = pNode->pLeft;
+        }
+    }
+
+    return pNode == NULL ? pNodeLast /* best fit */ : pNode /* perfect match */;
+}
+
+
+/**
+ * Rewindes a stack of pointer to pointers to nodes, rebalancing the tree.
+ * @param     pStack  Pointer to stack to rewind.
+ * @sketch    LOOP thru all stack entries
+ *            BEGIN
+ *                Get pointer to pointer to node (and pointer to node) from stack.
+ *                IF 2 higher left subtree than in right subtree THEN
+ *                BEGIN
+ *                    IF higher (or equal) left-sub-subtree than right-sub-subtree THEN
+ *                                *                       n+2|n+3
+ *                              /   \                     /     \
+ *                            n+2    n       ==>         n+1   n+1|n+2
+ *                           /   \                             /     \
+ *                         n+1 n|n+1                          n|n+1  n
+ *
+ *                         Or with keys:
+ *
+ *                               4                           2
+ *                             /   \                       /   \
+ *                            2     5        ==>          1     4
+ *                           / \                               / \
+ *                          1   3                             3   5
+ *
+ *                    ELSE
+ *                                *                         n+2
+ *                              /   \                      /   \
+ *                            n+2    n                   n+1   n+1
+ *                           /   \           ==>        /  \   /  \
+ *                          n    n+1                    n  L   R   n
+ *                               / \
+ *                              L   R
+ *
+ *                         Or with keys:
+ *                               6                           4
+ *                             /   \                       /   \
+ *                            2     7        ==>          2     6
+ *                          /   \                       /  \  /  \
+ *                          1    4                      1  3  5  7
+ *                              / \
+ *                             3   5
+ *                END
+ *                ELSE IF 2 higher in right subtree than in left subtree THEN
+ *                BEGIN
+ *                    Same as above but left <==> right. (invert the picture)
+ *                ELSE
+ *                    IF correct height THEN break
+ *                    ELSE correct height.
+ *            END
+ * @status
+ * @author    knut st. osmundsen
+ * @remark
+ */
+INLINE void AVLRebalance(PAVLSTACK pStack)
+{
+    while (pStack->cEntries > 0)
+    {
+        PPAVLNODECORE   ppNode = pStack->aEntries[--pStack->cEntries];
+        PAVLNODECORE    pNode = *ppNode;
+        PAVLNODECORE    pLeftNode = pNode->pLeft;
+        unsigned char   uchLeftHeight = AVL_HEIGHTOF(pLeftNode);
+        PAVLNODECORE    pRightNode = pNode->pRight;
+        unsigned char   uchRightHeight = AVL_HEIGHTOF(pRightNode);
+
+        if (uchRightHeight + 1 < uchLeftHeight)
+        {
+            PAVLNODECORE    pLeftLeftNode = pLeftNode->pLeft;
+            PAVLNODECORE    pLeftRightNode = pLeftNode->pRight;
+            unsigned char   uchLeftRightHeight = AVL_HEIGHTOF(pLeftRightNode);
+
+            if (AVL_HEIGHTOF(pLeftLeftNode) >= uchLeftRightHeight)
+            {
+                pNode->pLeft = pLeftRightNode;
+                pLeftNode->pRight = pNode;
+                pLeftNode->uchHeight = (unsigned char)(1 + (pNode->uchHeight = (unsigned char)(1 + uchLeftRightHeight)));
+                *ppNode = pLeftNode;
+            }
+            else
+            {
+                pLeftNode->pRight = pLeftRightNode->pLeft;
+                pNode->pLeft = pLeftRightNode->pRight;
+                pLeftRightNode->pLeft = pLeftNode;
+                pLeftRightNode->pRight = pNode;
+                pLeftNode->uchHeight = pNode->uchHeight = uchLeftRightHeight;
+                pLeftRightNode->uchHeight = uchLeftHeight;
+                *ppNode = pLeftRightNode;
+            }
+        }
+        else if (uchLeftHeight + 1 < uchRightHeight)
+        {
+            PAVLNODECORE    pRightLeftNode = pRightNode->pLeft;
+            unsigned char   uchRightLeftHeight = AVL_HEIGHTOF(pRightLeftNode);
+            PAVLNODECORE    pRightRightNode = pRightNode->pRight;
+
+            if (AVL_HEIGHTOF(pRightRightNode) >= uchRightLeftHeight)
+            {
+                pNode->pRight = pRightLeftNode;
+                pRightNode->pLeft = pNode;
+                pRightNode->uchHeight = (unsigned char)(1 + (pNode->uchHeight = (unsigned char)(1 + uchRightLeftHeight)));
+                *ppNode = pRightNode;
+            }
+            else
+            {
+                pRightNode->pLeft = pRightLeftNode->pRight;
+                pNode->pRight = pRightLeftNode->pLeft;
+                pRightLeftNode->pRight = pRightNode;
+                pRightLeftNode->pLeft = pNode;
+                pRightNode->uchHeight = pNode->uchHeight = uchRightLeftHeight;
+                pRightLeftNode->uchHeight = uchRightHeight;
+                *ppNode = pRightLeftNode;
+            }
+        }
+        else
+        {
+            register unsigned char uchHeight = (unsigned char)(max(uchLeftHeight, uchRightHeight) + 1);
+            if (uchHeight == pNode->uchHeight)
+                break;
+            pNode->uchHeight = uchHeight;
+        }
+    }
+}
+
Index: /tags/kBuild-0.1.4/src/fastdep/avl.h
===================================================================
--- /tags/kBuild-0.1.4/src/fastdep/avl.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/fastdep/avl.h	(revision 1780)
@@ -0,0 +1,102 @@
+/* $Id$
+ *
+ * AVL-Tree (lookalike) declaration.
+ *
+ * This AVL implementation is configurable from this headerfile. By
+ * for example alterning the AVLKEY typedefinition an the AVL_<L|G|E|N>[E]
+ * macros you are able to create different trees. Currently you may only have
+ * one type of trees within one program (module).
+ *
+ * TREETYPE: Case Sensitive Strings (Key is pointer).
+ *
+ *
+ * Copyright (c) 1999-2000 knut st. osmundsen
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+#ifndef _AVL_H_
+#define _AVL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * AVL configuration. PRIVATE!
+ */
+#define AVL_MAX_HEIGHT              19          /* Up to 2^16 nodes. */
+#define AVL_MAY_TRY_INSERT_EQUAL    1           /* Ignore attempts to insert existing nodes. */
+
+/*
+ * AVL Compare macros
+ */
+#define AVL_L(key1, key2)  (strcmp(key1, key2) <  0)
+#define AVL_LE(key1, key2) (strcmp(key1, key2) <= 0)
+#define AVL_G(key1, key2)  (strcmp(key1, key2) >  0)
+#define AVL_GE(key1, key2) (strcmp(key1, key2) >= 0)
+#define AVL_E(key1, key2)  (strcmp(key1, key2) == 0)
+#define AVL_NE(key1, key2) (strcmp(key1, key2) != 0)
+#define AVL_CMP(key1, key2) strcmp(key1, key2)
+
+/**
+ * AVL key type
+ */
+typedef const char *AVLKEY;
+
+
+/**
+ * AVL Core node.
+ */
+typedef struct _AVLNodeCore
+{
+    AVLKEY                  Key;       /* Key value. */
+    struct  _AVLNodeCore *  pLeft;     /* Pointer to left leaf node. */
+    struct  _AVLNodeCore *  pRight;    /* Pointer to right leaf node. */
+    unsigned char           uchHeight; /* Height of this tree: max(heigth(left), heigth(right)) + 1 */
+} AVLNODECORE, *PAVLNODECORE, **PPAVLNODECORE;
+
+
+/**
+ * AVL Enum data - All members are PRIVATE! Don't touch!
+ */
+typedef struct _AVLEnumData
+{
+    char         fFromLeft;
+    char         cEntries;
+    char         achFlags[AVL_MAX_HEIGHT];
+    PAVLNODECORE aEntries[AVL_MAX_HEIGHT];
+} AVLENUMDATA, *PAVLENUMDATA;
+
+
+/*
+ * callback type
+ */
+typedef unsigned ( _PAVLCALLBACK)(PAVLNODECORE, void*);
+typedef _PAVLCALLBACK *PAVLCALLBACK;
+
+
+BOOL            AVLInsert(PPAVLNODECORE ppTree, PAVLNODECORE pNode);
+PAVLNODECORE    AVLRemove(PPAVLNODECORE ppTree, AVLKEY Key);
+PAVLNODECORE    AVLGet(PPAVLNODECORE ppTree, AVLKEY Key);
+PAVLNODECORE    AVLGetWithParent(PPAVLNODECORE ppTree, PPAVLNODECORE ppParent, AVLKEY Key);
+PAVLNODECORE    AVLGetWithAdjecentNodes(PPAVLNODECORE ppTree, AVLKEY Key, PPAVLNODECORE ppLeft, PPAVLNODECORE ppRight);
+unsigned        AVLDoWithAll(PPAVLNODECORE ppTree, int fFromLeft, PAVLCALLBACK pfnCallBack, void *pvParam);
+PAVLNODECORE    AVLBeginEnumTree(PPAVLNODECORE ppTree, PAVLENUMDATA pEnumData, int fFromLeft);
+PAVLNODECORE    AVLGetNextNode(PAVLENUMDATA pEnumData);
+PAVLNODECORE    AVLGetBestFit(PPAVLNODECORE ppTree, AVLKEY Key, int fAbove);
+
+
+
+/*
+ * Just in case NULL is undefined.
+ */
+#ifndef NULL
+    #define NULL ((void*)0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /tags/kBuild-0.1.4/src/fastdep/fastdep.c
===================================================================
--- /tags/kBuild-0.1.4/src/fastdep/fastdep.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/fastdep/fastdep.c	(revision 1780)
@@ -0,0 +1,4136 @@
+/* $Id$
+ *
+ * Fast dependents. (Fast = Quick and Dirty!)
+ *
+ * Copyright (c) 1999-2002 knut st. osmundsen (bird-kBuild-spam@anduin.net)
+ *
+ * GPL
+ *
+ */
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#define INCL_DOSERRORS
+#define INCL_FILEMGR
+#define INCL_DOSMISC
+
+
+/*
+ * Size of the \n charater (forget '\r').
+ * If you're compiling this under a UNICODE system this may perhaps change,
+ * but I doubd that fastdep will work at all under a UNICODE system. ;-)
+ */
+#if defined(UNICODE) && !defined(__WIN32OS2__)
+#define CBNEWLINE       (2)
+#else
+#define CBNEWLINE       (1)
+#endif
+
+
+/*
+ * Time stamp size.
+ */
+#define TS_SIZE         (48)
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#if defined(OS2FAKE)
+#include "os2fake.h"
+#else
+#include <os2.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <direct.h>
+#include <assert.h>
+
+#include "avl.h"
+
+#ifdef __WIN32OS2__
+#   define WIN32API
+#   include <odinbuild.h>
+#else
+#   define ODIN32_BUILD_NR -1
+#endif
+
+#ifndef INLINE
+#   if defined(__IBMC__)
+#       define INLINE _Inline
+#   elif defined(__IBMCPP__)
+#       define INLINE inline
+#   elif defined(__WATCOMC__)
+#       define INLINE __inline
+#   elif defined(__WATCOM_CPLUSPLUS__)
+#       define INLINE inline
+#   else
+#       error message("unknown compiler - inline keyword unknown!")
+#   endif
+#endif
+
+/*
+ * This following section is used while testing fastdep.
+ * stdio.h should be included; string.h never included.
+ */
+/*
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+*/
+
+#if 1
+#include <stdio.h>
+#else
+#include <string.h>
+#include <string.h>
+#endif
+
+/*
+ */ /* */ /*
+#include <string.h>
+ */
+#if 1
+#    if 1
+        #if 0
+# include <string.h>
+        #else
+#            if 1
+                #if 1
+                    #if 0
+# include <string.h>
+                    #else /* */ /*
+*/
+ # include <stdio.h>
+                    #endif
+                #endif
+            #endif
+        #endif
+    #endif
+#endif
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+typedef struct _Options
+{
+    const char *    pszInclude;
+    const char *    pszExclude;
+    BOOL            fExcludeAll;
+    const char *    pszObjectExt;
+    const char *    pszObjectDir;
+    BOOL            fObjectDir;         /* replace object directory? */
+    const char *    pszRsrcExt;
+    BOOL            fObjRule;
+    BOOL            fNoObjectPath;
+    BOOL            fSrcWhenObj;
+    BOOL            fAppend;            /* append to the output file, not overwrite it. */
+    BOOL            fCheckCyclic;       /* allways check for cylic dependency before inserting an dependent. */
+    BOOL            fCacheSearchDirs;   /* cache entire search dirs. */
+    const char *    pszExcludeFiles;    /* List of excluded files. */
+    BOOL            fForceScan;         /* Force scan of all files. */
+} OPTIONS, *POPTIONS;
+
+
+/*
+ * Language specific analysis functions type.
+ */
+typedef int ( _FNLANG)  (const char *pszFilename, const char *pszNormFilename,
+                         const char *pszTS, BOOL fHeader, void **ppvRule);
+typedef _FNLANG    *PFNLANG;
+
+
+/**
+ * This struct holds the static configuration of the util.
+ */
+typedef struct _ConfigEntry
+{
+    char         szId[16];              /* Config ID. */
+    const char **papszExts;             /* Pointer to an array of pointer to extentions for this handler. */
+                                        /* If NULL this is the last entry. */
+    int          iFirstHdr;             /* Index into the papszExts array of the first headerfile/copybook. */
+                                        /* Set it to the NULL element of the array if no headers for this extention. */
+                                        /* A non-header file may get a object rule. */
+    PFNLANG      pfn;                   /* Pointer to handler function. */
+    char        *pszzAddDeps;           /* Pointer to an string of string of additional dependencies. */
+} CONFIGENTRY, *PCONFIGENTRY;
+
+
+/**
+ * Dependant Rule
+ */
+typedef struct _DepRule
+{
+    AVLNODECORE     avlCore;
+    char *          pszRule;            /* Pointer to rule name */
+    int             cDeps;              /* Entries in the dependant array. */
+    char **         papszDep;           /* Pointer to an array of pointers to dependants. */
+    BOOL            fUpdated;           /* If we have updated this entry during the run. */
+    char            szTS[TS_SIZE];      /* Time stamp. */
+} DEPRULE, *PDEPRULE;
+
+
+/**
+ * Filename cache entry.
+ */
+#define FCACHEENTRY     AVLNODECORE
+#define PFCACHEENTRY    PAVLNODECORE
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static void syntax(void);
+static int makeDependent(const char *pszFilename, const char *pszTS);
+
+static int langC_CPP(const char *pszFilename, const char *pszNormFilename, const char *pszTS, BOOL fHeader, void **ppvRule);
+static int langAsm(  const char *pszFilename, const char *pszNormFilename, const char *pszTS, BOOL fHeader, void **ppvRule);
+static int langRC(   const char *pszFilename, const char *pszNormFilename, const char *pszTS, BOOL fHeader, void **ppvRule);
+static int langCOBOL(const char *pszFilename, const char *pszNormFilename, const char *pszTS, BOOL fHeader, void **ppvRule);
+static int langIPF(  const char *pszFilename, const char *pszNormFilename, const char *pszTS, BOOL fHeader, void **ppvRule);
+
+
+/* string operations */
+static int strnicmpwords(const char *pszS1, const char *pszS2, int cch);
+
+/* file operations */
+static char *fileNormalize(char *pszFilename);
+static char *fileNormalize2(const char *pszFilename, char *pszBuffer);
+       char *filePath(const char *pszFilename, char *pszBuffer);
+static char *filePathSlash(const char *pszFilename, char *pszBuffer);
+static char *filePathSlash2(const char *pszFilename, char *pszBuffer);
+static char *fileName(const char *pszFilename, char *pszBuffer);
+static char *fileNameNoExt(const char *pszFilename, char *pszBuffer);
+static char *fileExt(const char *pszFilename, char *pszBuffer);
+
+/* filecache operations */
+static BOOL filecacheAddFile(const char *pszFilename);
+static BOOL filecacheAddDir(const char *pszDir);
+INLINE BOOL filecacheFind(const char *pszFilename);
+INLINE BOOL filecacheIsDirCached(const char *pszDir);
+static char*filecacheFileExist(const char *pszFilename, char *pszBuffer);
+
+/* pathlist operations */
+static char *pathlistFindFile(const char *pszPathList, const char *pszFilename, char *pszBuffer);
+static BOOL  pathlistFindFile2(const char *pszPathList, const char *pszFilename);
+
+/* word operations */
+static char *findEndOfWord(char *psz);
+#if 0 /* not used */
+static char *findStartOfWord(char *psz, const char *pszStart);
+#endif
+
+/* file helpers */
+static signed long fsize(FILE *phFile);
+
+/* text helpers */
+INLINE char *trim(char *psz);
+INLINE char *trimR(char *psz);
+INLINE char *trimQuotes(char *psz);
+
+/* preprocessors */
+static char *PreProcessLine(char *pszOut, const char *pszIn);
+
+/* textbuffer */
+static void *textbufferCreate(const char *pszFilename);
+static void  textbufferDestroy(void *pvBuffer);
+static char *textbufferNextLine(void *pvBuffer, char *psz);
+static char *textbufferGetNextLine(void *pvBuffer, void **ppv, char *pszLineBuffer, int cchLineBuffer);
+
+/* depend workers */
+static BOOL  depReadFile(const char *pszFilename, BOOL fAppend);
+static BOOL  depWriteFile(const char *pszFilename, BOOL fWriteUpdatedOnly);
+static void  depRemoveAll(void);
+static void *depAddRule(const char *pszRulePath, const char *pszName, const char *pszExt, const char *pszTS, BOOL fConvertName);
+static BOOL  depAddDepend(void *pvRule, const char *pszDep, BOOL fCheckCyclic, BOOL fConvertName);
+static int   depNameToReal(char *pszName);
+static int   depNameToMake(char *pszName, int cchName, const char *pszSrc);
+static void  depMarkNotFound(void *pvRule);
+static BOOL  depCheckCyclic(PDEPRULE pdepRule, const char *pszDep);
+static BOOL  depValidate(PDEPRULE pdepRule);
+INLINE char *depMakeTS(char *pszTS, PFILEFINDBUF3 pfindbuf3);
+static void  depAddSrcAddDeps(void *pvRule, const char *pszz);
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/*
+ * Pointer to the list of dependencies.
+ */
+static PDEPRULE pdepTree = NULL;
+
+
+/*
+ * Filecache - tree starts here.
+ */
+static PFCACHEENTRY pfcTree = NULL;
+static unsigned     cfcNodes = 0;
+static PFCACHEENTRY pfcDirTree = NULL;
+
+
+/*
+ * Current directory stuff
+ */
+static char     szCurDir[CCHMAXPATH];
+static int      aiSlashes[CCHMAXPATH];
+static int      cSlashes;
+
+
+/*
+ * Environment variables used.
+ * (These has the correct case.)
+ */
+static char *   pszIncludeEnv;
+
+
+/*
+ * Configuration stuff.
+ */
+static const char pszDefaultDepFile[] = ".depend";
+static const char *apszExtC_CPP[] = {"c", "sqc", "cpp", "h", "hpp", NULL};
+static const char *apszExtAsm[]   = {"asm", "inc", NULL};
+static const char *apszExtRC[]    = {"rc",  "dlg", NULL};
+static const char *apszExtORC[]   = {"orc", "dlg", NULL};
+static const char *apszExtCOBOL[] = {"cbl", "cob", "sqb", "wbl", NULL};
+static const char *apszExtIPF[]   = {"ipf", "man", NULL};
+static const char *apszExtIPP[]   = {"ipp", NULL};
+static CONFIGENTRY aConfig[] =
+{
+    {
+        "CX",
+        apszExtC_CPP,
+        3,
+        langC_CPP,
+        NULL,
+    },
+
+    {
+        "AS",
+        apszExtAsm,
+        1,
+        langAsm,
+        NULL,
+    },
+
+    {
+        "RC",
+        apszExtRC,
+        1,
+        langRC,
+        NULL,
+    },
+
+    {
+        "ORC",
+        apszExtORC,
+        1,
+        langRC,
+        NULL,
+    },
+
+    {
+        "COB",
+        apszExtCOBOL,
+        -1,
+        langCOBOL,
+        NULL,
+    },
+
+    {
+        "IPF",
+        apszExtIPF,
+        -1,
+        langIPF,
+        NULL,
+    },
+
+    {
+        "IPP",
+        apszExtIPP,
+        -1,
+        langC_CPP,
+        NULL,
+    },
+
+    /* terminating entry */
+    {
+        "",
+        NULL,
+        -1,
+        NULL,
+        NULL
+    }
+};
+
+
+static char szObjectDir[CCHMAXPATH];
+static char szObjectExt[64] = "obj";
+static char szRsrcExt[64]   = "res";
+static char szInclude[32768] = ";";
+static char szExclude[32768] = ";";
+static char szExcludeFiles[65536] = "";
+
+OPTIONS options =
+{
+    szInclude,       /* pszInclude */
+    szExclude,       /* pszExclude */
+    FALSE,           /* fExcludeAll */
+    szObjectExt,     /* pszObjectExt */
+    szObjectDir,     /* pszObjectDir */
+    FALSE,           /* fObjectDir */
+    szRsrcExt,       /* pszRsrcExt */
+    TRUE,            /* fObjRule */
+    FALSE,           /* fNoObjectPath */
+    TRUE,            /* fSrcWhenObj */
+    FALSE,           /* fAppend */
+    TRUE,            /* fCheckCyclic */
+    TRUE,            /* fCacheSearchDirs */
+    szExcludeFiles,  /* pszExcludeFiles */
+    FALSE            /* fForceScan */
+};
+
+
+/**
+ * Main function.
+ * @returns   0 on success.
+ *           -n count of failiures.
+ * @param
+ * @param
+ * @equiv
+ * @precond
+ * @methdesc
+ * @result
+ * @time
+ * @sketch
+ * @algo
+ * @remark
+ */
+int main(int argc, char **argv)
+{
+    int         rc   = 0;
+    int         argi = 1;
+    int         i;
+    char *      psz;
+    char *      psz2;
+    const char *pszDepFile = pszDefaultDepFile;
+    char        achBuffer[4096];
+
+    szObjectDir[0] = '\0';
+
+    if (argc == 1)
+    {
+        syntax();
+        return -87;
+    }
+
+    /*
+     * Initiate current directory stuff
+     */
+    if (_getcwd(szCurDir, sizeof(szCurDir)) == NULL)
+    {
+        fprintf(stderr, "fatal error: failed to get current directory\n");
+        return -88;
+    }
+    strlwr(szCurDir);
+    aiSlashes[0] = 0;
+    for (i = 1, cSlashes; szCurDir[i] != '\0'; i++)
+    {
+        if (szCurDir[i] == '/')
+            szCurDir[i] = '\\';
+        if (szCurDir[i] == '\\')
+            aiSlashes[cSlashes++] = i;
+    }
+    if (szCurDir[i-1] != '\\')
+    {
+        aiSlashes[cSlashes] = i;
+        szCurDir[i++] = '\\';
+        szCurDir[i] = '\0';
+    }
+
+
+    /*
+     * Initiate environment variables used: INCLUDE
+     */
+    psz = getenv("INCLUDE");
+    if (psz != NULL)
+    {
+        pszIncludeEnv = strdup(psz);
+        strlwr(pszIncludeEnv);
+    }
+    else
+        pszIncludeEnv = "";
+
+
+    /*
+     * Disable hard errors.
+     */
+    DosError(FERR_DISABLEHARDERR | FERR_ENABLEEXCEPTION);
+
+
+    /*
+     * parse arguments
+     */
+    while (argi < argc)
+    {
+        if (argv[argi][0] == '-' || argv[argi][0] == '/')
+        {
+            /* parameters */
+            switch (argv[argi][1])
+            {
+                case 'A':
+                case 'a': /* Append to the output file */
+                    options.fAppend = argv[argi][2] != '-';
+                    break;
+
+                case 'D':
+                case 'd': /* "-d <filename>" */
+                {
+                    const char *pszOld = pszDepFile;
+                    if (argv[argi][2] != '\0')
+                        pszDepFile = &argv[argi][2];
+                    else
+                    {
+                        argi++;
+                        if (argi < argc)
+                            pszDepFile = argv[argi];
+                        else
+                        {
+                            fprintf(stderr, "invalid parameter -d, filename missing!\n");
+                            return -1;
+                        }
+                    }
+
+                    /* if dependencies are generated we'll flush them to the old filename */
+                    if (pdepTree != NULL && pszOld != pszDepFile)
+                    {
+                        if (!depWriteFile(pszOld, !options.fAppend))
+                            fprintf(stderr, "error: failed to write (flush) dependencies.\n");
+                        depRemoveAll();
+                    }
+                    break;
+                }
+
+                case 'C': /* forced directory cache  'ca' or cylic check 'cy'*/
+                case 'c':
+                    if (argv[argi][2] == 'a' || argv[argi][2] == 'A')
+                        options.fCacheSearchDirs = TRUE;
+                    else if ((argv[argi][2] == 'y' || argv[argi][2] == 'Y'))
+                        options.fCheckCyclic = argv[argi][3] != '-';
+                    break;
+
+                case 'E': /* list of paths. If a file is found in one of these directories the */
+                case 'e': /* filename will be used without the directory path. */
+                    /* Eall<[+]|-> ? */
+                    if (strlen(&argv[argi][1]) <= 5 && strnicmp(&argv[argi][1], "Eall", 4) == 0)
+                    {
+                        options.fExcludeAll = argv[argi][5] != '-';
+                        break;
+                    }
+                    /* path or path list */
+                    if (strlen(argv[argi]) > 2)
+                        psz = &argv[argi][2];
+                    else
+                    {
+                        if (++argi >= argc)
+                        {
+                            fprintf(stderr, "syntax error! Option -e.\n");
+                            return 1;
+                        }
+                        psz = argv[argi];
+                    }
+                    /* check if enviroment variable */
+                    if (*psz == '%')
+                    {
+                        psz2 = strdup(psz+1);
+                        if (psz2 != NULL && *psz2 != '\0')
+                        {
+                            if (psz2[strlen(psz2)-1] == '%')
+                                psz2[strlen(psz2)-1] = '\0';
+                            psz = getenv(psz2);
+                            free(psz2);
+                            if (psz == NULL)
+                                break;
+                        }
+                        else
+                        {
+                            fprintf(stderr, "error: -E% is not an valid argument!\n");
+                            return -1;
+                        }
+                    }
+                    if (psz != NULL)
+                    {
+                        strcat(szExclude, psz);
+                        strlwr(szExclude);
+                        if (szExclude[strlen(szExclude)-1] != ';')
+                            strcat(szExclude, ";");
+                    }
+                    break;
+
+                case 'f':
+                case 'F': /* force scan of all files. */
+                    options.fForceScan = argv[argi][2] != '-';
+                    break;
+
+                case 'I': /* optional include path. This has precedence over the INCLUDE environment variable. */
+                case 'i':
+                    if (strlen(argv[argi]) > 2)
+                        psz = &argv[argi][2];
+                    else
+                    {
+                        if (++argi >= argc)
+                        {
+                            fprintf(stderr, "syntax error! Option -i.\n");
+                            return 1;
+                        }
+                        psz = argv[argi];
+                    }
+                    /* check if enviroment variable */
+                    if (*psz == '%')
+                    {
+                        psz2 = strdup(psz+1);
+                        if (psz2 != NULL && *psz2 != '\0')
+                        {
+                            if (psz2[strlen(psz2)-1] == '%')
+                                psz2[strlen(psz2)-1] = '\0';
+                            psz = getenv(psz2);
+                            free(psz2);
+                            if (psz == NULL)
+                                break;
+                        }
+                        else
+                        {
+                            fprintf(stderr, "error: -I% is not an valid argument!\n");
+                            return -1;
+                        }
+                    }
+                    if (psz != NULL)
+                    {
+                        strcat(szInclude, psz);
+                        strlwr(szInclude);
+                        if (szInclude[strlen(szInclude)-1] != ';')
+                            strcat(szInclude, ";");
+                    }
+                    break;
+
+                case 'n': /* no object path , -N<[+]|-> */
+                case 'N':
+                    if (strlen(argv[argi]) <= 1+1+1)
+                        options.fNoObjectPath = argv[argi][2] != '-';
+                    else
+                    {
+                        fprintf(stderr, "error: invalid parameter!, '%s'\n", argv[argi]);
+                        return -1;
+                    }
+                    break;
+
+                case 'o': /* object base directory, Obj or Obr<[+]|-> */
+                case 'O':
+                    if (strlen(&argv[argi][1]) <= 4 && strnicmp(&argv[argi][1], "Obr", 3) == 0)
+                    {
+                        options.fObjRule = argv[argi][4] != '-';
+                        break;
+                    }
+
+                    if (strlen(&argv[argi][1]) >= 4 && strnicmp(&argv[argi][1], "Obj", 3) == 0)
+                    {
+                        if (strlen(argv[argi]) > 4)
+                            strcpy(szObjectExt, argv[argi]+4);
+                        else
+                        {
+                            if (++argi >= argc)
+                            {
+                                fprintf(stderr, "syntax error! Option -obj.\n");
+                                return 1;
+                            }
+                            strcpy(szObjectExt, argv[argi]);
+                        }
+                        break;
+                    }
+
+                    /* path: -o or -o- */
+                    options.fObjectDir = TRUE;
+                    if (strlen(argv[argi]) > 2)
+                    {
+                        if (argv[argi][2] == '-')  /* no object path */
+                            szObjectDir[0] = '\0';
+                        else
+                            strcpy(szObjectDir, argv[argi]+2);
+                    }
+                    else
+                    {
+                        if (++argi >= argc)
+                        {
+                            fprintf(stderr, "syntax error! Option -o.\n");
+                            return 1;
+                        }
+                        strcpy(szObjectDir, argv[argi]);
+                    }
+                    if (szObjectDir[0] != '\0'
+                        && szObjectDir[strlen(szObjectDir)-1] != '\\'
+                        && szObjectDir[strlen(szObjectDir)-1] != '/'
+                        )
+                        strcat(szObjectDir, "\\");
+                    break;
+
+                case 'r':
+                case 'R':
+                    if (strlen(argv[argi]) > 2)
+                        strcpy(szRsrcExt, argv[argi]+2);
+                    else
+                    {
+                        if (++argi >= argc)
+                        {
+                            fprintf(stderr, "syntax error! Option -r.\n");
+                            return 1;
+                        }
+                        strcpy(szRsrcExt, argv[argi]);
+                    }
+                    break;
+
+                case 's':
+                case 'S':
+                    if (!strnicmp(argv[argi]+1, "srcadd", 6))
+                    {
+                        if (strlen(argv[argi]) > 7)
+                            psz = argv[argi]+2;
+                        else
+                        {
+                            if (++argi >= argc)
+                            {
+                                fprintf(stderr, "syntax error! Option -srcadd.\n");
+                                return 1;
+                            }
+                            psz = argv[argi];
+                        }
+                        if (!(psz2 = strchr(psz, ':')))
+                        {
+                            fprintf(stderr, "syntax error! Option -srcadd malformed!\n");
+                            return 1;
+                        }
+                        for (i = 0; aConfig[i].pfn; i++)
+                        {
+                            if (    !strnicmp(aConfig[i].szId, psz, psz2 - psz)
+                                &&  !aConfig[i].szId[psz2 - psz])
+                            {
+                                int cch, cch2;
+                                if (!*++psz2)
+                                {
+                                    fprintf(stderr, "error: Option -srcadd no additioanl dependancy!\n",
+                                            psz2 - psz, psz);
+                                    return 1;
+                                }
+                                cch = 0;
+                                psz = aConfig[i].pszzAddDeps;
+                                if (psz)
+                                {
+                                    do
+                                    {
+                                        cch += (cch2 = strlen(psz)) + 1;
+                                        psz += cch2 + 1;
+                                    } while (*psz);
+                                }
+                                cch2 = strlen(psz2);
+                                aConfig[i].pszzAddDeps = realloc(aConfig[i].pszzAddDeps, cch + cch2 + 2);
+                                if (!aConfig[i].pszzAddDeps)
+                                {
+                                    fprintf(stderr, "error: Out of memory!\n");
+                                    return 1;
+                                }
+                                strcpy(aConfig[i].pszzAddDeps + cch, psz2);
+                                aConfig[i].pszzAddDeps[cch + cch2 + 1] = '\0';
+                                psz = NULL;
+                                break;
+                            }
+                        }
+                        if (psz)
+                        {
+                            fprintf(stderr, "error: Option -srcadd, invalid language id '%.*s%'\n",
+                                    psz2 - psz, psz);
+                            return 1;
+                        }
+                    }
+                    else
+                    {
+                        fprintf(stderr, "syntax error! Invalid option %s\n", argv[argi]);
+                        return 1;
+                    }
+                    break;
+
+                case 'x':
+                case 'X': /* Exclude files */
+                    psz = &achBuffer[CCHMAXPATH+8];
+                    if (strlen(argv[argi]) > 2)
+                        strcpy(psz, &argv[argi][2]);
+                    else
+                    {
+                        if (++argi >= argc)
+                        {
+                            fprintf(stderr, "syntax error! Option -x.\n");
+                            return 1;
+                        }
+                        strcpy(psz, argv[argi]);
+                    }
+                    while (psz != NULL && *psz != ';')
+                    {
+                        char *  pszNext = strchr(psz, ';');
+                        int     cch = strlen(szExcludeFiles);
+                        if (pszNext)
+                            *pszNext++ = '\0';
+                        if (DosQueryPathInfo(psz, FIL_QUERYFULLNAME, &szExcludeFiles[cch], CCHMAXPATH))
+                        {
+                            fprintf(stderr, "error: Invalid exclude name\n");
+                            return -1;
+                        }
+                        strlwr(&szExcludeFiles[cch]);
+                        strcat(&szExcludeFiles[cch], ";");
+                        psz = pszNext;
+                    }
+                    break;
+
+                case 'h':
+                case 'H':
+                case '?':
+                    syntax();
+                    return 1;
+
+                default:
+                    fprintf(stderr, "error: invalid parameter! '%s'\n", argv[argi]);
+                    return -1;
+            }
+
+        }
+        else if (argv[argi][0] == '@')
+        {   /*
+             * Parameter file (debugger parameter length restrictions led to this):
+             *    Create a textbuffer.
+             *    Parse the file and create a new parameter vector.
+             *    Set argv to the new parameter vector, argi to 0 and argc to
+             *    the parameter count.
+             *    Restrictions: Parameters enclosed in "" is not implemented.
+             *                  No commandline parameters are processed after the @file
+             */
+            char *pszBuffer = (char*)textbufferCreate(&argv[argi][1]); /* !ASSUMS! that pvBuffer is the file string! */
+            if (pszBuffer != NULL)
+            {
+                char **apszArgs = NULL;
+                char *psz = pszBuffer;
+                int  i = 0;
+
+                while (*psz != '\0')
+                {
+                    /* find end of parameter word */
+                    char *pszEnd = psz + 1;
+                    char  ch = *pszEnd;
+                    while (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != '\0')
+                        ch = *++pszEnd;
+
+                    /* allocate more arg array space? */
+                    if ((i % 512) == 0)
+                    {
+                        apszArgs = realloc(apszArgs, sizeof(char*) * 512);
+                        if (apszArgs == NULL)
+                        {
+                            fprintf(stderr, "error: out of memory. (line=%d)\n", __LINE__);
+                            return -8;
+                        }
+                    }
+                    *pszEnd = '\0';
+                    apszArgs[i++] = psz;
+
+                    /* next */
+                    psz = pszEnd + 1;
+                    ch = *psz;
+                    while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+                        ch = *++psz;
+                }
+
+                argc = i;
+                argi = 0;
+                argv = apszArgs;
+                continue;
+            }
+            else
+            {
+                fprintf(stderr, "error: could not open parameter file\n");
+                return -1;
+            }
+        }
+        else
+        {   /* not a parameter! */
+            ULONG           ulRc;
+            PFILEFINDBUF3   pfindbuf3 = (PFILEFINDBUF3)(void*)&achBuffer[0];
+            HDIR            hDir = HDIR_CREATE;
+            ULONG           cFiles = ~0UL;
+            int             i;
+
+
+            /*
+             * If append option is or if the forcescan option isn't is
+             * we'll have to read the existing dep file before starting
+             * adding new dependencies.
+             */
+            if (pdepTree == NULL && (options.fAppend || !options.fForceScan))
+                depReadFile(pszDepFile, options.fAppend);
+
+            /*
+             * Search for the files specified.
+             */
+            ulRc = DosFindFirst(argv[argi], &hDir,
+                                FILE_READONLY |  FILE_HIDDEN | FILE_SYSTEM | FILE_ARCHIVED,
+                                pfindbuf3, sizeof(achBuffer), &cFiles, FIL_STANDARD);
+            if (!options.fCacheSearchDirs)
+                options.fCacheSearchDirs = cFiles > 25;
+            while (ulRc == NO_ERROR)
+            {
+                for (i = 0;
+                     i < cFiles;
+                     i++, pfindbuf3 = (PFILEFINDBUF3)((int)pfindbuf3 + pfindbuf3->oNextEntryOffset)
+                     )
+                {
+                    const char *    psz;
+                    char            szSource[CCHMAXPATH];
+                    BOOL            fExcluded;
+                    char            szTS[TS_SIZE];
+
+                    /*
+                     * Make full path.
+                     */
+                    if ((psz = strrchr(argv[argi], '\\')) || (psz = strrchr(argv[argi], '/')) || (*(psz = &argv[argi][1]) == ':'))
+                    {
+                        strncpy(szSource, argv[argi], psz - argv[argi] + 1);
+                        szSource[psz - argv[argi] + 1]  = '\0';
+                    }
+                    else
+                        szSource[0]  = '\0';
+                    strcat(szSource, pfindbuf3->achName);
+                    strlwr(szSource);
+                    fileNormalize(szSource);
+
+                    /*
+                     * Check if this is an excluded file.
+                     */
+                    fExcluded = FALSE;
+                    psz = options.pszExcludeFiles;
+                    while (*psz != '\0' && *psz != ';')
+                    {
+                        const char * pszNext = strchr(psz, ';');
+                        if (strlen(szSource) == pszNext - psz && strncmp(szSource, psz, pszNext - psz) == 0)
+                            fExcluded = TRUE;
+                        psz = pszNext + 1;
+                    }
+                    if (fExcluded)
+                        continue;
+
+                    /*
+                     * Analyse the file.
+                     */
+                    depMakeTS(szTS, pfindbuf3);
+                    rc -= makeDependent(&szSource[0], szTS);
+                }
+
+                /* next file */
+                cFiles = ~0UL;
+                pfindbuf3 = (PFILEFINDBUF3)(void*)&achBuffer[0];
+                ulRc = DosFindNext(hDir, pfindbuf3, sizeof(achBuffer), &cFiles);
+            }
+            DosFindClose(hDir);
+        }
+        /* next */
+        argi++;
+    }
+
+    /* Write the depend file! */
+    if (!depWriteFile(pszDepFile, !options.fAppend))
+        fprintf(stderr, "error: failed to write dependencies file!\n");
+    #if 0
+    printf("cfcNodes=%d\n", cfcNodes);
+    #endif
+
+    return rc;
+}
+
+
+/**
+ * Displays the syntax description for this util.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+void syntax(void)
+{
+    printf(
+        "FastDep v0.48 (build %d)\n"
+        "Dependency scanner. Creates a makefile readable depend file.\n"
+        " - was quick and dirty, now it's just quick -\n"
+        "\n"
+        "Syntax: FastDep [options] <files> [more options [more files [...]]]\n"
+        "    or\n"
+        "        FastDep [options] @<parameterfile>\n"
+        "\n"
+        "Options:\n"
+        "   -a<[+]|->       Append to the output file.            Default: Overwrite.\n"
+        "   -ca             Force search directory caching.\n"
+        "                   Default: cache if more that 25 files are to be searched.\n"
+        "                            (more than 25 in the first file expression.)\n"
+        "   -cy<[+]|->      Check for cylic dependencies.         Default: -cy-\n"
+        "   -d <outputfn>   Output filename.                      Default: %s\n"
+        "   -e excludepath  Exclude paths. If a filename is found in any\n"
+        "                   of these paths only the filename is used, not\n"
+        "                   the path+filename (which is default).\n"
+        "   -eall<[+]|->    Include and source filenames, paths or no paths.\n"
+        "                   -eall+: No path are added to the filename.\n"
+        "                   -eall-: The filename is appended the include path\n"
+        "                           was found in.\n"
+        "                   Default: eall-\n"
+        "   -f<[+]|->       Force scanning of all files. If disabled we'll only scan\n"
+        "                   files which are younger or up to one month older than the\n"
+        "                   dependancy file (if it exists).       Default: disabled\n"
+        "   -i <include>    Additional include paths. INCLUDE is searched after this.\n"
+        "   -n<[+]|->       No path for object files in the rules.\n"
+        "   -o <objdir>     Path were object files are placed. This path replaces the\n"
+        "                   entire filename path\n"
+        "   -o-             No object path\n"
+        "   -obr<[+]|->     -obr+: Object rule.\n"
+        "                   -obr-: No object rule, rule for source filename is generated.\n"
+        "   -obj[ ]<objext> Object extention.                     Default: obj\n"
+        "   -srcadd[ ]<langid>:<dep>\n"
+        "                   Additional dependants for source file of the given language\n"
+        "                   type. langid: AS,CX,RC,ORC,COB,IPF\n"
+        "                   This is very usfull for compiler configuration files.\n"
+        "   -r[ ]<rsrcext>  Resource binary extention.            Default: res\n"
+        "   -x[ ]<f1[;f2]>  Files to exclude. Only exact filenames.\n"
+        "   <files>         Files to scan. Wildchars are allowed.\n"
+        "\n"
+        "Options and files could be mixed.\n"
+        " copyright (c) 1999-2002 knut st. osmundsen (bird-kBuild-spam@anduin.net)\n",
+        ODIN32_BUILD_NR,
+        pszDefaultDepFile
+        );
+}
+
+
+/**
+ * Generates depend info on this file, these are stored internally
+ * and written to file later.
+ * @returns
+ * @param   pszFilename     Pointer to source filename. Correct case is assumed!
+ * @param   pszTS           File time stamp.
+ * @status  completely implemented.
+ * @author  knut st. osmundsen
+ */
+int makeDependent(const char *pszFilename, const char *pszTS)
+{
+    int    rc = -1;
+
+    char            szExt[CCHMAXPATH];
+    PCONFIGENTRY    pCfg = &aConfig[0];
+    BOOL            fHeader;
+
+    /*
+     * Find which filetype this is...
+     */
+    fileExt(pszFilename, szExt);
+    while (pCfg->papszExts != NULL)
+    {
+        const char **ppsz = pCfg->papszExts;
+        while (*ppsz != NULL && stricmp(*ppsz, szExt) != 0)
+            ppsz++;
+        if (*ppsz != NULL)
+        {
+            fHeader = pCfg->iFirstHdr > 0 && &pCfg->papszExts[pCfg->iFirstHdr] <= ppsz;
+            break;
+        }
+        pCfg++;
+    }
+
+    /* Found? */
+    if (pCfg->papszExts != NULL)
+    {
+        void *  pvRule = NULL;
+        char    szNormFile[CCHMAXPATH];
+        fileNormalize2(pszFilename, szNormFile);
+        rc = (*pCfg->pfn)(pszFilename, &szNormFile[0], pszTS, fHeader, &pvRule);
+        if (!rc && pvRule)
+        {
+            if (!fHeader && pCfg->pszzAddDeps)
+                depAddSrcAddDeps(pvRule, pCfg->pszzAddDeps);
+        }
+    }
+    else
+    {
+        if (*fileName(pszFilename, szExt) != '.') /* these are 'hidden' files, like .cvsignore, let's ignore them. */
+            fprintf(stderr, "warning: '%s' has an unknown file type.\n", pszFilename);
+        rc = 0;
+    }
+
+
+    return rc;
+}
+
+
+/**
+ * Generates depend info on this C or C++ file, these are stored internally
+ * and written to file later.
+ * @returns 0 on success.
+ *          !0 on error.
+ * @param   pszFilename         Pointer to source filename. Correct case is assumed!
+ * @param   pszNormFilename     Pointer to normalized source filename.
+ * @param   pszTS               File time stamp.
+ * @parma   fHeader             True if header file is being scanned.
+ * @param   ppvRule             Variabel to return any new rule handle.
+ * @status  completely implemented.
+ * @author  knut st. osmundsen
+ */
+int langC_CPP(const char *pszFilename, const char *pszNormFilename,
+              const char *pszTS, BOOL fHeader, void **ppvRule)
+{
+    void *  pvFile;                     /* Text buffer pointer. */
+    void *  pvRule;                     /* Handle to the current rule. */
+    char    szBuffer[4096];             /* Max line length is 4096... should not be a problem. */
+    int     iLine;                      /* Linenumber. */
+    void *  pv = NULL;                  /* An index used by textbufferGetNextLine. */
+    BOOL    fComment;                   /* TRUE when within a multiline comment. */
+                                        /* FALSE when not within a multiline comment. */
+    int     iIfStack;                   /* StackPointer. */
+    struct  IfStackEntry
+    {
+        int fIncluded : 1;              /* TRUE:  include this code;
+                                         * FALSE: excluded */
+        int fIf : 1;                    /* TRUE:  #if part of the expression.
+                                         * FALSE: #else part of the expression. */
+        int fSupported : 1;             /* TRUE:  supported if/else statement
+                                         * FALSE: unsupported all else[<something>] are ignored
+                                         *        All code is included.
+                                         */
+    } achIfStack[256];
+    char    szSrcDir[CCHMAXPATH];
+    filePath(pszNormFilename, szSrcDir);/* determin source code directory. */
+
+    /**********************************/
+    /* Add the depend rule            */
+    /**********************************/
+    if (options.fObjRule && !fHeader)
+    {
+        if (options.fNoObjectPath)
+            pvRule = depAddRule(fileNameNoExt(pszFilename, szBuffer), NULL, options.pszObjectExt, pszTS, FALSE);
+        else
+            pvRule = depAddRule(options.fObjectDir ?
+                                    options.pszObjectDir :
+                                    filePathSlash(pszFilename, szBuffer),
+                                fileNameNoExt(pszFilename, szBuffer + CCHMAXPATH),
+                                options.pszObjectExt, pszTS, FALSE);
+
+        if (options.fSrcWhenObj && pvRule)
+            depAddDepend(pvRule,
+                         options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename,
+                         options.fCheckCyclic,
+                         FALSE);
+    }
+    else
+        pvRule = depAddRule(options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename, NULL, NULL, pszTS, FALSE);
+
+    /* duplicate rule? */
+    *ppvRule = pvRule;
+    if (pvRule == NULL)
+        return 0;
+
+
+    /********************/
+    /* Make file buffer */
+    /********************/
+    pvFile = textbufferCreate(pszFilename);
+    if (!pvFile)
+    {
+        fprintf(stderr, "failed to open '%s'\n", pszFilename);
+        return -1;
+    }
+
+
+    /*******************/
+    /* find dependants */
+    /*******************/
+    /* Initiate the IF-stack, comment state and line number. */
+    iIfStack = 0;
+    achIfStack[iIfStack].fIf = TRUE;
+    achIfStack[iIfStack].fIncluded = TRUE;
+    achIfStack[iIfStack].fSupported = TRUE;
+    fComment = FALSE;
+    iLine = 0;
+    while (textbufferGetNextLine(pvFile, &pv, szBuffer, sizeof(szBuffer)) != NULL) /* line loop */
+    {
+        /* search for #include */
+        register char *pszC;
+        int cbLen;
+        int i = 0;
+        iLine++;
+
+        /* skip blank chars */
+        cbLen = strlen(szBuffer);
+        while (i + 2 < cbLen && (szBuffer[i] == ' ' || szBuffer[i] == '\t'))
+            i++;
+
+        /* preprocessor statement? */
+        if (!fComment && szBuffer[i] == '#')
+        {
+            /*
+             * Preprocessor checks
+             * We known that we have a preprocessor statment (starting with an '#' * at szBuffer[i]).
+             * Depending on the word afterwards we'll take some different actions.
+             * So we'll start of by extracting that word and make a string swich on it.
+             * Note that there might be some blanks between the hash and the word.
+             */
+            int     cchWord;
+            char *  pszEndWord;
+            char *  pszArgument;
+            i++;                /* skip hash ('#') */
+            while (szBuffer[i] == '\t' || szBuffer[i] == ' ') /* skip blanks */
+                i++;
+            pszArgument = pszEndWord = findEndOfWord(&szBuffer[i]);
+            cchWord = pszEndWord - &szBuffer[i];
+
+            /*
+             * Find the argument by skipping the blanks.
+             */
+            while (*pszArgument == '\t' || *pszArgument == ' ') /* skip blanks */
+                pszArgument++;
+
+            /*
+             * string switch.
+             */
+            if (strncmp(&szBuffer[i], "include", cchWord) == 0)
+            {
+                /*
+                 * #include
+                 *
+                 * Are we in a state where this file is to be included?
+                 */
+                if (achIfStack[iIfStack].fIncluded)
+                {
+                    char    szFullname[CCHMAXPATH];
+                    char *  psz;
+                    BOOL    f = FALSE;
+                    int     j;
+                    BOOL    fQuote;
+
+                    /* extract info between "" or <> */
+                    while (i < cbLen && !(f = (szBuffer[i] == '"' || szBuffer[i] == '<')))
+                        i++;
+                    fQuote = szBuffer[i] == '"';
+                    i++; /* skip '"' or '<' */
+
+                    /* if invalid statement then continue with the next line! */
+                    if (!f) continue;
+
+                    /* find end */
+                    j = f = 0;
+                    while (i + j < cbLen &&  j < CCHMAXPATH &&
+                           !(f = (szBuffer[i+j] == '"' || szBuffer[i+j] == '>')))
+                        j++;
+
+                    /* if invalid statement then continue with the next line! */
+                    if (!f) continue;
+
+                    /* copy filename */
+                    strncpy(szFullname, &szBuffer[i], j);
+                    szFullname[j] = '\0'; /* ensure terminatition. */
+                    strlwr(szFullname);
+
+                    /* find include file! */
+                    psz = fQuote ? pathlistFindFile(szSrcDir, szFullname, szBuffer) : NULL;
+                    if (psz == NULL)
+                        psz = pathlistFindFile(options.pszInclude, szFullname, szBuffer);
+                    if (psz == NULL)
+                        psz = pathlistFindFile(pszIncludeEnv, szFullname, szBuffer);
+
+                    /* did we find the include? */
+                    if (psz != NULL)
+                    {
+                        if (options.fExcludeAll || pathlistFindFile2(options.pszExclude, szBuffer))
+                        {   /* #include <sys/stats.h> makes trouble, check for '/' and '\'. */
+                            if (!strchr(szFullname, '/') && !strchr(szFullname, '\\'))
+                                depAddDepend(pvRule, szFullname, options.fCheckCyclic, FALSE);
+                            else
+                                fprintf(stderr, "%s(%d): warning include '%s' is ignored.\n",
+                                        pszFilename, iLine, szFullname);
+                        }
+                        else
+                            depAddDepend(pvRule, szBuffer, options.fCheckCyclic, FALSE);
+                    }
+                    else
+                    {
+                        fprintf(stderr, "%s(%d): warning include file '%s' not found!\n",
+                                pszFilename, iLine, szFullname);
+                        depMarkNotFound(pvRule);
+                    }
+                }
+            }
+            else
+                /*
+                 * #if
+                 */
+                if (strncmp(&szBuffer[i], "if", cchWord) == 0)
+            {   /* #if 0 and #if <1-9> are supported */
+                pszEndWord = findEndOfWord(pszArgument);
+                iIfStack++;
+                if ((pszEndWord - pszArgument) == 1
+                    && *pszArgument >= '0' && *pszArgument <= '9')
+                {
+                    if (*pszArgument != '0')
+                        achIfStack[iIfStack].fIncluded =  TRUE;
+                    else
+                        achIfStack[iIfStack].fIncluded =  FALSE;
+                }
+                else
+                    achIfStack[iIfStack].fSupported = FALSE;
+                achIfStack[iIfStack].fIncluded = TRUE;
+                achIfStack[iIfStack].fIf = TRUE;
+            }
+            else
+                /*
+                 * #else
+                 */
+                if (strncmp(&szBuffer[i], "else", cchWord) == 0)
+            {
+                if (achIfStack[iIfStack].fSupported)
+                {
+                    if (achIfStack[iIfStack].fIncluded) /* ARG!! this'll prevent warning */
+                        achIfStack[iIfStack].fIncluded = FALSE;
+                    else
+                        achIfStack[iIfStack].fIncluded = TRUE;
+                }
+                achIfStack[iIfStack].fIf = FALSE;
+            }
+            else
+                /*
+                 * #endif
+                 */
+                if (strncmp(&szBuffer[i], "endif", cchWord) == 0)
+            {   /* Pop the if-stack. */
+                if (iIfStack > 0)
+                    iIfStack--;
+                else
+                    fprintf(stderr, "%s(%d): If-Stack underflow!\n", pszFilename, iLine);
+            }
+            /*
+             * general if<something> and elseif<something> implementations
+             */
+            else
+                if (strncmp(&szBuffer[i], "elseif", 6) == 0)
+            {
+                achIfStack[iIfStack].fSupported = FALSE;
+                achIfStack[iIfStack].fIncluded = TRUE;
+            }
+            else
+                if (strncmp(&szBuffer[i], "if", 2) == 0)
+            {
+                iIfStack++;
+                achIfStack[iIfStack].fIf = TRUE;
+                achIfStack[iIfStack].fSupported = FALSE;
+                achIfStack[iIfStack].fIncluded = TRUE;
+            }
+            /* The rest of them aren't implemented yet.
+            else if (strncmp(&szBuffer[i], "if") == 0)
+            {
+            }
+            */
+        }
+
+        /*
+         * Comment checks.
+         *  -Start at first non-blank.
+         *  -Loop thru the line since we might have more than one
+         *   comment statement on a single line.
+         */
+        pszC = &szBuffer[i];
+        while (pszC != NULL && *pszC != '\0')
+        {
+            if (fComment)
+                pszC = strstr(pszC, "*/");  /* look for end comment mark. */
+            else
+            {
+                char *pszLC;
+                pszLC= strstr(pszC, "//");  /* look for single line comment mark. */
+                pszC = strstr(pszC, "/*");  /* look for start comment mark */
+                if (pszLC && pszLC < pszC)  /* if there is an single line comment mark before the */
+                    break;                  /* muliline comment mark we'll ignore the multiline mark. */
+            }
+
+            /* Comment mark found? */
+            if (pszC != NULL)
+            {
+                fComment = !fComment;
+                pszC += 2;          /* skip comment mark */
+
+                /* debug */
+                /*
+                if (fComment)
+                    fprintf(stderr, "starts at line %d\n", iLine);
+                else
+                    fprintf(stderr, "ends   at line %d\n", iLine);
+                    */
+            }
+        }
+    } /*while*/
+
+    textbufferDestroy(pvFile);
+
+    return 0;
+}
+
+
+/**
+ * Generates depend info on this file, these are stored internally
+ * and written to file later.
+ * @returns 0 on success.
+ *          !0 on error.
+ * @param   pszFilename         Pointer to source filename. Correct case is assumed!
+ * @param   pszNormFilename     Pointer to normalized source filename.
+ * @param   pszTS               File time stamp.
+ * @parma   fHeader             True if header file is being scanned.
+ * @param   ppvRule             Variabel to return any new rule handle.
+ * @status  completely implemented.
+ * @author  knut st. osmundsen
+ */
+int langAsm(const char *pszFilename, const char *pszNormFilename,
+            const char *pszTS, BOOL fHeader, void **ppvRule)
+{
+    void *  pvFile;                     /* Text buffer pointer. */
+    void *  pvRule;                     /* Handle to the current rule. */
+    char    szBuffer[4096];             /* Temporary buffer (max line lenght size...) */
+    int     iLine;                      /* current line number */
+    void *  pv = NULL;                  /* An index used by textbufferGetNextLine. */
+
+
+    /**********************************/
+    /* Add the depend rule            */
+    /**********************************/
+    if (options.fObjRule && !fHeader)
+    {
+        if (options.fNoObjectPath)
+            pvRule = depAddRule(fileNameNoExt(pszFilename, szBuffer), NULL, options.pszObjectExt, pszTS, FALSE);
+        else
+            pvRule = depAddRule(options.fObjectDir ?
+                                    options.pszObjectDir :
+                                    filePathSlash(pszFilename, szBuffer),
+                                fileNameNoExt(pszFilename, szBuffer + CCHMAXPATH),
+                                options.pszObjectExt, pszTS, FALSE);
+
+        if (options.fSrcWhenObj && pvRule)
+            depAddDepend(pvRule,
+                         options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename,
+                         options.fCheckCyclic, FALSE);
+    }
+    else
+        pvRule = depAddRule(options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename, NULL, NULL, pszTS, FALSE);
+
+    /* duplicate rule? */
+    *ppvRule = pvRule;
+    if (pvRule == NULL)
+        return 0;
+
+
+    /********************/
+    /* Make file buffer */
+    /********************/
+    pvFile = textbufferCreate(pszFilename);
+    if (!pvFile)
+    {
+        fprintf(stderr, "failed to open '%s'\n", pszFilename);
+        return -1;
+    }
+
+
+    /*******************/
+    /* find dependants */
+    /*******************/
+    iLine = 0;
+    while (textbufferGetNextLine(pvFile, &pv, szBuffer, sizeof(szBuffer)) != NULL) /* line loop */
+    {
+        /* search for include */
+        int cbLen;
+        int i = 0;
+        iLine++;
+
+        /* skip blank chars */
+        cbLen = strlen(szBuffer);
+        while (i + 9 < cbLen && (szBuffer[i] == ' ' || szBuffer[i] == '\t'))
+            i++;
+
+        /* is this an include? */
+        if (strnicmp(&szBuffer[i], "include", 7) == 0
+            && (szBuffer[i + 7] == '\t' || szBuffer[i + 7] == ' ')
+            )
+        {
+            char szFullname[CCHMAXPATH];
+            char *psz;
+            int  j;
+
+            /* skip to first no blank char  */
+            i += 7;
+            while (i < cbLen && (szBuffer[i] == ' ' || szBuffer[i] == '\t'))
+                i++;
+
+            /* comment check - if comment found, no filename was given. continue. */
+            if (szBuffer[i] == ';') continue;
+
+            /* find end */
+            j = 0;
+            while (i + j < cbLen
+                   &&  j < CCHMAXPATH
+                   && szBuffer[i+j] != ' '  && szBuffer[i+j] != '\t' && szBuffer[i+j] != '\n'
+                   && szBuffer[i+j] != '\0' && szBuffer[i+j] != ';'  && szBuffer[i+j] != '\r'
+                   )
+                j++;
+
+            /* copy filename */
+            strncpy(szFullname, &szBuffer[i], j);
+            szFullname[j] = '\0'; /* ensure terminatition. */
+            strlwr(szFullname);
+
+            /* find include file! */
+            psz = pathlistFindFile(options.pszInclude, szFullname, szBuffer);
+            if (psz == NULL)
+                psz = pathlistFindFile(pszIncludeEnv, szFullname, szBuffer);
+
+            /* Did we find the include? */
+            if (psz != NULL)
+            {
+                if (options.fExcludeAll || pathlistFindFile2(options.pszExclude, szBuffer))
+                {   /* include sys/stats.inc makes trouble, check for '/' and '\'. */
+                    if (!strchr(szFullname, '/') && !strchr(szFullname, '\\'))
+                        depAddDepend(pvRule, szFullname, options.fCheckCyclic, FALSE);
+                    else
+                        fprintf(stderr, "%s(%d): warning include '%s' is ignored.\n",
+                                pszFilename, iLine, szFullname);
+                }
+                else
+                    depAddDepend(pvRule, szBuffer, options.fCheckCyclic, FALSE);
+            }
+            else
+            {
+                fprintf(stderr, "%s(%d): warning include file '%s' not found!\n",
+                        pszFilename, iLine, szFullname);
+                depMarkNotFound(pvRule);
+            }
+        }
+    } /*while*/
+
+    textbufferDestroy(pvFile);
+
+    return 0;
+}
+
+
+/**
+ * Generates depend info on this Resource file, these are stored internally
+ * and written to file later.
+ * @returns 0 on success.
+ *          !0 on error.
+ * @param   pszFilename         Pointer to source filename. Correct case is assumed!
+ * @param   pszNormFilename     Pointer to normalized source filename.
+ * @param   pszTS               File time stamp.
+ * @parma   fHeader             True if header file is being scanned.
+ * @status  completely implemented.
+ * @author  knut st. osmundsen
+ */
+#if 0
+int langRC(const char *pszFilename, const char *pszNormFilename, void *pvFile, BOOL fHeader)
+{
+    void *  pvFile;                     /* Text buffer pointer. */
+    void *  pvRule;                     /* Handle to the current rule. */
+    char    szBuffer[4096];             /* Temporary buffer (max line lenght size...) */
+    int     iLine;                      /* current line number */
+    void *  pv = NULL;                  /* An index used by textbufferGetNextLine. */
+
+
+    /**********************************/
+    /* Add the depend rule            */
+    /**********************************/
+    if (options.fObjRule && !fHeader)
+    {
+        if (options.fNoObjectPath)
+            pvRule = depAddRule(fileNameNoExt(pszFilename, szBuffer), NULL, options.pszRsrcExt, pszTS, FALSE);
+        else
+            pvRule = depAddRule(options.fObjectDir ?
+                                    options.pszObjectDir :
+                                    filePathSlash(pszFilename, szBuffer),
+                                fileNameNoExt(pszFilename, szBuffer + CCHMAXPATH),
+                                options.pszRsrcExt, pszTS, FALSE);
+
+        if (options.fSrcWhenObj && pvRule)
+            depAddDepend(pvRule,
+                         options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : fileNormalize2(pszFilename, szBuffer),
+                         options.fCheckCyclic,
+                         FALSE);
+    }
+    else
+        pvRule = depAddRule(options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename, NULL, NULL, pszTS, FALSE);
+
+    /* duplicate rule? */
+    *ppvRule = pvRule;
+    if (pvRule == NULL)
+        return 0;
+
+
+    /********************/
+    /* Make file buffer */
+    /********************/
+    pvFile = textbufferCreate(pszFilename);
+    if (!pvFile)
+    {
+        fprintf(stderr, "failed to open '%s'\n", pszFilename);
+        return -1;
+    }
+
+
+    /*******************/
+    /* find dependants */
+    /*******************/
+    iLine = 0;
+    while (textbufferGetNextLine(pvFile, &pv, szBuffer, sizeof(szBuffer)) != NULL) /* line loop */
+    {
+        /* search for #include */
+        int cbLen;
+        int i = 0;
+        int i1;
+        iLine++;
+
+        /* skip blank chars */
+        cbLen = strlen(szBuffer);
+        while (i + 9 < cbLen && (szBuffer[i] == ' ' || szBuffer[i] == '\t'))
+            i++;
+
+        /* is this an include? */
+        i1 = 1;
+        if (   strncmp(&szBuffer[i], "#include", 8) == 0
+            || (i1 = strnicmp(&szBuffer[i], "RCINCLUDE", 9)) == 0
+            || strnicmp(&szBuffer[i], "DLGINCLUDE", 10) == 0
+            )
+        {
+            char szFullname[CCHMAXPATH];
+            char *psz;
+            BOOL f = FALSE;
+            int  j;
+
+            if (i1 != 0)
+            {   /*
+                 * #include <file.h>,  #include "file.h" or DLGINCLUDE 1 "file.h"
+                 *
+                 * extract info between "" or <>
+                 */
+                while (i < cbLen && !(f = (szBuffer[i] == '"' || szBuffer[i] == '<')))
+                    i++;
+                i++; /* skip '"' or '<' */
+
+                /* if invalid statement then continue with the next line! */
+                if (!f) continue;
+
+                /* find end */
+                j = f = 0;
+                while (i + j < cbLen &&  j < CCHMAXPATH &&
+                       !(f = (szBuffer[i+j] == '"' || szBuffer[i+j] == '>')))
+                    j++;
+
+                /* if invalid statement then continue with the next line! */
+                if (!f) continue;
+            }
+            else
+            {   /*
+                 * RCINCLUDE ["]filename.dlg["]
+                 * Extract filename.
+                 */
+
+                /* skip to filename.dlg start - if eol will continue to loop. */
+                i += 9;
+                while (szBuffer[i] == ' ' || szBuffer[i] == '\t' || szBuffer[i] == '"')
+                    i++;
+                if (szBuffer[i] == '\0')
+                    continue;
+
+                /* search to end of filename. */
+                j = i+1;
+                while (   szBuffer[i+j] != ' ' && szBuffer[i+j] != '\t'
+                       && szBuffer[i+j] != '"' && szBuffer[i+j] != '\0')
+                    j++;
+            }
+
+            /* copy filename */
+            strncpy(szFullname, &szBuffer[i], j);
+            szFullname[j] = '\0'; /* ensure terminatition. */
+            strlwr(szFullname);
+
+            /* find include file! */
+            psz = pathlistFindFile(options.pszInclude, szFullname, szBuffer);
+            if (psz == NULL)
+                psz = pathlistFindFile(pszIncludeEnv, szFullname, szBuffer);
+
+            /* did we find the include? */
+            if (psz != NULL)
+            {
+                if (options.fExcludeAll || pathlistFindFile2(options.pszExclude, szBuffer))
+                {   /* #include <sys/stats.h> makes trouble, check for '/' and '\'. */
+                    if (!strchr(szFullname, '/') && !strchr(szFullname, '\\'))
+                        depAddDepend(pvRule, szFullname, options.fCheckCyclic, FALSE);
+                    else
+                        fprintf(stderr, "%s(%d): warning include '%s' is ignored.\n",
+                                pszFilename, iLine, szFullname);
+                }
+                else
+                    depAddDepend(pvRule, szBuffer, options.fCheckCyclic, FALSE);
+            }
+            else
+            {
+                fprintf(stderr, "%s(%d): warning include file '%s' not found!\n",
+                        pszFilename, iLine, szFullname);
+                depMarkNotFound(pvRule);
+            }
+        }
+    } /*while*/
+
+    textbufferDestroy(pvFile);
+    return 0;
+}
+#else
+int langRC(const char *pszFilename, const char *pszNormFilename,
+           const char *pszTS, BOOL fHeader, void **ppvRule)
+{
+    void *  pvFile;                     /* Text buffer pointer. */
+    void *  pvRule;                     /* Handle to the current rule. */
+    char    szBuffer[4096];             /* Max line length is 4096... should not be a problem. */
+    int     iLine;                      /* Linenumber. */
+    void *  pv = NULL;                  /* An index used by textbufferGetNextLine. */
+    BOOL    fComment;                   /* TRUE when within a multiline comment. */
+                                        /* FALSE when not within a multiline comment. */
+    int     iIfStack;                   /* StackPointer. */
+    struct  IfStackEntry
+    {
+        int fIncluded : 1;              /* TRUE:  include this code;
+                                         * FALSE: excluded */
+        int fIf : 1;                    /* TRUE:  #if part of the expression.
+                                         * FALSE: #else part of the expression. */
+        int fSupported : 1;             /* TRUE:  supported if/else statement
+                                         * FALSE: unsupported all else[<something>] are ignored
+                                         *        All code is included.
+                                         */
+    } achIfStack[256];
+
+
+    /**********************************/
+    /* Add the depend rule            */
+    /**********************************/
+    if (options.fObjRule && !fHeader)
+    {
+        if (options.fNoObjectPath)
+            pvRule = depAddRule(fileNameNoExt(pszFilename, szBuffer), NULL, options.pszRsrcExt, pszTS, FALSE);
+        else
+            pvRule = depAddRule(options.fObjectDir ?
+                                    options.pszObjectDir :
+                                    filePathSlash(pszFilename, szBuffer),
+                                fileNameNoExt(pszFilename, szBuffer + CCHMAXPATH),
+                                options.pszRsrcExt, pszTS, FALSE);
+
+        if (options.fSrcWhenObj && pvRule)
+            depAddDepend(pvRule,
+                         options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename,
+                         options.fCheckCyclic,
+                         FALSE);
+    }
+    else
+        pvRule = depAddRule(options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename, NULL, NULL, pszTS, FALSE);
+
+    /* duplicate rule? */
+    *ppvRule = pvRule;
+    if (pvRule == NULL)
+        return 0;
+
+
+    /********************/
+    /* Make file buffer */
+    /********************/
+    pvFile = textbufferCreate(pszFilename);
+    if (!pvFile)
+    {
+        fprintf(stderr, "failed to open '%s'\n", pszFilename);
+        return -1;
+    }
+
+
+    /*******************/
+    /* find dependants */
+    /*******************/
+    /* Initiate the IF-stack, comment state and line number. */
+    iIfStack = 0;
+    achIfStack[iIfStack].fIf = TRUE;
+    achIfStack[iIfStack].fIncluded = TRUE;
+    achIfStack[iIfStack].fSupported = TRUE;
+    fComment = FALSE;
+    iLine = 0;
+    while (textbufferGetNextLine(pvFile, &pv, szBuffer, sizeof(szBuffer)) != NULL) /* line loop */
+    {
+        register char * pszC;
+        char            szFullname[CCHMAXPATH];
+        int             cbLen;
+        int             i1 = 1;
+        int             i = 0;
+        iLine++;
+
+        /* skip blank chars */
+        cbLen = strlen(szBuffer);
+        while (i + 2 < cbLen && (szBuffer[i] == ' ' || szBuffer[i] == '\t'))
+            i++;
+
+        /* preprocessor statement? */
+        if (!fComment && szBuffer[i] == '#')
+        {
+            /*
+             * Preprocessor checks
+             * We known that we have a preprocessor statment (starting with an '#' * at szBuffer[i]).
+             * Depending on the word afterwards we'll take some different actions.
+             * So we'll start of by extracting that word and make a string swich on it.
+             * Note that there might be some blanks between the hash and the word.
+             */
+            int     cchWord;
+            char *  pszEndWord;
+            char *  pszArgument;
+            i++;                /* skip hash ('#') */
+            while (szBuffer[i] == '\t' || szBuffer[i] == ' ') /* skip blanks */
+                i++;
+            pszArgument = pszEndWord = findEndOfWord(&szBuffer[i]);
+            cchWord = pszEndWord - &szBuffer[i];
+
+            /*
+             * Find the argument by skipping the blanks.
+             */
+            while (*pszArgument == '\t' || *pszArgument == ' ') /* skip blanks */
+                pszArgument++;
+
+            /*
+             * string switch.
+             */
+            if (strncmp(&szBuffer[i], "include", cchWord) == 0)
+            {
+                /*
+                 * #include
+                 *
+                 * Are we in a state where this file is to be included?
+                 */
+                if (achIfStack[iIfStack].fIncluded)
+                {
+                    char *psz;
+                    BOOL f = FALSE;
+                    int  j;
+
+                    /* extract info between "" or <> */
+                    while (i < cbLen && !(f = (szBuffer[i] == '"' || szBuffer[i] == '<')))
+                        i++;
+                    i++; /* skip '"' or '<' */
+
+                    /* if invalid statement then continue with the next line! */
+                    if (!f) continue;
+
+                    /* find end */
+                    j = f = 0;
+                    while (i + j < cbLen &&  j < CCHMAXPATH &&
+                           !(f = (szBuffer[i+j] == '"' || szBuffer[i+j] == '>')))
+                        j++;
+
+                    /* if invalid statement then continue with the next line! */
+                    if (!f) continue;
+
+                    /* copy filename */
+                    strncpy(szFullname, &szBuffer[i], j);
+                    szFullname[j] = '\0'; /* ensure terminatition. */
+                    strlwr(szFullname);
+
+                    /* find include file! */
+                    psz = pathlistFindFile(options.pszInclude, szFullname, szBuffer);
+                    if (psz == NULL)
+                        psz = pathlistFindFile(pszIncludeEnv, szFullname, szBuffer);
+
+                    /* did we find the include? */
+                    if (psz != NULL)
+                    {
+                        if (options.fExcludeAll || pathlistFindFile2(options.pszExclude, szBuffer))
+                        {   /* #include <sys/stats.h> makes trouble, check for '/' and '\'. */
+                            if (!strchr(szFullname, '/') && !strchr(szFullname, '\\'))
+                                depAddDepend(pvRule, szFullname, options.fCheckCyclic, FALSE);
+                            else
+                                fprintf(stderr, "%s(%d): warning include '%s' is ignored.\n",
+                                        pszFilename, iLine, szFullname);
+                        }
+                        else
+                            depAddDepend(pvRule, szBuffer, options.fCheckCyclic, FALSE);
+                    }
+                    else
+                    {
+                        fprintf(stderr, "%s(%d): warning include file '%s' not found!\n",
+                                pszFilename, iLine, szFullname);
+                        depMarkNotFound(pvRule);
+                    }
+                }
+            }
+            else
+                /*
+                 * #if
+                 */
+                if (strncmp(&szBuffer[i], "if", cchWord) == 0)
+            {   /* #if 0 and #if <1-9> are supported */
+                pszEndWord = findEndOfWord(pszArgument);
+                iIfStack++;
+                if ((pszEndWord - pszArgument) == 1
+                    && *pszArgument >= '0' && *pszArgument <= '9')
+                {
+                    if (*pszArgument != '0')
+                        achIfStack[iIfStack].fIncluded =  TRUE;
+                    else
+                        achIfStack[iIfStack].fIncluded =  FALSE;
+                }
+                else
+                    achIfStack[iIfStack].fSupported = FALSE;
+                achIfStack[iIfStack].fIncluded = TRUE;
+                achIfStack[iIfStack].fIf = TRUE;
+            }
+            else
+                /*
+                 * #else
+                 */
+                if (strncmp(&szBuffer[i], "else", cchWord) == 0)
+            {
+                if (achIfStack[iIfStack].fSupported)
+                {
+                    if (achIfStack[iIfStack].fIncluded) /* ARG!! this'll prevent warning */
+                        achIfStack[iIfStack].fIncluded = FALSE;
+                    else
+                        achIfStack[iIfStack].fIncluded = TRUE;
+                }
+                achIfStack[iIfStack].fIf = FALSE;
+            }
+            else
+                /*
+                 * #endif
+                 */
+                if (strncmp(&szBuffer[i], "endif", cchWord) == 0)
+            {   /* Pop the if-stack. */
+                if (iIfStack > 0)
+                    iIfStack--;
+                else
+                    fprintf(stderr, "%s(%d): If-Stack underflow!\n", pszFilename, iLine);
+            }
+            /*
+             * general if<something> and elseif<something> implementations
+             */
+            else
+                if (strncmp(&szBuffer[i], "elseif", 6) == 0)
+            {
+                achIfStack[iIfStack].fSupported = FALSE;
+                achIfStack[iIfStack].fIncluded = TRUE;
+            }
+            else
+                if (strncmp(&szBuffer[i], "if", 2) == 0)
+            {
+                iIfStack++;
+                achIfStack[iIfStack].fIf = TRUE;
+                achIfStack[iIfStack].fSupported = FALSE;
+                achIfStack[iIfStack].fIncluded = TRUE;
+            }
+            /* The rest of them aren't implemented yet.
+            else if (strncmp(&szBuffer[i], "if") == 0)
+            {
+            }
+            */
+        } else
+            /*
+             * Check for resource compiler directives.
+             */
+            if (    !fComment
+                &&  !strchr(&szBuffer[i], ',')
+                &&  (   !strnicmp(&szBuffer[i], "ICON", 4)
+                     || !strnicmp(&szBuffer[i], "FONT", 4)
+                     || !strnicmp(&szBuffer[i], "BITMAP", 6)
+                     || !strnicmp(&szBuffer[i], "POINTER", 7)
+                     || !strnicmp(&szBuffer[i], "RESOURCE", 8)
+                     || !(i1 = strnicmp(&szBuffer[i], "RCINCLUDE", 9))
+                   /*|| !strnicmp(&szBuffer[i], "DLGINCLUDE", 10) - only used by the dlgeditor */
+                     || !strnicmp(&szBuffer[i], "DEFAULTICON", 11)
+                     )
+                )
+        {
+            /*
+             * RESOURCE 123 1 ["]filename.ext["]
+             */
+            char    szLine[1024];
+            char *  pszFile;
+            char    chQuote = ' ';
+
+            PreProcessLine(szLine, &szBuffer[i]);
+
+            pszFile = &szLine[strlen(szLine)-1];
+            if (*pszFile == '\"' || *pszFile == '\'')
+            {
+                chQuote = *pszFile;
+                *pszFile-- = '\0';
+            }
+            while (*pszFile != chQuote)
+                pszFile--;
+            *pszFile++ = '\0'; /* We now have extracted the filename - pszFile. */
+            strlwr(pszFile);
+
+            /* Add filename to the dependencies. */
+            if (i1)
+                depAddDepend(pvRule, pszFile, options.fCheckCyclic, FALSE);
+            else
+            {
+                char *psz;
+                /* find include file! */
+                psz = pathlistFindFile(options.pszInclude, pszFile, szFullname);
+                if (psz == NULL)
+                    psz = pathlistFindFile(pszIncludeEnv, pszFile, szFullname);
+
+                /* did we find the include? */
+                if (psz != NULL)
+                {
+                    if (options.fExcludeAll || pathlistFindFile2(options.pszExclude, szFullname))
+                    {   /* #include <sys/stats.h> makes trouble, check for '/' and '\'. */
+                        if (!strchr(pszFile, '/') && !strchr(pszFile, '\\'))
+                            depAddDepend(pvRule, pszFile, options.fCheckCyclic, FALSE);
+                        else
+                            fprintf(stderr, "%s(%d): warning include '%s' is ignored.\n",
+                                    pszFilename, iLine, pszFile);
+                    }
+                    else
+                        depAddDepend(pvRule, szFullname, options.fCheckCyclic, FALSE);
+                }
+                else
+                {
+                    fprintf(stderr, "%s(%d): warning include file '%s' not found!\n",
+                            pszFilename, iLine, pszFile);
+                    depMarkNotFound(pvRule);
+                }
+            }
+        }
+
+
+        /*
+         * Comment checks.
+         *  -Start at first non-blank.
+         *  -Loop thru the line since we might have more than one
+         *   comment statement on a single line.
+         */
+        pszC = &szBuffer[i];
+        while (pszC != NULL && *pszC != '\0')
+        {
+            if (fComment)
+                pszC = strstr(pszC, "*/");  /* look for end comment mark. */
+            else
+            {
+                char *pszLC;
+                pszLC= strstr(pszC, "//");  /* look for single line comment mark. */
+                pszC = strstr(pszC, "/*");  /* look for start comment mark */
+                if (pszLC && pszLC < pszC)  /* if there is an single line comment mark before the */
+                    break;                  /* muliline comment mark we'll ignore the multiline mark. */
+            }
+
+            /* Comment mark found? */
+            if (pszC != NULL)
+            {
+                fComment = !fComment;
+                pszC += 2;          /* skip comment mark */
+
+                /* debug */
+                /*
+                if (fComment)
+                    fprintf(stderr, "starts at line %d\n", iLine);
+                else
+                    fprintf(stderr, "ends   at line %d\n", iLine);
+                    */
+            }
+        }
+    } /*while*/
+
+    textbufferDestroy(pvFile);
+
+    return 0;
+}
+#endif
+
+
+/**
+ * Generates depend info on this COBOL file, these are stored internally
+ * and written to file later.
+ * @returns 0 on success.
+ *          !0 on error.
+ * @param   pszFilename         Pointer to source filename. Correct case is assumed!
+ * @param   pszNormFilename     Pointer to normalized source filename.
+ * @param   pszTS               File time stamp.
+ * @parma   fHeader             True if header file is being scanned.
+ * @param   ppvRule             Variabel to return any new rule handle.
+ * @status  completely implemented.
+ * @author  knut st. osmundsen
+ */
+int langCOBOL(const char *pszFilename, const char *pszNormFilename,
+              const char *pszTS, BOOL fHeader, void **ppvRule)
+{
+    void *  pvFile;                     /* Text buffer pointer. */
+    void *  pvRule;                     /* Handle to the current rule. */
+    char    szBuffer[4096];             /* Temporary buffer (max line lenght size...) */
+    int     iLine;                      /* current line number */
+    void *  pv = NULL;                  /* An index used by textbufferGetNextLine. */
+
+
+    /**********************************/
+    /* Add the depend rule            */
+    /**********************************/
+    if (options.fObjRule && !fHeader)
+    {
+        if (options.fNoObjectPath)
+            pvRule = depAddRule(fileNameNoExt(pszFilename, szBuffer), NULL, options.pszObjectExt, pszTS, FALSE);
+        else
+            pvRule = depAddRule(options.fObjectDir ?
+                                    options.pszObjectDir :
+                                    filePathSlash(pszFilename, szBuffer),
+                                fileNameNoExt(pszFilename, szBuffer + CCHMAXPATH),
+                                options.pszObjectExt, pszTS, FALSE);
+
+        if (options.fSrcWhenObj && pvRule)
+            depAddDepend(pvRule,
+                         options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename)
+                            ? fileName(pszFilename, szBuffer) : fileNormalize2(pszFilename, szBuffer),
+                         options.fCheckCyclic,
+                         FALSE);
+    }
+    else
+        pvRule = depAddRule(options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename, NULL, NULL, pszTS, FALSE);
+
+    /* duplicate rule? */
+    *ppvRule = pvRule;
+    if (pvRule == NULL)
+        return 0;
+
+
+    /********************/
+    /* Make file buffer */
+    /********************/
+    pvFile = textbufferCreate(pszFilename);
+    if (!pvFile)
+    {
+        fprintf(stderr, "failed to open '%s'\n", pszFilename);
+        return -1;
+    }
+
+
+    /*******************/
+    /* find dependants */
+    /*******************/
+    iLine = 0;
+    while (textbufferGetNextLine(pvFile, &pv, szBuffer, sizeof(szBuffer)) != NULL) /* line loop */
+    {
+        /* search for #include */
+        int cbLen;
+        int i = 0;
+        int i1, i2;
+        iLine++;
+
+        /* check for comment mark (column 7) */
+        if (szBuffer[6] == '*')
+            continue;
+
+        /* skip blank chars */
+        cbLen = strlen(szBuffer);
+        while (i + 9 < cbLen && (szBuffer[i] == ' ' || szBuffer[i] == '\t'))
+            i++;
+
+        /* is this an include? */
+        if (   (i1 = strnicmp(&szBuffer[i], "COPY", 4)) == 0
+            || (i2 = strnicmpwords(&szBuffer[i], "EXEC SQL INCLUDE", 16)) == 0
+            )
+        {
+            char szFullname[CCHMAXPATH];
+            char *psz;
+            int  j;
+
+            /* skip statement */
+            i += 4;
+            if (i1 != 0)
+            {
+                int y = 2; /* skip two words */
+                do
+                {
+                    /* skip blanks */
+                    while (szBuffer[i] == ' ' || szBuffer[i] == '\t')
+                        i++;
+                    /* skip word */
+                    while (szBuffer[i] != ' ' && szBuffer[i] != '\t'
+                           && szBuffer[i] != '\0' && szBuffer[i] != '\n')
+                        i++;
+                    y--;
+                } while (y > 0);
+            }
+
+            /* check for blank */
+            if (szBuffer[i] != ' ' && szBuffer[i] != '\t') /* no copybook specified... */
+                continue;
+
+            /* skip blanks */
+            while (szBuffer[i] == ' ' || szBuffer[i] == '\t')
+                i++;
+
+            /* if invalid statement then continue with the next line! */
+            if (szBuffer[i] == '\0' || szBuffer[i] == '\n')
+                continue;
+
+            /* find end */
+            j = 0;
+            while (i + j < cbLen && j < CCHMAXPATH
+                   && szBuffer[i+j] != '.'
+                   && szBuffer[i+j] != ' '  && szBuffer[i+j] != '\t'
+                   && szBuffer[i+j] != '\0' && szBuffer[i+j] != '\n'
+                   )
+                j++;
+
+            /* if invalid statement then continue with the next line! */
+            if (szBuffer[i+j] != '.' && szBuffer[i+j] != ' ' && szBuffer[i] != '\t')
+                continue;
+
+            /* copy filename */
+            strncpy(szFullname, &szBuffer[i], j);
+            szFullname[j] = '\0'; /* ensure terminatition. */
+            strlwr(szFullname);
+
+            /* add extention .cpy - hardcoded for the moment. */
+            strcpy(&szFullname[j], ".cbl");
+
+            /* find include file! */
+            psz = pathlistFindFile(options.pszInclude, szFullname, szBuffer);
+            if (!psz)
+            {
+                strcpy(&szFullname[j], ".cpy");
+                psz = pathlistFindFile(options.pszInclude, szFullname, szBuffer);
+            }
+
+            /* did we find the include? */
+            if (psz != NULL)
+            {
+                if (options.fExcludeAll || pathlistFindFile2(options.pszExclude, szBuffer))
+                    depAddDepend(pvRule, szFullname, options.fCheckCyclic, FALSE);
+                else
+                    depAddDepend(pvRule, szBuffer, options.fCheckCyclic, FALSE);
+            }
+            else
+            {
+                szFullname[j] = '\0';
+                fprintf(stderr, "%s(%d): warning copybook '%s' was not found!\n",
+                        pszFilename, iLine, szFullname);
+                depMarkNotFound(pvRule);
+            }
+        }
+    } /*while*/
+
+    textbufferDestroy(pvFile);
+
+    return 0;
+}
+
+
+/**
+ * Generates depend info on this IPF file, these are stored internally
+ * and written to file later.
+ * @returns 0 on success.
+ *          !0 on error.
+ * @param   pszFilename         Pointer to source filename. Correct case is assumed!
+ * @param   pszNormFilename     Pointer to normalized source filename.
+ * @param   pszTS               File time stamp.
+ * @param   fHeader             True if header file is being scanned.
+ * @param   ppvRule             Variabel to return any new rule handle.
+ * @status  completely implemented.
+ * @author  knut st. osmundsen
+ */
+int langIPF(  const char *pszFilename, const char *pszNormFilename,
+              const char *pszTS, BOOL fHeader, void **ppvRule)
+{
+    void *  pvFile;                     /* Text buffer pointer. */
+    void *  pvRule;                     /* Handle to the current rule. */
+    char    szBuffer[4096];             /* Temporary buffer (max line lenght size...) */
+    int     iLine;                      /* current line number */
+    void *  pv = NULL;                  /* An index used by textbufferGetNextLine. */
+
+
+    /**********************************/
+    /* Add the depend rule            */
+    /**********************************/
+    /*if (options.fObjRule && !fHeader)
+    {
+        if (options.fNoObjectPath)
+            pvRule = depAddRule(fileNameNoExt(pszFilename, szBuffer), NULL, options.pszObjectExt, pszTS, FALSE);
+        else
+            pvRule = depAddRule(options.fObjectDir ?
+                                    options.pszObjectDir :
+                                    filePathSlash(pszFilename, szBuffer),
+                                fileNameNoExt(pszFilename, szBuffer + CCHMAXPATH),
+                                options.pszObjectExt, pszTS, FALSE);
+
+        if (options.fSrcWhenObj && pvRule)
+            depAddDepend(pvRule,
+                         options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename)
+                            ? fileName(pszFilename, szBuffer) : fileNormalize2(pszFilename, szBuffer),
+                         options.fCheckCyclic,
+                         FALSE);
+    }
+    else */
+        pvRule = depAddRule(options.fExcludeAll || pathlistFindFile2(options.pszExclude, pszNormFilename) ?
+                            fileName(pszFilename, szBuffer) : pszNormFilename, NULL, NULL, pszTS, FALSE);
+
+    /* duplicate rule? */
+    *ppvRule = pvRule;
+    if (pvRule == NULL)
+        return 0;
+
+
+    /********************/
+    /* Make file buffer */
+    /********************/
+    pvFile = textbufferCreate(pszFilename);
+    if (!pvFile)
+    {
+        fprintf(stderr, "failed to open '%s'\n", pszFilename);
+        return -1;
+    }
+
+
+    /*******************/
+    /* find dependants */
+    /*******************/
+    iLine = 0;
+    while (textbufferGetNextLine(pvFile, &pv, szBuffer, sizeof(szBuffer)) != NULL) /* line loop */
+    {
+        iLine++;
+
+        /* is this an imbed statement? */
+        if (!strncmp(&szBuffer[0], ".im", 3))
+        {
+            char    szFullname[CCHMAXPATH];
+            char *  psz;
+            int     i;
+            int     j;
+            char    chQuote = 0;
+
+            /* skip statement and blanks */
+            i = 4;
+            while (szBuffer[i] == ' ' || szBuffer[i] == '\t')
+                i++;
+
+            /* check for quotes */
+            if (szBuffer[i] == '\'' || szBuffer[i] == '\"')
+                chQuote = szBuffer[i++];
+
+            /* find end */
+            j = 0;
+            if (chQuote != 0)
+            {
+                while (szBuffer[i+j] != chQuote && szBuffer[i+j] != '\n' && szBuffer[i+j] != '\r' && szBuffer[i+j] != '\0')
+                    j++;
+            }
+            else
+            {
+                while (szBuffer[i+j] != '\n' && szBuffer[i+j] != '\r' && szBuffer[i+j] != '\0')
+                    j++;
+            }
+
+            /* find end */
+            if (j >= CCHMAXPATH)
+            {
+                fprintf(stderr, "%s(%d) warning: Filename too long ignored.\n", pszFilename, iLine);
+                continue;
+            }
+
+            /* copy filename */
+            strncpy(szFullname, &szBuffer[i], j);
+            szFullname[j] = '\0'; /* ensure terminatition. */
+            strlwr(szFullname);
+
+            /* find include file! */
+            psz = filecacheFileExist(szFullname, szBuffer);
+
+            /* did we find the include? */
+            if (psz != NULL)
+            {
+                if (options.fExcludeAll || pathlistFindFile2(options.pszExclude, szBuffer))
+                    depAddDepend(pvRule, fileName(szFullname, szBuffer), options.fCheckCyclic, FALSE);
+                else
+                    depAddDepend(pvRule, szBuffer, options.fCheckCyclic, FALSE);
+            }
+            else
+            {
+                fprintf(stderr, "%s(%d): warning imbeded file '%s' was not found!\n",
+                        pszFilename, iLine, szFullname);
+                depMarkNotFound(pvRule);
+            }
+        }
+    } /*while*/
+
+    textbufferDestroy(pvFile);
+    fHeader = fHeader;
+
+    return 0;
+}
+
+
+#define upcase(ch)   \
+     (ch >= 'a' && ch <= 'z' ? ch - ('a' - 'A') : ch)
+
+/**
+ * Compares words. Multiple spaces are treates as on single blank i both string when comparing them.
+ * @returns   0 equal. (same as strnicmp)
+ * @param     pszS1  String 1
+ * @param     pszS2  String 2
+ * @param     cch    Length to compare (relative to string 1)
+ */
+int strnicmpwords(const char *pszS1, const char *pszS2, int cch)
+{
+    do
+    {
+        while (cch > 0 && upcase(*pszS1) == upcase(*pszS2) && *pszS1 != ' ')
+            pszS1++, pszS2++, cch--;
+
+        /* blank test and skipping */
+        if (cch > 0 && *pszS1 == ' ' && *pszS2 == ' ')
+        {
+            while (cch > 0 && *pszS1 == ' ')
+                pszS1++, cch--;
+
+            while (*pszS2 == ' ')
+                pszS2++;
+        }
+        else
+            break;
+    } while (cch > 0);
+
+    return cch == 0 ? 0 : *pszS1 - *pszS2;
+}
+
+
+/**
+ * Normalizes the path slashes for the filename. It will partially expand paths too.
+ * @returns   pszFilename
+ * @param     pszFilename  Pointer to filename string. Not empty string!
+ *                         Much space to play with.
+ */
+char *fileNormalize(char *pszFilename)
+{
+    char *psz = pszFilename;
+
+    /* correct slashes */
+    while ((pszFilename = strchr(pszFilename, '//')) != NULL)
+        *pszFilename++ = '\\';
+
+    /* expand path? */
+    pszFilename = psz;
+    if (pszFilename[1] != ':')
+    {   /* relative path */
+        int     iSlash;
+        char    szFile[CCHMAXPATH];
+        char *  psz = szFile;
+
+        strcpy(szFile, pszFilename);
+        iSlash = *psz == '\\' ? 1 : cSlashes;
+        while (*psz != '\0')
+        {
+            if (*psz == '.' && psz[1] == '.'  && psz[2] == '\\')
+            {   /* up one directory */
+                if (iSlash > 0)
+                    iSlash--;
+                psz += 3;
+            }
+            else if (*psz == '.' && psz[1] == '\\')
+            {   /* no change */
+                psz += 2;
+            }
+            else
+            {   /* completed expantion! */
+                strncpy(pszFilename, szCurDir, aiSlashes[iSlash]+1);
+                strcpy(pszFilename + aiSlashes[iSlash]+1, psz);
+                break;
+            }
+        }
+    }
+    /* else: assume full path */
+
+    return psz;
+}
+
+
+/**
+ * Normalizes the path slashes for the filename. It will partially expand paths too.
+ * Makes name all lower case too.
+ * @returns   pszFilename
+ * @param     pszFilename  Pointer to filename string. Not empty string!
+ *                         Much space to play with.
+ * @param     pszBuffer    Pointer to output buffer.
+ */
+char *fileNormalize2(const char *pszFilename, char *pszBuffer)
+{
+    char *  psz = pszBuffer;
+    int     iSlash;
+
+    if (pszFilename[1] != ':')
+    {
+        /* iSlash */
+        if (*pszFilename == '\\' || *pszFilename == '/')
+            iSlash = 1;
+        else
+            iSlash = cSlashes;
+
+        /* interpret . and .. */
+        while (*pszFilename != '\0')
+        {
+            if (*pszFilename == '.' && pszFilename[1] == '.'  && (pszFilename[2] == '\\' || pszFilename[1] == '/'))
+            {   /* up one directory */
+                if (iSlash > 0)
+                    iSlash--;
+                pszFilename += 3;
+            }
+            else if (*pszFilename == '.' && (pszFilename[1] == '\\' || pszFilename[1] == '/'))
+            {   /* no change */
+                pszFilename += 2;
+            }
+            else
+            {   /* completed expantion! - TODO ..\ or .\ may appare within the remaining path too... */
+                strncpy(pszBuffer, szCurDir, aiSlashes[iSlash]+1);
+                strcpy(pszBuffer + aiSlashes[iSlash]+1, pszFilename);
+                break;
+            }
+        }
+    }
+    else
+    {   /* have drive letter specified - assume ok (TODO)*/
+        strcpy(pszBuffer, pszFilename);
+    }
+
+    /* correct slashes */
+    while ((pszBuffer = strchr(pszBuffer, '//')) != NULL)
+        *pszBuffer++ = '\\';
+
+    /* lower case it */
+    /*strlwr(psz);*/
+
+    return psz;
+}
+
+
+/**
+ * Copies the path part (excluding the slash) into pszBuffer and returns
+ * a pointer to the buffer.
+ * If no path is found "" is returned.
+ * @returns   Pointer to pszBuffer with path.
+ * @param     pszFilename  Pointer to readonly filename.
+ * @param     pszBuffer    Pointer to output Buffer.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+char *filePath(const char *pszFilename, char *pszBuffer)
+{
+    char *psz = strrchr(pszFilename, '\\');
+    if (psz == NULL)
+        psz = strrchr(pszFilename, '/');
+
+    if (psz == NULL)
+        *pszBuffer = '\0';
+    else
+    {
+        strncpy(pszBuffer, pszFilename, psz - pszFilename);
+        pszBuffer[psz - pszFilename] = '\0';
+    }
+
+    return pszBuffer;
+}
+
+
+/**
+ * Copies the path part including the slash into pszBuffer and returns
+ * a pointer to the buffer.
+ * If no path is found "" is returned.
+ * @returns   Pointer to pszBuffer with path.
+ * @param     pszFilename  Pointer to readonly filename.
+ * @param     pszBuffer    Pointer to output Buffer.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+char *filePathSlash(const char *pszFilename, char *pszBuffer)
+{
+    char *psz = strrchr(pszFilename, '\\');
+    if (psz == NULL)
+        psz = strrchr(pszFilename, '/');
+
+    if (psz == NULL)
+        *pszBuffer = '\0';
+    else
+    {
+        strncpy(pszBuffer, pszFilename, psz - pszFilename + 1);
+        pszBuffer[psz - pszFilename + 1] = '\0';
+    }
+
+    return pszBuffer;
+}
+
+
+/**
+ * Copies the path part including the slash into pszBuffer and returns
+ * a pointer to the buffer. If no path is found "" is returned.
+ * The path is normalized to only use '\\'.
+ * @returns   Pointer to pszBuffer with path.
+ * @param     pszFilename  Pointer to readonly filename.
+ * @param     pszBuffer    Pointer to output Buffer.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+char *filePathSlash2(const char *pszFilename, char *pszBuffer)
+{
+    char *psz = strrchr(pszFilename, '\\');
+    if (psz == NULL)
+        psz = strrchr(pszFilename, '/');
+
+    if (psz == NULL)
+        *pszBuffer = '\0';
+    else
+    {
+        strncpy(pszBuffer, pszFilename, psz - pszFilename + 1);
+        pszBuffer[psz - pszFilename + 1] = '\0';
+
+        /* normalize all '/' to '\\' */
+        psz = pszBuffer;
+        while ((psz = strchr(psz, '/')) != NULL)
+               *psz++ = '\\';
+    }
+
+    return pszBuffer;
+}
+
+
+/**
+ * Copies the filename (with extention) into pszBuffer and returns
+ * a pointer to the buffer.
+ * @returns   Pointer to pszBuffer with path.
+ * @param     pszFilename  Pointer to readonly filename.
+ * @param     pszBuffer    Pointer to output Buffer.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+char *fileName(const char *pszFilename, char *pszBuffer)
+{
+    char *psz = strrchr(pszFilename, '\\');
+    if (psz == NULL)
+        psz = strrchr(pszFilename, '/');
+
+    strcpy(pszBuffer, psz == NULL ? pszFilename : psz + 1);
+
+    return pszBuffer;
+}
+
+
+/**
+ * Copies the name part with out extention into pszBuffer and returns
+ * a pointer to the buffer.
+ * If no name is found "" is returned.
+ * @returns   Pointer to pszBuffer with path.
+ * @param     pszFilename  Pointer to readonly filename.
+ * @param     pszBuffer    Pointer to output Buffer.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+char *fileNameNoExt(const char *pszFilename, char *pszBuffer)
+{
+    char *psz = strrchr(pszFilename, '\\');
+    if (psz == NULL)
+        psz = strrchr(pszFilename, '/');
+
+    strcpy(pszBuffer, psz == NULL ? pszFilename : psz + 1);
+
+    psz = strrchr(pszBuffer, '.');
+    if (psz > pszBuffer) /* an extetion on it's own (.depend) is a filename not an extetion! */
+        *psz = '\0';
+
+    return pszBuffer;
+}
+
+
+/**
+ * Copies the extention part into pszBuffer and returns
+ * a pointer to the buffer.
+ * If no extention is found "" is returned.
+ * The dot ('.') is not included!
+ * @returns   Pointer to pszBuffer with path.
+ * @param     pszFilename  Pointer to readonly filename.
+ * @param     pszBuffer    Pointer to output Buffer.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+char *fileExt(const char *pszFilename, char *pszBuffer)
+{
+    char *psz = strrchr(pszFilename, '.');
+    if (psz != NULL)
+    {
+        if (strchr(psz, '\\') != NULL || strchr(psz, '/') != NULL)
+            *pszBuffer = '\0';
+        else
+            strcpy(pszBuffer, psz + 1);
+    }
+    else
+        *pszBuffer = '\0';
+
+    return pszBuffer;
+}
+
+
+/**
+ * Adds a file to the cache.
+ * @returns   Success indicator.
+ * @param     pszFilename   Name of the file which is to be added. (with path!)
+ */
+BOOL filecacheAddFile(const char *pszFilename)
+{
+    PFCACHEENTRY pfcNew;
+
+    /* allocate new block and fill in data */
+    pfcNew = malloc(sizeof(FCACHEENTRY) + strlen(pszFilename) + 1);
+    if (pfcNew == NULL)
+    {
+        fprintf(stderr, "error: out of memory! (line=%d)\n", __LINE__);
+        return FALSE;
+    }
+    pfcNew->Key = (char*)(void*)pfcNew + sizeof(FCACHEENTRY);
+    strcpy((char*)(unsigned)pfcNew->Key, pszFilename);
+    if (!AVLInsert(&pfcTree, pfcNew))
+    {
+        free(pfcNew);
+        return TRUE;
+    }
+    cfcNodes++;
+
+    return TRUE;
+}
+
+
+/**
+ * Adds a file to the cache.
+ * @returns   Success indicator.
+ * @param     pszDir   Name of the path which is to be added. (with slash!)
+ */
+BOOL filecacheAddDir(const char *pszDir)
+{
+    PFCACHEENTRY    pfcNew;
+    APIRET          rc;
+    char            szDir[CCHMAXPATH];
+    int             cchDir;
+    char            achBuffer[32768];
+    PFILEFINDBUF3   pfindbuf3 = (PFILEFINDBUF3)(void*)&achBuffer[0];
+    HDIR            hDir = HDIR_CREATE;
+    ULONG           cFiles = 0xFFFFFFF;
+    int             i;
+
+    /* Make path */
+    filePathSlash2(pszDir, szDir);
+    /*strlwr(szDir);*/ /* Convert name to lower case to allow faster searchs! */
+    cchDir = strlen(szDir);
+
+
+    /* Add directory to pfcDirTree. */
+    pfcNew = malloc(sizeof(FCACHEENTRY) + cchDir + 1);
+    if (pfcNew == NULL)
+    {
+        fprintf(stderr, "error: out of memory! (line=%d)\n", __LINE__);
+        DosFindClose(hDir);
+        return FALSE;
+    }
+    pfcNew->Key = (char*)(void*)pfcNew + sizeof(FCACHEENTRY);
+    strcpy((char*)(unsigned)pfcNew->Key, szDir);
+    AVLInsert(&pfcDirTree, pfcNew);
+
+
+    /* Start to search directory - all files */
+    strcat(szDir + cchDir, "*");
+    rc = DosFindFirst(szDir, &hDir, FILE_NORMAL,
+                      pfindbuf3, sizeof(achBuffer),
+                      &cFiles, FIL_STANDARD);
+    while (rc == NO_ERROR)
+    {
+        for (i = 0;
+             i < cFiles;
+             i++, pfindbuf3 = (PFILEFINDBUF3)((int)pfindbuf3 + pfindbuf3->oNextEntryOffset)
+             )
+        {
+            pfcNew = malloc(sizeof(FCACHEENTRY) + cchDir + pfindbuf3->cchName + 1);
+            if (pfcNew == NULL)
+            {
+                fprintf(stderr, "error: out of memory! (line=%d)\n", __LINE__);
+                DosFindClose(hDir);
+                return FALSE;
+            }
+            pfcNew->Key = (char*)(void*)pfcNew + sizeof(FCACHEENTRY);
+            strcpy((char*)(unsigned)pfcNew->Key, szDir);
+            strcpy((char*)(unsigned)pfcNew->Key + cchDir, pfindbuf3->achName);
+            strlwr((char*)(unsigned)pfcNew->Key + cchDir); /* Convert name to lower case to allow faster searchs! */
+            if (!AVLInsert(&pfcTree, pfcNew))
+                free(pfcNew);
+            else
+                cfcNodes++;
+        }
+
+        /* next */
+        cFiles = 0xFFFFFFF;
+        pfindbuf3 = (PFILEFINDBUF3)(void*)&achBuffer[0];
+        rc = DosFindNext(hDir, pfindbuf3, sizeof(achBuffer), &cFiles);
+    }
+
+    DosFindClose(hDir);
+
+    return TRUE;
+}
+
+
+/**
+ * Checks if pszFilename is exists in the cache.
+ * @return    TRUE if found. FALSE if not found.
+ * @param     pszFilename   Name of the file to be found. (with path!)
+ *                          This is in lower case!
+ */
+INLINE BOOL filecacheFind(const char *pszFilename)
+{
+    return AVLGet(&pfcTree, (AVLKEY)pszFilename) != NULL;
+}
+
+
+/**
+ * Checks if pszFilename is exists in the cache.
+ * @return    TRUE if found. FALSE if not found.
+ * @param     pszFilename   Name of the file to be found. (with path!)
+ *                          This is in lower case!
+ */
+INLINE BOOL filecacheIsDirCached(const char *pszDir)
+{
+    return AVLGet(&pfcDirTree, (AVLKEY)pszDir) != NULL;
+}
+
+
+/**
+ * Checks if a file exist, uses file cache if possible.
+ * @returns   Pointer to a filename consiting of the path part + the given filename.
+ *            (pointer into pszBuffer)
+ *            NULL if file is not found. ("" in buffer)
+ * @parma     pszFilename  Filename to find.
+ * @parma     pszBuffer    Ouput Buffer.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+char *filecacheFileExist(const char *pszFilename, char *pszBuffer)
+{
+    APIRET          rc;
+
+    *pszBuffer = '\0';
+
+    fileNormalize2(pszFilename, pszBuffer);
+
+    /*
+     * Search for the file in this directory.
+     *   Search cache first
+     */
+    if (!filecacheFind(pszBuffer))
+    {
+        char szDir[CCHMAXPATH];
+
+        filePathSlash(pszBuffer, szDir);
+        if (!filecacheIsDirCached(szDir))
+        {
+            /*
+             * If caching of entire dirs are enabled, we'll
+             * add the directory to the cache and search it.
+             */
+            if (options.fCacheSearchDirs && filecacheAddDir(szDir))
+            {
+                if (filecacheFind(pszBuffer))
+                    return pszBuffer;
+            }
+            else
+            {
+                FILESTATUS3 fsts3;
+
+                /* ask the OS */
+                rc = DosQueryPathInfo(pszBuffer, FIL_STANDARD, &fsts3, sizeof(fsts3));
+                if (rc == NO_ERROR)
+                {   /* add file to cache. */
+                    filecacheAddFile(pszBuffer);
+                    return pszBuffer;
+                }
+            }
+        }
+    }
+    else
+        return pszBuffer;
+
+    return NULL;
+}
+
+
+/**
+ * Finds a filename in a specified pathlist.
+ * @returns   Pointer to a filename consiting of the path part + the given filename.
+ *            (pointer into pszBuffer)
+ *            NULL if file is not found. ("" in buffer)
+ * @param     pszPathList  Path list to search for filename.
+ * @parma     pszFilename  Filename to find.
+ * @parma     pszBuffer    Ouput Buffer.
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+char *pathlistFindFile(const char *pszPathList, const char *pszFilename, char *pszBuffer)
+{
+    const char *psz = pszPathList;
+    const char *pszNext = NULL;
+
+    *pszBuffer = '\0';
+
+    if (pszPathList == NULL)
+        return NULL;
+
+    while (*psz != '\0')
+    {
+        /* find end of this path */
+        pszNext = strchr(psz, ';');
+        if (pszNext == NULL)
+            pszNext = psz + strlen(psz);
+
+        if (pszNext - psz > 0)
+        {
+            APIRET          rc;
+
+            /* make search statment */
+            strncpy(pszBuffer, psz, pszNext - psz);
+            pszBuffer[pszNext - psz] = '\0';
+            if (pszBuffer[pszNext - psz - 1] != '\\' && pszBuffer[pszNext - psz - 1] != '/')
+                strcpy(&pszBuffer[pszNext - psz], "\\");
+            strcat(pszBuffer, pszFilename);
+            fileNormalize(pszBuffer);
+
+            /*
+             * Search for the file in this directory.
+             *   Search cache first
+             */
+            if (!filecacheFind(pszBuffer))
+            {
+                char szDir[CCHMAXPATH];
+
+                filePathSlash(pszBuffer, szDir);
+                if (!filecacheIsDirCached(szDir))
+                {
+                    /*
+                     * If caching of entire dirs are enabled, we'll
+                     * add the directory to the cache and search it.
+                     */
+                    if (options.fCacheSearchDirs && filecacheAddDir(szDir))
+                    {
+                        if (filecacheFind(pszBuffer))
+                            return pszBuffer;
+                    }
+                    else
+                    {
+                        FILESTATUS3 fsts3;
+
+                        /* ask the OS */
+                        rc = DosQueryPathInfo(pszBuffer, FIL_STANDARD, &fsts3, sizeof(fsts3));
+                        if (rc == NO_ERROR)
+                        {   /* add file to cache. */
+                            filecacheAddFile(pszBuffer);
+                            return pszBuffer;
+                        }
+                    }
+                }
+            }
+            else
+                return pszBuffer;
+        }
+
+        /* next */
+        if (*pszNext != ';')
+            break;
+        psz = pszNext + 1;
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Checks if the given filename may exist within any of the given paths.
+ * This check only matches the filename path agianst the paths in the pathlist.
+ * @returns   TRUE: if exists.
+ *            FALSE: don't exist.
+ * @param     pszPathList  Path list to search for filename.
+ * @parma     pszFilename  Filename to find. The filename should be normalized!
+ * @status    completely implemented.
+ * @author    knut st. osmundsen
+ */
+BOOL pathlistFindFile2(const char *pszPathList, const char *pszFilename)
+{
+    const char *psz = pszPathList;
+    const char *pszNext = NULL;
+    char        szBuffer[CCHMAXPATH];
+    char        szBuffer2[CCHMAXPATH];
+    char       *pszPathToFind = &szBuffer2[0];
+
+    /*
+     * Input checking
+     */
+    if (pszPathList == NULL)
+        return FALSE;
+
+    /*
+     * Normalize the filename and get it's path.
+     */
+    filePath(pszFilename, pszPathToFind);
+
+
+    /*
+     * Loop thru the path list.
+     */
+    while (*psz != '\0')
+    {
+        /* find end of this path */
+        pszNext = strchr(psz, ';');
+        if (pszNext == NULL)
+            pszNext = psz + strlen(psz);
+
+        if (pszNext - psz > 0)
+        {
+            char *  pszPath = &szBuffer[0];
+
+            /*
+             * Extract and normalize the path
+             */
+            strncpy(pszPath, psz, pszNext - psz);
+            pszPath[pszNext - psz] = '\0';
+            if (pszPath[pszNext - psz - 1] == '\\' && pszPath[pszNext - psz - 1] == '/')
+                pszPath[pszNext - psz - 1] = '\0';
+            fileNormalize(pszPath);
+
+            /*
+             * Check if it matches the path of the filename
+             */
+            if (strcmp(pszPath, pszPathToFind) == 0)
+                return TRUE;
+        }
+
+        /*
+         * Next part of the path list.
+         */
+        if (*pszNext != ';')
+            break;
+        psz = pszNext + 1;
+    }
+
+    return FALSE;
+}
+
+
+/**
+ * Finds the first char after word.
+ * @returns   Pointer to the first char after word.
+ * @param     psz  Where to start.
+ */
+char *findEndOfWord(char *psz)
+{
+
+    while (*psz != '\0' &&
+            (
+              (*psz >= 'A' && *psz <= 'Z') || (*psz >= 'a' && *psz <= 'z')
+              ||
+              (*psz >= '0' && *psz <= '9')
+              ||
+              *psz == '_'
+            )
+          )
+        ++psz;
+    return (char *)psz;
+}
+
+#if 0 /* not used */
+/**
+ * Find the starting char of a word
+ * @returns   Pointer to first char in word.
+ * @param     psz       Where to start.
+ * @param     pszStart  Where to stop.
+ */
+char *findStartOfWord(const char *psz, const char *pszStart)
+{
+    const char *pszR = psz;
+    while (psz >= pszStart &&
+            (
+                 (*psz >= 'A' && *psz <= 'Z')
+              || (*psz >= 'a' && *psz <= 'z')
+              || (*psz >= '0' && *psz <= '9')
+              || *psz == '_'
+             )
+          )
+        pszR = psz--;
+    return (char*)pszR;
+}
+#endif
+
+/**
+ * Find the size of a file.
+ * @returns   Size of file. -1 on error.
+ * @param     phFile  File handle.
+ */
+signed long fsize(FILE *phFile)
+{
+    int ipos;
+    signed long cb;
+
+    if ((ipos = ftell(phFile)) < 0
+        ||
+        fseek(phFile, 0, SEEK_END) != 0
+        ||
+        (cb = ftell(phFile)) < 0
+        ||
+        fseek(phFile, ipos, SEEK_SET) != 0
+        )
+        cb = -1;
+    return cb;
+}
+
+
+/**
+ * Trims a string, ie. removing spaces (and tabs) from both ends of the string.
+ * @returns   Pointer to first not space or tab char in the string.
+ * @param     psz   Pointer to the string which is to be trimmed.
+ * @status    completely implmented.
+ */
+INLINE char *trim(char *psz)
+{
+    int i;
+    if (psz == NULL)
+        return NULL;
+    while (*psz == ' ' || *psz == '\t')
+        psz++;
+    i = strlen(psz) - 1;
+    while (i >= 0 && (psz[i] == ' ' || *psz == '\t'))
+        i--;
+    psz[i+1] = '\0';
+    return psz;
+}
+
+
+/**
+ * Right trims a string, ie. removing spaces (and tabs) from the end of the stri
+ * @returns   Pointer to the string passed in.
+ * @param     psz   Pointer to the string which is to be right trimmed.
+ * @status    completely implmented.
+ */
+INLINE char *trimR(char *psz)
+{
+    int i;
+    if (psz == NULL)
+        return NULL;
+    i = strlen(psz) - 1;
+    while (i >= 0 && (psz[i] == ' ' || *psz == '\t'))
+        i--;
+    psz[i+1] = '\0';
+    return psz;
+}
+
+
+/**
+ * Trims any quotes of a possibly quoted string.
+ * @returns   Pointer to the string passed in.
+ * @param     psz   Pointer to the string which is to be quote-trimmed.
+ * @status    completely implmented.
+ */
+INLINE char *trimQuotes(char *psz)
+{
+    int i;
+    if (psz == NULL)
+        return NULL;
+
+    if (*psz == '\"' || *psz == '\'')
+        psz++;
+    i = strlen(psz) - 1;
+    if (psz[i] == '\"' || psz[i] == '\'')
+        psz[i] = '\0';
+
+    return psz;
+}
+
+
+/**
+ * C/C++ preprocess a single line. Assumes that we're not starting
+ * with at comment.
+ * @returns Pointer to output buffer.
+ * @param   pszOut  Ouput (preprocessed) string.
+ * @param   pszIn   Input string.
+ */
+char *PreProcessLine(char *pszOut, const char *pszIn)
+{
+    char *  psz = pszOut;
+    BOOL    fComment = FALSE;
+    BOOL    fQuote = FALSE;
+
+    /*
+     * Loop thru the string.
+     */
+    while (*pszIn != '\0')
+    {
+        if (fQuote)
+        {
+            *psz++ = *pszIn;
+            if (*pszIn == '\\')
+            {
+                *psz++ = *++pszIn;
+                pszIn++;
+            }
+            else if (*pszIn++ == '"')
+                fQuote = FALSE;
+        }
+        else if (fComment)
+        {
+            if (*pszIn == '*' && pszIn[1] == '/')
+            {
+                fComment = FALSE;
+                pszIn += 2;
+            }
+            else
+                pszIn++;
+        }
+        else
+        {
+            if (   (*pszIn == '/' && pszIn[1] == '/')
+                ||  *pszIn == '\0')
+            {   /* End of line. */
+                break;
+            }
+
+            if (*pszIn == '/' && pszIn[1] == '*')
+            {   /* Start comment */
+                fComment = TRUE;
+                pszIn += 2;
+            }
+            else
+                *psz++ = *pszIn++;
+        }
+    }
+
+    /*
+     * Trim right.
+     */
+    psz--;
+    while (psz >= pszOut && (*psz == ' ' || *psz == '\t'))
+        psz--;
+    psz[1] = '\0';
+
+    return pszOut;
+}
+
+
+/**
+ * Creates a memory buffer for a text file.
+ * @returns   Pointer to file memoryblock. NULL on error.
+ * @param     pszFilename  Pointer to filename string.
+ * @remark    This function is the one using most of the execution
+ *            time (DosRead + DosOpen) - about 70% of the execution time!
+ */
+void *textbufferCreate(const char *pszFilename)
+{
+    void *pvFile = NULL;
+    FILE *phFile;
+
+    phFile = fopen(pszFilename, "rb");
+    if (phFile != NULL)
+    {
+        signed long cbFile = fsize(phFile);
+        if (cbFile >= 0)
+        {
+            pvFile = malloc(cbFile + 1);
+            if (pvFile != NULL)
+            {
+                memset(pvFile, 0, cbFile + 1);
+                if (cbFile > 0 && fread(pvFile, 1, cbFile, phFile) == 0)
+                {   /* failed! */
+                    free(pvFile);
+                    pvFile = NULL;
+                }
+            }
+            else
+                fprintf(stderr, "warning/error: failed to open file %s\n", pszFilename);
+        }
+        fclose(phFile);
+    }
+    return pvFile;
+}
+
+
+/**
+ * Destroys a text textbuffer.
+ * @param     pvBuffer   Buffer handle.
+ */
+void textbufferDestroy(void *pvBuffer)
+{
+    free(pvBuffer);
+}
+
+
+/**
+ * Gets the next line from an textbuffer.
+ * @returns   Pointer to the next line.
+ * @param     pvBuffer  Buffer handle.
+ * @param     psz       Pointer to current line.
+ *                      NULL is passed in to get the first line.
+ */
+char *textbufferNextLine(void *pvBuffer, register char *psz)
+{
+    register char ch;
+
+    /* if first line psz is NULL. */
+    if (psz == NULL)
+        return (char*)pvBuffer;
+
+    /* skip till end of file or end of line. */
+    ch = *psz;
+    while (ch != '\0' && ch != '\n' && ch != '\r')
+        ch = *++psz;
+
+    /* skip line end */
+    if (ch == '\r')
+        ch = *++psz;
+    if (ch == '\n')
+        psz++;
+
+    return psz;
+}
+
+
+/**
+ * Gets the next line from an textbuffer.
+ * (fgets for textbuffer)
+ * @returns   Pointer to pszOutBuffer. NULL when end of file.
+ * @param     pvBuffer  Buffer handle.
+ * @param     ppv       Pointer to a buffer index pointer. (holds the current buffer index)
+ *                      Pointer to a null pointer is passed in to get the first line.
+ * @param     pszLineBuffer  Output line buffer. (!= NULL)
+ * @param     cchLineBuffer  Size of the output line buffer. (> 0)
+ * @remark    '\n' and '\r' are removed!
+ */
+char *textbufferGetNextLine(void *pvBuffer, void **ppv, char *pszLineBuffer, int cchLineBuffer)
+{
+    char *          pszLine = pszLineBuffer;
+    char *          psz = *(char**)(void*)ppv;
+    register char   ch;
+
+    /* first line? */
+    if (psz == NULL)
+        psz = pvBuffer;
+
+    /* Copy to end of the line or end of the linebuffer. */
+    ch = *psz;
+    cchLineBuffer--; /* reserve space for '\0' */
+    while (cchLineBuffer > 0 && ch != '\0' && ch != '\n' && ch != '\r')
+    {
+        *pszLine++ = ch;
+        ch = *++psz;
+    }
+    *pszLine = '\0';
+
+    /* skip line end */
+    if (ch == '\r')
+        ch = *++psz;
+    if (ch == '\n')
+        psz++;
+
+    /* check if position has changed - if unchanged it's the end of file! */
+    if (*ppv == (void*)psz)
+        pszLineBuffer = NULL;
+
+    /* store current position */
+    *ppv = (void*)psz;
+
+    return pszLineBuffer;
+}
+
+
+/**
+ * Appends a depend file to the internal file.
+ * This will update the date in the option struct.
+ */
+BOOL  depReadFile(const char *pszFilename, BOOL fAppend)
+{
+    void *      pvFile;
+    char *      pszNext;
+    char *      pszPrev;                /* Previous line, only valid when finding new rule. */
+    BOOL        fMoreDeps = FALSE;
+    void *      pvRule = NULL;
+
+
+    /* read depend file */
+    pvFile = textbufferCreate(pszFilename);
+    if (pvFile == NULL)
+        return FALSE;
+
+    /* parse the original depend file */
+    pszPrev = NULL;
+    pszNext = pvFile;
+    while (*pszNext != '\0')
+    {
+        int   i;
+        int   cch;
+        char *psz;
+
+        /* get the next line. */
+        psz = pszNext;
+        pszNext = textbufferNextLine(pvFile, pszNext);
+
+        /*
+         * Process the current line:
+         *   Start off by terminating the line.
+         *   Trim the line,
+         *   Skip empty lines.
+         *   If not looking for more deps Then
+         *     Check if new rule starts here.
+         *   Endif
+         *
+         *   If more deps to last rule Then
+         *     Get dependant name.
+         *   Endif
+         */
+        i = -1;
+        while (psz <= &pszNext[i] && pszNext[i] == '\n' || pszNext[i] == '\r')
+            pszNext[i--] = '\0';
+        trimR(psz);
+        cch = strlen(psz);
+        if (cch == 0)
+        {
+            fMoreDeps = FALSE;
+            continue;
+        }
+
+        if (*psz == '#')
+        {
+            pszPrev = psz;
+            continue;
+        }
+
+        /* new rule? */
+        if (!fMoreDeps)
+        {
+            if (*psz != ' ' && *psz != '\t' && *psz != '\0')
+            {
+                i = 0;
+                while (psz[i] != '\0')
+                {
+                    if (psz[i] == ':'
+                        && (psz[i+1] == ' '
+                            || psz[i+1] == '\t'
+                            || psz[i+1] == '\0'
+                            || (psz[i+1] == '\\' && psz[i+2] == '\0')
+                            )
+                        )
+                    {
+                        char    szTS[TS_SIZE];
+                        char *  pszCont = strchr(&psz[i], '\\');
+                        fMoreDeps = pszCont != NULL && pszCont[1] == '\0';
+
+                        /* read evt. timestamp. */
+                        szTS[0] = '\0';
+                        if (pszPrev && strlen(pszPrev) > 25 && *pszPrev == '#')
+                            strcpy(szTS, pszPrev + 2);
+
+                        psz[i] = '\0';
+                        pvRule = depAddRule(trimQuotes(trimR(psz)), NULL, NULL, szTS, TRUE);
+                        if (pvRule)
+                            ((PDEPRULE)pvRule)->fUpdated = fAppend;
+                        psz += i + 1;
+                        cch -= i + 1;
+                        break;
+                    }
+                    i++;
+                }
+            }
+            pszPrev = NULL;
+        }
+
+
+        /* more dependants */
+        if (fMoreDeps)
+        {
+            if (cch > 0 && psz[cch-1] == '\\')
+            {
+                fMoreDeps = TRUE;
+                psz[cch-1] = '\0';
+            }
+            else
+                fMoreDeps = FALSE;
+
+            /* if not duplicate rule */
+            if (pvRule != NULL)
+            {
+                psz = trimQuotes(trim(psz));
+                if (*psz != '\0')
+                    depAddDepend(pvRule, psz, options.fCheckCyclic, TRUE);
+            }
+        }
+    } /* while */
+
+
+    /* return succesfully */
+    textbufferDestroy(pvFile);
+    return TRUE;
+}
+
+/**
+ *
+ * @returns   Success indicator.
+ * @param     pszFilename           Pointer to name of the output file.
+ * @param     fWriteUpdatedOnly     If set we'll only write updated rules.
+ */
+BOOL  depWriteFile(const char *pszFilename, BOOL fWriteUpdatedOnly)
+{
+    FILE *phFile;
+    phFile = fopen(pszFilename, "w");
+    if (phFile != NULL)
+    {
+        AVLENUMDATA EnumData;
+        PDEPRULE    pdep;
+        static char szBuffer[0x10000];
+        int         iBuffer = 0;
+        int         cch;
+
+        /*
+         * Write warning on top of file.
+         */
+        fputs("#\n"
+              "# This file was automatically generated by FastDep.\n"
+              "# FastDep was written by knut st. osmundsen, and it's GPL software.\n"
+              "#\n"
+              "# THIS FILE SHOULD   N O T   BE EDITED MANUALLY!!!\n"
+              "#\n"
+              "# (As this may possibly make it unreadable for fastdep\n"
+              "#  and ruin the caching methods of FastDep.)\n"
+              "#\n"
+              "\n",
+              phFile);
+
+        /* normal dependency output */
+        pdep = (PDEPRULE)(void*)AVLBeginEnumTree((PPAVLNODECORE)(void*)&pdepTree, &EnumData, TRUE);
+        while (pdep != NULL)
+        {
+            if (!fWriteUpdatedOnly || pdep->fUpdated)
+            {
+                int cchTS = strlen(pdep->szTS);
+                int fQuoted = strpbrk(pdep->pszRule, " \t") != NULL; /* TODO/BUGBUG/FIXME: are there more special chars to look out for?? */
+
+                /* Write rule. Flush the buffer first if necessary. */
+                cch = strlen(pdep->pszRule);
+                if (iBuffer + cch*3 + fQuoted * 2 + cchTS + 9 >= sizeof(szBuffer))
+                {
+                    fwrite(szBuffer, iBuffer, 1, phFile);
+                    iBuffer = 0;
+                }
+
+                memcpy(szBuffer + iBuffer, "# ", 2);
+                memcpy(szBuffer + iBuffer + 2, pdep->szTS, cchTS);
+                iBuffer += cchTS + 2;
+                szBuffer[iBuffer++] = '\n';
+
+                if (fQuoted) szBuffer[iBuffer++] = '"';
+                iBuffer += depNameToMake(szBuffer + iBuffer, sizeof(szBuffer) - iBuffer, pdep->pszRule);
+                if (fQuoted) szBuffer[iBuffer++] = '"';
+                strcpy(szBuffer + iBuffer++, ":");
+
+                /* write rule dependants. */
+                if (pdep->papszDep != NULL)
+                {
+                    char **ppsz = pdep->papszDep;
+                    while (*ppsz != NULL)
+                    {
+                        /* flush buffer? */
+                        fQuoted = strpbrk(*ppsz, " \t") != NULL; /* TODO/BUGBUG/FIXME: are there more special chars to look out for?? */
+                        cch = strlen(*ppsz);
+                        if (iBuffer + cch*3 + fQuoted * 2 + 20 >= sizeof(szBuffer))
+                        {
+                            fwrite(szBuffer, iBuffer, 1, phFile);
+                            iBuffer = 0;
+                        }
+                        strcpy(szBuffer + iBuffer, " \\\n    ");
+                        iBuffer += 7;
+                        if (fQuoted) szBuffer[iBuffer++] = '"';
+                        iBuffer += depNameToMake(szBuffer + iBuffer, sizeof(szBuffer) - iBuffer, *ppsz);
+                        if (fQuoted) szBuffer[iBuffer++] = '"';
+
+                        /* next dependant */
+                        ppsz++;
+                    }
+                }
+
+                /* Add two new lines. Flush buffer first if necessary. */
+                if (iBuffer + CBNEWLINE*2 >= sizeof(szBuffer))
+                {
+                    fwrite(szBuffer, iBuffer, 1, phFile);
+                    iBuffer = 0;
+                }
+
+                /* add 2 linefeeds */
+                strcpy(szBuffer + iBuffer, "\n\n");
+                iBuffer += CBNEWLINE*2;
+            }
+
+            /* next rule */
+            pdep = (PDEPRULE)(void*)AVLGetNextNode(&EnumData);
+        }
+
+
+        /* flush buffer. */
+        fwrite(szBuffer, iBuffer, 1, phFile);
+
+        fclose(phFile);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+
+/**
+ * Removes all nodes in the tree of dependencies. (pdepTree)
+ */
+void  depRemoveAll(void)
+{
+    AVLENUMDATA EnumData;
+    PDEPRULE    pdep;
+
+    pdep = (PDEPRULE)(void*)AVLBeginEnumTree((PPAVLNODECORE)(void*)&pdepTree, &EnumData, TRUE);
+    while (pdep != NULL)
+    {
+        /* free this */
+        if (pdep->papszDep != NULL)
+        {
+            char ** ppsz = pdep->papszDep;
+            while (*ppsz != NULL)
+                free(*ppsz++);
+            free(pdep->papszDep);
+        }
+        free(pdep);
+
+        /* next */
+        pdep = (PDEPRULE)(void*)AVLGetNextNode(&EnumData);
+    }
+    pdepTree = NULL;
+}
+
+
+/**
+ * Adds a rule to the list of dependant rules.
+ * @returns   Rule handle. NULL if rule exists/error.
+ * @param     pszRulePath   Pointer to rule text. Empty strings are banned!
+ *                          This string might only contain the path of the rule. (with '\\')
+ * @param     pszName       Name of the rule.
+ *                          NULL if pszRulePath contains the entire rule.
+ * @param     pszExt        Extention (without '.')
+ *                          NULL if pszRulePath or pszRulePath and pszName contains the entire rule.
+ * @param     fConvertName  If set we'll convert from makefile name to realname.
+ */
+void *depAddRule(const char *pszRulePath, const char *pszName, const char *pszExt, const char *pszTS, BOOL fConvertName)
+{
+    char     szRule[CCHMAXPATH*2];
+    PDEPRULE pNew;
+    int      cch;
+
+    /* make rulename */
+    strcpy(szRule, pszRulePath);
+    cch = strlen(szRule);
+    if (pszName != NULL)
+    {
+        strcpy(szRule + cch, pszName);
+        cch += strlen(szRule + cch);
+    }
+    if (pszExt != NULL)
+    {
+        strcat(szRule + cch++, ".");
+        strcat(szRule + cch, pszExt);
+        cch += strlen(szRule + cch);
+    }
+    if (fConvertName)
+        cch = depNameToReal(szRule);
+
+    /*
+     * Allocate a new rule structure and fill in data
+     * Note. One block for both the DEPRULE and the pszRule string.
+     */
+    pNew = malloc(sizeof(DEPRULE) + cch + 1);
+    if (pNew == NULL)
+    {
+        fprintf(stderr, "error: out of memory. (line=%d)\n", __LINE__);
+        return NULL;
+    }
+    pNew->pszRule = (char*)(void*)(pNew + 1);
+    strcpy(pNew->pszRule, szRule);
+    pNew->cDeps = 0;
+    pNew->papszDep = NULL;
+    pNew->fUpdated = TRUE;
+    pNew->avlCore.Key = pNew->pszRule;
+    strcpy(pNew->szTS, pszTS);
+
+    /* Insert the rule */
+    if (!AVLInsert((PPAVLNODECORE)(void*)&pdepTree, &pNew->avlCore))
+    {   /*
+         * The rule existed.
+         * If it's allready touched (updated) during this session
+         *   there is nothing to be done.
+         * If not force scan and it's newer than depfile-1month then
+         *   we'll use the information we've got.
+         * Reuse the node in the tree.
+         */
+        PDEPRULE    pOld = (PDEPRULE)(void*)AVLGet((PPAVLNODECORE)(void*)&pdepTree, pNew->avlCore.Key);
+        assert(pOld);
+        free(pNew);
+        if (pOld->fUpdated)
+            return NULL;
+
+        pOld->fUpdated = TRUE;
+        if (!options.fForceScan && !strcmp(pOld->szTS, pszTS) && depValidate(pOld))
+            return NULL;
+        strcpy(pOld->szTS, pszTS);
+
+        if (pOld->papszDep)
+        {
+            free(pOld->papszDep);
+            pOld->papszDep = NULL;
+        }
+        pOld->cDeps = 0;
+
+        return pOld;
+    }
+
+    return pNew;
+}
+
+
+/**
+ * Adds a dependant to a rule.
+ * @returns   Successindicator. TRUE = success.
+ *            FALSE = cyclic or out of memory.
+ * @param     pvRule        Rule handle.
+ * @param     pszDep        Pointer to dependant name
+ * @param     fCheckCyclic  When set we'll check that we're not creating an cyclic dependency.
+ * @param     fConvertName  If set we'll convert from makefile name to realname.
+ */
+BOOL  depAddDepend(void *pvRule, const char *pszDep, BOOL fCheckCyclic, BOOL fConvertName)
+{
+    PDEPRULE    pdep = (PDEPRULE)pvRule;
+    int         cchDep;
+
+    if (pszDep[0] == '\0')
+    {
+        fprintf(stderr, "warning-internal: empty dependancy filename to '%s'. Ignored.\n",
+                pdep->pszRule);
+        /* __interrupt(3); */
+        return FALSE;
+    }
+
+    if (fCheckCyclic && depCheckCyclic(pdep, pszDep))
+    {
+        fprintf(stderr, "warning: Cylic dependancy caused us to ignore '%s' in rule '%s'.\n",
+                pszDep, pdep->pszRule);
+        return FALSE;
+    }
+
+    /* allocate more array space */
+    if (((pdep->cDeps) % 48) == 0)
+    {
+        pdep->papszDep = realloc(pdep->papszDep, sizeof(char*) * (pdep->cDeps + 50));
+        if (pdep->papszDep == NULL)
+        {
+            pdep->cDeps = 0;
+            fprintf(stderr, "error: out of memory, (line=%d)\n", __LINE__);
+            return FALSE;
+        }
+    }
+
+    /* allocate string space and copy pszDep */
+    cchDep = strlen(pszDep) + 1;
+    if ((pdep->papszDep[pdep->cDeps] = malloc(cchDep)) == NULL)
+    {
+        fprintf(stderr, "error: out of memory, (line=%d)\n", __LINE__);
+        return FALSE;
+    }
+    strcpy(pdep->papszDep[pdep->cDeps], pszDep);
+
+    /* convert ^# and other stuff */
+    if (fConvertName)
+        depNameToReal(pdep->papszDep[pdep->cDeps]);
+
+    /* terminate array and increment dep count */
+    pdep->papszDep[++pdep->cDeps] = NULL;
+
+    /* successful! */
+    return TRUE;
+}
+
+
+/**
+ * Converts from makefile filename to real filename.
+ * @returns New name length.
+ * @param   pszName     Pointer to the string to make real.
+ */
+int depNameToReal(char *pszName)
+{
+    int cchNewName = strlen(pszName);
+    int iDisplacement = 0;
+
+    /*
+     * Look for '^' and '$$'.
+     */
+    while (*pszName)
+    {
+        if (    *pszName == '^'
+            ||  (*pszName == '$' && pszName[1] == '$'))
+        {
+            iDisplacement--;
+            pszName++;
+            cchNewName--;
+        }
+        if (iDisplacement)
+            pszName[iDisplacement] = *pszName;
+        pszName++;
+    }
+    pszName[iDisplacement] = '\0';
+
+    return cchNewName;
+}
+
+
+/**
+ * Converts from real filename to makefile filename.
+ * @returns New name length.
+ * @param   pszName     Output name buffer.
+ * @param   cchName     Size of name buffer.
+ * @param   pszSrc      Input name.
+ */
+int   depNameToMake(char *pszName, int cchName, const char *pszSrc)
+{
+    char *pszNameOrg = pszName;
+
+    /*
+     * Convert real name to makefile name.
+     */
+    while (*pszSrc)
+    {
+        if (    *pszSrc == '#'
+            ||  *pszSrc == '!'
+            ||  (*pszSrc == '$' && pszSrc[1] != '(')
+            ||  *pszSrc == '@'
+            ||  *pszSrc == '-'
+            ||  *pszSrc == '^'
+           /* ||  *pszSrc == '('
+            ||  *pszSrc == ')'
+            ||  *pszSrc == '{'
+            ||  *pszSrc == '}'*/)
+        {
+            if (!cchName--)
+            {
+                fprintf(stderr, "error: buffer too small, (line=%d)\n", __LINE__);
+                return pszName - pszNameOrg + strlen(pszName);
+            }
+            *pszName++ = '^';
+        }
+        if (!cchName--)
+        {
+            fprintf(stderr, "error: buffer too small, (line=%d)\n", __LINE__);
+            return pszName - pszNameOrg + strlen(pszName);
+        }
+        *pszName++ = *pszSrc++;
+    }
+    *pszName = '\0';
+
+    return pszName - pszNameOrg;
+}
+
+
+
+/**
+ * Marks the file as one which is to be rescanned next time
+ * since not all dependencies was found...
+ * @param   pvRule  Rule handle...
+ */
+void  depMarkNotFound(void *pvRule)
+{
+    ((PDEPRULE)pvRule)->szTS[0] = '\0';
+}
+
+
+/**
+ * Checks if adding this dependent will create a cyclic dependency.
+ * @returns   TRUE: Cyclic.
+ *            FALSE: Non-cylic.
+ * @param     pdepRule  Rule pszDep is to be inserted in.
+ * @param     pszDep    Depend name.
+ */
+BOOL depCheckCyclic(PDEPRULE pdepRule, const char *pszDep)
+{
+#define DEPTH_FIRST 1
+#ifdef DEPTH_FIRST
+    #define DEPTH 32
+#else
+    #define DEPTH 128
+#endif
+    #define HISTORY 256
+    char *  pszRule = pdepRule->pszRule;
+    char ** appsz[DEPTH];
+#if HISTORY
+    char *  apszHistory[HISTORY];
+    int     iHistory;
+    int     j;
+    int     iStart;
+    int     iEnd;
+    int     iCmp;
+#endif
+    PDEPRULE pdep;
+    int     i;
+
+    /* self check */
+    if (strcmp(pdepRule->pszRule, pszDep) == 0)
+        return TRUE;
+
+    /* find rule for the dep. */
+    if ((pdep = (PDEPRULE)(void*)AVLGet((PPAVLNODECORE)(void*)&pdepTree, pszDep)) == NULL
+        || pdep->papszDep == NULL)
+        return FALSE; /* no rule, or no dependents, not cyclic */
+
+    i = 1;
+    appsz[0] = pdep->papszDep;
+#ifdef HISTORY
+    iHistory = 1;
+    apszHistory[0] = pdep->pszRule;
+#endif
+    while (i > 0)
+    {
+        /* pop off element */
+        register char **  ppsz = appsz[--i];
+
+        while (*ppsz != NULL)
+        {
+            /* check if equal to the main rule */
+            if (strcmp(pszRule, *ppsz) == 0)
+                return TRUE;
+
+            /* push onto stack (ppsz is incremented in this test!) */
+            if ((pdep = (PDEPRULE)(void*)AVLGet((PPAVLNODECORE)(void*)&pdepTree, *ppsz++)) != NULL
+                && pdep->papszDep != NULL)
+            {
+                if (i >= DEPTH)
+                {
+                    fprintf(stderr, "error: too deep chain (%d). pszRule=%s  pszDep=%s\n",
+                            i, pszRule, pszDep);
+                    return FALSE;
+                }
+#ifdef HISTORY
+                /*
+                 * Check if in history, if so we'll skip it.
+                 */
+                #if 0
+                for (j = 0;  j < iHistory; j++)
+                    if (!strcmp(apszHistory[j], pdep->pszRule))
+                        break;
+                if (j != iHistory)
+                    continue;           /* found */
+
+                /*
+                 * Push into history - might concider make this binary sorted one day.
+                 */
+                if (iHistory < HISTORY)
+                    apszHistory[iHistory++] = pdep->pszRule;
+
+                #else
+
+                /*
+                 * Check if in history, if so we'll skip it.
+                 *  (Binary search)
+                 * ASSUMES: Always something in the history!
+                 */
+                iEnd = iHistory - 1;
+                iStart = 0;
+                j = iHistory / 2;
+                while (    (iCmp = strcmp(pdep->pszRule, apszHistory[j])) != 0
+                       &&   iEnd != iStart)
+                {
+                    if (iCmp < 0)
+                        iEnd = j - 1;
+                    else
+                        iStart = j + 1;
+                    if (iStart > iEnd)
+                        break;
+                    j = (iStart + iEnd) / 2;
+                }
+
+                if (!iCmp)
+                    continue;           /* found */
+
+                /*
+                 * Push into history - might concider make this binary sorted one day.
+                 */
+                if (iHistory < HISTORY)
+                {
+                    int k;
+                    if (iCmp > 0)       /* Insert after. */
+                        j++;
+                    for (k = iHistory; k > j; k--)
+                        apszHistory[k] = apszHistory[k - 1];
+                    apszHistory[j] = pdep->pszRule;
+                    iHistory++;
+                }
+
+                #endif
+
+#endif
+                /*
+                 * Push on to the stack.
+                 */
+                #ifdef DEPTH_FIRST
+                /* dept first */
+                appsz[i++] = ppsz;      /* save current posistion */
+                ppsz = pdep->papszDep;  /* process new node */
+                #else
+                /* complete current node first. */
+                appsz[i++] = pdep->papszDep;
+                #endif
+            }
+        }
+    }
+
+    return FALSE;
+}
+
+
+/**
+ * Validates that the dependencies for the file exists
+ * in the given locations. Dependants without path is ignored.
+ * @returns TRUE if all ok.
+ *          FALSE if one (or possibly more) dependants are non-existing.
+ * @param   pdepRule    Pointer to rule we're to validate.
+ */
+BOOL depValidate(PDEPRULE pdepRule)
+{
+    int i;
+
+    for (i = 0; i < pdepRule->cDeps; i++)
+    {
+        char *psz = pdepRule->papszDep[i];
+        if (    !strchr(psz, '$')
+            &&
+            (   psz[1] == ':'
+            ||  strchr(psz, '\\')
+            ||  strchr(psz, '/')
+                 )
+            )
+        {
+            /*
+             * Check existance of the file.
+             *   Search cache first
+             */
+            if (!filecacheFind(psz))
+            {
+                char szDir[CCHMAXPATH];
+
+                filePathSlash(psz, szDir);
+                if (!filecacheIsDirCached(szDir))
+                {
+                    /*
+                     * If caching of entire dirs are enabled, we'll
+                     * add the directory to the cache and search it.
+                     */
+                    if (options.fCacheSearchDirs && filecacheAddDir(szDir))
+                    {
+                        if (!filecacheFind(psz))
+                            return FALSE;
+                    }
+                    else
+                    {
+                        FILESTATUS3 fsts3;
+
+                        /* ask the OS */
+                        if (DosQueryPathInfo(psz, FIL_STANDARD, &fsts3, sizeof(fsts3)))
+                            return FALSE;
+                        /* add file to cache. */
+                        filecacheAddFile(psz);
+                    }
+                }
+                /*
+                 * Dir was cached, hence the file doesn't exist
+                 * and the we should rescan the source file.
+                 */
+                else
+                    return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+
+/**
+ * Make a timestamp from the file data provided thru the
+ * search API.
+ * @returns Pointer to pszTS
+ * @param   pszTS       Pointer to timestamp (output).
+ * @param   pfindbuf3   Pointer to search result.
+ */
+INLINE char *depMakeTS(char *pszTS, PFILEFINDBUF3 pfindbuf3)
+{
+    sprintf(pszTS, "%04d-%02d-%02d-%02d.%02d.%02d 0x%04x%04x %d",
+            pfindbuf3->fdateLastWrite.year + 1980,
+            pfindbuf3->fdateLastWrite.month,
+            pfindbuf3->fdateLastWrite.day,
+            pfindbuf3->ftimeLastWrite.hours,
+            pfindbuf3->ftimeLastWrite.minutes,
+            pfindbuf3->ftimeLastWrite.twosecs * 2,
+            (ULONG)*(PUSHORT)(void*)&pfindbuf3->fdateCreation,
+            (ULONG)*(PUSHORT)(void*)&pfindbuf3->ftimeCreation,
+            pfindbuf3->cbFile);
+    return pszTS;
+}
+
+
+/**
+ * Adds the src additioanl dependenies to a rule.
+ * @param   pvRule  Rule to add them to.
+ * @param   pszz    Pointer to the string of strings of extra dependencies.
+ */
+void depAddSrcAddDeps(void *pvRule, const char *pszz)
+{
+    while (*pszz)
+    {
+        depAddDepend(pvRule, pszz, FALSE, FALSE);
+        pszz += strlen(pszz) + 1;
+    }
+}
+
+
+
+
+
+/*
+ * Testing purpose.
+ */
+
+#if !defined(OS2FAKE)
+#include <os2.h>
+#endif
+#ifdef OLEMANN
+#include "olemann.h"
+#endif
Index: /tags/kBuild-0.1.4/src/fastdep/fastdep.def
===================================================================
--- /tags/kBuild-0.1.4/src/fastdep/fastdep.def	(revision 1780)
+++ /tags/kBuild-0.1.4/src/fastdep/fastdep.def	(revision 1780)
@@ -0,0 +1,3 @@
+NAME fastdef WINDOWCOMPAT
+DESCRIPTION "Knut''s Quick and Dirty Dependency Generator"
+
Index: /tags/kBuild-0.1.4/src/fastdep/os2fake-win.c
===================================================================
--- /tags/kBuild-0.1.4/src/fastdep/os2fake-win.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/fastdep/os2fake-win.c	(revision 1780)
@@ -0,0 +1,297 @@
+/* $Id$
+ * 
+ * OS/2 Fake library for Win32.
+ * 
+ * Copyright (c) 2001 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#define VALIDPTR(pv) (((PVOID)pv) >= (PVOID)0x10000 && ((PVOID)pv) <= (PVOID)0xc0000000)
+
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <windows.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "os2fake.h"
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static ULONG ConvertAttributes(DWORD dwFileAttributes);
+static ULONG ConvertFileTime(PFILETIME pFileTime);
+
+/**
+ * Converts Win32 file attribute to OS/2 file attributes.
+ * @returns OS/2 fileattributes.
+ * @param   dwFileAttributes    Win32 fileattributes.
+ */
+ULONG ConvertAttributes(DWORD dwFileAttributes)
+{
+    static struct _ConvAttr
+    {
+        ULONG   ulWin;
+        ULONG   ulOs2;
+    }       aConvAttr[] = 
+    {                                  
+        {FILE_ATTRIBUTE_READONLY,   FILE_READONLY},
+        {FILE_ATTRIBUTE_HIDDEN,     FILE_HIDDEN},
+        {FILE_ATTRIBUTE_SYSTEM,     FILE_SYSTEM},
+        {FILE_ATTRIBUTE_DIRECTORY,  FILE_DIRECTORY},
+        {FILE_ATTRIBUTE_ARCHIVE,    FILE_ARCHIVED}
+    };                                    
+    ULONG   ulOS2Attr = 0;
+    int     i;
+
+    for (i = 0; i < sizeof(aConvAttr) / sizeof(aConvAttr[0]); i++)
+        if (dwFileAttributes & aConvAttr[i].ulWin)
+            ulOS2Attr |= aConvAttr[i].ulOs2;
+
+    return ulOS2Attr;
+}
+
+
+/**
+ * Converts Win32 filetime to OS/2 filetime.
+ * @returns OS/2 filetime.
+ * @param   pFileTime   Pointer to Win32 filetime.
+ */
+ULONG ConvertFileTime(PFILETIME pFileTime)
+{
+    ULONG       ulOS2FileTime;
+    SYSTEMTIME  SystemTime;
+
+    if (   FileTimeToSystemTime(pFileTime, &SystemTime)
+        && SystemTime.wYear >= 1980 && SystemTime.wYear < (1980 + 0x7F))
+    {
+        ulOS2FileTime =    SystemTime.wDay
+                        | (SystemTime.wMonth << 5)
+                        | (((SystemTime.wYear - 1980) & 0x7F) << (5+4))
+                        | ((SystemTime.wSecond / 2) << (16))
+                        | (SystemTime.wMinute << (16+5))
+                        | (SystemTime.wHour << (16+5+6));
+    }
+    else
+        ulOS2FileTime = 0;
+
+    return ulOS2FileTime;
+}
+
+
+
+APIRET OS2ENTRY         DosQueryPathInfo(
+                            PCSZ        pszPathName,
+                            ULONG       ulInfoLevel,
+                            PVOID       pInfoBuf,
+                            ULONG       cbInfoBuf)
+{
+    APIRET  rc;                         /* Return code. */
+
+    if (!VALIDPTR(pszPathName))
+    {
+        fprintf(stderr, "DosQueryPathInfo: pszPathName is an invalid pointer - %p\n", pszPathName);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (!VALIDPTR(pInfoBuf))
+    {
+        fprintf(stderr, "DosQueryPathInfo: pInfoBuf is an invalid pointer - %p\n", pInfoBuf);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+
+    rc = ERROR_INVALID_PARAMETER;
+    switch (ulInfoLevel)
+    {
+        case FIL_QUERYFULLNAME:
+        {
+            LPTSTR   lpDummy;
+            if (GetFullPathName(pszPathName, cbInfoBuf, pInfoBuf, &lpDummy) > 0)
+                rc = NO_ERROR;
+            else
+                rc = GetLastError();
+            break;
+        }
+
+        case FIL_STANDARD:
+            if (cbInfoBuf == sizeof(FILESTATUS3))
+            {
+                WIN32_FILE_ATTRIBUTE_DATA   fad;
+                
+                if (GetFileAttributesEx(pszPathName, GetFileExInfoStandard, &fad)) //W98, NT4 and above.
+                {
+                    PFILESTATUS3    pfst3 = (PFILESTATUS3)(pInfoBuf);
+                    
+                    if (fad.nFileSizeHigh > 0)
+                        rc = ERROR_BAD_LENGTH;
+                    pfst3->cbFile = pfst3->cbFileAlloc = fad.nFileSizeLow;
+                    pfst3->attrFile = ConvertAttributes(fad.dwFileAttributes);
+                    *(PULONG)(&pfst3->fdateCreation) = ConvertFileTime(&fad.ftCreationTime);
+                    *(PULONG)(&pfst3->fdateLastAccess) = ConvertFileTime(&fad.ftLastAccessTime);
+                    *(PULONG)(&pfst3->fdateLastWrite) = ConvertFileTime(&fad.ftLastWriteTime);
+                    rc = NO_ERROR;
+                }
+                else
+                    rc = GetLastError();
+            }
+            else
+                fprintf(stderr, "DosQueryPathInfo: FIL_STANDARD - invalid structure size (cbInfoBuf=%d)\n", cbInfoBuf);
+            break;
+
+        default:
+            fprintf(stderr, "DosQueryPathInfo: ulInfoLevel=%d not supported\n", ulInfoLevel);
+    }
+
+    return rc;
+}
+            
+
+APIRET OS2ENTRY         DosFindFirst(
+                            PCSZ        pszFileSpec,
+                            PHDIR       phdir,
+                            ULONG       flAttribute,
+                            PVOID       pFindBuf,
+                            ULONG       cbFindBuf,
+                            PULONG      pcFileNames,
+                            ULONG       ulInfoLevel)
+{
+    WIN32_FIND_DATA FindData;           /* Win32 Find data (returned by FindFirstFile) */
+    APIRET          rc;
+
+    if (!VALIDPTR(pszFileSpec))
+    {
+        fprintf(stderr, "DosFindFirst: pszFileSpec - %p\n", pszFileSpec);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (!VALIDPTR(phdir))
+    {
+        fprintf(stderr, "DosFindFirst: phdir - %p\n", phdir);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (!VALIDPTR(pFindBuf))
+    {
+        fprintf(stderr, "DosFindFirst: pfindbuf - %p\n", pFindBuf);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (!VALIDPTR(pcFileNames))
+    {
+        fprintf(stderr, "DosFindFirst: pcFileNames - %p\n", pcFileNames);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (*phdir != HDIR_CREATE)
+    {
+        fprintf(stderr, "DosFindFirst: *phdir != HDIR_CREATE - 0x%08x\n", *phdir);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    switch (ulInfoLevel)
+    {
+        case FIL_STANDARD:
+            if (cbFindBuf < sizeof(FILEFINDBUF3))
+            {
+                fprintf(stderr, "DosFindFirst: unsupported buffer size - %d\n", cbFindBuf);
+                return ERROR_INVALID_PARAMETER;
+            }
+            break;
+
+        default:
+            fprintf(stderr, "DosFindFirst: invalid infolevel %d\n", ulInfoLevel);
+            return ERROR_INVALID_PARAMETER;
+    }
+
+    *phdir = (HDIR)FindFirstFile(pszFileSpec, &FindData);
+    if (*phdir != (HDIR)INVALID_HANDLE_VALUE)
+    {
+        PFILEFINDBUF3   pfindbuf = (PFILEFINDBUF3)pFindBuf;
+        
+        memcpy(pfindbuf->achName, FindData.cFileName, pfindbuf->cchName = strlen(FindData.cFileName) + 1);
+        pfindbuf->cbFile = pfindbuf->cbFileAlloc = FindData.nFileSizeHigh > 0 ? 0xffffffff : FindData.nFileSizeLow;
+        pfindbuf->attrFile = ConvertAttributes(FindData.dwFileAttributes);
+        *(PULONG)(&pfindbuf->fdateCreation) = ConvertFileTime(&FindData.ftCreationTime);
+        *(PULONG)(&pfindbuf->fdateLastAccess) = ConvertFileTime(&FindData.ftLastAccessTime);
+        *(PULONG)(&pfindbuf->fdateLastWrite) = ConvertFileTime(&FindData.ftLastWriteTime);
+        pfindbuf->oNextEntryOffset = 0;
+        *pcFileNames = 1;
+        rc = NO_ERROR;
+    }
+    else
+        rc = GetLastError();
+
+    return rc;
+}
+
+
+APIRET OS2ENTRY         DosFindNext(
+                            HDIR        hDir,
+                            PVOID       pFindBuf,
+                            ULONG       cbFindBuf,
+                            PULONG      pcFileNames)
+{
+    WIN32_FIND_DATA FindData;           /* Win32 Find data (returned by FindFirstFile) */
+    APIRET          rc;
+
+    if (!VALIDPTR(pFindBuf))
+    {
+        fprintf(stderr, "DosFindNext: pfindbuf - %p\n", pFindBuf);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (cbFindBuf < sizeof(FILEFINDBUF3))
+    {
+        fprintf(stderr, "DosFindNext: unsupported buffer size - %d\n", cbFindBuf);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (!VALIDPTR(pcFileNames))
+    {
+        fprintf(stderr, "DosFindNext: pcFileNames - %p\n", pcFileNames);
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (FindNextFile((HANDLE)hDir, &FindData))
+    {
+        PFILEFINDBUF3   pfindbuf = (PFILEFINDBUF3)pFindBuf;
+        
+        memcpy(pfindbuf->achName, FindData.cFileName, pfindbuf->cchName = strlen(FindData.cFileName) + 1);
+        pfindbuf->cbFile = pfindbuf->cbFileAlloc = FindData.nFileSizeHigh > 0 ? 0xffffffff : FindData.nFileSizeLow;
+        pfindbuf->attrFile = ConvertAttributes(FindData.dwFileAttributes);
+        *(PULONG)(&pfindbuf->fdateCreation) = ConvertFileTime(&FindData.ftCreationTime);
+        *(PULONG)(&pfindbuf->fdateLastAccess) = ConvertFileTime(&FindData.ftLastAccessTime);
+        *(PULONG)(&pfindbuf->fdateLastWrite) = ConvertFileTime(&FindData.ftLastWriteTime);
+        pfindbuf->oNextEntryOffset = 0;
+        *pcFileNames = 1;
+        rc = NO_ERROR;
+    }
+    else
+        rc = GetLastError();
+
+    return rc;
+
+}
+
+
+APIRET OS2ENTRY         DosFindClose(
+                            HDIR        hDir)
+{
+    if (FindClose((HANDLE)hDir))
+        return NO_ERROR;
+    return ERROR_INVALID_HANDLE;
+}
+
+
+                   
Index: /tags/kBuild-0.1.4/src/fastdep/os2fake.h
===================================================================
--- /tags/kBuild-0.1.4/src/fastdep/os2fake.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/fastdep/os2fake.h	(revision 1780)
@@ -0,0 +1,197 @@
+/* $Id$
+ * 
+ * Structures, defines and function prototypes for the OS/2 fake library.
+ * 
+ * Copyright (c) 2001 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+ 
+ 
+#ifndef _os2fake_h_
+#define _os2fake_h_
+
+                    
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#ifndef OS2ENTRY
+#define OS2ENTRY    
+#endif
+
+#ifndef CCHMAXPATHCOMP
+#define CCHMAXPATHCOMP          256
+#endif
+
+#ifndef CCHMAXPATH
+#define CCHMAXPATH              260
+#endif
+
+#ifndef FIL_STANDARD
+#define FIL_STANDARD            1
+#define FIL_QUERYEASIZE         2
+#define FIL_QUERYEASFROMLIST    3
+#define FIL_QUERYFULLNAME       5
+#endif
+   
+#define FILE_NORMAL             0x0000
+#define FILE_READONLY           0x0001
+#define FILE_HIDDEN             0x0002
+#define FILE_SYSTEM             0x0004
+#define FILE_DIRECTORY          0x0010
+#define FILE_ARCHIVED           0x0020
+
+#ifndef HDIR_CREATE
+#define HDIR_CREATE             (-1)
+#endif
+
+#ifndef TRUE
+#define TRUE                    1
+#endif
+#ifndef FALSE
+#define FALSE                   0
+#endif
+
+#ifndef NO_ERROR
+#define NO_ERROR                0
+#endif
+
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+typedef char *          PCH;
+
+typedef char *          PSZ;
+typedef const char *    PCSZ;
+
+typedef unsigned long   ULONG;
+typedef ULONG *         PULONG;
+
+typedef unsigned short  USHORT;
+typedef USHORT *        PUSHORT;
+
+#if !defined(_WINDEF_)
+typedef unsigned int    UINT;
+typedef UINT *          PUINT;
+
+typedef unsigned char   UCHAR;
+typedef UCHAR *         PUCHAR;
+
+#if !defined(CHAR)
+typedef char            CHAR;
+typedef CHAR *          PCHAR;
+#endif
+
+typedef unsigned long   BOOL;
+typedef BOOL *          PBOOL;
+#endif
+
+#if !defined(VOID)
+typedef void            VOID;
+#endif
+#if !defined(_WINNT_) && !defined(PVOID)
+typedef VOID *          PVOID;  
+#endif
+
+typedef unsigned long   HDIR;
+typedef HDIR *          PHDIR;
+
+typedef unsigned long   APIRET;
+
+
+typedef struct _FTIME   /* ftime */
+{
+#if defined(__IBMC__) || defined(__IBMCPP__)
+    UINT    twosecs : 5;
+    UINT    minutes : 6;
+    UINT    hours   : 5;
+#else
+    USHORT  twosecs : 5;
+    USHORT  minutes : 6;
+    USHORT  hours   : 5;
+#endif
+} FTIME;
+typedef FTIME *PFTIME;
+
+
+typedef struct _FDATE   /* fdate */
+{
+#if defined(__IBMC__) || defined(__IBMCPP__)
+    UINT    day     : 5;
+    UINT    month   : 4;
+    UINT    year    : 7;
+#else
+    USHORT  day     : 5;
+    USHORT  month   : 4;
+    USHORT  year    : 7;
+#endif
+} FDATE;
+typedef FDATE   *PFDATE;
+
+
+typedef struct _FILESTATUS3     /* fsts3 */
+{
+    FDATE   fdateCreation;
+    FTIME   ftimeCreation;
+    FDATE   fdateLastAccess;
+    FTIME   ftimeLastAccess;
+    FDATE   fdateLastWrite;
+    FTIME   ftimeLastWrite;
+    ULONG   cbFile;
+    ULONG   cbFileAlloc;
+    ULONG   attrFile;
+} FILESTATUS3;
+typedef FILESTATUS3 *PFILESTATUS3;
+
+typedef struct _FILEFINDBUF3    /* findbuf3 */
+{
+    ULONG   oNextEntryOffset;    
+    FDATE   fdateCreation;
+    FTIME   ftimeCreation;
+    FDATE   fdateLastAccess;
+    FTIME   ftimeLastAccess;
+    FDATE   fdateLastWrite;
+    FTIME   ftimeLastWrite;
+    ULONG   cbFile;
+    ULONG   cbFileAlloc;
+    ULONG   attrFile;            
+    UCHAR   cchName;
+    CHAR    achName[CCHMAXPATHCOMP];
+} FILEFINDBUF3;
+typedef FILEFINDBUF3 *PFILEFINDBUF3;
+
+
+/*******************************************************************************
+*   Function Prototypes                                                        *
+*******************************************************************************/
+APIRET OS2ENTRY         DosQueryPathInfo(
+                            PCSZ        pszPathName,
+                            ULONG       ulInfoLevel,
+                            PVOID       pInfoBuf,
+                            ULONG       cbInfoBuf);
+
+APIRET OS2ENTRY         DosFindFirst(
+                            PCSZ        pszFileSpec,
+                            PHDIR       phdir,
+                            ULONG       flAttribute,
+                            PVOID       pFindBuf,
+                            ULONG       cbFindBuf,
+                            PULONG      pcFileNames,
+                            ULONG       ulInfoLevel);
+
+APIRET OS2ENTRY         DosFindNext(
+                            HDIR        hDir,
+                            PVOID       pFindBuf,
+                            ULONG       cbFindBuf,
+                            PULONG      pcFileNames);
+
+APIRET OS2ENTRY         DosFindClose(
+                            HDIR        hDir);
+
+
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/kDepPre/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kDepPre/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kDepPre/Makefile.kmk	(revision 1780)
@@ -0,0 +1,40 @@
+# $Id$
+## @file
+# Sub-makefile for kDepPre, the precompiler based dependency generator.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../..
+include $(KBUILD_PATH)/subheader.kmk
+
+PROGRAMS += kDepPre
+kDepPre_TEMPLATE        = BIN
+kDepPre_LIBS            = $(LIB_KDEP)
+kDepPre_DEFS.linux      = HAVE_FGETC_UNLOCKED=1
+if1of ($(KBUILD_TARGET), win nt)
+kDepPre_DEFS           += NEED_ISBLANK=1 __WIN32__=1
+endif
+kDepPre_SOURCES         = kDepPre.c
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
Index: /tags/kBuild-0.1.4/src/kDepPre/kDepPre.c
===================================================================
--- /tags/kBuild-0.1.4/src/kDepPre/kDepPre.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kDepPre/kDepPre.c	(revision 1780)
@@ -0,0 +1,493 @@
+/* $Id$ */
+/** @file
+ *
+ * kDepPre - Dependency Generator using Precompiler output.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef _MSC_VER
+# include <io.h>
+#else
+# include <unistd.h>
+#endif 
+#include "kDep.h"
+
+#ifdef HAVE_FGETC_UNLOCKED
+# define FGETC(s)   getc_unlocked(s)
+#else
+# define FGETC(s)   fgetc(s)
+#endif
+
+#ifdef NEED_ISBLANK
+# define isblank(ch) ( (unsigned char)(ch) == ' ' || (unsigned char)(ch) == '\t' )
+#endif
+
+
+
+
+/**
+ * Parses the output from a preprocessor of a C-style language.
+ *
+ * @returns 0 on success.
+ * @returns 1 or other approriate exit code on failure.
+ * @param   pInput      Input stream. (probably not seekable)
+ */
+static int ParseCPrecompiler(FILE *pInput)
+{
+    enum
+    {
+        C_DISCOVER = 0,
+        C_SKIP_LINE,
+        C_PARSE_FILENAME,
+        C_EOF
+    } enmMode = C_DISCOVER;
+    PDEP    pDep = NULL;
+    int     ch = 0;
+    char    szBuf[8192];
+
+    for (;;)
+    {
+        switch (enmMode)
+        {
+            /*
+             * Start of line, need to look for '#[[:space]]*line <num> "file"' and '# <num> "file"'.
+             */
+            case C_DISCOVER:
+                /* first find '#' */
+                while ((ch = FGETC(pInput)) != EOF)
+                    if (!isblank(ch))
+                        break;
+                if (ch == '#')
+                {
+                    /* skip spaces */
+                    while ((ch = FGETC(pInput)) != EOF)
+                        if (!isblank(ch))
+                            break;
+
+                    /* check for "line" */
+                    if (ch == 'l')
+                    {
+                        if (    (ch = FGETC(pInput)) == 'i'
+                            &&  (ch = FGETC(pInput)) == 'n'
+                            &&  (ch = FGETC(pInput)) == 'e')
+                        {
+                            ch = FGETC(pInput);
+                            if (isblank(ch))
+                            {
+                                /* skip spaces */
+                                while ((ch = FGETC(pInput)) != EOF)
+                                    if (!isblank(ch))
+                                        break;
+                            }
+                            else
+                                ch = 'x';
+                        }
+                        else
+                            ch = 'x';
+                    }
+
+                    /* line number */
+                    if (ch >= '0' && ch <= '9')
+                    {
+                        /* skip the number following spaces */
+                        while ((ch = FGETC(pInput)) != EOF)
+                            if (!isxdigit(ch))
+                                break;
+                        if (isblank(ch))
+                        {
+                            while ((ch = FGETC(pInput)) != EOF)
+                                if (!isblank(ch))
+                                    break;
+                            /* quoted filename */
+                            if (ch == '"')
+                            {
+                                enmMode = C_PARSE_FILENAME;
+                                break;
+                            }
+                        }
+                    }
+                }
+                enmMode = C_SKIP_LINE;
+                break;
+
+            /*
+             * Skip past the end of the current line.
+             */
+            case C_SKIP_LINE:
+                do
+                {
+                    if (    ch == '\r'
+                        ||  ch == '\n')
+                        break;
+                } while ((ch = FGETC(pInput)) != EOF);
+                enmMode = C_DISCOVER;
+                break;
+
+            /*
+             * Parse the filename.
+             */
+            case C_PARSE_FILENAME:
+            {
+                /* retreive and unescape the filename. */
+                char   *psz = &szBuf[0];
+                while (     (ch = FGETC(pInput)) != EOF
+                       &&   psz < &szBuf[sizeof(szBuf) - 1])
+                {
+                    if (ch == '\\')
+                    {
+                        ch = FGETC(pInput);
+                        switch (ch)
+                        {
+                            case '\\': ch = '/'; break;
+                            case 't':  ch = '\t'; break;
+                            case 'r':  ch = '\r'; break;
+                            case 'n':  ch = '\n'; break;
+                            case 'b':  ch = '\b'; break;
+                            default:
+                                fprintf(stderr, "warning: unknown escape char '%c'\n", ch);
+                                continue;
+
+                        }
+                        *psz++ = ch == '\\' ? '/' : ch;
+                    }
+                    else if (ch != '"')
+                        *psz++ = ch;
+                    else
+                    {
+                        size_t cchFilename = psz - &szBuf[0];
+                        *psz = '\0';
+                        /* compare with current dep, add & switch on mismatch. */
+                        if (    !pDep
+                            ||  pDep->cchFilename != cchFilename
+                            ||  memcmp(pDep->szFilename, szBuf, cchFilename))
+                            pDep = depAdd(szBuf, cchFilename);
+                        break;
+                    }
+                }
+                enmMode = C_SKIP_LINE;
+                break;
+            }
+
+            /*
+             * Handle EOF.
+             */
+            case C_EOF:
+                if (feof(pInput))
+                    return 0;
+                enmMode = C_DISCOVER;
+                break;
+        }
+        if (ch == EOF)
+            enmMode = C_EOF;
+    }
+
+    return 0;
+}
+
+
+static int usage(FILE *pOut,  const char *argv0)
+{
+    fprintf(pOut,
+            "usage: %s [-l=c] -o <output> -t <target> [-f] [-s] < - | <filename> | -e <cmdline> >\n"
+            "   or: %s --help\n"
+            "   or: %s --version\n",
+            argv0, argv0, argv0);
+    return 1;
+}
+
+
+int main(int argc, char *argv[])
+{
+    int         i;
+
+    /* Arguments. */
+    int         iExec = 0;
+    FILE       *pOutput = NULL;
+    const char *pszOutput = NULL;
+    FILE       *pInput = NULL;
+    const char *pszTarget = NULL;
+    int         fStubs = 0;
+    int         fFixCase = 0;
+    /* Argument parsing. */
+    int         fInput = 0;             /* set when we've found input argument. */
+
+    /*
+     * Parse arguments.
+     */
+    if (argc <= 1)
+        return usage(stderr, argv[0]);
+    for (i = 1; i < argc; i++)
+    {
+        if (argv[i][0] == '-')
+        {
+            const char *psz = &argv[i][1];
+            if (*psz == '-')
+            {
+                if (!strcmp(psz, "-help"))
+                    psz = "h";
+                else if (!strcmp(psz, "-version"))
+                    psz = "V";
+            }
+
+            switch (*psz)
+            {
+                /*
+                 * Output file.
+                 */
+                case 'o':
+                {
+                    pszOutput = &argv[i][2];
+                    if (pOutput)
+                    {
+                        fprintf(stderr, "%s: syntax error: only one output file!\n", argv[0]);
+                        return 1;
+                    }
+                    if (!*pszOutput)
+                    {
+                        if (++i >= argc)
+                        {
+                            fprintf(stderr, "%s: syntax error: The '-o' argument is missing the filename.\n", argv[0]);
+                            return 1;
+                        }
+                        pszOutput = argv[i];
+                    }
+                    if (pszOutput[0] == '-' && !pszOutput[1])
+                        pOutput = stdout;
+                    else
+                        pOutput = fopen(pszOutput, "w");
+                    if (!pOutput)
+                    {
+                        fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", argv[0], pszOutput);
+                        return 1;
+                    }
+                    break;
+                }
+
+                /*
+                 * Language spec.
+                 */
+                case 'l':
+                {
+                    const char *psz = &argv[i][2];
+                    if (*psz == '=')
+                        psz++;
+                    if (!strcmp(psz, "c"))
+                        ;
+                    else
+                    {
+                        fprintf(stderr, "%s: error: The '%s' language is not supported.\n", argv[0], psz);
+                        return 1;
+                    }
+                    break;
+                }
+
+                /*
+                 * Target name.
+                 */
+                case 't':
+                {
+                    if (pszTarget)
+                    {
+                        fprintf(stderr, "%s: syntax error: only one target!\n", argv[0]);
+                        return 1;
+                    }
+                    pszTarget = &argv[i][2];
+                    if (!*pszTarget)
+                    {
+                        if (++i >= argc)
+                        {
+                            fprintf(stderr, "%s: syntax error: The '-t' argument is missing the target name.\n", argv[0]);
+                            return 1;
+                        }
+                        pszTarget = argv[i];
+                    }
+                    break;
+                }
+
+                /*
+                 * Exec.
+                 */
+                case 'e':
+                {
+                    if (++i >= argc)
+                    {
+                        fprintf(stderr, "%s: syntax error: The '-e' argument is missing the command.\n", argv[0]);
+                        return 1;
+                    }
+                    iExec = i;
+                    i = argc - 1;
+                    break;
+                }
+
+                /*
+                 * Pipe input.
+                 */
+                case '\0':
+                {
+                    pInput = stdin;
+                    fInput = 1;
+                    break;
+                }
+
+                /*
+                 * Fix case.
+                 */
+                case 'f':
+                {
+                    fFixCase = 1;
+                    break;
+                }
+
+                /*
+                 * Generate stubs.
+                 */
+                case 's':
+                {
+                    fStubs = 1;
+                    break;
+                }
+
+                /*
+                 * The obligatory help and version.
+                 */
+                case 'h':
+                    usage(stdout, argv[0]);
+                    return 0;
+
+                case 'V':
+                    printf("kDepPre - kBuild version %d.%d.%d\n"
+                           "Copyright (C) 2005-2007 Knut St. Osmundsen\n",
+                           KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH);
+                    return 0;
+
+                /*
+                 * Invalid argument.
+                 */
+                default:
+                    fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]);
+                    return usage(stderr, argv[0]);
+            }
+        }
+        else
+        {
+            pInput = fopen(argv[i], "r");
+            if (!pInput)
+            {
+                fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]);
+                return 1;
+            }
+            fInput = 1;
+        }
+
+        /*
+         * End of the line?
+         */
+        if (fInput)
+        {
+            if (++i < argc)
+            {
+                fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", argv[0]);
+                return 1;
+            }
+            break;
+        }
+    }
+
+    /*
+     * Got all we require?
+     */
+    if (!pInput && iExec <= 0)
+    {
+        fprintf(stderr, "%s: syntax error: No input!\n", argv[0]);
+        return 1;
+    }
+    if (!pOutput)
+    {
+        fprintf(stderr, "%s: syntax error: No output!\n", argv[0]);
+        return 1;
+    }
+    if (!pszTarget)
+    {
+        fprintf(stderr, "%s: syntax error: No target!\n", argv[0]);
+        return 1;
+    }
+
+    /*
+     * Spawn process?
+     */
+    if (iExec > 0)
+    {
+        fprintf(stderr, "%s: -e is not yet implemented!\n", argv[0]);
+        return 1;
+    }
+
+    /*
+     * Do the parsing.
+     */
+    i = ParseCPrecompiler(pInput);
+
+    /*
+     * Reap child.
+     */
+    if (iExec > 0)
+    {
+        /* later */
+    }
+
+    /*
+     * Write the dependecy file.
+     */
+    if (!i)
+    {
+        depOptimize(fFixCase);
+        fprintf(pOutput, "%s:", pszTarget);
+        depPrint(pOutput);
+        if (fStubs)
+            depPrintStubs(pOutput);
+    }
+
+    /*
+     * Close the output, delete output on failure.
+     */
+    if (!i && ferror(pOutput))
+    {
+        i = 1;
+        fprintf(stderr, "%s: error: Error writing to '%s'.\n", argv[0], pszOutput);
+    }
+    fclose(pOutput);
+    if (i)
+    {
+        if (unlink(pszOutput))
+            fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", argv[0], pszOutput);
+    }
+
+    return i;
+}
+
Index: /tags/kBuild-0.1.4/src/kObjCache/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kObjCache/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kObjCache/Makefile.kmk	(revision 1780)
@@ -0,0 +1,36 @@
+# $Id: Makefile.kmk 785 2007-01-24 22:21:56Z bird $
+## @file
+# Sub-makefile for kObjCache.
+#
+
+#
+# Copyright (c) 2007-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../..
+include $(PATH_KBUILD)/subheader.kmk
+
+PROGRAMS += kObjCache
+kObjCache_TEMPLATE = BIN
+kObjCache_SOURCES = kObjCache.c
+kObjCache_LIBS = $(LIB_KUTIL)
+
+include $(KBUILD_PATH)/subfooter.kmk
+
Index: /tags/kBuild-0.1.4/src/kObjCache/kObjCache.c
===================================================================
--- /tags/kBuild-0.1.4/src/kObjCache/kObjCache.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kObjCache/kObjCache.c	(revision 1780)
@@ -0,0 +1,3982 @@
+/* $Id$ */
+/** @file
+ * kObjCache - Object Cache.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#if 0
+# define ELECTRIC_HEAP
+# include "../kmk/electric.h"
+#endif
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <ctype.h>
+#ifndef PATH_MAX
+# define PATH_MAX _MAX_PATH /* windows */
+#endif
+#if defined(__OS2__) || defined(__WIN__)
+# include <process.h>
+# include <io.h>
+# ifdef __OS2__
+#  include <unistd.h>
+#  include <sys/wait.h>
+# endif
+# if defined(_MSC_VER)
+#  include <direct.h>
+   typedef intptr_t pid_t;
+# endif
+# ifndef _P_WAIT
+#  define _P_WAIT   P_WAIT
+# endif
+# ifndef _P_NOWAIT
+#  define _P_NOWAIT P_NOWAIT
+# endif
+#else
+# include <unistd.h>
+# include <sys/wait.h>
+# ifndef O_BINARY
+#  define O_BINARY 0
+# endif
+#endif
+#if defined(__WIN__)
+# include <Windows.h>
+#endif
+
+#include "crc32.h"
+#include "md5.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** The max line length in a cache file. */
+#define KOBJCACHE_MAX_LINE_LEN  16384
+#if defined(__WIN__)
+# define PATH_SLASH '\\'
+#else
+# define PATH_SLASH '/'
+#endif
+#if defined(__OS2__) || defined(__WIN__)
+# define IS_SLASH(ch)       ((ch) == '/' || (ch) == '\\')
+# define IS_SLASH_DRV(ch)   ((ch) == '/' || (ch) == '\\' || (ch) == ':')
+#else
+# define IS_SLASH(ch)       ((ch) == '/')
+# define IS_SLASH_DRV(ch)   ((ch) == '/')
+#endif
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Whether verbose output is enabled. */
+static unsigned g_cVerbosityLevel = 0;
+/** What to prefix the errors with. */
+static char g_szErrorPrefix[128];
+
+/** Read buffer shared by the cache components. */
+static char g_szLine[KOBJCACHE_MAX_LINE_LEN + 16];
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static char *MakePathFromDirAndFile(const char *pszName, const char *pszDir);
+static char *CalcRelativeName(const char *pszPath, const char *pszDir);
+static FILE *FOpenFileInDir(const char *pszName, const char *pszDir, const char *pszMode);
+static int UnlinkFileInDir(const char *pszName, const char *pszDir);
+static int RenameFileInDir(const char *pszOldName, const char *pszNewName, const char *pszDir);
+static int DoesFileInDirExist(const char *pszName, const char *pszDir);
+static void *ReadFileInDir(const char *pszName, const char *pszDir, size_t *pcbFile);
+
+
+void FatalMsg(const char *pszFormat, ...)
+{
+    va_list va;
+
+    if (g_szErrorPrefix[0])
+        fprintf(stderr, "%s - fatal error: ", g_szErrorPrefix);
+    else
+        fprintf(stderr, "fatal error: ");
+
+    va_start(va, pszFormat);
+    vfprintf(stderr, pszFormat, va);
+    va_end(va);
+}
+
+
+void FatalDie(const char *pszFormat, ...)
+{
+    va_list va;
+
+    if (g_szErrorPrefix[0])
+        fprintf(stderr, "%s - fatal error: ", g_szErrorPrefix);
+    else
+        fprintf(stderr, "fatal error: ");
+
+    va_start(va, pszFormat);
+    vfprintf(stderr, pszFormat, va);
+    va_end(va);
+
+    exit(1);
+}
+
+
+#if 0 /* unused */
+static void ErrorMsg(const char *pszFormat, ...)
+{
+    va_list va;
+
+    if (g_szErrorPrefix[0])
+        fprintf(stderr, "%s - error: ", g_szErrorPrefix);
+    else
+        fprintf(stderr, "error: ");
+
+    va_start(va, pszFormat);
+    vfprintf(stderr, pszFormat, va);
+    va_end(va);
+}
+#endif /* unused */
+
+
+static void InfoMsg(unsigned uLevel, const char *pszFormat, ...)
+{
+    if (uLevel <= g_cVerbosityLevel)
+    {
+        va_list va;
+
+        if (g_szErrorPrefix[0])
+            fprintf(stderr, "%s - info: ", g_szErrorPrefix);
+        else
+            fprintf(stderr, "info: ");
+
+        va_start(va, pszFormat);
+        vfprintf(stderr, pszFormat, va);
+        va_end(va);
+    }
+}
+
+
+static void SetErrorPrefix(const char *pszPrefix, ...)
+{
+    int cch;
+    va_list va;
+
+    va_start(va, pszPrefix);
+#if defined(_MSC_VER) || defined(__sun__)
+    cch = vsprintf(g_szErrorPrefix, pszPrefix, va);
+    if (cch >= sizeof(g_szErrorPrefix))
+        FatalDie("Buffer overflow setting error prefix!\n");
+#else
+    vsnprintf(g_szErrorPrefix, sizeof(g_szErrorPrefix), pszPrefix, va);
+#endif
+    va_end(va);
+    (void)cch;
+}
+
+#ifndef ELECTRIC_HEAP
+void *xmalloc(size_t cb)
+{
+    void *pv = malloc(cb);
+    if (!pv)
+        FatalDie("out of memory (%d)\n", (int)cb);
+    return pv;
+}
+
+
+void *xrealloc(void *pvOld, size_t cb)
+{
+    void *pv = realloc(pvOld, cb);
+    if (!pv)
+        FatalDie("out of memory (%d)\n", (int)cb);
+    return pv;
+}
+
+
+char *xstrdup(const char *pszIn)
+{
+    char *psz = strdup(pszIn);
+    if (!psz)
+        FatalDie("out of memory (%d)\n", (int)strlen(pszIn));
+    return psz;
+}
+#endif
+
+
+void *xmallocz(size_t cb)
+{
+    void *pv = xmalloc(cb);
+    memset(pv, 0, cb);
+    return pv;
+}
+
+
+
+
+
+/**
+ * Gets the absolute path
+ *
+ * @returns A new heap buffer containing the absolute path.
+ * @param   pszPath     The path to make absolute. (Readonly)
+ */
+static char *AbsPath(const char *pszPath)
+{
+/** @todo this isn't really working as it should... */
+    char szTmp[PATH_MAX];
+#if defined(__OS2__)
+    if (    _fullpath(szTmp, *pszPath ? pszPath : ".", sizeof(szTmp))
+        &&  !realpath(pszPath, szTmp))
+        return xstrdup(pszPath);
+#elif defined(__WIN__)
+    if (!_fullpath(szTmp, *pszPath ? pszPath : ".", sizeof(szTmp)))
+        return xstrdup(pszPath);
+#else
+    if (!realpath(pszPath, szTmp))
+        return xstrdup(pszPath);
+#endif
+   return xstrdup(szTmp);
+}
+
+
+/**
+ * Utility function that finds the filename part in a path.
+ *
+ * @returns Pointer to the file name part (this may be "").
+ * @param   pszPath     The path to parse.
+ */
+static const char *FindFilenameInPath(const char *pszPath)
+{
+    const char *pszFilename = strchr(pszPath, '\0') - 1;
+    if (pszFilename < pszPath)
+        return pszPath;
+    while (     pszFilename > pszPath
+           &&   !IS_SLASH_DRV(pszFilename[-1]))
+        pszFilename--;
+    return pszFilename;
+}
+
+
+/**
+ * Utility function that combines a filename and a directory into a path.
+ *
+ * @returns malloced buffer containing the result.
+ * @param   pszName     The file name.
+ * @param   pszDir      The directory path.
+ */
+static char *MakePathFromDirAndFile(const char *pszName, const char *pszDir)
+{
+    size_t cchName = strlen(pszName);
+    size_t cchDir = strlen(pszDir);
+    char *pszBuf = xmalloc(cchName + cchDir + 2);
+    memcpy(pszBuf, pszDir, cchDir);
+    if (cchDir > 0 && !IS_SLASH_DRV(pszDir[cchDir - 1]))
+        pszBuf[cchDir++] = PATH_SLASH;
+    memcpy(pszBuf + cchDir, pszName, cchName + 1);
+    return pszBuf;
+}
+
+
+/**
+ * Compares two path strings to see if they are identical.
+ *
+ * This doesn't do anything fancy, just the case ignoring and
+ * slash unification.
+ *
+ * @returns 1 if equal, 0 otherwise.
+ * @param   pszPath1    The first path.
+ * @param   pszPath2    The second path.
+ * @param   cch         The number of characters to compare.
+ */
+static int ArePathsIdentical(const char *pszPath1, const char *pszPath2, size_t cch)
+{
+#if defined(__OS2__) || defined(__WIN__)
+    if (strnicmp(pszPath1, pszPath2, cch))
+    {
+        /* Slashes may differ, compare char by char. */
+        const char *psz1 = pszPath1;
+        const char *psz2 = pszPath2;
+        for (;cch; psz1++, psz2++, cch--)
+        {
+            if (*psz1 != *psz2)
+            {
+                if (    tolower(*psz1) != tolower(*psz2)
+                    &&  toupper(*psz1) != toupper(*psz2)
+                    &&  *psz1 != '/'
+                    &&  *psz1 != '\\'
+                    &&  *psz2 != '/'
+                    &&  *psz2 != '\\')
+                    return 0;
+            }
+        }
+    }
+    return 1;
+#else
+    return !strncmp(pszPath1, pszPath2, cch);
+#endif
+}
+
+
+/**
+ * Calculate how to get to pszPath from pszDir.
+ *
+ * @returns The relative path from pszDir to path pszPath.
+ * @param   pszPath     The path to the object.
+ * @param   pszDir      The directory it shall be relative to.
+ */
+static char *CalcRelativeName(const char *pszPath, const char *pszDir)
+{
+    char *pszRet = NULL;
+    char *pszAbsPath = NULL;
+    size_t cchDir = strlen(pszDir);
+
+    /*
+     * This is indeed a bit tricky, so we'll try the easy way first...
+     */
+    if (ArePathsIdentical(pszPath, pszDir, cchDir))
+    {
+        if (pszPath[cchDir])
+            pszRet = (char *)pszPath + cchDir;
+        else
+            pszRet = "./";
+    }
+    else
+    {
+        pszAbsPath = AbsPath(pszPath);
+        if (ArePathsIdentical(pszAbsPath, pszDir, cchDir))
+        {
+            if (pszPath[cchDir])
+                pszRet = pszAbsPath + cchDir;
+            else
+                pszRet = "./";
+        }
+    }
+    if (pszRet)
+    {
+        while (IS_SLASH_DRV(*pszRet))
+            pszRet++;
+        pszRet = xstrdup(pszRet);
+        free(pszAbsPath);
+        return pszRet;
+    }
+
+    /*
+     * Damn, it's gonna be complicated. Deal with that later.
+     */
+    FatalDie("complicated relative path stuff isn't implemented yet. sorry.\n");
+    return NULL;
+}
+
+
+/**
+ * Utility function that combines a filename and directory and passes it onto fopen.
+ *
+ * @returns fopen return value.
+ * @param   pszName     The file name.
+ * @param   pszDir      The directory path.
+ * @param   pszMode     The fopen mode string.
+ */
+static FILE *FOpenFileInDir(const char *pszName, const char *pszDir, const char *pszMode)
+{
+    char *pszPath = MakePathFromDirAndFile(pszName, pszDir);
+    FILE *pFile = fopen(pszPath, pszMode);
+    free(pszPath);
+    return pFile;
+}
+
+
+/**
+ * Utility function that combines a filename and directory and passes it onto open.
+ *
+ * @returns open return value.
+ * @param   pszName     The file name.
+ * @param   pszDir      The directory path.
+ * @param   fFlags      The open flags.
+ * @param   fCreateMode The file creation mode.
+ */
+static int OpenFileInDir(const char *pszName, const char *pszDir, int fFlags, int fCreateMode)
+{
+    char *pszPath = MakePathFromDirAndFile(pszName, pszDir);
+    int fd = open(pszPath, fFlags, fCreateMode);
+    free(pszPath);
+    return fd;
+}
+
+
+
+/**
+ * Deletes a file in a directory.
+ *
+ * @returns whatever unlink returns.
+ * @param   pszName     The file name.
+ * @param   pszDir      The directory path.
+ */
+static int UnlinkFileInDir(const char *pszName, const char *pszDir)
+{
+    char *pszPath = MakePathFromDirAndFile(pszName, pszDir);
+    int rc = unlink(pszPath);
+    free(pszPath);
+    return rc;
+}
+
+
+/**
+ * Renames a file in a directory.
+ *
+ * @returns whatever rename returns.
+ * @param   pszOldName  The new file name.
+ * @param   pszNewName  The old file name.
+ * @param   pszDir      The directory path.
+ */
+static int RenameFileInDir(const char *pszOldName, const char *pszNewName, const char *pszDir)
+{
+    char *pszOldPath = MakePathFromDirAndFile(pszOldName, pszDir);
+    char *pszNewPath = MakePathFromDirAndFile(pszNewName, pszDir);
+    int rc = rename(pszOldPath, pszNewPath);
+    free(pszOldPath);
+    free(pszNewPath);
+    return rc;
+}
+
+
+/**
+ * Check if a (regular) file exists in a directory.
+ *
+ * @returns 1 if it exists and is a regular file, 0 if not.
+ * @param   pszName     The file name.
+ * @param   pszDir      The directory path.
+ */
+static int DoesFileInDirExist(const char *pszName, const char *pszDir)
+{
+    char *pszPath = MakePathFromDirAndFile(pszName, pszDir);
+    struct stat st;
+    int rc = stat(pszPath, &st);
+    free(pszPath);
+#ifdef S_ISREG
+    return !rc && S_ISREG(st.st_mode);
+#elif defined(_MSC_VER)
+    return !rc && (st.st_mode & _S_IFMT) == _S_IFREG;
+#else
+#error "Port me"
+#endif
+}
+
+
+/**
+ * Reads into memory an entire file.
+ *
+ * @returns Pointer to the heap allocation containing the file.
+ *          On failure NULL and errno is returned.
+ * @param   pszName     The file.
+ * @param   pszDir      The directory the file resides in.
+ * @param   pcbFile     Where to store the file size.
+ */
+static void *ReadFileInDir(const char *pszName, const char *pszDir, size_t *pcbFile)
+{
+    int SavedErrno;
+    char *pszPath = MakePathFromDirAndFile(pszName, pszDir);
+    int fd = open(pszPath, O_RDONLY | O_BINARY);
+    if (fd >= 0)
+    {
+        off_t cbFile = lseek(fd, 0, SEEK_END);
+        if (    cbFile >= 0
+            &&  lseek(fd, 0, SEEK_SET) == 0)
+        {
+            char *pb = malloc(cbFile + 1);
+            if (pb)
+            {
+                if (read(fd, pb, cbFile) == cbFile)
+                {
+                    close(fd);
+                    pb[cbFile] = '\0';
+                    *pcbFile = (size_t)cbFile;
+                    return pb;
+                }
+                SavedErrno = errno;
+                free(pb);
+            }
+            else
+                SavedErrno = ENOMEM;
+        }
+        else
+            SavedErrno = errno;
+        close(fd);
+    }
+    else
+        SavedErrno = errno;
+    free(pszPath);
+    errno = SavedErrno;
+    return NULL;
+}
+
+
+/**
+ * Creates a directory including all necessary parent directories.
+ *
+ * @returns 0 on success, -1 + errno on failure.
+ * @param   pszDir      The directory.
+ */
+static int MakePath(const char *pszPath)
+{
+    int iErr = 0;
+    char *pszAbsPath = AbsPath(pszPath);
+    char *psz = pszAbsPath;
+
+    /* Skip to the root slash (PC). */
+    while (!IS_SLASH(*psz) && *psz)
+        psz++;
+/** @todo UNC */
+    for (;;)
+    {
+        char chSaved;
+
+        /* skip slashes */
+        while (IS_SLASH(*psz))
+            psz++;
+        if (!*psz)
+            break;
+
+        /* find the next slash or end and terminate the string. */
+        while (!IS_SLASH(*psz) && *psz)
+            psz++;
+        chSaved = *psz;
+        *psz = '\0';
+
+        /* try create the directory, ignore failure because the directory already exists. */
+        errno = 0;
+#ifdef _MSC_VER
+        if (    _mkdir(pszAbsPath)
+            &&  errno != EEXIST)
+#else
+        if (    mkdir(pszAbsPath, 0777)
+            &&  errno != EEXIST)
+#endif
+        {
+            iErr = errno;
+            break;
+        }
+
+        /* restore the slash/terminator */
+        *psz = chSaved;
+    }
+
+    free(pszAbsPath);
+    return iErr ? -1 : 0;
+}
+
+
+/**
+ * Adds the arguments found in the pszCmdLine string to argument vector.
+ *
+ * The parsing of the pszCmdLine string isn't very sophisticated, no
+ * escaping or quotes.
+ *
+ * @param   pcArgs      Pointer to the argument counter.
+ * @param   ppapszArgs  Pointer to the argument vector pointer.
+ * @param   pszCmdLine  The command line to parse and append.
+ * @param   pszWedgeArg Argument to put infront of anything found in pszCmdLine.
+ */
+static void AppendArgs(int *pcArgs, char ***ppapszArgs, const char *pszCmdLine, const char *pszWedgeArg)
+{
+    int i;
+    int cExtraArgs;
+    const char *psz;
+    char **papszArgs;
+
+    /*
+     * Count the new arguments.
+     */
+    cExtraArgs = 0;
+    psz = pszCmdLine;
+    while (*psz)
+    {
+        while (isspace(*psz))
+            psz++;
+        if (!psz)
+            break;
+        cExtraArgs++;
+        while (!isspace(*psz) && *psz)
+            psz++;
+    }
+    if (!cExtraArgs)
+        return;
+
+    /*
+     * Allocate a new vector that can hold the arguments.
+     * (Reallocating might not work since the argv might not be allocated
+     *  from the heap but off the stack or somewhere... )
+     */
+    i = *pcArgs;
+    *pcArgs = i + cExtraArgs + !!pszWedgeArg;
+    papszArgs = xmalloc((*pcArgs + 1) * sizeof(char *));
+    *ppapszArgs = memcpy(papszArgs, *ppapszArgs, i * sizeof(char *));
+
+    if (pszWedgeArg)
+        papszArgs[i++] = xstrdup(pszWedgeArg);
+
+    psz = pszCmdLine;
+    while (*psz)
+    {
+        size_t cch;
+        const char *pszEnd;
+        while (isspace(*psz))
+            psz++;
+        if (!psz)
+            break;
+        pszEnd = psz;
+        while (!isspace(*pszEnd) && *pszEnd)
+            pszEnd++;
+
+        cch = pszEnd - psz;
+        papszArgs[i] = xmalloc(cch + 1);
+        memcpy(papszArgs[i], psz, cch);
+        papszArgs[i][cch] = '\0';
+
+        i++;
+        psz = pszEnd;
+    }
+
+    papszArgs[i] = NULL;
+}
+
+
+
+
+
+/** A checksum list entry.
+ * We keep a list checksums (of precompiler output) that matches, The planned
+ * matching algorithm doesn't require the precompiler output to be indentical,
+ * only to produce the same object files.
+ */
+typedef struct KOCSUM
+{
+    /** The next checksum. */
+    struct KOCSUM *pNext;
+    /** The crc32 checksum. */
+    uint32_t crc32;
+    /** The MD5 digest. */
+    unsigned char md5[16];
+    /** Valid or not. */
+    unsigned fUsed;
+} KOCSUM;
+/** Pointer to a KOCSUM. */
+typedef KOCSUM *PKOCSUM;
+/** Pointer to a const KOCSUM. */
+typedef const KOCSUM *PCKOCSUM;
+
+
+/**
+ * Temporary context record used when calculating
+ * the checksum of some data.
+ */
+typedef struct KOCSUMCTX
+{
+    /** The MD5 context. */
+    struct MD5Context MD5Ctx;
+} KOCSUMCTX;
+/** Pointer to a check context record. */
+typedef KOCSUMCTX *PKOCSUMCTX;
+
+
+
+/**
+ * Initializes a checksum object with an associated context.
+ *
+ * @param   pSum    The checksum object.
+ * @param   pCtx    The checksum context.
+ */
+static void kOCSumInitWithCtx(PKOCSUM pSum, PKOCSUMCTX pCtx)
+{
+    memset(pSum, 0, sizeof(*pSum));
+    MD5Init(&pCtx->MD5Ctx);
+}
+
+
+/**
+ * Updates the checksum calculation.
+ *
+ * @param   pSum    The checksum.
+ * @param   pCtx    The checksum calcuation context.
+ * @param   pvBuf   The input data to checksum.
+ * @param   cbBuf   The size of the input data.
+ */
+static void kOCSumUpdate(PKOCSUM pSum, PKOCSUMCTX pCtx, const void *pvBuf, size_t cbBuf)
+{
+    /*
+     * Take in relativly small chunks to try keep it in the cache.
+     */
+    const unsigned char *pb = (const unsigned char *)pvBuf;
+    while (cbBuf > 0)
+    {
+        size_t cb = cbBuf >= 128*1024 ? 128*1024 : cbBuf;
+        pSum->crc32 = crc32(pSum->crc32, pb, cb);
+        MD5Update(&pCtx->MD5Ctx, pb, (unsigned)cb);
+        cbBuf -= cb;
+    }
+}
+
+
+/**
+ * Finalizes a checksum calculation.
+ *
+ * @param   pSum    The checksum.
+ * @param   pCtx    The checksum calcuation context.
+ */
+static void kOCSumFinalize(PKOCSUM pSum, PKOCSUMCTX pCtx)
+{
+    MD5Final(&pSum->md5[0], &pCtx->MD5Ctx);
+    pSum->fUsed = 1;
+}
+
+
+/**
+ * Init a check sum chain head.
+ *
+ * @param   pSumHead    The checksum head to init.
+ */
+static void kOCSumInit(PKOCSUM pSumHead)
+{
+    memset(pSumHead, 0, sizeof(*pSumHead));
+}
+
+
+/**
+ * Parses the given string into a checksum head object.
+ *
+ * @returns 0 on success, -1 on format error.
+ * @param   pSumHead    The checksum head to init.
+ * @param   pszVal      The string to initialized it from.
+ */
+static int kOCSumInitFromString(PKOCSUM pSumHead, const char *pszVal)
+{
+    unsigned i;
+    char *pszNext;
+    char *pszMD5;
+
+    memset(pSumHead, 0, sizeof(*pSumHead));
+
+    pszMD5 = strchr(pszVal, ':');
+    if (pszMD5 == NULL)
+        return -1;
+    *pszMD5++ = '\0';
+
+    /* crc32 */
+    pSumHead->crc32 = (uint32_t)strtoul(pszVal, &pszNext, 16);
+    if (pszNext && *pszNext)
+        return -1;
+
+    /* md5 */
+    for (i = 0; i < sizeof(pSumHead->md5) * 2; i++)
+    {
+        unsigned char ch = pszMD5[i];
+        int x;
+        if ((unsigned char)(ch - '0') <= 9)
+            x = ch - '0';
+        else if ((unsigned char)(ch - 'a') <= 5)
+            x = ch - 'a' + 10;
+        else if ((unsigned char)(ch - 'A') <= 5)
+            x = ch - 'A' + 10;
+        else
+            return -1;
+        if (!(i & 1))
+            pSumHead->md5[i >> 1] = x << 4;
+        else
+            pSumHead->md5[i >> 1] |= x;
+    }
+
+    pSumHead->fUsed = 1;
+    return 0;
+}
+
+
+/**
+ * Delete a check sum chain.
+ *
+ * @param   pSumHead    The head of the checksum chain.
+ */
+static void kOCSumDeleteChain(PKOCSUM pSumHead)
+{
+    PKOCSUM pSum = pSumHead->pNext;
+    while (pSum)
+    {
+        void *pvFree = pSum;
+        pSum = pSum->pNext;
+        free(pvFree);
+    }
+    memset(pSumHead, 0, sizeof(*pSumHead));
+}
+
+
+/**
+ * Insert a check sum into the chain.
+ *
+ * @param   pSumHead    The head of the checksum list.
+ * @param   pSumAdd     The checksum to add (duplicate).
+ */
+static void kOCSumAdd(PKOCSUM pSumHead, PCKOCSUM pSumAdd)
+{
+    if (pSumHead->fUsed)
+    {
+        PKOCSUM pNew = xmalloc(sizeof(*pNew));
+        *pNew = *pSumAdd;
+        pNew->pNext = pSumHead->pNext;
+        pNew->fUsed = 1;
+        pSumHead->pNext = pNew;
+    }
+    else
+    {
+        *pSumHead = *pSumAdd;
+        pSumHead->pNext = NULL;
+        pSumHead->fUsed = 1;
+    }
+}
+
+
+/**
+ * Inserts an entrie chain into the given check sum chain.
+ *
+ * @param   pSumHead    The head of the checksum list.
+ * @param   pSumHeadAdd The head of the checksum list to be added.
+ */
+static void kOCSumAddChain(PKOCSUM pSumHead, PCKOCSUM pSumHeadAdd)
+{
+    while (pSumHeadAdd)
+    {
+        kOCSumAdd(pSumHead, pSumHeadAdd);
+        pSumHeadAdd = pSumHeadAdd->pNext;
+    }
+}
+
+
+
+/**
+ * Prints the checksum to the specified stream.
+ *
+ * @param   pSum    The checksum.
+ * @param   pFile   The output file stream
+ */
+static void kOCSumFPrintf(PCKOCSUM pSum, FILE *pFile)
+{
+    fprintf(pFile, "%#x:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+            pSum->crc32,
+            pSum->md5[0], pSum->md5[1], pSum->md5[2], pSum->md5[3],
+            pSum->md5[4], pSum->md5[5], pSum->md5[6], pSum->md5[7],
+            pSum->md5[8], pSum->md5[9], pSum->md5[10], pSum->md5[11],
+            pSum->md5[12], pSum->md5[13], pSum->md5[14], pSum->md5[15]);
+}
+
+
+/**
+ * Displays the checksum (not chain!) using the InfoMsg() method.
+ *
+ * @param   pSum    The checksum.
+ * @param   uLevel  The info message level.
+ * @param   pszMsg  Message to prefix the info message with.
+ */
+static void kOCSumInfo(PCKOCSUM pSum, unsigned uLevel, const char *pszMsg)
+{
+    InfoMsg(uLevel,
+            "%s: crc32=%#010x md5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+            pszMsg,
+            pSum->crc32,
+            pSum->md5[0], pSum->md5[1], pSum->md5[2], pSum->md5[3],
+            pSum->md5[4], pSum->md5[5], pSum->md5[6], pSum->md5[7],
+            pSum->md5[8], pSum->md5[9], pSum->md5[10], pSum->md5[11],
+            pSum->md5[12], pSum->md5[13], pSum->md5[14], pSum->md5[15]);
+}
+
+
+/**
+ * Compares two check sum entries.
+ *
+ * @returns 1 if equal, 0 if not equal.
+ *
+ * @param pSum1     The first checksum.
+ * @param pSum2     The second checksum.
+ */
+static int kOCSumIsEqual(PCKOCSUM pSum1, PCKOCSUM pSum2)
+{
+    if (pSum1 == pSum2)
+        return 1;
+    if (!pSum1 || !pSum2)
+        return 0;
+    if (pSum1->crc32 != pSum2->crc32)
+        return 0;
+    if (memcmp(&pSum1->md5[0], &pSum2->md5[0], sizeof(pSum1->md5)))
+        return 0;
+    return 1;
+}
+
+
+/**
+ * Checks if the specified checksum equals one of the
+ * checksums in the chain.
+ *
+ * @returns 1 if equals one of them, 0 if not.
+ *
+ * @param pSumHead  The checksum chain too look in.
+ * @param pSum      The checksum to look for.
+ * @todo ugly name. fix.
+ */
+static int kOCSumHasEqualInChain(PCKOCSUM pSumHead, PCKOCSUM pSum)
+{
+    for (; pSumHead; pSumHead = pSumHead->pNext)
+    {
+        if (pSumHead == pSum)
+            return 1;
+        if (pSumHead->crc32 != pSum->crc32)
+            continue;
+        if (memcmp(&pSumHead->md5[0], &pSum->md5[0], sizeof(pSumHead->md5)))
+            continue;
+        return 1;
+    }
+    return 0;
+}
+
+
+/**
+ * Checks if the checksum (chain) empty.
+ *
+ * @returns 1 if empty, 0 if it there is one or more checksums.
+ * @param   pSum    The checksum to test.
+ */
+static int kOCSumIsEmpty(PCKOCSUM pSum)
+{
+    return !pSum->fUsed;
+}
+
+
+
+
+
+
+/**
+ * The representation of a cache entry.
+ */
+typedef struct KOCENTRY
+{
+    /** The name of the cache entry. */
+    const char *pszName;
+    /** The dir that all other names are relative to. */
+    char *pszDir;
+    /** The absolute path. */
+    char *pszAbsPath;
+    /** Set if the object needs to be (re)compiled. */
+    unsigned fNeedCompiling;
+    /** Whether the precompiler runs in piped mode. If clear it's file
+     * mode (it could be redirected stdout, but that's essentially the
+     * same from our point of view). */
+    unsigned fPipedPreComp;
+    /** Whether the compiler runs in piped mode (precompiler output on stdin). */
+    unsigned fPipedCompile;
+    /** Cache entry key that's used for some quick digest validation. */
+    uint32_t uKey;
+
+    /** The file data. */
+    struct KOCENTRYDATA
+    {
+        /** The name of file containing the precompiler output. */
+        char *pszCppName;
+        /** Pointer to the precompiler output. */
+        char *pszCppMapping;
+        /** The size of the precompiler output. 0 if not determined. */
+        size_t cbCpp;
+        /** The precompiler output checksums that will produce the cached object. */
+        KOCSUM SumHead;
+        /** The object filename (relative to the cache file). */
+        char *pszObjName;
+        /** The compile argument vector used to build the object. */
+        char **papszArgvCompile;
+        /** The size of the compile  */
+        unsigned cArgvCompile;
+        /** The checksum of the compiler argument vector. */
+        KOCSUM SumCompArgv;
+        /** The target os/arch identifier. */
+        char *pszTarget;
+    }
+    /** The old data.*/
+            Old,
+    /** The new data. */
+            New;
+} KOCENTRY;
+/** Pointer to a KOCENTRY. */
+typedef KOCENTRY *PKOCENTRY;
+/** Pointer to a const KOCENTRY. */
+typedef const KOCENTRY *PCKOCENTRY;
+
+
+/**
+ * Creates a cache entry for the given cache file name.
+ *
+ * @returns Pointer to a cache entry.
+ * @param   pszFilename     The cache file name.
+ */
+static PKOCENTRY kOCEntryCreate(const char *pszFilename)
+{
+    PKOCENTRY pEntry;
+    size_t off;
+
+    /*
+     * Allocate an empty entry.
+     */
+    pEntry = xmallocz(sizeof(*pEntry));
+
+    kOCSumInit(&pEntry->New.SumHead);
+    kOCSumInit(&pEntry->Old.SumHead);
+
+    kOCSumInit(&pEntry->New.SumCompArgv);
+    kOCSumInit(&pEntry->Old.SumCompArgv);
+
+    /*
+     * Setup the directory and cache file name.
+     */
+    pEntry->pszAbsPath = AbsPath(pszFilename);
+    pEntry->pszName = FindFilenameInPath(pEntry->pszAbsPath);
+    off = pEntry->pszName - pEntry->pszAbsPath;
+    if (!off)
+        FatalDie("Failed to find abs path for '%s'!\n", pszFilename);
+    pEntry->pszDir = xmalloc(off);
+    memcpy(pEntry->pszDir, pEntry->pszAbsPath, off - 1);
+    pEntry->pszDir[off - 1] = '\0';
+
+    return pEntry;
+}
+
+
+/**
+ * Destroys the cache entry freeing up all it's resources.
+ *
+ * @param   pEntry      The entry to free.
+ */
+static void kOCEntryDestroy(PKOCENTRY pEntry)
+{
+    free(pEntry->pszDir);
+    free(pEntry->pszAbsPath);
+
+    kOCSumDeleteChain(&pEntry->New.SumHead);
+    kOCSumDeleteChain(&pEntry->Old.SumHead);
+
+    kOCSumDeleteChain(&pEntry->New.SumCompArgv);
+    kOCSumDeleteChain(&pEntry->Old.SumCompArgv);
+
+    free(pEntry->New.pszCppName);
+    free(pEntry->Old.pszCppName);
+
+    free(pEntry->New.pszCppMapping);
+    free(pEntry->Old.pszCppMapping);
+
+    free(pEntry->New.pszObjName);
+    free(pEntry->Old.pszObjName);
+
+    free(pEntry->New.pszTarget);
+    free(pEntry->Old.pszTarget);
+
+    while (pEntry->New.cArgvCompile > 0)
+        free(pEntry->New.papszArgvCompile[--pEntry->New.cArgvCompile]);
+    while (pEntry->Old.cArgvCompile > 0)
+        free(pEntry->Old.papszArgvCompile[--pEntry->Old.cArgvCompile]);
+
+    free(pEntry->New.papszArgvCompile);
+    free(pEntry->Old.papszArgvCompile);
+
+    free(pEntry);
+}
+
+
+/**
+ * Calculates the checksum of an compiler argument vector.
+ *
+ * @param   pEntry          The cache entry.
+ * @param   papszArgv       The argument vector.
+ * @param   cArgc           The number of entries in the vector.
+ * @param   pszIgnorePath   Path to ignore when encountered at the end of arguments.
+ *                          (Not quite safe for simple file names, but what the heck.)
+ * @param   pSum            Where to store the check sum.
+ */
+static void kOCEntryCalcArgvSum(PKOCENTRY pEntry, const char * const *papszArgv, unsigned cArgc,
+                                const char *pszIgnorePath, PKOCSUM pSum)
+{
+    size_t cchIgnorePath = strlen(pszIgnorePath);
+    KOCSUMCTX Ctx;
+    unsigned i;
+
+    kOCSumInitWithCtx(pSum, &Ctx);
+    for (i = 0; i < cArgc; i++)
+    {
+        size_t cch = strlen(papszArgv[i]);
+        if (    cch < cchIgnorePath
+            ||  !ArePathsIdentical(papszArgv[i] + cch - cchIgnorePath, pszIgnorePath, cch))
+            kOCSumUpdate(pSum, &Ctx, papszArgv[i], cch + 1);
+    }
+    kOCSumFinalize(pSum, &Ctx);
+
+    (void)pEntry;
+}
+
+
+/**
+ * Reads and parses the cache file.
+ *
+ * @param   pEntry      The entry to read it into.
+ */
+static void kOCEntryRead(PKOCENTRY pEntry)
+{
+    FILE *pFile;
+    pFile = FOpenFileInDir(pEntry->pszName, pEntry->pszDir, "rb");
+    if (pFile)
+    {
+        InfoMsg(4, "reading cache entry...\n");
+
+        /*
+         * Check the magic.
+         */
+        if (    !fgets(g_szLine, sizeof(g_szLine), pFile)
+            ||  strcmp(g_szLine, "magic=kObjCacheEntry-v0.1.0\n"))
+        {
+            InfoMsg(2, "bad cache file (magic)\n");
+            pEntry->fNeedCompiling = 1;
+        }
+        else
+        {
+            /*
+             * Parse the rest of the file (relaxed order).
+             */
+            unsigned i;
+            int fBad = 0;
+            int fBadBeforeMissing = 1;
+            while (fgets(g_szLine, sizeof(g_szLine), pFile))
+            {
+                char *pszNl;
+                char *pszVal;
+
+                /* Split the line and drop the trailing newline. */
+                pszVal = strchr(g_szLine, '=');
+                if ((fBad = pszVal == NULL))
+                    break;
+                *pszVal++ = '\0';
+
+                pszNl = strchr(pszVal, '\n');
+                if (pszNl)
+                    *pszNl = '\0';
+
+                /* string case on variable name */
+                if (!strcmp(g_szLine, "obj"))
+                {
+                    if ((fBad = pEntry->Old.pszObjName != NULL))
+                        break;
+                    pEntry->Old.pszObjName = xstrdup(pszVal);
+                }
+                else if (!strcmp(g_szLine, "cpp"))
+                {
+                    if ((fBad = pEntry->Old.pszCppName != NULL))
+                        break;
+                    pEntry->Old.pszCppName = xstrdup(pszVal);
+                }
+                else if (!strcmp(g_szLine, "cpp-size"))
+                {
+                    char *pszNext;
+                    if ((fBad = pEntry->Old.cbCpp != 0))
+                        break;
+                    pEntry->Old.cbCpp = strtoul(pszVal, &pszNext, 0);
+                    if ((fBad = pszNext && *pszNext))
+                        break;
+                }
+                else if (!strcmp(g_szLine, "cpp-sum"))
+                {
+                    KOCSUM Sum;
+                    if ((fBad = kOCSumInitFromString(&Sum, pszVal)))
+                        break;
+                    kOCSumAdd(&pEntry->Old.SumHead, &Sum);
+                }
+                else if (!strcmp(g_szLine, "cc-argc"))
+                {
+                    if ((fBad = pEntry->Old.papszArgvCompile != NULL))
+                        break;
+                    pEntry->Old.cArgvCompile = atoi(pszVal); /* if wrong, we'll fail below. */
+                    pEntry->Old.papszArgvCompile = xmallocz((pEntry->Old.cArgvCompile + 1) * sizeof(pEntry->Old.papszArgvCompile[0]));
+                }
+                else if (!strncmp(g_szLine, "cc-argv-#", sizeof("cc-argv-#") - 1))
+                {
+                    char *pszNext;
+                    unsigned i = strtoul(&g_szLine[sizeof("cc-argv-#") - 1], &pszNext, 0);
+                    if ((fBad = i >= pEntry->Old.cArgvCompile || pEntry->Old.papszArgvCompile[i] || (pszNext && *pszNext)))
+                        break;
+                    pEntry->Old.papszArgvCompile[i] = xstrdup(pszVal);
+                }
+                else if (!strcmp(g_szLine, "cc-argv-sum"))
+                {
+                    if ((fBad = !kOCSumIsEmpty(&pEntry->Old.SumCompArgv)))
+                        break;
+                    if ((fBad = kOCSumInitFromString(&pEntry->Old.SumCompArgv, pszVal)))
+                        break;
+                }
+                else if (!strcmp(g_szLine, "target"))
+                {
+                    if ((fBad = pEntry->Old.pszTarget != NULL))
+                        break;
+                    pEntry->Old.pszTarget = xstrdup(pszVal);
+                }
+                else if (!strcmp(g_szLine, "key"))
+                {
+                    char *pszNext;
+                    if ((fBad = pEntry->uKey != 0))
+                        break;
+                    pEntry->uKey = strtoul(pszVal, &pszNext, 0);
+                    if ((fBad = pszNext && *pszNext))
+                        break;
+                }
+                else if (!strcmp(g_szLine, "the-end"))
+                {
+                    fBadBeforeMissing = fBad = strcmp(pszVal, "fine");
+                    break;
+                }
+                else
+                {
+                    fBad = 1;
+                    break;
+                }
+            } /* parse loop */
+
+            /*
+             * Did we find everything and does it add up correctly?
+             */
+            if (!fBad && fBadBeforeMissing)
+            {
+                InfoMsg(2, "bad cache file (no end)\n");
+                fBad = 1;
+            }
+            else
+            {
+                fBadBeforeMissing = fBad;
+                if (    !fBad
+                    &&  (   !pEntry->Old.papszArgvCompile
+                         || !pEntry->Old.pszObjName
+                         || !pEntry->Old.pszCppName
+                         || kOCSumIsEmpty(&pEntry->Old.SumHead)))
+                    fBad = 1;
+                if (!fBad)
+                    for (i = 0; i < pEntry->Old.cArgvCompile; i++)
+                        if ((fBad = !pEntry->Old.papszArgvCompile[i]))
+                            break;
+                if (!fBad)
+                {
+                    KOCSUM Sum;
+                    kOCEntryCalcArgvSum(pEntry, (const char * const *)pEntry->Old.papszArgvCompile,
+                                        pEntry->Old.cArgvCompile, pEntry->Old.pszObjName, &Sum);
+                    fBad = !kOCSumIsEqual(&pEntry->Old.SumCompArgv, &Sum);
+                }
+                if (fBad)
+                    InfoMsg(2, "bad cache file (%s)\n", fBadBeforeMissing ? g_szLine : "missing stuff");
+                else if (ferror(pFile))
+                {
+                    InfoMsg(2, "cache file read error\n");
+                    fBad = 1;
+                }
+
+                /*
+                 * Verify the existance of the object file.
+                 */
+                if (!fBad)
+                {
+                    struct stat st;
+                    char *pszPath = MakePathFromDirAndFile(pEntry->Old.pszObjName, pEntry->pszDir);
+                    if (stat(pszPath, &st) != 0)
+                    {
+                        InfoMsg(2, "failed to stat object file: %s\n", strerror(errno));
+                        fBad = 1;
+                    }
+                    else
+                    {
+                        /** @todo verify size and the timestamp. */
+                    }
+                }
+            }
+            pEntry->fNeedCompiling = fBad;
+        }
+        fclose(pFile);
+    }
+    else
+    {
+        InfoMsg(2, "no cache file\n");
+        pEntry->fNeedCompiling = 1;
+    }
+}
+
+
+/**
+ * Writes the cache file.
+ *
+ * @param   pEntry      The entry to write.
+ */
+static void kOCEntryWrite(PKOCENTRY pEntry)
+{
+    FILE *pFile;
+    PCKOCSUM pSum;
+    unsigned i;
+
+    InfoMsg(4, "writing cache entry '%s'...\n", pEntry->pszName);
+    pFile = FOpenFileInDir(pEntry->pszName, pEntry->pszDir, "wb");
+    if (!pFile)
+        FatalDie("Failed to open '%s' in '%s': %s\n",
+                 pEntry->pszName, pEntry->pszDir, strerror(errno));
+
+#define CHECK_LEN(expr) \
+        do { int cch = expr; if (cch >= KOBJCACHE_MAX_LINE_LEN) FatalDie("Line too long: %d (max %d)\nexpr: %s\n", cch, KOBJCACHE_MAX_LINE_LEN, #expr); } while (0)
+
+    fprintf(pFile, "magic=kObjCacheEntry-v0.1.0\n");
+    CHECK_LEN(fprintf(pFile, "target=%s\n", pEntry->New.pszTarget ? pEntry->New.pszTarget : pEntry->Old.pszTarget));
+    CHECK_LEN(fprintf(pFile, "key=%lu\n", (unsigned long)pEntry->uKey));
+    CHECK_LEN(fprintf(pFile, "obj=%s\n", pEntry->New.pszObjName ? pEntry->New.pszObjName : pEntry->Old.pszObjName));
+    CHECK_LEN(fprintf(pFile, "cpp=%s\n", pEntry->New.pszCppName ? pEntry->New.pszCppName : pEntry->Old.pszCppName));
+    CHECK_LEN(fprintf(pFile, "cpp-size=%lu\n", pEntry->New.pszCppName ? pEntry->New.cbCpp : pEntry->Old.cbCpp));
+
+    if (!kOCSumIsEmpty(&pEntry->New.SumCompArgv))
+    {
+        CHECK_LEN(fprintf(pFile, "cc-argc=%u\n", pEntry->New.cArgvCompile));
+        for (i = 0; i < pEntry->New.cArgvCompile; i++)
+            CHECK_LEN(fprintf(pFile, "cc-argv-#%u=%s\n", i, pEntry->New.papszArgvCompile[i]));
+        fprintf(pFile, "cc-argv-sum=");
+        kOCSumFPrintf(&pEntry->New.SumCompArgv, pFile);
+    }
+    else
+    {
+        CHECK_LEN(fprintf(pFile, "cc-argc=%u\n", pEntry->Old.cArgvCompile));
+        for (i = 0; i < pEntry->Old.cArgvCompile; i++)
+            CHECK_LEN(fprintf(pFile, "cc-argv-#%u=%s\n", i, pEntry->Old.papszArgvCompile[i]));
+        fprintf(pFile, "cc-argv-sum=");
+        kOCSumFPrintf(&pEntry->Old.SumCompArgv, pFile);
+    }
+
+
+    for (pSum = !kOCSumIsEmpty(&pEntry->New.SumHead) ? &pEntry->New.SumHead : &pEntry->Old.SumHead;
+         pSum;
+         pSum = pSum->pNext)
+    {
+        fprintf(pFile, "cpp-sum=");
+        kOCSumFPrintf(pSum, pFile);
+    }
+
+    fprintf(pFile, "the-end=fine\n");
+
+#undef CHECK_LEN
+
+    /*
+     * Flush the file and check for errors.
+     * On failure delete the file so we won't be seeing any invalid
+     * files the next time or upset make with new timestamps.
+     */
+    errno = 0;
+    if (    fflush(pFile) < 0
+        ||  ferror(pFile))
+    {
+        int iErr = errno;
+        fclose(pFile);
+        UnlinkFileInDir(pEntry->pszName, pEntry->pszDir);
+        FatalDie("Stream error occured while writing '%s' in '%s': %s\n",
+                 pEntry->pszName, pEntry->pszDir, strerror(iErr));
+    }
+    fclose(pFile);
+}
+
+
+/**
+ * Checks that the read cache entry is valid.
+ * It sets fNeedCompiling if it isn't.
+ *
+ * @returns 1 valid, 0 invalid.
+ * @param   pEntry      The cache entry.
+ */
+static int kOCEntryCheck(PKOCENTRY pEntry)
+{
+    return !pEntry->fNeedCompiling;
+}
+
+
+/**
+ * Sets the object name and compares it with the old name if present.
+ *
+ * @param   pEntry      The cache entry.
+ * @param   pszObjName  The new object name.
+ */
+static void kOCEntrySetCompileObjName(PKOCENTRY pEntry, const char *pszObjName)
+{
+    assert(!pEntry->New.pszObjName);
+    pEntry->New.pszObjName = CalcRelativeName(pszObjName, pEntry->pszDir);
+
+    if (    !pEntry->fNeedCompiling
+        &&  (   !pEntry->Old.pszObjName
+             || strcmp(pEntry->New.pszObjName, pEntry->Old.pszObjName)))
+    {
+        InfoMsg(2, "object file name differs\n");
+        pEntry->fNeedCompiling = 1;
+    }
+
+    if (    !pEntry->fNeedCompiling
+        &&  !DoesFileInDirExist(pEntry->New.pszObjName, pEntry->pszDir))
+    {
+        InfoMsg(2, "object file doesn't exist\n");
+        pEntry->fNeedCompiling = 1;
+    }
+}
+
+
+/**
+ * Set the new compiler args, calc their checksum, and comparing them with any old ones.
+ *
+ * @param   pEntry              The cache entry.
+ * @param   papszArgvCompile    The new argument vector for compilation.
+ * @param   cArgvCompile        The number of arguments in the vector.
+ *
+ * @remark  Must call kOCEntrySetCompileObjName before this function!
+ */
+static void kOCEntrySetCompileArgv(PKOCENTRY pEntry, const char * const *papszArgvCompile, unsigned cArgvCompile)
+{
+    unsigned i;
+
+    /* call me only once! */
+    assert(!pEntry->New.cArgvCompile);
+    /* call kOCEntrySetCompilerObjName first! */
+    assert(pEntry->New.pszObjName);
+
+    /*
+     * Copy the argument vector and calculate the checksum.
+     */
+    pEntry->New.cArgvCompile = cArgvCompile;
+    pEntry->New.papszArgvCompile = xmalloc((cArgvCompile + 1) * sizeof(pEntry->New.papszArgvCompile[0]));
+    for (i = 0; i < cArgvCompile; i++)
+        pEntry->New.papszArgvCompile[i] = xstrdup(papszArgvCompile[i]);
+    pEntry->New.papszArgvCompile[i] = NULL; /* for exev/spawnv */
+
+    kOCEntryCalcArgvSum(pEntry, papszArgvCompile, cArgvCompile, pEntry->New.pszObjName, &pEntry->New.SumCompArgv);
+    kOCSumInfo(&pEntry->New.SumCompArgv, 4, "comp-argv");
+
+    /*
+     * Compare with the old argument vector.
+     */
+    if (    !pEntry->fNeedCompiling
+        &&  !kOCSumIsEqual(&pEntry->New.SumCompArgv, &pEntry->Old.SumCompArgv))
+    {
+        InfoMsg(2, "compiler args differs\n");
+        pEntry->fNeedCompiling = 1;
+    }
+}
+
+
+/**
+ * Sets the arch/os target and compares it with the old name if present.
+ *
+ * @param   pEntry      The cache entry.
+ * @param   pszObjName  The new object name.
+ */
+static void kOCEntrySetTarget(PKOCENTRY pEntry, const char *pszTarget)
+{
+    assert(!pEntry->New.pszTarget);
+    pEntry->New.pszTarget = xstrdup(pszTarget);
+
+    if (    !pEntry->fNeedCompiling
+        &&  (   !pEntry->Old.pszTarget
+             || strcmp(pEntry->New.pszTarget, pEntry->Old.pszTarget)))
+    {
+        InfoMsg(2, "target differs\n");
+        pEntry->fNeedCompiling = 1;
+    }
+}
+
+
+/**
+ * Sets the precompiler output filename.
+ * We don't generally care if this matches the old name or not.
+ *
+ * @param   pEntry      The cache entry.
+ * @param   pszCppName  The precompiler output filename.
+ */
+static void kOCEntrySetCppName(PKOCENTRY pEntry, const char *pszCppName)
+{
+    assert(!pEntry->New.pszCppName);
+    pEntry->New.pszCppName = CalcRelativeName(pszCppName, pEntry->pszDir);
+}
+
+
+/**
+ * Sets the piped mode of the precompiler and compiler.
+ *
+ * @param   pEntry                  The cache entry.
+ * @param   fRedirPreCompStdOut     Whether the precompiler is in piped mode.
+ * @param   fRedirCompileStdIn      Whether the compiler is in piped mode.
+ */
+static void kOCEntrySetPipedMode(PKOCENTRY pEntry, int fRedirPreCompStdOut, int fRedirCompileStdIn)
+{
+    pEntry->fPipedPreComp = fRedirPreCompStdOut;
+    pEntry->fPipedCompile = fRedirCompileStdIn;
+}
+
+
+/**
+ * Spawns a child in a synchronous fashion.
+ * Terminating on failure.
+ *
+ * @param   papszArgv       Argument vector. The cArgv element is NULL.
+ * @param   cArgv           The number of arguments in the vector.
+ */
+static void kOCEntrySpawn(PCKOCENTRY pEntry, const char * const *papszArgv, unsigned cArgv, const char *pszMsg, const char *pszStdOut)
+{
+#if defined(__OS2__) || defined(__WIN__)
+    intptr_t rc;
+    int fdStdOut = -1;
+    if (pszStdOut)
+    {
+        int fdReDir;
+        fdStdOut = dup(STDOUT_FILENO);
+        close(STDOUT_FILENO);
+        fdReDir = open(pszStdOut, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+        if (fdReDir < 0)
+            FatalDie("%s - failed to create stdout redirection file '%s': %s\n",
+                     pszMsg, pszStdOut, strerror(errno));
+
+        if (fdReDir != STDOUT_FILENO)
+        {
+            if (dup2(fdReDir, STDOUT_FILENO) < 0)
+                FatalDie("%s - dup2 failed: %s\n", pszMsg, strerror(errno));
+            close(fdReDir);
+        }
+    }
+
+    errno = 0;
+    rc = _spawnvp(_P_WAIT, papszArgv[0], papszArgv);
+    if (rc < 0)
+        FatalDie("%s - _spawnvp failed (rc=0x%p): %s\n", pszMsg, rc, strerror(errno));
+    if (rc > 0)
+        FatalDie("%s - failed rc=%d\n", pszMsg, (int)rc);
+    if (fdStdOut)
+    {
+        close(STDOUT_FILENO);
+        fdStdOut = dup2(fdStdOut, STDOUT_FILENO);
+        close(fdStdOut);
+    }
+
+#else
+    int iStatus;
+    pid_t pidWait;
+    pid_t pid = fork();
+    if (!pid)
+    {
+        if (pszStdOut)
+        {
+            int fdReDir;
+
+            close(STDOUT_FILENO);
+            fdReDir = open(pszStdOut, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+            if (fdReDir < 0)
+                FatalDie("%s - failed to create stdout redirection file '%s': %s\n",
+                         pszMsg, pszStdOut, strerror(errno));
+            if (fdReDir != STDOUT_FILENO)
+            {
+                if (dup2(fdReDir, STDOUT_FILENO) < 0)
+                    FatalDie("%s - dup2 failed: %s\n", pszMsg, strerror(errno));
+                close(fdReDir);
+            }
+        }
+
+        execvp(papszArgv[0], (char **)papszArgv);
+        FatalDie("%s - execvp failed: %s\n",
+                 pszMsg, strerror(errno));
+    }
+    if (pid == -1)
+        FatalDie("%s - fork() failed: %s\n", pszMsg, strerror(errno));
+
+    pidWait = waitpid(pid, &iStatus, 0);
+    while (pidWait < 0 && errno == EINTR)
+        pidWait = waitpid(pid, &iStatus, 0);
+    if (pidWait != pid)
+        FatalDie("%s - waitpid failed rc=%d: %s\n",
+                 pszMsg, pidWait, strerror(errno));
+    if (!WIFEXITED(iStatus))
+        FatalDie("%s - abended (iStatus=%#x)\n", pszMsg, iStatus);
+    if (WEXITSTATUS(iStatus))
+        FatalDie("%s - failed with rc %d\n", pszMsg, WEXITSTATUS(iStatus));
+#endif
+
+     (void)pEntry; (void)cArgv;
+}
+
+
+/**
+ * Spawns child with optional redirection of stdin and stdout.
+ *
+ * @param   pEntry          The cache entry.
+ * @param   papszArgv       Argument vector. The cArgv element is NULL.
+ * @param   cArgv           The number of arguments in the vector.
+ * @param   fdStdIn         Child stdin, -1 if it should inherit our stdin. Will be closed.
+ * @param   fdStdOut        Child stdout, -1 if it should inherit our stdout. Will be closed.
+ * @param   pszMsg          Message to start the info/error messages with.
+ */
+static pid_t kOCEntrySpawnChild(PCKOCENTRY pEntry, const char * const *papszArgv, unsigned cArgv, int fdStdIn, int fdStdOut, const char *pszMsg)
+{
+    pid_t pid;
+    int fdSavedStdOut = -1;
+    int fdSavedStdIn = -1;
+
+    /*
+     * Setup redirection.
+     */
+    if (fdStdOut != -1 && fdStdOut != STDOUT_FILENO)
+    {
+        fdSavedStdOut = dup(STDOUT_FILENO);
+        if (dup2(fdStdOut, STDOUT_FILENO) < 0)
+            FatalDie("%s - dup2(,1) failed: %s\n", pszMsg, strerror(errno));
+        close(fdStdOut);
+#ifndef __WIN__
+        fcntl(fdSavedStdOut, F_SETFD, FD_CLOEXEC);
+#endif
+    }
+    if (fdStdIn != -1 && fdStdIn != STDIN_FILENO)
+    {
+        fdSavedStdIn = dup(STDIN_FILENO);
+        if (dup2(fdStdIn, STDIN_FILENO) < 0)
+            FatalDie("%s - dup2(,0) failed: %s\n", pszMsg, strerror(errno));
+        close(fdStdIn);
+#ifndef __WIN__
+        fcntl(fdSavedStdIn, F_SETFD, FD_CLOEXEC);
+#endif
+    }
+
+    /*
+     * Create the child process.
+     */
+#if defined(__OS2__) || defined(__WIN__)
+    errno = 0;
+    pid = _spawnvp(_P_NOWAIT, papszArgv[0], papszArgv);
+    if (pid == -1)
+        FatalDie("precompile - _spawnvp failed: %s\n", strerror(errno));
+
+#else
+    pid = fork();
+    if (!pid)
+    {
+        execvp(papszArgv[0], (char **)papszArgv);
+        FatalDie("precompile - execvp failed: %s\n", strerror(errno));
+    }
+    if (pid == -1)
+        FatalDie("precompile - fork() failed: %s\n", strerror(errno));
+#endif
+
+    /*
+     * Restore stdout & stdin.
+     */
+    if (fdSavedStdIn != -1)
+    {
+        close(STDIN_FILENO);
+        dup2(fdStdOut, STDIN_FILENO);
+        close(fdSavedStdIn);
+    }
+    if (fdSavedStdOut != -1)
+    {
+        close(STDOUT_FILENO);
+        dup2(fdSavedStdOut, STDOUT_FILENO);
+        close(fdSavedStdOut);
+    }
+
+    InfoMsg(3, "%s - spawned %ld\n", pszMsg, (long)pid);
+    (void)cArgv;
+    (void)pEntry;
+    return pid;
+}
+
+
+/**
+ * Waits for a child and exits fatally if the child failed in any way.
+ *
+ * @param   pEntry      The cache entry.
+ * @param   pid         The child to wait for.
+ * @param   pszMsg      Message to start the info/error messages with.
+ */
+static void kOCEntryWaitChild(PCKOCENTRY pEntry, pid_t pid, const char *pszMsg)
+{
+    int iStatus = -1;
+    pid_t pidWait;
+    InfoMsg(3, "%s - wait-child %ld\n", pszMsg, (long)pid);
+
+#ifdef __WIN__
+    pidWait = _cwait(&iStatus, pid, _WAIT_CHILD);
+    if (pidWait == -1)
+        FatalDie("%s - waitpid failed: %s\n", pszMsg, strerror(errno));
+    if (iStatus)
+        FatalDie("%s - failed with rc %d\n", pszMsg, iStatus);
+#else
+    pidWait = waitpid(pid, &iStatus, 0);
+    while (pidWait < 0 && errno == EINTR)
+        pidWait = waitpid(pid, &iStatus, 0);
+    if (pidWait != pid)
+        FatalDie("%s - waitpid failed rc=%d: %s\n", pidWait, strerror(errno));
+    if (!WIFEXITED(iStatus))
+        FatalDie("%s - abended (iStatus=%#x)\n", pszMsg, iStatus);
+    if (WEXITSTATUS(iStatus))
+        FatalDie("%s - failed with rc %d\n", pszMsg, WEXITSTATUS(iStatus));
+#endif
+    (void)pEntry;
+}
+
+
+/**
+ * Creates a pipe for setting up redirected stdin/stdout.
+ *
+ * @param   pEntry          The cache entry.
+ * @param   pFDs            Where to store the two file descriptors.
+ * @param   pszMsg          The operation message for info/error messages.
+ */
+static void kOCEntryCreatePipe(PKOCENTRY pEntry, int *pFDs, const char *pszMsg)
+{
+    pFDs[0] = pFDs[1] = -1;
+#if defined(__WIN__)
+    if (_pipe(pFDs, 0, _O_NOINHERIT | _O_BINARY) < 0)
+#else
+    if (pipe(pFDs) < 0)
+#endif
+        FatalDie("%s - pipe failed: %s\n", pszMsg, strerror(errno));
+#if !defined(__WIN__)
+    fcntl(pFDs[0], F_SETFD, FD_CLOEXEC);
+    fcntl(pFDs[1], F_SETFD, FD_CLOEXEC);
+#endif
+
+    (void)pEntry;
+}
+
+
+/**
+ * Spawns a child that produces output to stdout.
+ *
+ * @param   papszArgv       Argument vector. The cArgv element is NULL.
+ * @param   cArgv           The number of arguments in the vector.
+ * @param   pszMsg          The operation message for info/error messages.
+ * @param   pfnConsumer     Pointer to a consumer callback function that is responsible
+ *                          for servicing the child output and closing the pipe.
+ */
+static void kOCEntrySpawnProducer(PKOCENTRY pEntry, const char * const *papszArgv, unsigned cArgv, const char *pszMsg,
+                                  void (*pfnConsumer)(PKOCENTRY, int))
+{
+    int fds[2];
+    pid_t pid;
+
+    kOCEntryCreatePipe(pEntry, fds, pszMsg);
+    pid = kOCEntrySpawnChild(pEntry, papszArgv, cArgv, -1, fds[1 /* write */], pszMsg);
+
+    pfnConsumer(pEntry, fds[0 /* read */]);
+
+    kOCEntryWaitChild(pEntry, pid, pszMsg);
+}
+
+
+/**
+ * Spawns a child that consumes input on stdin.
+ *
+ * @param   papszArgv       Argument vector. The cArgv element is NULL.
+ * @param   cArgv           The number of arguments in the vector.
+ * @param   pszMsg          The operation message for info/error messages.
+ * @param   pfnProducer     Pointer to a producer callback function that is responsible
+ *                          for serving the child input and closing the pipe.
+ */
+static void kOCEntrySpawnConsumer(PKOCENTRY pEntry, const char * const *papszArgv, unsigned cArgv, const char *pszMsg,
+                                  void (*pfnProducer)(PKOCENTRY, int))
+{
+    int fds[2];
+    pid_t pid;
+
+    kOCEntryCreatePipe(pEntry, fds, pszMsg);
+    pid = kOCEntrySpawnChild(pEntry, papszArgv, cArgv, fds[0 /* read */], -1, pszMsg);
+
+    pfnProducer(pEntry, fds[1 /* write */]);
+
+    kOCEntryWaitChild(pEntry, pid, pszMsg);
+}
+
+
+/**
+ * Spawns two child processes, one producing output and one consuming.
+ * Terminating on failure.
+ *
+ * @param   papszArgv       Argument vector. The cArgv element is NULL.
+ * @param   cArgv           The number of arguments in the vector.
+ * @param   pszMsg          The operation message for info/error messages.
+ * @param   pfnConsumer     Pointer to a consumer callback function that is responsible
+ *                          for servicing the child output and closing the pipe.
+ */
+static void kOCEntrySpawnTee(PKOCENTRY pEntry, const char * const *papszProdArgv, unsigned cProdArgv,
+                             const char * const *papszConsArgv, unsigned cConsArgv,
+                             const char *pszMsg, void (*pfnTeeConsumer)(PKOCENTRY, int, int))
+{
+    int fds[2];
+    int fdIn, fdOut;
+    pid_t pidProducer, pidConsumer;
+
+    /*
+     * The producer.
+     */
+    kOCEntryCreatePipe(pEntry, fds, pszMsg);
+    pidConsumer = kOCEntrySpawnChild(pEntry, papszProdArgv, cProdArgv, -1, fds[1 /* write */], pszMsg);
+    fdIn = fds[0 /* read */];
+
+    /*
+     * The consumer.
+     */
+    kOCEntryCreatePipe(pEntry, fds, pszMsg);
+    pidProducer = kOCEntrySpawnChild(pEntry, papszConsArgv, cConsArgv, fds[0 /* read */], -1, pszMsg);
+    fdOut = fds[1 /* write */];
+
+    /*
+     * Hand it on to the tee consumer.
+     */
+    pfnTeeConsumer(pEntry, fdIn, fdOut);
+
+    /*
+     * Reap the children.
+     */
+    kOCEntryWaitChild(pEntry, pidProducer, pszMsg);
+    kOCEntryWaitChild(pEntry, pidConsumer, pszMsg);
+}
+
+
+/**
+ * Reads the output from the precompiler.
+ *
+ * @param   pEntry      The cache entry. New.cbCpp and New.pszCppMapping will be updated.
+ * @param   pWhich      Specifies what to read (old/new).
+ * @param   fNonFatal   Whether failure is fatal or not.
+ */
+static int kOCEntryReadCppOutput(PKOCENTRY pEntry, struct KOCENTRYDATA *pWhich, int fNonFatal)
+{
+    pWhich->pszCppMapping = ReadFileInDir(pWhich->pszCppName, pEntry->pszDir, &pWhich->cbCpp);
+    if (!pWhich->pszCppMapping)
+    {
+        if (!fNonFatal)
+            FatalDie("failed to open/read '%s' in '%s': %s\n",
+                     pWhich->pszCppName, pEntry->pszDir, strerror(errno));
+        InfoMsg(2, "failed to open/read '%s' in '%s': %s\n",
+                pWhich->pszCppName, pEntry->pszDir, strerror(errno));
+        return -1;
+    }
+
+    InfoMsg(3, "precompiled file is %lu bytes long\n", (unsigned long)pWhich->cbCpp);
+    return 0;
+}
+
+
+/**
+ * Worker for kOCEntryPreCompile and calculates the checksum of
+ * the precompiler output.
+ *
+ * @param   pEntry      The cache entry. NewSum will be updated.
+ */
+static void kOCEntryCalcChecksum(PKOCENTRY pEntry)
+{
+    KOCSUMCTX Ctx;
+    kOCSumInitWithCtx(&pEntry->New.SumHead, &Ctx);
+    kOCSumUpdate(&pEntry->New.SumHead, &Ctx, pEntry->New.pszCppMapping, pEntry->New.cbCpp);
+    kOCSumFinalize(&pEntry->New.SumHead, &Ctx);
+    kOCSumInfo(&pEntry->New.SumHead, 4, "cpp (file)");
+}
+
+
+/**
+ * This consumes the precompiler output and checksums it.
+ *
+ * @param   pEntry  The cache entry.
+ * @param   fdIn    The precompiler output pipe.
+ * @param   fdOut   The compiler input pipe, -1 if no compiler.
+ */
+static void kOCEntryPreCompileConsumer(PKOCENTRY pEntry, int fdIn)
+{
+    KOCSUMCTX Ctx;
+    long cbLeft;
+    long cbAlloc;
+    char *psz;
+
+    kOCSumInitWithCtx(&pEntry->New.SumHead, &Ctx);
+    cbAlloc = pEntry->Old.cbCpp ? ((long)pEntry->Old.cbCpp + 4*1024*1024 + 4096) & ~(4*1024*1024 - 1) : 4*1024*1024;
+    cbLeft = cbAlloc;
+    pEntry->New.pszCppMapping = psz = xmalloc(cbAlloc);
+    for (;;)
+    {
+        /*
+         * Read data from the pipe.
+         */
+        long cbRead = read(fdIn, psz, cbLeft - 1);
+        if (!cbRead)
+            break;
+        if (cbRead < 0)
+        {
+            if (errno == EINTR)
+                continue;
+            FatalDie("precompile - read(%d,,%ld) failed: %s\n",
+                     fdIn, (long)cbLeft, strerror(errno));
+        }
+
+        /*
+         * Process the data.
+         */
+        psz[cbRead] = '\0';
+        kOCSumUpdate(&pEntry->New.SumHead, &Ctx, psz, cbRead);
+
+        /*
+         * Advance.
+         */
+        psz += cbRead;
+        cbLeft -= cbRead;
+        if (cbLeft <= 1)
+        {
+            size_t off = psz - pEntry->New.pszCppMapping;
+            cbLeft = 4*1024*1024;
+            cbAlloc += cbLeft;
+            pEntry->New.pszCppMapping = xrealloc(pEntry->New.pszCppMapping, cbAlloc);
+            psz = pEntry->New.pszCppMapping + off;
+        }
+    }
+
+    close(fdIn);
+    pEntry->New.cbCpp = cbAlloc - cbLeft;
+    kOCSumFinalize(&pEntry->New.SumHead, &Ctx);
+    kOCSumInfo(&pEntry->New.SumHead, 4, "cpp (pipe)");
+}
+
+
+
+
+/**
+ * Run the precompiler and calculate the checksum of the output.
+ *
+ * @param   pEntry              The cache entry.
+ * @param   papszArgvPreComp    The argument vector for executing precompiler. The cArgvPreComp'th argument must be NULL.
+ * @param   cArgvPreComp        The number of arguments.
+ */
+static void kOCEntryPreCompile(PKOCENTRY pEntry, const char * const *papszArgvPreComp, unsigned cArgvPreComp)
+{
+    /*
+     * If we're executing the precompiler in piped mode, it's relatively simple.
+     */
+    if (pEntry->fPipedPreComp)
+        kOCEntrySpawnProducer(pEntry, papszArgvPreComp, cArgvPreComp, "precompile",
+                              kOCEntryPreCompileConsumer);
+    else
+    {
+        /*
+         * Rename the old precompiled output to '-old' so the precompiler won't
+         * overwrite it when we execute it.
+         */
+        if (    pEntry->Old.pszCppName
+            &&  DoesFileInDirExist(pEntry->Old.pszCppName, pEntry->pszDir))
+        {
+            size_t cch = strlen(pEntry->Old.pszCppName);
+            char *psz = xmalloc(cch + sizeof("-old"));
+            memcpy(psz, pEntry->Old.pszCppName, cch);
+            memcpy(psz + cch, "-old", sizeof("-old"));
+
+            InfoMsg(3, "renaming '%s' to '%s' in '%s'\n", pEntry->Old.pszCppName, psz, pEntry->pszDir);
+            UnlinkFileInDir(psz, pEntry->pszDir);
+            if (RenameFileInDir(pEntry->Old.pszCppName, psz, pEntry->pszDir))
+                FatalDie("failed to rename '%s' -> '%s' in '%s': %s\n",
+                         pEntry->Old.pszCppName, psz, pEntry->pszDir, strerror(errno));
+            free(pEntry->Old.pszCppName);
+            pEntry->Old.pszCppName = psz;
+        }
+
+        /*
+         * Precompile it and calculate the checksum on the output.
+         */
+        InfoMsg(3, "precompiling -> '%s'...\n", pEntry->New.pszCppName);
+        kOCEntrySpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", NULL);
+        kOCEntryReadCppOutput(pEntry, &pEntry->New, 0 /* fatal */);
+        kOCEntryCalcChecksum(pEntry);
+    }
+}
+
+
+/**
+ * Worker function for kOCEntryTeeConsumer and kOCEntryCompileIt that
+ * writes the precompiler output to disk.
+ *
+ * @param   pEntry      The cache entry.
+ * @param   fFreeIt     Whether we can free it after writing it or not.
+ */
+static void kOCEntryWriteCppOutput(PKOCENTRY pEntry, int fFreeIt)
+{
+    /*
+     * Remove old files.
+     */
+    if (pEntry->Old.pszCppName)
+        UnlinkFileInDir(pEntry->Old.pszCppName, pEntry->pszDir);
+    if (pEntry->New.pszCppName)
+        UnlinkFileInDir(pEntry->New.pszCppName, pEntry->pszDir);
+
+    /*
+     * Write it to disk if we've got a file name.
+     */
+    if (pEntry->New.pszCppName)
+    {
+        long cbLeft;
+        char *psz;
+        int fd = OpenFileInDir(pEntry->New.pszCppName, pEntry->pszDir,
+                               O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+        if (fd == -1)
+            FatalDie("Failed to create '%s' in '%s': %s\n",
+                     pEntry->New.pszCppName, pEntry->pszDir, strerror(errno));
+        psz = pEntry->New.pszCppMapping;
+        cbLeft = (long)pEntry->New.cbCpp;
+        while (cbLeft > 0)
+        {
+            long cbWritten = write(fd, psz, cbLeft);
+            if (cbWritten < 0)
+            {
+                int iErr = errno;
+                if (iErr == EINTR)
+                    continue;
+                close(fd);
+                UnlinkFileInDir(pEntry->New.pszCppName, pEntry->pszDir);
+                FatalDie("error writing '%s' in '%s': %s\n",
+                         pEntry->New.pszCppName, pEntry->pszDir, strerror(iErr));
+            }
+
+            psz += cbWritten;
+            cbLeft -= cbWritten;
+        }
+        close(fd);
+    }
+
+    /*
+     * Free it.
+     */
+    if (fFreeIt)
+    {
+        free(pEntry->New.pszCppMapping);
+        pEntry->New.pszCppMapping = NULL;
+    }
+}
+
+
+/**
+ * kOCEntrySpawnConsumer callback that passes the precompiler
+ * output to the compiler and writes it to the disk (latter only when necesary).
+ *
+ * @param   pEntry      The cache entry.
+ * @param   fdOut       The pipe handle connected to the childs stdin.
+ */
+static void kOCEntryCompileProducer(PKOCENTRY pEntry, int fdOut)
+{
+    const char *psz = pEntry->New.pszCppMapping;
+    long cbLeft = (long)pEntry->New.cbCpp;
+    while (cbLeft > 0)
+    {
+        long cbWritten = write(fdOut, psz, cbLeft);
+        if (cbWritten < 0)
+        {
+            if (errno == EINTR)
+                continue;
+            FatalDie("compile - write(%d,,%ld) failed: %s\n", fdOut, cbLeft, strerror(errno));
+        }
+        psz += cbWritten;
+        cbLeft -= cbWritten;
+    }
+    close(fdOut);
+
+    if (pEntry->fPipedPreComp)
+        kOCEntryWriteCppOutput(pEntry, 1 /* free it */);
+}
+
+
+/**
+ * Does the actual compiling.
+ *
+ * @param   pEntry      The cache entry.
+ */
+static void kOCEntryCompileIt(PKOCENTRY pEntry)
+{
+    /*
+     * Delete the object files and free old cpp output that's no longer needed.
+     */
+    if (pEntry->Old.pszObjName)
+        UnlinkFileInDir(pEntry->Old.pszObjName, pEntry->pszDir);
+    UnlinkFileInDir(pEntry->New.pszObjName, pEntry->pszDir);
+
+    free(pEntry->Old.pszCppMapping);
+    pEntry->Old.pszCppMapping = NULL;
+    if (!pEntry->fPipedPreComp && !pEntry->fPipedCompile)
+    {
+        free(pEntry->New.pszCppMapping);
+        pEntry->New.pszCppMapping = NULL;
+    }
+
+    /*
+     * Do the (re-)compile job.
+     */
+    if (pEntry->fPipedCompile)
+    {
+        if (    !pEntry->fPipedPreComp
+            &&  !pEntry->New.pszCppMapping)
+            kOCEntryReadCppOutput(pEntry, &pEntry->New, 0 /* fatal */);
+        InfoMsg(3, "compiling -> '%s'...\n", pEntry->New.pszObjName);
+        kOCEntrySpawnConsumer(pEntry, (const char * const *)pEntry->New.papszArgvCompile, pEntry->New.cArgvCompile,
+                              "compile", kOCEntryCompileProducer);
+    }
+    else
+    {
+        if (pEntry->fPipedPreComp)
+            kOCEntryWriteCppOutput(pEntry, 1 /* free it */);
+        InfoMsg(3, "compiling -> '%s'...\n", pEntry->New.pszObjName);
+        kOCEntrySpawn(pEntry, (const char * const *)pEntry->New.papszArgvCompile, pEntry->New.cArgvCompile, "compile", NULL);
+    }
+}
+
+
+/**
+ * kOCEntrySpawnTee callback that works sort of like 'tee'.
+ *
+ * It will calculate the precompiled output checksum and
+ * write it to disk while the compiler is busy compiling it.
+ *
+ * @param   pEntry  The cache entry.
+ * @param   fdIn    The input handle (connected to the precompiler).
+ * @param   fdOut   The output handle (connected to the compiler).
+ */
+static void kOCEntryTeeConsumer(PKOCENTRY pEntry, int fdIn, int fdOut)
+{
+    KOCSUMCTX Ctx;
+    long cbLeft;
+    long cbAlloc;
+    char *psz;
+
+    kOCSumInitWithCtx(&pEntry->New.SumHead, &Ctx);
+    cbAlloc = pEntry->Old.cbCpp ? ((long)pEntry->Old.cbCpp + 4*1024*1024 + 4096) & ~(4*1024*1024 - 1) : 4*1024*1024;
+    cbLeft = cbAlloc;
+    pEntry->New.pszCppMapping = psz = xmalloc(cbAlloc);
+    InfoMsg(3, "precompiler|compile - starting passhtru...\n");
+    for (;;)
+    {
+        /*
+         * Read data from the pipe.
+         */
+        long cbRead = read(fdIn, psz, cbLeft - 1);
+        if (!cbRead)
+            break;
+        if (cbRead < 0)
+        {
+            if (errno == EINTR)
+                continue;
+            FatalDie("precompile|compile - read(%d,,%ld) failed: %s\n",
+                     fdIn, (long)cbLeft, strerror(errno));
+        }
+        InfoMsg(3, "precompiler|compile - read %d\n", cbRead);
+
+        /*
+         * Process the data.
+         */
+        psz[cbRead] = '\0';
+        kOCSumUpdate(&pEntry->New.SumHead, &Ctx, psz, cbRead);
+        do
+        {
+            long cbWritten = write(fdOut, psz, cbRead);
+            if (cbWritten < 0)
+            {
+                if (errno == EINTR)
+                    continue;
+                FatalDie("precompile|compile - write(%d,,%ld) failed: %s\n", fdOut, cbRead, strerror(errno));
+            }
+            psz += cbWritten;
+            cbRead -= cbWritten;
+            cbLeft -= cbWritten;
+        } while (cbRead > 0);
+
+        /*
+         * Expand the buffer?
+         */
+        if (cbLeft <= 1)
+        {
+            size_t off = psz - pEntry->New.pszCppMapping;
+            cbLeft = 4*1024*1024;
+            cbAlloc += cbLeft;
+            pEntry->New.pszCppMapping = xrealloc(pEntry->New.pszCppMapping, cbAlloc);
+            psz = pEntry->New.pszCppMapping + off;
+        }
+    }
+    InfoMsg(3, "precompiler|compile - done passhtru\n");
+
+    close(fdIn);
+    close(fdOut);
+    pEntry->New.cbCpp = cbAlloc - cbLeft;
+    kOCSumFinalize(&pEntry->New.SumHead, &Ctx);
+    kOCSumInfo(&pEntry->New.SumHead, 4, "cpp (tee)");
+
+    /*
+     * Write the precompiler output to disk and free the memory it
+     * occupies while the compiler is busy compiling.
+     */
+    kOCEntryWriteCppOutput(pEntry, 1 /* free it */);
+}
+
+
+/**
+ * Performs pre-compile and compile in one go (typical clean build scenario).
+ *
+ * @param   pEntry              The cache entry.
+ * @param   papszArgvPreComp    The argument vector for executing precompiler. The cArgvPreComp'th argument must be NULL.
+ * @param   cArgvPreComp        The number of arguments.
+ */
+static void kOCEntryPreCompileAndCompile(PKOCENTRY pEntry, const char * const *papszArgvPreComp, unsigned cArgvPreComp)
+{
+    if (    pEntry->fPipedCompile
+        &&  pEntry->fPipedPreComp)
+    {
+        /*
+         * Clean up old stuff first.
+         */
+        if (pEntry->Old.pszObjName)
+            UnlinkFileInDir(pEntry->Old.pszObjName, pEntry->pszDir);
+        if (pEntry->New.pszObjName)
+            UnlinkFileInDir(pEntry->New.pszObjName, pEntry->pszDir);
+        if (pEntry->Old.pszCppName)
+            UnlinkFileInDir(pEntry->Old.pszCppName, pEntry->pszDir);
+        if (pEntry->New.pszCppName)
+            UnlinkFileInDir(pEntry->New.pszCppName, pEntry->pszDir);
+
+        /*
+         * Do the actual compile and write the precompiler output to disk.
+         */
+        kOCEntrySpawnTee(pEntry, papszArgvPreComp, cArgvPreComp,
+                         (const char * const *)pEntry->New.papszArgvCompile, pEntry->New.cArgvCompile,
+                         "precompile|compile", kOCEntryTeeConsumer);
+    }
+    else
+    {
+        kOCEntryPreCompile(pEntry, papszArgvPreComp, cArgvPreComp);
+        kOCEntryCompileIt(pEntry);
+    }
+}
+
+
+/**
+ * Check whether the string is a '#line' statement.
+ *
+ * @returns 1 if it is, 0 if it isn't.
+ * @param   psz         The line to examin.
+ * @parma   piLine      Where to store the line number.
+ * @parma   ppszFile    Where to store the start of the filename.
+ */
+static int kOCEntryIsLineStatement(const char *psz, unsigned *piLine, const char **ppszFile)
+{
+    unsigned iLine;
+
+    /* Expect a hash. */
+    if (*psz++ != '#')
+        return 0;
+
+    /* Skip blanks between '#' and the line / number */
+    while (*psz == ' ' || *psz == '\t')
+        psz++;
+
+    /* Skip the 'line' if present. */
+    if (!strncmp(psz, "line", sizeof("line") - 1))
+        psz += sizeof("line");
+
+    /* Expect a line number now. */
+    if ((unsigned char)(*psz - '0') > 9)
+        return 0;
+    iLine = 0;
+    do
+    {
+        iLine *= 10;
+        iLine += (*psz - '0');
+        psz++;
+    }
+    while ((unsigned char)(*psz - '0') <= 9);
+
+    /* Expect one or more space now. */
+    if (*psz != ' ' && *psz != '\t')
+        return 0;
+    do  psz++;
+    while (*psz == ' ' || *psz == '\t');
+
+    /* that's good enough. */
+    *piLine = iLine;
+    *ppszFile = psz;
+    return 1;
+}
+
+
+/**
+ * Scan backwards for the previous #line statement.
+ *
+ * @returns The filename in the previous statement.
+ * @param   pszStart        Where to start.
+ * @param   pszStop         Where to stop. Less than pszStart.
+ * @param   piLine          The line number count to adjust.
+ */
+static const char *kOCEntryFindFileStatement(const char *pszStart, const char *pszStop, unsigned *piLine)
+{
+    unsigned iLine = *piLine;
+    assert(pszStart >= pszStop);
+    while (pszStart >= pszStop)
+    {
+        if (*pszStart == '\n')
+            iLine++;
+        else if (*pszStart == '#')
+        {
+            unsigned iLineTmp;
+            const char *pszFile;
+            const char *psz = pszStart - 1;
+            while (psz >= pszStop && (*psz == ' ' || *psz =='\t'))
+                psz--;
+            if (    (psz < pszStop || *psz == '\n')
+                &&  kOCEntryIsLineStatement(pszStart, &iLineTmp, &pszFile))
+            {
+                *piLine = iLine + iLineTmp - 1;
+                return pszFile;
+            }
+        }
+        pszStart--;
+    }
+    return NULL;
+}
+
+
+/**
+ * Worker for kOCEntryCompareOldAndNewOutput() that compares the
+ * precompiled output using a fast but not very good method.
+ *
+ * @returns 1 if matching, 0 if not matching.
+ * @param   pEntry      The entry containing the names of the files to compare.
+ *                      The entry is not updated in any way.
+ */
+static int kOCEntryCompareFast(PCKOCENTRY pEntry)
+{
+    const char *        psz1 = pEntry->New.pszCppMapping;
+    const char * const  pszEnd1 = psz1 + pEntry->New.cbCpp;
+    const char *        psz2 = pEntry->Old.pszCppMapping;
+    const char * const  pszEnd2 = psz2 + pEntry->Old.cbCpp;
+
+    assert(*pszEnd1 == '\0');
+    assert(*pszEnd2 == '\0');
+
+    /*
+     * Iterate block by block and backtrack when we find a difference.
+     */
+    for (;;)
+    {
+        size_t cch = pszEnd1 - psz1;
+        if (cch > (size_t)(pszEnd2 - psz2))
+            cch = pszEnd2 - psz2;
+        if (cch > 4096)
+            cch = 4096;
+        if (    cch
+            &&  !memcmp(psz1, psz2, cch))
+        {
+            /* no differences */
+            psz1 += cch;
+            psz2 += cch;
+        }
+        else
+        {
+            /*
+             * Pinpoint the difference exactly and the try find the start
+             * of that line. Then skip forward until we find something to
+             * work on that isn't spaces, #line statements or closing curly
+             * braces.
+             *
+             * The closing curly braces are ignored because they are frequently
+             * found at the end of header files (__END_DECLS) and the worst
+             * thing that may happen if it isn't one of these braces we're
+             * ignoring is that the final line in a function block is a little
+             * bit off in the debug info.
+             *
+             * Since we might be skipping a few new empty headers, it is
+             * possible that we will omit this header from the dependencies
+             * when using VCC. This might not be a problem, since it seems
+             * we'll have to use the precompiler output to generate the deps
+             * anyway.
+             */
+            const char *psz;
+            const char *pszMismatch1;
+            const char *pszFile1 = NULL;
+            unsigned    iLine1 = 0;
+            unsigned    cCurlyBraces1 = 0;
+            const char *pszMismatch2;
+            const char *pszFile2 = NULL;
+            unsigned    iLine2 = 0;
+            unsigned    cCurlyBraces2 = 0;
+
+            /* locate the difference. */
+            while (cch >= 512 && !memcmp(psz1, psz2, 512))
+                psz1 += 512, psz2 += 512, cch -= 512;
+            while (cch >= 64 && !memcmp(psz1, psz2, 64))
+                psz1 += 64, psz2 += 64, cch -= 64;
+            while (*psz1 == *psz2 && cch > 0)
+                psz1++, psz2++, cch--;
+
+            /* locate the start of that line. */
+            psz = psz1;
+            while (     psz > pEntry->New.pszCppMapping
+                   &&   psz[-1] != '\n')
+                psz--;
+            psz2 -= (psz1 - psz);
+            pszMismatch2 = psz2;
+            pszMismatch1 = psz1 = psz;
+
+            /* Parse the 1st file line by line. */
+            while (psz1 < pszEnd1)
+            {
+                if (*psz1 == '\n')
+                {
+                    psz1++;
+                    iLine1++;
+                }
+                else
+                {
+                    psz = psz1;
+                    while (isspace(*psz) && *psz != '\n')
+                        psz++;
+                    if (*psz == '\n')
+                    {
+                        psz1 = psz + 1;
+                        iLine1++;
+                    }
+                    else if (*psz == '#' && kOCEntryIsLineStatement(psz, &iLine1, &pszFile1))
+                    {
+                        psz1 = memchr(psz, '\n', pszEnd1 - psz);
+                        if (!psz1++)
+                            psz1 = pszEnd1;
+                    }
+                    else if (*psz == '}')
+                    {
+                        do psz++;
+                        while (isspace(*psz) && *psz != '\n');
+                        if (*psz == '\n')
+                            iLine1++;
+                        else if (psz != pszEnd1)
+                            break;
+                        cCurlyBraces1++;
+                        psz1 = psz;
+                    }
+                    else if (psz == pszEnd1)
+                        psz1 = psz;
+                    else /* found something that can be compared. */
+                        break;
+                }
+            }
+
+            /* Ditto for the 2nd file. */
+            while (psz2 < pszEnd2)
+            {
+                if (*psz2 == '\n')
+                {
+                    psz2++;
+                    iLine2++;
+                }
+                else
+                {
+                    psz = psz2;
+                    while (isspace(*psz) && *psz != '\n')
+                        psz++;
+                    if (*psz == '\n')
+                    {
+                        psz2 = psz + 1;
+                        iLine2++;
+                    }
+                    else if (*psz == '#' && kOCEntryIsLineStatement(psz, &iLine2, &pszFile2))
+                    {
+                        psz2 = memchr(psz, '\n', pszEnd2 - psz);
+                        if (!psz2++)
+                            psz2 = pszEnd2;
+                    }
+                    else if (*psz == '}')
+                    {
+                        do psz++;
+                        while (isspace(*psz) && *psz != '\n');
+                        if (*psz == '\n')
+                            iLine2++;
+                        else if (psz != pszEnd2)
+                            break;
+                        cCurlyBraces2++;
+                        psz2 = psz;
+                    }
+                    else if (psz == pszEnd2)
+                        psz2 = psz;
+                    else /* found something that can be compared. */
+                        break;
+                }
+            }
+
+            /* Match the number of ignored closing curly braces. */
+            if (cCurlyBraces1 != cCurlyBraces2)
+                return 0;
+
+            /* Reaching the end of any of them means the return statement can decide. */
+            if (   psz1 == pszEnd1
+                || psz2 == pszEnd2)
+                break;
+
+            /* Match the current line. */
+            psz = memchr(psz1, '\n', pszEnd1 - psz1);
+            if (!psz++)
+                psz = pszEnd1;
+            cch = psz - psz1;
+            if (psz2 + cch > pszEnd2)
+                break;
+            if (memcmp(psz1, psz2, cch))
+                break;
+
+            /* Check that we're at the same location now. */
+            if (!pszFile1)
+                pszFile1 = kOCEntryFindFileStatement(pszMismatch1, pEntry->New.pszCppMapping, &iLine1);
+            if (!pszFile2)
+                pszFile2 = kOCEntryFindFileStatement(pszMismatch2, pEntry->Old.pszCppMapping, &iLine2);
+            if (pszFile1 && pszFile2)
+            {
+                if (iLine1 != iLine2)
+                    break;
+                while (*pszFile1 == *pszFile2 && *pszFile1 != '\n' && *pszFile1)
+                    pszFile1++, pszFile2++;
+                if (*pszFile1 != *pszFile2)
+                    break;
+            }
+            else if (pszFile1 || pszFile2)
+            {
+                assert(0); /* this shouldn't happen. */
+                break;
+            }
+
+            /* Advance. We might now have a misaligned buffer, but that's memcmps problem... */
+            psz1 += cch;
+            psz2 += cch;
+        }
+    }
+
+    return psz1 == pszEnd1
+        && psz2 == pszEnd2;
+}
+
+
+/**
+ * Worker for kOCEntryCompileIfNeeded that compares the
+ * precompiled output.
+ *
+ * @returns 1 if matching, 0 if not matching.
+ * @param   pEntry      The entry containing the names of the files to compare.
+ *                      This will load the old cpp output (changing pszOldCppName and Old.cbCpp).
+ */
+static int kOCEntryCompareOldAndNewOutput(PKOCENTRY pEntry)
+{
+    /*
+     * I may implement a more sophisticated alternative method later... maybe.
+     */
+    if (kOCEntryReadCppOutput(pEntry, &pEntry->Old, 1 /* nonfatal */) == -1)
+        return 0;
+    /*if ()
+        return kOCEntryCompareBest(pEntry);*/
+    return kOCEntryCompareFast(pEntry);
+}
+
+
+/**
+ * Check if re-compilation is required.
+ * This sets the fNeedCompile flag.
+ *
+ * @param   pEntry              The cache entry.
+ */
+static void kOCEntryCalcRecompile(PKOCENTRY pEntry)
+{
+    if (pEntry->fNeedCompiling)
+        return;
+
+    /*
+     * Check if the precompiler output differ in any significant way?
+     */
+    if (!kOCSumHasEqualInChain(&pEntry->Old.SumHead, &pEntry->New.SumHead))
+    {
+        InfoMsg(2, "no checksum match - comparing output\n");
+        if (!kOCEntryCompareOldAndNewOutput(pEntry))
+            pEntry->fNeedCompiling = 1;
+        else
+            kOCSumAddChain(&pEntry->New.SumHead, &pEntry->Old.SumHead);
+    }
+}
+
+
+/**
+ * Does this cache entry need compiling or what?
+ *
+ * @returns 1 if it does, 0 if it doesn't.
+ * @param   pEntry      The cache entry in question.
+ */
+static int kOCEntryNeedsCompiling(PCKOCENTRY pEntry)
+{
+    return pEntry->fNeedCompiling;
+}
+
+
+/**
+ * Worker function for kOCEntryCopy.
+ *
+ * @param   pEntry      The entry we're coping to, which pszTo is relative to.
+ * @param   pszTo       The destination.
+ * @param   pszFrom     The source. This path will be freed.
+ */
+static void kOCEntryCopyFile(PCKOCENTRY pEntry, const char *pszTo, char *pszSrc)
+{
+    char *pszDst = MakePathFromDirAndFile(pszTo, pEntry->pszDir);
+    char *pszBuf = xmalloc(256 * 1024);
+    char *psz;
+    int fdSrc;
+    int fdDst;
+
+    /*
+     * Open the files.
+     */
+    fdSrc = open(pszSrc, O_RDONLY | O_BINARY);
+    if (fdSrc == -1)
+        FatalDie("failed to open '%s': %s\n", pszSrc, strerror(errno));
+
+    unlink(pszDst);
+    fdDst = open(pszDst, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+    if (fdDst == -1)
+        FatalDie("failed to create '%s': %s\n", pszDst, strerror(errno));
+
+    /*
+     * Copy them.
+     */
+    for (;;)
+    {
+        /* read a chunk. */
+        long cbRead = read(fdSrc, pszBuf, 256*1024);
+        if (cbRead < 0)
+        {
+            if (errno == EINTR)
+                continue;
+            FatalDie("read '%s' failed: %s\n", pszSrc, strerror(errno));
+        }
+        if (!cbRead)
+            break; /* eof */
+
+        /* write the chunk. */
+        psz = pszBuf;
+        do
+        {
+            long cbWritten = write(fdDst, psz, cbRead);
+            if (cbWritten < 0)
+            {
+                if (errno == EINTR)
+                    continue;
+                FatalDie("write '%s' failed: %s\n", pszSrc, strerror(errno));
+            }
+            psz += cbWritten;
+            cbRead -= cbWritten;
+        } while (cbRead > 0);
+    }
+
+    /* cleanup */
+    if (close(fdDst) != 0)
+        FatalDie("closing '%s' failed: %s\n", pszDst, strerror(errno));
+    close(fdSrc);
+    free(pszBuf);
+    free(pszDst);
+    free(pszSrc);
+}
+
+
+/**
+ * Copies the object (and whatever else) from one cache entry to another.
+ *
+ * This is called when a matching cache entry has been found and we don't
+ * need to recompile anything.
+ *
+ * @param   pEntry      The entry to copy to.
+ * @param   pFrom       The entry to copy from.
+ */
+static void kOCEntryCopy(PKOCENTRY pEntry, PCKOCENTRY pFrom)
+{
+    kOCEntryCopyFile(pEntry, pEntry->New.pszObjName,
+                     MakePathFromDirAndFile(pFrom->New.pszObjName
+                                            ? pFrom->New.pszObjName : pFrom->Old.pszObjName,
+                                            pFrom->pszDir));
+}
+
+
+/**
+ * Gets the absolute path to the cache entry.
+ *
+ * @returns absolute path to the cache entry.
+ * @param   pEntry      The cache entry in question.
+ */
+static const char *kOCEntryAbsPath(PCKOCENTRY pEntry)
+{
+    return pEntry->pszAbsPath;
+}
+
+
+
+
+
+
+/**
+ * Digest of one cache entry.
+ *
+ * This contains all the information required to find a matching
+ * cache entry without having to open each of the files.
+ */
+typedef struct KOCDIGEST
+{
+    /** The relative path to the entry. Optional if pszAbsPath is set. */
+    char *pszRelPath;
+    /** The absolute path to the entry. Optional if pszRelPath is set. */
+    char *pszAbsPath;
+    /** The target os/arch identifier. */
+    char *pszTarget;
+    /** A unique number assigned to the entry when it's (re)-inserted
+     * into the cache. This is used for simple consitency checking. */
+    uint32_t uKey;
+    /** The checksum of the compile argument vector. */
+    KOCSUM SumCompArgv;
+    /** The list of precompiler output checksums that's . */
+    KOCSUM SumHead;
+} KOCDIGEST;
+/** Pointer to a file digest. */
+typedef KOCDIGEST *PKOCDIGEST;
+/** Pointer to a const file digest. */
+typedef KOCDIGEST *PCKOCDIGEST;
+
+
+/**
+ * Initializes the specified digest.
+ *
+ * @param   pDigest     The digest.
+ */
+static void kOCDigestInit(PKOCDIGEST pDigest)
+{
+    memset(pDigest, 0, sizeof(*pDigest));
+    kOCSumInit(&pDigest->SumHead);
+}
+
+
+/**
+ * Initializes the digest for the specified entry.
+ *
+ * @param   pDigest     The (uninitialized) digest.
+ * @param   pEntry      The entry.
+ */
+static void kOCDigestInitFromEntry(PKOCDIGEST pDigest, PCKOCENTRY pEntry)
+{
+    kOCDigestInit(pDigest);
+
+    pDigest->uKey = pEntry->uKey;
+    pDigest->pszTarget = xstrdup(pEntry->New.pszTarget ? pEntry->New.pszTarget : pEntry->Old.pszTarget);
+
+    kOCSumInit(&pDigest->SumCompArgv);
+    if (!kOCSumIsEmpty(&pEntry->New.SumCompArgv))
+        kOCSumAdd(&pDigest->SumCompArgv, &pEntry->New.SumCompArgv);
+    else
+        kOCSumAdd(&pDigest->SumCompArgv, &pEntry->Old.SumCompArgv);
+
+    kOCSumInit(&pDigest->SumHead);
+    if (!kOCSumIsEmpty(&pEntry->New.SumHead))
+        kOCSumAddChain(&pDigest->SumHead, &pEntry->New.SumHead);
+    else
+        kOCSumAddChain(&pDigest->SumHead, &pEntry->Old.SumHead);
+
+    /** @todo implement selective relative path support. */
+    pDigest->pszRelPath = NULL;
+    pDigest->pszAbsPath = xstrdup(kOCEntryAbsPath(pEntry));
+}
+
+
+/**
+ * Purges a digest, freeing all resources and returning
+ * it to the initial state.
+ *
+ * @param   pDigest     The digest.
+ */
+static void kOCDigestPurge(PKOCDIGEST pDigest)
+{
+    free(pDigest->pszRelPath);
+    free(pDigest->pszAbsPath);
+    free(pDigest->pszTarget);
+    pDigest->pszTarget = pDigest->pszAbsPath = pDigest->pszRelPath = NULL;
+    pDigest->uKey = 0;
+    kOCSumDeleteChain(&pDigest->SumCompArgv);
+    kOCSumDeleteChain(&pDigest->SumHead);
+}
+
+
+/**
+ * Returns the absolute path to the entry, calculating
+ * the path if necessary.
+ *
+ * @returns absolute path.
+ * @param   pDigest     The digest.
+ * @param   pszDir      The cache directory that it might be relative to.
+ */
+static const char *kOCDigestAbsPath(PCKOCDIGEST pDigest, const char *pszDir)
+{
+    if (!pDigest->pszAbsPath)
+    {
+        char *pszPath = MakePathFromDirAndFile(pDigest->pszRelPath, pszDir);
+        ((PKOCDIGEST)pDigest)->pszAbsPath = AbsPath(pszPath);
+        free(pszPath);
+    }
+    return pDigest->pszAbsPath;
+}
+
+
+/**
+ * Checks that the digest matches the
+ *
+ * @returns 1 if valid, 0 if invalid in some way.
+ *
+ * @param   pDigest     The digest to validate.
+ * @param   pEntry      What to validate it against.
+ */
+static int kOCDigestIsValid(PCKOCDIGEST pDigest, PCKOCENTRY pEntry)
+{
+    PCKOCSUM pSum;
+    PCKOCSUM pSumEntry;
+
+    if (pDigest->uKey != pEntry->uKey)
+        return 0;
+
+    if (!kOCSumIsEqual(&pDigest->SumCompArgv,
+                       kOCSumIsEmpty(&pEntry->New.SumCompArgv)
+                       ? &pEntry->Old.SumCompArgv : &pEntry->New.SumCompArgv))
+        return 0;
+
+    if (strcmp(pDigest->pszTarget, pEntry->New.pszTarget ? pEntry->New.pszTarget : pEntry->Old.pszTarget))
+        return 0;
+
+    /* match the checksums */
+    pSumEntry = kOCSumIsEmpty(&pEntry->New.SumHead)
+              ? &pEntry->Old.SumHead : &pEntry->New.SumHead;
+    for (pSum = &pDigest->SumHead; pSum; pSum = pSum->pNext)
+        if (!kOCSumHasEqualInChain(pSumEntry, pSum))
+            return 0;
+
+    return 1;
+}
+
+
+
+
+
+/**
+ * The structure for the central cache entry.
+ */
+typedef struct KOBJCACHE
+{
+    /** The entry name. */
+    const char *pszName;
+    /** The dir that relative names in the digest are relative to. */
+    char *pszDir;
+    /** The absolute path. */
+    char *pszAbsPath;
+
+    /** The cache file descriptor. */
+    int fd;
+    /** The stream associated with fd. */
+    FILE *pFile;
+    /** Whether it's currently locked or not. */
+    unsigned fLocked;
+    /** Whether the cache file is dirty and needs writing back. */
+    unsigned fDirty;
+    /** Whether this is a new cache or not. */
+    unsigned fNewCache;
+
+    /** The cache file generation. */
+    uint32_t uGeneration;
+    /** The next valid key. (Determin at load time.) */
+    uint32_t uNextKey;
+
+    /** Number of digests in paDigests. */
+    unsigned cDigests;
+    /** Array of digests for the KOCENTRY objects in the cache. */
+    PKOCDIGEST paDigests;
+
+} KOBJCACHE;
+/** Pointer to a cache. */
+typedef KOBJCACHE *PKOBJCACHE;
+/** Pointer to a const cache. */
+typedef KOBJCACHE const *PCKOBJCACHE;
+
+
+/**
+ * Creates an empty cache.
+ *
+ * This doesn't touch the file system, it just create the data structure.
+ *
+ * @returns Pointer to a cache.
+ * @param   pszCacheFile        The cache file.
+ */
+static PKOBJCACHE kObjCacheCreate(const char *pszCacheFile)
+{
+    PKOBJCACHE pCache;
+    size_t off;
+
+    /*
+     * Allocate an empty entry.
+     */
+    pCache = xmallocz(sizeof(*pCache));
+    pCache->fd = -1;
+
+    /*
+     * Setup the directory and cache file name.
+     */
+    pCache->pszAbsPath = AbsPath(pszCacheFile);
+    pCache->pszName = FindFilenameInPath(pCache->pszAbsPath);
+    off = pCache->pszName - pCache->pszAbsPath;
+    if (!off)
+        FatalDie("Failed to find abs path for '%s'!\n", pszCacheFile);
+    pCache->pszDir = xmalloc(off);
+    memcpy(pCache->pszDir, pCache->pszAbsPath, off - 1);
+    pCache->pszDir[off - 1] = '\0';
+
+    return pCache;
+}
+
+
+/**
+ * Destroys the cache - closing any open files, freeing up heap memory and such.
+ *
+ * @param   pCache      The cache.
+ */
+static void kObjCacheDestroy(PKOBJCACHE pCache)
+{
+    if (pCache->pFile)
+    {
+        errno = 0;
+        if (fclose(pCache->pFile) != 0)
+            FatalMsg("fclose failed: %s\n", strerror(errno));
+        pCache->pFile = NULL;
+        pCache->fd = -1;
+    }
+    free(pCache->paDigests);
+    free(pCache->pszAbsPath);
+    free(pCache->pszDir);
+    free(pCache);
+}
+
+
+/**
+ * Purges the data in the cache object.
+ *
+ * @param   pCache      The cache object.
+ */
+static void kObjCachePurge(PKOBJCACHE pCache)
+{
+    while (pCache->cDigests > 0)
+        kOCDigestPurge(&pCache->paDigests[--pCache->cDigests]);
+    free(pCache->paDigests);
+    pCache->paDigests = NULL;
+    pCache->uGeneration = 0;
+    pCache->uNextKey = 0;
+}
+
+
+/**
+ * (Re-)reads the file.
+ *
+ * @param   pCache      The cache to (re)-read.
+ */
+static void kObjCacheRead(PKOBJCACHE pCache)
+{
+    unsigned i;
+    char szBuf[8192];
+    int fBad = 0;
+
+    InfoMsg(4, "reading cache file...\n");
+
+    /*
+     * Rewind the file & stream, and associate a temporary buffer
+     * with the stream to speed up reading.
+     */
+    if (lseek(pCache->fd, 0, SEEK_SET) == -1)
+        FatalDie("lseek(cache-fd) failed: %s\n", strerror(errno));
+    rewind(pCache->pFile);
+    if (setvbuf(pCache->pFile, szBuf, _IOFBF, sizeof(szBuf)) != 0)
+        FatalDie("fdopen(cache-fd,rb) failed: %s\n", strerror(errno));
+
+    /*
+     * Read magic and generation.
+     */
+    if (    !fgets(g_szLine, sizeof(g_szLine), pCache->pFile)
+        ||  strcmp(g_szLine, "magic=kObjCache-v0.1.0\n"))
+    {
+        InfoMsg(2, "bad cache file (magic)\n");
+        fBad = 1;
+    }
+    else if (    !fgets(g_szLine, sizeof(g_szLine), pCache->pFile)
+             ||  strncmp(g_szLine, "generation=", sizeof("generation=") - 1))
+    {
+        InfoMsg(2, "bad cache file (generation)\n");
+        fBad = 1;
+    }
+    else if (   pCache->uGeneration
+             && (long)pCache->uGeneration == atol(&g_szLine[sizeof("generation=") - 1]))
+    {
+        InfoMsg(3, "drop re-read unmodified cache file\n");
+        fBad = 0;
+    }
+    else
+    {
+        int fBadBeforeMissing;
+
+        /*
+         * Read everything (anew).
+         */
+        kObjCachePurge(pCache);
+        do
+        {
+            PKOCDIGEST pDigest;
+            char *pszNl;
+            char *pszVal;
+            char *psz;
+
+            /* Split the line and drop the trailing newline. */
+            pszVal = strchr(g_szLine, '=');
+            if ((fBad = pszVal == NULL))
+                break;
+            *pszVal++ = '\0';
+
+            pszNl = strchr(pszVal, '\n');
+            if (pszNl)
+                *pszNl = '\0';
+
+            /* digest '#'? */
+            psz = strchr(g_szLine, '#');
+            if (psz)
+            {
+                char *pszNext;
+                i = strtoul(++psz, &pszNext, 0);
+                if ((fBad = pszNext && *pszNext))
+                    break;
+                if ((fBad = i >= pCache->cDigests))
+                    break;
+                pDigest = &pCache->paDigests[i];
+                *psz = '\0';
+            }
+            else
+                pDigest = NULL;
+
+
+            /* string case on value name. */
+            if (!strcmp(g_szLine, "sum-#"))
+            {
+                KOCSUM Sum;
+                if ((fBad = kOCSumInitFromString(&Sum, pszVal) != 0))
+                    break;
+                kOCSumAdd(&pDigest->SumHead, &Sum);
+            }
+            else if (!strcmp(g_szLine, "digest-abs-#"))
+            {
+                if ((fBad = pDigest->pszAbsPath != NULL))
+                    break;
+                pDigest->pszAbsPath = xstrdup(pszVal);
+            }
+            else if (!strcmp(g_szLine, "digest-rel-#"))
+            {
+                if ((fBad = pDigest->pszRelPath != NULL))
+                    break;
+                pDigest->pszRelPath = xstrdup(pszVal);
+            }
+            else if (!strcmp(g_szLine, "key-#"))
+            {
+                if ((fBad = pDigest->uKey != 0))
+                    break;
+                pDigest->uKey = strtoul(pszVal, &psz, 0);
+                if ((fBad = psz && *psz))
+                    break;
+                if (pDigest->uKey >= pCache->uNextKey)
+                    pCache->uNextKey = pDigest->uKey + 1;
+            }
+            else if (!strcmp(g_szLine, "comp-argv-sum-#"))
+            {
+                if ((fBad = !kOCSumIsEmpty(&pDigest->SumCompArgv)))
+                    break;
+                if ((fBad = kOCSumInitFromString(&pDigest->SumCompArgv, pszVal) != 0))
+                    break;
+            }
+            else if (!strcmp(g_szLine, "target-#"))
+            {
+                if ((fBad = pDigest->pszTarget != NULL))
+                    break;
+                pDigest->pszTarget = xstrdup(pszVal);
+            }
+            else if (!strcmp(g_szLine, "digests"))
+            {
+                if ((fBad = pCache->paDigests != NULL))
+                    break;
+                pCache->cDigests = strtoul(pszVal, &psz, 0);
+                if ((fBad = psz && *psz))
+                    break;
+                i = (pCache->cDigests + 4) & ~3;
+                pCache->paDigests = xmalloc(i * sizeof(pCache->paDigests[0]));
+                for (i = 0; i < pCache->cDigests; i++)
+                    kOCDigestInit(&pCache->paDigests[i]);
+            }
+            else if (!strcmp(g_szLine, "generation"))
+            {
+                if ((fBad = pCache->uGeneration != 0))
+                    break;
+                pCache->uGeneration = strtoul(pszVal, &psz, 0);
+                if ((fBad = psz && *psz))
+                    break;
+            }
+            else if (!strcmp(g_szLine, "the-end"))
+            {
+                fBad = strcmp(pszVal, "fine");
+                break;
+            }
+            else
+            {
+                fBad = 1;
+                break;
+            }
+        } while (fgets(g_szLine, sizeof(g_szLine), pCache->pFile));
+
+        /*
+         * Did we find everything?
+         */
+        fBadBeforeMissing = fBad;
+        if (    !fBad
+            &&  !pCache->uGeneration)
+            fBad = 1;
+        if (!fBad)
+            for (i = 0; i < pCache->cDigests; i++)
+            {
+                if ((fBad = kOCSumIsEmpty(&pCache->paDigests[i].SumCompArgv)))
+                    break;
+                if ((fBad = kOCSumIsEmpty(&pCache->paDigests[i].SumHead)))
+                    break;
+                if ((fBad = pCache->paDigests[i].uKey == 0))
+                    break;
+                if ((fBad = pCache->paDigests[i].pszAbsPath == NULL
+                         && pCache->paDigests[i].pszRelPath == NULL))
+                    break;
+                if ((fBad = pCache->paDigests[i].pszTarget == NULL))
+                    break;
+                InfoMsg(4, "digest-%u: %s\n", i, pCache->paDigests[i].pszAbsPath
+                        ? pCache->paDigests[i].pszAbsPath : pCache->paDigests[i].pszRelPath);
+            }
+        if (fBad)
+            InfoMsg(2, "bad cache file (%s)\n", fBadBeforeMissing ? g_szLine : "missing stuff");
+        else if (ferror(pCache->pFile))
+        {
+            InfoMsg(2, "cache file read error\n");
+            fBad = 1;
+        }
+    }
+    if (fBad)
+    {
+        kObjCachePurge(pCache);
+        pCache->fNewCache = 1;
+    }
+
+    /*
+     * Disassociate the buffer from the stream changing
+     * it to non-buffered mode.
+     */
+    if (setvbuf(pCache->pFile, NULL, _IONBF, 0) != 0)
+        FatalDie("setvbuf(,0,,0) failed: %s\n", strerror(errno));
+}
+
+
+/**
+ * Re-writes the cache file.
+ *
+ * @param   pCache      The cache to commit and unlock.
+ */
+static void kObjCacheWrite(PKOBJCACHE pCache)
+{
+    unsigned i;
+    off_t cb;
+    char szBuf[8192];
+    assert(pCache->fLocked);
+    assert(pCache->fDirty);
+
+    /*
+     * Rewind the file & stream, and associate a temporary buffer
+     * with the stream to speed up the writing.
+     */
+    if (lseek(pCache->fd, 0, SEEK_SET) == -1)
+        FatalDie("lseek(cache-fd) failed: %s\n", strerror(errno));
+    rewind(pCache->pFile);
+    if (setvbuf(pCache->pFile, szBuf, _IOFBF, sizeof(szBuf)) != 0)
+        FatalDie("setvbuf failed: %s\n", strerror(errno));
+
+    /*
+     * Write the header.
+     */
+    pCache->uGeneration++;
+    fprintf(pCache->pFile,
+            "magic=kObjCache-v0.1.0\n"
+            "generation=%d\n"
+            "digests=%d\n",
+            pCache->uGeneration,
+            pCache->cDigests);
+
+    /*
+     * Write the digests.
+     */
+    for (i = 0; i < pCache->cDigests; i++)
+    {
+        PCKOCDIGEST pDigest = &pCache->paDigests[i];
+        PKOCSUM pSum;
+
+        if (pDigest->pszAbsPath)
+            fprintf(pCache->pFile, "digest-abs-#%u=%s\n", i, pDigest->pszAbsPath);
+        if (pDigest->pszRelPath)
+            fprintf(pCache->pFile, "digest-rel-#%u=%s\n", i, pDigest->pszRelPath);
+        fprintf(pCache->pFile, "key-#%u=%u\n", i, pDigest->uKey);
+        fprintf(pCache->pFile, "target-#%u=%s\n", i, pDigest->pszTarget);
+        fprintf(pCache->pFile, "comp-argv-sum-#%u=", i);
+        kOCSumFPrintf(&pDigest->SumCompArgv, pCache->pFile);
+        for (pSum = &pDigest->SumHead; pSum; pSum = pSum->pNext)
+        {
+            fprintf(pCache->pFile, "sum-#%u=", i);
+            kOCSumFPrintf(pSum, pCache->pFile);
+        }
+    }
+
+    /*
+     * Close the stream and unlock fhe file.
+     * (Closing the stream shouldn't close the file handle IIRC...)
+     */
+    fprintf(pCache->pFile, "the-end=fine\n");
+    errno = 0;
+    if (    fflush(pCache->pFile) < 0
+        ||  ferror(pCache->pFile))
+    {
+        int iErr = errno;
+        fclose(pCache->pFile);
+        UnlinkFileInDir(pCache->pszName, pCache->pszDir);
+        FatalDie("Stream error occured while writing '%s' in '%s': %s\n",
+                 pCache->pszName, pCache->pszDir, strerror(iErr));
+    }
+    if (setvbuf(pCache->pFile, NULL, _IONBF, 0) != 0)
+        FatalDie("setvbuf(,0,,0) failed: %s\n", strerror(errno));
+
+    cb = lseek(pCache->fd, 0, SEEK_CUR);
+    if (cb == -1)
+        FatalDie("lseek(cache-file,0,CUR) failed: %s\n", strerror(errno));
+#if defined(__WIN__)
+    if (_chsize(pCache->fd, cb) == -1)
+#else
+    if (ftruncate(pCache->fd, cb) == -1)
+#endif
+        FatalDie("file truncation failed: %s\n", strerror(errno));
+    InfoMsg(4, "wrote '%s' in '%s', %d bytes\n", pCache->pszName, pCache->pszDir, cb);
+}
+
+
+/**
+ * Cleans out all invalid digests.s
+ *
+ * This is done periodically from the unlock routine to make
+ * sure we don't accidentally accumulate stale digests.
+ *
+ * @param   pCache      The cache to chek.
+ */
+static void kObjCacheClean(PKOBJCACHE pCache)
+{
+    unsigned i = pCache->cDigests;
+    while (i-- > 0)
+    {
+        /*
+         * Try open it and purge it if it's bad.
+         * (We don't kill the entry file because that's kmk clean's job.)
+         */
+        PCKOCDIGEST pDigest = &pCache->paDigests[i];
+        PKOCENTRY pEntry = kOCEntryCreate(kOCDigestAbsPath(pDigest, pCache->pszDir));
+        kOCEntryRead(pEntry);
+        if (    !kOCEntryCheck(pEntry)
+            ||  !kOCDigestIsValid(pDigest, pEntry))
+        {
+            unsigned cLeft;
+            kOCDigestPurge(pDigest);
+
+            pCache->cDigests--;
+            cLeft = pCache->cDigests - i;
+            if (cLeft)
+                memmove(pDigest, pDigest + 1, cLeft * sizeof(*pDigest));
+
+            pCache->fDirty = 1;
+        }
+        kOCEntryDestroy(pEntry);
+    }
+}
+
+
+/**
+ * Locks the cache for exclusive access.
+ *
+ * This will open the file if necessary and lock the entire file
+ * using the best suitable platform API (tricky).
+ *
+ * @param   pCache      The cache to lock.
+ */
+static void kObjCacheLock(PKOBJCACHE pCache)
+{
+    struct stat st;
+#if defined(__WIN__)
+    OVERLAPPED OverLapped;
+#endif
+
+    assert(!pCache->fLocked);
+
+    /*
+     * Open it?
+     */
+    if (pCache->fd < 0)
+    {
+        pCache->fd = OpenFileInDir(pCache->pszName, pCache->pszDir, O_CREAT | O_RDWR | O_BINARY, 0666);
+        if (pCache->fd == -1)
+        {
+            MakePath(pCache->pszDir);
+            pCache->fd = OpenFileInDir(pCache->pszName, pCache->pszDir, O_CREAT | O_RDWR | O_BINARY, 0666);
+            if (pCache->fd == -1)
+                FatalDie("Failed to create '%s' in '%s': %s\n", pCache->pszName, pCache->pszDir, strerror(errno));
+        }
+
+        pCache->pFile = fdopen(pCache->fd, "r+b");
+        if (!pCache->pFile)
+            FatalDie("fdopen failed: %s\n", strerror(errno));
+        if (setvbuf(pCache->pFile, NULL, _IONBF, 0) != 0)
+            FatalDie("setvbuf(,0,,0) failed: %s\n", strerror(errno));
+    }
+
+    /*
+     * Lock it.
+     */
+#if defined(__WIN__)
+    memset(&OverLapped, 0, sizeof(OverLapped));
+    if (!LockFileEx((HANDLE)_get_osfhandle(pCache->fd), LOCKFILE_EXCLUSIVE_LOCK, 0, ~0, 0, &OverLapped))
+        FatalDie("Failed to lock the cache file: Windows Error %d\n", GetLastError());
+#elif defined(__sun__)
+    {
+        struct flock fl;
+        fl.l_whence = 0;
+        fl.l_start = 0;
+        fl.l_len = 0;
+        fl.l_type = F_WRLCK;
+        if (fcntl(pCache->fd, F_SETLKW, &fl) != 0)
+            FatalDie("Failed to lock the cache file: %s\n", strerror(errno));
+    }
+#else
+    if (flock(pCache->fd, LOCK_EX) != 0)
+        FatalDie("Failed to lock the cache file: %s\n", strerror(errno));
+#endif
+    pCache->fLocked = 1;
+
+    /*
+     * Check for new cache and read it it's an existing cache.
+     *
+     * There is no point in initializing a new cache until we've finished
+     * compiling and has something to put into it, so we'll leave it as a
+     * 0 byte file.
+     */
+    if (fstat(pCache->fd, &st) == -1)
+        FatalDie("fstat(cache-fd) failed: %s\n", strerror(errno));
+    if (st.st_size)
+        kObjCacheRead(pCache);
+    else
+    {
+        pCache->fNewCache = 1;
+        InfoMsg(2, "the cache file is empty\n");
+    }
+}
+
+
+/**
+ * Unlocks the cache (without writing anything back).
+ *
+ * @param   pCache      The cache to unlock.
+ */
+static void kObjCacheUnlock(PKOBJCACHE pCache)
+{
+#if defined(__WIN__)
+    OVERLAPPED OverLapped;
+#endif
+    assert(pCache->fLocked);
+
+    /*
+     * Write it back if it's dirty.
+     */
+    if (pCache->fDirty)
+    {
+        if (    pCache->cDigests >= 16
+            &&  (pCache->uGeneration % 19) == 19)
+            kObjCacheClean(pCache);
+        kObjCacheWrite(pCache);
+        pCache->fDirty = 0;
+    }
+
+    /*
+     * Lock it.
+     */
+#if defined(__WIN__)
+    memset(&OverLapped, 0, sizeof(OverLapped));
+    if (!UnlockFileEx((HANDLE)_get_osfhandle(pCache->fd), 0, ~0U, 0, &OverLapped))
+        FatalDie("Failed to unlock the cache file: Windows Error %d\n", GetLastError());
+#elif defined(__sun__)
+    {
+        struct flock fl;
+        fl.l_whence = 0;
+        fl.l_start = 0;
+        fl.l_len = 0;
+        fl.l_type = F_UNLCK;
+        if (fcntl(pCache->fd, F_SETLKW, &fl) != 0)
+            FatalDie("Failed to lock the cache file: %s\n", strerror(errno));
+    }
+#else
+    if (flock(pCache->fd, LOCK_UN) != 0)
+        FatalDie("Failed to unlock the cache file: %s\n", strerror(errno));
+#endif
+    pCache->fLocked = 0;
+}
+
+
+/**
+ * Removes the entry from the cache.
+ *
+ * The entry doesn't need to be in the cache.
+ * The cache entry (file) itself is not touched.
+ *
+ * @param   pCache      The cache.
+ * @param   pEntry      The entry.
+ */
+static void kObjCacheRemoveEntry(PKOBJCACHE pCache, PCKOCENTRY pEntry)
+{
+    unsigned i = pCache->cDigests;
+    while (i-- > 0)
+    {
+        PKOCDIGEST pDigest = &pCache->paDigests[i];
+        if (ArePathsIdentical(kOCDigestAbsPath(pDigest, pCache->pszDir),
+                              kOCEntryAbsPath(pEntry), ~0U))
+        {
+            unsigned cLeft;
+            kOCDigestPurge(pDigest);
+
+            pCache->cDigests--;
+            cLeft = pCache->cDigests - i;
+            if (cLeft)
+                memmove(pDigest, pDigest + 1, cLeft * sizeof(*pDigest));
+
+            pCache->fDirty = 1;
+            InfoMsg(3, "removing entry '%s'; %d left.\n", kOCEntryAbsPath(pEntry), pCache->cDigests);
+        }
+    }
+}
+
+
+/**
+ * Inserts the entry into the cache.
+ *
+ * The cache entry (file) itself is not touched by this operation,
+ * the pEntry object otoh is.
+ *
+ * @param   pCache      The cache.
+ * @param   pEntry      The entry.
+ */
+static void kObjCacheInsertEntry(PKOBJCACHE pCache, PKOCENTRY pEntry)
+{
+    unsigned i;
+
+    /*
+     * Find a new key.
+     */
+    pEntry->uKey = pCache->uNextKey++;
+    if (!pEntry->uKey)
+        pEntry->uKey = pCache->uNextKey++;
+    i = pCache->cDigests;
+    while (i-- > 0)
+        if (pCache->paDigests[i].uKey == pEntry->uKey)
+        {
+            pEntry->uKey = pCache->uNextKey++;
+            if (!pEntry->uKey)
+                pEntry->uKey = pCache->uNextKey++;
+            i = pCache->cDigests;
+        }
+
+    /*
+     * Reallocate the digest array?
+     */
+    if (    !(pCache->cDigests & 3)
+        &&  (pCache->cDigests || !pCache->paDigests))
+        pCache->paDigests = xrealloc(pCache->paDigests, sizeof(pCache->paDigests[0]) * (pCache->cDigests + 4));
+
+    /*
+     * Create a new digest.
+     */
+    kOCDigestInitFromEntry(&pCache->paDigests[pCache->cDigests], pEntry);
+    pCache->cDigests++;
+    InfoMsg(4, "Inserted digest #%u: %s\n", pCache->cDigests - 1, kOCEntryAbsPath(pEntry));
+
+    pCache->fDirty = 1;
+}
+
+
+/**
+ * Find a matching cache entry.
+ */
+static PKOCENTRY kObjCacheFindMatchingEntry(PKOBJCACHE pCache, PCKOCENTRY pEntry)
+{
+    unsigned i = pCache->cDigests;
+
+    assert(pEntry->fNeedCompiling);
+    assert(!kOCSumIsEmpty(&pEntry->New.SumCompArgv));
+    assert(!kOCSumIsEmpty(&pEntry->New.SumHead));
+
+    while (i-- > 0)
+    {
+        /*
+         * Matching?
+         */
+        PCKOCDIGEST pDigest = &pCache->paDigests[i];
+        if (    kOCSumIsEqual(&pDigest->SumCompArgv, &pEntry->New.SumCompArgv)
+            &&  kOCSumHasEqualInChain(&pDigest->SumHead, &pEntry->New.SumHead))
+        {
+            /*
+             * Try open it.
+             */
+            unsigned cLeft;
+            PKOCENTRY pRetEntry = kOCEntryCreate(kOCDigestAbsPath(pDigest, pCache->pszDir));
+            kOCEntryRead(pRetEntry);
+            if (    kOCEntryCheck(pRetEntry)
+                &&  kOCDigestIsValid(pDigest, pRetEntry))
+                return pRetEntry;
+            kOCEntryDestroy(pRetEntry);
+
+            /* bad entry, purge it. */
+            InfoMsg(3, "removing bad digest '%s'\n", kOCDigestAbsPath(pDigest, pCache->pszDir));
+            kOCDigestPurge(pDigest);
+
+            pCache->cDigests--;
+            cLeft = pCache->cDigests - i;
+            if (cLeft)
+                memmove(pDigest, pDigest + 1, cLeft * sizeof(*pDigest));
+
+            pCache->fDirty = 1;
+        }
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Is this a new cache?
+ *
+ * @returns 1 if new, 0 if not new.
+ * @param   pEntry      The entry.
+ */
+static int kObjCacheIsNew(PKOBJCACHE pCache)
+{
+    return pCache->fNewCache;
+}
+
+
+/**
+ * Prints a syntax error and returns the appropriate exit code
+ *
+ * @returns approriate exit code.
+ * @param   pszFormat   The syntax error message.
+ * @param   ...         Message args.
+ */
+static int SyntaxError(const char *pszFormat, ...)
+{
+    va_list va;
+    fprintf(stderr, "kObjCache: syntax error: ");
+    va_start(va, pszFormat);
+    vfprintf(stderr, pszFormat, va);
+    va_end(va);
+    return 1;
+}
+
+
+/**
+ * Prints the usage.
+ * @returns 0.
+ */
+static int usage(FILE *pOut)
+{
+    fprintf(pOut,
+            "syntax: kObjCache [--kObjCache-options] [-v|--verbose]\n"
+            "            <  [-c|--cache-file <cache-file>]\n"
+            "             | [-n|--name <name-in-cache>] [[-d|--cache-dir <cache-dir>]] >\n"
+            "            <-f|--file <local-cache-file>>\n"
+            "            <-t|--target <target-name>>\n"
+            "            [-r|--redir-stdout] [-p|--passthru]\n"
+            "            --kObjCache-cpp <filename> <precompiler + args>\n"
+            "            --kObjCache-cc <object> <compiler + args>\n"
+            "            [--kObjCache-both [args]]\n"
+            );
+    fprintf(pOut,
+            "            [--kObjCache-cpp|--kObjCache-cc [more args]]\n"
+            "        kObjCache <-V|--version>\n"
+            "        kObjCache [-?|/?|-h|/h|--help|/help]\n"
+            "\n"
+            "The env.var. KOBJCACHE_DIR sets the default cache diretory (-d).\n"
+            "The env.var. KOBJCACHE_OPTS allow you to specifie additional options\n"
+            "without having to mess with the makefiles. These are appended with "
+            "a --kObjCache-options between them and the command args.\n"
+            "\n");
+    return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+    PKOBJCACHE pCache;
+    PKOCENTRY pEntry;
+
+    const char *pszCacheDir = getenv("KOBJCACHE_DIR");
+    const char *pszCacheName = NULL;
+    const char *pszCacheFile = NULL;
+    const char *pszEntryFile = NULL;
+
+    const char **papszArgvPreComp = NULL;
+    unsigned cArgvPreComp = 0;
+    const char *pszPreCompName = NULL;
+    int fRedirPreCompStdOut = 0;
+
+    const char **papszArgvCompile = NULL;
+    unsigned cArgvCompile = 0;
+    const char *pszObjName = NULL;
+    int fRedirCompileStdIn = 0;
+
+    const char *pszTarget = NULL;
+
+    enum { kOC_Options, kOC_CppArgv, kOC_CcArgv, kOC_BothArgv } enmMode = kOC_Options;
+
+    size_t cch;
+    char *psz;
+    int i;
+
+    SetErrorPrefix("kObjCache");
+
+    /*
+     * Arguments passed in the environmnet?
+     */
+    psz = getenv("KOBJCACHE_OPTS");
+    if (psz)
+        AppendArgs(&argc, &argv, psz, "--kObjCache-options");
+
+    /*
+     * Parse the arguments.
+     */
+    if (argc <= 1)
+        return usage(stderr);
+    for (i = 1; i < argc; i++)
+    {
+        if (!strcmp(argv[i], "--kObjCache-cpp"))
+        {
+            enmMode = kOC_CppArgv;
+            if (!pszPreCompName)
+            {
+                if (++i >= argc)
+                    return SyntaxError("--kObjCache-cpp requires an object filename!\n");
+                pszPreCompName = argv[i];
+            }
+        }
+        else if (!strcmp(argv[i], "--kObjCache-cc"))
+        {
+            enmMode = kOC_CcArgv;
+            if (!pszObjName)
+            {
+                if (++i >= argc)
+                    return SyntaxError("--kObjCache-cc requires an precompiler output filename!\n");
+                pszObjName = argv[i];
+            }
+        }
+        else if (!strcmp(argv[i], "--kObjCache-both"))
+            enmMode = kOC_BothArgv;
+        else if (!strcmp(argv[i], "--kObjCache-options"))
+            enmMode = kOC_Options;
+        else if (!strcmp(argv[i], "--help"))
+            return usage(stderr);
+        else if (enmMode != kOC_Options)
+        {
+            if (enmMode == kOC_CppArgv || enmMode == kOC_BothArgv)
+            {
+                if (!(cArgvPreComp % 16))
+                    papszArgvPreComp = xrealloc((void *)papszArgvPreComp, (cArgvPreComp + 17) * sizeof(papszArgvPreComp[0]));
+                papszArgvPreComp[cArgvPreComp++] = argv[i];
+                papszArgvPreComp[cArgvPreComp] = NULL;
+            }
+            if (enmMode == kOC_CcArgv || enmMode == kOC_BothArgv)
+            {
+                if (!(cArgvCompile % 16))
+                    papszArgvCompile = xrealloc((void *)papszArgvCompile, (cArgvCompile + 17) * sizeof(papszArgvCompile[0]));
+                papszArgvCompile[cArgvCompile++] = argv[i];
+                papszArgvCompile[cArgvCompile] = NULL;
+            }
+        }
+        else if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--entry-file"))
+        {
+            if (i + 1 >= argc)
+                return SyntaxError("%s requires a cache entry filename!\n", argv[i]);
+            pszEntryFile = argv[++i];
+        }
+        else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--cache-file"))
+        {
+            if (i + 1 >= argc)
+                return SyntaxError("%s requires a cache filename!\n", argv[i]);
+            pszCacheFile = argv[++i];
+        }
+        else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--name"))
+        {
+            if (i + 1 >= argc)
+                return SyntaxError("%s requires a cache name!\n", argv[i]);
+            pszCacheName = argv[++i];
+        }
+        else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--cache-dir"))
+        {
+            if (i + 1 >= argc)
+                return SyntaxError("%s requires a cache directory!\n", argv[i]);
+            pszCacheDir = argv[++i];
+        }
+        else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "--target"))
+        {
+            if (i + 1 >= argc)
+                return SyntaxError("%s requires a target platform/arch name!\n", argv[i]);
+            pszTarget = argv[++i];
+        }
+        else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--passthru"))
+            fRedirPreCompStdOut = fRedirCompileStdIn = 1;
+        else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--redir-stdout"))
+            fRedirPreCompStdOut = 1;
+        else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose"))
+            g_cVerbosityLevel++;
+        else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--quiet"))
+            g_cVerbosityLevel = 0;
+        else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-?")
+              || !strcmp(argv[i], "/h") || !strcmp(argv[i], "/?") || !strcmp(argv[i], "/help"))
+        {
+            usage(stdout);
+            return 0;
+        }
+        else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version"))
+        {
+            printf("kObjCache - kBuild version %d.%d.%d ($Revision$)\n"
+                   "Copyright (C) 2007 Knut St. Osmundsen\n",
+                   KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH);
+            return 0;
+        }
+        else
+            return SyntaxError("Doesn't grok '%s'!\n", argv[i]);
+    }
+    if (!pszEntryFile)
+        return SyntaxError("No cache entry filename (-f)!\n");
+    if (!pszTarget)
+        return SyntaxError("No target name (-t)!\n");
+    if (!cArgvCompile)
+        return SyntaxError("No compiler arguments (--kObjCache-cc)!\n");
+    if (!cArgvPreComp)
+        return SyntaxError("No precompiler arguments (--kObjCache-cc)!\n");
+
+    /*
+     * Calc the cache file name.
+     * It's a bit messy since the extension has to be replaced.
+     */
+    if (!pszCacheFile)
+    {
+        if (!pszCacheDir)
+            return SyntaxError("No cache dir (-d / KOBJCACHE_DIR) and no cache filename!\n");
+        if (!pszCacheName)
+        {
+            psz = (char *)FindFilenameInPath(pszEntryFile);
+            if (!*psz)
+                return SyntaxError("The cache file (-f) specifies a directory / nothing!\n");
+            cch = psz - pszEntryFile;
+            pszCacheName = memcpy(xmalloc(cch + 5), psz, cch + 1);
+            psz = strrchr(pszCacheName, '.');
+            if (!psz || psz <= pszCacheName)
+                psz = (char *)pszCacheName + cch;
+            memcpy(psz, ".koc", sizeof(".koc") - 1);
+        }
+        pszCacheFile = MakePathFromDirAndFile(pszCacheName, pszCacheDir);
+    }
+
+    /*
+     * Create and initialize the two objects we'll be working on.
+     *
+     * We're supposed to be the only ones actually writing to the local file,
+     * so it's perfectly fine to read it here before we lock it. This simplifies
+     * the detection of object name and compiler argument changes.
+     */
+    SetErrorPrefix("kObjCache - %s", FindFilenameInPath(pszCacheFile));
+    pCache = kObjCacheCreate(pszCacheFile);
+
+    pEntry = kOCEntryCreate(pszEntryFile);
+    kOCEntryRead(pEntry);
+    kOCEntrySetCompileObjName(pEntry, pszObjName);
+    kOCEntrySetCompileArgv(pEntry, papszArgvCompile, cArgvCompile);
+    kOCEntrySetTarget(pEntry, pszTarget);
+    kOCEntrySetCppName(pEntry, pszPreCompName);
+    kOCEntrySetPipedMode(pEntry, fRedirPreCompStdOut, fRedirCompileStdIn);
+
+    /*
+     * Open (& lock) the two files and do validity checks and such.
+     */
+    kObjCacheLock(pCache);
+    if (    kObjCacheIsNew(pCache)
+        &&  kOCEntryNeedsCompiling(pEntry))
+    {
+        /*
+         * Both files are missing/invalid.
+         * Optimize this path as it is frequently used when making a clean build.
+         */
+        kObjCacheUnlock(pCache);
+        InfoMsg(1, "doing full compile\n");
+        kOCEntryPreCompileAndCompile(pEntry, papszArgvPreComp, cArgvPreComp);
+        kObjCacheLock(pCache);
+    }
+    else
+    {
+        /*
+         * Do the precompile (don't need to lock the cache file for this).
+         */
+        kObjCacheUnlock(pCache);
+        kOCEntryPreCompile(pEntry, papszArgvPreComp, cArgvPreComp);
+
+        /*
+         * Check if we need to recompile. If we do, try see if the is a cache entry first.
+         */
+        kOCEntryCalcRecompile(pEntry);
+        if (kOCEntryNeedsCompiling(pEntry))
+        {
+            PKOCENTRY pUseEntry;
+            kObjCacheLock(pCache);
+            kObjCacheRemoveEntry(pCache, pEntry);
+            pUseEntry = kObjCacheFindMatchingEntry(pCache, pEntry);
+            if (pUseEntry)
+            {
+                InfoMsg(1, "using cache entry '%s'\n", kOCEntryAbsPath(pUseEntry));
+                kOCEntryCopy(pEntry, pUseEntry);
+                kOCEntryDestroy(pUseEntry);
+            }
+            else
+            {
+                kObjCacheUnlock(pCache);
+                InfoMsg(1, "recompiling\n");
+                kOCEntryCompileIt(pEntry);
+                kObjCacheLock(pCache);
+            }
+        }
+        else
+        {
+            InfoMsg(1, "no need to recompile\n");
+            kObjCacheLock(pCache);
+        }
+    }
+
+    /*
+     * Update the cache files.
+     */
+    kObjCacheRemoveEntry(pCache, pEntry);
+    kObjCacheInsertEntry(pCache, pEntry);
+    kOCEntryWrite(pEntry);
+    kObjCacheUnlock(pCache);
+    kObjCacheDestroy(pCache);
+    return 0;
+}
+
+
+/** @page kObjCache Benchmarks.
+ *
+ * (2007-06-10)
+ *
+ * Mac OS X debug -j 3 cached clobber build (rm -Rf out ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 USE_KOBJCACHE=1):
+ *  real    11m28.811s
+ *  user    13m59.291s
+ *  sys     3m24.590s
+ *
+ * Mac OS X debug -j 3 cached depend build [cdefs.h] (touch include/iprt/cdefs.h ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 USE_KOBJCACHE=1):
+ *  real    1m26.895s
+ *  user    1m26.971s
+ *  sys     0m32.532s
+ *
+ * Mac OS X debug -j 3 cached depend build [err.h] (touch include/iprt/err.h ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 USE_KOBJCACHE=1):
+ *  real    1m18.049s
+ *  user    1m20.462s
+ *  sys     0m27.887s
+ *
+ * Mac OS X release -j 3 cached clobber build (rm -Rf out/darwin.x86/release ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 USE_KOBJCACHE=1 BUILD_TYPE=release):
+ *  real    13m27.751s
+ *  user    18m12.654s
+ *  sys     3m25.170s
+ *
+ * Mac OS X profile -j 3 cached clobber build (rm -Rf out/darwin.x86/profile ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 USE_KOBJCACHE=1 BUILD_TYPE=profile):
+ *  real    9m9.720s
+ *  user    8m53.005s
+ *  sys     2m13.110s
+ *
+ * Mac OS X debug -j 3 clobber build (rm -Rf out/darwin.x86/debug ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 BUILD_TYPE=debug):
+ *  real    10m18.129s
+ *  user    12m52.687s
+ *  sys     2m51.277s
+ *
+ * Mac OS X debug -j 3 debug build [cdefs.h] (touch include/iprt/cdefs.h ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 BUILD_TYPE=debug):
+ *  real    4m46.147s
+ *  user    5m27.087s
+ *  sys     1m11.775s
+ *
+ * Mac OS X debug -j 3 debug build [err.h] (touch include/iprt/cdefs.h ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 BUILD_TYPE=debug):
+ *  real    4m17.572s
+ *  user    5m7.450s
+ *  sys     1m3.450s
+ *
+ * Mac OS X release -j 3 clobber build (rm -Rf out/darwin.x86/release ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 BUILD_TYPE=release):
+ *  real    12m14.742s
+ *  user    17m11.794s
+ *  sys     2m51.454s
+ *
+ * Mac OS X profile -j 3 clobber build (rm -Rf out/darwin.x86/profile ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 BUILD_TYPE=profile):
+ *  real    12m33.821s
+ *  user    17m35.086s
+ *  sys     2m53.312s
+ *
+ * Note. The profile build can pick object files from the release build.
+ * (all with KOBJCACHE_OPTS=-v; which means a bit more output and perhaps a second or two slower.)
+ */
+
Index: /tags/kBuild-0.1.4/src/kash/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kash/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/Makefile.kmk	(revision 1780)
@@ -0,0 +1,170 @@
+# $Id$
+## @file
+# Sub-makefile for kash.
+#
+
+#
+# Copyright (c) 2005-2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# The program.
+#
+PROGRAMS += kash
+kash_TEMPLATE = BIN
+kash_DEFS = lint SHELL SMALL
+kash_DEFS += SH_STUB_MODE # for the time being.
+kash_DEFS.debug = DEBUG
+kash_DEFS.linux = BSD
+kash_DEFS.solaris = BSD
+kash_DEFS.win = \
+	BSD PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS YY_NO_UNISTD_H
+kash_DEFS.os2 = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME \
+	EXEC_HASH_BANG_SCRIPT PC_OS2_LIBPATHS PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS
+kash_DEFS.darwin = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
+kash_DEFS.dragonfly = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
+kash_DEFS.freebsd = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
+kash_INCS = $(PATH_kash) . # (the last is because of error.h)
+kash_SOURCES = \
+	main.c \
+	alias.c \
+	cd.c \
+	error.c \
+	eval.c \
+	exec.c \
+	expand.c \
+	histedit.c \
+	input.c \
+	jobs.c \
+	mail.c \
+	memalloc.c \
+	mystring.c \
+	options.c \
+	output.c \
+	parser.c \
+	redir.c \
+	show.c \
+	syntax.c \
+	trap.c \
+	var.c \
+	miscbltin.c \
+	bltin/echo.c \
+	bltin/kill.c \
+	bltin/test.c \
+	\
+	$(PATH_kash)/arith.c \
+	$(PATH_kash)/arith_lex.c \
+	$(PATH_kash)/builtins.c \
+	$(PATH_kash)/init.c \
+	$(PATH_kash)/nodes.c \
+	\
+	setmode.c \
+	shinstance.c \
+	shthread.c \
+	shfile.c
+kash_SOURCES.linux = \
+	sys_signame.c \
+	strlcpy.c
+kash_SOURCES.win = \
+	sys_signame.c \
+	strlcpy.c
+kash_SOURCES.solaris = \
+	sys_signame.c \
+	strlcpy.c
+
+kash_ORDERDEPS = \
+	$(PATH_kash)/arith.h \
+	$(PATH_kash)/builtins.h \
+	$(PATH_kash)/nodes.h \
+	$(PATH_kash)/token.h
+kash_CLEAN = \
+	$(kash_ORDERDEPS)	\
+	$(PATH_kash)/arith.c \
+	$(PATH_kash)/arith_lex.c \
+	$(PATH_kash)/builtins.c \
+	$(PATH_kash)/init.c \
+	$(PATH_kash)/nodes.c
+
+##
+## The manual page.
+##
+#INSTALLS += kash.man
+#kash.man_TEMPLATE = usr.bin.man
+#kash.man_SOURCES = sh.1=>kash.1
+
+
+ifeq ($(filter-out win,$(KBUILD_TARGET)),)
+
+#
+# Use the pregenerated code.
+#
+kash_ORDERDEPS :=
+kash_INCS += generated
+kash_SOURCES := $(patsubst $(PATH_kash)/%,generated/%,$(kash_SOURCES))
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
+else
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
+#
+# ATTENTION! ATTENTION! ATTENTION!
+#
+# Older ash versions has trouble with some of these scripts, great.
+# Kudos to the NetBSD guys for this clever move. ;)
+#
+# So, when building for the frist time, setting BOOSTRAP_SHELL=/bin/bash is good idea.
+#
+BOOTSTRAP_SHELL ?= $(SHELL)
+YACC ?= yacc
+
+$(PATH_kash)/arith.h $(PATH_kash)/arith.c: arith.y | $(call DIRDEP,$(PATH_kash))
+	$(YACC) -ld $^
+	$(MV) -f y.tab.c $(PATH_kash)/arith.c
+	$(MV) -f y.tab.h $(PATH_kash)/arith.h
+
+$(PATH_kash)/arith_lex.c: arith_lex.l | $(call DIRDEP,$(PATH_kash))
+	flex -8 -o$@ $^                     # 8-bit lex scanner for arithmetic
+
+$(PATH_kash)/builtins.h $(PATH_kash)/builtins.c: $(kash_PATH)/mkbuiltins shell.h builtins.def | $(call DIRDEP,$(PATH_kash))
+	$(BOOTSTRAP_SHELL) $+ $(dir $@)
+	[ -f $(PATH_kash)/builtins.h ]
+
+$(PATH_kash)/nodes.h $(PATH_kash)/nodes.c: $(kash_PATH)/mknodes.sh nodetypes nodes.c.pat | $(call DIRDEP,$(PATH_kash))
+	$(BOOTSTRAP_SHELL) $+ $(dir $@)
+	[ -f $(dir $@)/nodes.h ]
+
+$(PATH_kash)/token.h: $(kash_PATH)/mktokens | $(call DIRDEP,$(PATH_kash))
+	$(BOOTSTRAP_SHELL) $+
+	$(MV) token.h $@
+
+$(PATH_kash)/init.c: $(kash_PATH)/mkinit.sh $(filter-out $(PATH_kash)/%,$(kash_SOURCES)) | $(call DIRDEP,$(PATH_kash))
+	$(BOOTSTRAP_SHELL) $+
+	$(MV) init.c $@
+
+endif
Index: /tags/kBuild-0.1.4/src/kash/TOUR
===================================================================
--- /tags/kBuild-0.1.4/src/kash/TOUR	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/TOUR	(revision 1780)
@@ -0,0 +1,357 @@
+#	$NetBSD: TOUR,v 1.8 1996/10/16 14:24:56 christos Exp $
+#	@(#)TOUR	8.1 (Berkeley) 5/31/93
+
+NOTE -- This is the original TOUR paper distributed with ash and
+does not represent the current state of the shell.  It is provided anyway
+since it provides helpful information for how the shell is structured,
+but be warned that things have changed -- the current shell is
+still under development.
+
+================================================================
+
+                       A Tour through Ash
+
+               Copyright 1989 by Kenneth Almquist.
+
+
+DIRECTORIES:  The subdirectory bltin contains commands which can
+be compiled stand-alone.  The rest of the source is in the main
+ash directory.
+
+SOURCE CODE GENERATORS:  Files whose names begin with "mk" are
+programs that generate source code.  A complete list of these
+programs is:
+
+        program         intput files        generates
+        -------         ------------        ---------
+        mkbuiltins      builtins            builtins.h builtins.c
+        mkinit          *.c                 init.c
+        mknodes         nodetypes           nodes.h nodes.c
+        mksignames          -               signames.h signames.c
+        mksyntax            -               syntax.h syntax.c
+        mktokens            -               token.h
+        bltin/mkexpr    unary_op binary_op  operators.h operators.c
+
+There are undoubtedly too many of these.  Mkinit searches all the
+C source files for entries looking like:
+
+        INIT {
+              x = 1;    /* executed during initialization */
+        }
+
+        RESET {
+              x = 2;    /* executed when the shell does a longjmp
+                           back to the main command loop */
+        }
+
+        SHELLPROC {
+              x = 3;    /* executed when the shell runs a shell procedure */
+        }
+
+It pulls this code out into routines which are when particular
+events occur.  The intent is to improve modularity by isolating
+the information about which modules need to be explicitly
+initialized/reset within the modules themselves.
+
+Mkinit recognizes several constructs for placing declarations in
+the init.c file.
+        INCLUDE "file.h"
+includes a file.  The storage class MKINIT makes a declaration
+available in the init.c file, for example:
+        MKINIT int funcnest;    /* depth of function calls */
+MKINIT alone on a line introduces a structure or union declara-
+tion:
+        MKINIT
+        struct redirtab {
+              short renamed[10];
+        };
+Preprocessor #define statements are copied to init.c without any
+special action to request this.
+
+INDENTATION:  The ash source is indented in multiples of six
+spaces.  The only study that I have heard of on the subject con-
+cluded that the optimal amount to indent is in the range of four
+to six spaces.  I use six spaces since it is not too big a jump
+from the widely used eight spaces.  If you really hate six space
+indentation, use the adjind (source included) program to change
+it to something else.
+
+EXCEPTIONS:  Code for dealing with exceptions appears in
+exceptions.c.  The C language doesn't include exception handling,
+so I implement it using setjmp and longjmp.  The global variable
+exception contains the type of exception.  EXERROR is raised by
+calling error.  EXINT is an interrupt.  EXSHELLPROC is an excep-
+tion which is raised when a shell procedure is invoked.  The pur-
+pose of EXSHELLPROC is to perform the cleanup actions associated
+with other exceptions.  After these cleanup actions, the shell
+can interpret a shell procedure itself without exec'ing a new
+copy of the shell.
+
+INTERRUPTS:  In an interactive shell, an interrupt will cause an
+EXINT exception to return to the main command loop.  (Exception:
+EXINT is not raised if the user traps interrupts using the trap
+command.)  The INTOFF and INTON macros (defined in exception.h)
+provide uninterruptable critical sections.  Between the execution
+of INTOFF and the execution of INTON, interrupt signals will be
+held for later delivery.  INTOFF and INTON can be nested.
+
+MEMALLOC.C:  Memalloc.c defines versions of malloc and realloc
+which call error when there is no memory left.  It also defines a
+stack oriented memory allocation scheme.  Allocating off a stack
+is probably more efficient than allocation using malloc, but the
+big advantage is that when an exception occurs all we have to do
+to free up the memory in use at the time of the exception is to
+restore the stack pointer.  The stack is implemented using a
+linked list of blocks.
+
+STPUTC:  If the stack were contiguous, it would be easy to store
+strings on the stack without knowing in advance how long the
+string was going to be:
+        p = stackptr;
+        *p++ = c;       /* repeated as many times as needed */
+        stackptr = p;
+The folloing three macros (defined in memalloc.h) perform these
+operations, but grow the stack if you run off the end:
+        STARTSTACKSTR(p);
+        STPUTC(c, p);   /* repeated as many times as needed */
+        grabstackstr(p);
+
+We now start a top-down look at the code:
+
+MAIN.C:  The main routine performs some initialization, executes
+the user's profile if necessary, and calls cmdloop.  Cmdloop is
+repeatedly parses and executes commands.
+
+OPTIONS.C:  This file contains the option processing code.  It is
+called from main to parse the shell arguments when the shell is
+invoked, and it also contains the set builtin.  The -i and -j op-
+tions (the latter turns on job control) require changes in signal
+handling.  The routines setjobctl (in jobs.c) and setinteractive
+(in trap.c) are called to handle changes to these options.
+
+PARSING:  The parser code is all in parser.c.  A recursive des-
+cent parser is used.  Syntax tables (generated by mksyntax) are
+used to classify characters during lexical analysis.  There are
+three tables:  one for normal use, one for use when inside single
+quotes, and one for use when inside double quotes.  The tables
+are machine dependent because they are indexed by character vari-
+ables and the range of a char varies from machine to machine.
+
+PARSE OUTPUT:  The output of the parser consists of a tree of
+nodes.  The various types of nodes are defined in the file node-
+types.
+
+Nodes of type NARG are used to represent both words and the con-
+tents of here documents.  An early version of ash kept the con-
+tents of here documents in temporary files, but keeping here do-
+cuments in memory typically results in significantly better per-
+formance.  It would have been nice to make it an option to use
+temporary files for here documents, for the benefit of small
+machines, but the code to keep track of when to delete the tem-
+porary files was complex and I never fixed all the bugs in it.
+(AT&T has been maintaining the Bourne shell for more than ten
+years, and to the best of my knowledge they still haven't gotten
+it to handle temporary files correctly in obscure cases.)
+
+The text field of a NARG structure points to the text of the
+word.  The text consists of ordinary characters and a number of
+special codes defined in parser.h.  The special codes are:
+
+        CTLVAR              Variable substitution
+        CTLENDVAR           End of variable substitution
+        CTLBACKQ            Command substitution
+        CTLBACKQ|CTLQUOTE   Command substitution inside double quotes
+        CTLESC              Escape next character
+
+A variable substitution contains the following elements:
+
+        CTLVAR type name '=' [ alternative-text CTLENDVAR ]
+
+The type field is a single character specifying the type of sub-
+stitution.  The possible types are:
+
+        VSNORMAL            $var
+        VSMINUS             ${var-text}
+        VSMINUS|VSNUL       ${var:-text}
+        VSPLUS              ${var+text}
+        VSPLUS|VSNUL        ${var:+text}
+        VSQUESTION          ${var?text}
+        VSQUESTION|VSNUL    ${var:?text}
+        VSASSIGN            ${var=text}
+        VSASSIGN|VSNUL      ${var=text}
+
+In addition, the type field will have the VSQUOTE flag set if the
+variable is enclosed in double quotes.  The name of the variable
+comes next, terminated by an equals sign.  If the type is not
+VSNORMAL, then the text field in the substitution follows, ter-
+minated by a CTLENDVAR byte.
+
+Commands in back quotes are parsed and stored in a linked list.
+The locations of these commands in the string are indicated by
+CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether
+the back quotes were enclosed in double quotes.
+
+The character CTLESC escapes the next character, so that in case
+any of the CTL characters mentioned above appear in the input,
+they can be passed through transparently.  CTLESC is also used to
+escape '*', '?', '[', and '!' characters which were quoted by the
+user and thus should not be used for file name generation.
+
+CTLESC characters have proved to be particularly tricky to get
+right.  In the case of here documents which are not subject to
+variable and command substitution, the parser doesn't insert any
+CTLESC characters to begin with (so the contents of the text
+field can be written without any processing).  Other here docu-
+ments, and words which are not subject to splitting and file name
+generation, have the CTLESC characters removed during the vari-
+able and command substitution phase.  Words which are subject
+splitting and file name generation have the CTLESC characters re-
+moved as part of the file name phase.
+
+EXECUTION:  Command execution is handled by the following files:
+        eval.c     The top level routines.
+        redir.c    Code to handle redirection of input and output.
+        jobs.c     Code to handle forking, waiting, and job control.
+        exec.c     Code to to path searches and the actual exec sys call.
+        expand.c   Code to evaluate arguments.
+        var.c      Maintains the variable symbol table.  Called from expand.c.
+
+EVAL.C:  Evaltree recursively executes a parse tree.  The exit
+status is returned in the global variable exitstatus.  The alter-
+native entry evalbackcmd is called to evaluate commands in back
+quotes.  It saves the result in memory if the command is a buil-
+tin; otherwise it forks off a child to execute the command and
+connects the standard output of the child to a pipe.
+
+JOBS.C:  To create a process, you call makejob to return a job
+structure, and then call forkshell (passing the job structure as
+an argument) to create the process.  Waitforjob waits for a job
+to complete.  These routines take care of process groups if job
+control is defined.
+
+REDIR.C:  Ash allows file descriptors to be redirected and then
+restored without forking off a child process.  This is accom-
+plished by duplicating the original file descriptors.  The redir-
+tab structure records where the file descriptors have be dupli-
+cated to.
+
+EXEC.C:  The routine find_command locates a command, and enters
+the command in the hash table if it is not already there.  The
+third argument specifies whether it is to print an error message
+if the command is not found.  (When a pipeline is set up,
+find_command is called for all the commands in the pipeline be-
+fore any forking is done, so to get the commands into the hash
+table of the parent process.  But to make command hashing as
+transparent as possible, we silently ignore errors at that point
+and only print error messages if the command cannot be found
+later.)
+
+The routine shellexec is the interface to the exec system call.
+
+EXPAND.C:  Arguments are processed in three passes.  The first
+(performed by the routine argstr) performs variable and command
+substitution.  The second (ifsbreakup) performs word splitting
+and the third (expandmeta) performs file name generation.  If the
+"/u" directory is simulated, then when "/u/username" is replaced
+by the user's home directory, the flag "didudir" is set.  This
+tells the cd command that it should print out the directory name,
+just as it would if the "/u" directory were implemented using
+symbolic links.
+
+VAR.C:  Variables are stored in a hash table.  Probably we should
+switch to extensible hashing.  The variable name is stored in the
+same string as the value (using the format "name=value") so that
+no string copying is needed to create the environment of a com-
+mand.  Variables which the shell references internally are preal-
+located so that the shell can reference the values of these vari-
+ables without doing a lookup.
+
+When a program is run, the code in eval.c sticks any environment
+variables which precede the command (as in "PATH=xxx command") in
+the variable table as the simplest way to strip duplicates, and
+then calls "environment" to get the value of the environment.
+There are two consequences of this.  First, if an assignment to
+PATH precedes the command, the value of PATH before the assign-
+ment must be remembered and passed to shellexec.  Second, if the
+program turns out to be a shell procedure, the strings from the
+environment variables which preceded the command must be pulled
+out of the table and replaced with strings obtained from malloc,
+since the former will automatically be freed when the stack (see
+the entry on memalloc.c) is emptied.
+
+BUILTIN COMMANDS:  The procedures for handling these are scat-
+tered throughout the code, depending on which location appears
+most appropriate.  They can be recognized because their names al-
+ways end in "cmd".  The mapping from names to procedures is
+specified in the file builtins, which is processed by the mkbuil-
+tins command.
+
+A builtin command is invoked with argc and argv set up like a
+normal program.  A builtin command is allowed to overwrite its
+arguments.  Builtin routines can call nextopt to do option pars-
+ing.  This is kind of like getopt, but you don't pass argc and
+argv to it.  Builtin routines can also call error.  This routine
+normally terminates the shell (or returns to the main command
+loop if the shell is interactive), but when called from a builtin
+command it causes the builtin command to terminate with an exit
+status of 2.
+
+The directory bltins contains commands which can be compiled in-
+dependently but can also be built into the shell for efficiency
+reasons.  The makefile in this directory compiles these programs
+in the normal fashion (so that they can be run regardless of
+whether the invoker is ash), but also creates a library named
+bltinlib.a which can be linked with ash.  The header file bltin.h
+takes care of most of the differences between the ash and the
+stand-alone environment.  The user should call the main routine
+"main", and #define main to be the name of the routine to use
+when the program is linked into ash.  This #define should appear
+before bltin.h is included; bltin.h will #undef main if the pro-
+gram is to be compiled stand-alone.
+
+CD.C:  This file defines the cd and pwd builtins.  The pwd com-
+mand runs /bin/pwd the first time it is invoked (unless the user
+has already done a cd to an absolute pathname), but then
+remembers the current directory and updates it when the cd com-
+mand is run, so subsequent pwd commands run very fast.  The main
+complication in the cd command is in the docd command, which
+resolves symbolic links into actual names and informs the user
+where the user ended up if he crossed a symbolic link.
+
+SIGNALS:  Trap.c implements the trap command.  The routine set-
+signal figures out what action should be taken when a signal is
+received and invokes the signal system call to set the signal ac-
+tion appropriately.  When a signal that a user has set a trap for
+is caught, the routine "onsig" sets a flag.  The routine dotrap
+is called at appropriate points to actually handle the signal.
+When an interrupt is caught and no trap has been set for that
+signal, the routine "onint" in error.c is called.
+
+OUTPUT:  Ash uses it's own output routines.  There are three out-
+put structures allocated.  "Output" represents the standard out-
+put, "errout" the standard error, and "memout" contains output
+which is to be stored in memory.  This last is used when a buil-
+tin command appears in backquotes, to allow its output to be col-
+lected without doing any I/O through the UNIX operating system.
+The variables out1 and out2 normally point to output and errout,
+respectively, but they are set to point to memout when appropri-
+ate inside backquotes.
+
+INPUT:  The basic input routine is pgetc, which reads from the
+current input file.  There is a stack of input files; the current
+input file is the top file on this stack.  The code allows the
+input to come from a string rather than a file.  (This is for the
+-c option and the "." and eval builtin commands.)  The global
+variable plinno is saved and restored when files are pushed and
+popped from the stack.  The parser routines store the number of
+the current line in this variable.
+
+DEBUGGING:  If DEBUG is defined in shell.h, then the shell will
+write debugging information to the file $HOME/trace.  Most of
+this is done using the TRACE macro, which takes a set of printf
+arguments inside two sets of parenthesis.  Example:
+"TRACE(("n=%d0, n))".  The double parenthesis are necessary be-
+cause the preprocessor can't handle functions with a variable
+number of arguments.  Defining DEBUG also causes the shell to
+generate a core dump if it is sent a quit signal.  The tracing
+code is in show.c.
Index: /tags/kBuild-0.1.4/src/kash/alias.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/alias.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/alias.c	(revision 1780)
@@ -0,0 +1,273 @@
+/*	$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)alias.c	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdlib.h>
+#include "shell.h"
+#include "input.h"
+#include "output.h"
+#include "error.h"
+#include "memalloc.h"
+#include "mystring.h"
+#include "alias.h"
+#include "options.h"	/* XXX for argptr (should remove?) */
+#include "var.h"
+#include "shinstance.h"
+
+/*#define ATABSIZE 39
+
+struct alias *atab[ATABSIZE];*/
+
+STATIC void setalias(shinstance *, char *, char *);
+STATIC int unalias(shinstance *, char *);
+STATIC struct alias **hashalias(shinstance *, char *);
+
+STATIC
+void
+setalias(shinstance *psh, char *name, char *val)
+{
+	struct alias *ap, **app;
+
+	app = hashalias(psh, name);
+	for (ap = *app; ap; ap = ap->next) {
+		if (equal(name, ap->name)) {
+			INTOFF;
+			ckfree(ap->val);
+			ap->val	= savestr(val);
+			INTON;
+			return;
+		}
+	}
+	/* not found */
+	INTOFF;
+	ap = ckmalloc(sizeof (struct alias));
+	ap->name = savestr(name);
+	/*
+	 * XXX - HACK: in order that the parser will not finish reading the
+	 * alias value off the input before processing the next alias, we
+	 * dummy up an extra space at the end of the alias.  This is a crock
+	 * and should be re-thought.  The idea (if you feel inclined to help)
+	 * is to avoid alias recursions.  The mechanism used is: when
+	 * expanding an alias, the value of the alias is pushed back on the
+	 * input as a string and a pointer to the alias is stored with the
+	 * string.  The alias is marked as being in use.  When the input
+	 * routine finishes reading the string, it markes the alias not
+	 * in use.  The problem is synchronization with the parser.  Since
+	 * it reads ahead, the alias is marked not in use before the
+	 * resulting token(s) is next checked for further alias sub.  The
+	 * H A C K is that we add a little fluff after the alias value
+	 * so that the string will not be exhausted.  This is a good
+	 * idea ------- ***NOT***
+	 */
+#ifdef notyet
+	ap->val = savestr(val);
+#else /* hack */
+	{
+	size_t len = strlen(val);
+	ap->val = ckmalloc(len + 2);
+	memcpy(ap->val, val, len);
+	ap->val[len] = ' ';	/* fluff */
+	ap->val[len+1] = '\0';
+	}
+#endif
+	ap->next = *app;
+	*app = ap;
+	INTON;
+}
+
+STATIC int
+unalias(shinstance *psh, char *name)
+{
+	struct alias *ap, **app;
+
+	app = hashalias(psh, name);
+
+	for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
+		if (equal(name, ap->name)) {
+			/*
+			 * if the alias is currently in use (i.e. its
+			 * buffer is being used by the input routine) we
+			 * just null out the name instead of freeing it.
+			 * We could clear it out later, but this situation
+			 * is so rare that it hardly seems worth it.
+			 */
+			if (ap->flag & ALIASINUSE)
+				*ap->name = '\0';
+			else {
+				INTOFF;
+				*app = ap->next;
+				ckfree(ap->name);
+				ckfree(ap->val);
+				ckfree(ap);
+				INTON;
+			}
+			return (0);
+		}
+	}
+
+	return (1);
+}
+
+#ifdef mkinit
+MKINIT void rmaliases(shinstance *psh);
+
+SHELLPROC {
+	rmaliases(psh);
+}
+#endif
+
+void
+rmaliases(shinstance *psh)
+{
+	struct alias *ap, *tmp;
+	int i;
+
+	INTOFF;
+	for (i = 0; i < ATABSIZE; i++) {
+		ap = psh->atab[i];
+		psh->atab[i] = NULL;
+		while (ap) {
+			ckfree(ap->name);
+			ckfree(ap->val);
+			tmp = ap;
+			ap = ap->next;
+			ckfree(tmp);
+		}
+	}
+	INTON;
+}
+
+struct alias *
+lookupalias(shinstance *psh, char *name, int check)
+{
+	struct alias *ap = *hashalias(psh, name);
+
+	for (; ap; ap = ap->next) {
+		if (equal(name, ap->name)) {
+			if (check && (ap->flag & ALIASINUSE))
+				return (NULL);
+			return (ap);
+		}
+	}
+
+	return (NULL);
+}
+
+char *
+get_alias_text(shinstance *psh, char *name)
+{
+	struct alias *ap;
+
+	ap = lookupalias(psh, name, 0);
+	if (ap == NULL)
+		return NULL;
+	return ap->val;
+}
+
+/*
+ * TODO - sort output
+ */
+int
+aliascmd(shinstance *psh, int argc, char **argv)
+{
+	char *n, *v;
+	int ret = 0;
+	struct alias *ap;
+
+	if (argc == 1) {
+		int i;
+
+		for (i = 0; i < ATABSIZE; i++)
+			for (ap = psh->atab[i]; ap; ap = ap->next) {
+				if (*ap->name != '\0') {
+					out1fmt(psh, "alias %s=", ap->name);
+					print_quoted(psh, ap->val);
+					out1c(psh, '\n');
+				}
+			}
+		return (0);
+	}
+	while ((n = *++argv) != NULL) {
+		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
+			if ((ap = lookupalias(psh, n, 0)) == NULL) {
+				outfmt(psh->out2, "alias: %s not found\n", n);
+				ret = 1;
+			} else {
+				out1fmt(psh, "alias %s=", n);
+				print_quoted(psh, ap->val);
+				out1c(psh, '\n');
+			}
+		} else {
+			*v++ = '\0';
+			setalias(psh, n, v);
+		}
+	}
+
+	return (ret);
+}
+
+int
+unaliascmd(shinstance *psh, int argc, char **argv)
+{
+	int i;
+
+	while ((i = nextopt(psh, "a")) != '\0') {
+		if (i == 'a') {
+			rmaliases(psh);
+			return (0);
+		}
+	}
+	for (i = 0; *psh->argptr; psh->argptr++)
+		i = unalias(psh, *psh->argptr);
+
+	return (i);
+}
+
+STATIC struct alias **
+hashalias(shinstance *psh, char *p)
+{
+	unsigned int hashval;
+
+	hashval = *p << 4;
+	while (*p)
+		hashval+= *p++;
+	return &psh->atab[hashval % ATABSIZE];
+}
Index: /tags/kBuild-0.1.4/src/kash/alias.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/alias.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/alias.h	(revision 1780)
@@ -0,0 +1,50 @@
+/*	$NetBSD: alias.h,v 1.6 2003/08/07 09:05:29 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)alias.h	8.2 (Berkeley) 5/4/95
+ */
+
+#define ALIASINUSE	1
+
+struct alias {
+	struct alias *next;
+	char *name;
+	char *val;
+	int flag;
+};
+
+struct alias *lookupalias(struct shinstance *, char *, int);
+char *get_alias_text(struct shinstance *, char *);
+int aliascmd(struct shinstance *, int, char **);
+int unaliascmd(struct shinstance *, int, char **);
+void rmaliases(struct shinstance *);
Index: /tags/kBuild-0.1.4/src/kash/arith.y
===================================================================
--- /tags/kBuild-0.1.4/src/kash/arith.y	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/arith.y	(revision 1780)
@@ -0,0 +1,200 @@
+%{
+/*	$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)arith.y	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdlib.h>
+#include "expand.h"
+#include "shell.h"
+#include "error.h"
+#include "output.h"
+#include "memalloc.h"
+#include "shinstance.h"
+
+shinstance *arith_psh;
+const char *arith_buf, *arith_startbuf;
+
+void yyerror(const char *);
+#ifdef TESTARITH
+int main(int , char *[]);
+int error(char *);
+#endif
+
+%}
+%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
+
+%left ARITH_OR
+%left ARITH_AND
+%left ARITH_BOR
+%left ARITH_BXOR
+%left ARITH_BAND
+%left ARITH_EQ ARITH_NE
+%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
+%left ARITH_LSHIFT ARITH_RSHIFT
+%left ARITH_ADD ARITH_SUB
+%left ARITH_MUL ARITH_DIV ARITH_REM
+%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
+%%
+
+exp:	expr {
+			return ($1);
+		}
+	;
+
+
+expr:	ARITH_LPAREN expr ARITH_RPAREN { $$ = $2; }
+	| expr ARITH_OR expr	{ $$ = $1 ? $1 : $3 ? $3 : 0; }
+	| expr ARITH_AND expr	{ $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
+	| expr ARITH_BOR expr	{ $$ = $1 | $3; }
+	| expr ARITH_BXOR expr	{ $$ = $1 ^ $3; }
+	| expr ARITH_BAND expr	{ $$ = $1 & $3; }
+	| expr ARITH_EQ expr	{ $$ = $1 == $3; }
+	| expr ARITH_GT expr	{ $$ = $1 > $3; }
+	| expr ARITH_GE expr	{ $$ = $1 >= $3; }
+	| expr ARITH_LT expr	{ $$ = $1 < $3; }
+	| expr ARITH_LE expr	{ $$ = $1 <= $3; }
+	| expr ARITH_NE expr	{ $$ = $1 != $3; }
+	| expr ARITH_LSHIFT expr { $$ = $1 << $3; }
+	| expr ARITH_RSHIFT expr { $$ = $1 >> $3; }
+	| expr ARITH_ADD expr	{ $$ = $1 + $3; }
+	| expr ARITH_SUB expr	{ $$ = $1 - $3; }
+	| expr ARITH_MUL expr	{ $$ = $1 * $3; }
+	| expr ARITH_DIV expr	{
+			if ($3 == 0)
+				yyerror("division by zero");
+			$$ = $1 / $3;
+			}
+	| expr ARITH_REM expr   {
+			if ($3 == 0)
+				yyerror("division by zero");
+			$$ = $1 % $3;
+			}
+	| ARITH_NOT expr	{ $$ = !($2); }
+	| ARITH_BNOT expr	{ $$ = ~($2); }
+	| ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); }
+	| ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; }
+	| ARITH_NUM
+	;
+%%
+int
+arith(shinstance *psh, const char *s)
+{
+	long result;
+
+	INTOFF;
+/* todo lock */
+   arith_psh = psh;
+	arith_buf = arith_startbuf = s;
+	result = yyparse();
+	arith_lex_reset();	/* reprime lex */
+   arith_psh = NULL;
+/* todo unlock */
+	INTON;
+
+	return (result);
+}
+
+
+/*
+ *  The exp(1) builtin.
+ */
+int
+expcmd(shinstance *psh, int argc, char **argv)
+{
+	const char *p;
+	char *concat;
+	char **ap;
+	long i;
+
+	if (argc > 1) {
+		p = argv[1];
+		if (argc > 2) {
+			/*
+			 * concatenate arguments
+			 */
+			STARTSTACKSTR(psh, concat);
+			ap = argv + 2;
+			for (;;) {
+				while (*p)
+					STPUTC(psh, *p++, concat);
+				if ((p = *ap++) == NULL)
+					break;
+				STPUTC(psh, ' ', concat);
+			}
+			STPUTC(psh, '\0', concat);
+			p = grabstackstr(psh, concat);
+		}
+	} else
+		p = "";
+
+	i = arith(psh, p);
+
+	out1fmt(psh, "%ld\n", i);
+	return (! i);
+}
+
+/*************************/
+#ifdef TEST_ARITH
+#include <stdio.h>
+main(argc, argv)
+	char *argv[];
+{
+	printf("%d\n", exp(argv[1]));
+}
+error(s)
+	char *s;
+{
+	fprintf(stderr, "exp: %s\n", s);
+	exit(1);
+}
+#endif
+
+void
+yyerror(const char *s)
+{
+   shinstance *psh = arith_psh;
+	yyerrok;
+	yyclearin;
+	arith_lex_reset();	/* reprime lex */
+/** @todo unlock */
+	error(psh, "arithmetic expression: %s: \"%s\"", s, arith_startbuf);
+	/* NOTREACHED */
+}
Index: /tags/kBuild-0.1.4/src/kash/arith_lex.l
===================================================================
--- /tags/kBuild-0.1.4/src/kash/arith_lex.l	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/arith_lex.l	(revision 1780)
@@ -0,0 +1,103 @@
+%option noyywrap
+%{
+/*	$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)arith_lex.l	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $");
+#endif /* not lint */
+#endif
+
+#include "arith.h"
+#include "error.h"
+#include "expand.h"
+#include "var.h"
+#include "shinstance.h"
+
+extern int yylval;
+extern shinstance *arith_psh;
+extern char *arith_buf, *arith_startbuf;
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max) \
+	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
+#define YY_NO_UNPUT
+%}
+
+%%
+[ \t\n]	{ ; }
+0x[0-9a-fA-F]+	{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+0[0-7]*		{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+[1-9][0-9]*	{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+[A-Za-z_][A-Za-z_0-9]*	{ char *v = lookupvar(arith_psh, yytext);
+			if (v) {
+				yylval = strtol(v, &v, 0);
+				if (*v == 0)
+					return ARITH_NUM;
+			}
+			error(arith_psh, "arith: syntax error: \"%s\"", arith_startbuf);
+		}
+"("	{ return(ARITH_LPAREN); }
+")"	{ return(ARITH_RPAREN); }
+"||"	{ return(ARITH_OR); }
+"&&"	{ return(ARITH_AND); }
+"|"	{ return(ARITH_BOR); }
+"^"	{ return(ARITH_BXOR); }
+"&"	{ return(ARITH_BAND); }
+"=="	{ return(ARITH_EQ); }
+"!="	{ return(ARITH_NE); }
+">"	{ return(ARITH_GT); }
+">="	{ return(ARITH_GE); }
+"<"	{ return(ARITH_LT); }
+"<="	{ return(ARITH_LE); }
+"<<"	{ return(ARITH_LSHIFT); }
+">>"	{ return(ARITH_RSHIFT); }
+"*"	{ return(ARITH_MUL); }
+"/"	{ return(ARITH_DIV); }
+"%"	{ return(ARITH_REM); }
+"+"	{ return(ARITH_ADD); }
+"-"	{ return(ARITH_SUB); }
+"~"	{ return(ARITH_BNOT); }
+"!"	{ return(ARITH_NOT); }
+.	{ error(arith_psh, "arith: syntax error: \"%s\"", arith_startbuf); }
+%%
+
+void
+arith_lex_reset() {
+#ifdef YY_NEW_FILE
+	YY_NEW_FILE;
+#endif
+}
Index: /tags/kBuild-0.1.4/src/kash/bltin/echo.1
===================================================================
--- /tags/kBuild-0.1.4/src/kash/bltin/echo.1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/bltin/echo.1	(revision 1780)
@@ -0,0 +1,109 @@
+.\"	$NetBSD: echo.1,v 1.13 2003/08/07 09:05:40 agc Exp $
+.\"
+.\" Copyright (c) 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Kenneth Almquist.
+.\" Copyright 1989 by Kenneth Almquist
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)echo.1	8.1 (Berkeley) 5/31/93
+.\"
+.Dd May 31, 1993
+.Dt ECHO 1
+.Os
+.Sh NAME
+.Nm echo
+.Nd produce message in a shell script
+.Sh SYNOPSIS
+.Nm
+.Op Fl n | Fl e
+.Ar args ...
+.Sh DESCRIPTION
+.Nm
+prints its arguments on the standard output, separated by spaces.
+Unless the
+.Fl n
+option is present, a newline is output following the arguments.
+The
+.Fl e
+option causes
+.Nm
+to treat the escape sequences specially, as described in the following
+paragraph.
+The
+.Fl e
+option is the default, and is provided solely for compatibility with
+other systems.
+Only one of the options
+.Fl n
+and
+.Fl e
+may be given.
+.Pp
+If any of the following sequences of characters is encountered during
+output, the sequence is not output.  Instead, the specified action is
+performed:
+.Bl -tag -width indent
+.It Li \eb
+A backspace character is output.
+.It Li \ec
+Subsequent output is suppressed.  This is normally used at the end of the
+last argument to suppress the trailing newline that
+.Nm
+would otherwise output.
+.It Li \ef
+Output a form feed.
+.It Li \en
+Output a newline character.
+.It Li \er
+Output a carriage return.
+.It Li \et
+Output a (horizontal) tab character.
+.It Li \ev
+Output a vertical tab.
+.It Li \e0 Ns Ar digits
+Output the character whose value is given by zero to three digits.
+If there are zero digits, a nul character is output.
+.It Li \e\e
+Output a backslash.
+.El
+.Sh HINTS
+Remember that backslash is special to the shell and needs to be escaped.
+To output a message to standard error, say
+.Pp
+.D1  echo message \*[Gt]\*[Am]2
+.Sh BUGS
+The octal character escape mechanism
+.Pq Li \e0 Ns Ar digits
+differs from the
+C language mechanism.
+.Pp
+There is no way to force
+.Nm
+to treat its arguments literally, rather than interpreting them as
+options and escape sequences.
Index: /tags/kBuild-0.1.4/src/kash/bltin/echo.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/bltin/echo.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/bltin/echo.c	(revision 1780)
@@ -0,0 +1,120 @@
+/*	$NetBSD: echo.c,v 1.12 2005/02/06 04:43:43 perry Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)echo.c	8.1 (Berkeley) 5/31/93
+ */
+
+/*
+ * Echo command.
+ *
+ * echo is steeped in tradition - several of them!
+ * netbsd has supported 'echo [-n | -e] args' in spite of -e not being
+ * documented anywhere.
+ * Posix requires that -n be supported, output from strings containing
+ * \ is implementation defined
+ * The Single Unix Spec requires that \ escapes be treated as if -e
+ * were set, but that -n not be treated as an option.
+ * (ksh supports 'echo [-eEn] args', but not -- so that it is actually
+ * impossible to actually output '-n')
+ *
+ * It is suggested that 'printf "%b" "string"' be used to get \ sequences
+ * expanded.  printf is now a builtin of netbsd's sh and csh.
+ */
+
+#include "shinstance.h"
+#include "builtins.h"
+
+int
+echocmd(shinstance *psh, int argc, char **argv)
+{
+	char **ap;
+	const char *p;
+	int nflag = 0;
+	int eflag = 0;
+
+	ap = argv;
+	if (argc)
+		ap++;
+
+	if ((p = *ap) != NULL && *p == '-') {
+		if (p[1] == 'n' && !p[2]) {
+			nflag = 1;
+			ap++;
+		} else if (p[1] == 'e' && !p[2]) {
+			eflag = 1;
+			ap++;
+		}
+	}
+
+	while ((p = *ap++) != NULL) {
+		if (!eflag) {
+			out1str(psh, p);
+		} else {
+			char c;
+			int count;
+
+			while ((c = *p++) != '\0') {
+				if (c == '\\') {
+					switch (*p++) {
+					case 'a':  c = '\a';  break;	/* bell */
+					case 'b':  c = '\b';  break;
+					case 'c':  return 0;		/* exit */
+					case 'e':  c =  033;  break;	/* escape */
+					case 'f':  c = '\f';  break;
+					case 'n':  c = '\n';  break;
+					case 'r':  c = '\r';  break;
+					case 't':  c = '\t';  break;
+					case 'v':  c = '\v';  break;
+					case '\\':  break;		/* c = '\\' */
+					case '0':
+						c = 0;
+						count = 3;
+						while (--count >= 0 && (unsigned)(*p - '0') < 8)
+							c = (c << 3) + (*p++ - '0');
+						break;
+					default:
+						/* Output the '/' and char following */
+						p--;
+						break;
+					}
+				}
+				out1c(psh, c);
+			}
+		}
+		if (*ap)
+			out1c(psh, ' ');
+	}
+	if (! nflag)
+		out1c(psh, '\n');
+	return 0;
+}
Index: /tags/kBuild-0.1.4/src/kash/bltin/kill.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/bltin/kill.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/bltin/kill.c	(revision 1780)
@@ -0,0 +1,235 @@
+/* $NetBSD: kill.c,v 1.23 2003/08/07 09:05:13 agc Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#if !defined(lint) && !defined(SHELL)
+__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n");
+#endif /* not lint */
+#ifndef lint
+static char sccsid[] = "@(#)kill.c	8.4 (Berkeley) 4/28/95";
+#else
+__RCSID("$NetBSD: kill.c,v 1.23 2003/08/07 09:05:13 agc Exp $");
+#endif /* not lint */
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "shtypes.h"
+#include "jobs.h"
+#include "error.h"
+#include "shinstance.h"
+
+#ifndef HAVE_SYS_SIGNAME
+extern void init_sys_signame(void);
+extern char sys_signame[NSIG][16];
+#endif
+
+static int nosig(shinstance *, char *);
+static void printsignals(shinstance *, struct output *);
+static int signame_to_signum(char *);
+static int usage(shinstance *psh);
+
+int
+killcmd(shinstance *psh, int argc, char *argv[])
+{
+	int errors, numsig, pid;
+	char *ep;
+
+	if (argc < 2)
+		return usage(psh);
+
+	numsig = SIGTERM;
+#ifndef HAVE_SYS_SIGNAME
+	init_sys_signame();
+#endif
+
+	argc--, argv++;
+	if (strcmp(*argv, "-l") == 0) {
+		argc--, argv++;
+		if (argc > 1)
+			return usage(psh);
+		if (argc == 1) {
+			if (isdigit((unsigned char)**argv) == 0)
+				return usage(psh);
+			numsig = strtol(*argv, &ep, 10);
+			if (*ep != '\0') {
+				sh_errx(psh, EXIT_FAILURE, "illegal signal number: %s",
+						*argv);
+				/* NOTREACHED */
+			}
+			if (numsig >= 128)
+				numsig -= 128;
+			if (numsig <= 0 || numsig >= NSIG)
+				return nosig(psh, *argv);
+			outfmt(psh->out1, "%s\n", sys_signame[numsig]);
+			//sh_exit(psh, 0);
+			return 0;
+		}
+		printsignals(psh, psh->out1);
+		//sh_exit(psh, 0);
+		return 0;
+	}
+
+	if (!strcmp(*argv, "-s")) {
+		argc--, argv++;
+		if (argc < 1) {
+			sh_warnx(psh, "option requires an argument -- s");
+			return usage(psh);
+		}
+		if (strcmp(*argv, "0")) {
+			if ((numsig = signame_to_signum(*argv)) < 0)
+				return nosig(psh, *argv);
+		} else
+			numsig = 0;
+		argc--, argv++;
+	} else if (**argv == '-') {
+		++*argv;
+		if (isalpha((unsigned char)**argv)) {
+			if ((numsig = signame_to_signum(*argv)) < 0)
+				return nosig(psh, *argv);
+		} else if (isdigit((unsigned char)**argv)) {
+			numsig = strtol(*argv, &ep, 10);
+			if (!*argv || *ep) {
+				sh_errx(psh, EXIT_FAILURE, "illegal signal number: %s",
+						*argv);
+				/* NOTREACHED */
+			}
+			if (numsig < 0 || numsig >= NSIG)
+				return nosig(psh, *argv);
+		} else
+			return nosig(psh, *argv);
+		argc--, argv++;
+	}
+
+	if (argc == 0)
+		return usage(psh);
+
+	for (errors = 0; argc; argc--, argv++) {
+		if (*argv[0] == '%') {
+			pid = getjobpgrp(psh, *argv);
+			if (pid == 0) {
+				sh_warnx(psh, "illegal job id: %s", *argv);
+				errors = 1;
+				continue;
+			}
+		} else {
+			pid = strtol(*argv, &ep, 10);
+			if (!**argv || *ep) {
+				sh_warnx(psh, "illegal process id: %s", *argv);
+				errors = 1;
+				continue;
+			}
+		}
+		if (sh_kill(psh, pid, numsig) == -1) {
+			sh_warn(psh, "%s", *argv);
+			errors = 1;
+		}
+		/* Wakeup the process if it was suspended, so it can
+		   exit without an explicit 'fg'. */
+		if (numsig == SIGTERM || numsig == SIGHUP)
+			sh_kill(psh, pid, SIGCONT);
+	}
+
+	//sh_exit(psh, errors);
+	///* NOTREACHED */
+	return errors;
+}
+
+static int
+signame_to_signum(char *sig)
+{
+	int n;
+	if (strncasecmp(sig, "sig", 3) == 0)
+		sig += 3;
+	for (n = 1; n < NSIG; n++) {
+		if (!strcasecmp(sys_signame[n], sig))
+			return (n);
+	}
+	return (-1);
+}
+
+static int
+nosig(shinstance *psh, char *name)
+{
+	sh_warnx(psh, "unknown signal %s; valid signals:", name);
+	printsignals(psh, psh->out2);
+	//sh_exit(psh, 1);
+	///* NOTREACHED */
+	return 1;
+}
+
+static void
+printsignals(shinstance *psh, struct output *out)
+{
+	int sig;
+	size_t len, nl;
+	const char *name;
+	int termwidth = 80;
+
+	if (shfile_isatty(&psh->fdtab, out->fd)) {
+		sh_winsize win;
+		if (shfile_ioctl(&psh->fdtab, out->fd, TIOCGWINSZ, &win) == 0 && win.ws_col > 0)
+			termwidth = win.ws_col;
+	}
+
+	for (len = 0, sig = 1; sig < NSIG; sig++) {
+		name = sys_signame[sig];
+		nl = 1 + strlen(name);
+
+		if (len + nl >= termwidth) {
+			outfmt(out, "\n");
+			len = 0;
+		} else if (len != 0)
+			outfmt(out, " ");
+		len += nl;
+		outfmt(out, "%s", name);
+	}
+	if (len != 0)
+		outfmt(out, "\n");
+}
+
+static int
+usage(shinstance *psh)
+{
+	outfmt(psh->out2,
+	    "usage: %s [-s signal_name] pid ...\n"
+	    "       %s -l [exit_status]\n"
+	    "       %s -signal_name pid ...\n"
+	    "       %s -signal_number pid ...\n",
+	    psh->commandname, psh->commandname, psh->commandname, psh->commandname);
+	//sh_exit(psh, 1);
+	///* NOTREACHED */
+	return 1;
+}
Index: /tags/kBuild-0.1.4/src/kash/bltin/printf.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/bltin/printf.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/bltin/printf.c	(revision 1780)
@@ -0,0 +1,658 @@
+/*	$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#if !defined(BUILTIN) && !defined(SHELL)
+__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n");
+#endif
+#ifndef lint
+static char sccsid[] = "@(#)printf.c	8.2 (Berkeley) 3/22/95";
+#else
+__RCSID("$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $");
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __GNUC__
+#define ESCAPE '\e'
+#else
+#define ESCAPE 033
+#endif
+
+static void	 conv_escape_str(char *, void (*)(int));
+static char	*conv_escape(char *, char *);
+static char	*conv_expand(const char *);
+static int	 getchr(void);
+static double	 getdouble(void);
+static int	 getwidth(void);
+static intmax_t	 getintmax(void);
+static uintmax_t getuintmax(void);
+static char	*getstr(void);
+static char	*mklong(const char *, int);
+static void      check_conversion(const char *, const char *);
+static void	 usage(void);
+
+static void	b_count(int);
+static void	b_output(int);
+static size_t	b_length;
+static char	*b_fmt;
+
+static int	rval;
+static char  **gargv;
+
+#ifdef BUILTIN		/* csh builtin */
+#define main progprintf
+#endif
+
+#ifdef SHELL		/* sh (aka ash) builtin */
+#define main printfcmd
+#include "../../bin/sh/bltin/bltin.h"
+#endif /* SHELL */
+
+#define PF(f, func) { \
+	if (fieldwidth != -1) { \
+		if (precision != -1) \
+			(void)printf(f, fieldwidth, precision, func); \
+		else \
+			(void)printf(f, fieldwidth, func); \
+	} else if (precision != -1) \
+		(void)printf(f, precision, func); \
+	else \
+		(void)printf(f, func); \
+}
+
+#define APF(cpp, f, func) { \
+	if (fieldwidth != -1) { \
+		if (precision != -1) \
+			(void)asprintf(cpp, f, fieldwidth, precision, func); \
+		else \
+			(void)asprintf(cpp, f, fieldwidth, func); \
+	} else if (precision != -1) \
+		(void)asprintf(cpp, f, precision, func); \
+	else \
+		(void)asprintf(cpp, f, func); \
+}
+
+int main(int, char **);
+int main(int argc, char *argv[])
+{
+	char *fmt, *start;
+	int fieldwidth, precision;
+	char nextch;
+	char *format;
+	int ch;
+
+#if !defined(SHELL) && !defined(BUILTIN)
+	(void)setlocale (LC_ALL, "");
+#endif
+
+	while ((ch = getopt(argc, argv, "")) != -1) {
+		switch (ch) {
+		case '?':
+		default:
+			usage();
+			return 1;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1) {
+		usage();
+		return 1;
+	}
+
+	format = *argv;
+	gargv = ++argv;
+
+#define SKIP1	"#-+ 0"
+#define SKIP2	"*0123456789"
+	do {
+		/*
+		 * Basic algorithm is to scan the format string for conversion
+		 * specifications -- once one is found, find out if the field
+		 * width or precision is a '*'; if it is, gather up value.
+		 * Note, format strings are reused as necessary to use up the
+		 * provided arguments, arguments of zero/null string are
+		 * provided to use up the format string.
+		 */
+
+		/* find next format specification */
+		for (fmt = format; (ch = *fmt++) != '\0';) {
+			if (ch == '\\') {
+				char c_ch;
+				fmt = conv_escape(fmt, &c_ch);
+				putchar(c_ch);
+				continue;
+			}
+			if (ch != '%' || (*fmt == '%' && ++fmt)) {
+				(void)putchar(ch);
+				continue;
+			}
+
+			/* Ok - we've found a format specification,
+			   Save its address for a later printf(). */
+			start = fmt - 1;
+
+			/* skip to field width */
+			fmt += strspn(fmt, SKIP1);
+			fieldwidth = *fmt == '*' ? getwidth() : -1;
+
+			/* skip to possible '.', get following precision */
+			fmt += strspn(fmt, SKIP2);
+			if (*fmt == '.')
+				++fmt;
+			precision = *fmt == '*' ? getwidth() : -1;
+
+			fmt += strspn(fmt, SKIP2);
+
+			ch = *fmt;
+			if (!ch) {
+				warnx("missing format character");
+				return (1);
+			}
+			/* null terminate format string to we can use it
+			   as an argument to printf. */
+			nextch = fmt[1];
+			fmt[1] = 0;
+			switch (ch) {
+
+			case 'B': {
+				const char *p = conv_expand(getstr());
+				*fmt = 's';
+				PF(start, p);
+				break;
+			}
+			case 'b': {
+				/* There has to be a better way to do this,
+				 * but the string we generate might have
+				 * embedded nulls. */
+				static char *a, *t;
+				char *cp = getstr();
+				/* Free on entry in case shell longjumped out */
+				if (a != NULL)
+					free(a);
+				a = NULL;
+				if (t != NULL)
+					free(t);
+				t = NULL;
+				/* Count number of bytes we want to output */
+				b_length = 0;
+				conv_escape_str(cp, b_count);
+				t = malloc(b_length + 1);
+				if (t == NULL)
+					break;
+				memset(t, 'x', b_length);
+				t[b_length] = 0;
+				/* Get printf to calculate the lengths */
+				*fmt = 's';
+				APF(&a, start, t);
+				b_fmt = a;
+				/* Output leading spaces and data bytes */
+				conv_escape_str(cp, b_output);
+				/* Add any trailing spaces */
+				printf("%s", b_fmt);
+				break;
+			}
+			case 'c': {
+				char p = getchr();
+				PF(start, p);
+				break;
+			}
+			case 's': {
+				char *p = getstr();
+				PF(start, p);
+				break;
+			}
+			case 'd':
+			case 'i': {
+				intmax_t p = getintmax();
+				char *f = mklong(start, ch);
+				PF(f, p);
+				break;
+			}
+			case 'o':
+			case 'u':
+			case 'x':
+			case 'X': {
+				uintmax_t p = getuintmax();
+				char *f = mklong(start, ch);
+				PF(f, p);
+				break;
+			}
+			case 'e':
+			case 'E':
+			case 'f':
+			case 'g':
+			case 'G': {
+				double p = getdouble();
+				PF(start, p);
+				break;
+			}
+			default:
+				warnx("%s: invalid directive", start);
+				return 1;
+			}
+			*fmt++ = ch;
+			*fmt = nextch;
+			/* escape if a \c was encountered */
+			if (rval & 0x100)
+				return rval & ~0x100;
+		}
+	} while (gargv != argv && *gargv);
+
+	return rval;
+}
+
+/* helper functions for conv_escape_str */
+
+static void
+/*ARGSUSED*/
+b_count(int ch)
+{
+	b_length++;
+}
+
+/* Output one converted character for every 'x' in the 'format' */
+
+static void
+b_output(int ch)
+{
+	for (;;) {
+		switch (*b_fmt++) {
+		case 0:
+			b_fmt--;
+			return;
+		case ' ':
+			putchar(' ');
+			break;
+		default:
+			putchar(ch);
+			return;
+		}
+	}
+}
+
+
+/*
+ * Print SysV echo(1) style escape string
+ *	Halts processing string if a \c escape is encountered.
+ */
+static void
+conv_escape_str(char *str, void (*do_putchar)(int))
+{
+	int value;
+	int ch;
+	char c;
+
+	while ((ch = *str++) != '\0') {
+		if (ch != '\\') {
+			do_putchar(ch);
+			continue;
+		}
+
+		ch = *str++;
+		if (ch == 'c') {
+			/* \c as in SYSV echo - abort all processing.... */
+			rval |= 0x100;
+			break;
+		}
+
+		/*
+		 * %b string octal constants are not like those in C.
+		 * They start with a \0, and are followed by 0, 1, 2,
+		 * or 3 octal digits.
+		 */
+		if (ch == '0') {
+			int octnum = 0, i;
+			for (i = 0; i < 3; i++) {
+				if (!isdigit((unsigned char)*str) || *str > '7')
+					break;
+				octnum = (octnum << 3) | (*str++ - '0');
+			}
+			do_putchar(octnum);
+			continue;
+		}
+
+		/* \[M][^|-]C as defined by vis(3) */
+		if (ch == 'M' && *str == '-') {
+			do_putchar(0200 | str[1]);
+			str += 2;
+			continue;
+		}
+		if (ch == 'M' && *str == '^') {
+			str++;
+			value = 0200;
+			ch = '^';
+		} else
+			value = 0;
+		if (ch == '^') {
+			ch = *str++;
+			if (ch == '?')
+				value |= 0177;
+			else
+				value |= ch & 037;
+			do_putchar(value);
+			continue;
+		}
+
+		/* Finally test for sequences valid in the format string */
+		str = conv_escape(str - 1, &c);
+		do_putchar(c);
+	}
+}
+
+/*
+ * Print "standard" escape characters
+ */
+static char *
+conv_escape(char *str, char *conv_ch)
+{
+	int value;
+	int ch;
+	char num_buf[4], *num_end;
+
+	ch = *str++;
+
+	switch (ch) {
+	case '0': case '1': case '2': case '3':
+	case '4': case '5': case '6': case '7':
+		num_buf[0] = ch;
+		ch = str[0];
+		num_buf[1] = ch;
+		num_buf[2] = ch ? str[1] : 0;
+		num_buf[3] = 0;
+		value = strtoul(num_buf, &num_end, 8);
+		str += num_end  - (num_buf + 1);
+		break;
+
+	case 'x':
+		/* Hexadecimal character constants are not required to be
+		   supported (by SuS v1) because there is no consistent
+		   way to detect the end of the constant.
+		   Supporting 2 byte constants is a compromise. */
+		ch = str[0];
+		num_buf[0] = ch;
+		num_buf[1] = ch ? str[1] : 0;
+		num_buf[2] = 0;
+		value = strtoul(num_buf, &num_end, 16);
+		str += num_end - num_buf;
+		break;
+
+	case '\\':	value = '\\';	break;	/* backslash */
+	case '\'':	value = '\'';	break;	/* single quote */
+	case '"':	value = '"';	break;	/* double quote */
+	case 'a':	value = '\a';	break;	/* alert */
+	case 'b':	value = '\b';	break;	/* backspace */
+	case 'e':	value = ESCAPE;	break;	/* escape */
+	case 'f':	value = '\f';	break;	/* form-feed */
+	case 'n':	value = '\n';	break;	/* newline */
+	case 'r':	value = '\r';	break;	/* carriage-return */
+	case 't':	value = '\t';	break;	/* tab */
+	case 'v':	value = '\v';	break;	/* vertical-tab */
+
+	default:
+		warnx("unknown escape sequence `\\%c'", ch);
+		rval = 1;
+		value = ch;
+		break;
+	}
+
+	*conv_ch = value;
+	return str;
+}
+
+/* expand a string so that everything is printable */
+
+static char *
+conv_expand(const char *str)
+{
+	static char *conv_str;
+	static char no_memory[] = "<no memory>";
+	char *cp;
+	int ch;
+
+	if (conv_str)
+		free(conv_str);
+	/* get a buffer that is definitely large enough.... */
+	conv_str = malloc(4 * strlen(str) + 1);
+	if (!conv_str)
+		return no_memory;
+	cp = conv_str;
+
+	while ((ch = *(const unsigned char *)str++) != '\0') {
+		switch (ch) {
+		/* Use C escapes for expected control characters */
+		case '\\':	ch = '\\';	break;	/* backslash */
+		case '\'':	ch = '\'';	break;	/* single quote */
+		case '"':	ch = '"';	break;	/* double quote */
+		case '\a':	ch = 'a';	break;	/* alert */
+		case '\b':	ch = 'b';	break;	/* backspace */
+		case ESCAPE:	ch = 'e';	break;	/* escape */
+		case '\f':	ch = 'f';	break;	/* form-feed */
+		case '\n':	ch = 'n';	break;	/* newline */
+		case '\r':	ch = 'r';	break;	/* carriage-return */
+		case '\t':	ch = 't';	break;	/* tab */
+		case '\v':	ch = 'v';	break;	/* vertical-tab */
+		default:
+			/* Copy anything printable */
+			if (isprint(ch)) {
+				*cp++ = ch;
+				continue;
+			}
+			/* Use vis(3) encodings for the rest */
+			*cp++ = '\\';
+			if (ch & 0200) {
+				*cp++ = 'M';
+				ch &= ~0200;
+			}
+			if (ch == 0177) {
+				*cp++ = '^';
+				*cp++ = '?';
+				continue;
+			}
+			if (ch < 040) {
+				*cp++ = '^';
+				*cp++ = ch | 0100;
+				continue;
+			}
+			*cp++ = '-';
+			*cp++ = ch;
+			continue;
+		}
+		*cp++ = '\\';
+		*cp++ = ch;
+	}
+
+	*cp = 0;
+	return conv_str;
+}
+
+static char *
+mklong(const char *str, int ch)
+{
+	static char copy[64];
+	size_t len;
+
+	len = strlen(str) + 2;
+	if (len > sizeof copy) {
+		warnx("format %s too complex\n", str);
+		len = 4;
+	}
+	(void)memmove(copy, str, len - 3);
+	copy[len - 3] = 'j';
+	copy[len - 2] = ch;
+	copy[len - 1] = '\0';
+	return copy;
+}
+
+static int
+getchr(void)
+{
+	if (!*gargv)
+		return 0;
+	return (int)**gargv++;
+}
+
+static char *
+getstr(void)
+{
+	static char empty[] = "";
+	if (!*gargv)
+		return empty;
+	return *gargv++;
+}
+
+static int
+getwidth(void)
+{
+	long val;
+	char *s, *ep;
+
+	s = *gargv;
+	if (!*gargv)
+		return (0);
+	gargv++;
+
+	errno = 0;
+	val = strtoul(s, &ep, 0);
+	check_conversion(s, ep);
+
+	/* Arbitrarily 'restrict' field widths to 1Mbyte */
+	if (val < 0 || val > 1 << 20) {
+		warnx("%s: invalid field width", s);
+		return 0;
+	}
+
+	return val;
+}
+
+static intmax_t
+getintmax(void)
+{
+	intmax_t val;
+	char *cp, *ep;
+
+	cp = *gargv;
+	if (cp == NULL)
+		return 0;
+	gargv++;
+
+	if (*cp == '\"' || *cp == '\'')
+		return *(cp+1);
+
+	errno = 0;
+	val = strtoimax(cp, &ep, 0);
+	check_conversion(cp, ep);
+	return val;
+}
+
+static uintmax_t
+getuintmax(void)
+{
+	uintmax_t val;
+	char *cp, *ep;
+
+	cp = *gargv;
+	if (cp == NULL)
+		return 0;
+	gargv++;
+
+	if (*cp == '\"' || *cp == '\'')
+		return *(cp + 1);
+
+	/* strtoumax won't error -ve values */
+	while (isspace(*(unsigned char *)cp))
+		cp++;
+	if (*cp == '-') {
+		warnx("%s: expected positive numeric value", cp);
+		rval = 1;
+		return 0;
+	}
+
+	errno = 0;
+	val = strtoumax(cp, &ep, 0);
+	check_conversion(cp, ep);
+	return val;
+}
+
+static double
+getdouble(void)
+{
+	double val;
+	char *ep;
+
+	if (!*gargv)
+		return (0.0);
+
+	if (**gargv == '\"' || **gargv == '\'')
+		return (double) *((*gargv++)+1);
+
+	errno = 0;
+	val = strtod(*gargv, &ep);
+	check_conversion(*gargv++, ep);
+	return val;
+}
+
+static void
+check_conversion(const char *s, const char *ep)
+{
+	if (*ep) {
+		if (ep == s)
+			warnx("%s: expected numeric value", s);
+		else
+			warnx("%s: not completely converted", s);
+		rval = 1;
+	} else if (errno == ERANGE) {
+		warnx("%s: %s", s, strerror(ERANGE));
+		rval = 1;
+	}
+}
+
+static void
+usage(void)
+{
+	(void)fprintf(stderr, "Usage: %s format [arg ...]\n", getprogname());
+}
Index: /tags/kBuild-0.1.4/src/kash/bltin/test.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/bltin/test.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/bltin/test.c	(revision 1780)
@@ -0,0 +1,483 @@
+/* $NetBSD: test.c,v 1.26 2005/02/10 06:56:55 simonb Exp $ */
+
+/*
+ * test(1); version 7-like  --  author Erik Baalbergen
+ * modified by Eric Gisin to be used as built-in.
+ * modified by Arnold Robbins to add SVR3 compatibility
+ * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
+ * modified by J.T. Conklin for NetBSD.
+ *
+ * This program is in the Public Domain.
+ */
+
+#if 0
+#ifndef lint
+__RCSID("$NetBSD: test.c,v 1.26 2005/02/10 06:56:55 simonb Exp $");
+#endif
+#endif
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "shell.h"
+#include "error.h"
+#include "shinstance.h"
+
+
+/* test(1) accepts the following grammar:
+	oexpr	::= aexpr | aexpr "-o" oexpr ;
+	aexpr	::= nexpr | nexpr "-a" aexpr ;
+	nexpr	::= primary | "!" primary
+	primary	::= unary-operator operand
+		| operand binary-operator operand
+		| operand
+		| "(" oexpr ")"
+		;
+	unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
+		"-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
+
+	binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
+			"-nt"|"-ot"|"-ef";
+	operand ::= <any legal UNIX file name>
+*/
+
+enum token {
+	EOI,
+	FILRD,
+	FILWR,
+	FILEX,
+	FILEXIST,
+	FILREG,
+	FILDIR,
+	FILCDEV,
+	FILBDEV,
+	FILFIFO,
+	FILSOCK,
+	FILSYM,
+	FILGZ,
+	FILTT,
+	FILSUID,
+	FILSGID,
+	FILSTCK,
+	FILNT,
+	FILOT,
+	FILEQ,
+	FILUID,
+	FILGID,
+	STREZ,
+	STRNZ,
+	STREQ,
+	STRNE,
+	STRLT,
+	STRGT,
+	INTEQ,
+	INTNE,
+	INTGE,
+	INTGT,
+	INTLE,
+	INTLT,
+	UNOT,
+	BAND,
+	BOR,
+	LPAREN,
+	RPAREN,
+	OPERAND
+};
+
+enum token_types {
+	UNOP,
+	BINOP,
+	BUNOP,
+	BBINOP,
+	PAREN
+};
+
+static struct t_op {
+	const char *op_text;
+	short op_num, op_type;
+} const ops [] = {
+	{"-r",	FILRD,	UNOP},
+	{"-w",	FILWR,	UNOP},
+	{"-x",	FILEX,	UNOP},
+	{"-e",	FILEXIST,UNOP},
+	{"-f",	FILREG,	UNOP},
+	{"-d",	FILDIR,	UNOP},
+	{"-c",	FILCDEV,UNOP},
+	{"-b",	FILBDEV,UNOP},
+	{"-p",	FILFIFO,UNOP},
+	{"-u",	FILSUID,UNOP},
+	{"-g",	FILSGID,UNOP},
+	{"-k",	FILSTCK,UNOP},
+	{"-s",	FILGZ,	UNOP},
+	{"-t",	FILTT,	UNOP},
+	{"-z",	STREZ,	UNOP},
+	{"-n",	STRNZ,	UNOP},
+	{"-h",	FILSYM,	UNOP},		/* for backwards compat */
+	{"-O",	FILUID,	UNOP},
+	{"-G",	FILGID,	UNOP},
+	{"-L",	FILSYM,	UNOP},
+	{"-S",	FILSOCK,UNOP},
+	{"=",	STREQ,	BINOP},
+	{"!=",	STRNE,	BINOP},
+	{"<",	STRLT,	BINOP},
+	{">",	STRGT,	BINOP},
+	{"-eq",	INTEQ,	BINOP},
+	{"-ne",	INTNE,	BINOP},
+	{"-ge",	INTGE,	BINOP},
+	{"-gt",	INTGT,	BINOP},
+	{"-le",	INTLE,	BINOP},
+	{"-lt",	INTLT,	BINOP},
+	{"-nt",	FILNT,	BINOP},
+	{"-ot",	FILOT,	BINOP},
+	{"-ef",	FILEQ,	BINOP},
+	{"!",	UNOT,	BUNOP},
+	{"-a",	BAND,	BBINOP},
+	{"-o",	BOR,	BBINOP},
+	{"(",	LPAREN,	PAREN},
+	{")",	RPAREN,	PAREN},
+	{0,	0,	0}
+};
+
+//static char **t_wp;
+//static struct t_op const *t_wp_op;
+
+static void syntax(shinstance *, const char *, const char *);
+static int oexpr(shinstance *, enum token);
+static int aexpr(shinstance *, enum token);
+static int nexpr(shinstance *, enum token);
+static int primary(shinstance *, enum token);
+static int binop(shinstance *);
+static int filstat(shinstance *, char *, enum token);
+static enum token t_lex(shinstance *, char *);
+static int isoperand(shinstance *);
+static int getn(shinstance *, const char *);
+static int newerf(shinstance *, const char *, const char *);
+static int olderf(shinstance *, const char *, const char *);
+static int equalf(shinstance *, const char *, const char *);
+
+
+int
+testcmd(shinstance *psh, int argc, char **argv)
+{
+	int res;
+
+	if (strcmp(argv[0], "[") == 0) {
+		if (strcmp(argv[--argc], "]"))
+			error(psh, "missing ]");
+		argv[argc] = NULL;
+	}
+
+	if (argc < 2)
+		return 1;
+
+	psh->t_wp_op = NULL;
+	psh->t_wp = &argv[1];
+	res = !oexpr(psh, t_lex(psh, *psh->t_wp));
+
+	if (*psh->t_wp != NULL && *++psh->t_wp != NULL)
+		syntax(psh, *psh->t_wp, "unexpected operator");
+
+	return res;
+}
+
+static void
+syntax(shinstance *psh, const char *op, const char *msg)
+{
+
+	if (op && *op)
+		error(psh, "%s: %s", op, msg);
+	else
+		error(psh, "%s", msg);
+}
+
+static int
+oexpr(shinstance *psh, enum token n)
+{
+	int res;
+
+	res = aexpr(psh, n);
+	if (t_lex(psh, *++psh->t_wp) == BOR)
+		return oexpr(psh, t_lex(psh, *++psh->t_wp)) || res;
+	psh->t_wp--;
+	return res;
+}
+
+static int
+aexpr(shinstance *psh, enum token n)
+{
+	int res;
+
+	res = nexpr(psh, n);
+	if (t_lex(psh, *++psh->t_wp) == BAND)
+		return aexpr(psh, t_lex(psh, *++psh->t_wp)) && res;
+	psh->t_wp--;
+	return res;
+}
+
+static int
+nexpr(shinstance *psh, enum token n)
+{
+
+	if (n == UNOT)
+		return !nexpr(psh, t_lex(psh, *++psh->t_wp));
+	return primary(psh, n);
+}
+
+static int
+primary(shinstance *psh, enum token n)
+{
+	enum token nn;
+	int res;
+
+	if (n == EOI)
+		return 0;		/* missing expression */
+	if (n == LPAREN) {
+		if ((nn = t_lex(psh, *++psh->t_wp)) == RPAREN)
+			return 0;	/* missing expression */
+		res = oexpr(psh, nn);
+		if (t_lex(psh, *++psh->t_wp) != RPAREN)
+			syntax(psh, NULL, "closing paren expected");
+		return res;
+	}
+	if (psh->t_wp_op && psh->t_wp_op->op_type == UNOP) {
+		/* unary expression */
+		if (*++psh->t_wp == NULL)
+			syntax(psh, psh->t_wp_op->op_text, "argument expected");
+		switch (n) {
+		case STREZ:
+			return strlen(*psh->t_wp) == 0;
+		case STRNZ:
+			return strlen(*psh->t_wp) != 0;
+		case FILTT:
+			return shfile_isatty(&psh->fdtab, getn(psh, *psh->t_wp));
+		default:
+			return filstat(psh, *psh->t_wp, n);
+		}
+	}
+
+	if (t_lex(psh, psh->t_wp[1]), psh->t_wp_op && psh->t_wp_op->op_type == BINOP) {
+		return binop(psh);
+	}
+
+	return strlen(*psh->t_wp) > 0;
+}
+
+static int
+binop(shinstance *psh)
+{
+	const char *opnd1, *opnd2;
+	struct t_op const *op;
+
+	opnd1 = *psh->t_wp;
+	(void) t_lex(psh, *++psh->t_wp);
+	op = psh->t_wp_op;
+
+	if ((opnd2 = *++psh->t_wp) == NULL)
+		syntax(psh, op->op_text, "argument expected");
+
+	switch (op->op_num) {
+	case STREQ:
+		return strcmp(opnd1, opnd2) == 0;
+	case STRNE:
+		return strcmp(opnd1, opnd2) != 0;
+	case STRLT:
+		return strcmp(opnd1, opnd2) < 0;
+	case STRGT:
+		return strcmp(opnd1, opnd2) > 0;
+	case INTEQ:
+		return getn(psh, opnd1) == getn(psh, opnd2);
+	case INTNE:
+		return getn(psh, opnd1) != getn(psh, opnd2);
+	case INTGE:
+		return getn(psh, opnd1) >= getn(psh, opnd2);
+	case INTGT:
+		return getn(psh, opnd1) > getn(psh, opnd2);
+	case INTLE:
+		return getn(psh, opnd1) <= getn(psh, opnd2);
+	case INTLT:
+		return getn(psh, opnd1) < getn(psh, opnd2);
+	case FILNT:
+		return newerf(psh, opnd1, opnd2);
+	case FILOT:
+		return olderf(psh, opnd1, opnd2);
+	case FILEQ:
+		return equalf(psh, opnd1, opnd2);
+	default:
+		sh_abort(psh);
+		/* NOTREACHED */
+		return -1;
+	}
+}
+
+static int
+filstat(shinstance *psh, char *nm, enum token mode)
+{
+	struct stat s;
+
+	if (mode == FILSYM
+		? shfile_lstat(&psh->fdtab, nm, &s)
+		: shfile_stat(&psh->fdtab, nm, &s))
+		return 0;
+
+	switch (mode) {
+	case FILRD:
+		return shfile_access(&psh->fdtab, nm, R_OK) == 0;
+	case FILWR:
+		return shfile_access(&psh->fdtab, nm, W_OK) == 0;
+	case FILEX:
+		return shfile_access(&psh->fdtab, nm, X_OK) == 0;
+	case FILEXIST:
+		return shfile_access(&psh->fdtab, nm, F_OK) == 0;
+	case FILREG:
+		return S_ISREG(s.st_mode);
+	case FILDIR:
+		return S_ISDIR(s.st_mode);
+	case FILCDEV:
+#ifdef S_ISCHR
+		return S_ISCHR(s.st_mode);
+#else
+        return 0;
+#endif
+	case FILBDEV:
+#ifdef S_ISBLK
+		return S_ISBLK(s.st_mode);
+#else
+        return 0;
+#endif
+	case FILFIFO:
+#ifdef S_ISFIFO
+		return S_ISFIFO(s.st_mode);
+#else
+        return 0;
+#endif
+	case FILSOCK:
+#ifdef S_ISSOCK
+		return S_ISSOCK(s.st_mode);
+#else
+        return 0;
+#endif
+	case FILSYM:
+		return S_ISLNK(s.st_mode);
+	case FILSUID:
+		return (s.st_mode & S_ISUID) != 0;
+	case FILSGID:
+		return (s.st_mode & S_ISGID) != 0;
+	case FILSTCK:
+#ifdef S_ISVTX
+		return (s.st_mode & S_ISVTX) != 0;
+#else
+        return 0;
+#endif
+	case FILGZ:
+		return s.st_size > (off_t)0;
+	case FILUID:
+		return s.st_uid == sh_geteuid(psh);
+	case FILGID:
+		return s.st_gid == sh_getegid(psh);
+	default:
+		return 1;
+	}
+}
+
+static enum token
+t_lex(shinstance *psh, char *s)
+{
+	struct t_op const *op;
+
+	op = ops;
+
+	if (s == 0) {
+		psh->t_wp_op = NULL;
+		return EOI;
+	}
+	while (op->op_text) {
+		if (strcmp(s, op->op_text) == 0) {
+			if ((op->op_type == UNOP && isoperand(psh)) ||
+			    (op->op_num == LPAREN && *(psh->t_wp+1) == 0))
+				break;
+			psh->t_wp_op = op;
+			return op->op_num;
+		}
+		op++;
+	}
+	psh->t_wp_op = NULL;
+	return OPERAND;
+}
+
+static int
+isoperand(shinstance *psh)
+{
+	struct t_op const *op;
+	char *s, *t;
+
+	op = ops;
+	if ((s  = *(psh->t_wp+1)) == 0)
+		return 1;
+	if ((t = *(psh->t_wp+2)) == 0)
+		return 0;
+	while (op->op_text) {
+		if (strcmp(s, op->op_text) == 0)
+	    		return op->op_type == BINOP &&
+	    		    (t[0] != ')' || t[1] != '\0');
+		op++;
+	}
+	return 0;
+}
+
+/* atoi with error detection */
+static int
+getn(shinstance *psh, const char *s)
+{
+	char *p;
+	long r;
+
+	errno = 0;
+	r = strtol(s, &p, 10);
+
+	if (errno != 0)
+	      error(psh, "%s: out of range", s);
+
+	while (isspace((unsigned char)*p))
+	      p++;
+
+	if (*p)
+	      error(psh, "%s: bad number", s);
+
+	return (int) r;
+}
+
+static int
+newerf(shinstance *psh, const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (shfile_stat(&psh->fdtab, f1, &b1) == 0 &&
+		shfile_stat(&psh->fdtab, f2, &b2) == 0 &&
+		b1.st_mtime > b2.st_mtime);
+}
+
+static int
+olderf(shinstance *psh, const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (shfile_stat(&psh->fdtab, f1, &b1) == 0 &&
+		shfile_stat(&psh->fdtab, f2, &b2) == 0 &&
+		b1.st_mtime < b2.st_mtime);
+}
+
+static int
+equalf(shinstance *psh, const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (shfile_stat(&psh->fdtab, f1, &b1) == 0 &&
+		shfile_stat(&psh->fdtab, f2, &b2) == 0 &&
+		b1.st_dev == b2.st_dev &&
+		b1.st_ino == b2.st_ino);
+}
Index: /tags/kBuild-0.1.4/src/kash/builtins.def
===================================================================
--- /tags/kBuild-0.1.4/src/kash/builtins.def	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/builtins.def	(revision 1780)
@@ -0,0 +1,92 @@
+#!/bin/sh -
+#	$NetBSD: builtins.def,v 1.21 2004/07/13 15:05:59 seb Exp $
+#
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)builtins.def	8.4 (Berkeley) 5/4/95
+
+#
+# This file lists all the builtin commands.  The first column is the name
+# of a C routine.
+# The -j flag specifies that this command is to be excluded from systems
+# without job control.
+# The -h flag specifies that this command is to be excluded from systems
+# based on the SMALL compile-time symbol.
+# The -s flag specifies that this is a posix 'special builtin' command.
+# The -u flag specifies that this is a posix 'standard utility'.
+# The rest of the line specifies the command name or names used to run
+# the command.
+
+bltincmd	-u command
+bgcmd -j	-u bg
+breakcmd	-s break -s continue
+cdcmd		-u cd chdir
+dotcmd		-s .
+echocmd		echo
+evalcmd		-s eval
+execcmd		-s exec
+exitcmd		-s exit
+expcmd		exp let
+exportcmd	-s export -s readonly
+falsecmd	-u false
+histcmd -h	-u fc
+inputrc		inputrc
+fgcmd -j	-u fg
+getoptscmd	-u getopts
+hashcmd		hash
+jobidcmd	jobid
+jobscmd		-u jobs
+localcmd	local
+#ifndef SMALL
+printfcmd	printf
+#endif
+pwdcmd		-u pwd
+readcmd		-u read
+returncmd	-s return
+setcmd		-s set
+setvarcmd	setvar
+shiftcmd	-s shift
+timescmd	-s times
+trapcmd		-s trap
+truecmd		-s : -u true
+typecmd		type
+umaskcmd	-u umask
+unaliascmd	-u unalias
+unsetcmd	-s unset
+waitcmd		-u wait
+aliascmd	-u alias
+ulimitcmd	ulimit
+testcmd		test [
+killcmd		-u kill		# mandated by posix for 'kill %job'
+wordexpcmd	wordexp
+#newgrp		-u newgrp	# optional command in posix
+
+#exprcmd	expr
Index: /tags/kBuild-0.1.4/src/kash/cd.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/cd.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/cd.c	(revision 1780)
@@ -0,0 +1,445 @@
+/*	$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)cd.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $");
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * The cd and pwd commands.
+ */
+
+#include "shell.h"
+#include "var.h"
+#include "nodes.h"	/* for jobs.h */
+#include "jobs.h"
+#include "options.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "exec.h"
+#include "redir.h"
+#include "mystring.h"
+#include "show.h"
+#include "cd.h"
+#include "shinstance.h"
+
+STATIC int docd(shinstance *psh, char *, int);
+STATIC char *getcomponent(shinstance *psh);
+STATIC void updatepwd(shinstance *psh, char *);
+STATIC void find_curdir(shinstance *psh, int noerror);
+
+/*char *curdir = NULL;*/		/* current working directory */
+/*char *prevdir;*/			/* previous working directory */
+/*STATIC char *cdcomppath;*/
+
+int
+cdcmd(shinstance *psh, int argc, char **argv)
+{
+	const char *dest;
+	const char *path;
+	char *p, *d;
+	struct stat statb;
+	int print = cdprint(psh);	/* set -cdprint to enable */
+
+	nextopt(psh, nullstr);
+
+	/*
+	 * Try (quite hard) to have 'curdir' defined, nothing has set
+	 * it on entry to the shell, but we want 'cd fred; cd -' to work.
+	 */
+	getpwd(psh, 1);
+	dest = *psh->argptr;
+	if (dest == NULL) {
+		dest = bltinlookup(psh, "HOME", 1);
+		if (dest == NULL)
+			error(psh, "HOME not set");
+	} else {
+		if (psh->argptr[1]) {
+			/* Do 'ksh' style substitution */
+			if (!psh->curdir)
+				error(psh, "PWD not set");
+			p = strstr(psh->curdir, dest);
+			if (!p)
+				error(psh, "bad substitution");
+			d = stalloc(psh, strlen(psh->curdir) + strlen(psh->argptr[1]) + 1);
+			memcpy(d, psh->curdir, p - psh->curdir);
+			strcpy(d + (p - psh->curdir), psh->argptr[1]);
+			strcat(d, p + strlen(dest));
+			dest = d;
+			print = 1;
+		}
+	}
+
+	if (dest[0] == '-' && dest[1] == '\0') {
+		dest = psh->prevdir ? psh->prevdir : psh->curdir;
+		print = 1;
+	}
+	if (*dest == '\0')
+	        dest = ".";
+	if (IS_ROOT(dest) || (path = bltinlookup(psh, "CDPATH", 1)) == NULL)
+		path = nullstr;
+	while ((p = padvance(psh, &path, dest)) != NULL) {
+		if (shfile_stat(&psh->fdtab, p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
+			if (!print) {
+				/*
+				 * XXX - rethink
+				 */
+				if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
+					p += 2;
+				print = strcmp(p, dest);
+			}
+			if (docd(psh, p, print) >= 0)
+				return 0;
+
+		}
+	}
+	error(psh, "can't cd to %s", dest);
+	/* NOTREACHED */
+        return 1;
+}
+
+
+/*
+ * Actually do the chdir.  In an interactive shell, print the
+ * directory name if "print" is nonzero.
+ */
+
+STATIC int
+docd(shinstance *psh, char *dest, int print)
+{
+	char *p;
+	char *q;
+	char *component;
+	struct stat statb;
+	int first;
+	int badstat;
+
+	TRACE((psh, "docd(\"%s\", %d) called\n", dest, print));
+
+	/*
+	 *  Check each component of the path. If we find a symlink or
+	 *  something we can't stat, clear curdir to force a getcwd()
+	 *  next time we get the value of the current directory.
+	 */
+	badstat = 0;
+	psh->cdcomppath = stalloc(psh, strlen(dest) + 1);
+	scopy(dest, psh->cdcomppath);
+	STARTSTACKSTR(psh, p);
+	if (IS_ROOT(dest)) {
+		STPUTC(psh, '/', p);
+		psh->cdcomppath++;
+	}
+	first = 1;
+	while ((q = getcomponent(psh)) != NULL) {
+		if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
+			continue;
+		if (! first)
+			STPUTC(psh, '/', p);
+		first = 0;
+		component = q;
+		while (*q)
+			STPUTC(psh, *q++, p);
+		if (equal(component, ".."))
+			continue;
+		STACKSTRNUL(psh, p);
+		if ((shfile_lstat(&psh->fdtab, stackblock(psh), &statb) < 0)
+		    || (S_ISLNK(statb.st_mode)))  {
+			/* print = 1; */
+			badstat = 1;
+			break;
+		}
+	}
+
+	INTOFF;
+	if (shfile_chdir(&psh->fdtab, dest) < 0) {
+		INTON;
+		return -1;
+	}
+	updatepwd(psh, badstat ? NULL : dest);
+	INTON;
+	if (print && iflag(psh) && psh->curdir)
+		out1fmt(psh, "%s\n", psh->curdir);
+	return 0;
+}
+
+
+/*
+ * Get the next component of the path name pointed to by psh->cdcomppath.
+ * This routine overwrites the string pointed to by psh->cdcomppath.
+ */
+
+STATIC char *
+getcomponent(shinstance *psh)
+{
+	char *p;
+	char *start;
+
+	if ((p = psh->cdcomppath) == NULL)
+		return NULL;
+	start = psh->cdcomppath;
+	while (*p != '/' && *p != '\0')
+		p++;
+	if (*p == '\0') {
+		psh->cdcomppath = NULL;
+	} else {
+		*p++ = '\0';
+		psh->cdcomppath = p;
+	}
+	return start;
+}
+
+
+
+/*
+ * Update curdir (the name of the current directory) in response to a
+ * cd command.  We also call hashcd to let the routines in exec.c know
+ * that the current directory has changed.
+ */
+
+STATIC void
+updatepwd(shinstance *psh, char *dir)
+{
+	char *new;
+	char *p;
+
+	hashcd(psh);				/* update command hash table */
+
+	/*
+	 * If our argument is NULL, we don't know the current directory
+	 * any more because we traversed a symbolic link or something
+	 * we couldn't stat().
+	 */
+	if (dir == NULL || psh->curdir == NULL)  {
+		if (psh->prevdir)
+			ckfree(psh->prevdir);
+		INTOFF;
+		psh->prevdir = psh->curdir;
+		psh->curdir = NULL;
+		getpwd(psh, 1);
+		INTON;
+		if (psh->curdir)
+			setvar(psh, "PWD", psh->curdir, VEXPORT);
+		else
+			unsetvar(psh, "PWD", 0);
+		return;
+	}
+	psh->cdcomppath = stalloc(psh, strlen(dir) + 1);
+	scopy(dir, psh->cdcomppath);
+	STARTSTACKSTR(psh, new);
+	if (!IS_ROOT(dir)) {
+		p = psh->curdir;
+		while (*p)
+			STPUTC(psh, *p++, new);
+		if (p[-1] == '/')
+			STUNPUTC(psh, new);
+	}
+	while ((p = getcomponent(psh)) != NULL) {
+		if (equal(p, "..")) {
+			while (new > stackblock(psh) && (STUNPUTC(psh, new), *new) != '/');
+		} else if (*p != '\0' && ! equal(p, ".")) {
+			STPUTC(psh, '/', new);
+			while (*p)
+				STPUTC(psh, *p++, new);
+		}
+	}
+	if (new == stackblock(psh))
+		STPUTC(psh, '/', new);
+	STACKSTRNUL(psh, new);
+	INTOFF;
+	if (psh->prevdir)
+		ckfree(psh->prevdir);
+	psh->prevdir = psh->curdir;
+	psh->curdir = savestr(stackblock(psh));
+	setvar(psh, "PWD", psh->curdir, VEXPORT);
+	INTON;
+}
+
+/*
+ * Posix says the default should be 'pwd -L' (as below), however
+ * the 'cd' command (above) does something much nearer to the
+ * posix 'cd -P' (not the posix default of 'cd -L').
+ * If 'cd' is changed to support -P/L then the default here
+ * needs to be revisited if the historic behaviour is to be kept.
+ */
+
+int
+pwdcmd(shinstance *psh, int argc, char **argv)
+{
+	int i;
+	char opt = 'L';
+
+	while ((i = nextopt(psh, "LP")) != '\0')
+		opt = i;
+	if (*psh->argptr)
+		error(psh, "unexpected argument");
+
+	if (opt == 'L')
+		getpwd(psh, 0);
+	else
+		find_curdir(psh, 0);
+
+	setvar(psh, "PWD", psh->curdir, VEXPORT);
+	out1str(psh, psh->curdir);
+	out1c(psh, '\n');
+	return 0;
+}
+
+
+
+
+#define MAXPWD 256
+
+/*
+ * Find out what the current directory is. If we already know the current
+ * directory, this routine returns immediately.
+ */
+const char *
+getpwd(shinstance *psh, int noerror)
+{
+	char *pwd;
+	struct stat stdot, stpwd;
+	/*static int first = 1;*/
+
+	if (psh->curdir)
+		return psh->curdir;
+
+	if (psh->getpwd_first) {
+		psh->getpwd_first = 0;
+		pwd = sh_getenv(psh, "PWD");
+		if (pwd && IS_ROOT(pwd) && shfile_stat(&psh->fdtab, ".", &stdot) != -1 &&
+		    shfile_stat(&psh->fdtab, pwd, &stpwd) != -1 &&
+		    stdot.st_dev == stpwd.st_dev &&
+		    stdot.st_ino == stpwd.st_ino) {
+			psh->curdir = savestr(pwd);
+			return psh->curdir;
+		}
+	}
+
+	find_curdir(psh, noerror);
+
+	return psh->curdir;
+}
+
+STATIC void
+find_curdir(shinstance *psh, int noerror)
+{
+	int i;
+	char *pwd;
+
+	/*
+	 * Things are a bit complicated here; we could have just used
+	 * getcwd, but traditionally getcwd is implemented using popen
+	 * to /bin/pwd. This creates a problem for us, since we cannot
+	 * keep track of the job if it is being ran behind our backs.
+	 * So we re-implement getcwd(), and we suppress interrupts
+	 * throughout the process. This is not completely safe, since
+	 * the user can still break out of it by killing the pwd program.
+	 * We still try to use getcwd for systems that we know have a
+	 * c implementation of getcwd, that does not open a pipe to
+	 * /bin/pwd.
+	 */
+#if 1 //defined(__NetBSD__) || defined(__SVR4) || defined(__INNOTEK_LIBC__)
+
+	for (i = MAXPWD;; i *= 2) {
+		pwd = stalloc(psh, i);
+		if (shfile_getcwd(&psh->fdtab, pwd, i) != NULL) {
+			psh->curdir = savestr(pwd);
+			return;
+		}
+		stunalloc(psh, pwd);
+		if (errno == ERANGE)
+			continue;
+		if (!noerror)
+			error(psh, "getcwd() failed: %s", strerror(errno));
+		return;
+	}
+#else
+	{
+		char *p;
+		int status;
+		struct job *jp;
+		int pip[2];
+
+		pwd = stalloc(psh, MAXPWD);
+		INTOFF;
+		if (pipe(pip) < 0)
+			error(psh, "Pipe call failed");
+		jp = makejob((union node *)NULL, 1);
+		if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
+			(void) close(pip[0]);
+			if (pip[1] != 1) {
+				close(1);
+				copyfd(pip[1], 1);
+				close(pip[1]);
+			}
+			(void) execl("/bin/pwd", "pwd", (char *)0);
+			error(psh, "Cannot exec /bin/pwd");
+		}
+		(void) close(pip[1]);
+		pip[1] = -1;
+		p = pwd;
+		while ((i = read(pip[0], p, pwd + MAXPWD - p)) > 0
+		     || (i == -1 && errno == EINTR)) {
+			if (i > 0)
+				p += i;
+		}
+		(void) close(pip[0]);
+		pip[0] = -1;
+		status = waitforjob(jp);
+		if (status != 0)
+			error(psh, (char *)0);
+		if (i < 0 || p == pwd || p[-1] != '\n') {
+			if (noerror) {
+				INTON;
+				return;
+			}
+			error(psh, "pwd command failed");
+		}
+		p[-1] = '\0';
+		INTON;
+		psh->curdir = savestr(pwd);
+		return;
+	}
+#endif
+}
Index: /tags/kBuild-0.1.4/src/kash/cd.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/cd.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/cd.h	(revision 1780)
@@ -0,0 +1,43 @@
+/*	$NetBSD: cd.h,v 1.4 2003/08/07 09:05:30 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+const char *getpwd(struct shinstance *, int);
+int	cdcmd(struct shinstance *, int, char **);
+int	pwdcmd(struct shinstance *, int, char **);
+#ifdef PC_DRIVE_LETTERS
+#define IS_ROOT(path) (   *(path) == '/' \
+                       || *(path) == '\\' \
+                       ||  ( ((*(path) >= 'A' && *(path) <= 'Z') || (*(path) >= 'a' && *(path) <= 'z')) \
+                             && (path)[1] == ':') )
+#else
+#define IS_ROOT(path) ( *(path) == '/' )
+#endif
Index: /tags/kBuild-0.1.4/src/kash/error.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/error.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/error.c	(revision 1780)
@@ -0,0 +1,366 @@
+/*	$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $");
+#endif /* not lint */
+#endif
+
+/*
+ * Errors and exceptions.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "shell.h"
+#include "main.h"
+#include "options.h"
+#include "output.h"
+#include "error.h"
+#include "show.h"
+#include "shinstance.h"
+
+
+/*
+ * Code to handle exceptions in C.
+ */
+
+/*struct jmploc *handler;
+int exception;
+volatile int suppressint;
+volatile int intpending;
+char *commandname;*/
+
+
+static void exverror(shinstance *psh, int, const char *, va_list)
+    __attribute__((__noreturn__));
+
+/*
+ * Called to raise an exception.  Since C doesn't include exceptions, we
+ * just do a longjmp to the exception handler.  The type of exception is
+ * stored in the global variable "exception".
+ */
+
+void
+exraise(shinstance *psh, int e)
+{
+	if (psh->handler == NULL)
+		sh_abort(psh);
+	psh->exception = e;
+	longjmp(psh->handler->loc, 1);
+}
+
+
+/*
+ * Called from trap.c when a SIGINT is received.  (If the user specifies
+ * that SIGINT is to be trapped or ignored using the trap builtin, then
+ * this routine is not called.)  Suppressint is nonzero when interrupts
+ * are held using the INTOFF macro.  The call to _exit is necessary because
+ * there is a short period after a fork before the signal handlers are
+ * set to the appropriate value for the child.  (The test for iflag is
+ * just defensive programming.)
+ */
+
+void
+onint(shinstance *psh)
+{
+	shsigset_t nsigset;
+
+	if (psh->suppressint) {
+		psh->intpending = 1;
+		return;
+	}
+	psh->intpending = 0;
+	sh_sigemptyset(&nsigset);
+	sh_sigprocmask(psh, SIG_SETMASK, &nsigset, NULL);
+	if (psh->rootshell && iflag(psh))
+		exraise(psh, EXINT);
+	else {
+		sh_signal(psh, SIGINT, SH_SIG_DFL);
+		sh_raise_sigint(psh);/*raise(psh, SIGINT);*/
+	}
+	/* NOTREACHED */
+}
+
+static void
+exvwarning(shinstance *psh, int sv_errno, const char *msg, va_list ap)
+{
+	/* Partially emulate line buffered output so that:
+	 *	printf '%d\n' 1 a 2
+	 * and
+	 *	printf '%d %d %d\n' 1 a 2
+	 * both generate sensible text when stdout and stderr are merged.
+	 */
+	if (psh->output.nextc != psh->output.buf && psh->output.nextc[-1] == '\n')
+		flushout(&psh->output);
+	if (psh->commandname)
+		outfmt(&psh->errout, "%s: ", psh->commandname);
+	if (msg != NULL) {
+		doformat(&psh->errout, msg, ap);
+		if (sv_errno >= 0)
+			outfmt(&psh->errout, ": ");
+	}
+	if (sv_errno >= 0)
+		outfmt(&psh->errout, "%s", strerror(sv_errno));
+	out2c(psh, '\n');
+	flushout(&psh->errout);
+}
+
+/*
+ * Exverror is called to raise the error exception.  If the second argument
+ * is not NULL then error prints an error message using printf style
+ * formatting.  It then raises the error exception.
+ */
+static void
+exverror(shinstance *psh, int cond, const char *msg, va_list ap)
+{
+	CLEAR_PENDING_INT;
+	INTOFF;
+
+#ifdef DEBUG
+	if (msg) {
+		TRACE((psh, "exverror(%d, \"", cond));
+		TRACEV((psh, msg, ap));
+		TRACE((psh, "\") pid=%d\n", sh_getpid(psh)));
+	} else
+		TRACE((psh, "exverror(%d, NULL) pid=%d\n", cond, sh_getpid(psh)));
+#endif
+	if (msg)
+		exvwarning(psh, -1, msg, ap);
+
+	output_flushall(psh);
+	exraise(psh, cond);
+	/* NOTREACHED */
+}
+
+
+void
+error(shinstance *psh, const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+	exverror(psh, EXERROR, msg, ap);
+	/* NOTREACHED */
+	va_end(ap);
+}
+
+
+void
+exerror(shinstance *psh, int cond, const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+	exverror(psh, cond, msg, ap);
+	/* NOTREACHED */
+	va_end(ap);
+}
+
+/*
+ * error/warning routines for external builtins
+ */
+
+void
+sh_exit(shinstance *psh, int rval)
+{
+	psh->exerrno = rval & 255;
+	exraise(psh, EXEXEC);
+}
+
+void
+sh_err(shinstance *psh, int status, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(psh, errno, fmt, ap);
+	va_end(ap);
+	sh_exit(psh, status);
+}
+
+void
+sh_verr(shinstance *psh, int status, const char *fmt, va_list ap)
+{
+	exvwarning(psh, errno, fmt, ap);
+	sh_exit(psh, status);
+}
+
+void
+sh_errx(shinstance *psh, int status, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(psh, -1, fmt, ap);
+	va_end(ap);
+	sh_exit(psh, status);
+}
+
+void
+sh_verrx(shinstance *psh, int status, const char *fmt, va_list ap)
+{
+	exvwarning(psh, -1, fmt, ap);
+	sh_exit(psh, status);
+}
+
+void
+sh_warn(shinstance *psh, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(psh, errno, fmt, ap);
+	va_end(ap);
+}
+
+void
+sh_vwarn(shinstance *psh, const char *fmt, va_list ap)
+{
+	exvwarning(psh, errno, fmt, ap);
+}
+
+void
+sh_warnx(shinstance *psh, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(psh, -1, fmt, ap);
+	va_end(ap);
+}
+
+void
+sh_vwarnx(shinstance *psh, const char *fmt, va_list ap)
+{
+	exvwarning(psh, -1, fmt, ap);
+}
+
+
+/*
+ * Table of error messages.
+ */
+
+struct errname {
+	short errcode;		/* error number */
+	short action;		/* operation which encountered the error */
+	const char *msg;	/* text describing the error */
+};
+
+
+#define ALL (E_OPEN|E_CREAT|E_EXEC)
+
+STATIC const struct errname errormsg[] = {
+	{ EINTR,	ALL,	"interrupted" },
+	{ EACCES,	ALL,	"permission denied" },
+	{ EIO,		ALL,	"I/O error" },
+	{ EEXIST,	ALL,	"file exists" },
+	{ ENOENT,	E_OPEN,	"no such file" },
+	{ ENOENT,	E_CREAT,"directory nonexistent" },
+	{ ENOENT,	E_EXEC,	"not found" },
+	{ ENOTDIR,	E_OPEN,	"no such file" },
+	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
+	{ ENOTDIR,	E_EXEC,	"not found" },
+	{ EISDIR,	ALL,	"is a directory" },
+#ifdef EMFILE
+	{ EMFILE,	ALL,	"too many open files" },
+#endif
+	{ ENFILE,	ALL,	"file table overflow" },
+	{ ENOSPC,	ALL,	"file system full" },
+#ifdef EDQUOT
+	{ EDQUOT,	ALL,	"disk quota exceeded" },
+#endif
+#ifdef ENOSR
+	{ ENOSR,	ALL,	"no streams resources" },
+#endif
+	{ ENXIO,	ALL,	"no such device or address" },
+	{ EROFS,	ALL,	"read-only file system" },
+#ifdef ETXTBSY
+	{ ETXTBSY,	ALL,	"text busy" },
+#endif
+#ifdef EAGAIN
+	{ EAGAIN,	E_EXEC,	"not enough memory" },
+#endif
+	{ ENOMEM,	ALL,	"not enough memory" },
+#ifdef ENOLINK
+	{ ENOLINK,	ALL,	"remote access failed" },
+#endif
+#ifdef EMULTIHOP
+	{ EMULTIHOP,	ALL,	"remote access failed" },
+#endif
+#ifdef ECOMM
+	{ ECOMM,	ALL,	"remote access failed" },
+#endif
+#ifdef ESTALE
+	{ ESTALE,	ALL,	"remote access failed" },
+#endif
+#ifdef ETIMEDOUT
+	{ ETIMEDOUT,	ALL,	"remote access failed" },
+#endif
+#ifdef ELOOP
+	{ ELOOP,	ALL,	"symbolic link loop" },
+#endif
+	{ E2BIG,	E_EXEC,	"argument list too long" },
+#ifdef ELIBACC
+	{ ELIBACC,	E_EXEC,	"shared library missing" },
+#endif
+	{ 0,		0,	NULL },
+};
+
+
+/*
+ * Return a string describing an error.  The returned string may be a
+ * pointer to a static buffer that will be overwritten on the next call.
+ * Action describes the operation that got the error.
+ */
+
+const char *
+errmsg(shinstance *psh, int e, int action)
+{
+	struct errname const *ep;
+	/*static char buf[12];*/
+
+	for (ep = errormsg ; ep->errcode ; ep++) {
+		if (ep->errcode == e && (ep->action & action) != 0)
+			return ep->msg;
+	}
+	fmtstr(psh->errmsg_buf, sizeof psh->errmsg_buf, "error %d", e);
+	return psh->errmsg_buf;
+}
Index: /tags/kBuild-0.1.4/src/kash/error.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/error.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/error.h	(revision 1780)
@@ -0,0 +1,128 @@
+/*	$NetBSD: error.h,v 1.16 2003/08/07 09:05:30 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)error.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef ___error_h
+#define ___error_h
+
+#include "shtypes.h"
+#include <stdarg.h>
+
+/*
+ * Types of operations (passed to the errmsg routine).
+ */
+
+#define E_OPEN 01	/* opening a file */
+#define E_CREAT 02	/* creating a file */
+#define E_EXEC 04	/* executing a program */
+
+
+/*
+ * We enclose jmp_buf in a structure so that we can declare pointers to
+ * jump locations.  The global variable handler contains the location to
+ * jump to when an exception occurs, and the global variable exception
+ * contains a code identifying the exeception.  To implement nested
+ * exception handlers, the user should save the value of handler on entry
+ * to an inner scope, set handler to point to a jmploc structure for the
+ * inner scope, and restore handler on exit from the scope.
+ */
+
+#include <setjmp.h>
+
+struct jmploc {
+	jmp_buf loc;
+};
+
+/*
+extern struct jmploc *handler;
+extern int exception;
+extern int exerrno;*/	/* error for EXEXEC */
+
+/* exceptions */
+#define EXINT 0		/* SIGINT received */
+#define EXERROR 1	/* a generic error */
+#define EXSHELLPROC 2	/* execute a shell procedure */
+#define EXEXEC 3	/* command execution failed */
+
+
+/*
+ * These macros allow the user to suspend the handling of interrupt signals
+ * over a period of time.  This is similar to SIGHOLD to or sigblock, but
+ * much more efficient and portable.  (But hacking the kernel is so much
+ * more fun than worrying about efficiency and portability. :-))
+ */
+
+/*extern volatile int suppressint;
+extern volatile int intpending;*/
+
+#define INTOFF psh->suppressint++
+#define INTON { if (--psh->suppressint == 0 && psh->intpending) onint(psh); }
+#define FORCEINTON {psh->suppressint = 0; if (psh->intpending) onint(psh);}
+#define CLEAR_PENDING_INT psh->intpending = 0
+#define int_pending() psh->intpending
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+# define __attribute__(a)
+#endif
+
+void exraise(struct shinstance *, int) __attribute__((__noreturn__));
+void onint(struct shinstance *);
+void error(struct shinstance *, const char *, ...) __attribute__((__noreturn__));
+void exerror(struct shinstance *, int, const char *, ...) __attribute__((__noreturn__));
+const char *errmsg(struct shinstance *, int, int);
+
+void sh_err(struct shinstance *, int, const char *, ...) __attribute__((__noreturn__));
+void sh_verr(struct shinstance *, int, const char *, va_list) __attribute__((__noreturn__));
+void sh_errx(struct shinstance *, int, const char *, ...) __attribute__((__noreturn__));
+void sh_verrx(struct shinstance *, int, const char *, va_list) __attribute__((__noreturn__));
+void sh_warn(struct shinstance *, const char *, ...);
+void sh_vwarn(struct shinstance *, const char *, va_list);
+void sh_warnx(struct shinstance *, const char *, ...);
+void sh_vwarnx(struct shinstance *, const char *, va_list);
+
+void sh_exit(struct shinstance *, int) __attribute__((__noreturn__));
+
+
+/*
+ * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
+ * so we use _setjmp instead.
+ */
+
+#if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__) && !defined(__KLIBC__) && !defined(_MSC_VER)
+#define setjmp(jmploc)	_setjmp(jmploc)
+#define longjmp(jmploc, val)	_longjmp(jmploc, val)
+#endif
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/eval.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/eval.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/eval.c	(revision 1780)
@@ -0,0 +1,1271 @@
+/*	$NetBSD: eval.c,v 1.84 2005/06/23 23:05:29 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
+#else
+__RCSID("$NetBSD: eval.c,v 1.84 2005/06/23 23:05:29 christos Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_SYSCTL_H
+# include <sys/sysctl.h>
+#endif
+
+/*
+ * Evaluate a command.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "syntax.h"
+#include "expand.h"
+#include "parser.h"
+#include "jobs.h"
+#include "eval.h"
+#include "builtins.h"
+#include "options.h"
+#include "exec.h"
+#include "redir.h"
+#include "input.h"
+#include "output.h"
+#include "trap.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "show.h"
+#include "mystring.h"
+#include "main.h"
+#ifndef SMALL
+# include "myhistedit.h"
+#endif
+#include "shinstance.h"
+
+
+/* flags in argument to evaltree */
+#define EV_EXIT 01		/* exit after evaluating tree */
+#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
+#define EV_BACKCMD 04		/* command executing within back quotes */
+
+/*int evalskip;*/			/* set if we are skipping commands */
+/*STATIC int skipcount;*/		/* number of levels to skip */
+/*MKINIT int loopnest;*/		/* current loop nesting level */
+/*int funcnest;*/			/* depth of function calls */
+
+
+/*char *commandname;*/
+/*struct strlist *cmdenviron;*/
+/*int exitstatus;*/			/* exit status of last command */
+/*int back_exitstatus;*/		/* exit status of backquoted command */
+
+
+STATIC void evalloop(shinstance *, union node *, int);
+STATIC void evalfor(shinstance *, union node *, int);
+STATIC void evalcase(shinstance *, union node *, int);
+STATIC void evalsubshell(shinstance *, union node *, int);
+STATIC void expredir(shinstance *, union node *);
+STATIC void evalpipe(shinstance *, union node *);
+STATIC void evalcommand(shinstance *, union node *, int, struct backcmd *);
+STATIC void prehash(shinstance *, union node *);
+
+
+/*
+ * Called to reset things after an exception.
+ */
+
+#ifdef mkinit
+INCLUDE "eval.h"
+
+RESET {
+	psh->evalskip = 0;
+	psh->loopnest = 0;
+	psh->funcnest = 0;
+}
+
+SHELLPROC {
+	psh->exitstatus = 0;
+}
+#endif
+
+static int
+sh_pipe(shinstance *psh, int fds[2])
+{
+	int nfd;
+
+	if (shfile_pipe(&psh->fdtab, fds))
+		return -1;
+
+	if (fds[0] < 3) {
+		nfd = shfile_fcntl(&psh->fdtab, fds[0], F_DUPFD, 3);
+		if (nfd != -1) {
+			shfile_close(&psh->fdtab, fds[0]);
+			fds[0] = nfd;
+		}
+	}
+
+	if (fds[1] < 3) {
+		nfd = shfile_fcntl(&psh->fdtab, fds[1], F_DUPFD, 3);
+		if (nfd != -1) {
+			shfile_close(&psh->fdtab, fds[1]);
+			fds[1] = nfd;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * The eval commmand.
+ */
+
+int
+evalcmd(shinstance *psh, int argc, char **argv)
+{
+	char *p;
+	char *concat;
+	char **ap;
+
+	if (argc > 1) {
+		p = argv[1];
+		if (argc > 2) {
+			STARTSTACKSTR(psh, concat);
+			ap = argv + 2;
+			for (;;) {
+				while (*p)
+					STPUTC(psh, *p++, concat);
+				if ((p = *ap++) == NULL)
+					break;
+				STPUTC(psh, ' ', concat);
+			}
+			STPUTC(psh, '\0', concat);
+			p = grabstackstr(psh, concat);
+		}
+		evalstring(psh, p, EV_TESTED);
+	}
+	return psh->exitstatus;
+}
+
+
+/*
+ * Execute a command or commands contained in a string.
+ */
+
+void
+evalstring(shinstance *psh, char *s, int flag)
+{
+	union node *n;
+	struct stackmark smark;
+
+	setstackmark(psh, &smark);
+	setinputstring(psh, s, 1);
+
+	while ((n = parsecmd(psh, 0)) != NEOF) {
+		evaltree(psh, n, flag);
+		popstackmark(psh, &smark);
+	}
+	popfile(psh);
+	popstackmark(psh, &smark);
+}
+
+
+
+/*
+ * Evaluate a parse tree.  The value is left in the global variable
+ * exitstatus.
+ */
+
+void
+evaltree(shinstance *psh, union node *n, int flags)
+{
+	if (n == NULL) {
+		TRACE((psh, "evaltree(NULL) called\n"));
+		psh->exitstatus = 0;
+		goto out;
+	}
+#ifndef SMALL
+	psh->displayhist = 1;	/* show history substitutions done with fc */
+#endif
+	TRACE((psh, "pid %d, evaltree(%p: %d, %d) called\n",
+	       sh_getpid(psh), n, n->type, flags));
+	switch (n->type) {
+	case NSEMI:
+		evaltree(psh, n->nbinary.ch1, flags & EV_TESTED);
+		if (psh->evalskip)
+			goto out;
+		evaltree(psh, n->nbinary.ch2, flags);
+		break;
+	case NAND:
+		evaltree(psh, n->nbinary.ch1, EV_TESTED);
+		if (psh->evalskip || psh->exitstatus != 0)
+			goto out;
+		evaltree(psh, n->nbinary.ch2, flags);
+		break;
+	case NOR:
+		evaltree(psh, n->nbinary.ch1, EV_TESTED);
+		if (psh->evalskip || psh->exitstatus == 0)
+			goto out;
+		evaltree(psh, n->nbinary.ch2, flags);
+		break;
+	case NREDIR:
+		expredir(psh, n->nredir.redirect);
+		redirect(psh, n->nredir.redirect, REDIR_PUSH);
+		evaltree(psh, n->nredir.n, flags);
+		popredir(psh);
+		break;
+	case NSUBSHELL:
+		evalsubshell(psh, n, flags);
+		break;
+	case NBACKGND:
+		evalsubshell(psh, n, flags);
+		break;
+	case NIF: {
+		evaltree(psh, n->nif.test, EV_TESTED);
+		if (psh->evalskip)
+			goto out;
+		if (psh->exitstatus == 0)
+			evaltree(psh, n->nif.ifpart, flags);
+		else if (n->nif.elsepart)
+			evaltree(psh, n->nif.elsepart, flags);
+		else
+			psh->exitstatus = 0;
+		break;
+	}
+	case NWHILE:
+	case NUNTIL:
+		evalloop(psh, n, flags);
+		break;
+	case NFOR:
+		evalfor(psh, n, flags);
+		break;
+	case NCASE:
+		evalcase(psh, n, flags);
+		break;
+	case NDEFUN:
+		defun(psh, n->narg.text, n->narg.next);
+		psh->exitstatus = 0;
+		break;
+	case NNOT:
+		evaltree(psh, n->nnot.com, EV_TESTED);
+		psh->exitstatus = !psh->exitstatus;
+		break;
+	case NPIPE:
+		evalpipe(psh, n);
+		break;
+	case NCMD:
+		evalcommand(psh, n, flags, (struct backcmd *)NULL);
+		break;
+	default:
+		out1fmt(psh, "Node type = %d\n", n->type);
+		flushout(&psh->output);
+		break;
+	}
+out:
+	if (psh->pendingsigs)
+		dotrap(psh);
+	if ((flags & EV_EXIT) != 0)
+		exitshell(psh, psh->exitstatus);
+}
+
+
+STATIC void
+evalloop(shinstance *psh, union node *n, int flags)
+{
+	int status;
+
+	psh->loopnest++;
+	status = 0;
+	for (;;) {
+		evaltree(psh, n->nbinary.ch1, EV_TESTED);
+		if (psh->evalskip) {
+skipping:	  if (psh->evalskip == SKIPCONT && --psh->skipcount <= 0) {
+				psh->evalskip = 0;
+				continue;
+			}
+			if (psh->evalskip == SKIPBREAK && --psh->skipcount <= 0)
+				psh->evalskip = 0;
+			break;
+		}
+		if (n->type == NWHILE) {
+			if (psh->exitstatus != 0)
+				break;
+		} else {
+			if (psh->exitstatus == 0)
+				break;
+		}
+		evaltree(psh, n->nbinary.ch2, flags & EV_TESTED);
+		status = psh->exitstatus;
+		if (psh->evalskip)
+			goto skipping;
+	}
+	psh->loopnest--;
+	psh->exitstatus = status;
+}
+
+
+
+STATIC void
+evalfor(shinstance *psh, union node *n, int flags)
+{
+	struct arglist arglist;
+	union node *argp;
+	struct strlist *sp;
+	struct stackmark smark;
+	int status = 0;
+
+	setstackmark(psh, &smark);
+	arglist.lastp = &arglist.list;
+	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
+		expandarg(psh, argp, &arglist, EXP_FULL | EXP_TILDE);
+		if (psh->evalskip)
+			goto out;
+	}
+	*arglist.lastp = NULL;
+
+	psh->loopnest++;
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		setvar(psh, n->nfor.var, sp->text, 0);
+		evaltree(psh, n->nfor.body, flags & EV_TESTED);
+		status = psh->exitstatus;
+		if (psh->evalskip) {
+			if (psh->evalskip == SKIPCONT && --psh->skipcount <= 0) {
+				psh->evalskip = 0;
+				continue;
+			}
+			if (psh->evalskip == SKIPBREAK && --psh->skipcount <= 0)
+				psh->evalskip = 0;
+			break;
+		}
+	}
+	psh->loopnest--;
+	psh->exitstatus = status;
+out:
+	popstackmark(psh, &smark);
+}
+
+
+
+STATIC void
+evalcase(shinstance *psh, union node *n, int flags)
+{
+	union node *cp;
+	union node *patp;
+	struct arglist arglist;
+	struct stackmark smark;
+	int status = 0;
+
+	setstackmark(psh, &smark);
+	arglist.lastp = &arglist.list;
+	expandarg(psh, n->ncase.expr, &arglist, EXP_TILDE);
+	for (cp = n->ncase.cases ; cp && psh->evalskip == 0 ; cp = cp->nclist.next) {
+		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
+			if (casematch(psh, patp, arglist.list->text)) {
+				if (psh->evalskip == 0) {
+					evaltree(psh, cp->nclist.body, flags);
+					status = psh->exitstatus;
+				}
+				goto out;
+			}
+		}
+	}
+out:
+	psh->exitstatus = status;
+	popstackmark(psh, &smark);
+}
+
+
+
+/*
+ * Kick off a subshell to evaluate a tree.
+ */
+
+STATIC void
+evalsubshell(shinstance *psh, union node *n, int flags)
+{
+	struct job *jp;
+	int backgnd = (n->type == NBACKGND);
+
+	expredir(psh, n->nredir.redirect);
+	INTOFF;
+	jp = makejob(psh, n, 1);
+	if (forkshell(psh, jp, n, backgnd ? FORK_BG : FORK_FG) == 0) {
+		INTON;
+		if (backgnd)
+			flags &=~ EV_TESTED;
+		redirect(psh, n->nredir.redirect, 0);
+		/* never returns */
+		evaltree(psh, n->nredir.n, flags | EV_EXIT);
+	}
+	if (! backgnd)
+		psh->exitstatus = waitforjob(psh, jp);
+	INTON;
+}
+
+
+
+/*
+ * Compute the names of the files in a redirection list.
+ */
+
+STATIC void
+expredir(shinstance *psh, union node *n)
+{
+	union node *redir;
+
+	for (redir = n ; redir ; redir = redir->nfile.next) {
+		struct arglist fn;
+		fn.lastp = &fn.list;
+		switch (redir->type) {
+		case NFROMTO:
+		case NFROM:
+		case NTO:
+		case NCLOBBER:
+		case NAPPEND:
+			expandarg(psh, redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+			redir->nfile.expfname = fn.list->text;
+			break;
+		case NFROMFD:
+		case NTOFD:
+			if (redir->ndup.vname) {
+				expandarg(psh, redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
+				fixredir(psh, redir, fn.list->text, 1);
+			}
+			break;
+		}
+	}
+}
+
+
+
+/*
+ * Evaluate a pipeline.  All the processes in the pipeline are children
+ * of the process creating the pipeline.  (This differs from some versions
+ * of the shell, which make the last process in a pipeline the parent
+ * of all the rest.)
+ */
+
+STATIC void
+evalpipe(shinstance *psh, union node *n)
+{
+	struct job *jp;
+	struct nodelist *lp;
+	int pipelen;
+	int prevfd;
+	int pip[2];
+
+	TRACE((psh, "evalpipe(0x%lx) called\n", (long)n));
+	pipelen = 0;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
+		pipelen++;
+	INTOFF;
+	jp = makejob(psh, n, pipelen);
+	prevfd = -1;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+		prehash(psh, lp->n);
+		pip[1] = -1;
+		if (lp->next) {
+			if (sh_pipe(psh, pip) < 0) {
+				shfile_close(&psh->fdtab, prevfd);
+				error(psh, "Pipe call failed");
+			}
+		}
+		if (forkshell(psh, jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) {
+			INTON;
+			if (prevfd > 0) {
+				shfile_close(&psh->fdtab, 0);
+				copyfd(psh, prevfd, 0);
+				shfile_close(&psh->fdtab, prevfd);
+			}
+			if (pip[1] >= 0) {
+				shfile_close(&psh->fdtab, pip[0]);
+				if (pip[1] != 1) {
+					shfile_close(&psh->fdtab, 1);
+					copyfd(psh, pip[1], 1);
+					shfile_close(&psh->fdtab, pip[1]);
+				}
+			}
+			evaltree(psh, lp->n, EV_EXIT);
+		}
+		if (prevfd >= 0)
+			shfile_close(&psh->fdtab, prevfd);
+		prevfd = pip[0];
+		shfile_close(&psh->fdtab, pip[1]);
+	}
+	if (n->npipe.backgnd == 0) {
+		psh->exitstatus = waitforjob(psh, jp);
+		TRACE((psh, "evalpipe:  job done exit status %d\n", psh->exitstatus));
+	}
+	INTON;
+}
+
+
+
+/*
+ * Execute a command inside back quotes.  If it's a builtin command, we
+ * want to save its output in a block obtained from malloc.  Otherwise
+ * we fork off a subprocess and get the output of the command via a pipe.
+ * Should be called with interrupts off.
+ */
+
+void
+evalbackcmd(shinstance *psh, union node *n, struct backcmd *result)
+{
+	int pip[2];
+	struct job *jp;
+	struct stackmark smark;		/* unnecessary */
+
+	setstackmark(psh, &smark);
+	result->fd = -1;
+	result->buf = NULL;
+	result->nleft = 0;
+	result->jp = NULL;
+	if (n == NULL) {
+		goto out;
+	}
+#ifdef notyet
+	/*
+	 * For now we disable executing builtins in the same
+	 * context as the shell, because we are not keeping
+	 * enough state to recover from changes that are
+	 * supposed only to affect subshells. eg. echo "`cd /`"
+	 */
+	if (n->type == NCMD) {
+		psh->exitstatus = opsh->exitstatus;
+		evalcommand(psh, n, EV_BACKCMD, result);
+	} else
+#endif
+	{
+		INTOFF;
+		if (sh_pipe(psh, pip) < 0)
+			error(psh, "Pipe call failed");
+		jp = makejob(psh, n, 1);
+		if (forkshell(psh, jp, n, FORK_NOJOB) == 0) {
+			FORCEINTON;
+			shfile_close(&psh->fdtab, pip[0]);
+			if (pip[1] != 1) {
+				shfile_close(&psh->fdtab, 1);
+				copyfd(psh, pip[1], 1);
+				shfile_close(&psh->fdtab, pip[1]);
+			}
+			eflag(psh) = 0;
+			evaltree(psh, n, EV_EXIT);
+			/* NOTREACHED */
+		}
+		shfile_close(&psh->fdtab, pip[1]);
+		result->fd = pip[0];
+		result->jp = jp;
+		INTON;
+	}
+out:
+	popstackmark(psh, &smark);
+	TRACE((psh, "evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
+		result->fd, result->buf, result->nleft, result->jp));
+}
+
+static const char *
+syspath(shinstance *psh)
+{
+#ifdef CTL_USER
+	static char *sys_path = NULL;
+	static int mib[] = {CTL_USER, USER_CS_PATH};
+#endif
+#ifdef PC_PATH_SEP
+	static char def_path[] = "PATH=/usr/bin;/bin;/usr/sbin;/sbin";
+#else
+	static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin";
+#endif
+#ifdef CTL_USER
+	size_t len;
+
+	if (sys_path == NULL) {
+		if (sysctl(mib, 2, 0, &len, 0, 0) != -1 &&
+		    (sys_path = ckmalloc(len + 5)) != NULL &&
+		    sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) {
+			memcpy(sys_path, "PATH=", 5);
+		} else {
+			ckfree(sys_path);
+			/* something to keep things happy */
+			sys_path = def_path;
+		}
+	}
+	return sys_path;
+#else
+	return def_path;
+#endif
+}
+
+static int
+parse_command_args(shinstance *psh, int argc, char **argv, int *use_syspath)
+{
+	int sv_argc = argc;
+	char *cp, c;
+
+	*use_syspath = 0;
+
+	for (;;) {
+		argv++;
+		if (--argc == 0)
+			break;
+		cp = *argv;
+		if (*cp++ != '-')
+			break;
+		if (*cp == '-' && cp[1] == 0) {
+			argv++;
+			argc--;
+			break;
+		}
+		while ((c = *cp++)) {
+			switch (c) {
+			case 'p':
+				*use_syspath = 1;
+				break;
+			default:
+				/* run 'typecmd' for other options */
+				return 0;
+			}
+		}
+	}
+	return sv_argc - argc;
+}
+
+/*int vforked = 0;*/
+
+/*
+ * Execute a simple command.
+ */
+
+STATIC void
+evalcommand(shinstance *psh, union node *cmd, int flags, struct backcmd *backcmd)
+{
+	struct stackmark smark;
+	union node *argp;
+	struct arglist arglist;
+	struct arglist varlist;
+	char **argv;
+	int argc;
+	char **envp;
+	int varflag;
+	struct strlist *sp;
+	int mode;
+	int pip[2];
+	struct cmdentry cmdentry;
+	struct job *jp;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	char *volatile savecmdname;
+	volatile struct shparam saveparam;
+	struct localvar *volatile savelocalvars;
+	volatile int e;
+	char *lastarg;
+	const char *path = pathval(psh);
+	volatile int temp_path;
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &argv;
+	(void) &argc;
+	(void) &lastarg;
+	(void) &flags;
+#endif
+
+	psh->vforked = 0;
+	/* First expand the arguments. */
+	TRACE((psh, "evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
+	setstackmark(psh, &smark);
+	psh->exitstatus = 0;
+
+	arglist.lastp = &arglist.list;
+	varflag = 1;
+	/* Expand arguments, ignoring the initial 'name=value' ones */
+	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
+		char *p = argp->narg.text;
+		if (varflag && is_name(*p)) {
+			do {
+				p++;
+			} while (is_in_name(*p));
+			if (*p == '=')
+				continue;
+		}
+		expandarg(psh, argp, &arglist, EXP_FULL | EXP_TILDE);
+		varflag = 0;
+	}
+	*arglist.lastp = NULL;
+
+	expredir(psh, cmd->ncmd.redirect);
+
+	/* Now do the initial 'name=value' ones we skipped above */
+	varlist.lastp = &varlist.list;
+	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
+		char *p = argp->narg.text;
+		if (!is_name(*p))
+			break;
+		do
+			p++;
+		while (is_in_name(*p));
+		if (*p != '=')
+			break;
+		expandarg(psh, argp, &varlist, EXP_VARTILDE);
+	}
+	*varlist.lastp = NULL;
+
+	argc = 0;
+	for (sp = arglist.list ; sp ; sp = sp->next)
+		argc++;
+	argv = stalloc(psh, sizeof (char *) * (argc + 1));
+
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		TRACE((psh, "evalcommand arg: %s\n", sp->text));
+		*argv++ = sp->text;
+	}
+	*argv = NULL;
+	lastarg = NULL;
+	if (iflag(psh) && psh->funcnest == 0 && argc > 0)
+		lastarg = argv[-1];
+	argv -= argc;
+
+	/* Print the command if xflag is set. */
+	if (xflag(psh)) {
+		char sep = 0;
+		out2str(psh, ps4val(psh));
+		for (sp = varlist.list ; sp ; sp = sp->next) {
+			if (sep != 0)
+				outc(sep, &psh->errout);
+			out2str(psh, sp->text);
+			sep = ' ';
+		}
+		for (sp = arglist.list ; sp ; sp = sp->next) {
+			if (sep != 0)
+				outc(sep, &psh->errout);
+			out2str(psh, sp->text);
+			sep = ' ';
+		}
+		outc('\n', &psh->errout);
+		flushout(&psh->errout);
+	}
+
+	/* Now locate the command. */
+	if (argc == 0) {
+		cmdentry.cmdtype = CMDSPLBLTIN;
+		cmdentry.u.bltin = bltincmd;
+	} else {
+		static const char PATH[] = "PATH=";
+		int cmd_flags = DO_ERR;
+
+		/*
+		 * Modify the command lookup path, if a PATH= assignment
+		 * is present
+		 */
+		for (sp = varlist.list; sp; sp = sp->next)
+			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
+				path = sp->text + sizeof(PATH) - 1;
+
+		do {
+			int argsused, use_syspath;
+			find_command(psh, argv[0], &cmdentry, cmd_flags, path);
+			if (cmdentry.cmdtype == CMDUNKNOWN) {
+				psh->exitstatus = 127;
+				flushout(&psh->errout);
+				goto out;
+			}
+
+			/* implement the 'command' builtin here */
+			if (cmdentry.cmdtype != CMDBUILTIN ||
+			    cmdentry.u.bltin != bltincmd)
+				break;
+			cmd_flags |= DO_NOFUNC;
+			argsused = parse_command_args(psh, argc, argv, &use_syspath);
+			if (argsused == 0) {
+				/* use 'type' builting to display info */
+				cmdentry.u.bltin = typecmd;
+				break;
+			}
+			argc -= argsused;
+			argv += argsused;
+			if (use_syspath)
+				path = syspath(psh) + 5;
+		} while (argc != 0);
+		if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC)
+			/* posix mandates that 'command <splbltin>' act as if
+			   <splbltin> was a normal builtin */
+			cmdentry.cmdtype = CMDBUILTIN;
+	}
+
+	/* Fork off a child process if necessary. */
+	if (cmd->ncmd.backgnd
+	 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
+	 || ((flags & EV_BACKCMD) != 0
+	    && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN)
+		 || cmdentry.u.bltin == dotcmd
+		 || cmdentry.u.bltin == evalcmd))) {
+		INTOFF;
+		jp = makejob(psh, cmd, 1);
+		mode = cmd->ncmd.backgnd;
+		if (flags & EV_BACKCMD) {
+			mode = FORK_NOJOB;
+			if (sh_pipe(psh, pip) < 0)
+				error(psh, "Pipe call failed");
+		}
+#ifdef DO_SHAREDVFORK
+		/* It is essential that if DO_SHAREDVFORK is defined that the
+		 * child's address space is actually shared with the parent as
+		 * we rely on this.
+		 */
+		if (cmdentry.cmdtype == CMDNORMAL) {
+			pid_t	pid;
+
+			savelocalvars = psh->localvars;
+			psh->localvars = NULL;
+			psh->vforked = 1;
+			switch (pid = vfork()) {
+			case -1:
+				TRACE((psh, "Vfork failed, errno=%d\n", errno));
+				INTON;
+				error(psh, "Cannot vfork");
+				break;
+			case 0:
+				/* Make sure that exceptions only unwind to
+				 * after the vfork(2)
+				 */
+				if (setjmp(jmploc.loc)) {
+					if (psh->exception == EXSHELLPROC) {
+						/* We can't progress with the vfork,
+						 * so, set vforked = 2 so the parent
+						 * knows, and _exit();
+						 */
+						psh->vforked = 2;
+						sh__exit(psh, 0);
+					} else {
+						sh__exit(psh, psh->exerrno);
+					}
+				}
+				savehandler = psh->handler;
+				psh->handler = &jmploc;
+				listmklocal(psh, varlist.list, VEXPORT | VNOFUNC);
+				forkchild(psh, jp, cmd, mode, psh->vforked);
+				break;
+			default:
+				psh->handler = savehandler;	/* restore from vfork(2) */
+				poplocalvars(psh);
+				psh->localvars = savelocalvars;
+				if (psh->vforked == 2) {
+					psh->vforked = 0;
+
+					(void)sh_waitpid(psh, pid, NULL, 0);
+					/* We need to progress in a normal fork fashion */
+					goto normal_fork;
+				}
+				psh->vforked = 0;
+				forkparent(psh, jp, cmd, mode, pid);
+				goto parent;
+			}
+		} else {
+normal_fork:
+#endif
+			if (forkshell(psh, jp, cmd, mode) != 0)
+				goto parent;	/* at end of routine */
+			FORCEINTON;
+#ifdef DO_SHAREDVFORK
+		}
+#endif
+		if (flags & EV_BACKCMD) {
+			if (!psh->vforked) {
+				FORCEINTON;
+			}
+			shfile_close(&psh->fdtab, pip[0]);
+			if (pip[1] != 1) {
+				shfile_close(&psh->fdtab, 1);
+				copyfd(psh, pip[1], 1);
+				shfile_close(&psh->fdtab, pip[1]);
+			}
+		}
+		flags |= EV_EXIT;
+	}
+
+	/* This is the child process if a fork occurred. */
+	/* Execute the command. */
+	switch (cmdentry.cmdtype) {
+	case CMDFUNCTION:
+#ifdef DEBUG
+		trputs(psh, "Shell function:  ");  trargs(psh, argv);
+#endif
+		redirect(psh, cmd->ncmd.redirect, REDIR_PUSH);
+		saveparam = psh->shellparam;
+		psh->shellparam.malloc = 0;
+		psh->shellparam.reset = 1;
+		psh->shellparam.nparam = argc - 1;
+		psh->shellparam.p = argv + 1;
+		psh->shellparam.optnext = NULL;
+		INTOFF;
+		savelocalvars = psh->localvars;
+		psh->localvars = NULL;
+		INTON;
+		if (setjmp(jmploc.loc)) {
+			if (psh->exception == EXSHELLPROC) {
+				freeparam((volatile struct shparam *)
+				    &saveparam);
+			} else {
+				freeparam(&psh->shellparam);
+				psh->shellparam = saveparam;
+			}
+			poplocalvars(psh);
+			psh->localvars = savelocalvars;
+			psh->handler = savehandler;
+			longjmp(psh->handler->loc, 1);
+		}
+		savehandler = psh->handler;
+		psh->handler = &jmploc;
+		listmklocal(psh, varlist.list, 0);
+		/* stop shell blowing its stack */
+		if (++psh->funcnest > 1000)
+			error(psh, "too many nested function calls");
+		evaltree(psh, cmdentry.u.func, flags & EV_TESTED);
+		psh->funcnest--;
+		INTOFF;
+		poplocalvars(psh);
+		psh->localvars = savelocalvars;
+		freeparam(&psh->shellparam);
+		psh->shellparam = saveparam;
+		psh->handler = savehandler;
+		popredir(psh);
+		INTON;
+		if (psh->evalskip == SKIPFUNC) {
+			psh->evalskip = 0;
+			psh->skipcount = 0;
+		}
+		if (flags & EV_EXIT)
+			exitshell(psh, psh->exitstatus);
+		break;
+
+	case CMDBUILTIN:
+	case CMDSPLBLTIN:
+#ifdef DEBUG
+		trputs(psh, "builtin command:  ");  trargs(psh, argv);
+#endif
+		mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH;
+		if (flags == EV_BACKCMD) {
+			psh->memout.nleft = 0;
+			psh->memout.nextc = psh->memout.buf;
+			psh->memout.bufsize = 64;
+			mode |= REDIR_BACKQ;
+		}
+		e = -1;
+		savehandler = psh->handler;
+		savecmdname = psh->commandname;
+		psh->handler = &jmploc;
+		if (!setjmp(jmploc.loc)) {
+			/* We need to ensure the command hash table isn't
+			 * corruped by temporary PATH assignments.
+			 * However we must ensure the 'local' command works!
+			 */
+			if (path != pathval(psh) && (cmdentry.u.bltin == hashcmd ||
+			    cmdentry.u.bltin == typecmd)) {
+				savelocalvars = psh->localvars;
+				psh->localvars = 0;
+				mklocal(psh, path - 5 /* PATH= */, 0);
+				temp_path = 1;
+			} else
+				temp_path = 0;
+			redirect(psh, cmd->ncmd.redirect, mode);
+
+			/* exec is a special builtin, but needs this list... */
+			psh->cmdenviron = varlist.list;
+			/* we must check 'readonly' flag for all builtins */
+			listsetvar(psh, varlist.list,
+				cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET);
+			psh->commandname = argv[0];
+			/* initialize nextopt */
+			psh->argptr = argv + 1;
+			psh->optptr = NULL;
+			/* and getopt */
+#if 0 /** @todo fix getop usage! */
+#if defined(__FreeBSD__) || defined(__EMX__) || defined(__APPLE__)
+			optreset = 1;
+			optind = 1;
+#else
+			optind = 0; /* init */
+#endif
+#endif
+
+			psh->exitstatus = cmdentry.u.bltin(psh, argc, argv);
+		} else {
+			e = psh->exception;
+			psh->exitstatus = e == EXINT ? SIGINT + 128 :
+					e == EXEXEC ? psh->exerrno : 2;
+		}
+		psh->handler = savehandler;
+		output_flushall(psh);
+		psh->out1 = &psh->output;
+		psh->out2 = &psh->errout;
+		freestdout(psh);
+		if (temp_path) {
+			poplocalvars(psh);
+			psh->localvars = savelocalvars;
+		}
+		psh->cmdenviron = NULL;
+		if (e != EXSHELLPROC) {
+			psh->commandname = savecmdname;
+			if (flags & EV_EXIT)
+				exitshell(psh, psh->exitstatus);
+		}
+		if (e != -1) {
+			if ((e != EXERROR && e != EXEXEC)
+			    || cmdentry.cmdtype == CMDSPLBLTIN)
+				exraise(psh, e);
+			FORCEINTON;
+		}
+		if (cmdentry.u.bltin != execcmd)
+			popredir(psh);
+		if (flags == EV_BACKCMD) {
+			backcmd->buf = psh->memout.buf;
+			backcmd->nleft = (int)(psh->memout.nextc - psh->memout.buf);
+			psh->memout.buf = NULL;
+		}
+		break;
+
+	default:
+#ifdef DEBUG
+		trputs(psh, "normal command:  ");  trargs(psh, argv);
+#endif
+		clearredir(psh, psh->vforked);
+		redirect(psh, cmd->ncmd.redirect, psh->vforked ? REDIR_VFORK : 0);
+		if (!psh->vforked)
+			for (sp = varlist.list ; sp ; sp = sp->next)
+				setvareq(psh, sp->text, VEXPORT|VSTACK);
+		envp = environment(psh);
+		shellexec(psh, argv, envp, path, cmdentry.u.index, psh->vforked);
+		break;
+	}
+	goto out;
+
+parent:	/* parent process gets here (if we forked) */
+	if (mode == FORK_FG) {	/* argument to fork */
+		psh->exitstatus = waitforjob(psh, jp);
+	} else if (mode == FORK_NOJOB) {
+		backcmd->fd = pip[0];
+		shfile_close(&psh->fdtab, pip[1]);
+		backcmd->jp = jp;
+	}
+	FORCEINTON;
+
+out:
+	if (lastarg)
+		/* dsl: I think this is intended to be used to support
+		 * '_' in 'vi' command mode during line editing...
+		 * However I implemented that within libedit itself.
+		 */
+		setvar(psh, "_", lastarg, 0);
+	popstackmark(psh, &smark);
+
+	if (eflag(psh) && psh->exitstatus && !(flags & EV_TESTED))
+		exitshell(psh, psh->exitstatus);
+}
+
+
+/*
+ * Search for a command.  This is called before we fork so that the
+ * location of the command will be available in the parent as well as
+ * the child.  The check for "goodname" is an overly conservative
+ * check that the name will not be subject to expansion.
+ */
+
+STATIC void
+prehash(shinstance *psh, union node *n)
+{
+	struct cmdentry entry;
+
+	if (n->type == NCMD && n->ncmd.args)
+		if (goodname(n->ncmd.args->narg.text))
+			find_command(psh, n->ncmd.args->narg.text, &entry, 0,
+				     pathval(psh));
+}
+
+
+
+/*
+ * Builtin commands.  Builtin commands whose functions are closely
+ * tied to evaluation are implemented here.
+ */
+
+/*
+ * No command given.
+ */
+
+int
+bltincmd(shinstance *psh, int argc, char **argv)
+{
+	/*
+	 * Preserve psh->exitstatus of a previous possible redirection
+	 * as POSIX mandates
+	 */
+	return psh->exitstatus;
+}
+
+
+/*
+ * Handle break and continue commands.  Break, continue, and return are
+ * all handled by setting the psh->evalskip flag.  The evaluation routines
+ * above all check this flag, and if it is set they start skipping
+ * commands rather than executing them.  The variable skipcount is
+ * the number of loops to break/continue, or the number of function
+ * levels to return.  (The latter is always 1.)  It should probably
+ * be an error to break out of more loops than exist, but it isn't
+ * in the standard shell so we don't make it one here.
+ */
+
+int
+breakcmd(shinstance *psh, int argc, char **argv)
+{
+	int n = argc > 1 ? number(psh, argv[1]) : 1;
+
+	if (n > psh->loopnest)
+		n = psh->loopnest;
+	if (n > 0) {
+		psh->evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
+		psh->skipcount = n;
+	}
+	return 0;
+}
+
+
+/*
+ * The return command.
+ */
+
+int
+returncmd(shinstance *psh, int argc, char **argv)
+{
+	int ret = argc > 1 ? number(psh, argv[1]) : psh->exitstatus;
+
+	if (psh->funcnest) {
+		psh->evalskip = SKIPFUNC;
+		psh->skipcount = 1;
+		return ret;
+	}
+	else {
+		/* Do what ksh does; skip the rest of the file */
+		psh->evalskip = SKIPFILE;
+		psh->skipcount = 1;
+		return ret;
+	}
+}
+
+
+int
+falsecmd(shinstance *psh, int argc, char **argv)
+{
+	return 1;
+}
+
+
+int
+truecmd(shinstance *psh, int argc, char **argv)
+{
+	return 0;
+}
+
+
+int
+execcmd(shinstance *psh, int argc, char **argv)
+{
+	if (argc > 1) {
+		struct strlist *sp;
+
+		iflag(psh) = 0;		/* exit on error */
+		mflag(psh) = 0;
+		optschanged(psh);
+		for (sp = psh->cmdenviron; sp; sp = sp->next)
+			setvareq(psh, sp->text, VEXPORT|VSTACK);
+		shellexec(psh, argv + 1, environment(psh), pathval(psh), 0, 0);
+	}
+	return 0;
+}
+
+static int
+conv_time(clock_t ticks, char *seconds, size_t l)
+{
+	static clock_t tpm = 0;
+	clock_t mins;
+	size_t i;
+
+	if (!tpm)
+		tpm = /*sysconf(_SC_CLK_TCK)*/sh_sysconf_clk_tck() * 60;
+
+	mins = ticks / tpm;
+#ifdef _MSC_VER
+	{
+		char tmp[64];
+		sprintf(tmp, "%.4f", (ticks - mins * tpm) * 60.0 / tpm);
+		strlcpy(seconds, tmp, l);
+	}
+#else
+	snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm );
+#endif
+
+	if (seconds[0] == '6' && seconds[1] == '0') {
+		/* 59.99995 got rounded up... */
+		mins++;
+		strlcpy(seconds, "0.0", l);
+		return mins;
+	}
+
+	/* suppress trailing zeros */
+	i = strlen(seconds) - 1;
+	for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--)
+		seconds[i] = 0;
+	return mins;
+}
+
+int
+timescmd(shinstance *psh, int argc, char **argv)
+{
+	shtms tms;
+	int u, s, cu, cs;
+	char us[8], ss[8], cus[8], css[8];
+
+	nextopt(psh, "");
+
+	sh_times(psh, &tms);
+
+	u = conv_time(tms.tms_utime, us, sizeof(us));
+	s = conv_time(tms.tms_stime, ss, sizeof(ss));
+	cu = conv_time(tms.tms_cutime, cus, sizeof(cus));
+	cs = conv_time(tms.tms_cstime, css, sizeof(css));
+
+	outfmt(psh->out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n",
+		u, us, s, ss, cu, cus, cs, css);
+
+	return 0;
+}
Index: /tags/kBuild-0.1.4/src/kash/eval.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/eval.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/eval.h	(revision 1780)
@@ -0,0 +1,64 @@
+/*	$NetBSD: eval.h,v 1.14 2003/08/07 09:05:31 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)eval.h	8.2 (Berkeley) 5/4/95
+ */
+
+/*extern char *commandname;*/	/* currently executing command */
+/*extern int exitstatus;*/		/* exit status of last command */
+/*extern int back_exitstatus;*/	/* exit status of backquoted command */
+/*extern struct strlist *cmdenviron;*/  /* environment for builtin command */
+
+
+struct backcmd {		/* result of evalbackcmd */
+	int fd;			/* file descriptor to read from */
+	char *buf;		/* buffer */
+	int nleft;		/* number of chars in buffer */
+	struct job *jp;		/* job structure for command */
+};
+
+void evalstring(struct shinstance *, char *, int);
+union node;	/* BLETCH for ansi C */
+void evaltree(struct shinstance *, union node *, int);
+void evalbackcmd(struct shinstance *, union node *, struct backcmd *);
+
+/* in_function returns nonzero if we are currently evaluating a function */
+#define in_function(psh)	(psh)->funcnest
+/*extern int funcnest;
+extern int evalskip;*/
+
+/* reasons for skipping commands (see comment on breakcmd routine) */
+#define SKIPBREAK	1
+#define SKIPCONT	2
+#define SKIPFUNC	3
+#define SKIPFILE	4
Index: /tags/kBuild-0.1.4/src/kash/exec.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/exec.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/exec.c	(revision 1780)
@@ -0,0 +1,1180 @@
+/*	$NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)exec.c	8.4 (Berkeley) 6/8/95";
+#else
+__RCSID("$NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $");
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * When commands are first encountered, they are entered in a hash table.
+ * This ensures that a full path search will not have to be done for them
+ * on each invocation.
+ *
+ * We should investigate converting to a linear search, even though that
+ * would make the command name "hash" a misnomer.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"
+#include "parser.h"
+#include "redir.h"
+#include "eval.h"
+#include "exec.h"
+#include "builtins.h"
+#include "var.h"
+#include "options.h"
+#include "input.h"
+#include "output.h"
+#include "syntax.h"
+#include "memalloc.h"
+#include "error.h"
+#include "init.h"
+#include "mystring.h"
+#include "show.h"
+#include "jobs.h"
+#include "alias.h"
+#ifdef __INNOTEK_LIBC__
+#include <InnoTekLIBC/backend.h>
+#endif
+#include "shinstance.h"
+
+//#define CMDTABLESIZE 31		/* should be prime */
+//#define ARB 1			/* actual size determined at run time */
+//
+//
+//
+//struct tblentry {
+//	struct tblentry *next;	/* next entry in hash chain */
+//	union param param;	/* definition of builtin function */
+//	short cmdtype;		/* index identifying command */
+//	char rehash;		/* if set, cd done since entry created */
+//	char cmdname[ARB];	/* name of command */
+//};
+//
+//
+//STATIC struct tblentry *cmdtable[CMDTABLESIZE];
+//STATIC int builtinloc = -1;		/* index in path of %builtin, or -1 */
+//int exerrno = 0;			/* Last exec error */
+
+
+STATIC void tryexec(shinstance *, char *, char **, char **, int, int);
+STATIC void execinterp(shinstance *, char **, char **);
+STATIC void printentry(shinstance *, struct tblentry *, int);
+STATIC void clearcmdentry(shinstance *, int);
+STATIC struct tblentry *cmdlookup(shinstance *, const char *, int);
+STATIC void delete_cmd_entry(shinstance *);
+#ifdef PC_EXE_EXTS
+STATIC int stat_pc_exec_exts(shinstance *, char *fullname, struct stat *st, int has_ext);
+#endif
+
+
+extern char *const parsekwd[];
+
+/*
+ * Exec a program.  Never returns.  If you change this routine, you may
+ * have to change the find_command routine as well.
+ */
+
+void
+shellexec(shinstance *psh, char **argv, char **envp, const char *path, int idx, int vforked)
+{
+	char *cmdname;
+	int e;
+#ifdef PC_EXE_EXTS
+        int has_ext = (int)strlen(argv[0]) - 4;
+        has_ext = has_ext > 0
+            && argv[0][has_ext] == '.'
+            /* use strstr and upper/lower permuated extensions to avoid multiple strcasecmp calls. */
+            && strstr("exe;" "Exe;" "EXe;" "EXE;" "ExE;" "eXe;" "eXE;" "exE;"
+                      "cmd;" "Cmd;" "CMd;" "CMD;" "CmD;" "cMd;" "cMD;" "cmD;"
+                      "com;" "Com;" "COm;" "COM;" "CoM;" "cOm;" "cOM;" "coM;"
+                      "bat;" "Bat;" "BAt;" "BAT;" "BaT;" "bAt;" "bAT;" "baT;"
+                      "btm;" "Btm;" "BTm;" "BTM;" "BtM;" "bTm;" "bTM;" "btM;",
+                      argv[0] + has_ext + 1)
+               != NULL;
+#else
+	const int has_ext = 1;
+#endif
+	TRACE((psh, "shellexec: argv[0]=%s idx=%d\n", argv[0], idx));
+	if (strchr(argv[0], '/') != NULL) {
+		cmdname = stalloc(psh, strlen(argv[0]) + 5);
+		strcpy(cmdname, argv[0]);
+		tryexec(psh, cmdname, argv, envp, vforked, has_ext);
+		TRACE((psh, "shellexec: cmdname=%s\n", cmdname));
+		stunalloc(psh, cmdname);
+		e = errno;
+	} else {
+		e = ENOENT;
+		while ((cmdname = padvance(psh, &path, argv[0])) != NULL) {
+			if (--idx < 0 && psh->pathopt == NULL) {
+				tryexec(psh, cmdname, argv, envp, vforked, has_ext);
+				if (errno != ENOENT && errno != ENOTDIR)
+					e = errno;
+			}
+			stunalloc(psh, cmdname);
+		}
+	}
+
+	/* Map to POSIX errors */
+	switch (e) {
+	case EACCES:
+		psh->exerrno = 126;
+		break;
+	case ENOENT:
+		psh->exerrno = 127;
+		break;
+	default:
+		psh->exerrno = 2;
+		break;
+	}
+	TRACE((psh, "shellexec failed for '%s', errno %d, vforked %d, suppressint %d\n",
+		argv[0], e, vforked, psh->suppressint ));
+	exerror(psh, EXEXEC, "%s: %s", argv[0], errmsg(psh, e, E_EXEC));
+	/* NOTREACHED */
+}
+
+
+STATIC void
+tryexec(shinstance *psh, char *cmd, char **argv, char **envp, int vforked, int has_ext)
+{
+	int e;
+#ifdef EXEC_HASH_BANG_SCRIPT
+	char *p;
+#endif
+#ifdef PC_EXE_EXTS
+        /* exploit the effect of stat_pc_exec_exts which adds the
+         * correct extentions to the file.
+         */
+        struct stat st;
+        if (!has_ext)
+            stat_pc_exec_exts(psh, cmd, &st, 0);
+#endif
+#if defined(__INNOTEK_LIBC__) && defined(EXEC_HASH_BANG_SCRIPT)
+	__libc_Back_gfProcessHandleHashBangScripts = 0;
+#endif
+
+#ifdef SYSV
+	do {
+		sh_execve(psh, cmd, argv, envp);
+	} while (errno == EINTR);
+#else
+	sh_execve(psh, cmd, (const char * const*)argv, (const char * const*)envp);
+#endif
+	e = errno;
+	if (e == ENOEXEC) {
+		if (vforked) {
+			/* We are currently vfork(2)ed, so raise an
+			 * exception, and evalcommand will try again
+			 * with a normal fork(2).
+			 */
+			exraise(psh, EXSHELLPROC);
+		}
+		initshellproc(psh);
+		setinputfile(psh, cmd, 0);
+		psh->commandname = psh->arg0 = savestr(argv[0]);
+#ifdef EXEC_HASH_BANG_SCRIPT
+		pgetc(psh); pungetc(psh);		/* fill up input buffer */
+		p = psh->parsenextc;
+		if (psh->parsenleft > 2 && p[0] == '#' && p[1] == '!') {
+			argv[0] = cmd;
+			execinterp(psh, argv, envp);
+		}
+#endif
+		setparam(psh, argv + 1);
+		exraise(psh, EXSHELLPROC);
+	}
+	errno = e;
+}
+
+
+#ifdef EXEC_HASH_BANG_SCRIPT
+/*
+ * Execute an interpreter introduced by "#!", for systems where this
+ * feature has not been built into the kernel.  If the interpreter is
+ * the shell, return (effectively ignoring the "#!").  If the execution
+ * of the interpreter fails, exit.
+ *
+ * This code peeks inside the input buffer in order to avoid actually
+ * reading any input.  It would benefit from a rewrite.
+ */
+
+#define NEWARGS 5
+
+STATIC void
+execinterp(shinstance *psh, char **argv, char **envp)
+{
+	int n;
+	char *inp;
+	char *outp;
+	char c;
+	char *p;
+	char **ap;
+	char *newargs[NEWARGS];
+	int i;
+	char **ap2;
+	char **new;
+
+	n = psh->parsenleft - 2;
+	inp = psh->parsenextc + 2;
+	ap = newargs;
+	for (;;) {
+		while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
+			inp++;
+		if (n < 0)
+			goto bad;
+		if ((c = *inp++) == '\n')
+			break;
+		if (ap == &newargs[NEWARGS])
+bad:		  error(psh, "Bad #! line");
+		STARTSTACKSTR(psh, outp);
+		do {
+			STPUTC(psh, c, outp);
+		} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
+		STPUTC(psh, '\0', outp);
+		n++, inp--;
+		*ap++ = grabstackstr(psh, outp);
+	}
+	if (ap == newargs + 1) {	/* if no args, maybe no exec is needed */
+		p = newargs[0];
+		for (;;) {
+			if (equal(p, "sh") || equal(p, "ash")) {
+				TRACE((psh, "hash bang self\n"));
+				return;
+			}
+			while (*p != '/') {
+				if (*p == '\0')
+					goto break2;
+				p++;
+			}
+			p++;
+		}
+break2:;
+	}
+	i = (char *)ap - (char *)newargs;		/* size in bytes */
+	if (i == 0)
+		error(psh, "Bad #! line");
+	for (ap2 = argv ; *ap2++ != NULL ; );
+	new = ckmalloc(i + ((char *)ap2 - (char *)argv));
+	ap = newargs, ap2 = new;
+	while ((i -= sizeof (char **)) >= 0)
+		*ap2++ = *ap++;
+	ap = argv;
+	while (*ap2++ = *ap++);
+	TRACE((psh, "hash bang '%s'\n", new[0]));
+	shellexec(psh, new, envp, pathval(psh), 0, 0);
+	/* NOTREACHED */
+}
+#endif
+
+
+
+/*
+ * Do a path search.  The variable path (passed by reference) should be
+ * set to the start of the path before the first call; padvance will update
+ * this value as it proceeds.  Successive calls to padvance will return
+ * the possible path expansions in sequence.  If an option (indicated by
+ * a percent sign) appears in the path entry then the global variable
+ * psh->pathopt will be set to point to it; otherwise psh->pathopt will be set to
+ * NULL.
+ */
+
+//const char *pathopt;
+
+char *
+padvance(shinstance *psh, const char **path, const char *name)
+{
+	const char *p;
+	char *q;
+	const char *start;
+	int len;
+
+	if (*path == NULL)
+		return NULL;
+	start = *path;
+#ifdef PC_PATH_SEP
+	for (p = start ; *p && *p != ';' && *p != '%' ; p++);
+#else
+	for (p = start ; *p && *p != ':' && *p != '%' ; p++);
+#endif
+	len = (int)(p - start + strlen(name) + 2);	/* "2" is for '/' and '\0' */
+#ifdef PC_EXE_EXTS
+        len += 4; /* "4" is for .exe/.com/.cmd/.bat/.btm */
+#endif
+	while (stackblocksize(psh) < len)
+		growstackblock(psh);
+	q = stackblock(psh);
+	if (p != start) {
+		memcpy(q, start, p - start);
+		q += p - start;
+		*q++ = '/';
+	}
+	strcpy(q, name);
+	psh->pathopt = NULL;
+	if (*p == '%') {
+		psh->pathopt = ++p;
+#ifdef PC_PATH_SEP
+		while (*p && *p != ';')  p++;
+#else
+		while (*p && *p != ':')  p++;
+#endif
+	}
+#ifdef PC_PATH_SEP
+	if (*p == ';')
+#else
+	if (*p == ':')
+#endif
+		*path = p + 1;
+	else
+		*path = NULL;
+	return stalloc(psh, len);
+}
+
+
+#ifdef PC_EXE_EXTS
+STATIC int stat_pc_exec_exts(shinstance *psh, char *fullname, struct stat *st, int has_ext)
+{
+    /* skip the SYSV crap */
+    if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
+        return 0;
+    if (!has_ext && errno == ENOENT)
+    {
+        char *psz = strchr(fullname, '\0');
+        memcpy(psz, ".exe", 5);
+        if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
+            return 0;
+        if (errno != ENOENT && errno != ENOTDIR)
+            return -1;
+
+        memcpy(psz, ".cmd", 5);
+        if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
+            return 0;
+        if (errno != ENOENT && errno != ENOTDIR)
+            return -1;
+
+        memcpy(psz, ".bat", 5);
+        if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
+            return 0;
+        if (errno != ENOENT && errno != ENOTDIR)
+            return -1;
+
+        memcpy(psz, ".com", 5);
+        if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
+            return 0;
+        if (errno != ENOENT && errno != ENOTDIR)
+            return -1;
+
+        memcpy(psz, ".btm", 5);
+        if (shfile_stat(&psh->fdtab, fullname, st) >= 0)
+            return 0;
+        *psz = '\0';
+    }
+    return -1;
+}
+#endif /* PC_EXE_EXTS */
+
+
+
+/*** Command hashing code ***/
+
+
+int
+hashcmd(shinstance *psh, int argc, char **argv)
+{
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+	int c;
+	int verbose;
+	struct cmdentry entry;
+	char *name;
+
+	verbose = 0;
+	while ((c = nextopt(psh, "rv")) != '\0') {
+		if (c == 'r') {
+			clearcmdentry(psh, 0);
+		} else if (c == 'v') {
+			verbose++;
+		}
+	}
+	if (*psh->argptr == NULL) {
+		for (pp = psh->cmdtable ; pp < &psh->cmdtable[CMDTABLESIZE] ; pp++) {
+			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+				if (verbose || cmdp->cmdtype == CMDNORMAL)
+					printentry(psh, cmdp, verbose);
+			}
+		}
+		return 0;
+	}
+	while ((name = *psh->argptr) != NULL) {
+		if ((cmdp = cmdlookup(psh, name, 0)) != NULL
+		 && (cmdp->cmdtype == CMDNORMAL
+		     || (cmdp->cmdtype == CMDBUILTIN && psh->builtinloc >= 0)))
+			delete_cmd_entry(psh);
+		find_command(psh, name, &entry, DO_ERR, pathval(psh));
+		if (verbose) {
+			if (entry.cmdtype != CMDUNKNOWN) {	/* if no error msg */
+				cmdp = cmdlookup(psh, name, 0);
+				printentry(psh, cmdp, verbose);
+			}
+			output_flushall(psh);
+		}
+		psh->argptr++;
+	}
+	return 0;
+}
+
+
+STATIC void
+printentry(shinstance *psh, struct tblentry *cmdp, int verbose)
+{
+	int idx;
+	const char *path;
+	char *name;
+
+	switch (cmdp->cmdtype) {
+	case CMDNORMAL:
+		idx = cmdp->param.index;
+		path = pathval(psh);
+		do {
+			name = padvance(psh, &path, cmdp->cmdname);
+			stunalloc(psh, name);
+		} while (--idx >= 0);
+		out1str(psh, name);
+		break;
+	case CMDSPLBLTIN:
+		out1fmt(psh, "special builtin %s", cmdp->cmdname);
+		break;
+	case CMDBUILTIN:
+		out1fmt(psh, "builtin %s", cmdp->cmdname);
+		break;
+	case CMDFUNCTION:
+		out1fmt(psh, "function %s", cmdp->cmdname);
+		if (verbose) {
+			struct procstat ps;
+			INTOFF;
+			commandtext(psh, &ps, cmdp->param.func);
+			INTON;
+			out1str(psh, "() { ");
+			out1str(psh, ps.cmd);
+			out1str(psh, "; }");
+		}
+		break;
+	default:
+		error(psh, "internal error: %s cmdtype %d", cmdp->cmdname, cmdp->cmdtype);
+	}
+	if (cmdp->rehash)
+		out1c(psh, '*');
+	out1c(psh, '\n');
+}
+
+
+
+/*
+ * Resolve a command name.  If you change this routine, you may have to
+ * change the shellexec routine as well.
+ */
+
+void
+find_command(shinstance *psh, char *name, struct cmdentry *entry, int act, const char *path)
+{
+	struct tblentry *cmdp, loc_cmd;
+	int idx;
+	int prev;
+	char *fullname;
+	struct stat statb;
+	int e;
+	int (*bltin)(shinstance*,int,char **);
+
+#ifdef PC_EXE_EXTS
+        int has_ext = (int)(strlen(name) - 4);
+        has_ext = has_ext > 0
+            && name[has_ext] == '.'
+            /* use strstr and upper/lower permuated extensions to avoid multiple strcasecmp calls. */
+            && strstr("exe;" "Exe;" "EXe;" "EXE;" "ExE;" "eXe;" "eXE;" "exE;"
+                      "cmd;" "Cmd;" "CMd;" "CMD;" "CmD;" "cMd;" "cMD;" "cmD;"
+                      "com;" "Com;" "COm;" "COM;" "CoM;" "cOm;" "cOM;" "coM;"
+                      "bat;" "Bat;" "BAt;" "BAT;" "BaT;" "bAt;" "bAT;" "baT;"
+                      "btm;" "Btm;" "BTm;" "BTM;" "BtM;" "bTm;" "bTM;" "btM;",
+                      name + has_ext + 1)
+               != NULL;
+#endif
+
+	/* If name contains a slash, don't use PATH or hash table */
+	if (strchr(name, '/') != NULL) {
+		if (act & DO_ABS) {
+			while (shfile_stat(&psh->fdtab, name, &statb) < 0) {
+#ifdef SYSV
+				if (errno == EINTR)
+					continue;
+#endif
+				if (errno != ENOENT && errno != ENOTDIR)
+					e = errno;
+				entry->cmdtype = CMDUNKNOWN;
+				entry->u.index = -1;
+				return;
+			}
+			entry->cmdtype = CMDNORMAL;
+			entry->u.index = -1;
+			return;
+		}
+		entry->cmdtype = CMDNORMAL;
+		entry->u.index = 0;
+		return;
+	}
+
+	if (path != pathval(psh))
+		act |= DO_ALTPATH;
+
+	if (act & DO_ALTPATH && strstr(path, "%builtin") != NULL)
+		act |= DO_ALTBLTIN;
+
+	/* If name is in the table, check answer will be ok */
+	if ((cmdp = cmdlookup(psh, name, 0)) != NULL) {
+		do {
+			switch (cmdp->cmdtype) {
+			case CMDNORMAL:
+				if (act & DO_ALTPATH) {
+					cmdp = NULL;
+					continue;
+				}
+				break;
+			case CMDFUNCTION:
+				if (act & DO_NOFUNC) {
+					cmdp = NULL;
+					continue;
+				}
+				break;
+			case CMDBUILTIN:
+				if ((act & DO_ALTBLTIN) || psh->builtinloc >= 0) {
+					cmdp = NULL;
+					continue;
+				}
+				break;
+			}
+			/* if not invalidated by cd, we're done */
+			if (cmdp->rehash == 0)
+				goto success;
+		} while (0);
+	}
+
+	/* If %builtin not in path, check for builtin next */
+	if ((act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : psh->builtinloc < 0) &&
+	    (bltin = find_builtin(psh, name)) != 0)
+		goto builtin_success;
+
+	/* We have to search path. */
+	prev = -1;		/* where to start */
+	if (cmdp) {		/* doing a rehash */
+		if (cmdp->cmdtype == CMDBUILTIN)
+			prev = psh->builtinloc;
+		else
+			prev = cmdp->param.index;
+	}
+
+	e = ENOENT;
+	idx = -1;
+loop:
+	while ((fullname = padvance(psh, &path, name)) != NULL) {
+		stunalloc(psh, fullname);
+		idx++;
+		if (psh->pathopt) {
+			if (prefix("builtin", psh->pathopt)) {
+				if ((bltin = find_builtin(psh, name)) == 0)
+					goto loop;
+				goto builtin_success;
+			} else if (prefix("func", psh->pathopt)) {
+				/* handled below */
+			} else {
+				/* ignore unimplemented options */
+				goto loop;
+			}
+		}
+		/* if rehash, don't redo absolute path names */
+		if (fullname[0] == '/' && idx <= prev) {
+			if (idx < prev)
+				goto loop;
+			TRACE((psh, "searchexec \"%s\": no change\n", name));
+			goto success;
+		}
+#ifdef PC_EXE_EXTS
+		while (stat_pc_exec_exts(psh, fullname, &statb, has_ext) < 0) {
+#else
+		while (shfile_stat(&psh->fdtab, fullname, &statb) < 0) {
+#endif
+#ifdef SYSV
+			if (errno == EINTR)
+				continue;
+#endif
+			if (errno != ENOENT && errno != ENOTDIR)
+				e = errno;
+
+			goto loop;
+		}
+		e = EACCES;	/* if we fail, this will be the error */
+		if (!S_ISREG(statb.st_mode))
+			goto loop;
+		if (psh->pathopt) {		/* this is a %func directory */
+			if (act & DO_NOFUNC)
+				goto loop;
+			stalloc(psh, strlen(fullname) + 1);
+			readcmdfile(psh, fullname);
+			if ((cmdp = cmdlookup(psh, name, 0)) == NULL ||
+			    cmdp->cmdtype != CMDFUNCTION)
+				error(psh, "%s not defined in %s", name, fullname);
+			stunalloc(psh, fullname);
+			goto success;
+		}
+#ifdef notdef
+		/* XXX this code stops root executing stuff, and is buggy
+		   if you need a group from the group list. */
+		if (statb.st_uid == sh_geteuid(psh)) {
+			if ((statb.st_mode & 0100) == 0)
+				goto loop;
+		} else if (statb.st_gid == sh_getegid(psh)) {
+			if ((statb.st_mode & 010) == 0)
+				goto loop;
+		} else {
+			if ((statb.st_mode & 01) == 0)
+				goto loop;
+		}
+#endif
+		TRACE((psh, "searchexec \"%s\" returns \"%s\"\n", name, fullname));
+		INTOFF;
+		if (act & DO_ALTPATH) {
+			stalloc(psh, strlen(fullname) + 1);
+			cmdp = &loc_cmd;
+		} else
+			cmdp = cmdlookup(psh, name, 1);
+		cmdp->cmdtype = CMDNORMAL;
+		cmdp->param.index = idx;
+		INTON;
+		goto success;
+	}
+
+	/* We failed.  If there was an entry for this command, delete it */
+	if (cmdp)
+		delete_cmd_entry(psh);
+	if (act & DO_ERR)
+		outfmt(psh->out2, "%s: %s\n", name, errmsg(psh, e, E_EXEC));
+	entry->cmdtype = CMDUNKNOWN;
+	return;
+
+builtin_success:
+	INTOFF;
+	if (act & DO_ALTPATH)
+		cmdp = &loc_cmd;
+	else
+		cmdp = cmdlookup(psh, name, 1);
+	if (cmdp->cmdtype == CMDFUNCTION)
+		/* DO_NOFUNC must have been set */
+		cmdp = &loc_cmd;
+	cmdp->cmdtype = CMDBUILTIN;
+	cmdp->param.bltin = bltin;
+	INTON;
+success:
+	cmdp->rehash = 0;
+	entry->cmdtype = cmdp->cmdtype;
+	entry->u = cmdp->param;
+}
+
+
+
+/*
+ * Search the table of builtin commands.
+ */
+
+int
+(*find_builtin(shinstance *psh, char *name))(shinstance *psh, int, char **)
+{
+	const struct builtincmd *bp;
+
+	for (bp = builtincmd ; bp->name ; bp++) {
+		if (*bp->name == *name && equal(bp->name, name))
+			return bp->builtin;
+	}
+	return 0;
+}
+
+int
+(*find_splbltin(shinstance *psh, char *name))(shinstance *psh, int, char **)
+{
+	const struct builtincmd *bp;
+
+	for (bp = splbltincmd ; bp->name ; bp++) {
+		if (*bp->name == *name && equal(bp->name, name))
+			return bp->builtin;
+	}
+	return 0;
+}
+
+/*
+ * At shell startup put special builtins into hash table.
+ * ensures they are executed first (see posix).
+ * We stop functions being added with the same name
+ * (as they are impossible to call)
+ */
+
+void
+hash_special_builtins(shinstance *psh)
+{
+	const struct builtincmd *bp;
+	struct tblentry *cmdp;
+
+	for (bp = splbltincmd ; bp->name ; bp++) {
+		cmdp = cmdlookup(psh, bp->name, 1);
+		cmdp->cmdtype = CMDSPLBLTIN;
+		cmdp->param.bltin = bp->builtin;
+	}
+}
+
+
+
+/*
+ * Called when a cd is done.  Marks all commands so the next time they
+ * are executed they will be rehashed.
+ */
+
+void
+hashcd(shinstance *psh)
+{
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	for (pp = psh->cmdtable ; pp < &psh->cmdtable[CMDTABLESIZE] ; pp++) {
+		for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+			if (cmdp->cmdtype == CMDNORMAL
+			 || (cmdp->cmdtype == CMDBUILTIN && psh->builtinloc >= 0))
+				cmdp->rehash = 1;
+		}
+	}
+}
+
+
+
+/*
+ * Fix command hash table when PATH changed.
+ * Called before PATH is changed.  The argument is the new value of PATH;
+ * pathval(psh) still returns the old value at this point.
+ * Called with interrupts off.
+ */
+
+void
+changepath(shinstance *psh, const char *newval)
+{
+	const char *old, *new;
+	int idx;
+	int firstchange;
+	int bltin;
+
+	old = pathval(psh);
+	new = newval;
+	firstchange = 9999;	/* assume no change */
+	idx = 0;
+	bltin = -1;
+	for (;;) {
+		if (*old != *new) {
+			firstchange = idx;
+#ifdef PC_PATH_SEP
+			if ((*old == '\0' && *new == ';')
+			 || (*old == ';' && *new == '\0'))
+#else
+			if ((*old == '\0' && *new == ':')
+			 || (*old == ':' && *new == '\0'))
+#endif
+				firstchange++;
+			old = new;	/* ignore subsequent differences */
+		}
+		if (*new == '\0')
+			break;
+		if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
+			bltin = idx;
+#ifdef PC_PATH_SEP
+		if (*new == ';') {
+#else
+		if (*new == ':') {
+#endif
+			idx++;
+		}
+		new++, old++;
+	}
+	if (psh->builtinloc < 0 && bltin >= 0)
+		psh->builtinloc = bltin;		/* zap builtins */
+	if (psh->builtinloc >= 0 && bltin < 0)
+		firstchange = 0;
+	clearcmdentry(psh, firstchange);
+	psh->builtinloc = bltin;
+}
+
+
+/*
+ * Clear out command entries.  The argument specifies the first entry in
+ * PATH which has changed.
+ */
+
+STATIC void
+clearcmdentry(shinstance *psh, int firstchange)
+{
+	struct tblentry **tblp;
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	INTOFF;
+	for (tblp = psh->cmdtable ; tblp < &psh->cmdtable[CMDTABLESIZE] ; tblp++) {
+		pp = tblp;
+		while ((cmdp = *pp) != NULL) {
+			if ((cmdp->cmdtype == CMDNORMAL &&
+			     cmdp->param.index >= firstchange)
+			 || (cmdp->cmdtype == CMDBUILTIN &&
+			     psh->builtinloc >= firstchange)) {
+				*pp = cmdp->next;
+				ckfree(cmdp);
+			} else {
+				pp = &cmdp->next;
+			}
+		}
+	}
+	INTON;
+}
+
+
+/*
+ * Delete all functions.
+ */
+
+#ifdef mkinit
+MKINIT void deletefuncs(struct shinstance *);
+MKINIT void hash_special_builtins(struct shinstance *);
+
+INIT {
+	hash_special_builtins(psh);
+}
+
+SHELLPROC {
+	deletefuncs(psh);
+}
+#endif
+
+void
+deletefuncs(shinstance *psh)
+{
+	struct tblentry **tblp;
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	INTOFF;
+	for (tblp = psh->cmdtable ; tblp < &psh->cmdtable[CMDTABLESIZE] ; tblp++) {
+		pp = tblp;
+		while ((cmdp = *pp) != NULL) {
+			if (cmdp->cmdtype == CMDFUNCTION) {
+				*pp = cmdp->next;
+				freefunc(cmdp->param.func);
+				ckfree(cmdp);
+			} else {
+				pp = &cmdp->next;
+			}
+		}
+	}
+	INTON;
+}
+
+
+
+/*
+ * Locate a command in the command hash table.  If "add" is nonzero,
+ * add the command to the table if it is not already present.  The
+ * variable "lastcmdentry" is set to point to the address of the link
+ * pointing to the entry, so that delete_cmd_entry can delete the
+ * entry.
+ */
+
+struct tblentry **lastcmdentry;
+
+
+STATIC struct tblentry *
+cmdlookup(shinstance *psh, const char *name, int add)
+{
+	int hashval;
+	const char *p;
+	struct tblentry *cmdp;
+	struct tblentry **pp;
+
+	p = name;
+	hashval = *p << 4;
+	while (*p)
+		hashval += *p++;
+	hashval &= 0x7FFF;
+	pp = &psh->cmdtable[hashval % CMDTABLESIZE];
+	for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+		if (equal(cmdp->cmdname, name))
+			break;
+		pp = &cmdp->next;
+	}
+	if (add && cmdp == NULL) {
+		INTOFF;
+		cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
+					+ strlen(name) + 1);
+		cmdp->next = NULL;
+		cmdp->cmdtype = CMDUNKNOWN;
+		cmdp->rehash = 0;
+		strcpy(cmdp->cmdname, name);
+		INTON;
+	}
+	lastcmdentry = pp;
+	return cmdp;
+}
+
+/*
+ * Delete the command entry returned on the last lookup.
+ */
+
+STATIC void
+delete_cmd_entry(shinstance *psh)
+{
+	struct tblentry *cmdp;
+
+	INTOFF;
+	cmdp = *lastcmdentry;
+	*lastcmdentry = cmdp->next;
+	ckfree(cmdp);
+	INTON;
+}
+
+
+
+#ifdef notdef
+void
+getcmdentry(shinstance *psh, char *name, struct cmdentry *entry)
+{
+	struct tblentry *cmdp = cmdlookup(psh, name, 0);
+
+	if (cmdp) {
+		entry->u = cmdp->param;
+		entry->cmdtype = cmdp->cmdtype;
+	} else {
+		entry->cmdtype = CMDUNKNOWN;
+		entry->u.index = 0;
+	}
+}
+#endif
+
+
+/*
+ * Add a new command entry, replacing any existing command entry for
+ * the same name - except special builtins.
+ */
+
+STATIC void
+addcmdentry(shinstance *psh, char *name, struct cmdentry *entry)
+{
+	struct tblentry *cmdp;
+
+	INTOFF;
+	cmdp = cmdlookup(psh, name, 1);
+	if (cmdp->cmdtype != CMDSPLBLTIN) {
+		if (cmdp->cmdtype == CMDFUNCTION) {
+			freefunc(cmdp->param.func);
+		}
+		cmdp->cmdtype = entry->cmdtype;
+		cmdp->param = entry->u;
+	}
+	INTON;
+}
+
+
+/*
+ * Define a shell function.
+ */
+
+void
+defun(shinstance *psh,char *name, union node *func)
+{
+	struct cmdentry entry;
+
+	INTOFF;
+	entry.cmdtype = CMDFUNCTION;
+	entry.u.func = copyfunc(func);
+	addcmdentry(psh, name, &entry);
+	INTON;
+}
+
+
+/*
+ * Delete a function if it exists.
+ */
+
+int
+unsetfunc(shinstance *psh, char *name)
+{
+	struct tblentry *cmdp;
+
+	if ((cmdp = cmdlookup(psh, name, 0)) != NULL &&
+	    cmdp->cmdtype == CMDFUNCTION) {
+		freefunc(cmdp->param.func);
+		delete_cmd_entry(psh);
+		return (0);
+	}
+	return (1);
+}
+
+/*
+ * Locate and print what a word is...
+ * also used for 'command -[v|V]'
+ */
+
+int
+typecmd(shinstance *psh, int argc, char **argv)
+{
+	struct cmdentry entry;
+	struct tblentry *cmdp;
+	char * const *pp;
+	struct alias *ap;
+	int err = 0;
+	char *arg;
+	int c;
+	int V_flag = 0;
+	int v_flag = 0;
+	int p_flag = 0;
+
+	while ((c = nextopt(psh, "vVp")) != 0) {
+		switch (c) {
+		case 'v': v_flag = 1; break;
+		case 'V': V_flag = 1; break;
+		case 'p': p_flag = 1; break;
+		}
+	}
+
+	if (p_flag && (v_flag || V_flag))
+		error(psh, "cannot specify -p with -v or -V");
+
+	while ((arg = *psh->argptr++)) {
+		if (!v_flag)
+			out1str(psh, arg);
+		/* First look at the keywords */
+		for (pp = parsekwd; *pp; pp++)
+			if (**pp == *arg && equal(*pp, arg))
+				break;
+
+		if (*pp) {
+			if (v_flag)
+				err = 1;
+			else
+				out1str(psh, " is a shell keyword\n");
+			continue;
+		}
+
+		/* Then look at the aliases */
+		if ((ap = lookupalias(psh, arg, 1)) != NULL) {
+			if (!v_flag)
+				out1fmt(psh, " is an alias for \n");
+			out1fmt(psh, "%s\n", ap->val);
+			continue;
+		}
+
+		/* Then check if it is a tracked alias */
+		if ((cmdp = cmdlookup(psh, arg, 0)) != NULL) {
+			entry.cmdtype = cmdp->cmdtype;
+			entry.u = cmdp->param;
+		} else {
+			/* Finally use brute force */
+			find_command(psh, arg, &entry, DO_ABS, pathval(psh));
+		}
+
+		switch (entry.cmdtype) {
+		case CMDNORMAL: {
+			if (strchr(arg, '/') == NULL) {
+				const char *path = pathval(psh);
+				char *name;
+				int j = entry.u.index;
+				do {
+					name = padvance(psh, &path, arg);
+					stunalloc(psh, name);
+				} while (--j >= 0);
+				if (!v_flag)
+					out1fmt(psh, " is%s ",
+					    cmdp ? " a tracked alias for" : "");
+				out1fmt(psh, "%s\n", name);
+			} else {
+				if (shfile_access(&psh->fdtab, arg, X_OK) == 0) {
+					if (!v_flag)
+						out1fmt(psh, " is ");
+					out1fmt(psh, "%s\n", arg);
+				} else {
+					if (!v_flag)
+						out1fmt(psh, ": %s\n",
+						    strerror(errno));
+					else
+						err = 126;
+				}
+			}
+ 			break;
+		}
+		case CMDFUNCTION:
+			if (!v_flag)
+				out1str(psh, " is a shell function\n");
+			else
+				out1fmt(psh, "%s\n", arg);
+			break;
+
+		case CMDBUILTIN:
+			if (!v_flag)
+				out1str(psh, " is a shell builtin\n");
+			else
+				out1fmt(psh, "%s\n", arg);
+			break;
+
+		case CMDSPLBLTIN:
+			if (!v_flag)
+				out1str(psh, " is a special shell builtin\n");
+			else
+				out1fmt(psh, "%s\n", arg);
+			break;
+
+		default:
+			if (!v_flag)
+				out1str(psh, ": not found\n");
+			err = 127;
+			break;
+		}
+	}
+	return err;
+}
Index: /tags/kBuild-0.1.4/src/kash/exec.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/exec.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/exec.h	(revision 1780)
@@ -0,0 +1,88 @@
+/*	$NetBSD: exec.h,v 1.21 2003/08/07 09:05:31 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)exec.h	8.3 (Berkeley) 6/8/95
+ */
+
+#ifndef ___exec_h
+#define ___exec_h
+
+/* values of cmdtype */
+#define CMDUNKNOWN	-1	/* no entry in table for command */
+#define CMDNORMAL	0	/* command is an executable program */
+#define CMDFUNCTION	1	/* command is a shell function */
+#define CMDBUILTIN	2	/* command is a shell builtin */
+#define CMDSPLBLTIN	3	/* command is a special shell builtin */
+
+
+struct cmdentry {
+	int cmdtype;
+	union param {
+		int index;
+		int (*bltin)(struct shinstance*, int, char**);
+		union node *func;
+	} u;
+};
+
+
+/* action to find_command() */
+#define DO_ERR		0x01	/* prints errors */
+#define DO_ABS		0x02	/* checks absolute paths */
+#define DO_NOFUNC	0x04	/* don't return shell functions, for command */
+#define DO_ALTPATH	0x08	/* using alternate path */
+#define DO_ALTBLTIN	0x20	/* %builtin in alt. path */
+
+/*extern const char *pathopt;*/	/* set by padvance */
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+# define __attribute__(a)
+#endif
+
+void shellexec(struct shinstance *, char **, char **, const char *, int, int)
+    __attribute__((__noreturn__));
+char *padvance(struct shinstance *, const char **, const char *);
+int hashcmd(struct shinstance *, int, char **);
+void find_command(struct shinstance *, char *, struct cmdentry *, int, const char *);
+int (*find_builtin(struct shinstance *, char *))(struct shinstance *, int, char **);
+int (*find_splbltin(struct shinstance *, char *))(struct shinstance *, int, char **);
+void hashcd(struct shinstance *);
+void changepath(struct shinstance *, const char *);
+void deletefuncs(struct shinstance *);
+void getcmdentry(struct shinstance *, char *, struct cmdentry *);
+void addcmdentry(struct shinstance *, char *, struct cmdentry *);
+void defun(struct shinstance *, char *, union node *);
+int unsetfunc(struct shinstance *, char *);
+int typecmd(struct shinstance *, int, char **);
+void hash_special_builtins(struct shinstance *);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/expand.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/expand.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/expand.c	(revision 1780)
@@ -0,0 +1,1557 @@
+/*	$NetBSD: expand.c,v 1.71 2005/06/01 15:41:19 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)expand.c	8.5 (Berkeley) 5/15/95";
+#else
+__RCSID("$NetBSD: expand.c,v 1.71 2005/06/01 15:41:19 lukem Exp $");
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * Routines to expand arguments to commands.  We have to deal with
+ * backquotes, shell variables, and file metacharacters.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"
+#include "eval.h"
+#include "expand.h"
+#include "syntax.h"
+#include "parser.h"
+#include "jobs.h"
+#include "options.h"
+#include "var.h"
+#include "input.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "show.h"
+#include "shinstance.h"
+
+///*
+// * Structure specifying which parts of the string should be searched
+// * for IFS characters.
+// */
+//
+//struct ifsregion {
+//	struct ifsregion *next;	/* next region in list */
+//	int begoff;		/* offset of start of region */
+//	int endoff;		/* offset of end of region */
+//	int inquotes;		/* search for nul bytes only */
+//};
+//
+//
+//char *expdest;			/* output of current string */
+//struct nodelist *argbackq;	/* list of back quote expressions */
+//struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
+//struct ifsregion *ifslastp;	/* last struct in list */
+//struct arglist exparg;		/* holds expanded arg list */
+
+STATIC void argstr(shinstance *, char *, int);
+STATIC char *exptilde(shinstance *, char *, int);
+STATIC void expbackq(shinstance *, union node *, int, int);
+STATIC int subevalvar(shinstance *, char *, char *, int, int, int, int);
+STATIC char *evalvar(shinstance *, char *, int);
+STATIC int varisset(shinstance *, char *, int);
+STATIC void varvalue(shinstance *, char *, int, int, int);
+STATIC void recordregion(shinstance *, int, int, int);
+STATIC void removerecordregions(shinstance *, int);
+STATIC void ifsbreakup(shinstance *, char *, struct arglist *);
+STATIC void ifsfree(shinstance *);
+STATIC void expandmeta(shinstance *, struct strlist *, int);
+STATIC void expmeta(shinstance *, char *, char *);
+STATIC void addfname(shinstance *, char *);
+STATIC struct strlist *expsort(struct strlist *);
+STATIC struct strlist *msort(struct strlist *, int);
+STATIC int pmatch(char *, char *, int);
+STATIC char *cvtnum(shinstance *, int, char *);
+
+/*
+ * Expand shell variables and backquotes inside a here document.
+ */
+
+void
+expandhere(shinstance *psh, union node *arg, int fd)
+{
+	psh->herefd = fd;
+	expandarg(psh, arg, (struct arglist *)NULL, 0);
+	xwrite(psh, fd, stackblock(psh), psh->expdest - stackblock(psh));
+}
+
+
+/*
+ * Perform variable substitution and command substitution on an argument,
+ * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
+ * perform splitting and file name expansion.  When arglist is NULL, perform
+ * here document expansion.
+ */
+
+void
+expandarg(shinstance *psh, union node *arg, struct arglist *arglist, int flag)
+{
+	struct strlist *sp;
+	char *p;
+
+	psh->argbackq = arg->narg.backquote;
+	STARTSTACKSTR(psh, psh->expdest);
+	psh->ifsfirst.next = NULL;
+	psh->ifslastp = NULL;
+	argstr(psh, arg->narg.text, flag);
+	if (arglist == NULL) {
+		return;			/* here document expanded */
+	}
+	STPUTC(psh, '\0', psh->expdest);
+	p = grabstackstr(psh, psh->expdest);
+	psh->exparg.lastp = &psh->exparg.list;
+	/*
+	 * TODO - EXP_REDIR
+	 */
+	if (flag & EXP_FULL) {
+		ifsbreakup(psh, p, &psh->exparg);
+		*psh->exparg.lastp = NULL;
+		psh->exparg.lastp = &psh->exparg.list;
+		expandmeta(psh, psh->exparg.list, flag);
+	} else {
+		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
+			rmescapes(psh, p);
+		sp = (struct strlist *)stalloc(psh, sizeof (struct strlist));
+		sp->text = p;
+		*psh->exparg.lastp = sp;
+		psh->exparg.lastp = &sp->next;
+	}
+	ifsfree(psh);
+	*psh->exparg.lastp = NULL;
+	if (psh->exparg.list) {
+		*arglist->lastp = psh->exparg.list;
+		arglist->lastp = psh->exparg.lastp;
+	}
+}
+
+
+
+/*
+ * Perform variable and command substitution.
+ * If EXP_FULL is set, output CTLESC characters to allow for further processing.
+ * Otherwise treat $@ like $* since no splitting will be performed.
+ */
+
+STATIC void
+argstr(shinstance *psh, char *p, int flag)
+{
+	char c;
+	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
+	int firsteq = 1;
+	const char *ifs = NULL;
+	int ifs_split = EXP_IFS_SPLIT;
+
+	if (flag & EXP_IFS_SPLIT)
+		ifs = ifsset(psh) ? ifsval(psh) : " \t\n";
+
+	if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
+		p = exptilde(psh, p, flag);
+	for (;;) {
+		switch (c = *p++) {
+		case '\0':
+		case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */
+			return;
+		case CTLQUOTEMARK:
+			/* "$@" syntax adherence hack */
+			if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
+				break;
+			if ((flag & EXP_FULL) != 0)
+				STPUTC(psh, c, psh->expdest);
+			ifs_split = 0;
+			break;
+		case CTLQUOTEEND:
+			ifs_split = EXP_IFS_SPLIT;
+			break;
+		case CTLESC:
+			if (quotes)
+				STPUTC(psh, c, psh->expdest);
+			c = *p++;
+			STPUTC(psh, c, psh->expdest);
+			break;
+		case CTLVAR:
+			p = evalvar(psh, p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split));
+			break;
+		case CTLBACKQ:
+		case CTLBACKQ|CTLQUOTE:
+			expbackq(psh, psh->argbackq->n, c & CTLQUOTE, flag);
+			psh->argbackq = psh->argbackq->next;
+			break;
+		case CTLENDARI:
+			expari(psh, flag);
+			break;
+		case ':':
+		case '=':
+			/*
+			 * sort of a hack - expand tildes in variable
+			 * assignments (after the first '=' and after ':'s).
+			 */
+			STPUTC(psh, c, psh->expdest);
+			if (flag & EXP_VARTILDE && *p == '~') {
+				if (c == '=') {
+					if (firsteq)
+						firsteq = 0;
+					else
+						break;
+				}
+				p = exptilde(psh, p, flag);
+			}
+			break;
+		default:
+			STPUTC(psh, c, psh->expdest);
+			if (flag & EXP_IFS_SPLIT & ifs_split && strchr(ifs, c) != NULL) {
+				/* We need to get the output split here... */
+				recordregion(psh, (int)(psh->expdest - stackblock(psh) - 1),
+						(int)(psh->expdest - stackblock(psh)), 0);
+			}
+			break;
+		}
+	}
+}
+
+STATIC char *
+exptilde(shinstance *psh, char *p, int flag)
+{
+	char c, *startp = p;
+	const char *home;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+
+	while ((c = *p) != '\0') {
+		switch(c) {
+		case CTLESC:
+			return (startp);
+		case CTLQUOTEMARK:
+			return (startp);
+		case ':':
+			if (flag & EXP_VARTILDE)
+				goto done;
+			break;
+		case '/':
+			goto done;
+		}
+		p++;
+	}
+done:
+	*p = '\0';
+	if (*(startp+1) == '\0') {
+		if ((home = lookupvar(psh, "HOME")) == NULL)
+			goto lose;
+	} else {
+		if ((home = sh_gethomedir(psh, startp+1)) == NULL)
+			goto lose;
+	}
+	if (*home == '\0')
+		goto lose;
+	*p = c;
+	while ((c = *home++) != '\0') {
+		if (quotes && SQSYNTAX[(int)c] == CCTL)
+			STPUTC(psh, CTLESC, psh->expdest);
+		STPUTC(psh, c, psh->expdest);
+	}
+	return (p);
+lose:
+	*p = c;
+	return (startp);
+}
+
+
+STATIC void
+removerecordregions(shinstance *psh, int endoff)
+{
+	if (psh->ifslastp == NULL)
+		return;
+
+	if (psh->ifsfirst.endoff > endoff) {
+		while (psh->ifsfirst.next != NULL) {
+			struct ifsregion *ifsp;
+			INTOFF;
+			ifsp = psh->ifsfirst.next->next;
+			ckfree(psh->ifsfirst.next);
+			psh->ifsfirst.next = ifsp;
+			INTON;
+		}
+		if (psh->ifsfirst.begoff > endoff)
+			psh->ifslastp = NULL;
+		else {
+			psh->ifslastp = &psh->ifsfirst;
+			psh->ifsfirst.endoff = endoff;
+		}
+		return;
+	}
+
+	psh->ifslastp = &psh->ifsfirst;
+	while (psh->ifslastp->next && psh->ifslastp->next->begoff < endoff)
+		psh->ifslastp=psh->ifslastp->next;
+	while (psh->ifslastp->next != NULL) {
+		struct ifsregion *ifsp;
+		INTOFF;
+		ifsp = psh->ifslastp->next->next;
+		ckfree(psh->ifslastp->next);
+		psh->ifslastp->next = ifsp;
+		INTON;
+	}
+	if (psh->ifslastp->endoff > endoff)
+		psh->ifslastp->endoff = endoff;
+}
+
+
+/*
+ * Expand arithmetic expression.  Backup to start of expression,
+ * evaluate, place result in (backed up) result, adjust string position.
+ */
+void
+expari(shinstance *psh, int flag)
+{
+	char *p, *start;
+	int result;
+	int begoff;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+	int quoted;
+
+	/*	ifsfree(); */
+
+	/*
+	 * This routine is slightly over-complicated for
+	 * efficiency.  First we make sure there is
+	 * enough space for the result, which may be bigger
+	 * than the expression if we add exponentation.  Next we
+	 * scan backwards looking for the start of arithmetic.  If the
+	 * next previous character is a CTLESC character, then we
+	 * have to rescan starting from the beginning since CTLESC
+	 * characters have to be processed left to right.
+	 */
+#if INT_MAX / 1000000000 >= 10 || INT_MIN / 1000000000 <= -10
+#error "integers with more than 10 digits are not supported"
+#endif
+	CHECKSTRSPACE(psh, 12 - 2, psh->expdest);
+	USTPUTC(psh, '\0', psh->expdest);
+	start = stackblock(psh);
+	p = psh->expdest - 1;
+	while (*p != CTLARI && p >= start)
+		--p;
+	if (*p != CTLARI)
+		error(psh, "missing CTLARI (shouldn't happen)");
+	if (p > start && *(p-1) == CTLESC)
+		for (p = start; *p != CTLARI; p++)
+			if (*p == CTLESC)
+				p++;
+
+	if (p[1] == '"')
+		quoted=1;
+	else
+		quoted=0;
+	begoff = (int)(p - start);
+	removerecordregions(psh, begoff);
+	if (quotes)
+		rmescapes(psh, p+2);
+	result = arith(psh, p+2);
+	fmtstr(p, 12, "%d", result);
+
+	while (*p++)
+		;
+
+	if (quoted == 0)
+		recordregion(psh, begoff, (int)(p - 1 - start), 0);
+	result = (int)(psh->expdest - p + 1);
+	STADJUST(psh, -result, psh->expdest);
+}
+
+
+/*
+ * Expand stuff in backwards quotes.
+ */
+
+STATIC void
+expbackq(shinstance *psh, union node *cmd, int quoted, int flag)
+{
+	struct backcmd in;
+	int i;
+	char buf[128];
+	char *p;
+	char *dest = psh->expdest;
+	struct ifsregion saveifs, *savelastp;
+	struct nodelist *saveargbackq;
+	char lastc;
+	int startloc = (int)(dest - stackblock(psh));
+	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
+	int saveherefd;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+
+	INTOFF;
+	saveifs = psh->ifsfirst;
+	savelastp = psh->ifslastp;
+	saveargbackq = psh->argbackq;
+	saveherefd = psh->herefd;
+	psh->herefd = -1;
+	p = grabstackstr(psh, dest);
+	evalbackcmd(psh, cmd, &in);
+	ungrabstackstr(psh, p, dest);
+	psh->ifsfirst = saveifs;
+	psh->ifslastp = savelastp;
+	psh->argbackq = saveargbackq;
+	psh->herefd = saveherefd;
+
+	p = in.buf;
+	lastc = '\0';
+	for (;;) {
+		if (--in.nleft < 0) {
+			if (in.fd < 0)
+				break;
+			while ((i = shfile_read(&psh->fdtab, in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
+			TRACE((psh, "expbackq: read returns %d\n", i));
+			if (i <= 0)
+				break;
+			p = buf;
+			in.nleft = i - 1;
+		}
+		lastc = *p++;
+		if (lastc != '\0') {
+			if (quotes && syntax[(int)lastc] == CCTL)
+				STPUTC(psh, CTLESC, dest);
+			STPUTC(psh, lastc, dest);
+		}
+	}
+
+	/* Eat all trailing newlines */
+	p = stackblock(psh) + startloc;
+	while (dest > p && dest[-1] == '\n')
+		STUNPUTC(psh, dest);
+
+	if (in.fd >= 0)
+		shfile_close(&psh->fdtab, in.fd);
+	if (in.buf)
+		ckfree(in.buf);
+	if (in.jp)
+		psh->back_exitstatus = waitforjob(psh, in.jp);
+	if (quoted == 0)
+		recordregion(psh, startloc, (int)(dest - stackblock(psh)), 0);
+	TRACE((psh, "evalbackq: size=%d: \"%.*s\"\n",
+		(dest - stackblock(psh)) - startloc,
+		(dest - stackblock(psh)) - startloc,
+		stackblock(psh) + startloc));
+	psh->expdest = dest;
+	INTON;
+}
+
+
+
+STATIC int
+subevalvar(shinstance *psh, char *p, char *str, int strloc, int subtype, int startloc, int varflags)
+{
+	char *startp;
+	char *loc = NULL;
+	char *q;
+	int c = 0;
+	int saveherefd = psh->herefd;
+	struct nodelist *saveargbackq = psh->argbackq;
+	int amount;
+
+	psh->herefd = -1;
+	argstr(psh, p, 0);
+	STACKSTRNUL(psh, psh->expdest);
+	psh->herefd = saveherefd;
+	psh->argbackq = saveargbackq;
+	startp = stackblock(psh) + startloc;
+	if (str == NULL)
+	    str = stackblock(psh) + strloc;
+
+	switch (subtype) {
+	case VSASSIGN:
+		setvar(psh, str, startp, 0);
+		amount = (int)(startp - psh->expdest);
+		STADJUST(psh, amount, psh->expdest);
+		varflags &= ~VSNUL;
+		if (c != 0)
+			*loc = c;
+		return 1;
+
+	case VSQUESTION:
+		if (*p != CTLENDVAR) {
+			outfmt(&psh->errout, "%s\n", startp);
+			error(psh, (char *)NULL);
+		}
+		error(psh, "%.*s: parameter %snot set", p - str - 1,
+		      str, (varflags & VSNUL) ? "null or "
+					      : nullstr);
+		/* NOTREACHED */
+
+	case VSTRIMLEFT:
+		for (loc = startp; loc < str; loc++) {
+			c = *loc;
+			*loc = '\0';
+			if (patmatch(psh, str, startp, varflags & VSQUOTE))
+				goto recordleft;
+			*loc = c;
+			if ((varflags & VSQUOTE) && *loc == CTLESC)
+			        loc++;
+		}
+		return 0;
+
+	case VSTRIMLEFTMAX:
+		for (loc = str - 1; loc >= startp;) {
+			c = *loc;
+			*loc = '\0';
+			if (patmatch(psh, str, startp, varflags & VSQUOTE))
+				goto recordleft;
+			*loc = c;
+			loc--;
+			if ((varflags & VSQUOTE) && loc > startp &&
+			    *(loc - 1) == CTLESC) {
+				for (q = startp; q < loc; q++)
+					if (*q == CTLESC)
+						q++;
+				if (q > loc)
+					loc--;
+			}
+		}
+		return 0;
+
+	case VSTRIMRIGHT:
+	        for (loc = str - 1; loc >= startp;) {
+			if (patmatch(psh, str, loc, varflags & VSQUOTE))
+				goto recordright;
+			loc--;
+			if ((varflags & VSQUOTE) && loc > startp &&
+			    *(loc - 1) == CTLESC) {
+				for (q = startp; q < loc; q++)
+					if (*q == CTLESC)
+						q++;
+				if (q > loc)
+					loc--;
+			}
+		}
+		return 0;
+
+	case VSTRIMRIGHTMAX:
+		for (loc = startp; loc < str - 1; loc++) {
+			if (patmatch(psh, str, loc, varflags & VSQUOTE))
+				goto recordright;
+			if ((varflags & VSQUOTE) && *loc == CTLESC)
+			        loc++;
+		}
+		return 0;
+
+	default:
+		sh_abort(psh);
+	}
+
+recordleft:
+	*loc = c;
+	amount = (int)(((str - 1) - (loc - startp)) - psh->expdest);
+	STADJUST(psh, amount, psh->expdest);
+	while (loc != str - 1)
+		*startp++ = *loc++;
+	return 1;
+
+recordright:
+	amount = (int)(loc - psh->expdest);
+	STADJUST(psh, amount, psh->expdest);
+	STPUTC(psh, '\0', psh->expdest);
+	STADJUST(psh, -1, psh->expdest);
+	return 1;
+}
+
+
+/*
+ * Expand a variable, and return a pointer to the next character in the
+ * input string.
+ */
+
+STATIC char *
+evalvar(shinstance *psh, char *p, int flag)
+{
+	int subtype;
+	int varflags;
+	char *var;
+	char *val;
+	int patloc;
+	int c;
+	int set;
+	int special;
+	int startloc;
+	int varlen;
+	int apply_ifs;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+
+	varflags = (unsigned char)*p++;
+	subtype = varflags & VSTYPE;
+	var = p;
+	special = !is_name(*p);
+	p = strchr(p, '=') + 1;
+
+again: /* jump here after setting a variable with ${var=text} */
+	if (special) {
+		set = varisset(psh, var, varflags & VSNUL);
+		val = NULL;
+	} else {
+		val = lookupvar(psh, var);
+		if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
+			val = NULL;
+			set = 0;
+		} else
+			set = 1;
+	}
+
+	varlen = 0;
+	startloc = (int)(psh->expdest - stackblock(psh));
+
+	if (!set && uflag(psh)) {
+		switch (subtype) {
+		case VSNORMAL:
+		case VSTRIMLEFT:
+		case VSTRIMLEFTMAX:
+		case VSTRIMRIGHT:
+		case VSTRIMRIGHTMAX:
+		case VSLENGTH:
+			error(psh, "%.*s: parameter not set", p - var - 1, var);
+			/* NOTREACHED */
+		}
+	}
+
+	if (set && subtype != VSPLUS) {
+		/* insert the value of the variable */
+		if (special) {
+			varvalue(psh, var, varflags & VSQUOTE, subtype, flag);
+			if (subtype == VSLENGTH) {
+				varlen = (int)(psh->expdest - stackblock(psh) - startloc);
+				STADJUST(psh, -varlen, psh->expdest);
+			}
+		} else {
+			char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
+								  : BASESYNTAX;
+
+			if (subtype == VSLENGTH) {
+				for (;*val; val++)
+					varlen++;
+			} else {
+				while (*val) {
+					if (quotes && syntax[(int)*val] == CCTL)
+						STPUTC(psh, CTLESC, psh->expdest);
+					STPUTC(psh, *val++, psh->expdest);
+				}
+
+			}
+		}
+	}
+
+
+	apply_ifs = ((varflags & VSQUOTE) == 0 ||
+		(*var == '@' && psh->shellparam.nparam != 1));
+
+	switch (subtype) {
+	case VSLENGTH:
+		psh->expdest = cvtnum(psh, varlen, psh->expdest);
+		break;
+
+	case VSNORMAL:
+		break;
+
+	case VSPLUS:
+		set = !set;
+		/* FALLTHROUGH */
+	case VSMINUS:
+		if (!set) {
+		        argstr(psh, p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0));
+			/*
+			 * ${x-a b c} doesn't get split, but removing the
+			 * 'apply_ifs = 0' apparantly breaks ${1+"$@"}..
+			 * ${x-'a b' c} should generate 2 args.
+			 */
+			/* We should have marked stuff already */
+			apply_ifs = 0;
+		}
+		break;
+
+	case VSTRIMLEFT:
+	case VSTRIMLEFTMAX:
+	case VSTRIMRIGHT:
+	case VSTRIMRIGHTMAX:
+		if (!set)
+			break;
+		/*
+		 * Terminate the string and start recording the pattern
+		 * right after it
+		 */
+		STPUTC(psh, '\0', psh->expdest);
+		patloc = (int)(psh->expdest - stackblock(psh));
+		if (subevalvar(psh, p, NULL, patloc, subtype,
+			       startloc, varflags) == 0) {
+			int amount = (int)(psh->expdest - stackblock(psh) - patloc) + 1;
+			STADJUST(psh, -amount, psh->expdest);
+		}
+		/* Remove any recorded regions beyond start of variable */
+		removerecordregions(psh, startloc);
+		apply_ifs = 1;
+		break;
+
+	case VSASSIGN:
+	case VSQUESTION:
+		if (set)
+			break;
+		if (subevalvar(psh, p, var, 0, subtype, startloc, varflags)) {
+			varflags &= ~VSNUL;
+			/*
+			 * Remove any recorded regions beyond
+			 * start of variable
+			 */
+			removerecordregions(psh, startloc);
+			goto again;
+		}
+		apply_ifs = 0;
+		break;
+
+	default:
+		sh_abort(psh);
+	}
+
+	if (apply_ifs)
+		recordregion(psh, startloc, (int)(psh->expdest - stackblock(psh)),
+			     varflags & VSQUOTE);
+
+	if (subtype != VSNORMAL) {	/* skip to end of alternative */
+		int nesting = 1;
+		for (;;) {
+			if ((c = *p++) == CTLESC)
+				p++;
+			else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
+				if (set)
+					psh->argbackq = psh->argbackq->next;
+			} else if (c == CTLVAR) {
+				if ((*p++ & VSTYPE) != VSNORMAL)
+					nesting++;
+			} else if (c == CTLENDVAR) {
+				if (--nesting == 0)
+					break;
+			}
+		}
+	}
+	return p;
+}
+
+
+
+/*
+ * Test whether a specialized variable is set.
+ */
+
+STATIC int
+varisset(shinstance *psh, char *name, int nulok)
+{
+	if (*name == '!')
+		return psh->backgndpid != -1;
+	else if (*name == '@' || *name == '*') {
+		if (*psh->shellparam.p == NULL)
+			return 0;
+
+		if (nulok) {
+			char **av;
+
+			for (av = psh->shellparam.p; *av; av++)
+				if (**av != '\0')
+					return 1;
+			return 0;
+		}
+	} else if (is_digit(*name)) {
+		char *ap;
+		int num = atoi(name);
+
+		if (num > psh->shellparam.nparam)
+			return 0;
+
+		if (num == 0)
+			ap = psh->arg0;
+		else
+			ap = psh->shellparam.p[num - 1];
+
+		if (nulok && (ap == NULL || *ap == '\0'))
+			return 0;
+	}
+	return 1;
+}
+
+
+
+/*
+ * Add the value of a specialized variable to the stack string.
+ */
+
+STATIC void
+varvalue(shinstance *psh, char *name, int quoted, int subtype, int flag)
+{
+	int num;
+	char *p;
+	int i;
+	char sep;
+	char **ap;
+	char const *syntax;
+
+#define STRTODEST(p) \
+	do {\
+	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \
+		syntax = quoted? DQSYNTAX : BASESYNTAX; \
+		while (*p) { \
+			if (syntax[(int)*p] == CCTL) \
+				STPUTC(psh, CTLESC, psh->expdest); \
+			STPUTC(psh, *p++, psh->expdest); \
+		} \
+	} else \
+		while (*p) \
+			STPUTC(psh, *p++, psh->expdest); \
+	} while (0)
+
+
+	switch (*name) {
+	case '$':
+		num = psh->rootpid;
+		goto numvar;
+	case '?':
+		num = psh->exitstatus;
+		goto numvar;
+	case '#':
+		num = psh->shellparam.nparam;
+		goto numvar;
+	case '!':
+		num = psh->backgndpid;
+numvar:
+		psh->expdest = cvtnum(psh, num, psh->expdest);
+		break;
+	case '-':
+		for (i = 0; psh->optlist[i].name; i++) {
+			if (psh->optlist[i].val)
+				STPUTC(psh, psh->optlist[i].letter, psh->expdest);
+		}
+		break;
+	case '@':
+		if (flag & EXP_FULL && quoted) {
+			for (ap = psh->shellparam.p ; (p = *ap++) != NULL ; ) {
+				STRTODEST(p);
+				if (*ap)
+					STPUTC(psh, '\0', psh->expdest);
+			}
+			break;
+		}
+		/* fall through */
+	case '*':
+		if (ifsset(psh) != 0)
+			sep = ifsval(psh)[0];
+		else
+			sep = ' ';
+		for (ap = psh->shellparam.p ; (p = *ap++) != NULL ; ) {
+			STRTODEST(p);
+			if (*ap && sep)
+				STPUTC(psh, sep, psh->expdest);
+		}
+		break;
+	case '0':
+		p = psh->arg0;
+		STRTODEST(p);
+		break;
+	default:
+		if (is_digit(*name)) {
+			num = atoi(name);
+			if (num > 0 && num <= psh->shellparam.nparam) {
+				p = psh->shellparam.p[num - 1];
+				STRTODEST(p);
+			}
+		}
+		break;
+	}
+}
+
+
+
+/*
+ * Record the fact that we have to scan this region of the
+ * string for IFS characters.
+ */
+
+STATIC void
+recordregion(shinstance *psh, int start, int end, int inquotes)
+{
+	struct ifsregion *ifsp;
+
+	if (psh->ifslastp == NULL) {
+		ifsp = &psh->ifsfirst;
+	} else {
+		if (psh->ifslastp->endoff == start
+		    && psh->ifslastp->inquotes == inquotes) {
+			/* extend previous area */
+			psh->ifslastp->endoff = end;
+			return;
+		}
+		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
+		psh->ifslastp->next = ifsp;
+	}
+	psh->ifslastp = ifsp;
+	psh->ifslastp->next = NULL;
+	psh->ifslastp->begoff = start;
+	psh->ifslastp->endoff = end;
+	psh->ifslastp->inquotes = inquotes;
+}
+
+
+
+/*
+ * Break the argument string into pieces based upon IFS and add the
+ * strings to the argument list.  The regions of the string to be
+ * searched for IFS characters have been stored by recordregion.
+ */
+STATIC void
+ifsbreakup(shinstance *psh, char *string, struct arglist *arglist)
+{
+	struct ifsregion *ifsp;
+	struct strlist *sp;
+	char *start;
+	char *p;
+	char *q;
+	const char *ifs;
+	const char *ifsspc;
+	int inquotes;
+
+	start = string;
+	ifsspc = NULL;
+	inquotes = 0;
+
+	if (psh->ifslastp == NULL) {
+		/* Return entire argument, IFS doesn't apply to any of it */
+		sp = (struct strlist *)stalloc(psh, sizeof *sp);
+		sp->text = start;
+		*arglist->lastp = sp;
+		arglist->lastp = &sp->next;
+		return;
+	}
+
+	ifs = ifsset(psh) ? ifsval(psh) : " \t\n";
+
+	for (ifsp = &psh->ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
+		p = string + ifsp->begoff;
+		inquotes = ifsp->inquotes;
+		ifsspc = NULL;
+		while (p < string + ifsp->endoff) {
+			q = p;
+			if (*p == CTLESC)
+				p++;
+			if (inquotes) {
+				/* Only NULs (probably from "$@") end args */
+				if (*p != 0) {
+					p++;
+					continue;
+				}
+			} else {
+				if (!strchr(ifs, *p)) {
+					p++;
+					continue;
+				}
+				ifsspc = strchr(" \t\n", *p);
+
+				/* Ignore IFS whitespace at start */
+				if (q == start && ifsspc != NULL) {
+					p++;
+					start = p;
+					continue;
+				}
+			}
+
+			/* Save this argument... */
+			*q = '\0';
+			sp = (struct strlist *)stalloc(psh, sizeof *sp);
+			sp->text = start;
+			*arglist->lastp = sp;
+			arglist->lastp = &sp->next;
+			p++;
+
+			if (ifsspc != NULL) {
+				/* Ignore further trailing IFS whitespace */
+				for (; p < string + ifsp->endoff; p++) {
+					q = p;
+					if (*p == CTLESC)
+						p++;
+					if (strchr(ifs, *p) == NULL) {
+						p = q;
+						break;
+					}
+					if (strchr(" \t\n", *p) == NULL) {
+						p++;
+						break;
+					}
+				}
+			}
+			start = p;
+		}
+	}
+
+	/*
+	 * Save anything left as an argument.
+	 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as
+	 * generating 2 arguments, the second of which is empty.
+	 * Some recent clarification of the Posix spec say that it
+	 * should only generate one....
+	 */
+	if (*start /* || (!ifsspc && start > string) */) {
+		sp = (struct strlist *)stalloc(psh, sizeof *sp);
+		sp->text = start;
+		*arglist->lastp = sp;
+		arglist->lastp = &sp->next;
+	}
+}
+
+STATIC void
+ifsfree(shinstance *psh)
+{
+	while (psh->ifsfirst.next != NULL) {
+		struct ifsregion *ifsp;
+		INTOFF;
+		ifsp = psh->ifsfirst.next->next;
+		ckfree(psh->ifsfirst.next);
+		psh->ifsfirst.next = ifsp;
+		INTON;
+	}
+	psh->ifslastp = NULL;
+	psh->ifsfirst.next = NULL;
+}
+
+
+
+/*
+ * Expand shell metacharacters.  At this point, the only control characters
+ * should be escapes.  The results are stored in the list psh->exparg.
+ */
+
+//char *expdir;
+
+
+STATIC void
+expandmeta(shinstance *psh, struct strlist *str, int flag)
+{
+	char *p;
+	struct strlist **savelastp;
+	struct strlist *sp;
+	char c;
+	/* TODO - EXP_REDIR */
+
+	while (str) {
+		if (fflag(psh))
+			goto nometa;
+		p = str->text;
+		for (;;) {			/* fast check for meta chars */
+			if ((c = *p++) == '\0')
+				goto nometa;
+			if (c == '*' || c == '?' || c == '[' || c == '!')
+				break;
+		}
+		savelastp = psh->exparg.lastp;
+		INTOFF;
+		if (psh->expdir == NULL) {
+			size_t i = strlen(str->text);
+			psh->expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
+		}
+
+		expmeta(psh, psh->expdir, str->text);
+		ckfree(psh->expdir);
+		psh->expdir = NULL;
+		INTON;
+		if (psh->exparg.lastp == savelastp) {
+			/*
+			 * no matches
+			 */
+nometa:
+			*psh->exparg.lastp = str;
+			rmescapes(psh, str->text);
+			psh->exparg.lastp = &str->next;
+		} else {
+			*psh->exparg.lastp = NULL;
+			*savelastp = sp = expsort(*savelastp);
+			while (sp->next != NULL)
+				sp = sp->next;
+			psh->exparg.lastp = &sp->next;
+		}
+		str = str->next;
+	}
+}
+
+
+/*
+ * Do metacharacter (i.e. *, ?, [...]) expansion.
+ */
+
+STATIC void
+expmeta(shinstance *psh, char *enddir, char *name)
+{
+	char *p;
+	const char *cp;
+	char *q;
+	char *start;
+	char *endname;
+	int metaflag;
+	struct stat statb;
+	shdir *dirp;
+	shdirent *dp;
+	int atend;
+	int matchdot;
+
+	metaflag = 0;
+	start = name;
+	for (p = name ; ; p++) {
+		if (*p == '*' || *p == '?')
+			metaflag = 1;
+		else if (*p == '[') {
+			q = p + 1;
+			if (*q == '!')
+				q++;
+			for (;;) {
+				while (*q == CTLQUOTEMARK)
+					q++;
+				if (*q == CTLESC)
+					q++;
+				if (*q == '/' || *q == '\0')
+					break;
+				if (*++q == ']') {
+					metaflag = 1;
+					break;
+				}
+			}
+		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {
+			metaflag = 1;
+		} else if (*p == '\0')
+			break;
+		else if (*p == CTLQUOTEMARK)
+			continue;
+		else if (*p == CTLESC)
+			p++;
+		if (*p == '/') {
+			if (metaflag)
+				break;
+			start = p + 1;
+		}
+	}
+	if (metaflag == 0) {	/* we've reached the end of the file name */
+		if (enddir != psh->expdir)
+			metaflag++;
+		for (p = name ; ; p++) {
+			if (*p == CTLQUOTEMARK)
+				continue;
+			if (*p == CTLESC)
+				p++;
+			*enddir++ = *p;
+			if (*p == '\0')
+				break;
+		}
+		if (metaflag == 0 || shfile_lstat(&psh->fdtab, psh->expdir, &statb) >= 0)
+			addfname(psh, psh->expdir);
+		return;
+	}
+	endname = p;
+	if (start != name) {
+		p = name;
+		while (p < start) {
+			while (*p == CTLQUOTEMARK)
+				p++;
+			if (*p == CTLESC)
+				p++;
+			*enddir++ = *p++;
+		}
+	}
+	if (enddir == psh->expdir) {
+		cp = ".";
+	} else if (enddir == psh->expdir + 1 && *psh->expdir == '/') {
+		cp = "/";
+	} else {
+		cp = psh->expdir;
+		enddir[-1] = '\0';
+	}
+	if ((dirp = shfile_opendir(&psh->fdtab, cp)) == NULL)
+		return;
+	if (enddir != psh->expdir)
+		enddir[-1] = '/';
+	if (*endname == 0) {
+		atend = 1;
+	} else {
+		atend = 0;
+		*endname++ = '\0';
+	}
+	matchdot = 0;
+	p = start;
+	while (*p == CTLQUOTEMARK)
+		p++;
+	if (*p == CTLESC)
+		p++;
+	if (*p == '.')
+		matchdot++;
+	while (! int_pending() && (dp = shfile_readdir(dirp)) != NULL) {
+		if (dp->name[0] == '.' && ! matchdot)
+			continue;
+		if (patmatch(psh, start, dp->name, 0)) {
+			if (atend) {
+				scopy(dp->name, enddir);
+				addfname(psh, psh->expdir);
+			} else {
+				for (p = enddir, cp = dp->name;
+				     (*p++ = *cp++) != '\0';)
+					continue;
+				p[-1] = '/';
+				expmeta(psh, p, endname);
+			}
+		}
+	}
+	shfile_closedir(dirp);
+	if (! atend)
+		endname[-1] = '/';
+}
+
+
+/*
+ * Add a file name to the list.
+ */
+
+STATIC void
+addfname(shinstance *psh, char *name)
+{
+	char *p;
+	struct strlist *sp;
+
+	p = stalloc(psh, strlen(name) + 1);
+	scopy(name, p);
+	sp = (struct strlist *)stalloc(psh, sizeof *sp);
+	sp->text = p;
+	*psh->exparg.lastp = sp;
+	psh->exparg.lastp = &sp->next;
+}
+
+
+/*
+ * Sort the results of file name expansion.  It calculates the number of
+ * strings to sort and then calls msort (short for merge sort) to do the
+ * work.
+ */
+
+STATIC struct strlist *
+expsort(struct strlist *str)
+{
+	int len;
+	struct strlist *sp;
+
+	len = 0;
+	for (sp = str ; sp ; sp = sp->next)
+		len++;
+	return msort(str, len);
+}
+
+
+STATIC struct strlist *
+msort(struct strlist *list, int len)
+{
+	struct strlist *p, *q = NULL;
+	struct strlist **lpp;
+	int half;
+	int n;
+
+	if (len <= 1)
+		return list;
+	half = len >> 1;
+	p = list;
+	for (n = half ; --n >= 0 ; ) {
+		q = p;
+		p = p->next;
+	}
+	q->next = NULL;			/* terminate first half of list */
+	q = msort(list, half);		/* sort first half of list */
+	p = msort(p, len - half);		/* sort second half */
+	lpp = &list;
+	for (;;) {
+		if (strcmp(p->text, q->text) < 0) {
+			*lpp = p;
+			lpp = &p->next;
+			if ((p = *lpp) == NULL) {
+				*lpp = q;
+				break;
+			}
+		} else {
+			*lpp = q;
+			lpp = &q->next;
+			if ((q = *lpp) == NULL) {
+				*lpp = p;
+				break;
+			}
+		}
+	}
+	return list;
+}
+
+
+
+/*
+ * Returns true if the pattern matches the string.
+ */
+
+int
+patmatch(shinstance *psh, char *pattern, char *string, int squoted)
+{
+#ifdef notdef
+	if (pattern[0] == '!' && pattern[1] == '!')
+		return 1 - pmatch(pattern + 2, string);
+	else
+#endif
+		return pmatch(pattern, string, squoted);
+}
+
+
+STATIC int
+pmatch(char *pattern, char *string, int squoted)
+{
+	char *p, *q;
+	char c;
+
+	p = pattern;
+	q = string;
+	for (;;) {
+		switch (c = *p++) {
+		case '\0':
+			goto breakloop;
+		case CTLESC:
+			if (squoted && *q == CTLESC)
+				q++;
+			if (*q++ != *p++)
+				return 0;
+			break;
+		case CTLQUOTEMARK:
+			continue;
+		case '?':
+			if (squoted && *q == CTLESC)
+				q++;
+			if (*q++ == '\0')
+				return 0;
+			break;
+		case '*':
+			c = *p;
+			while (c == CTLQUOTEMARK || c == '*')
+				c = *++p;
+			if (c != CTLESC &&  c != CTLQUOTEMARK &&
+			    c != '?' && c != '*' && c != '[') {
+				while (*q != c) {
+					if (squoted && *q == CTLESC &&
+					    q[1] == c)
+						break;
+					if (*q == '\0')
+						return 0;
+					if (squoted && *q == CTLESC)
+						q++;
+					q++;
+				}
+			}
+			do {
+				if (pmatch(p, q, squoted))
+					return 1;
+				if (squoted && *q == CTLESC)
+					q++;
+			} while (*q++ != '\0');
+			return 0;
+		case '[': {
+			char *endp;
+			int invert, found;
+			char chr;
+
+			endp = p;
+			if (*endp == '!')
+				endp++;
+			for (;;) {
+				while (*endp == CTLQUOTEMARK)
+					endp++;
+				if (*endp == '\0')
+					goto dft;		/* no matching ] */
+				if (*endp == CTLESC)
+					endp++;
+				if (*++endp == ']')
+					break;
+			}
+			invert = 0;
+			if (*p == '!') {
+				invert++;
+				p++;
+			}
+			found = 0;
+			chr = *q++;
+			if (squoted && chr == CTLESC)
+				chr = *q++;
+			if (chr == '\0')
+				return 0;
+			c = *p++;
+			do {
+				if (c == CTLQUOTEMARK)
+					continue;
+				if (c == CTLESC)
+					c = *p++;
+				if (*p == '-' && p[1] != ']') {
+					p++;
+					while (*p == CTLQUOTEMARK)
+						p++;
+					if (*p == CTLESC)
+						p++;
+					if (chr >= c && chr <= *p)
+						found = 1;
+					p++;
+				} else {
+					if (chr == c)
+						found = 1;
+				}
+			} while ((c = *p++) != ']');
+			if (found == invert)
+				return 0;
+			break;
+		}
+dft:	        default:
+			if (squoted && *q == CTLESC)
+				q++;
+			if (*q++ != c)
+				return 0;
+			break;
+		}
+	}
+breakloop:
+	if (*q != '\0')
+		return 0;
+	return 1;
+}
+
+
+
+/*
+ * Remove any CTLESC characters from a string.
+ */
+
+void
+rmescapes(shinstance *psh, char *str)
+{
+	char *p, *q;
+
+	p = str;
+	while (*p != CTLESC && *p != CTLQUOTEMARK) {
+		if (*p++ == '\0')
+			return;
+	}
+	q = p;
+	while (*p) {
+		if (*p == CTLQUOTEMARK) {
+			p++;
+			continue;
+		}
+		if (*p == CTLESC)
+			p++;
+		*q++ = *p++;
+	}
+	*q = '\0';
+}
+
+
+
+/*
+ * See if a pattern matches in a case statement.
+ */
+
+int
+casematch(shinstance *psh, union node *pattern, char *val)
+{
+	struct stackmark smark;
+	int result;
+	char *p;
+
+	setstackmark(psh, &smark);
+	psh->argbackq = pattern->narg.backquote;
+	STARTSTACKSTR(psh, psh->expdest);
+	psh->ifslastp = NULL;
+	argstr(psh, pattern->narg.text, EXP_TILDE | EXP_CASE);
+	STPUTC(psh, '\0', psh->expdest);
+	p = grabstackstr(psh, psh->expdest);
+	result = patmatch(psh, p, val, 0);
+	popstackmark(psh, &smark);
+	return result;
+}
+
+/*
+ * Our own itoa().
+ */
+
+STATIC char *
+cvtnum(shinstance *psh, int num, char *buf)
+{
+	char temp[32];
+	int neg = num < 0;
+	char *p = temp + 31;
+
+	temp[31] = '\0';
+
+	do {
+		*--p = num % 10 + '0';
+	} while ((num /= 10) != 0);
+
+	if (neg)
+		*--p = '-';
+
+	while (*p)
+		STPUTC(psh, *p++, buf);
+	return buf;
+}
+
+/*
+ * Do most of the work for wordexp(3).
+ */
+
+int
+wordexpcmd(shinstance *psh, int argc, char **argv)
+{
+	size_t len;
+	int i;
+
+	out1fmt(psh, "%d", argc - 1);
+	out1c(psh, '\0');
+	for (i = 1, len = 0; i < argc; i++)
+		len += strlen(argv[i]);
+	out1fmt(psh, "%zd", len);
+	out1c(psh, '\0');
+	for (i = 1; i < argc; i++) {
+		out1str(psh, argv[i]);
+		out1c(psh, '\0');
+	}
+	return (0);
+}
Index: /tags/kBuild-0.1.4/src/kash/expand.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/expand.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/expand.h	(revision 1780)
@@ -0,0 +1,79 @@
+/*	$NetBSD: expand.h,v 1.16 2004/07/13 15:05:59 seb Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)expand.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef ___expand_h
+#define ___expand_h
+
+#include "shtypes.h"
+
+struct strlist {
+	struct strlist *next;
+	char *text;
+};
+
+
+struct arglist {
+	struct strlist *list;
+	struct strlist **lastp;
+};
+
+/*
+ * expandarg() flags
+ */
+#define EXP_FULL	0x1	/* perform word splitting & file globbing */
+#define EXP_TILDE	0x2	/* do normal tilde expansion */
+#define	EXP_VARTILDE	0x4	/* expand tildes in an assignment */
+#define	EXP_REDIR	0x8	/* file glob for a redirection (1 match only) */
+#define EXP_CASE	0x10	/* keeps quotes around for CASE pattern */
+#define EXP_IFS_SPLIT	0x20	/* need to record arguments for ifs breakup */
+
+
+union node;
+void expandhere(struct shinstance *, union node *, int);
+void expandarg(struct shinstance *, union node *, struct arglist *, int);
+void expari(struct shinstance *, int);
+int patmatch(struct shinstance *, char *, char *, int);
+void rmescapes(struct shinstance *, char *);
+int casematch(struct shinstance *, union node *, char *);
+int wordexpcmd(struct shinstance *, int, char **);
+
+/* From arith.y */
+int arith(struct shinstance *, const char *);
+int expcmd(struct shinstance *, int , char **);
+void arith_lex_reset(void);
+int yylex(void);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/funcs/cmv
===================================================================
--- /tags/kBuild-0.1.4/src/kash/funcs/cmv	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/funcs/cmv	(revision 1780)
@@ -0,0 +1,50 @@
+#	$NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)cmv	8.2 (Berkeley) 5/4/95
+
+# Conditional move--don't replace an existing file.
+
+cmv() {
+	if test $# != 2
+	then	echo "cmv: arg count"
+		return 2
+	fi
+	if test -f "$2" -o -w "$2"
+	then	echo "$2 exists"
+		return 2
+	fi
+	/bin/mv "$1" "$2"
+}
Index: /tags/kBuild-0.1.4/src/kash/funcs/dirs
===================================================================
--- /tags/kBuild-0.1.4/src/kash/funcs/dirs	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/funcs/dirs	(revision 1780)
@@ -0,0 +1,74 @@
+#	$NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)dirs	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /tags/kBuild-0.1.4/src/kash/funcs/kill
===================================================================
--- /tags/kBuild-0.1.4/src/kash/funcs/kill	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/funcs/kill	(revision 1780)
@@ -0,0 +1,50 @@
+#	$NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)kill	8.2 (Berkeley) 5/4/95
+
+# Convert job names to process ids and then run /bin/kill.
+
+kill() {
+	local args x
+	args=
+	for x in "$@"
+	do	case $x in
+		%*)	x=`jobid "$x"` ;;
+		esac
+		args="$args $x"
+	done
+	/bin/kill $args
+}
Index: /tags/kBuild-0.1.4/src/kash/funcs/login
===================================================================
--- /tags/kBuild-0.1.4/src/kash/funcs/login	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/funcs/login	(revision 1780)
@@ -0,0 +1,39 @@
+#	$NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)login	8.2 (Berkeley) 5/4/95
+
+# replaces the login builtin in the BSD shell
+login () exec login "$@"
Index: /tags/kBuild-0.1.4/src/kash/funcs/newgrp
===================================================================
--- /tags/kBuild-0.1.4/src/kash/funcs/newgrp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/funcs/newgrp	(revision 1780)
@@ -0,0 +1,38 @@
+#	$NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)newgrp	8.2 (Berkeley) 5/4/95
+
+newgrp() exec newgrp "$@"
Index: /tags/kBuild-0.1.4/src/kash/funcs/popd
===================================================================
--- /tags/kBuild-0.1.4/src/kash/funcs/popd	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/funcs/popd	(revision 1780)
@@ -0,0 +1,74 @@
+#	$NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)popd	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /tags/kBuild-0.1.4/src/kash/funcs/pushd
===================================================================
--- /tags/kBuild-0.1.4/src/kash/funcs/pushd	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/funcs/pushd	(revision 1780)
@@ -0,0 +1,74 @@
+#	$NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)pushd	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
Index: /tags/kBuild-0.1.4/src/kash/funcs/suspend
===================================================================
--- /tags/kBuild-0.1.4/src/kash/funcs/suspend	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/funcs/suspend	(revision 1780)
@@ -0,0 +1,42 @@
+#	$NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)suspend	8.2 (Berkeley) 5/4/95
+
+suspend() {
+	local -
+	set +j
+	kill -TSTP 0
+}
Index: /tags/kBuild-0.1.4/src/kash/generated/arith.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/arith.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/arith.c	(revision 1780)
@@ -0,0 +1,667 @@
+#ifndef lint
+/*static char yysccsid[] = "from: @(#)yaccpar	1.9 (Berkeley) 02/21/93";*/
+static char yyrcsid[] = "$Id$";
+#endif
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define yyclearin (yychar=(-1))
+#define yyerrok (yyerrflag=0)
+#define YYRECOVERING (yyerrflag!=0)
+#define YYPREFIX "yy"
+/*	$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)arith.y	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdlib.h>
+#include "expand.h"
+#include "shell.h"
+#include "error.h"
+#include "output.h"
+#include "memalloc.h"
+#include "shinstance.h"
+
+shinstance *arith_psh;
+const char *arith_buf, *arith_startbuf;
+
+void yyerror(const char *);
+#ifdef TESTARITH
+int main(int , char *[]);
+int error(char *);
+#endif
+
+#define ARITH_NUM 257
+#define ARITH_LPAREN 258
+#define ARITH_RPAREN 259
+#define ARITH_OR 260
+#define ARITH_AND 261
+#define ARITH_BOR 262
+#define ARITH_BXOR 263
+#define ARITH_BAND 264
+#define ARITH_EQ 265
+#define ARITH_NE 266
+#define ARITH_LT 267
+#define ARITH_GT 268
+#define ARITH_GE 269
+#define ARITH_LE 270
+#define ARITH_LSHIFT 271
+#define ARITH_RSHIFT 272
+#define ARITH_ADD 273
+#define ARITH_SUB 274
+#define ARITH_MUL 275
+#define ARITH_DIV 276
+#define ARITH_REM 277
+#define ARITH_UNARYMINUS 278
+#define ARITH_UNARYPLUS 279
+#define ARITH_NOT 280
+#define ARITH_BNOT 281
+#define YYERRCODE 256
+short yylhs[] = {                                        -1,
+    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,
+};
+short yylen[] = {                                         2,
+    1,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+    3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+    2,    2,    2,    2,    1,
+};
+short yydefred[] = {                                      0,
+   25,    0,    0,    0,    0,    0,    0,    0,    0,   24,
+   23,   21,   22,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    2,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,   18,   19,   20,
+};
+short yydgoto[] = {                                       7,
+    8,
+};
+short yysindex[] = {                                   -255,
+    0, -255, -255, -255, -255, -255,    0,  -67,  -85,    0,
+    0,    0,    0, -255, -255, -255, -255, -255, -255, -255,
+ -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
+ -255,    0,  -50,  -34,  -19,  141, -261, -233, -233, -223,
+ -223, -223, -223, -253, -253, -248, -248,    0,    0,    0,
+};
+short yyrindex[] = {                                      0,
+    0,    0,    0,    0,    0,    0,    0,   30,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,  143,  140,  136,  131,  125,  109,  117,   61,
+   73,   85,   97,   33,   47,    1,   17,    0,    0,    0,
+};
+short yygindex[] = {                                      0,
+  142,
+};
+#define YYTABLESIZE 418
+short yytable[] = {                                       0,
+   16,    1,    2,   19,   20,   21,   22,   23,   24,   25,
+   26,   27,   28,   29,   30,   31,   17,    3,    4,   27,
+   28,   29,   30,   31,    5,    6,   29,   30,   31,    1,
+    0,    0,   14,   21,   22,   23,   24,   25,   26,   27,
+   28,   29,   30,   31,    0,    0,   15,   25,   26,   27,
+   28,   29,   30,   31,    0,    0,    0,    0,    0,    0,
+   11,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    9,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,   10,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   12,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    8,    0,
+    0,    0,    0,    0,    0,    0,   13,    0,    0,    0,
+    0,    0,    0,    0,    7,    0,    0,    0,    0,    0,
+    6,    0,    0,    0,    0,    5,    0,    0,    0,    4,
+    0,    0,    3,    9,   10,   11,   12,   13,    0,    0,
+    0,    0,    0,    0,    0,   33,   34,   35,   36,   37,
+   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,
+   48,   49,   50,   32,   14,   15,   16,   17,   18,   19,
+   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,
+   30,   31,   14,   15,   16,   17,   18,   19,   20,   21,
+   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,
+   15,   16,   17,   18,   19,   20,   21,   22,   23,   24,
+   25,   26,   27,   28,   29,   30,   31,   16,   17,   18,
+   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+   29,   30,   31,   17,   18,   19,   20,   21,   22,   23,
+   24,   25,   26,   27,   28,   29,   30,   31,    0,   16,
+   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+   16,   16,   16,   16,   16,   17,   17,   17,   17,   17,
+   17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+   17,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+   14,   14,   14,   14,   14,   15,   15,   15,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   11,
+   11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+   11,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+    9,    9,    9,   10,   10,   10,   10,   10,   10,   10,
+   10,   10,   10,   10,   10,   12,   12,   12,   12,   12,
+   12,   12,   12,   12,   12,   12,   12,    8,    8,    8,
+    8,    8,    8,    8,    8,   13,   13,   13,   13,   13,
+   13,   13,   13,    7,    7,    7,    7,    7,    7,    6,
+    6,    6,    6,    6,    5,    5,    5,    5,    4,    4,
+    4,    3,    3,    0,   18,   19,   20,   21,   22,   23,
+   24,   25,   26,   27,   28,   29,   30,   31,
+};
+short yycheck[] = {                                      -1,
+    0,  257,  258,  265,  266,  267,  268,  269,  270,  271,
+  272,  273,  274,  275,  276,  277,    0,  273,  274,  273,
+  274,  275,  276,  277,  280,  281,  275,  276,  277,    0,
+   -1,   -1,    0,  267,  268,  269,  270,  271,  272,  273,
+  274,  275,  276,  277,   -1,   -1,    0,  271,  272,  273,
+  274,  275,  276,  277,   -1,   -1,   -1,   -1,   -1,   -1,
+    0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,
+    0,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,    0,
+   -1,   -1,    0,    2,    3,    4,    5,    6,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   14,   15,   16,   17,   18,
+   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+   29,   30,   31,  259,  260,  261,  262,  263,  264,  265,
+  266,  267,  268,  269,  270,  271,  272,  273,  274,  275,
+  276,  277,  260,  261,  262,  263,  264,  265,  266,  267,
+  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,
+  261,  262,  263,  264,  265,  266,  267,  268,  269,  270,
+  271,  272,  273,  274,  275,  276,  277,  262,  263,  264,
+  265,  266,  267,  268,  269,  270,  271,  272,  273,  274,
+  275,  276,  277,  263,  264,  265,  266,  267,  268,  269,
+  270,  271,  272,  273,  274,  275,  276,  277,   -1,  259,
+  260,  261,  262,  263,  264,  265,  266,  267,  268,  269,
+  270,  271,  272,  273,  274,  259,  260,  261,  262,  263,
+  264,  265,  266,  267,  268,  269,  270,  271,  272,  273,
+  274,  259,  260,  261,  262,  263,  264,  265,  266,  267,
+  268,  269,  270,  271,  272,  259,  260,  261,  262,  263,
+  264,  265,  266,  267,  268,  269,  270,  271,  272,  259,
+  260,  261,  262,  263,  264,  265,  266,  267,  268,  269,
+  270,  259,  260,  261,  262,  263,  264,  265,  266,  267,
+  268,  269,  270,  259,  260,  261,  262,  263,  264,  265,
+  266,  267,  268,  269,  270,  259,  260,  261,  262,  263,
+  264,  265,  266,  267,  268,  269,  270,  259,  260,  261,
+  262,  263,  264,  265,  266,  259,  260,  261,  262,  263,
+  264,  265,  266,  259,  260,  261,  262,  263,  264,  259,
+  260,  261,  262,  263,  259,  260,  261,  262,  259,  260,
+  261,  259,  260,   -1,  264,  265,  266,  267,  268,  269,
+  270,  271,  272,  273,  274,  275,  276,  277,
+};
+#define YYFINAL 7
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 281
+#if YYDEBUG
+char *yyname[] = {
+"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"ARITH_NUM","ARITH_LPAREN",
+"ARITH_RPAREN","ARITH_OR","ARITH_AND","ARITH_BOR","ARITH_BXOR","ARITH_BAND",
+"ARITH_EQ","ARITH_NE","ARITH_LT","ARITH_GT","ARITH_GE","ARITH_LE",
+"ARITH_LSHIFT","ARITH_RSHIFT","ARITH_ADD","ARITH_SUB","ARITH_MUL","ARITH_DIV",
+"ARITH_REM","ARITH_UNARYMINUS","ARITH_UNARYPLUS","ARITH_NOT","ARITH_BNOT",
+};
+char *yyrule[] = {
+"$accept : exp",
+"exp : expr",
+"expr : ARITH_LPAREN expr ARITH_RPAREN",
+"expr : expr ARITH_OR expr",
+"expr : expr ARITH_AND expr",
+"expr : expr ARITH_BOR expr",
+"expr : expr ARITH_BXOR expr",
+"expr : expr ARITH_BAND expr",
+"expr : expr ARITH_EQ expr",
+"expr : expr ARITH_GT expr",
+"expr : expr ARITH_GE expr",
+"expr : expr ARITH_LT expr",
+"expr : expr ARITH_LE expr",
+"expr : expr ARITH_NE expr",
+"expr : expr ARITH_LSHIFT expr",
+"expr : expr ARITH_RSHIFT expr",
+"expr : expr ARITH_ADD expr",
+"expr : expr ARITH_SUB expr",
+"expr : expr ARITH_MUL expr",
+"expr : expr ARITH_DIV expr",
+"expr : expr ARITH_REM expr",
+"expr : ARITH_NOT expr",
+"expr : ARITH_BNOT expr",
+"expr : ARITH_SUB expr",
+"expr : ARITH_ADD expr",
+"expr : ARITH_NUM",
+};
+#endif
+#ifndef YYSTYPE
+typedef int YYSTYPE;
+#endif
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 500
+#define YYMAXDEPTH 500
+#endif
+#endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+short yyss[YYSTACKSIZE];
+YYSTYPE yyvs[YYSTACKSIZE];
+#define yystacksize YYSTACKSIZE
+int
+arith(shinstance *psh, const char *s)
+{
+	long result;
+
+	INTOFF;
+/* todo lock */
+   arith_psh = psh;
+	arith_buf = arith_startbuf = s;
+	result = yyparse();
+	arith_lex_reset();	/* reprime lex */
+   arith_psh = NULL;
+/* todo unlock */
+	INTON;
+
+	return (result);
+}
+
+
+/*
+ *  The exp(1) builtin.
+ */
+int
+expcmd(shinstance *psh, int argc, char **argv)
+{
+	const char *p;
+	char *concat;
+	char **ap;
+	long i;
+
+	if (argc > 1) {
+		p = argv[1];
+		if (argc > 2) {
+			/*
+			 * concatenate arguments
+			 */
+			STARTSTACKSTR(psh, concat);
+			ap = argv + 2;
+			for (;;) {
+				while (*p)
+					STPUTC(psh, *p++, concat);
+				if ((p = *ap++) == NULL)
+					break;
+				STPUTC(psh, ' ', concat);
+			}
+			STPUTC(psh, '\0', concat);
+			p = grabstackstr(psh, concat);
+		}
+	} else
+		p = "";
+
+	i = arith(psh, p);
+
+	out1fmt(psh, "%ld\n", i);
+	return (! i);
+}
+
+/*************************/
+#ifdef TEST_ARITH
+#include <stdio.h>
+main(argc, argv)
+	char *argv[];
+{
+	printf("%d\n", exp(argv[1]));
+}
+error(s)
+	char *s;
+{
+	fprintf(stderr, "exp: %s\n", s);
+	exit(1);
+}
+#endif
+
+void
+yyerror(const char *s)
+{
+   shinstance *psh = arith_psh;
+	yyerrok;
+	yyclearin;
+	arith_lex_reset();	/* reprime lex */
+/** @todo unlock */
+	error(psh, "arithmetic expression: %s: \"%s\"", s, arith_startbuf);
+	/* NOTREACHED */
+}
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+#ifdef __cplusplus
+extern "C" { 
+char * getenv();
+int yylex();
+int yyparse();
+}
+
+#endif
+int
+#if defined(__STDC__)
+yyparse(void)
+#else
+yyparse()
+#endif
+{
+    register int yym, yyn, yystate;
+#if YYDEBUG
+    register char *yys;
+#ifndef __cplusplus
+    extern char *getenv();
+#endif
+
+    if (yys = getenv("YYDEBUG"))
+    {
+        yyn = *yys;
+        if (yyn >= '0' && yyn <= '9')
+            yydebug = yyn - '0';
+    }
+#endif
+
+    yynerrs = 0;
+    yyerrflag = 0;
+    yychar = (-1);
+
+    yyssp = yyss;
+    yyvsp = yyvs;
+    *yyssp = yystate = 0;
+
+yyloop:
+    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+    if (yychar < 0)
+    {
+        if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, reading %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+    }
+    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: state %d, shifting to state %d\n",
+                    YYPREFIX, yystate, yytable[yyn]);
+#endif
+        if (yyssp >= yyss + yystacksize - 1)
+        {
+            goto yyoverflow;
+        }
+        *++yyssp = yystate = yytable[yyn];
+        *++yyvsp = yylval;
+        yychar = (-1);
+        if (yyerrflag > 0)  --yyerrflag;
+        goto yyloop;
+    }
+    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+        yyn = yytable[yyn];
+        goto yyreduce;
+    }
+    if (yyerrflag) goto yyinrecovery;
+    yyerror("syntax error");
+#ifdef lint
+    goto yyerrlab;
+#endif
+yyerrlab:
+    ++yynerrs;
+yyinrecovery:
+    if (yyerrflag < 3)
+    {
+        yyerrflag = 3;
+        for (;;)
+        {
+            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+                if (yyssp >= yyss + yystacksize - 1)
+                {
+                    goto yyoverflow;
+                }
+                *++yyssp = yystate = yytable[yyn];
+                *++yyvsp = yylval;
+                goto yyloop;
+            }
+            else
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: error recovery discarding state %d\n",
+                            YYPREFIX, *yyssp);
+#endif
+                if (yyssp <= yyss) goto yyabort;
+                --yyssp;
+                --yyvsp;
+            }
+        }
+    }
+    else
+    {
+        if (yychar == 0) goto yyabort;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+        yychar = (-1);
+        goto yyloop;
+    }
+yyreduce:
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+                YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+    yym = yylen[yyn];
+    yyval = yyvsp[1-yym];
+    switch (yyn)
+    {
+case 1:
+{
+			return (yyvsp[0]);
+		}
+break;
+case 2:
+{ yyval = yyvsp[-1]; }
+break;
+case 3:
+{ yyval = yyvsp[-2] ? yyvsp[-2] : yyvsp[0] ? yyvsp[0] : 0; }
+break;
+case 4:
+{ yyval = yyvsp[-2] ? ( yyvsp[0] ? yyvsp[0] : 0 ) : 0; }
+break;
+case 5:
+{ yyval = yyvsp[-2] | yyvsp[0]; }
+break;
+case 6:
+{ yyval = yyvsp[-2] ^ yyvsp[0]; }
+break;
+case 7:
+{ yyval = yyvsp[-2] & yyvsp[0]; }
+break;
+case 8:
+{ yyval = yyvsp[-2] == yyvsp[0]; }
+break;
+case 9:
+{ yyval = yyvsp[-2] > yyvsp[0]; }
+break;
+case 10:
+{ yyval = yyvsp[-2] >= yyvsp[0]; }
+break;
+case 11:
+{ yyval = yyvsp[-2] < yyvsp[0]; }
+break;
+case 12:
+{ yyval = yyvsp[-2] <= yyvsp[0]; }
+break;
+case 13:
+{ yyval = yyvsp[-2] != yyvsp[0]; }
+break;
+case 14:
+{ yyval = yyvsp[-2] << yyvsp[0]; }
+break;
+case 15:
+{ yyval = yyvsp[-2] >> yyvsp[0]; }
+break;
+case 16:
+{ yyval = yyvsp[-2] + yyvsp[0]; }
+break;
+case 17:
+{ yyval = yyvsp[-2] - yyvsp[0]; }
+break;
+case 18:
+{ yyval = yyvsp[-2] * yyvsp[0]; }
+break;
+case 19:
+{
+			if (yyvsp[0] == 0)
+				yyerror("division by zero");
+			yyval = yyvsp[-2] / yyvsp[0];
+			}
+break;
+case 20:
+{
+			if (yyvsp[0] == 0)
+				yyerror("division by zero");
+			yyval = yyvsp[-2] % yyvsp[0];
+			}
+break;
+case 21:
+{ yyval = !(yyvsp[0]); }
+break;
+case 22:
+{ yyval = ~(yyvsp[0]); }
+break;
+case 23:
+{ yyval = -(yyvsp[0]); }
+break;
+case 24:
+{ yyval = yyvsp[0]; }
+break;
+    }
+    yyssp -= yym;
+    yystate = *yyssp;
+    yyvsp -= yym;
+    yym = yylhs[yyn];
+    if (yystate == 0 && yym == 0)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+        yystate = YYFINAL;
+        *++yyssp = YYFINAL;
+        *++yyvsp = yyval;
+        if (yychar < 0)
+        {
+            if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+            if (yydebug)
+            {
+                yys = 0;
+                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+                if (!yys) yys = "illegal-symbol";
+                printf("%sdebug: state %d, reading %d (%s)\n",
+                        YYPREFIX, YYFINAL, yychar, yys);
+            }
+#endif
+        }
+        if (yychar == 0) goto yyaccept;
+        goto yyloop;
+    }
+    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+        yystate = yytable[yyn];
+    else
+        yystate = yydgoto[yym];
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
+#endif
+    if (yyssp >= yyss + yystacksize - 1)
+    {
+        goto yyoverflow;
+    }
+    *++yyssp = yystate;
+    *++yyvsp = yyval;
+    goto yyloop;
+yyoverflow:
+    yyerror("yacc stack overflow");
+yyabort:
+    return (1);
+yyaccept:
+    return (0);
+}
Index: /tags/kBuild-0.1.4/src/kash/generated/arith.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/arith.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/arith.h	(revision 1780)
@@ -0,0 +1,25 @@
+#define ARITH_NUM 257
+#define ARITH_LPAREN 258
+#define ARITH_RPAREN 259
+#define ARITH_OR 260
+#define ARITH_AND 261
+#define ARITH_BOR 262
+#define ARITH_BXOR 263
+#define ARITH_BAND 264
+#define ARITH_EQ 265
+#define ARITH_NE 266
+#define ARITH_LT 267
+#define ARITH_GT 268
+#define ARITH_GE 269
+#define ARITH_LE 270
+#define ARITH_LSHIFT 271
+#define ARITH_RSHIFT 272
+#define ARITH_ADD 273
+#define ARITH_SUB 274
+#define ARITH_MUL 275
+#define ARITH_DIV 276
+#define ARITH_REM 277
+#define ARITH_UNARYMINUS 278
+#define ARITH_UNARYPLUS 279
+#define ARITH_NOT 280
+#define ARITH_BNOT 281
Index: /tags/kBuild-0.1.4/src/kash/generated/arith_lex.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/arith_lex.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/arith_lex.c	(revision 1780)
@@ -0,0 +1,1934 @@
+#line 2 "/home/bird/vax/gdrive/coding/kbuild/svn/trunk/out/linux.x86/release/obj/src/kash/arith_lex.c"
+
+#line 4 "/home/bird/vax/gdrive/coding/kbuild/svn/trunk/out/linux.x86/release/obj/src/kash/arith_lex.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 29
+#define YY_END_OF_BUFFER 30
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[39] =
+    {   0,
+        0,    0,   30,   28,    1,    1,   27,   23,   12,    6,
+        7,   21,   24,   25,   22,    3,    4,   17,   28,   15,
+        5,   11,   10,   26,   14,    9,    3,    0,    4,   19,
+       18,   13,   16,   20,    5,    8,    2,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    1,    1,    1,    5,    6,    1,    7,
+        8,    9,   10,    1,   11,    1,   12,   13,   14,   14,
+       14,   14,   14,   14,   14,   15,   15,    1,    1,   16,
+       17,   18,    1,    1,   19,   19,   19,   19,   19,   19,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+        1,    1,    1,   21,   20,    1,   19,   19,   19,   19,
+
+       19,   19,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   22,
+       20,   20,    1,   23,    1,   24,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[25] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    2,    2,    2,    1,    1,    1,    2,    3,
+        1,    3,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[41] =
+    {   0,
+        0,    0,   47,   48,   48,   48,   29,   48,   39,   48,
+       48,   48,   48,   48,   48,   12,   14,   14,   27,   15,
+        0,   48,   20,   48,   48,   48,   22,    0,   24,   48,
+       48,   48,   48,   48,    0,   48,    0,   48,   38,   40
+    } ;
+
+static yyconst flex_int16_t yy_def[41] =
+    {   0,
+       38,    1,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       39,   38,   38,   38,   38,   38,   38,   40,   38,   38,
+       38,   38,   38,   38,   39,   38,   40,    0,   38,   38
+    } ;
+
+static yyconst flex_int16_t yy_nxt[73] =
+    {   0,
+        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
+       14,   15,   16,   17,   17,   18,   19,   20,   21,   21,
+       22,   21,   23,   24,   27,   27,   29,   29,   29,   30,
+       31,   33,   34,   28,   27,   27,   29,   29,   29,   35,
+       35,   37,   36,   32,   26,   25,   38,    3,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38
+    } ;
+
+static yyconst flex_int16_t yy_chk[73] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,   16,   16,   17,   17,   17,   18,
+       18,   20,   20,   16,   27,   27,   29,   29,   29,   39,
+       39,   40,   23,   19,    9,    7,    3,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "arith_lex.l"
+#line 3 "arith_lex.l"
+/*	$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)arith_lex.l	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $");
+#endif /* not lint */
+#endif
+
+#include "arith.h"
+#include "error.h"
+#include "expand.h"
+#include "var.h"
+#include "shinstance.h"
+
+extern int yylval;
+extern shinstance *arith_psh;
+extern char *arith_buf, *arith_startbuf;
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max) \
+	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
+#define YY_NO_UNPUT
+#line 538 "/home/bird/vax/gdrive/coding/kbuild/svn/trunk/out/linux.x86/release/obj/src/kash/arith_lex.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 60 "arith_lex.l"
+
+#line 693 "/home/bird/vax/gdrive/coding/kbuild/svn/trunk/out/linux.x86/release/obj/src/kash/arith_lex.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 39 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 48 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 61 "arith_lex.l"
+{ ; }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 62 "arith_lex.l"
+{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 63 "arith_lex.l"
+{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 64 "arith_lex.l"
+{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 65 "arith_lex.l"
+{ char *v = lookupvar(arith_psh, yytext);
+			if (v) {
+				yylval = strtol(v, &v, 0);
+				if (*v == 0)
+					return ARITH_NUM;
+			}
+			error(arith_psh, "arith: syntax error: \"%s\"", arith_startbuf);
+		}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 73 "arith_lex.l"
+{ return(ARITH_LPAREN); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 74 "arith_lex.l"
+{ return(ARITH_RPAREN); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 75 "arith_lex.l"
+{ return(ARITH_OR); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 76 "arith_lex.l"
+{ return(ARITH_AND); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 77 "arith_lex.l"
+{ return(ARITH_BOR); }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 78 "arith_lex.l"
+{ return(ARITH_BXOR); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 79 "arith_lex.l"
+{ return(ARITH_BAND); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 80 "arith_lex.l"
+{ return(ARITH_EQ); }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 81 "arith_lex.l"
+{ return(ARITH_NE); }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 82 "arith_lex.l"
+{ return(ARITH_GT); }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 83 "arith_lex.l"
+{ return(ARITH_GE); }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 84 "arith_lex.l"
+{ return(ARITH_LT); }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 85 "arith_lex.l"
+{ return(ARITH_LE); }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 86 "arith_lex.l"
+{ return(ARITH_LSHIFT); }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 87 "arith_lex.l"
+{ return(ARITH_RSHIFT); }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 88 "arith_lex.l"
+{ return(ARITH_MUL); }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 89 "arith_lex.l"
+{ return(ARITH_DIV); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 90 "arith_lex.l"
+{ return(ARITH_REM); }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 91 "arith_lex.l"
+{ return(ARITH_ADD); }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 92 "arith_lex.l"
+{ return(ARITH_SUB); }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 93 "arith_lex.l"
+{ return(ARITH_BNOT); }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 94 "arith_lex.l"
+{ return(ARITH_NOT); }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 95 "arith_lex.l"
+{ error(arith_psh, "arith: syntax error: \"%s\"", arith_startbuf); }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 96 "arith_lex.l"
+ECHO;
+	YY_BREAK
+#line 929 "/home/bird/vax/gdrive/coding/kbuild/svn/trunk/out/linux.x86/release/obj/src/kash/arith_lex.c"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 39 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 39 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 38);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up yytext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+	yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf  );
+
+	yyfree((void *) b  );
+}
+
+#ifndef _UNISTD_H /* assume unistd.h has isatty() for us */
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __THROW /* this is a gnuism */
+extern int isatty (int ) __THROW;
+#else
+extern int isatty (int );
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param str a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 96 "arith_lex.l"
+
+
+
+void
+arith_lex_reset() {
+#ifdef YY_NEW_FILE
+	YY_NEW_FILE;
+#endif
+}
+
Index: /tags/kBuild-0.1.4/src/kash/generated/builtins.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/builtins.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/builtins.c	(revision 1780)
@@ -0,0 +1,63 @@
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include "shell.h"
+#include "builtins.h"
+
+const struct builtincmd builtincmd[] = {
+
+	{ "command",	bltincmd },
+	{ "bg",	bgcmd },
+	{ "cd",	cdcmd },
+	{ "chdir",	cdcmd },
+	{ "echo",	echocmd },
+	{ "exp",	expcmd },
+	{ "let",	expcmd },
+	{ "false",	falsecmd },
+	{ "fc",	histcmd },
+	{ "inputrc",	inputrc },
+	{ "fg",	fgcmd },
+	{ "getopts",	getoptscmd },
+	{ "hash",	hashcmd },
+	{ "jobid",	jobidcmd },
+	{ "jobs",	jobscmd },
+	{ "local",	localcmd },
+#ifndef SMALL
+	{ "printf",	printfcmd },
+#endif
+	{ "pwd",	pwdcmd },
+	{ "read",	readcmd },
+	{ "setvar",	setvarcmd },
+	{ "true",	truecmd },
+	{ "type",	typecmd },
+	{ "umask",	umaskcmd },
+	{ "unalias",	unaliascmd },
+	{ "wait",	waitcmd },
+	{ "alias",	aliascmd },
+	{ "ulimit",	ulimitcmd },
+	{ "test",	testcmd },
+	{ "[",	testcmd },
+	{ "kill",	killcmd },
+	{ "wordexp",	wordexpcmd },
+	{ 0, 0 },
+};
+
+const struct builtincmd splbltincmd[] = {
+	{ "break",	breakcmd },
+	{ "continue",	breakcmd },
+	{ ".",	dotcmd },
+	{ "eval",	evalcmd },
+	{ "exec",	execcmd },
+	{ "exit",	exitcmd },
+	{ "export",	exportcmd },
+	{ "readonly",	exportcmd },
+	{ "return",	returncmd },
+	{ "set",	setcmd },
+	{ "shift",	shiftcmd },
+	{ "times",	timescmd },
+	{ "trap",	trapcmd },
+	{ ":",	truecmd },
+	{ "unset",	unsetcmd },
+	{ 0, 0 },
+};
Index: /tags/kBuild-0.1.4/src/kash/generated/builtins.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/builtins.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/builtins.h	(revision 1780)
@@ -0,0 +1,57 @@
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include "shtypes.h"
+
+struct builtincmd {
+      const char *name;
+      int (*builtin)(shinstance *, int, char **);
+};
+
+extern const struct builtincmd builtincmd[];
+extern const struct builtincmd splbltincmd[];
+
+
+int bltincmd(shinstance *, int, char **);
+int bgcmd(shinstance *, int, char **);
+int breakcmd(shinstance *, int, char **);
+int cdcmd(shinstance *, int, char **);
+int dotcmd(shinstance *, int, char **);
+int echocmd(shinstance *, int, char **);
+int evalcmd(shinstance *, int, char **);
+int execcmd(shinstance *, int, char **);
+int exitcmd(shinstance *, int, char **);
+int expcmd(shinstance *, int, char **);
+int exportcmd(shinstance *, int, char **);
+int falsecmd(shinstance *, int, char **);
+int histcmd(shinstance *, int, char **);
+int inputrc(shinstance *, int, char **);
+int fgcmd(shinstance *, int, char **);
+int getoptscmd(shinstance *, int, char **);
+int hashcmd(shinstance *, int, char **);
+int jobidcmd(shinstance *, int, char **);
+int jobscmd(shinstance *, int, char **);
+int localcmd(shinstance *, int, char **);
+#ifndef SMALL
+int printfcmd(shinstance *, int, char **);
+#endif
+int pwdcmd(shinstance *, int, char **);
+int readcmd(shinstance *, int, char **);
+int returncmd(shinstance *, int, char **);
+int setcmd(shinstance *, int, char **);
+int setvarcmd(shinstance *, int, char **);
+int shiftcmd(shinstance *, int, char **);
+int timescmd(shinstance *, int, char **);
+int trapcmd(shinstance *, int, char **);
+int truecmd(shinstance *, int, char **);
+int typecmd(shinstance *, int, char **);
+int umaskcmd(shinstance *, int, char **);
+int unaliascmd(shinstance *, int, char **);
+int unsetcmd(shinstance *, int, char **);
+int waitcmd(shinstance *, int, char **);
+int aliascmd(shinstance *, int, char **);
+int ulimitcmd(shinstance *, int, char **);
+int testcmd(shinstance *, int, char **);
+int killcmd(shinstance *, int, char **);
+int wordexpcmd(shinstance *, int, char **);
Index: /tags/kBuild-0.1.4/src/kash/generated/init.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/init.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/init.c	(revision 1780)
@@ -0,0 +1,276 @@
+/*
+ * This file was generated by the mkinit program.
+ */
+
+#include "shell.h"
+#include "mystring.h"
+#include "init.h"
+#include "eval.h"
+#include <stdio.h>
+#include "input.h"
+#include "error.h"
+#include <stdlib.h>
+#include "options.h"
+#include "output.h"
+#include "memalloc.h"
+#include "redir.h"
+#include <signal.h>
+#include "trap.h"
+#include "var.h"
+#include "shinstance.h"
+
+
+
+#undef  PROFILE
+#define PROFILE 0
+#undef  SIGSSIZE
+#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
+#undef  MAXPWD
+#define MAXPWD 256
+#undef  ALL
+#define ALL (E_OPEN|E_CREAT|E_EXEC)
+#undef  EV_EXIT
+#define EV_EXIT 01		/* exit after evaluating tree */
+#undef  EV_TESTED
+#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
+#undef  EV_BACKCMD
+#define EV_BACKCMD 04		/* command executing within back quotes */
+#undef  NEWARGS
+#define NEWARGS 5
+#undef  MAXHISTLOOPS
+#define MAXHISTLOOPS	4	/* max recursions through fc */
+#undef  DEFEDITOR
+#define DEFEDITOR	"ed"	/* default editor *should* be $EDITOR */
+#undef  editing
+#define editing (Eflag(psh) || Vflag(psh))
+#undef  EOF_NLEFT
+#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
+#undef  DEFINE_OPTIONS
+#define DEFINE_OPTIONS
+#undef  BLOCK_OUT
+#define BLOCK_OUT -2		/* output to a fixed block of memory */
+#undef  OUTPUT_ERR
+#define OUTPUT_ERR 01		/* error occurred on output */
+#undef  TEMPSIZE
+#define TEMPSIZE 32
+#undef  HAVE_VASPRINTF
+#define HAVE_VASPRINTF 1
+#undef  EOFMARKLEN
+#define EOFMARKLEN 79
+#undef  OPENBRACE
+#define OPENBRACE '{'
+#undef  CLOSEBRACE
+#define CLOSEBRACE '}'
+#undef  EMPTY
+#define EMPTY -2		/* marks an unused slot in redirtab */
+#undef  S_DFL
+#define S_DFL 1			/* default signal handling (SIG_DFL) */
+#undef  S_CATCH
+#define S_CATCH 2		/* signal is caught */
+#undef  S_IGN
+#define S_IGN 3			/* signal is ignored (SIG_IGN) */
+#undef  S_HARD_IGN
+#define S_HARD_IGN 4		/* signal is ignored permenantly */
+#undef  S_RESET
+#define S_RESET 5		/* temporary - to reset a hard ignored sig */
+#undef  INCL_BASE
+#define INCL_BASE
+#undef  LIBPATHSTRICT
+#define LIBPATHSTRICT 3
+#undef  QHINF_EXEINFO
+#define QHINF_EXEINFO       1 /* NE exeinfo. */
+#undef  QHINF_READRSRCTBL
+#define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
+#undef  QHINF_READFILE
+#define QHINF_READFILE      3 /* Reads from the executable file. */
+#undef  QHINF_LIBPATHLENGTH
+#define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
+#undef  QHINF_LIBPATH
+#define QHINF_LIBPATH       5 /* Gets the entire libpath. */
+#undef  QHINF_FIXENTRY
+#define QHINF_FIXENTRY      6 /* NE only */
+#undef  QHINF_STE
+#define QHINF_STE           7 /* NE only */
+#undef  QHINF_MAPSEL
+#define QHINF_MAPSEL        8 /* NE only */
+#undef  SET_LEN
+#define	SET_LEN	6		/* initial # of bitcmd struct to malloc */
+#undef  SET_LEN_INCR
+#define	SET_LEN_INCR 4		/* # of bitcmd structs to add as needed */
+#undef  CMD2_CLR
+#define	CMD2_CLR	0x01
+#undef  CMD2_SET
+#define	CMD2_SET	0x02
+#undef  CMD2_GBITS
+#define	CMD2_GBITS	0x04
+#undef  CMD2_OBITS
+#define	CMD2_OBITS	0x08
+#undef  CMD2_UBITS
+#define	CMD2_UBITS	0x10
+#undef  STANDARD_BITS
+#define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+
+
+
+extern void rmaliases(shinstance *psh);
+
+extern void deletefuncs(struct shinstance *);
+extern void hash_special_builtins(struct shinstance *);
+
+struct redirtab {
+	struct redirtab *next;
+	short renamed[10];
+};
+
+
+
+/*
+ * Initialization code.
+ */
+
+void
+init(shinstance *psh) {
+
+      /* from exec.c: */
+      {
+	      hash_special_builtins(psh);
+      }
+
+      /* from input.c: */
+      {
+	      psh->basepf.nextc = psh->basepf.buf = psh->basebuf;
+      }
+
+      /* from options.c: */
+      {
+	      memcpy(&psh->optlist[0], &ro_optlist[0], sizeof(psh->optlist));
+      }
+
+      /* from var.c: */
+      {
+	      char **envp;
+
+	      initvar(psh);
+	      for (envp = sh_environ(psh) ; *envp ; envp++) {
+		      if (strchr(*envp, '=')) {
+			      setvareq(psh, *envp, VEXPORT|VTEXTFIXED);
+		      }
+	      }
+      }
+}
+
+
+
+/*
+ * This routine is called when an error or an interrupt occurs in an
+ * interactive shell and control is returned to the main command loop.
+ */
+
+void
+reset(shinstance *psh) {
+
+      /* from eval.c: */
+      {
+	      psh->evalskip = 0;
+	      psh->loopnest = 0;
+	      psh->funcnest = 0;
+      }
+
+      /* from input.c: */
+      {
+	      if (psh->exception != EXSHELLPROC)
+		      psh->parselleft = psh->parsenleft = 0;	/* clear input buffer */
+	      popallfiles(psh);
+      }
+
+      /* from output.c: */
+      {
+	      psh->out1 = &psh->output;
+	      psh->out2 = &psh->errout;
+	      if (psh->memout.buf != NULL) {
+		      ckfree(psh->memout.buf);
+		      psh->memout.buf = NULL;
+	      }
+      }
+
+      /* from parser.c: */
+      {
+	      psh->tokpushback = 0;
+	      psh->checkkwd = 0;
+      }
+
+      /* from redir.c: */
+      {
+	      while (psh->redirlist)
+		      popredir(psh);
+      }
+}
+
+
+
+/*
+ * This routine is called to initialize the shell to run a shell procedure.
+ */
+
+void
+initshellproc(shinstance *psh) {
+
+      /* from alias.c: */
+      {
+	      rmaliases(psh);
+      }
+
+      /* from eval.c: */
+      {
+	      psh->exitstatus = 0;
+      }
+
+      /* from exec.c: */
+      {
+	      deletefuncs(psh);
+      }
+
+      /* from input.c: */
+      {
+	      popallfiles(psh);
+      }
+
+      /* from jobs.c: */
+      {
+	      psh->backgndpid = -1;
+#if JOBS
+	      psh->jobctl = 0;
+#endif
+      }
+
+      /* from options.c: */
+      {
+	      int i;
+
+	      for (i = 0; psh->optlist[i].name; i++)
+		      psh->optlist[i].val = 0;
+	      optschanged(psh);
+
+      }
+
+      /* from redir.c: */
+      {
+	      clearredir(psh, 0);
+      }
+
+      /* from trap.c: */
+      {
+	      char *sm;
+
+	      clear_traps(psh, 0);
+	      for (sm = psh->sigmode ; sm < psh->sigmode + NSIG ; sm++) {
+		      if (*sm == S_IGN)
+			      *sm = S_HARD_IGN;
+	      }
+      }
+
+      /* from var.c: */
+      {
+	      shprocvar(psh);
+      }
+}
Index: /tags/kBuild-0.1.4/src/kash/generated/nodes.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/nodes.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/nodes.c	(revision 1780)
@@ -0,0 +1,347 @@
+/*
+ * This file was generated by mknodes.sh
+ */
+
+/*	$NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
+ */
+
+#include <stdlib.h>
+/*
+ * Routine for dealing with parsed shell commands.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "memalloc.h"
+#include "machdep.h"
+#include "mystring.h"
+
+
+int     funcblocksize;		/* size of structures in function */
+int     funcstringsize;		/* size of strings in node */
+pointer funcblock;		/* block to allocate function from */
+char   *funcstring;		/* block to allocate strings from */
+
+static const short nodesize[26] = {
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct ncmd)),
+      SHELL_ALIGN(sizeof (struct npipe)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nif)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nfor)),
+      SHELL_ALIGN(sizeof (struct ncase)),
+      SHELL_ALIGN(sizeof (struct nclist)),
+      SHELL_ALIGN(sizeof (struct narg)),
+      SHELL_ALIGN(sizeof (struct narg)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct ndup)),
+      SHELL_ALIGN(sizeof (struct ndup)),
+      SHELL_ALIGN(sizeof (struct nhere)),
+      SHELL_ALIGN(sizeof (struct nhere)),
+      SHELL_ALIGN(sizeof (struct nnot)),
+};
+
+
+STATIC void calcsize(union node *);
+STATIC void sizenodelist(struct nodelist *);
+STATIC union node *copynode(union node *);
+STATIC struct nodelist *copynodelist(struct nodelist *);
+STATIC char *nodesavestr(char *);
+
+
+
+/*
+ * Make a copy of a parse tree.
+ */
+
+union node *
+copyfunc(n)
+	union node *n;
+{
+	if (n == NULL)
+		return NULL;
+	funcblocksize = 0;
+	funcstringsize = 0;
+	calcsize(n);
+	funcblock = ckmalloc(funcblocksize + funcstringsize);
+	funcstring = (char *) funcblock + funcblocksize;
+	return copynode(n);
+}
+
+
+
+STATIC void
+calcsize(n)
+	union node *n;
+{
+      if (n == NULL)
+	    return;
+      funcblocksize += nodesize[n->type];
+      switch (n->type) {
+      case NSEMI:
+      case NAND:
+      case NOR:
+      case NWHILE:
+      case NUNTIL:
+	    calcsize(n->nbinary.ch2);
+	    calcsize(n->nbinary.ch1);
+	    break;
+      case NCMD:
+	    calcsize(n->ncmd.redirect);
+	    calcsize(n->ncmd.args);
+	    break;
+      case NPIPE:
+	    sizenodelist(n->npipe.cmdlist);
+	    break;
+      case NREDIR:
+      case NBACKGND:
+      case NSUBSHELL:
+	    calcsize(n->nredir.redirect);
+	    calcsize(n->nredir.n);
+	    break;
+      case NIF:
+	    calcsize(n->nif.elsepart);
+	    calcsize(n->nif.ifpart);
+	    calcsize(n->nif.test);
+	    break;
+      case NFOR:
+	    funcstringsize += strlen(n->nfor.var) + 1;
+	    calcsize(n->nfor.body);
+	    calcsize(n->nfor.args);
+	    break;
+      case NCASE:
+	    calcsize(n->ncase.cases);
+	    calcsize(n->ncase.expr);
+	    break;
+      case NCLIST:
+	    calcsize(n->nclist.body);
+	    calcsize(n->nclist.pattern);
+	    calcsize(n->nclist.next);
+	    break;
+      case NDEFUN:
+      case NARG:
+	    sizenodelist(n->narg.backquote);
+	    funcstringsize += strlen(n->narg.text) + 1;
+	    calcsize(n->narg.next);
+	    break;
+      case NTO:
+      case NCLOBBER:
+      case NFROM:
+      case NFROMTO:
+      case NAPPEND:
+	    calcsize(n->nfile.fname);
+	    calcsize(n->nfile.next);
+	    break;
+      case NTOFD:
+      case NFROMFD:
+	    calcsize(n->ndup.vname);
+	    calcsize(n->ndup.next);
+	    break;
+      case NHERE:
+      case NXHERE:
+	    calcsize(n->nhere.doc);
+	    calcsize(n->nhere.next);
+	    break;
+      case NNOT:
+	    calcsize(n->nnot.com);
+	    break;
+      };
+}
+
+
+
+STATIC void
+sizenodelist(lp)
+	struct nodelist *lp;
+{
+	while (lp) {
+		funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
+		calcsize(lp->n);
+		lp = lp->next;
+	}
+}
+
+
+
+STATIC union node *
+copynode(n)
+	union node *n;
+{
+	union node *new;
+
+      if (n == NULL)
+	    return NULL;
+      new = funcblock;
+      funcblock = (char *) funcblock + nodesize[n->type];
+      switch (n->type) {
+      case NSEMI:
+      case NAND:
+      case NOR:
+      case NWHILE:
+      case NUNTIL:
+	    new->nbinary.ch2 = copynode(n->nbinary.ch2);
+	    new->nbinary.ch1 = copynode(n->nbinary.ch1);
+	    break;
+      case NCMD:
+	    new->ncmd.redirect = copynode(n->ncmd.redirect);
+	    new->ncmd.args = copynode(n->ncmd.args);
+	    new->ncmd.backgnd = n->ncmd.backgnd;
+	    break;
+      case NPIPE:
+	    new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
+	    new->npipe.backgnd = n->npipe.backgnd;
+	    break;
+      case NREDIR:
+      case NBACKGND:
+      case NSUBSHELL:
+	    new->nredir.redirect = copynode(n->nredir.redirect);
+	    new->nredir.n = copynode(n->nredir.n);
+	    break;
+      case NIF:
+	    new->nif.elsepart = copynode(n->nif.elsepart);
+	    new->nif.ifpart = copynode(n->nif.ifpart);
+	    new->nif.test = copynode(n->nif.test);
+	    break;
+      case NFOR:
+	    new->nfor.var = nodesavestr(n->nfor.var);
+	    new->nfor.body = copynode(n->nfor.body);
+	    new->nfor.args = copynode(n->nfor.args);
+	    break;
+      case NCASE:
+	    new->ncase.cases = copynode(n->ncase.cases);
+	    new->ncase.expr = copynode(n->ncase.expr);
+	    break;
+      case NCLIST:
+	    new->nclist.body = copynode(n->nclist.body);
+	    new->nclist.pattern = copynode(n->nclist.pattern);
+	    new->nclist.next = copynode(n->nclist.next);
+	    break;
+      case NDEFUN:
+      case NARG:
+	    new->narg.backquote = copynodelist(n->narg.backquote);
+	    new->narg.text = nodesavestr(n->narg.text);
+	    new->narg.next = copynode(n->narg.next);
+	    break;
+      case NTO:
+      case NCLOBBER:
+      case NFROM:
+      case NFROMTO:
+      case NAPPEND:
+	    new->nfile.fname = copynode(n->nfile.fname);
+	    new->nfile.fd = n->nfile.fd;
+	    new->nfile.next = copynode(n->nfile.next);
+	    break;
+      case NTOFD:
+      case NFROMFD:
+	    new->ndup.vname = copynode(n->ndup.vname);
+	    new->ndup.dupfd = n->ndup.dupfd;
+	    new->ndup.fd = n->ndup.fd;
+	    new->ndup.next = copynode(n->ndup.next);
+	    break;
+      case NHERE:
+      case NXHERE:
+	    new->nhere.doc = copynode(n->nhere.doc);
+	    new->nhere.fd = n->nhere.fd;
+	    new->nhere.next = copynode(n->nhere.next);
+	    break;
+      case NNOT:
+	    new->nnot.com = copynode(n->nnot.com);
+	    break;
+      };
+      new->type = n->type;
+	return new;
+}
+
+
+STATIC struct nodelist *
+copynodelist(lp)
+	struct nodelist *lp;
+{
+	struct nodelist *start;
+	struct nodelist **lpp;
+
+	lpp = &start;
+	while (lp) {
+		*lpp = funcblock;
+		funcblock = (char *) funcblock +
+		    SHELL_ALIGN(sizeof(struct nodelist));
+		(*lpp)->n = copynode(lp->n);
+		lp = lp->next;
+		lpp = &(*lpp)->next;
+	}
+	*lpp = NULL;
+	return start;
+}
+
+
+
+STATIC char *
+nodesavestr(s)
+	char   *s;
+{
+	register char *p = s;
+	register char *q = funcstring;
+	char   *rtn = funcstring;
+
+	while ((*q++ = *p++) != 0)
+		continue;
+	funcstring = q;
+	return rtn;
+}
+
+
+
+/*
+ * Free a parse tree.
+ */
+
+void
+freefunc(n)
+	union node *n;
+{
+	if (n)
+		ckfree(n);
+}
Index: /tags/kBuild-0.1.4/src/kash/generated/nodes.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/nodes.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/nodes.h	(revision 1780)
@@ -0,0 +1,159 @@
+/*
+ * This file was generated by mknodes.sh
+ */
+
+#define NSEMI 0
+#define NCMD 1
+#define NPIPE 2
+#define NREDIR 3
+#define NBACKGND 4
+#define NSUBSHELL 5
+#define NAND 6
+#define NOR 7
+#define NIF 8
+#define NWHILE 9
+#define NUNTIL 10
+#define NFOR 11
+#define NCASE 12
+#define NCLIST 13
+#define NDEFUN 14
+#define NARG 15
+#define NTO 16
+#define NCLOBBER 17
+#define NFROM 18
+#define NFROMTO 19
+#define NAPPEND 20
+#define NTOFD 21
+#define NFROMFD 22
+#define NHERE 23
+#define NXHERE 24
+#define NNOT 25
+
+
+
+struct nbinary {
+      int type;
+      union node *ch1;
+      union node *ch2;
+};
+
+
+struct ncmd {
+      int type;
+      int backgnd;
+      union node *args;
+      union node *redirect;
+};
+
+
+struct npipe {
+      int type;
+      int backgnd;
+      struct nodelist *cmdlist;
+};
+
+
+struct nredir {
+      int type;
+      union node *n;
+      union node *redirect;
+};
+
+
+struct nif {
+      int type;
+      union node *test;
+      union node *ifpart;
+      union node *elsepart;
+};
+
+
+struct nfor {
+      int type;
+      union node *args;
+      union node *body;
+      char *var;
+};
+
+
+struct ncase {
+      int type;
+      union node *expr;
+      union node *cases;
+};
+
+
+struct nclist {
+      int type;
+      union node *next;
+      union node *pattern;
+      union node *body;
+};
+
+
+struct narg {
+      int type;
+      union node *next;
+      char *text;
+      struct nodelist *backquote;
+};
+
+
+struct nfile {
+      int type;
+      union node *next;
+      int fd;
+      union node *fname;
+      char *expfname;
+};
+
+
+struct ndup {
+      int type;
+      union node *next;
+      int fd;
+      int dupfd;
+      union node *vname;
+};
+
+
+struct nhere {
+      int type;
+      union node *next;
+      int fd;
+      union node *doc;
+};
+
+
+struct nnot {
+      int type;
+      union node *com;
+};
+
+
+union node {
+      int type;
+      struct nbinary nbinary;
+      struct ncmd ncmd;
+      struct npipe npipe;
+      struct nredir nredir;
+      struct nif nif;
+      struct nfor nfor;
+      struct ncase ncase;
+      struct nclist nclist;
+      struct narg narg;
+      struct nfile nfile;
+      struct ndup ndup;
+      struct nhere nhere;
+      struct nnot nnot;
+};
+
+
+struct nodelist {
+	struct nodelist *next;
+	union node *n;
+};
+
+
+union node *copyfunc(union node *);
+void freefunc(union node *);
Index: /tags/kBuild-0.1.4/src/kash/generated/token.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/generated/token.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/generated/token.h	(revision 1780)
@@ -0,0 +1,112 @@
+#define TEOF 0
+#define TNL 1
+#define TSEMI 2
+#define TBACKGND 3
+#define TAND 4
+#define TOR 5
+#define TPIPE 6
+#define TLP 7
+#define TRP 8
+#define TENDCASE 9
+#define TENDBQUOTE 10
+#define TREDIR 11
+#define TWORD 12
+#define TIF 13
+#define TTHEN 14
+#define TELSE 15
+#define TELIF 16
+#define TFI 17
+#define TWHILE 18
+#define TUNTIL 19
+#define TFOR 20
+#define TDO 21
+#define TDONE 22
+#define TBEGIN 23
+#define TEND 24
+#define TCASE 25
+#define TESAC 26
+#define TNOT 27
+
+/* Array indicating which tokens mark the end of a list */
+const char tokendlist[] = {
+	1,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	1,
+	1,
+	1,
+	0,
+	0,
+	0,
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	0,
+	1,
+	1,
+	0,
+	1,
+	0,
+	1,
+	0,
+};
+
+const char *const tokname[] = {
+	"end of file",
+	"newline",
+	"\";\"",
+	"\"&\"",
+	"\"&&\"",
+	"\"||\"",
+	"\"|\"",
+	"\"(\"",
+	"\")\"",
+	"\";;\"",
+	"\"`\"",
+	"redirection",
+	"word",
+	"\"if\"",
+	"\"then\"",
+	"\"else\"",
+	"\"elif\"",
+	"\"fi\"",
+	"\"while\"",
+	"\"until\"",
+	"\"for\"",
+	"\"do\"",
+	"\"done\"",
+	"\"{\"",
+	"\"}\"",
+	"\"case\"",
+	"\"esac\"",
+	"\"!\"",
+};
+
+#define KWDOFFSET 13
+
+const char *const parsekwd[] = {
+	"if",
+	"then",
+	"else",
+	"elif",
+	"fi",
+	"while",
+	"until",
+	"for",
+	"do",
+	"done",
+	"{",
+	"}",
+	"case",
+	"esac",
+	"!",
+	0
+};
Index: /tags/kBuild-0.1.4/src/kash/histedit.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/histedit.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/histedit.c	(revision 1780)
@@ -0,0 +1,546 @@
+/*	$NetBSD: histedit.c,v 1.36 2005/05/09 11:35:19 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)histedit.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: histedit.c,v 1.36 2005/05/09 11:35:19 christos Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Editline and history functions (and glue).
+ */
+#include "shell.h"
+#include "parser.h"
+#include "var.h"
+#include "options.h"
+#include "main.h"
+#include "output.h"
+#include "mystring.h"
+#include "myhistedit.h"
+#include "error.h"
+
+#ifndef SMALL
+#include "eval.h"
+#include "memalloc.h"
+
+#define MAXHISTLOOPS	4	/* max recursions through fc */
+#define DEFEDITOR	"ed"	/* default editor *should* be $EDITOR */
+
+History *hist;	/* history cookie */
+EditLine *el;	/* editline cookie */
+int displayhist;
+static FILE *el_in, *el_out;
+unsigned char _el_fn_complete(EditLine *, int);
+
+STATIC const char *fc_replace(const char *, char *, char *);
+
+#ifdef DEBUG
+extern FILE *tracefile;
+#endif
+
+/*
+ * Set history and editing status.  Called whenever the status may
+ * have changed (figures out what to do).
+ */
+void
+histedit(void)
+{
+	FILE *el_err;
+
+#define editing (Eflag(psh) || Vflag(psh))
+
+	if (iflag(psh)) {
+		if (!hist) {
+			/*
+			 * turn history on
+			 */
+			INTOFF;
+			hist = history_init();
+			INTON;
+
+			if (hist != NULL)
+				sethistsize(histsizeval());
+			else
+				out2str(psh, "sh: can't initialize history\n");
+		}
+		if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
+			/*
+			 * turn editing on
+			 */
+			char *term, *shname;
+
+			INTOFF;
+			if (el_in == NULL)
+				el_in = fdopen(0, "r");
+			if (el_out == NULL)
+				el_out = fdopen(2, "w");
+			if (el_in == NULL || el_out == NULL)
+				goto bad;
+			el_err = el_out;
+#if DEBUG
+			if (tracefile)
+				el_err = tracefile;
+#endif
+			term = lookupvar(psh, "TERM");
+			if (term)
+				setenv("TERM", term, 1);
+			else
+				unsetenv("TERM");
+			shname = psh->arg0;
+			if (shname[0] == '-')
+				shname++;
+			el = el_init(shname, el_in, el_out, el_err);
+			if (el != NULL) {
+				if (hist)
+					el_set(el, EL_HIST, history, hist);
+				el_set(el, EL_PROMPT, getprompt);
+				el_set(el, EL_SIGNAL, 1);
+				el_set(el, EL_ADDFN, "rl-complete",
+				    "ReadLine compatible completion function",
+				    _el_fn_complete);
+			} else {
+bad:
+				out2str(psh, "sh: can't initialize editing\n");
+			}
+			INTON;
+		} else if (!editing && el) {
+			INTOFF;
+			el_end(el);
+			el = NULL;
+			INTON;
+		}
+		if (el) {
+			if (Vflag(psh))
+				el_set(el, EL_EDITOR, "vi");
+			else if (Eflag(psh))
+				el_set(el, EL_EDITOR, "emacs");
+			el_set(el, EL_BIND, "^I",
+			    tabcomplete(psh) ? "rl-complete" : "ed-insert", NULL);
+			el_source(el, NULL);
+		}
+	} else {
+		INTOFF;
+		if (el) {	/* no editing if not interactive */
+			el_end(el);
+			el = NULL;
+		}
+		if (hist) {
+			history_end(hist);
+			hist = NULL;
+		}
+		INTON;
+	}
+}
+
+
+void
+sethistsize(shinstance *psh, const char *hs)
+{
+	int histsize;
+	HistEvent he;
+
+	if (hist != NULL) {
+		if (hs == NULL || *hs == '\0' ||
+		   (histsize = atoi(hs)) < 0)
+			histsize = 100;
+		history(hist, &he, H_SETSIZE, histsize);
+	}
+}
+
+void
+setterm(shinstance *psh, const char *term)
+{
+	if (el != NULL && term != NULL)
+		if (el_set(el, EL_TERMINAL, term) != 0) {
+			outfmt(psh->out2, "sh: Can't set terminal type %s\n", term);
+			outfmt(psh->out2, "sh: Using dumb terminal settings.\n");
+		}
+}
+
+int
+inputrc(argc, argv)
+	int argc;
+	char **argv;
+{
+	if (argc != 2) {
+		out2str(psh, "usage: inputrc file\n");
+		return 1;
+	}
+	if (el != NULL) {
+		if (el_source(el, argv[1])) {
+			out2str(psh, "inputrc: failed\n");
+			return 1;
+		} else
+			return 0;
+	} else {
+		out2str(psh, "sh: inputrc ignored, not editing\n");
+		return 1;
+	}
+}
+
+/*
+ *  This command is provided since POSIX decided to standardize
+ *  the Korn shell fc command.  Oh well...
+ */
+int
+histcmd(int argc, char **argv)
+{
+	int ch;
+	const char *editor = NULL;
+	HistEvent he;
+	int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
+	int i, retval;
+	const char *firststr, *laststr;
+	int first, last, direction;
+	char *pat = NULL, *repl;	/* ksh "fc old=new" crap */
+	static int active = 0;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	char editfile[MAXPATHLEN + 1];
+	FILE *efp;
+#ifdef __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &editor;
+	(void) &lflg;
+	(void) &nflg;
+	(void) &rflg;
+	(void) &sflg;
+	(void) &firststr;
+	(void) &laststr;
+	(void) &pat;
+	(void) &repl;
+	(void) &efp;
+	(void) &argc;
+	(void) &argv;
+#endif
+
+	if (hist == NULL)
+		error(psh, "history not active");
+
+	if (argc == 1)
+		error(psh, "missing history argument");
+
+	optreset = 1; optind = 1; /* initialize getopt */
+	while (not_fcnumber(argv[optind]) &&
+	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
+		switch ((char)ch) {
+		case 'e':
+			editor = optionarg;
+			break;
+		case 'l':
+			lflg = 1;
+			break;
+		case 'n':
+			nflg = 1;
+			break;
+		case 'r':
+			rflg = 1;
+			break;
+		case 's':
+			sflg = 1;
+			break;
+		case ':':
+			error(psh, "option -%c expects argument", optopt);
+			/* NOTREACHED */
+		case '?':
+		default:
+			error(psh, "unknown option: -%c", optopt);
+			/* NOTREACHED */
+		}
+	argc -= optind, argv += optind;
+
+	/*
+	 * If executing...
+	 */
+	if (lflg == 0 || editor || sflg) {
+		lflg = 0;	/* ignore */
+		editfile[0] = '\0';
+		/*
+		 * Catch interrupts to reset active counter and
+		 * cleanup temp files.
+		 */
+		if (setjmp(jmploc.loc)) {
+			active = 0;
+			if (*editfile)
+				unlink(editfile);
+			handler = savehandler;
+			longjmp(handler->loc, 1);
+		}
+		savehandler = handler;
+		handler = &jmploc;
+		if (++active > MAXHISTLOOPS) {
+			active = 0;
+			displayhist = 0;
+			error(psh, "called recursively too many times");
+		}
+		/*
+		 * Set editor.
+		 */
+		if (sflg == 0) {
+			if (editor == NULL &&
+			    (editor = bltinlookup(psh, "FCEDIT", 1)) == NULL &&
+			    (editor = bltinlookup(psh, "EDITOR", 1)) == NULL)
+				editor = DEFEDITOR;
+			if (editor[0] == '-' && editor[1] == '\0') {
+				sflg = 1;	/* no edit */
+				editor = NULL;
+			}
+		}
+	}
+
+	/*
+	 * If executing, parse [old=new] now
+	 */
+	if (lflg == 0 && argc > 0 &&
+	     ((repl = strchr(argv[0], '=')) != NULL)) {
+		pat = argv[0];
+		*repl++ = '\0';
+		argc--, argv++;
+	}
+	/*
+	 * determine [first] and [last]
+	 */
+	switch (argc) {
+	case 0:
+		firststr = lflg ? "-16" : "-1";
+		laststr = "-1";
+		break;
+	case 1:
+		firststr = argv[0];
+		laststr = lflg ? "-1" : argv[0];
+		break;
+	case 2:
+		firststr = argv[0];
+		laststr = argv[1];
+		break;
+	default:
+		error(psh, "too many args");
+		/* NOTREACHED */
+	}
+	/*
+	 * Turn into event numbers.
+	 */
+	first = str_to_event(firststr, 0);
+	last = str_to_event(laststr, 1);
+
+	if (rflg) {
+		i = last;
+		last = first;
+		first = i;
+	}
+	/*
+	 * XXX - this should not depend on the event numbers
+	 * always increasing.  Add sequence numbers or offset
+	 * to the history element in next (diskbased) release.
+	 */
+	direction = first < last ? H_PREV : H_NEXT;
+
+	/*
+	 * If editing, grab a temp file.
+	 */
+	if (editor) {
+		int fd;
+		INTOFF;		/* easier */
+		snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP);
+		if ((fd = mkstemp(editfile)) < 0)
+			error(psh, "can't create temporary file %s", editfile);
+		if ((efp = fdopen(fd, "w")) == NULL) {
+			shfile_close(&psh->fdtab, fd);
+			error(psh, "can't allocate stdio buffer for temp");
+		}
+	}
+
+	/*
+	 * Loop through selected history events.  If listing or executing,
+	 * do it now.  Otherwise, put into temp file and call the editor
+	 * after.
+	 *
+	 * The history interface needs rethinking, as the following
+	 * convolutions will demonstrate.
+	 */
+	history(hist, &he, H_FIRST);
+	retval = history(hist, &he, H_NEXT_EVENT, first);
+	for (;retval != -1; retval = history(hist, &he, direction)) {
+		if (lflg) {
+			if (!nflg)
+				out1fmt(psh, "%5d ", he.num);
+			out1str(psh, he.str);
+		} else {
+			const char *s = pat ?
+			   fc_replace(he.str, pat, repl) : he.str;
+
+			if (sflg) {
+				if (displayhist) {
+					out2str(psh, s);
+				}
+
+				evalstring(psh, strcpy(stalloc(psh, strlen(s) + 1), s), 0);
+				if (displayhist && hist) {
+					/*
+					 *  XXX what about recursive and
+					 *  relative histnums.
+					 */
+					history(hist, &he, H_ENTER, s);
+				}
+			} else
+				fputs(s, efp);
+		}
+		/*
+		 * At end?  (if we were to lose last, we'd sure be
+		 * messed up).
+		 */
+		if (he.num == last)
+			break;
+	}
+	if (editor) {
+		char *editcmd;
+
+		fclose(efp);
+		editcmd = stalloc(psh, strlen(editor) + strlen(editfile) + 2);
+		sprintf(editcmd, "%s %s", editor, editfile);
+		evalstring(psh, editcmd, 0);	/* XXX - should use no JC command */
+		INTON;
+		readcmdfile(psh, editfile);	/* XXX - should read back - quick tst */
+		unlink(editfile);
+	}
+
+	if (lflg == 0 && active > 0)
+		--active;
+	if (displayhist)
+		displayhist = 0;
+	return 0;
+}
+
+STATIC const char *
+fc_replace(const char *s, char *p, char *r)
+{
+	char *dest;
+	int plen = strlen(p);
+
+	STARTSTACKSTR(psh, dest);
+	while (*s) {
+		if (*s == *p && strncmp(s, p, plen) == 0) {
+			while (*r)
+				STPUTC(psh, *r++, dest);
+			s += plen;
+			*p = '\0';	/* so no more matches */
+		} else
+			STPUTC(psh, *s++, dest);
+	}
+	STACKSTRNUL(psh, dest);
+	dest = grabstackstr(psh, dest);
+
+	return (dest);
+}
+
+int
+not_fcnumber(char *s)
+{
+	if (s == NULL)
+		return 0;
+        if (*s == '-')
+                s++;
+	return (!is_number(s));
+}
+
+int
+str_to_event(const char *str, int last)
+{
+	HistEvent he;
+	const char *s = str;
+	int relative = 0;
+	int i, retval;
+
+	retval = history(hist, &he, H_FIRST);
+	switch (*s) {
+	case '-':
+		relative = 1;
+		/*FALLTHROUGH*/
+	case '+':
+		s++;
+	}
+	if (is_number(s)) {
+		i = atoi(s);
+		if (relative) {
+			while (retval != -1 && i--) {
+				retval = history(hist, &he, H_NEXT);
+			}
+			if (retval == -1)
+				retval = history(hist, &he, H_LAST);
+		} else {
+			retval = history(hist, &he, H_NEXT_EVENT, i);
+			if (retval == -1) {
+				/*
+				 * the notion of first and last is
+				 * backwards to that of the history package
+				 */
+				retval = history(hist, &he,
+						last ? H_FIRST : H_LAST);
+			}
+		}
+		if (retval == -1)
+			error(psh, "history number %s not found (internal error)",
+			       str);
+	} else {
+		/*
+		 * pattern
+		 */
+		retval = history(hist, &he, H_PREV_STR, str);
+		if (retval == -1)
+			error(psh, "history pattern not found: %s", str);
+	}
+	return (he.num);
+}
+#else /* SMALL */
+int
+histcmd(shinstance *psh, int argc, char **argv)
+{
+	error(psh, "not compiled with history support");
+	/* NOTREACHED */
+	return -1;
+}
+int
+inputrc(shinstance *psh, int argc, char **argv)
+{
+	error(psh, "not compiled with history support");
+	/* NOTREACHED */
+	return -1;
+}
+#endif /* SMALL */
Index: /tags/kBuild-0.1.4/src/kash/init.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/init.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/init.h	(revision 1780)
@@ -0,0 +1,39 @@
+/*	$NetBSD: init.h,v 1.10 2003/08/07 09:05:32 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)init.h	8.2 (Berkeley) 5/4/95
+ */
+
+void init(struct shinstance *);
+void reset(struct shinstance *);
+void initshellproc(struct shinstance *);
Index: /tags/kBuild-0.1.4/src/kash/input.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/input.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/input.c	(revision 1780)
@@ -0,0 +1,530 @@
+/*	$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
+#else
+__RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdio.h>	/* defines BUFSIZ */
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * This file implements the input routines used by the parser.
+ */
+
+#include "shell.h"
+#include "redir.h"
+#include "syntax.h"
+#include "input.h"
+#include "output.h"
+#include "options.h"
+#include "memalloc.h"
+#include "error.h"
+#include "alias.h"
+#include "parser.h"
+#include "myhistedit.h"
+#include "shinstance.h"
+
+#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
+
+//MKINIT
+//struct strpush {
+//	struct strpush *prev;	/* preceding string on stack */
+//	char *prevstring;
+//	int prevnleft;
+//	int prevlleft;
+//	struct alias *ap;	/* if push was associated with an alias */
+//};
+//
+///*
+// * The parsefile structure pointed to by the global variable parsefile
+// * contains information about the current file being read.
+// */
+//
+//MKINIT
+//struct parsefile {
+//	struct parsefile *prev;	/* preceding file on stack */
+//	int linno;		/* current line */
+//	int fd;			/* file descriptor (or -1 if string) */
+//	int nleft;		/* number of chars left in this line */
+//	int lleft;		/* number of chars left in this buffer */
+//	char *nextc;		/* next char in buffer */
+//	char *buf;		/* input buffer */
+//	struct strpush *strpush; /* for pushing strings at this level */
+//	struct strpush basestrpush; /* so pushing one is fast */
+//};
+//
+//
+//int plinno = 1;			/* input line number */
+//int parsenleft;			/* copy of parsefile->nleft */
+//MKINIT int parselleft;		/* copy of parsefile->lleft */
+//char *parsenextc;		/* copy of parsefile->nextc */
+//MKINIT struct parsefile basepf;	/* top level input file */
+//MKINIT char basebuf[BUFSIZ];	/* buffer for top level input file */
+//struct parsefile *parsefile = &basepf;	/* current input file */
+//int init_editline = 0;		/* editline library initialized? */
+//int whichprompt;		/* 1 == PS1, 2 == PS2 */
+//
+//#ifndef SMALL
+//EditLine *el;			/* cookie for editline package */
+//#endif
+
+STATIC void pushfile(shinstance *psh);
+static int preadfd(shinstance *psh);
+
+#ifdef mkinit
+INCLUDE <stdio.h>
+INCLUDE "input.h"
+INCLUDE "error.h"
+
+INIT {
+	psh->basepf.nextc = psh->basepf.buf = psh->basebuf;
+}
+
+RESET {
+	if (psh->exception != EXSHELLPROC)
+		psh->parselleft = psh->parsenleft = 0;	/* clear input buffer */
+	popallfiles(psh);
+}
+
+SHELLPROC {
+	popallfiles(psh);
+}
+#endif
+
+
+/*
+ * Read a line from the script.
+ */
+
+char *
+pfgets(shinstance *psh, char *line, int len)
+{
+	char *p = line;
+	int nleft = len;
+	int c;
+
+	while (--nleft > 0) {
+		c = pgetc_macro(psh);
+		if (c == PEOF) {
+			if (p == line)
+				return NULL;
+			break;
+		}
+		*p++ = c;
+		if (c == '\n')
+			break;
+	}
+	*p = '\0';
+	return line;
+}
+
+
+
+/*
+ * Read a character from the script, returning PEOF on end of file.
+ * Nul characters in the input are silently discarded.
+ */
+
+int
+pgetc(shinstance *psh)
+{
+	return pgetc_macro(psh);
+}
+
+
+static int
+preadfd(shinstance *psh)
+{
+	int nr;
+	char *buf = psh->parsefile->buf;
+	psh->parsenextc = buf;
+
+retry:
+#ifndef SMALL
+	if (psh->parsefile->fd == 0 && psh->el) {
+		static const char *rl_cp;
+		static int el_len;
+
+		if (rl_cp == NULL)
+			rl_cp = el_gets(psh->el, &el_len);
+		if (rl_cp == NULL)
+			nr = 0;
+		else {
+			nr = el_len;
+			if (nr > BUFSIZ - 8)
+				nr = BUFSIZ - 8;
+			memcpy(buf, rl_cp, nr);
+			if (nr != el_len) {
+				el_len -= nr;
+				rl_cp += nr;
+			} else
+				rl_cp = 0;
+		}
+
+	} else
+#endif
+		nr = shfile_read(&psh->fdtab, psh->parsefile->fd, buf, BUFSIZ - 8);
+
+
+	if (nr <= 0) {
+                if (nr < 0) {
+                        if (errno == EINTR)
+                                goto retry;
+                        if (psh->parsefile->fd == 0 && errno == EWOULDBLOCK) {
+                                int flags = shfile_fcntl(&psh->fdtab, 0, F_GETFL, 0);
+                                if (flags >= 0 && flags & O_NONBLOCK) {
+                                        flags &=~ O_NONBLOCK;
+                                        if (shfile_fcntl(&psh->fdtab, 0, F_SETFL, flags) >= 0) {
+						out2str(psh, "sh: turning off NDELAY mode\n");
+                                                goto retry;
+                                        }
+                                }
+                        }
+                }
+                nr = -1;
+	}
+	return nr;
+}
+
+/*
+ * Refill the input buffer and return the next input character:
+ *
+ * 1) If a string was pushed back on the input, pop it;
+ * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
+ *    from a string so we can't refill the buffer, return EOF.
+ * 3) If the is more stuff in this buffer, use it else call read to fill it.
+ * 4) Process input up to the next newline, deleting nul characters.
+ */
+
+int
+preadbuffer(shinstance *psh)
+{
+	char *p, *q;
+	int more;
+	int something;
+	char savec;
+
+	if (psh->parsefile->strpush) {
+		popstring(psh);
+		if (--psh->parsenleft >= 0)
+			return (*psh->parsenextc++);
+	}
+	if (psh->parsenleft == EOF_NLEFT || psh->parsefile->buf == NULL)
+		return PEOF;
+	flushout(&psh->output);
+	flushout(&psh->errout);
+
+again:
+	if (psh->parselleft <= 0) {
+		if ((psh->parselleft = preadfd(psh)) == -1) {
+			psh->parselleft = psh->parsenleft = EOF_NLEFT;
+			return PEOF;
+		}
+	}
+
+	q = p = psh->parsenextc;
+
+	/* delete nul characters */
+	something = 0;
+	for (more = 1; more;) {
+		switch (*p) {
+		case '\0':
+			p++;	/* Skip nul */
+			goto check;
+
+		case '\t':
+		case ' ':
+			break;
+
+		case '\n':
+			psh->parsenleft = (int)(q - psh->parsenextc);
+			more = 0; /* Stop processing here */
+			break;
+
+		default:
+			something = 1;
+			break;
+		}
+
+		*q++ = *p++;
+check:
+		if (--psh->parselleft <= 0) {
+			psh->parsenleft = (int)(q - psh->parsenextc - 1);
+			if (psh->parsenleft < 0)
+				goto again;
+			*q = '\0';
+			more = 0;
+		}
+	}
+
+	savec = *q;
+	*q = '\0';
+
+#ifndef SMALL
+	if (psh->parsefile->fd == 0 && hist && something) {
+		HistEvent he;
+		INTOFF;
+		history(hist, &he, psh->whichprompt == 1? H_ENTER : H_APPEND,
+		    psh->parsenextc);
+		INTON;
+	}
+#endif
+
+	if (vflag(psh)) {
+		out2str(psh, psh->parsenextc);
+		flushout(psh->out2);
+	}
+
+	*q = savec;
+
+	return *psh->parsenextc++;
+}
+
+/*
+ * Undo the last call to pgetc.  Only one character may be pushed back.
+ * PEOF may be pushed back.
+ */
+
+void
+pungetc(shinstance *psh)
+{
+	psh->parsenleft++;
+	psh->parsenextc--;
+}
+
+/*
+ * Push a string back onto the input at this current parsefile level.
+ * We handle aliases this way.
+ */
+void
+pushstring(shinstance *psh, char *s, size_t len, void *ap)
+{
+	struct strpush *sp;
+
+	INTOFF;
+/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
+	if (psh->parsefile->strpush) {
+		sp = ckmalloc(sizeof (struct strpush));
+		sp->prev = psh->parsefile->strpush;
+		psh->parsefile->strpush = sp;
+	} else
+		sp = psh->parsefile->strpush = &(psh->parsefile->basestrpush);
+	sp->prevstring = psh->parsenextc;
+	sp->prevnleft = psh->parsenleft;
+	sp->prevlleft = psh->parselleft;
+	sp->ap = (struct alias *)ap;
+	if (ap)
+		((struct alias *)ap)->flag |= ALIASINUSE;
+	psh->parsenextc = s;
+	psh->parsenleft = (int)len;
+	INTON;
+}
+
+void
+popstring(shinstance *psh)
+{
+	struct strpush *sp = psh->parsefile->strpush;
+
+	INTOFF;
+	psh->parsenextc = sp->prevstring;
+	psh->parsenleft = sp->prevnleft;
+	psh->parselleft = sp->prevlleft;
+/*dprintf("*** calling popstring: restoring to '%s'\n", psh->parsenextc);*/
+	if (sp->ap)
+		sp->ap->flag &= ~ALIASINUSE;
+	psh->parsefile->strpush = sp->prev;
+	if (sp != &(psh->parsefile->basestrpush))
+		ckfree(sp);
+	INTON;
+}
+
+/*
+ * Set the input to take input from a file.  If push is set, push the
+ * old input onto the stack first.
+ */
+
+void
+setinputfile(shinstance *psh, const char *fname, int push)
+{
+	int fd;
+	int fd2;
+
+	INTOFF;
+/** @todo shfile fixme */
+	if ((fd = shfile_open(&psh->fdtab, fname, O_RDONLY, 0)) < 0)
+		error(psh, "Can't open %s", fname);
+	if (fd < 10) {
+		fd2 = copyfd(psh, fd, 10);
+		shfile_close(&psh->fdtab, fd);
+		if (fd2 < 0)
+			error(psh, "Out of file descriptors");
+		fd = fd2;
+	}
+	setinputfd(psh, fd, push);
+	INTON;
+}
+
+
+/*
+ * Like setinputfile, but takes an open file descriptor.  Call this with
+ * interrupts off.
+ */
+
+void
+setinputfd(shinstance *psh, int fd, int push)
+{
+	(void) shfile_fcntl(&psh->fdtab, fd, F_SETFD, FD_CLOEXEC);
+	if (push) {
+		pushfile(psh);
+		psh->parsefile->buf = ckmalloc(BUFSIZ);
+	}
+	if (psh->parsefile->fd > 0)
+		shfile_close(&psh->fdtab, psh->parsefile->fd);
+	psh->parsefile->fd = fd;
+	if (psh->parsefile->buf == NULL)
+		psh->parsefile->buf = ckmalloc(BUFSIZ);
+	psh->parselleft = psh->parsenleft = 0;
+	psh->plinno = 1;
+}
+
+
+/*
+ * Like setinputfile, but takes input from a string.
+ */
+
+void
+setinputstring(shinstance *psh, char *string, int push)
+{
+	INTOFF;
+	if (push)
+		pushfile(psh);
+	psh->parsenextc = string;
+	psh->parselleft = psh->parsenleft = (int)strlen(string);
+	psh->parsefile->buf = NULL;
+	psh->plinno = 1;
+	INTON;
+}
+
+
+
+/*
+ * To handle the "." command, a stack of input files is used.  Pushfile
+ * adds a new entry to the stack and popfile restores the previous level.
+ */
+
+STATIC void
+pushfile(shinstance *psh)
+{
+	struct parsefile *pf;
+
+	psh->parsefile->nleft = psh->parsenleft;
+	psh->parsefile->lleft = psh->parselleft;
+	psh->parsefile->nextc = psh->parsenextc;
+	psh->parsefile->linno = psh->plinno;
+	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
+	pf->prev = psh->parsefile;
+	pf->fd = -1;
+	pf->strpush = NULL;
+	pf->basestrpush.prev = NULL;
+	psh->parsefile = pf;
+}
+
+
+void
+popfile(shinstance *psh)
+{
+	struct parsefile *pf = psh->parsefile;
+
+	INTOFF;
+	if (pf->fd >= 0)
+		shfile_close(&psh->fdtab, pf->fd);
+	if (pf->buf)
+		ckfree(pf->buf);
+	while (pf->strpush)
+		popstring(psh);
+	psh->parsefile = pf->prev;
+	ckfree(pf);
+	psh->parsenleft = psh->parsefile->nleft;
+	psh->parselleft = psh->parsefile->lleft;
+	psh->parsenextc = psh->parsefile->nextc;
+	psh->plinno = psh->parsefile->linno;
+	INTON;
+}
+
+
+/*
+ * Return to top level.
+ */
+
+void
+popallfiles(shinstance *psh)
+{
+	while (psh->parsefile != &psh->basepf)
+		popfile(psh);
+}
+
+
+
+/*
+ * Close the file(s) that the shell is reading commands from.  Called
+ * after a fork is done.
+ *
+ * Takes one arg, vfork, which tells it to not modify its global vars
+ * as it is still running in the parent.
+ *
+ * This code is (probably) unnecessary as the 'close on exec' flag is
+ * set and should be enough.  In the vfork case it is definitely wrong
+ * to close the fds as another fork() may be done later to feed data
+ * from a 'here' document into a pipe and we don't want to close the
+ * pipe!
+ */
+
+void
+closescript(shinstance *psh, int vforked)
+{
+	if (vforked)
+		return;
+	popallfiles(psh);
+	if (psh->parsefile->fd > 0) {
+		shfile_close(&psh->fdtab, psh->parsefile->fd);
+		psh->parsefile->fd = 0;
+	}
+}
Index: /tags/kBuild-0.1.4/src/kash/input.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/input.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/input.h	(revision 1780)
@@ -0,0 +1,62 @@
+/*	$NetBSD: input.h,v 1.15 2003/08/07 09:05:33 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)input.h	8.2 (Berkeley) 5/4/95
+ */
+
+/* PEOF (the end of file marker) is defined in syntax.h */
+
+/*
+ * The input line number.  Input.c just defines this variable, and saves
+ * and restores it when files are pushed and popped.  The user of this
+ * package must set its value.
+ */
+//extern int plinno;
+//extern int parsenleft;		/* number of characters left in input buffer */
+//extern char *parsenextc;	/* next character in input buffer */
+//extern int init_editline;	/* 0 == not setup, 1 == OK, -1 == failed */
+
+char *pfgets(struct shinstance *, char *, int);
+int pgetc(struct shinstance *);
+int preadbuffer(struct shinstance *);
+void pungetc(struct shinstance *);
+void pushstring(struct shinstance *, char *, size_t, void *);
+void popstring(struct shinstance *);
+void setinputfile(struct shinstance *, const char *, int);
+void setinputfd(struct shinstance *, int, int);
+void setinputstring(struct shinstance *, char *, int);
+void popfile(struct shinstance *);
+void popallfiles(struct shinstance *);
+void closescript(struct shinstance *, int);
+
+#define pgetc_macro(psh)	(--(psh)->parsenleft >= 0? *(psh)->parsenextc++ : preadbuffer(psh))
Index: /tags/kBuild-0.1.4/src/kash/jobs.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/jobs.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/jobs.c	(revision 1780)
@@ -0,0 +1,1364 @@
+/*	$NetBSD: jobs.c,v 1.63 2005/06/01 15:41:19 lukem Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: jobs.c,v 1.63 2005/06/01 15:41:19 lukem Exp $");
+#endif /* not lint */
+#endif
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "shell.h"
+#if JOBS && !defined(_MSC_VER)
+# include <termios.h>
+#endif
+#include "redir.h"
+#include "show.h"
+#include "main.h"
+#include "parser.h"
+#include "nodes.h"
+#include "jobs.h"
+#include "options.h"
+#include "trap.h"
+#include "syntax.h"
+#include "input.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "shinstance.h"
+
+//static struct job *jobtab;		/* array of jobs */
+//static int njobs;			/* size of array */
+//static int jobs_invalid;		/* set in child */
+//MKINIT pid_t backgndpid = -1;	/* pid of last background process */
+#if JOBS
+//int initialpgrp;		/* pgrp of shell on invocation */
+//static int curjob = -1;		/* current job */
+#endif
+//static int ttyfd = -1;
+
+STATIC void restartjob(shinstance *, struct job *);
+STATIC void freejob(shinstance *, struct job *);
+STATIC struct job *getjob(shinstance *, const char *, int);
+STATIC int dowait(shinstance *, int, struct job *);
+STATIC int waitproc(shinstance *, int, struct job *, int *);
+STATIC void cmdtxt(shinstance *, union node *);
+STATIC void cmdlist(shinstance *, union node *, int);
+STATIC void cmdputs(shinstance *, const char *);
+
+
+/*
+ * Turn job control on and off.
+ *
+ * Note:  This code assumes that the third arg to ioctl is a character
+ * pointer, which is true on Berkeley systems but not System V.  Since
+ * System V doesn't have job control yet, this isn't a problem now.
+ */
+
+//MKINIT int jobctl;
+
+void
+setjobctl(shinstance *psh, int on)
+{
+	if (on == psh->jobctl || psh->rootshell == 0)
+		return;
+	if (on) {
+		int err;
+		int i;
+		if (psh->ttyfd != -1)
+			shfile_close(&psh->fdtab, psh->ttyfd);
+		if ((psh->ttyfd = shfile_open(&psh->fdtab, "/dev/tty", O_RDWR, 0)) == -1) {
+			for (i = 0; i < 3; i++) {
+				if (shfile_isatty(&psh->fdtab, i)
+				 && (psh->ttyfd = shfile_dup(&psh->fdtab, i)) != -1)
+					break;
+			}
+			if (i == 3)
+				goto out;
+		}
+		/* Move to a high fd */
+		for (i = 10; i > 2; i--) {
+			if ((err = shfile_fcntl(&psh->fdtab, psh->ttyfd, F_DUPFD, (1 << i) - 1)) != -1)
+				break;
+		}
+		if (err != -1) {
+			shfile_close(&psh->fdtab, psh->ttyfd);
+			psh->ttyfd = err;
+		}
+                err = shfile_cloexec(&psh->fdtab, psh->ttyfd, 1);
+		if (err == -1) {
+			shfile_close(&psh->fdtab, psh->ttyfd);
+			psh->ttyfd = -1;
+			goto out;
+		}
+		do { /* while we are in the background */
+			if ((psh->initialpgrp = sh_tcgetpgrp(psh, psh->ttyfd)) < 0) {
+out:
+				out2str(psh, "sh: can't access tty; job control turned off\n");
+				mflag(psh) = 0;
+				return;
+			}
+			if (psh->initialpgrp == -1)
+				psh->initialpgrp = sh_getpgrp(psh);
+			else if (psh->initialpgrp != sh_getpgrp(psh)) {
+				sh_killpg(psh, 0, SIGTTIN);
+				continue;
+			}
+		} while (0);
+
+		setsignal(psh, SIGTSTP, 0);
+		setsignal(psh, SIGTTOU, 0);
+		setsignal(psh, SIGTTIN, 0);
+		if (sh_getpgid(psh, 0) != psh->rootpid && sh_setpgid(psh, 0, psh->rootpid) == -1)
+			error(psh, "Cannot set process group (%s) at %d",
+			    strerror(errno), __LINE__);
+		if (sh_tcsetpgrp(psh, psh->ttyfd, psh->rootpid) == -1)
+			error(psh, "Cannot set tty process group (%s) at %d",
+			    strerror(errno), __LINE__);
+	} else { /* turning job control off */
+		if (sh_getpgid(psh, 0) != psh->initialpgrp && sh_setpgid(psh, 0, psh->initialpgrp) == -1)
+			error(psh, "Cannot set process group (%s) at %d",
+			    strerror(errno), __LINE__);
+		if (sh_tcsetpgrp(psh, psh->ttyfd, psh->initialpgrp) == -1)
+			error(psh, "Cannot set tty process group (%s) at %d",
+			    strerror(errno), __LINE__);
+		shfile_close(&psh->fdtab, psh->ttyfd);
+		psh->ttyfd = -1;
+		setsignal(psh, SIGTSTP, 0);
+		setsignal(psh, SIGTTOU, 0);
+		setsignal(psh, SIGTTIN, 0);
+	}
+	psh->jobctl = on;
+}
+
+
+#ifdef mkinit
+INCLUDE <stdlib.h>
+
+SHELLPROC {
+	psh->backgndpid = -1;
+#if JOBS
+	psh->jobctl = 0;
+#endif
+}
+
+#endif
+
+
+
+#if JOBS
+int
+fgcmd(shinstance *psh, int argc, char **argv)
+{
+	struct job *jp;
+	int i;
+	int status;
+
+	nextopt(psh, "");
+	jp = getjob(psh, *psh->argptr, 0);
+	if (jp->jobctl == 0)
+		error(psh, "job not created under job control");
+	out1fmt(psh, "%s", jp->ps[0].cmd);
+	for (i = 1; i < jp->nprocs; i++)
+		out1fmt(psh, " | %s", jp->ps[i].cmd );
+	out1c(psh, '\n');
+	output_flushall(psh);
+
+	for (i = 0; i < jp->nprocs; i++)
+	    if (sh_tcsetpgrp(psh, psh->ttyfd, jp->ps[i].pid) != -1)
+		    break;
+
+	if (i >= jp->nprocs) {
+		error(psh, "Cannot set tty process group (%s) at %d",
+		    strerror(errno), __LINE__);
+	}
+	restartjob(psh, jp);
+	INTOFF;
+	status = waitforjob(psh, jp);
+	INTON;
+	return status;
+}
+
+static void
+set_curjob(shinstance *psh, struct job *jp, int mode)
+{
+	struct job *jp1, *jp2;
+	int i, ji;
+
+	ji = (int)(jp - psh->jobtab);
+
+	/* first remove from list */
+	if (ji == psh->curjob)
+		psh->curjob = jp->prev_job;
+	else {
+		for (i = 0; i < psh->njobs; i++) {
+			if (psh->jobtab[i].prev_job != ji)
+				continue;
+			psh->jobtab[i].prev_job = jp->prev_job;
+			break;
+		}
+	}
+
+	/* Then re-insert in correct position */
+	switch (mode) {
+	case 0:	/* job being deleted */
+		jp->prev_job = -1;
+		break;
+	case 1:	/* newly created job or backgrounded job,
+		   put after all stopped jobs. */
+		if (psh->curjob != -1 && psh->jobtab[psh->curjob].state == JOBSTOPPED) {
+			for (jp1 = psh->jobtab + psh->curjob; ; jp1 = jp2) {
+				if (jp1->prev_job == -1)
+					break;
+				jp2 = psh->jobtab + jp1->prev_job;
+				if (jp2->state != JOBSTOPPED)
+					break;
+			}
+			jp->prev_job = jp1->prev_job;
+			jp1->prev_job = ji;
+			break;
+		}
+		/* FALLTHROUGH */
+	case 2:	/* newly stopped job - becomes psh->curjob */
+		jp->prev_job = psh->curjob;
+		psh->curjob = ji;
+		break;
+	}
+}
+
+int
+bgcmd(shinstance *psh, int argc, char **argv)
+{
+	struct job *jp;
+	int i;
+
+	nextopt(psh, "");
+	do {
+		jp = getjob(psh, *psh->argptr, 0);
+		if (jp->jobctl == 0)
+			error(psh, "job not created under job control");
+		set_curjob(psh, jp, 1);
+		out1fmt(psh, "[%ld] %s", (long)(jp - psh->jobtab + 1), jp->ps[0].cmd);
+		for (i = 1; i < jp->nprocs; i++)
+			out1fmt(psh, " | %s", jp->ps[i].cmd );
+		out1c(psh, '\n');
+		output_flushall(psh);
+		restartjob(psh, jp);
+	} while (*psh->argptr && *++psh->argptr);
+	return 0;
+}
+
+
+STATIC void
+restartjob(shinstance *psh, struct job *jp)
+{
+	struct procstat *ps;
+	int i;
+
+	if (jp->state == JOBDONE)
+		return;
+	INTOFF;
+	for (i = 0; i < jp->nprocs; i++)
+		if (sh_killpg(psh, jp->ps[i].pid, SIGCONT) != -1)
+			break;
+	if (i >= jp->nprocs)
+		error(psh, "Cannot continue job (%s)", strerror(errno));
+	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
+		if (WIFSTOPPED(ps->status)) {
+			ps->status = -1;
+			jp->state = JOBRUNNING;
+		}
+	}
+	INTON;
+}
+#endif
+
+static void
+showjob(shinstance *psh, struct output *out, struct job *jp, int mode)
+{
+	int procno;
+	int st;
+	struct procstat *ps;
+	size_t col;
+	char s[64];
+
+#if JOBS
+	if (mode & SHOW_PGID) {
+		/* just output process (group) id of pipeline */
+		outfmt(out, "%ld\n", (long)jp->ps->pid);
+		return;
+	}
+#endif
+
+	procno = jp->nprocs;
+	if (!procno)
+		return;
+
+	if (mode & SHOW_PID)
+		mode |= SHOW_MULTILINE;
+
+	if ((procno > 1 && !(mode & SHOW_MULTILINE))
+	    || (mode & SHOW_SIGNALLED)) {
+		/* See if we have more than one status to report */
+		ps = jp->ps;
+		st = ps->status;
+		do {
+			int st1 = ps->status;
+			if (st1 != st)
+				/* yes - need multi-line output */
+				mode |= SHOW_MULTILINE;
+			if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1))
+				continue;
+			if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f)
+			    && st1 != SIGINT && st1 != SIGPIPE))
+				mode |= SHOW_ISSIG;
+
+		} while (ps++, --procno);
+		procno = jp->nprocs;
+	}
+
+	if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) {
+		if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) {
+			TRACE((psh, "showjob: freeing job %d\n", jp - psh->jobtab + 1));
+			freejob(psh, jp);
+		}
+		return;
+	}
+
+	for (ps = jp->ps; --procno >= 0; ps++) {	/* for each process */
+		if (ps == jp->ps)
+			fmtstr(s, 16, "[%ld] %c ",
+				(long)(jp - psh->jobtab + 1),
+#if JOBS
+				jp == psh->jobtab + psh->curjob ? '+' :
+				psh->curjob != -1 && jp == psh->jobtab +
+					    psh->jobtab[psh->curjob].prev_job ? '-' :
+#endif
+				' ');
+		else
+			fmtstr(s, 16, "      " );
+		col = strlen(s);
+		if (mode & SHOW_PID) {
+			fmtstr(s + col, 16, "%ld ", (long)ps->pid);
+			     col += strlen(s + col);
+		}
+		if (ps->status == -1) {
+			scopy("Running", s + col);
+		} else if (WIFEXITED(ps->status)) {
+			st = WEXITSTATUS(ps->status);
+			if (st)
+				fmtstr(s + col, 16, "Done(%d)", st);
+			else
+				fmtstr(s + col, 16, "Done");
+		} else {
+#if JOBS
+			if (WIFSTOPPED(ps->status))
+				st = WSTOPSIG(ps->status);
+			else /* WIFSIGNALED(ps->status) */
+#endif
+				st = WTERMSIG(ps->status);
+			st &= 0x7f;
+			if (st < NSIG && sys_siglist[st])
+				scopyn(sys_siglist[st], s + col, 32);
+			else
+				fmtstr(s + col, 16, "Signal %d", st);
+			if (WCOREDUMP(ps->status)) {
+				col += strlen(s + col);
+				scopyn(" (core dumped)", s + col,  64 - col);
+			}
+		}
+		col += strlen(s + col);
+		outstr(s, out);
+		do {
+			outc(' ', out);
+			col++;
+		} while (col < 30);
+		outstr(ps->cmd, out);
+		if (mode & SHOW_MULTILINE) {
+			if (procno > 0) {
+				outc(' ', out);
+				outc('|', out);
+			}
+		} else {
+			while (--procno >= 0)
+				outfmt(out, " | %s", (++ps)->cmd );
+		}
+		outc('\n', out);
+	}
+	flushout(out);
+	jp->changed = 0;
+	if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE))
+		freejob(psh, jp);
+}
+
+
+int
+jobscmd(shinstance *psh, int argc, char **argv)
+{
+	int mode, m;
+	int sv = psh->jobs_invalid;
+
+	psh->jobs_invalid = 0;
+	mode = 0;
+	while ((m = nextopt(psh, "lp")))
+		if (m == 'l')
+			mode = SHOW_PID;
+		else
+			mode = SHOW_PGID;
+	if (*psh->argptr)
+		do
+			showjob(psh, psh->out1, getjob(psh, *psh->argptr,0), mode);
+		while (*++psh->argptr);
+	else
+		showjobs(psh, psh->out1, mode);
+	psh->jobs_invalid = sv;
+	return 0;
+}
+
+
+/*
+ * Print a list of jobs.  If "change" is nonzero, only print jobs whose
+ * statuses have changed since the last call to showjobs.
+ *
+ * If the shell is interrupted in the process of creating a job, the
+ * result may be a job structure containing zero processes.  Such structures
+ * will be freed here.
+ */
+
+void
+showjobs(shinstance *psh, struct output *out, int mode)
+{
+	int jobno;
+	struct job *jp;
+	int silent = 0, gotpid;
+
+	TRACE((psh, "showjobs(%x) called\n", mode));
+
+	/* If not even one one job changed, there is nothing to do */
+	gotpid = dowait(psh, 0, NULL);
+	while (dowait(psh, 0, NULL) > 0)
+		continue;
+#ifdef JOBS
+	/*
+	 * Check if we are not in our foreground group, and if not
+	 * put us in it.
+	 */
+	if (mflag(psh) && gotpid != -1 && sh_tcgetpgrp(psh, psh->ttyfd) != sh_getpid(psh)) {
+		if (sh_tcsetpgrp(psh, psh->ttyfd, sh_getpid(psh)) == -1)
+			error(psh, "Cannot set tty process group (%s) at %d",
+			    strerror(errno), __LINE__);
+		TRACE((psh, "repaired tty process group\n"));
+		silent = 1;
+	}
+#endif
+	if (psh->jobs_invalid)
+		return;
+
+	for (jobno = 1, jp = psh->jobtab ; jobno <= psh->njobs ; jobno++, jp++) {
+		if (!jp->used)
+			continue;
+		if (jp->nprocs == 0) {
+			freejob(psh, jp);
+			continue;
+		}
+		if ((mode & SHOW_CHANGED) && !jp->changed)
+			continue;
+		if (silent && jp->changed) {
+			jp->changed = 0;
+			continue;
+		}
+		showjob(psh, out, jp, mode);
+	}
+}
+
+/*
+ * Mark a job structure as unused.
+ */
+
+STATIC void
+freejob(shinstance *psh, struct job *jp)
+{
+	INTOFF;
+	if (jp->ps != &jp->ps0) {
+		ckfree(jp->ps);
+		jp->ps = &jp->ps0;
+	}
+	jp->nprocs = 0;
+	jp->used = 0;
+#if JOBS
+	set_curjob(psh, jp, 0);
+#endif
+	INTON;
+}
+
+
+
+int
+waitcmd(shinstance *psh, int argc, char **argv)
+{
+	struct job *job;
+	int status, retval;
+	struct job *jp;
+
+	nextopt(psh, "");
+
+	if (!*psh->argptr) {
+		/* wait for all jobs */
+		jp = psh->jobtab;
+		if (psh->jobs_invalid)
+			return 0;
+		for (;;) {
+			if (jp >= psh->jobtab + psh->njobs) {
+				/* no running procs */
+				return 0;
+			}
+			if (!jp->used || jp->state != JOBRUNNING) {
+				jp++;
+				continue;
+			}
+			if (dowait(psh, 1, (struct job *)NULL) == -1)
+			       return 128 + SIGINT;
+			jp = psh->jobtab;
+		}
+	}
+
+	retval = 127;		/* XXXGCC: -Wuninitialized */
+	for (; *psh->argptr; psh->argptr++) {
+		job = getjob(psh, *psh->argptr, 1);
+		if (!job) {
+			retval = 127;
+			continue;
+		}
+		/* loop until process terminated or stopped */
+		while (job->state == JOBRUNNING) {
+			if (dowait(psh, 1, (struct job *)NULL) == -1)
+			       return 128 + SIGINT;
+		}
+		status = job->ps[job->nprocs].status;
+		if (WIFEXITED(status))
+			retval = WEXITSTATUS(status);
+#if JOBS
+		else if (WIFSTOPPED(status))
+			retval = WSTOPSIG(status) + 128;
+#endif
+		else {
+			/* XXX: limits number of signals */
+			retval = WTERMSIG(status) + 128;
+		}
+		if (!iflag(psh))
+			freejob(psh, job);
+	}
+	return retval;
+}
+
+
+
+int
+jobidcmd(shinstance *psh, int argc, char **argv)
+{
+	struct job *jp;
+	int i;
+
+	nextopt(psh, "");
+	jp = getjob(psh, *psh->argptr, 0);
+	for (i = 0 ; i < jp->nprocs ; ) {
+		out1fmt(psh, "%ld", (long)jp->ps[i].pid);
+		out1c(psh, ++i < jp->nprocs ? ' ' : '\n');
+	}
+	return 0;
+}
+
+int
+getjobpgrp(shinstance *psh, const char *name)
+{
+	struct job *jp;
+
+	jp = getjob(psh, name, 1);
+	if (jp == 0)
+		return 0;
+	return -jp->ps[0].pid;
+}
+
+/*
+ * Convert a job name to a job structure.
+ */
+
+STATIC struct job *
+getjob(shinstance *psh, const char *name, int noerror)
+{
+	int jobno = -1;
+	struct job *jp;
+	int pid;
+	int i;
+	const char *err_msg = "No such job: %s";
+
+	if (name == NULL) {
+#if JOBS
+		jobno = psh->curjob;
+#endif
+		err_msg = "No current job";
+	} else if (name[0] == '%') {
+		if (is_number(name + 1)) {
+			jobno = number(psh, name + 1) - 1;
+		} else if (!name[2]) {
+			switch (name[1]) {
+#if JOBS
+			case 0:
+			case '+':
+			case '%':
+				jobno = psh->curjob;
+				err_msg = "No current job";
+				break;
+			case '-':
+				jobno = psh->curjob;
+				if (jobno != -1)
+					jobno = psh->jobtab[jobno].prev_job;
+				err_msg = "No previous job";
+				break;
+#endif
+			default:
+				goto check_pattern;
+			}
+		} else {
+			struct job *found;
+    check_pattern:
+			found = NULL;
+			for (jp = psh->jobtab, i = psh->njobs ; --i >= 0 ; jp++) {
+				if (!jp->used || jp->nprocs <= 0)
+					continue;
+				if ((name[1] == '?'
+					&& strstr(jp->ps[0].cmd, name + 2))
+				    || prefix(name + 1, jp->ps[0].cmd)) {
+					if (found) {
+						err_msg = "%s: ambiguous";
+						found = 0;
+						break;
+					}
+					found = jp;
+				}
+			}
+			if (found)
+				return found;
+		}
+
+	} else if (is_number(name)) {
+		pid = number(psh, name);
+		for (jp = psh->jobtab, i = psh->njobs ; --i >= 0 ; jp++) {
+			if (jp->used && jp->nprocs > 0
+			 && jp->ps[jp->nprocs - 1].pid == pid)
+				return jp;
+		}
+	}
+
+	if (!psh->jobs_invalid && jobno >= 0 && jobno < psh->njobs) {
+		jp = psh->jobtab + jobno;
+		if (jp->used)
+			return jp;
+	}
+	if (!noerror)
+		error(psh, err_msg, name);
+	return 0;
+}
+
+
+
+/*
+ * Return a new job structure,
+ */
+
+struct job *
+makejob(shinstance *psh, union node *node, int nprocs)
+{
+	int i;
+	struct job *jp;
+
+	if (psh->jobs_invalid) {
+		for (i = psh->njobs, jp = psh->jobtab ; --i >= 0 ; jp++) {
+			if (jp->used)
+				freejob(psh, jp);
+		}
+		psh->jobs_invalid = 0;
+	}
+
+	for (i = psh->njobs, jp = psh->jobtab ; ; jp++) {
+		if (--i < 0) {
+			INTOFF;
+			if (psh->njobs == 0) {
+				psh->jobtab = ckmalloc(4 * sizeof psh->jobtab[0]);
+			} else {
+				jp = ckmalloc((psh->njobs + 4) * sizeof psh->jobtab[0]);
+				memcpy(jp, psh->jobtab, psh->njobs * sizeof jp[0]);
+				/* Relocate `ps' pointers */
+				for (i = 0; i < psh->njobs; i++)
+					if (jp[i].ps == &psh->jobtab[i].ps0)
+						jp[i].ps = &jp[i].ps0;
+				ckfree(psh->jobtab);
+				psh->jobtab = jp;
+			}
+			jp = psh->jobtab + psh->njobs;
+			for (i = 4 ; --i >= 0 ; psh->jobtab[psh->njobs++].used = 0);
+			INTON;
+			break;
+		}
+		if (jp->used == 0)
+			break;
+	}
+	INTOFF;
+	jp->state = JOBRUNNING;
+	jp->used = 1;
+	jp->changed = 0;
+	jp->nprocs = 0;
+#if JOBS
+	jp->jobctl = psh->jobctl;
+	set_curjob(psh, jp, 1);
+#endif
+	if (nprocs > 1) {
+		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
+	} else {
+		jp->ps = &jp->ps0;
+	}
+	INTON;
+	TRACE((psh, "makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
+	       jp - psh->jobtab + 1));
+	return jp;
+}
+
+
+/*
+ * Fork off a subshell.  If we are doing job control, give the subshell its
+ * own process group.  Jp is a job structure that the job is to be added to.
+ * N is the command that will be evaluated by the child.  Both jp and n may
+ * be NULL.  The mode parameter can be one of the following:
+ *	FORK_FG - Fork off a foreground process.
+ *	FORK_BG - Fork off a background process.
+ *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
+ *		     process group even if job control is on.
+ *
+ * When job control is turned off, background processes have their standard
+ * input redirected to /dev/null (except for the second and later processes
+ * in a pipeline).
+ */
+
+int
+forkshell(shinstance *psh, struct job *jp, union node *n, int mode)
+{
+	int pid;
+
+	TRACE((psh, "forkshell(%%%d, %p, %d) called\n", jp - psh->jobtab, n, mode));
+	switch ((pid = sh_fork(psh))) {
+	case -1:
+		TRACE((psh, "Fork failed, errno=%d\n", errno));
+		INTON;
+		error(psh, "Cannot fork");
+		return -1; /* won't get here */
+	case 0:
+		forkchild(psh, jp, n, mode, 0);
+		return 0;
+	default:
+		return forkparent(psh, jp, n, mode, pid);
+	}
+}
+
+int
+forkparent(shinstance *psh, struct job *jp, union node *n, int mode, pid_t pid)
+{
+	int pgrp;
+
+	if (psh->rootshell && mode != FORK_NOJOB && mflag(psh)) {
+		if (jp == NULL || jp->nprocs == 0)
+			pgrp = pid;
+		else
+			pgrp = jp->ps[0].pid;
+		/* This can fail because we are doing it in the child also */
+		(void)sh_setpgid(psh, pid, pgrp);
+	}
+	if (mode == FORK_BG)
+		psh->backgndpid = pid;		/* set $! */
+	if (jp) {
+		struct procstat *ps = &jp->ps[jp->nprocs++];
+		ps->pid = pid;
+		ps->status = -1;
+		ps->cmd[0] = 0;
+		if (/* iflag && rootshell && */ n)
+			commandtext(psh, ps, n);
+	}
+	TRACE((psh, "In parent shell:  child = %d\n", pid));
+	return pid;
+}
+
+void
+forkchild(shinstance *psh, struct job *jp, union node *n, int mode, int vforked)
+{
+	int wasroot;
+	int pgrp;
+	const char *devnull = _PATH_DEVNULL;
+	const char *nullerr = "Can't open %s";
+
+	wasroot = psh->rootshell;
+	TRACE((psh, "Child shell %d\n", sh_getpid(psh)));
+	if (!vforked)
+		psh->rootshell = 0;
+
+	closescript(psh, vforked);
+	clear_traps(psh, vforked);
+#if JOBS
+	if (!vforked)
+		psh->jobctl = 0;		/* do job control only in root shell */
+	if (wasroot && mode != FORK_NOJOB && mflag(psh)) {
+		if (jp == NULL || jp->nprocs == 0)
+			pgrp = sh_getpid(psh);
+		else
+			pgrp = jp->ps[0].pid;
+		/* This can fail because we are doing it in the parent also */
+		(void)sh_setpgid(psh, 0, pgrp);
+		if (mode == FORK_FG) {
+			if (sh_tcsetpgrp(psh, psh->ttyfd, pgrp) == -1)
+				error(psh, "Cannot set tty process group (%s) at %d",
+				    strerror(errno), __LINE__);
+		}
+		setsignal(psh, SIGTSTP, vforked);
+		setsignal(psh, SIGTTOU, vforked);
+	} else if (mode == FORK_BG) {
+		ignoresig(psh, SIGINT, vforked);
+		ignoresig(psh, SIGQUIT, vforked);
+		if ((jp == NULL || jp->nprocs == 0) &&
+		    ! fd0_redirected_p(psh)) {
+			shfile_close(&psh->fdtab, 0);
+			if (shfile_open(&psh->fdtab, devnull, O_RDONLY, 0) != 0)
+				error(psh, nullerr, devnull);
+		}
+	}
+#else
+	if (mode == FORK_BG) {
+		ignoresig(psh, SIGINT, vforked);
+		ignoresig(psh, SIGQUIT, vforked);
+		if ((jp == NULL || jp->nprocs == 0) &&
+		    ! fd0_redirected_p(psh)) {
+			shfile_close(&psh->fdtab, 0);
+			if (shfile_open(&psh->fdtab, devnull, O_RDONLY, 0) != 0)
+				error(psh, nullerr, devnull);
+		}
+	}
+#endif
+	if (wasroot && iflag(psh)) {
+		setsignal(psh, SIGINT, vforked);
+		setsignal(psh, SIGQUIT, vforked);
+		setsignal(psh, SIGTERM, vforked);
+	}
+
+	if (!vforked)
+		psh->jobs_invalid = 1;
+}
+
+/*
+ * Wait for job to finish.
+ *
+ * Under job control we have the problem that while a child process is
+ * running interrupts generated by the user are sent to the child but not
+ * to the shell.  This means that an infinite loop started by an inter-
+ * active user may be hard to kill.  With job control turned off, an
+ * interactive user may place an interactive program inside a loop.  If
+ * the interactive program catches interrupts, the user doesn't want
+ * these interrupts to also abort the loop.  The approach we take here
+ * is to have the shell ignore interrupt signals while waiting for a
+ * forground process to terminate, and then send itself an interrupt
+ * signal if the child process was terminated by an interrupt signal.
+ * Unfortunately, some programs want to do a bit of cleanup and then
+ * exit on interrupt; unless these processes terminate themselves by
+ * sending a signal to themselves (instead of calling exit) they will
+ * confuse this approach.
+ */
+
+int
+waitforjob(shinstance *psh, struct job *jp)
+{
+#if JOBS
+	int mypgrp = sh_getpgrp(psh);
+#endif
+	int status;
+	int st;
+
+	INTOFF;
+	TRACE((psh, "waitforjob(%%%d) called\n", jp - psh->jobtab + 1));
+	while (jp->state == JOBRUNNING) {
+		dowait(psh, 1, jp);
+	}
+#if JOBS
+	if (jp->jobctl) {
+		if (sh_tcsetpgrp(psh, psh->ttyfd, mypgrp) == -1)
+			error(psh, "Cannot set tty process group (%s) at %d",
+			    strerror(errno), __LINE__);
+	}
+	if (jp->state == JOBSTOPPED && psh->curjob != jp - psh->jobtab)
+		set_curjob(psh, jp, 2);
+#endif
+	status = jp->ps[jp->nprocs - 1].status;
+	/* convert to 8 bits */
+	if (WIFEXITED(status))
+		st = WEXITSTATUS(status);
+#if JOBS
+	else if (WIFSTOPPED(status))
+		st = WSTOPSIG(status) + 128;
+#endif
+	else
+		st = WTERMSIG(status) + 128;
+	TRACE((psh, "waitforjob: job %d, nproc %d, status %x, st %x\n",
+		jp - psh->jobtab + 1, jp->nprocs, status, st ));
+#if JOBS
+	if (jp->jobctl) {
+		/*
+		 * This is truly gross.
+		 * If we're doing job control, then we did a TIOCSPGRP which
+		 * caused us (the shell) to no longer be in the controlling
+		 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
+		 * intuit from the subprocess exit status whether a SIGINT
+		 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
+		 */
+		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
+			sh_raise_sigint(psh);/*raise(SIGINT);*/
+	}
+#endif
+	if (! JOBS || jp->state == JOBDONE)
+		freejob(psh, jp);
+	INTON;
+	return st;
+}
+
+
+
+/*
+ * Wait for a process to terminate.
+ */
+
+STATIC int
+dowait(shinstance *psh, int block, struct job *job)
+{
+	int pid;
+	int status;
+	struct procstat *sp;
+	struct job *jp;
+	struct job *thisjob;
+	int done;
+	int stopped;
+
+	TRACE((psh, "dowait(%d) called\n", block));
+	do {
+		pid = waitproc(psh, block, job, &status);
+		TRACE((psh, "wait returns pid %d, status %d\n", pid, status));
+	} while (pid == -1 && errno == EINTR && psh->gotsig[SIGINT - 1] == 0);
+	if (pid <= 0)
+		return pid;
+	INTOFF;
+	thisjob = NULL;
+	for (jp = psh->jobtab ; jp < psh->jobtab + psh->njobs ; jp++) {
+		if (jp->used) {
+			done = 1;
+			stopped = 1;
+			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
+				if (sp->pid == -1)
+					continue;
+				if (sp->pid == pid) {
+					TRACE((psh, "Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - psh->jobtab + 1, pid, sp->status, status));
+					sp->status = status;
+					thisjob = jp;
+				}
+				if (sp->status == -1)
+					stopped = 0;
+				else if (WIFSTOPPED(sp->status))
+					done = 0;
+			}
+			if (stopped) {		/* stopped or done */
+				int state = done ? JOBDONE : JOBSTOPPED;
+				if (jp->state != state) {
+					TRACE((psh, "Job %d: changing state from %d to %d\n", jp - psh->jobtab + 1, jp->state, state));
+					jp->state = state;
+#if JOBS
+					if (done)
+						set_curjob(psh, jp, 0);
+#endif
+				}
+			}
+		}
+	}
+
+	if (thisjob && thisjob->state != JOBRUNNING) {
+		int mode = 0;
+		if (!psh->rootshell || !iflag(psh))
+			mode = SHOW_SIGNALLED;
+		if (job == thisjob)
+			mode = SHOW_SIGNALLED | SHOW_NO_FREE;
+		if (mode)
+			showjob(psh, psh->out2, thisjob, mode);
+		else {
+			TRACE((psh, "Not printing status, rootshell=%d, job=%p\n",
+				psh->rootshell, job));
+			thisjob->changed = 1;
+		}
+	}
+
+	INTON;
+	return pid;
+}
+
+
+
+/*
+ * Do a wait system call.  If job control is compiled in, we accept
+ * stopped processes.  If block is zero, we return a value of zero
+ * rather than blocking.
+ */
+STATIC int
+waitproc(shinstance *psh, int block, struct job *jp, int *status)
+{
+	int flags = 0;
+
+#if JOBS
+	if (jp != NULL && jp->jobctl)
+		flags |= WUNTRACED;
+#endif
+	if (block == 0)
+		flags |= WNOHANG;
+	return sh_waitpid(psh, -1, status, flags);
+}
+
+/*
+ * return 1 if there are stopped jobs, otherwise 0
+ */
+//int job_warning = 0;
+int
+stoppedjobs(shinstance *psh)
+{
+	int jobno;
+	struct job *jp;
+
+	if (psh->job_warning || psh->jobs_invalid)
+		return (0);
+	for (jobno = 1, jp = psh->jobtab; jobno <= psh->njobs; jobno++, jp++) {
+		if (jp->used == 0)
+			continue;
+		if (jp->state == JOBSTOPPED) {
+			out2str(psh, "You have stopped jobs.\n");
+			psh->job_warning = 2;
+			return (1);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Return a string identifying a command (to be printed by the
+ * jobs command).
+ */
+
+//STATIC char *cmdnextc;
+//STATIC int cmdnleft;
+
+void
+commandtext(shinstance *psh, struct procstat *ps, union node *n)
+{
+	int len;
+
+	psh->cmdnextc = ps->cmd;
+	if (iflag(psh) || mflag(psh) || sizeof(ps->cmd) < 100)
+		len = sizeof(ps->cmd);
+	else
+		len = sizeof(ps->cmd) / 10;
+	psh->cmdnleft = len;
+	cmdtxt(psh, n);
+	if (psh->cmdnleft <= 0) {
+		char *p = ps->cmd + len - 4;
+		p[0] = '.';
+		p[1] = '.';
+		p[2] = '.';
+		p[3] = 0;
+	} else
+		*psh->cmdnextc = '\0';
+	TRACE((psh, "commandtext: ps->cmd %x, end %x, left %d\n\t\"%s\"\n",
+		ps->cmd, psh->cmdnextc, psh->cmdnleft, ps->cmd));
+}
+
+
+STATIC void
+cmdtxt(shinstance *psh, union node *n)
+{
+	union node *np;
+	struct nodelist *lp;
+	const char *p;
+	int i;
+	char s[2];
+
+	if (n == NULL || psh->cmdnleft <= 0)
+		return;
+	switch (n->type) {
+	case NSEMI:
+		cmdtxt(psh, n->nbinary.ch1);
+		cmdputs(psh, "; ");
+		cmdtxt(psh, n->nbinary.ch2);
+		break;
+	case NAND:
+		cmdtxt(psh, n->nbinary.ch1);
+		cmdputs(psh, " && ");
+		cmdtxt(psh, n->nbinary.ch2);
+		break;
+	case NOR:
+		cmdtxt(psh, n->nbinary.ch1);
+		cmdputs(psh, " || ");
+		cmdtxt(psh, n->nbinary.ch2);
+		break;
+	case NPIPE:
+		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+			cmdtxt(psh, lp->n);
+			if (lp->next)
+				cmdputs(psh, " | ");
+		}
+		break;
+	case NSUBSHELL:
+		cmdputs(psh, "(");
+		cmdtxt(psh, n->nredir.n);
+		cmdputs(psh, ")");
+		break;
+	case NREDIR:
+	case NBACKGND:
+		cmdtxt(psh, n->nredir.n);
+		break;
+	case NIF:
+		cmdputs(psh, "if ");
+		cmdtxt(psh, n->nif.test);
+		cmdputs(psh, "; then ");
+		cmdtxt(psh, n->nif.ifpart);
+		if (n->nif.elsepart) {
+			cmdputs(psh, "; else ");
+			cmdtxt(psh, n->nif.elsepart);
+		}
+		cmdputs(psh, "; fi");
+		break;
+	case NWHILE:
+		cmdputs(psh, "while ");
+		goto until;
+	case NUNTIL:
+		cmdputs(psh, "until ");
+until:
+		cmdtxt(psh, n->nbinary.ch1);
+		cmdputs(psh, "; do ");
+		cmdtxt(psh, n->nbinary.ch2);
+		cmdputs(psh, "; done");
+		break;
+	case NFOR:
+		cmdputs(psh, "for ");
+		cmdputs(psh, n->nfor.var);
+		cmdputs(psh, " in ");
+		cmdlist(psh, n->nfor.args, 1);
+		cmdputs(psh, "; do ");
+		cmdtxt(psh, n->nfor.body);
+		cmdputs(psh, "; done");
+		break;
+	case NCASE:
+		cmdputs(psh, "case ");
+		cmdputs(psh, n->ncase.expr->narg.text);
+		cmdputs(psh, " in ");
+		for (np = n->ncase.cases; np; np = np->nclist.next) {
+			cmdtxt(psh, np->nclist.pattern);
+			cmdputs(psh, ") ");
+			cmdtxt(psh, np->nclist.body);
+			cmdputs(psh, ";; ");
+		}
+		cmdputs(psh, "esac");
+		break;
+	case NDEFUN:
+		cmdputs(psh, n->narg.text);
+		cmdputs(psh, "() { ... }");
+		break;
+	case NCMD:
+		cmdlist(psh, n->ncmd.args, 1);
+		cmdlist(psh, n->ncmd.redirect, 0);
+		break;
+	case NARG:
+		cmdputs(psh, n->narg.text);
+		break;
+	case NTO:
+		p = ">";  i = 1;  goto redir;
+	case NCLOBBER:
+		p = ">|";  i = 1;  goto redir;
+	case NAPPEND:
+		p = ">>";  i = 1;  goto redir;
+	case NTOFD:
+		p = ">&";  i = 1;  goto redir;
+	case NFROM:
+		p = "<";  i = 0;  goto redir;
+	case NFROMFD:
+		p = "<&";  i = 0;  goto redir;
+	case NFROMTO:
+		p = "<>";  i = 0;  goto redir;
+redir:
+		if (n->nfile.fd != i) {
+			s[0] = n->nfile.fd + '0';
+			s[1] = '\0';
+			cmdputs(psh, s);
+		}
+		cmdputs(psh, p);
+		if (n->type == NTOFD || n->type == NFROMFD) {
+			s[0] = n->ndup.dupfd + '0';
+			s[1] = '\0';
+			cmdputs(psh, s);
+		} else {
+			cmdtxt(psh, n->nfile.fname);
+		}
+		break;
+	case NHERE:
+	case NXHERE:
+		cmdputs(psh, "<<...");
+		break;
+	default:
+		cmdputs(psh, "???");
+		break;
+	}
+}
+
+STATIC void
+cmdlist(shinstance *psh, union node *np, int sep)
+{
+	for (; np; np = np->narg.next) {
+		if (!sep)
+			cmdputs(psh, " ");
+		cmdtxt(psh, np);
+		if (sep && np->narg.next)
+			cmdputs(psh, " ");
+	}
+}
+
+
+STATIC void
+cmdputs(shinstance *psh, const char *s)
+{
+	const char *p, *str = 0;
+	char c, cc[2] = " ";
+	char *nextc;
+	int nleft;
+	int subtype = 0;
+	int quoted = 0;
+	static char vstype[16][4] = { "", "}", "-", "+", "?", "=",
+					"#", "##", "%", "%%" };
+
+	p = s;
+	nextc = psh->cmdnextc;
+	nleft = psh->cmdnleft;
+	while (nleft > 0 && (c = *p++) != 0) {
+		switch (c) {
+		case CTLESC:
+			c = *p++;
+			break;
+		case CTLVAR:
+			subtype = *p++;
+			if ((subtype & VSTYPE) == VSLENGTH)
+				str = "${#";
+			else
+				str = "${";
+			if (!(subtype & VSQUOTE) != !(quoted & 1)) {
+				quoted ^= 1;
+				c = '"';
+			} else
+				c = *str++;
+			break;
+		case CTLENDVAR:
+			if (quoted & 1) {
+				c = '"';
+				str = "}";
+			} else
+				c = '}';
+			quoted >>= 1;
+			subtype = 0;
+			break;
+		case CTLBACKQ:
+			c = '$';
+			str = "(...)";
+			break;
+		case CTLBACKQ+CTLQUOTE:
+			c = '"';
+			str = "$(...)\"";
+			break;
+		case CTLARI:
+			c = '$';
+			str = "((";
+			break;
+		case CTLENDARI:
+			c = ')';
+			str = ")";
+			break;
+		case CTLQUOTEMARK:
+			quoted ^= 1;
+			c = '"';
+			break;
+		case '=':
+			if (subtype == 0)
+				break;
+			str = vstype[subtype & VSTYPE];
+			if (subtype & VSNUL)
+				c = ':';
+			else
+				c = *str++;
+			if (c != '}')
+				quoted <<= 1;
+			break;
+		case '\'':
+		case '\\':
+		case '"':
+		case '$':
+			/* These can only happen inside quotes */
+			cc[0] = c;
+			str = cc;
+			c = '\\';
+			break;
+		default:
+			break;
+		}
+		do {
+			*nextc++ = c;
+		} while (--nleft > 0 && str && (c = *str++));
+		str = 0;
+	}
+	if ((quoted & 1) && nleft) {
+		*nextc++ = '"';
+		nleft--;
+	}
+	psh->cmdnleft = nleft;
+	psh->cmdnextc = nextc;
+}
Index: /tags/kBuild-0.1.4/src/kash/jobs.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/jobs.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/jobs.h	(revision 1780)
@@ -0,0 +1,107 @@
+/*	$NetBSD: jobs.h,v 1.19 2003/11/27 21:16:14 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include "output.h"
+
+/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
+#define FORK_FG 0
+#define FORK_BG 1
+#define FORK_NOJOB 2
+
+/* mode flags for showjob(s) */
+#define	SHOW_PGID	0x01	/* only show pgid - for jobs -p */
+#define	SHOW_MULTILINE	0x02	/* one line per process */
+#define	SHOW_PID	0x04	/* include process pid */
+#define	SHOW_CHANGED	0x08	/* only jobs whose state has changed */
+#define	SHOW_SIGNALLED	0x10	/* only if stopped/exited on signal */
+#define	SHOW_ISSIG	0x20	/* job was signalled */
+#define	SHOW_NO_FREE	0x40	/* do not free job */
+
+
+/*
+ * A job structure contains information about a job.  A job is either a
+ * single process or a set of processes contained in a pipeline.  In the
+ * latter case, pidlist will be non-NULL, and will point to a -1 terminated
+ * array of pids.
+ */
+#define	MAXCMDTEXT	200
+
+struct procstat {
+	pid_t	pid;		/* process id */
+ 	int	status;		/* last process status from wait() */
+ 	char	cmd[MAXCMDTEXT];/* text of command being run */
+};
+
+struct job {
+	struct procstat ps0;	/* status of process */
+	struct procstat *ps;	/* status or processes when more than one */
+	int	nprocs;		/* number of processes */
+	pid_t	pgrp;		/* process group of this job */
+	char	state;
+#define	JOBRUNNING	0	/* at least one proc running */
+#define	JOBSTOPPED	1	/* all procs are stopped */
+#define	JOBDONE		2	/* all procs are completed */
+	char	used;		/* true if this entry is in used */
+	char	changed;	/* true if status has changed */
+#if JOBS
+	char 	jobctl;		/* job running under job control */
+	int	prev_job;	/* previous job index */
+#endif
+};
+
+/*extern pid_t backgndpid;*/	/* pid of last background process */
+/*extern int job_warning;*/		/* user was warned about stopped jobs */
+
+void setjobctl(struct shinstance *, int);
+int fgcmd(struct shinstance *, int, char **);
+int bgcmd(struct shinstance *, int, char **);
+int jobscmd(struct shinstance *, int, char **);
+void showjobs(struct shinstance *, struct output *, int);
+int waitcmd(struct shinstance *, int, char **);
+int jobidcmd(struct shinstance *, int, char **);
+union node;
+struct job *makejob(struct shinstance *, union node *, int);
+int forkshell(struct shinstance *, struct job *, union node *, int);
+void forkchild(struct shinstance *, struct job *, union node *, int, int);
+int forkparent(struct shinstance *, struct job *, union node *, int, pid_t);
+int waitforjob(struct shinstance *, struct job *);
+int stoppedjobs(struct shinstance *);
+void commandtext(struct shinstance *, struct procstat *, union node *);
+int getjobpgrp(struct shinstance *, const char *);
+
+#if ! JOBS
+#define setjobctl(psh, on)	/* do nothing */
+#endif
Index: /tags/kBuild-0.1.4/src/kash/machdep.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/machdep.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/machdep.h	(revision 1780)
@@ -0,0 +1,52 @@
+/*	$NetBSD: machdep.h,v 1.11 2003/08/07 09:05:33 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)machdep.h	8.2 (Berkeley) 5/4/95
+ */
+
+/*
+ * Most machines require the value returned from malloc to be aligned
+ * in some way.  The following macro will get this right on many machines.
+ */
+
+#ifdef _MSC_VER
+#define SHELL_SIZE (8 - 1)
+#else
+#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
+#endif
+
+/*
+ * It appears that grabstackstr() will barf with such alignments
+ * because stalloc() will return a string allocated in a new stackblock.
+ */
+#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
Index: /tags/kBuild-0.1.4/src/kash/mail.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/mail.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/mail.c	(revision 1780)
@@ -0,0 +1,119 @@
+/*	$NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)mail.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $");
+#endif /* not lint */
+#endif
+
+/*
+ * Routines to check for mail.  (Perhaps make part of main.c?)
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "exec.h"	/* defines padvance() */
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mail.h"
+#include "shinstance.h"
+
+
+/*#define MAXMBOXES 10*/
+
+
+/*STATIC int nmboxes;			/* number of mailboxes */
+/*STATIC time_t mailtime[MAXMBOXES];*/	/* times of mailboxes */
+
+
+
+/*
+ * Print appropriate message(s) if mail has arrived.  If the argument is
+ * nozero, then the value of MAIL has changed, so we just update the
+ * values.
+ */
+
+void
+chkmail(shinstance *psh, int silent)
+{
+	int i;
+	const char *mpath;
+	char *p;
+	char *q;
+	struct stackmark smark;
+	struct stat statb;
+
+	if (silent)
+		psh->nmboxes = 10;
+	if (psh->nmboxes == 0)
+		return;
+	setstackmark(psh, &smark);
+	mpath = mpathset(psh) ? mpathval(psh) : mailval(psh);
+	for (i = 0 ; i < psh->nmboxes ; i++) {
+		p = padvance(psh, &mpath, nullstr);
+		if (p == NULL)
+			break;
+		if (*p == '\0')
+			continue;
+		for (q = p ; *q ; q++);
+		if (q[-1] != '/')
+			sh_abort(psh);
+		q[-1] = '\0';			/* delete trailing '/' */
+#ifdef notdef /* this is what the System V shell claims to do (it lies) */
+		if (shfile_stat(&psh->fdtab, p, &statb) < 0)
+			statb.st_mtime = 0;
+		if (statb.st_mtime > psh->mailtime[i] && ! silent) {
+			out2str(psh, psh->pathopt ? psh->pathopt : "you have mail");
+			out2c(psh, '\n');
+		}
+		psh->mailtime[i] = statb.st_mtime;
+#else /* this is what it should do */
+		if (shfile_stat(&psh->fdtab, p, &statb) < 0)
+			statb.st_size = 0;
+		if (statb.st_size > psh->mailtime[i] && ! silent) {
+			out2str(psh, psh->pathopt ? psh->pathopt : "you have mail");
+			out2c(psh, '\n');
+		}
+		psh->mailtime[i] = statb.st_size;
+#endif
+	}
+	psh->nmboxes = i;
+	popstackmark(psh, &smark);
+}
Index: /tags/kBuild-0.1.4/src/kash/mail.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/mail.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/mail.h	(revision 1780)
@@ -0,0 +1,37 @@
+/*	$NetBSD: mail.h,v 1.10 2003/08/07 09:05:34 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)mail.h	8.2 (Berkeley) 5/4/95
+ */
+
+void chkmail(struct shinstance *, int);
Index: /tags/kBuild-0.1.4/src/kash/main.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/main.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/main.c	(revision 1780)
@@ -0,0 +1,485 @@
+/*	$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n");
+#endif /* not lint */
+#ifndef lint
+static char sccsid[] = "@(#)main.c	8.7 (Berkeley) 7/19/95";
+#else
+__RCSID("$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $");
+#endif /* not lint */
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <locale.h>
+
+
+#include "shell.h"
+#include "main.h"
+#include "mail.h"
+#include "options.h"
+#include "output.h"
+#include "parser.h"
+#include "nodes.h"
+#include "expand.h"
+#include "eval.h"
+#include "jobs.h"
+#include "input.h"
+#include "trap.h"
+#include "var.h"
+#include "show.h"
+#include "memalloc.h"
+#include "error.h"
+#include "init.h"
+#include "mystring.h"
+#include "exec.h"
+#include "cd.h"
+#include "shinstance.h"
+
+#define PROFILE 0
+
+/*int rootpid;
+int rootshell;*/
+#ifdef unused_variables
+STATIC union node *curcmd;
+STATIC union node *prevcmd;
+#endif
+
+STATIC void read_profile(struct shinstance *, const char *);
+STATIC char *find_dot_file(struct shinstance *, char *);
+int main(int, char **);
+int shell_main(shinstance *, int, char **);
+#ifdef _MSC_VER
+extern void init_syntax(void);
+#endif
+STATIC int usage(const char *argv0);
+STATIC int version(const char *argv0);
+
+/*
+ * Main routine.  We initialize things, parse the arguments, execute
+ * profiles if we're a login shell, and then call cmdloop to execute
+ * commands.  The setjmp call sets up the location to jump to when an
+ * exception occurs.  When an exception occurs the variable "state"
+ * is used to figure out how far we had gotten.
+ */
+
+int
+main(int argc, char **argv)
+{
+	shinstance *psh;
+
+	/*
+	 * Global initializations.
+	 */
+	setlocale(LC_ALL, "");
+#ifdef _MSC_VER
+	init_syntax();
+#endif
+
+	/*
+	 * Check for --version and --help.
+	 */
+	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') {
+		if (!strcmp(argv[1], "--help"))
+			return usage(argv[0]);
+		if (!strcmp(argv[1], "--version"))
+			return version(argv[0]);
+	}
+
+	/*
+	 * Create the root shell instance.
+	 */
+	psh = sh_create_root_shell(NULL, argc, argv);
+	if (!psh)
+		return 2;
+	shthread_set_shell(psh);
+	return shell_main(psh, argc, argv);
+}
+
+int
+shell_main(shinstance *psh, int argc, char **argv)
+{
+	struct jmploc jmploc;
+	struct stackmark smark;
+	volatile int state;
+	char *shinit;
+
+	state = 0;
+	if (setjmp(jmploc.loc)) {
+		/*
+		 * When a shell procedure is executed, we raise the
+		 * exception EXSHELLPROC to clean up before executing
+		 * the shell procedure.
+		 */
+		switch (psh->exception) {
+		case EXSHELLPROC:
+			psh->rootpid = /*getpid()*/ psh->pid;
+			psh->rootshell = 1;
+			psh->minusc = NULL;
+			state = 3;
+			break;
+
+		case EXEXEC:
+			psh->exitstatus = psh->exerrno;
+			break;
+
+		case EXERROR:
+			psh->exitstatus = 2;
+			break;
+
+		default:
+			break;
+		}
+
+		if (psh->exception != EXSHELLPROC) {
+			if (state == 0 || iflag(psh) == 0 || ! psh->rootshell)
+				exitshell(psh, psh->exitstatus);
+		}
+		reset(psh);
+		if (psh->exception == EXINT
+#if ATTY
+		 && (! attyset(psh) || equal(termval(psh), "emacs"))
+#endif
+		 ) {
+			out2c(psh, '\n');
+			flushout(&psh->errout);
+		}
+		popstackmark(psh, &smark);
+		FORCEINTON;				/* enable interrupts */
+		if (state == 1)
+			goto state1;
+		else if (state == 2)
+			goto state2;
+		else if (state == 3)
+			goto state3;
+		else
+			goto state4;
+	}
+	psh->handler = &jmploc;
+	psh->rootpid = /*getpid()*/ psh->pid;
+	psh->rootshell = 1;
+#ifdef DEBUG
+#if DEBUG == 2
+	debug(psh) = 1;
+#endif
+	opentrace(psh);
+	trputs(psh, "Shell args:  ");  trargs(psh, argv);
+#endif
+
+	init(psh);
+	setstackmark(psh, &smark);
+	procargs(psh, argc, argv);
+	if (argv[0] && argv[0][0] == '-') {
+		state = 1;
+		read_profile(psh, "/etc/profile");
+state1:
+		state = 2;
+		read_profile(psh, ".profile");
+	}
+state2:
+	state = 3;
+	if (sh_getuid(psh) == sh_geteuid(psh) && sh_getgid(psh) == sh_getegid(psh)) {
+		if ((shinit = lookupvar(psh, "ENV")) != NULL && *shinit != '\0') {
+			state = 3;
+			read_profile(psh, shinit);
+		}
+	}
+state3:
+	state = 4;
+	if (sflag(psh) == 0 || psh->minusc) {
+		static int sigs[] =  {
+		    SIGINT, SIGQUIT, SIGHUP,
+#ifdef SIGTSTP
+		    SIGTSTP,
+#endif
+		    SIGPIPE
+		};
+#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
+		int i;
+
+		for (i = 0; i < SIGSSIZE; i++)
+		    setsignal(psh, sigs[i], 0);
+	}
+
+	if (psh->minusc)
+		evalstring(psh, psh->minusc, 0);
+
+	if (sflag(psh) || psh->minusc == NULL) {
+state4:	/* XXX ??? - why isn't this before the "if" statement */
+		cmdloop(psh, 1);
+	}
+	exitshell(psh, psh->exitstatus);
+	/* NOTREACHED */
+	return 1;
+}
+
+
+/*
+ * Read and execute commands.  "Top" is nonzero for the top level command
+ * loop; it turns on prompting if the shell is interactive.
+ */
+
+void
+cmdloop(struct shinstance *psh, int top)
+{
+	union node *n;
+	struct stackmark smark;
+	int inter;
+	int numeof = 0;
+
+	TRACE((psh, "cmdloop(%d) called\n", top));
+	setstackmark(psh, &smark);
+	for (;;) {
+		if (psh->pendingsigs)
+			dotrap(psh);
+		inter = 0;
+		if (iflag(psh) && top) {
+			inter = 1;
+			showjobs(psh, psh->out2, SHOW_CHANGED);
+			chkmail(psh, 0);
+			flushout(&psh->errout);
+		}
+		n = parsecmd(psh, inter);
+		/* showtree(n); DEBUG */
+		if (n == NEOF) {
+			if (!top || numeof >= 50)
+				break;
+			if (!stoppedjobs(psh)) {
+				if (!Iflag(psh))
+					break;
+				out2str(psh, "\nUse \"exit\" to leave shell.\n");
+			}
+			numeof++;
+		} else if (n != NULL && nflag(psh) == 0) {
+			psh->job_warning = (psh->job_warning == 2) ? 1 : 0;
+			numeof = 0;
+			evaltree(psh, n, 0);
+		}
+		popstackmark(psh, &smark);
+		setstackmark(psh, &smark);
+		if (psh->evalskip == SKIPFILE) {
+			psh->evalskip = 0;
+			break;
+		}
+	}
+	popstackmark(psh, &smark);
+}
+
+
+
+/*
+ * Read /etc/profile or .profile.  Return on error.
+ */
+
+STATIC void
+read_profile(struct shinstance *psh, const char *name)
+{
+	int fd;
+	int xflag_set = 0;
+	int vflag_set = 0;
+
+	INTOFF;
+	if ((fd = shfile_open(&psh->fdtab, name, O_RDONLY, 0)) >= 0)
+		setinputfd(psh, fd, 1);
+	INTON;
+	if (fd < 0)
+		return;
+	/* -q turns off -x and -v just when executing init files */
+	if (qflag(psh))  {
+	    if (xflag(psh))
+		    xflag(psh) = 0, xflag_set = 1;
+	    if (vflag(psh))
+		    vflag(psh) = 0, vflag_set = 1;
+	}
+	cmdloop(psh, 0);
+	if (qflag(psh))  {
+	    if (xflag_set)
+		    xflag(psh) = 1;
+	    if (vflag_set)
+		    vflag(psh) = 1;
+	}
+	popfile(psh);
+}
+
+
+
+/*
+ * Read a file containing shell functions.
+ */
+
+void
+readcmdfile(struct shinstance *psh, char *name)
+{
+	int fd;
+
+	INTOFF;
+	if ((fd = shfile_open(&psh->fdtab, name, O_RDONLY, 0)) >= 0)
+		setinputfd(psh, fd, 1);
+	else
+		error(psh, "Can't open %s", name);
+	INTON;
+	cmdloop(psh, 0);
+	popfile(psh);
+}
+
+
+
+/*
+ * Take commands from a file.  To be compatible we should do a path
+ * search for the file, which is necessary to find sub-commands.
+ */
+
+
+STATIC char *
+find_dot_file(struct shinstance *psh, char *basename)
+{
+	char *fullname;
+	const char *path = pathval(psh);
+	struct stat statb;
+
+	/* don't try this for absolute or relative paths */
+	if (strchr(basename, '/'))
+		return basename;
+
+	while ((fullname = padvance(psh, &path, basename)) != NULL) {
+		if ((shfile_stat(&psh->fdtab, fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
+			/*
+			 * Don't bother freeing here, since it will
+			 * be freed by the caller.
+			 */
+			return fullname;
+		}
+		stunalloc(psh, fullname);
+	}
+
+	/* not found in the PATH */
+	error(psh, "%s: not found", basename);
+	/* NOTREACHED */
+	return NULL;
+}
+
+int
+dotcmd(struct shinstance *psh, int argc, char **argv)
+{
+	psh->exitstatus = 0;
+
+	if (argc >= 2) {		/* That's what SVR2 does */
+		char *fullname;
+		struct stackmark smark;
+
+		setstackmark(psh, &smark);
+		fullname = find_dot_file(psh, argv[1]);
+		setinputfile(psh, fullname, 1);
+		psh->commandname = fullname;
+		cmdloop(psh, 0);
+		popfile(psh);
+		popstackmark(psh, &smark);
+	}
+	return psh->exitstatus;
+}
+
+
+int
+exitcmd(struct shinstance *psh, int argc, char **argv)
+{
+	if (stoppedjobs(psh))
+		return 0;
+	if (argc > 1)
+		psh->exitstatus = number(psh, argv[1]);
+	exitshell(psh, psh->exitstatus);
+	/* NOTREACHED */
+	return 1;
+}
+
+
+STATIC const char *
+strip_argv0(const char *argv0, size_t *lenp)
+{
+	const char *tmp;
+
+	/* skip the path */
+	for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:"))
+		argv0 = tmp + 1;
+
+	/* find the end, ignoring extenions */
+	tmp = strrchr(argv0, '.');
+	if (!tmp)
+		tmp = strchr(argv0, '\0');
+	*lenp = tmp - argv0;
+	return argv0;
+}
+
+STATIC int
+usage(const char *argv0)
+{
+	size_t len;
+	argv0 = strip_argv0(argv0, &len);
+
+	fprintf(stdout,
+			"usage: %.*s [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+		    "               [+o option_name] [command_file [argument ...]]\n"
+		    "   or: %.*s -c [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+		    "               [+o option_name] command_string [command_name [argument ...]]\n"
+		    "   or: %.*s -s [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+		    "               [+o option_name] [argument ...]\n"
+		    "   or: %.*s --help\n"
+		    "   or: %.*s --version\n",
+		    len, argv0, len, argv0, len, argv0, len, argv0, len, argv0);
+	return 0;
+}
+
+STATIC int
+version(const char *argv0)
+{
+	size_t len;
+	strip_argv0(argv0, &len);
+
+	fprintf(stdout,
+			"%.*s - kBuild version %d.%d.%d\n",
+		    len, argv0,
+		    KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH);
+	return 0;
+}
+
+
+/*
+ * Local Variables:
+ *   c-file-style: bsd
+ * End:
+ */
Index: /tags/kBuild-0.1.4/src/kash/main.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/main.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/main.h	(revision 1780)
@@ -0,0 +1,44 @@
+/*	$NetBSD: main.h,v 1.10 2003/08/07 09:05:34 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)main.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include "shtypes.h"
+/*extern int rootpid;*/	/* pid of main shell */
+/*extern int rootshell;*/	/* true if we aren't a child of the main shell */
+
+void readcmdfile(struct shinstance *, char *);
+void cmdloop(struct shinstance *, int);
+int dotcmd(struct shinstance *, int, char **);
+int exitcmd(struct shinstance *, int, char **);
Index: /tags/kBuild-0.1.4/src/kash/memalloc.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/memalloc.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/memalloc.c	(revision 1780)
@@ -0,0 +1,306 @@
+/*	$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)memalloc.c	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdlib.h>
+
+#include "shell.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "machdep.h"
+#include "mystring.h"
+#include "shinstance.h"
+
+/*
+ * Like malloc, but returns an error when out of space.
+ */
+
+pointer
+ckmalloc(size_t nbytes)
+{
+	pointer p;
+
+	p = malloc(nbytes);
+	if (p == NULL)
+		error(NULL, "Out of space");
+	return p;
+}
+
+
+/*
+ * Same for realloc.
+ */
+
+pointer
+ckrealloc(pointer p, size_t nbytes)
+{
+	p = realloc(p, nbytes);
+	if (p == NULL)
+		error(NULL, "Out of space");
+	return p;
+}
+
+
+/*
+ * Make a copy of a string in safe storage.
+ */
+
+char *
+savestr(const char *s)
+{
+	char *p;
+
+	p = ckmalloc(strlen(s) + 1);
+	scopy(s, p);
+	return p;
+}
+
+
+/*
+ * Parse trees for commands are allocated in lifo order, so we use a stack
+ * to make this more efficient, and also to avoid all sorts of exception
+ * handling code to handle interrupts in the middle of a parse.
+ *
+ * The size 504 was chosen because the Ultrix malloc handles that size
+ * well.
+ */
+
+//#define MINSIZE 504		/* minimum size of a block */
+
+//struct stack_block {
+//	struct stack_block *prev;
+//	char space[MINSIZE];
+//};
+
+//struct stack_block stackbase;
+//struct stack_block *stackp = &stackbase;
+//struct stackmark *markp;
+//char *stacknxt = stackbase.space;
+//int stacknleft = MINSIZE;
+//int sstrnleft;
+//int herefd = -1;
+
+pointer
+stalloc(shinstance *psh, size_t nbytes)
+{
+	char *p;
+
+	nbytes = SHELL_ALIGN(nbytes);
+	if (nbytes > psh->stacknleft) {
+		size_t blocksize;
+		struct stack_block *sp;
+
+		blocksize = nbytes;
+		if (blocksize < MINSIZE)
+			blocksize = MINSIZE;
+		INTOFF;
+		sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
+		sp->prev = psh->stackp;
+		psh->stacknxt = sp->space;
+		psh->stacknleft = (int)blocksize;
+		psh->stackp = sp;
+		INTON;
+	}
+	p = psh->stacknxt;
+	psh->stacknxt += nbytes;
+	psh->stacknleft -= (int)nbytes;
+	return p;
+}
+
+
+void
+stunalloc(shinstance *psh, pointer p)
+{
+	if (p == NULL) {		/*DEBUG */
+		shfile_write(&psh->fdtab, 2, "stunalloc\n", 10);
+		sh_abort(psh);
+	}
+	psh->stacknleft += (int)(psh->stacknxt - (char *)p);
+	psh->stacknxt = p;
+}
+
+
+
+void
+setstackmark(shinstance *psh, struct stackmark *mark)
+{
+	mark->stackp = psh->stackp;
+	mark->stacknxt = psh->stacknxt;
+	mark->stacknleft = psh->stacknleft;
+	mark->marknext = psh->markp;
+	psh->markp = mark;
+}
+
+
+void
+popstackmark(shinstance *psh, struct stackmark *mark)
+{
+	struct stack_block *sp;
+
+	INTOFF;
+	psh->markp = mark->marknext;
+	while (psh->stackp != mark->stackp) {
+		sp = psh->stackp;
+		psh->stackp = sp->prev;
+		ckfree(sp);
+	}
+	psh->stacknxt = mark->stacknxt;
+	psh->stacknleft = mark->stacknleft;
+	INTON;
+}
+
+
+/*
+ * When the parser reads in a string, it wants to stick the string on the
+ * stack and only adjust the stack pointer when it knows how big the
+ * string is.  Stackblock (defined in stack.h) returns a pointer to a block
+ * of space on top of the stack and stackblocklen returns the length of
+ * this block.  Growstackblock will grow this space by at least one byte,
+ * possibly moving it (like realloc).  Grabstackblock actually allocates the
+ * part of the block that has been used.
+ */
+
+void
+growstackblock(shinstance *psh)
+{
+	int newlen = SHELL_ALIGN(psh->stacknleft * 2 + 100);
+
+	if (psh->stacknxt == psh->stackp->space && psh->stackp != &psh->stackbase) {
+		struct stack_block *oldstackp;
+		struct stackmark *xmark;
+		struct stack_block *sp;
+
+		INTOFF;
+		oldstackp = psh->stackp;
+		sp = psh->stackp;
+		psh->stackp = sp->prev;
+		sp = ckrealloc((pointer)sp,
+		    sizeof(struct stack_block) - MINSIZE + newlen);
+		sp->prev = psh->stackp;
+		psh->stackp = sp;
+		psh->stacknxt = sp->space;
+		psh->stacknleft = newlen;
+
+		/*
+		 * Stack marks pointing to the start of the old block
+		 * must be relocated to point to the new block
+		 */
+		xmark = psh->markp;
+		while (xmark != NULL && xmark->stackp == oldstackp) {
+			xmark->stackp = psh->stackp;
+			xmark->stacknxt = psh->stacknxt;
+			xmark->stacknleft = psh->stacknleft;
+			xmark = xmark->marknext;
+		}
+		INTON;
+	} else {
+		char *oldspace = psh->stacknxt;
+		int oldlen = psh->stacknleft;
+		char *p = stalloc(psh, newlen);
+
+		(void)memcpy(p, oldspace, oldlen);
+		psh->stacknxt = p;			/* free the space */
+		psh->stacknleft += newlen;		/* we just allocated */
+	}
+}
+
+void
+grabstackblock(shinstance *psh, int len)
+{
+	len = SHELL_ALIGN(len);
+	psh->stacknxt += len;
+	psh->stacknleft -= len;
+}
+
+/*
+ * The following routines are somewhat easier to use than the above.
+ * The user declares a variable of type STACKSTR, which may be declared
+ * to be a register.  The macro STARTSTACKSTR initializes things.  Then
+ * the user uses the macro STPUTC to add characters to the string.  In
+ * effect, STPUTC(psh, c, p) is the same as *p++ = c except that the stack is
+ * grown as necessary.  When the user is done, she can just leave the
+ * string there and refer to it using stackblock(psh).  Or she can allocate
+ * the space for it using grabstackstr().  If it is necessary to allow
+ * someone else to use the stack temporarily and then continue to grow
+ * the string, the user should use grabstack to allocate the space, and
+ * then call ungrabstr(p) to return to the previous mode of operation.
+ *
+ * USTPUTC is like STPUTC except that it doesn't check for overflow.
+ * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
+ * is space for at least one character.
+ */
+
+char *
+growstackstr(shinstance *psh)
+{
+	int len = stackblocksize(psh);
+	if (psh->herefd >= 0 && len >= 1024) {
+		xwrite(psh, psh->herefd, stackblock(psh), len);
+		psh->sstrnleft = len - 1;
+		return stackblock(psh);
+	}
+	growstackblock(psh);
+	psh->sstrnleft = stackblocksize(psh) - len - 1;
+	return stackblock(psh) + len;
+}
+
+/*
+ * Called from CHECKSTRSPACE.
+ */
+
+char *
+makestrspace(shinstance *psh)
+{
+	int len = stackblocksize(psh) - psh->sstrnleft;
+	growstackblock(psh);
+	psh->sstrnleft = stackblocksize(psh) - len;
+	return stackblock(psh) + len;
+}
+
+void
+ungrabstackstr(shinstance *psh, char *s, char *p)
+{
+	psh->stacknleft += (int)(psh->stacknxt - s);
+	psh->stacknxt = s;
+	psh->sstrnleft = (int)(psh->stacknleft - (p - s));
+
+}
Index: /tags/kBuild-0.1.4/src/kash/memalloc.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/memalloc.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/memalloc.h	(revision 1780)
@@ -0,0 +1,77 @@
+/*	$NetBSD: memalloc.h,v 1.14 2003/08/07 09:05:34 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
+ */
+
+struct stackmark {
+	struct stack_block *stackp;
+	char *stacknxt;
+	int stacknleft;
+	struct stackmark *marknext;
+};
+
+
+/*extern char *stacknxt;
+extern int stacknleft;
+extern int sstrnleft;
+extern int herefd;*/
+
+pointer ckmalloc(size_t);
+pointer ckrealloc(pointer, size_t);
+char *savestr(const char *);
+pointer stalloc(struct shinstance *, size_t);
+void stunalloc(struct shinstance *, pointer);
+void setstackmark(struct shinstance *, struct stackmark *);
+void popstackmark(struct shinstance *, struct stackmark *);
+void growstackblock(struct shinstance *);
+void grabstackblock(struct shinstance *, int);
+char *growstackstr(struct shinstance *);
+char *makestrspace(struct shinstance *);
+void ungrabstackstr(struct shinstance *, char *, char *);
+
+
+
+#define stackblock(psh)             (psh)->stacknxt
+#define stackblocksize(psh)         (psh)->stacknleft
+#define STARTSTACKSTR(psh, p)       p = stackblock(psh), (psh)->sstrnleft = stackblocksize(psh)
+#define STPUTC(psh, c, p)           (--(psh)->sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(psh), *p++ = (c)))
+#define CHECKSTRSPACE(psh, n, p)    { if ((psh)->sstrnleft < n) p = makestrspace(psh); }
+#define USTPUTC(psh, c, p)          (--(psh)->sstrnleft, *p++ = (c))
+#define STACKSTRNUL(psh, p)         ((psh)->sstrnleft == 0? (p = growstackstr(psh), *p = '\0') : (*p = '\0'))
+#define STUNPUTC(psh, p)            (++(psh)->sstrnleft, --p)
+#define STTOPC(psh, p)	            p[-1]
+#define STADJUST(psh, amount, p)    (p += (amount), (psh)->sstrnleft -= (amount))
+#define grabstackstr(psh, p)        stalloc((psh), stackblocksize(psh) - (psh)->sstrnleft)
+
+#define ckfree(p)	free((pointer)(p))
Index: /tags/kBuild-0.1.4/src/kash/miscbltin.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/miscbltin.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/miscbltin.c	(revision 1780)
@@ -0,0 +1,444 @@
+/*	$NetBSD: miscbltin.c,v 1.35 2005/03/19 14:22:50 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)miscbltin.c	8.4 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: miscbltin.c,v 1.35 2005/03/19 14:22:50 dsl Exp $");
+#endif /* not lint */
+#endif
+
+/*
+ * Miscelaneous builtins.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "shell.h"
+#include "options.h"
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "miscbltin.h"
+#include "mystring.h"
+#include "shinstance.h"
+
+#undef rflag
+
+void *bsd_setmode(shinstance *psh, const char *p);
+mode_t bsd_getmode(const void *bbox, mode_t omode);
+
+
+/*
+ * The read builtin.
+ * Backslahes escape the next char unless -r is specified.
+ *
+ * This uses unbuffered input, which may be avoidable in some cases.
+ *
+ * Note that if IFS=' :' then read x y should work so that:
+ * 'a b'	x='a', y='b'
+ * ' a b '	x='a', y='b'
+ * ':b'		x='',  y='b'
+ * ':'		x='',  y=''
+ * '::'		x='',  y=''
+ * ': :'	x='',  y=''
+ * ':::'	x='',  y='::'
+ * ':b c:'	x='',  y='b c:'
+ */
+
+int
+readcmd(shinstance *psh, int argc, char **argv)
+{
+	char **ap;
+	char c;
+	int rflag;
+	char *prompt;
+	const char *ifs;
+	char *p;
+	int startword;
+	int status;
+	int i;
+	int is_ifs;
+	int saveall = 0;
+
+	rflag = 0;
+	prompt = NULL;
+	while ((i = nextopt(psh, "p:r")) != '\0') {
+		if (i == 'p')
+			prompt = psh->optionarg;
+		else
+			rflag = 1;
+	}
+
+	if (prompt && isatty(0)) {
+		out2str(psh, prompt);
+		output_flushall(psh);
+	}
+
+	if (*(ap = psh->argptr) == NULL)
+		error(psh, "arg count");
+
+	if ((ifs = bltinlookup(psh, "IFS", 1)) == NULL)
+		ifs = " \t\n";
+
+	status = 0;
+	startword = 2;
+	STARTSTACKSTR(psh, p);
+	for (;;) {
+		if (shfile_read(&psh->fdtab, 0, &c, 1) != 1) {
+			status = 1;
+			break;
+		}
+		if (c == '\0')
+			continue;
+		if (c == '\\' && !rflag) {
+			if (shfile_read(&psh->fdtab, 0, &c, 1) != 1) {
+				status = 1;
+				break;
+			}
+			if (c != '\n')
+				STPUTC(psh, c, p);
+			continue;
+		}
+		if (c == '\n')
+			break;
+		if (strchr(ifs, c))
+			is_ifs = strchr(" \t\n", c) ? 1 : 2;
+		else
+			is_ifs = 0;
+
+		if (startword != 0) {
+			if (is_ifs == 1) {
+				/* Ignore leading IFS whitespace */
+				if (saveall)
+					STPUTC(psh, c, p);
+				continue;
+			}
+			if (is_ifs == 2 && startword == 1) {
+				/* Only one non-whitespace IFS per word */
+				startword = 2;
+				if (saveall)
+					STPUTC(psh, c, p);
+				continue;
+			}
+		}
+
+		if (is_ifs == 0) {
+			/* append this character to the current variable */
+			startword = 0;
+			if (saveall)
+				/* Not just a spare terminator */
+				saveall++;
+			STPUTC(psh, c, p);
+			continue;
+		}
+
+		/* end of variable... */
+		startword = is_ifs;
+
+		if (ap[1] == NULL) {
+			/* Last variable needs all IFS chars */
+			saveall++;
+			STPUTC(psh, c, p);
+			continue;
+		}
+
+		STACKSTRNUL(psh, p);
+		setvar(psh, *ap, stackblock(psh), 0);
+		ap++;
+		STARTSTACKSTR(psh, p);
+	}
+	STACKSTRNUL(psh, p);
+
+	/* Remove trailing IFS chars */
+	for (; stackblock(psh) <= --p; *p = 0) {
+		if (!strchr(ifs, *p))
+			break;
+		if (strchr(" \t\n", *p))
+			/* Always remove whitespace */
+			continue;
+		if (saveall > 1)
+			/* Don't remove non-whitespace unless it was naked */
+			break;
+	}
+	setvar(psh, *ap, stackblock(psh), 0);
+
+	/* Set any remaining args to "" */
+	while (*++ap != NULL)
+		setvar(psh, *ap, nullstr, 0);
+	return status;
+}
+
+
+
+int
+umaskcmd(shinstance *psh, int argc, char **argv)
+{
+	char *ap;
+	int mask;
+	int i;
+	int symbolic_mode = 0;
+
+	while ((i = nextopt(psh, "S")) != '\0') {
+		symbolic_mode = 1;
+	}
+
+	INTOFF;
+	mask = umask(0);
+	umask(mask);
+	INTON;
+
+	if ((ap = *psh->argptr) == NULL) {
+		if (symbolic_mode) {
+			char u[4], g[4], o[4];
+
+			i = 0;
+			if ((mask & S_IRUSR) == 0)
+				u[i++] = 'r';
+			if ((mask & S_IWUSR) == 0)
+				u[i++] = 'w';
+			if ((mask & S_IXUSR) == 0)
+				u[i++] = 'x';
+			u[i] = '\0';
+
+			i = 0;
+			if ((mask & S_IRGRP) == 0)
+				g[i++] = 'r';
+			if ((mask & S_IWGRP) == 0)
+				g[i++] = 'w';
+			if ((mask & S_IXGRP) == 0)
+				g[i++] = 'x';
+			g[i] = '\0';
+
+			i = 0;
+			if ((mask & S_IROTH) == 0)
+				o[i++] = 'r';
+			if ((mask & S_IWOTH) == 0)
+				o[i++] = 'w';
+			if ((mask & S_IXOTH) == 0)
+				o[i++] = 'x';
+			o[i] = '\0';
+
+			out1fmt(psh, "u=%s,g=%s,o=%s\n", u, g, o);
+		} else {
+			out1fmt(psh, "%.4o\n", mask);
+		}
+	} else {
+		if (isdigit((unsigned char)*ap)) {
+			mask = 0;
+			do {
+				if (*ap >= '8' || *ap < '0')
+					error(psh, "Illegal number: %s", argv[1]);
+				mask = (mask << 3) + (*ap - '0');
+			} while (*++ap != '\0');
+			umask(mask);
+		} else {
+			void *set;
+
+			INTOFF;
+			if ((set = bsd_setmode(psh, ap)) != 0) {
+				mask = bsd_getmode(set, ~mask & 0777);
+				ckfree(set);
+			}
+			INTON;
+			if (!set)
+				error(psh, "Illegal mode: %s", ap);
+
+			umask(~mask & 0777);
+		}
+	}
+	return 0;
+}
+
+/*
+ * ulimit builtin
+ *
+ * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
+ * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
+ * ash by J.T. Conklin.
+ *
+ * Public domain.
+ */
+
+struct limits {
+	const char *name;
+	int	cmd;
+	int	factor;	/* multiply by to get rlim_{cur,max} values */
+	char	option;
+};
+
+static const struct limits limits[] = {
+#ifdef RLIMIT_CPU
+	{ "time(seconds)",		RLIMIT_CPU,	   1, 't' },
+#endif
+#ifdef RLIMIT_FSIZE
+	{ "file(blocks)",		RLIMIT_FSIZE,	 512, 'f' },
+#endif
+#ifdef RLIMIT_DATA
+	{ "data(kbytes)",		RLIMIT_DATA,	1024, 'd' },
+#endif
+#ifdef RLIMIT_STACK
+	{ "stack(kbytes)",		RLIMIT_STACK,	1024, 's' },
+#endif
+#ifdef  RLIMIT_CORE
+	{ "coredump(blocks)",		RLIMIT_CORE,	 512, 'c' },
+#endif
+#ifdef RLIMIT_RSS
+	{ "memory(kbytes)",		RLIMIT_RSS,	1024, 'm' },
+#endif
+#ifdef RLIMIT_MEMLOCK
+	{ "locked memory(kbytes)",	RLIMIT_MEMLOCK, 1024, 'l' },
+#endif
+#ifdef RLIMIT_NPROC
+	{ "process(processes)",		RLIMIT_NPROC,      1, 'p' },
+#endif
+#ifdef RLIMIT_NOFILE
+	{ "nofiles(descriptors)",	RLIMIT_NOFILE,     1, 'n' },
+#endif
+#ifdef RLIMIT_VMEM
+	{ "vmemory(kbytes)",		RLIMIT_VMEM,	1024, 'v' },
+#endif
+#ifdef RLIMIT_SWAP
+	{ "swap(kbytes)",		RLIMIT_SWAP,	1024, 'w' },
+#endif
+#ifdef RLIMIT_SBSIZE
+	{ "sbsize(bytes)",		RLIMIT_SBSIZE,	   1, 'b' },
+#endif
+	{ (char *) 0,			0,		   0,  '\0' }
+};
+
+int
+ulimitcmd(shinstance *psh, int argc, char **argv)
+{
+	int	c;
+	shrlim_t val = 0;
+	enum { SOFT = 0x1, HARD = 0x2 }
+			how = SOFT | HARD;
+	const struct limits	*l;
+	int		set, all = 0;
+	int		optc, what;
+	shrlimit	limit;
+
+	what = 'f';
+	while ((optc = nextopt(psh, "HSabtfdsmcnpl")) != '\0')
+		switch (optc) {
+		case 'H':
+			how = HARD;
+			break;
+		case 'S':
+			how = SOFT;
+			break;
+		case 'a':
+			all = 1;
+			break;
+		default:
+			what = optc;
+		}
+
+	for (l = limits; l->name && l->option != what; l++)
+		;
+	if (!l->name)
+		error(psh, "internal error (%c)", what);
+
+	set = *psh->argptr ? 1 : 0;
+	if (set) {
+		char *p = *psh->argptr;
+
+		if (all || psh->argptr[1])
+			error(psh, "too many arguments");
+		if (strcmp(p, "unlimited") == 0)
+			val = RLIM_INFINITY;
+		else {
+			val = (shrlim_t) 0;
+
+			while ((c = *p++) >= '0' && c <= '9')
+			{
+				val = (val * 10) + (long)(c - '0');
+				if (val < (shrlim_t) 0)
+					break;
+			}
+			if (c)
+				error(psh, "bad number");
+			val *= l->factor;
+		}
+	}
+	if (all) {
+		for (l = limits; l->name; l++) {
+			sh_getrlimit(psh, l->cmd, &limit);
+			if (how & SOFT)
+				val = limit.rlim_cur;
+			else if (how & HARD)
+				val = limit.rlim_max;
+
+			out1fmt(psh, "%-20s ", l->name);
+			if (val == RLIM_INFINITY)
+				out1fmt(psh, "unlimited\n");
+			else
+			{
+				val /= l->factor;
+				out1fmt(psh, "%lld\n", (long long) val);
+			}
+		}
+		return 0;
+	}
+
+	sh_getrlimit(psh, l->cmd, &limit);
+	if (set) {
+		if (how & HARD)
+			limit.rlim_max = val;
+		if (how & SOFT)
+			limit.rlim_cur = val;
+		if (sh_setrlimit(psh, l->cmd, &limit) < 0)
+			error(psh, "error setting limit (%s)", strerror(errno));
+	} else {
+		if (how & SOFT)
+			val = limit.rlim_cur;
+		else if (how & HARD)
+			val = limit.rlim_max;
+
+		if (val == RLIM_INFINITY)
+			out1fmt(psh, "unlimited\n");
+		else
+		{
+			val /= l->factor;
+			out1fmt(psh, "%lld\n", (long long) val);
+		}
+	}
+	return 0;
+}
Index: /tags/kBuild-0.1.4/src/kash/miscbltin.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/miscbltin.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/miscbltin.h	(revision 1780)
@@ -0,0 +1,31 @@
+/*	$NetBSD: miscbltin.h,v 1.3 2003/08/21 17:57:53 christos Exp $	*/
+
+/*
+ * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+int readcmd(struct shinstance *, int, char **);
+int umaskcmd(struct shinstance *, int, char **);
+int ulimitcmd(struct shinstance *, int, char **);
Index: /tags/kBuild-0.1.4/src/kash/mkbuiltins
===================================================================
--- /tags/kBuild-0.1.4/src/kash/mkbuiltins	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/mkbuiltins	(revision 1780)
@@ -0,0 +1,136 @@
+#!/bin/sh -
+#	$NetBSD: mkbuiltins,v 1.21 2004/06/06 07:03:11 christos Exp $
+#
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)mkbuiltins	8.2 (Berkeley) 5/4/95
+
+havehist=1
+if [ "X$1" = "X-h" ]; then
+	havehist=0
+	shift
+fi
+
+shell=$1
+builtins=$2
+objdir=$3
+
+havejobs=0
+if grep '^#define JOBS[	 ]*1' ${shell} > /dev/null
+then
+	havejobs=1
+fi
+
+exec <$builtins 3> ${objdir}/builtins.c 4> ${objdir}/builtins.h
+
+echo '/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include "shell.h"
+#include "builtins.h"
+
+const struct builtincmd builtincmd[] = {
+' >&3
+
+echo '/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include "shtypes.h"
+
+struct builtincmd {
+      const char *name;
+      int (*builtin)(shinstance *, int, char **);
+};
+
+extern const struct builtincmd builtincmd[];
+extern const struct builtincmd splbltincmd[];
+
+' >&4
+
+specials=
+
+while read line
+do
+	set -- $line
+	[ -z "$1" ] && continue
+	case "$1" in
+	\#if*|\#def*|\#end*)
+		echo $line >&3
+		echo $line >&4
+		continue
+		;;
+	esac
+	l1="${line###}"
+	[ "$l1" != "$line" ] && continue
+
+
+	func=$1
+	shift
+	[ x"$1" = x'-j' ] && {
+		[ $havejobs = 0 ] && continue
+		shift
+	}
+	[ x"$1" = x'-h' ] && {
+		[ $havehist = 0 ] && continue
+		shift
+	}
+	echo 'int '"$func"'(shinstance *, int, char **);' >&4
+	while
+		[ $# != 0 -a "$1" != '#' ]
+	do
+		[ "$1" = '-s' ] && {
+			specials="$specials $2 $func"
+			shift 2
+			continue;
+		}
+		[ "$1" = '-u' ] && shift
+		echo '	{ "'$1'",	'"$func"' },' >&3
+		shift
+	done
+done
+
+echo '	{ 0, 0 },' >&3
+echo '};' >&3
+echo >&3
+echo 'const struct builtincmd splbltincmd[] = {' >&3
+
+set -- $specials
+while
+	[ $# != 0 ]
+do
+	echo '	{ "'$1'",	'"$2"' },' >&3
+	shift 2
+done
+
+echo '	{ 0, 0 },' >&3
+echo "};" >&3
Index: /tags/kBuild-0.1.4/src/kash/mkinit.sh
===================================================================
--- /tags/kBuild-0.1.4/src/kash/mkinit.sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/mkinit.sh	(revision 1780)
@@ -0,0 +1,198 @@
+#! /bin/sh
+#	$NetBSD: mkinit.sh,v 1.2 2004/06/15 23:09:54 dsl Exp $
+
+# Copyright (c) 2003 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by David Laight.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of The NetBSD Foundation nor the names of its
+#    contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+srcs="$*"
+
+nl='
+'
+openparen='('
+backslash='\'
+
+includes=' "shell.h" "mystring.h" "init.h" '
+defines=
+decles=
+event_init=
+event_reset=
+event_shellproc=
+
+for src in $srcs; do
+	exec <$src
+	decnl="$nl"
+	while IFS=; read -r line; do
+		[ "$line" = x ]
+		case "$line " in
+		INIT["{ 	"]* ) event=init;;
+		RESET["{ 	"]* ) event=reset;;
+		SHELLPROC["{ 	"]* ) event=shellproc;;
+		INCLUDE[\ \	]* )
+			IFS=' 	'
+			set -- $line
+			# ignore duplicates
+			[ "${includes}" != "${includes%* $2 }" ] && continue
+			includes="$includes$2 "
+			continue
+			;;
+		MKINIT\  )
+			# struct declaration
+			decles="$decles$nl"
+			while
+				read -r line
+				decles="${decles}${line}${nl}"
+				[ "$line" != "};" ]
+			do
+				:
+			done
+			decnl="$nl"
+			continue
+			;;
+		MKINIT["{ 	"]* )
+			# strip initialiser
+			def=${line#MKINIT}
+			comment="${def#*;}"
+			def="${def%;$comment}"
+			def="${def%%=*}"
+			def="${def% }"
+			decles="${decles}${decnl}extern${def};${comment}${nl}"
+			decnl=
+			continue
+			;;
+		\#define[\ \	]* )
+			IFS=' 	'
+			set -- $line
+			# Ignore those with arguments
+			[ "$2" = "${2##*$openparen}" ] || continue
+			# and multiline definitions
+			[ "$line" = "${line%$backslash}" ] || continue
+			defines="${defines}#undef  $2${nl}${line}${nl}"
+			continue
+			;;
+		* ) continue;;
+		esac
+		# code for events
+		ev="${nl}      /* from $src: */${nl}      {${nl}"
+		while
+			read -r line
+			[ "$line" != "}" ]
+		do
+			# The C program indented by an extra 6 chars using
+			# tabs then spaces. I need to compare the output :-(
+			indent=6
+			while
+				l=${line#	}
+				[ "$l" != "$line" ]
+			do
+				indent=$(($indent + 8))
+				line="$l"
+			done
+			while
+				l=${line# }
+				[ "$l" != "$line" ]
+			do
+				indent=$(($indent + 1))
+				line="$l"
+			done
+			[ -z "$line" -o "$line" != "${line###}" ] && indent=0
+			while
+				[ $indent -ge 8 ]
+			do
+				ev="$ev	"
+				indent="$(($indent - 8))"
+			done
+			while
+				[ $indent -gt 0 ]
+			do
+				ev="$ev "
+				indent="$(($indent - 1))"
+			done
+			ev="${ev}${line}${nl}"
+		done
+		ev="${ev}      }${nl}"
+		eval event_$event=\"\$event_$event\$ev\"
+	done
+done
+
+exec >init.c.tmp
+
+echo "/*"
+echo " * This file was generated by the mkinit program."
+echo " */"
+echo
+
+IFS=' '
+for f in $includes; do
+	echo "#include $f"
+done
+echo "#include \"shinstance.h\""
+
+echo
+echo
+echo
+echo "$defines"
+echo
+echo "$decles"
+echo
+echo
+echo "/*"
+echo " * Initialization code."
+echo " */"
+echo
+echo "void"
+echo "init(shinstance *psh) {"
+echo "${event_init%$nl}"
+echo "}"
+echo
+echo
+echo
+echo "/*"
+echo " * This routine is called when an error or an interrupt occurs in an"
+echo " * interactive shell and control is returned to the main command loop."
+echo " */"
+echo
+echo "void"
+echo "reset(shinstance *psh) {"
+echo "${event_reset%$nl}"
+echo "}"
+echo
+echo
+echo
+echo "/*"
+echo " * This routine is called to initialize the shell to run a shell procedure."
+echo " */"
+echo
+echo "void"
+echo "initshellproc(shinstance *psh) {"
+echo "${event_shellproc%$nl}"
+echo "}"
+
+exec >&-
+mv init.c.tmp init.c
Index: /tags/kBuild-0.1.4/src/kash/mknodes.sh
===================================================================
--- /tags/kBuild-0.1.4/src/kash/mknodes.sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/mknodes.sh	(revision 1780)
@@ -0,0 +1,217 @@
+#! /bin/sh
+#	$NetBSD: mknodes.sh,v 1.1 2004/01/16 23:24:38 dsl Exp $
+
+# Copyright (c) 2003 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by David Laight.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of The NetBSD Foundation nor the names of its
+#    contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+nodetypes=$1
+nodes_pat=$2
+objdir="$3"
+
+exec <$nodetypes
+exec >$objdir/nodes.h.tmp
+
+echo "/*"
+echo " * This file was generated by mknodes.sh"
+echo " */"
+echo
+
+tagno=0
+while IFS=; read -r line; do
+	line="${line%%#*}"
+	IFS=' 	'
+	set -- $line
+	IFS=
+	[ -z "$2" ] && continue
+	case "$line" in
+	[" 	"]* )
+		IFS=' '
+		[ $field = 0 ] && struct_list="$struct_list $struct"
+		eval field_${struct}_$field=\"\$*\"
+		eval numfld_$struct=\$field
+		field=$(($field + 1))
+		;;
+	* )
+		define=$1
+		struct=$2
+		echo "#define $define $tagno"
+		tagno=$(($tagno + 1))
+		eval define_$struct=\"\$define_$struct \$define\"
+		struct_define="$struct_define $struct"
+		field=0
+		;;
+	esac
+done
+
+echo
+
+IFS=' '
+for struct in $struct_list; do
+	echo
+	echo
+	echo "struct $struct {"
+	field=0
+	while
+		eval line=\"\$field_${struct}_$field\"
+		field=$(($field + 1))
+		[ -n "$line" ]
+	do
+		IFS=' '
+		set -- $line
+		name=$1
+		case $2 in
+		nodeptr ) type="union node *";;
+		nodelist ) type="struct nodelist *";;
+		string ) type="char *";;
+		int ) type="int ";;
+		* ) name=; shift 2; type="$*";;
+		esac
+		echo "      $type$name;"
+	done
+	echo "};"
+done
+
+echo
+echo
+echo "union node {"
+echo "      int type;"
+for struct in $struct_list; do
+	echo "      struct $struct $struct;"
+done
+echo "};"
+echo
+echo
+echo "struct nodelist {"
+echo "	struct nodelist *next;"
+echo "	union node *n;"
+echo "};"
+echo
+echo
+echo "union node *copyfunc(union node *);"
+echo "void freefunc(union node *);"
+
+exec <$nodes_pat
+exec >$objdir/nodes.c.tmp
+mv -f $objdir/nodes.h.tmp $objdir/nodes.h || exit 1
+
+echo "/*"
+echo " * This file was generated by mknodes.sh"
+echo " */"
+echo
+
+while IFS=; read -r line; do
+	IFS=' 	'
+	set -- $line
+	IFS=
+	case "$1" in
+	'%SIZES' )
+		echo "static const short nodesize[$tagno] = {"
+		IFS=' '
+		for struct in $struct_define; do
+			echo "      SHELL_ALIGN(sizeof (struct $struct)),"
+		done
+		echo "};"
+		;;
+	'%CALCSIZE' )
+		echo "      if (n == NULL)"
+		echo "	    return;"
+		echo "      funcblocksize += nodesize[n->type];"
+		echo "      switch (n->type) {"
+		IFS=' '
+		for struct in $struct_list; do
+			eval defines=\"\$define_$struct\"
+			for define in $defines; do
+				echo "      case $define:"
+			done
+			eval field=\$numfld_$struct
+			while
+				[ $field != 0 ]
+			do
+				eval line=\"\$field_${struct}_$field\"
+				field=$(($field - 1))
+				IFS=' '
+				set -- $line
+				name=$1
+				cl=")"
+				case $2 in
+				nodeptr ) fn=calcsize;;
+				nodelist ) fn=sizenodelist;;
+				string ) fn="funcstringsize += strlen"
+					cl=") + 1";;
+				* ) continue;;
+				esac
+				echo "	    ${fn}(n->$struct.$name${cl};"
+			done
+			echo "	    break;"
+		done
+		echo "      };"
+		;;
+	'%COPY' )
+		echo "      if (n == NULL)"
+		echo "	    return NULL;"
+		echo "      new = funcblock;"
+		echo "      funcblock = (char *) funcblock + nodesize[n->type];"
+		echo "      switch (n->type) {"
+		IFS=' '
+		for struct in $struct_list; do
+			eval defines=\"\$define_$struct\"
+			for define in $defines; do
+				echo "      case $define:"
+			done
+			eval field=\$numfld_$struct
+			while
+				[ $field != 0 ]
+			do
+				eval line=\"\$field_${struct}_$field\"
+				field=$(($field - 1))
+				IFS=' '
+				set -- $line
+				name=$1
+				case $2 in
+				nodeptr ) fn="copynode(";;
+				nodelist ) fn="copynodelist(";;
+				string ) fn="nodesavestr(";;
+				int ) fn=;;
+				* ) continue;;
+				esac
+				f="$struct.$name"
+				echo "	    new->$f = ${fn}n->$f${fn:+)};"
+			done
+			echo "	    break;"
+		done
+		echo "      };"
+		echo "      new->type = n->type;"
+		;;
+	* ) echo "$line";;
+	esac
+done
+
+exec >/dev/null
+mv -f $objdir/nodes.c.tmp $objdir/nodes.c || exit 1
Index: /tags/kBuild-0.1.4/src/kash/mktokens
===================================================================
--- /tags/kBuild-0.1.4/src/kash/mktokens	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/mktokens	(revision 1780)
@@ -0,0 +1,98 @@
+#!/bin/sh -
+#	$NetBSD: mktokens,v 1.10 2003/08/22 11:22:23 agc Exp $
+#
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)mktokens	8.1 (Berkeley) 5/31/93
+
+# The following is a list of tokens.  The second column is nonzero if the
+# token marks the end of a list.  The third column is the name to print in
+# error messages.
+
+if [ -z "$TMPDIR" ]; then
+    TMPDIR="/tmp"
+    export TMPDIR
+fi
+F="$TMPDIR/ka$$"
+echo $F
+cat > $F <<\!
+TEOF	1	end of file
+TNL	0	newline
+TSEMI	0	";"
+TBACKGND 0	"&"
+TAND	0	"&&"
+TOR	0	"||"
+TPIPE	0	"|"
+TLP	0	"("
+TRP	1	")"
+TENDCASE 1	";;"
+TENDBQUOTE 1	"`"
+TREDIR	0	redirection
+TWORD	0	word
+TIF	0	"if"
+TTHEN	1	"then"
+TELSE	1	"else"
+TELIF	1	"elif"
+TFI	1	"fi"
+TWHILE	0	"while"
+TUNTIL	0	"until"
+TFOR	0	"for"
+TDO	1	"do"
+TDONE	1	"done"
+TBEGIN	0	"{"
+TEND	1	"}"
+TCASE	0	"case"
+TESAC	1	"esac"
+TNOT	0	"!"
+!
+nl=`wc -l $F`
+exec > token.h
+awk '{print "#define " $1 " " NR-1}' $F
+echo '
+/* Array indicating which tokens mark the end of a list */
+const char tokendlist[] = {'
+awk '{print "\t" $2 ","}' $F
+echo '};
+
+const char *const tokname[] = {'
+sed -e 's/"/\\"/g' \
+    -e 's/[^	 ]*[	 ][	 ]*[^	 ]*[	 ][	 ]*\(.*\)/	"\1",/' \
+    $F
+echo '};
+'
+sed 's/"//g' $F | awk '
+/TIF/{print "#define KWDOFFSET " NR-1; print "";
+      print "const char *const parsekwd[] = {"}
+/TIF/,/neverfound/{print "	\"" $3 "\","}'
+echo '	0
+};'
+
+rm $F
Index: /tags/kBuild-0.1.4/src/kash/myhistedit.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/myhistedit.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/myhistedit.h	(revision 1780)
@@ -0,0 +1,49 @@
+/*	$NetBSD: myhistedit.h,v 1.10 2003/08/07 09:05:35 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)myhistedit.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef SMALL
+#include <histedit.h>
+
+/*extern History *hist;
+extern EditLine *el;*/
+#endif
+/*extern int displayhist;*/
+
+void histedit(struct shinstance *);
+void sethistsize(struct shinstance *, const char *);
+void setterm(struct shinstance *, const char *);
+int histcmd(struct shinstance *, int, char **);
+int inputrc(struct shinstance *, int, char **);
+int not_fcnumber(struct shinstance *, char *);
+int str_to_event(struct shinstance *, const char *, int);
+
Index: /tags/kBuild-0.1.4/src/kash/mystring.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/mystring.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/mystring.c	(revision 1780)
@@ -0,0 +1,132 @@
+/*	$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)mystring.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $");
+#endif /* not lint */
+#endif
+
+/*
+ * String functions.
+ *
+ *	equal(s1, s2)		Return true if strings are equal.
+ *	scopy(from, to)		Copy a string.
+ *	scopyn(from, to, n)	Like scopy, but checks for overflow.
+ *	number(s)		Convert a string of digits to an integer.
+ *	is_number(s)		Return true if s is a string of digits.
+ */
+
+#include <stdlib.h>
+#include "shell.h"
+#include "syntax.h"
+#include "error.h"
+#include "mystring.h"
+
+
+char nullstr[1];		/* zero length string */
+
+/*
+ * equal - #defined in mystring.h
+ */
+
+/*
+ * scopy - #defined in mystring.h
+ */
+
+
+/*
+ * scopyn - copy a string from "from" to "to", truncating the string
+ *		if necessary.  "To" is always nul terminated, even if
+ *		truncation is performed.  "Size" is the size of "to".
+ */
+
+void
+scopyn(const char *from, char *to, ssize_t size)
+{
+
+	while (--size > 0) {
+		if ((*to++ = *from++) == '\0')
+			return;
+	}
+	*to = '\0';
+}
+
+
+/*
+ * prefix -- see if pfx is a prefix of string.
+ */
+
+int
+prefix(const char *pfx, const char *string)
+{
+	while (*pfx) {
+		if (*pfx++ != *string++)
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Convert a string of digits to an integer, printing an error message on
+ * failure.
+ */
+
+int
+number(shinstance *psh, const char *s)
+{
+
+	if (! is_number(s))
+		error(psh, "Illegal number: %s", s);
+	return atoi(s);
+}
+
+
+
+/*
+ * Check for a valid number.  This should be elsewhere.
+ */
+
+int
+is_number(const char *p)
+{
+	do {
+		if (! is_digit(*p))
+			return 0;
+	} while (*++p != '\0');
+	return 1;
+}
Index: /tags/kBuild-0.1.4/src/kash/mystring.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/mystring.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/mystring.h	(revision 1780)
@@ -0,0 +1,54 @@
+/*	$NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)mystring.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef ___mystring_h
+#define ___mystring_h
+
+#include <string.h>
+#include "shtypes.h" /* ssize_t */
+
+void scopyn(const char *, char *, ssize_t);
+int prefix(const char *, const char *);
+int number(struct shinstance *, const char *);
+int is_number(const char *);
+#ifdef _MSC_VER
+size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+
+#define equal(s1, s2)	(strcmp(s1, s2) == 0)
+#define scopy(s1, s2)	((void)strcpy(s2, s1))
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/nodes.c.pat
===================================================================
--- /tags/kBuild-0.1.4/src/kash/nodes.c.pat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/nodes.c.pat	(revision 1780)
@@ -0,0 +1,166 @@
+/*	$NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
+ */
+
+#include <stdlib.h>
+/*
+ * Routine for dealing with parsed shell commands.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "memalloc.h"
+#include "machdep.h"
+#include "mystring.h"
+
+
+int     funcblocksize;		/* size of structures in function */
+int     funcstringsize;		/* size of strings in node */
+pointer funcblock;		/* block to allocate function from */
+char   *funcstring;		/* block to allocate strings from */
+
+%SIZES
+
+
+STATIC void calcsize(union node *);
+STATIC void sizenodelist(struct nodelist *);
+STATIC union node *copynode(union node *);
+STATIC struct nodelist *copynodelist(struct nodelist *);
+STATIC char *nodesavestr(char *);
+
+
+
+/*
+ * Make a copy of a parse tree.
+ */
+
+union node *
+copyfunc(n)
+	union node *n;
+{
+	if (n == NULL)
+		return NULL;
+	funcblocksize = 0;
+	funcstringsize = 0;
+	calcsize(n);
+	funcblock = ckmalloc(funcblocksize + funcstringsize);
+	funcstring = (char *) funcblock + funcblocksize;
+	return copynode(n);
+}
+
+
+
+STATIC void
+calcsize(n)
+	union node *n;
+{
+	%CALCSIZE
+}
+
+
+
+STATIC void
+sizenodelist(lp)
+	struct nodelist *lp;
+{
+	while (lp) {
+		funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
+		calcsize(lp->n);
+		lp = lp->next;
+	}
+}
+
+
+
+STATIC union node *
+copynode(n)
+	union node *n;
+{
+	union node *new;
+
+	%COPY
+	return new;
+}
+
+
+STATIC struct nodelist *
+copynodelist(lp)
+	struct nodelist *lp;
+{
+	struct nodelist *start;
+	struct nodelist **lpp;
+
+	lpp = &start;
+	while (lp) {
+		*lpp = funcblock;
+		funcblock = (char *) funcblock +
+		    SHELL_ALIGN(sizeof(struct nodelist));
+		(*lpp)->n = copynode(lp->n);
+		lp = lp->next;
+		lpp = &(*lpp)->next;
+	}
+	*lpp = NULL;
+	return start;
+}
+
+
+
+STATIC char *
+nodesavestr(s)
+	char   *s;
+{
+	register char *p = s;
+	register char *q = funcstring;
+	char   *rtn = funcstring;
+
+	while ((*q++ = *p++) != 0)
+		continue;
+	funcstring = q;
+	return rtn;
+}
+
+
+
+/*
+ * Free a parse tree.
+ */
+
+void
+freefunc(n)
+	union node *n;
+{
+	if (n)
+		ckfree(n);
+}
Index: /tags/kBuild-0.1.4/src/kash/nodetypes
===================================================================
--- /tags/kBuild-0.1.4/src/kash/nodetypes	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/nodetypes	(revision 1780)
@@ -0,0 +1,143 @@
+#	$NetBSD: nodetypes,v 1.12 2003/08/22 11:22:23 agc Exp $
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	@(#)nodetypes	8.2 (Berkeley) 5/4/95
+
+# This file describes the nodes used in parse trees.  Unindented lines
+# contain a node type followed by a structure tag.  Subsequent indented
+# lines specify the fields of the structure.  Several node types can share
+# the same structure, in which case the fields of the structure should be
+# specified only once.
+#
+# A field of a structure is described by the name of the field followed
+# by a type.  The currently implemented types are:
+#	nodeptr - a pointer to a node
+#	nodelist - a pointer to a list of nodes
+#	string - a pointer to a nul terminated string
+#	int - an integer
+#	other - any type that can be copied by assignment
+#	temp - a field that doesn't have to be copied when the node is copied
+# The last two types should be followed by the text of a C declaration for
+# the field.
+
+NSEMI nbinary			# two commands separated by a semicolon
+	type	  int
+	ch1	  nodeptr		# the first child
+	ch2	  nodeptr		# the second child
+
+NCMD ncmd			# a simple command
+	type	  int
+	backgnd	  int			# set to run command in background
+	args	  nodeptr		# the arguments
+	redirect  nodeptr		# list of file redirections
+
+NPIPE npipe			# a pipeline
+	type	  int
+	backgnd	  int			# set to run pipeline in background
+	cmdlist	  nodelist		# the commands in the pipeline
+
+NREDIR nredir			# redirection (of a complex command)
+	type	  int
+	n	  nodeptr		# the command
+	redirect  nodeptr		# list of file redirections
+
+NBACKGND nredir			# run command in background
+NSUBSHELL nredir		# run command in a subshell
+
+NAND nbinary			# the && operator
+NOR nbinary			# the || operator
+
+NIF nif				# the if statement.  Elif clauses are handled
+	type	  int		    # using multiple if nodes.
+	test	  nodeptr		# if test
+	ifpart	  nodeptr		# then ifpart
+	elsepart  nodeptr		# else elsepart
+
+NWHILE nbinary			# the while statement.  First child is the test
+NUNTIL nbinary			# the until statement
+
+NFOR nfor			# the for statement
+	type	  int
+	args	  nodeptr		# for var in args
+	body	  nodeptr		# do body; done
+	var	  string		# the for variable
+
+NCASE ncase			# a case statement
+	type	  int
+	expr	  nodeptr		# the word to switch on
+	cases	  nodeptr		# the list of cases (NCLIST nodes)
+
+NCLIST nclist			# a case
+	type	  int
+	next	  nodeptr		# the next case in list
+	pattern	  nodeptr		# list of patterns for this case
+	body	  nodeptr		# code to execute for this case
+
+
+NDEFUN narg			# define a function.  The "next" field contains
+				# the body of the function.
+
+NARG narg			# represents a word
+	type	  int
+	next	  nodeptr		# next word in list
+	text	  string		# the text of the word
+	backquote nodelist		# list of commands in back quotes
+
+NTO nfile			# fd> fname
+NCLOBBER nfile			# fd>| fname
+NFROM nfile			# fd< fname
+NFROMTO nfile			# fd<> fname
+NAPPEND nfile			# fd>> fname
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	fname	  nodeptr		# file name, in a NARG node
+	expfname  temp	char *expfname	# actual file name
+
+NTOFD ndup			# fd<&dupfd
+NFROMFD ndup			# fd>&dupfd
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	dupfd	  int			# file descriptor to duplicate
+	vname	  nodeptr		# file name if fd>&$var
+
+
+NHERE nhere			# fd<<\!
+NXHERE nhere			# fd<<!
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	doc	  nodeptr		# input to command (NARG node)
+
+NNOT nnot			# ! command  (actually pipeline)
+	type	int
+	com	nodeptr
Index: /tags/kBuild-0.1.4/src/kash/options.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/options.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/options.c	(revision 1780)
@@ -0,0 +1,532 @@
+/*	$NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdlib.h>
+
+#include "shell.h"
+#define DEFINE_OPTIONS
+#include "options.h"
+#undef DEFINE_OPTIONS
+#include "nodes.h"	/* for other header files */
+#include "eval.h"
+#include "jobs.h"
+#include "input.h"
+#include "output.h"
+#include "trap.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#ifndef SMALL
+# include "myhistedit.h"
+#endif
+#include "show.h"
+#include "shinstance.h"
+
+//char *arg0;			/* value of $0 */
+//struct shparam shellparam;	/* current positional parameters */
+//char **argptr;			/* argument list for builtin commands */
+//char *optionarg;		/* set by nextopt (like getopt) */
+//char *optptr;			/* used by nextopt */
+
+//char *minusc;			/* argument to -c option */
+
+
+STATIC void options(shinstance *, int);
+STATIC void minus_o(shinstance *, char *, int);
+STATIC void setoption(shinstance *, int, int);
+STATIC int getopts(shinstance *, char *, char *, char **, char ***, char **);
+
+
+/*
+ * Process the shell command line arguments.
+ */
+
+void
+procargs(shinstance *psh, int argc, char **argv)
+{
+	int i;
+
+	psh->argptr = argv;
+	if (argc > 0)
+		psh->argptr++;
+	for (i = 0; i < NOPTS; i++)
+		psh->optlist[i].val = 2;
+	options(psh, 1);
+	if (*psh->argptr == NULL && psh->minusc == NULL)
+		sflag(psh) = 1;
+	if (iflag(psh) == 2 && sflag(psh) == 1 && shfile_isatty(&psh->fdtab, 0) && shfile_isatty(&psh->fdtab, 1))
+		iflag(psh) = 1;
+	if (mflag(psh) == 2)
+		mflag(psh) = iflag(psh);
+	for (i = 0; i < NOPTS; i++)
+		if (psh->optlist[i].val == 2)
+			psh->optlist[i].val = 0;
+#if DEBUG == 2
+	debug(psh) = 1;
+#endif
+	psh->arg0 = argv[0];
+	if (sflag(psh) == 0 && psh->minusc == NULL) {
+		psh->commandname = argv[0];
+		psh->arg0 = *psh->argptr++;
+		setinputfile(psh, psh->arg0, 0);
+		psh->commandname = psh->arg0;
+	}
+	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
+	if (psh->minusc != NULL) {
+		if (psh->argptr == NULL || *psh->argptr == NULL)
+			error(psh, "Bad -c option");
+		psh->minusc = *psh->argptr++;
+		if (*psh->argptr != 0)
+			psh->arg0 = *psh->argptr++;
+	}
+
+	psh->shellparam.p = psh->argptr;
+	psh->shellparam.reset = 1;
+	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
+	while (*psh->argptr) {
+		psh->shellparam.nparam++;
+		psh->argptr++;
+	}
+	optschanged(psh);
+}
+
+
+void
+optschanged(shinstance *psh)
+{
+	setinteractive(psh, iflag(psh));
+#ifndef SMALL
+	histedit(psh);
+#endif
+	setjobctl(psh, mflag(psh));
+}
+
+/*
+ * Process shell options.  The global variable argptr contains a pointer
+ * to the argument list; we advance it past the options.
+ */
+
+STATIC void
+options(shinstance *psh, int cmdline)
+{
+	static char empty[] = "";
+	char *p;
+	int val;
+	int c;
+
+	if (cmdline)
+		psh->minusc = NULL;
+	while ((p = *psh->argptr) != NULL) {
+		psh->argptr++;
+		if ((c = *p++) == '-') {
+			val = 1;
+                        if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
+                                if (!cmdline) {
+                                        /* "-" means turn off -x and -v */
+                                        if (p[0] == '\0')
+                                                xflag(psh) = vflag(psh) = 0;
+                                        /* "--" means reset params */
+                                        else if (*psh->argptr == NULL)
+						setparam(psh, psh->argptr);
+                                }
+				break;	  /* "-" or  "--" terminates options */
+			}
+		} else if (c == '+') {
+			val = 0;
+		} else {
+			psh->argptr--;
+			break;
+		}
+		while ((c = *p++) != '\0') {
+			if (c == 'c' && cmdline) {
+				/* command is after shell args*/
+				psh->minusc = empty;
+			} else if (c == 'o') {
+				minus_o(psh, *psh->argptr, val);
+				if (*psh->argptr)
+					psh->argptr++;
+			} else {
+				setoption(psh, c, val);
+			}
+		}
+	}
+}
+
+static void
+set_opt_val(shinstance *psh, int i, int val)
+{
+	int j;
+	int flag;
+
+	if (val && (flag = psh->optlist[i].opt_set)) {
+		/* some options (eg vi/emacs) are mutually exclusive */
+		for (j = 0; j < NOPTS; j++)
+		    if (psh->optlist[j].opt_set == flag)
+			psh->optlist[j].val = 0;
+	}
+	psh->optlist[i].val = val;
+#ifdef DEBUG
+	if (&psh->optlist[i].val == &debug(psh))
+		opentrace(psh);
+#endif
+}
+
+STATIC void
+minus_o(shinstance *psh, char *name, int val)
+{
+	int i;
+
+	if (name == NULL) {
+		out1str(psh, "Current option settings\n");
+		for (i = 0; i < NOPTS; i++)
+			out1fmt(psh, "%-16s%s\n", psh->optlist[i].name,
+				psh->optlist[i].val ? "on" : "off");
+	} else {
+		for (i = 0; i < NOPTS; i++)
+			if (equal(name, psh->optlist[i].name)) {
+				set_opt_val(psh, i, val);
+				return;
+			}
+		error(psh, "Illegal option -o %s", name);
+	}
+}
+
+
+STATIC void
+setoption(shinstance *psh, int flag, int val)
+{
+	int i;
+
+	for (i = 0; i < NOPTS; i++)
+		if (psh->optlist[i].letter == flag) {
+			set_opt_val(psh, i, val);
+			return;
+		}
+	error(psh, "Illegal option -%c", flag);
+	/* NOTREACHED */
+}
+
+
+
+#ifdef mkinit
+INCLUDE "options.h"
+
+INIT {
+	memcpy(&psh->optlist[0], &ro_optlist[0], sizeof(psh->optlist));
+}
+
+SHELLPROC {
+	int i;
+
+	for (i = 0; psh->optlist[i].name; i++)
+		psh->optlist[i].val = 0;
+	optschanged(psh);
+
+}
+#endif
+
+
+/*
+ * Set the shell parameters.
+ */
+
+void
+setparam(shinstance *psh, char **argv)
+{
+	char **newparam;
+	char **ap;
+	int nparam;
+
+	for (nparam = 0 ; argv[nparam] ; nparam++)
+		continue;
+	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
+	while (*argv) {
+		*ap++ = savestr(*argv++);
+	}
+	*ap = NULL;
+	freeparam(&psh->shellparam);
+	psh->shellparam.malloc = 1;
+	psh->shellparam.nparam = nparam;
+	psh->shellparam.p = newparam;
+	psh->shellparam.optnext = NULL;
+}
+
+
+/*
+ * Free the list of positional parameters.
+ */
+
+void
+freeparam(volatile struct shparam *param)
+{
+	char **ap;
+
+	if (param->malloc) {
+		for (ap = param->p ; *ap ; ap++)
+			ckfree(*ap);
+		ckfree(param->p);
+	}
+}
+
+
+
+/*
+ * The shift builtin command.
+ */
+
+int
+shiftcmd(shinstance *psh, int argc, char **argv)
+{
+	int n;
+	char **ap1, **ap2;
+
+	n = 1;
+	if (argc > 1)
+		n = number(psh, argv[1]);
+	if (n > psh->shellparam.nparam)
+		error(psh, "can't shift that many");
+	INTOFF;
+	psh->shellparam.nparam -= n;
+	for (ap1 = psh->shellparam.p ; --n >= 0 ; ap1++) {
+		if (psh->shellparam.malloc)
+			ckfree(*ap1);
+	}
+	ap2 = psh->shellparam.p;
+	while ((*ap2++ = *ap1++) != NULL);
+	psh->shellparam.optnext = NULL;
+	INTON;
+	return 0;
+}
+
+
+
+/*
+ * The set command builtin.
+ */
+
+int
+setcmd(shinstance *psh, int argc, char **argv)
+{
+	if (argc == 1)
+		return showvars(psh, 0, 0, 1);
+	INTOFF;
+	options(psh, 0);
+	optschanged(psh);
+	if (*psh->argptr != NULL) {
+		setparam(psh, psh->argptr);
+	}
+	INTON;
+	return 0;
+}
+
+
+void
+getoptsreset(shinstance *psh, const char *value)
+{
+	if (number(psh, value) == 1) {
+		psh->shellparam.optnext = NULL;
+		psh->shellparam.reset = 1;
+	}
+}
+
+/*
+ * The getopts builtin.  Shellparam.optnext points to the next argument
+ * to be processed.  Shellparam.optptr points to the next character to
+ * be processed in the current argument.  If shellparam.optnext is NULL,
+ * then it's the first time getopts has been called.
+ */
+
+int
+getoptscmd(shinstance *psh, int argc, char **argv)
+{
+	char **optbase;
+
+	if (argc < 3)
+		error(psh, "usage: getopts optstring var [arg]");
+	else if (argc == 3)
+		optbase = psh->shellparam.p;
+	else
+		optbase = &argv[3];
+
+	if (psh->shellparam.reset == 1) {
+		psh->shellparam.optnext = optbase;
+		psh->shellparam.optptr = NULL;
+		psh->shellparam.reset = 0;
+	}
+
+	return getopts(psh, argv[1], argv[2], optbase, &psh->shellparam.optnext,
+		       &psh->shellparam.optptr);
+}
+
+STATIC int
+getopts(shinstance *psh, char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
+{
+	char *p, *q;
+	char c = '?';
+	int done = 0;
+	int ind = 0;
+	int err = 0;
+	char s[12];
+
+	if ((p = *optpptr) == NULL || *p == '\0') {
+		/* Current word is done, advance */
+		if (*optnext == NULL)
+			return 1;
+		p = **optnext;
+		if (p == NULL || *p != '-' || *++p == '\0') {
+atend:
+			ind = (int)(*optnext - optfirst + 1);
+			*optnext = NULL;
+			p = NULL;
+			done = 1;
+			goto out;
+		}
+		(*optnext)++;
+		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+			goto atend;
+	}
+
+	c = *p++;
+	for (q = optstr; *q != c; ) {
+		if (*q == '\0') {
+			if (optstr[0] == ':') {
+				s[0] = c;
+				s[1] = '\0';
+				err |= setvarsafe(psh, "OPTARG", s, 0);
+			} else {
+				outfmt(&psh->errout, "Illegal option -%c\n", c);
+				(void) unsetvar(psh, "OPTARG", 0);
+			}
+			c = '?';
+			goto bad;
+		}
+		if (*++q == ':')
+			q++;
+	}
+
+	if (*++q == ':') {
+		if (*p == '\0' && (p = **optnext) == NULL) {
+			if (optstr[0] == ':') {
+				s[0] = c;
+				s[1] = '\0';
+				err |= setvarsafe(psh, "OPTARG", s, 0);
+				c = ':';
+			} else {
+				outfmt(&psh->errout, "No arg for -%c option\n", c);
+				(void) unsetvar(psh, "OPTARG", 0);
+				c = '?';
+			}
+			goto bad;
+		}
+
+		if (p == **optnext)
+			(*optnext)++;
+		err |= setvarsafe(psh, "OPTARG", p, 0);
+		p = NULL;
+	} else
+		err |= setvarsafe(psh, "OPTARG", "", 0);
+	ind = (int)(*optnext - optfirst + 1);
+	goto out;
+
+bad:
+	ind = 1;
+	*optnext = NULL;
+	p = NULL;
+out:
+	*optpptr = p;
+	fmtstr(s, sizeof(s), "%d", ind);
+	err |= setvarsafe(psh, "OPTIND", s, VNOFUNC);
+	s[0] = c;
+	s[1] = '\0';
+	err |= setvarsafe(psh, optvar, s, 0);
+	if (err) {
+		*optnext = NULL;
+		*optpptr = NULL;
+		output_flushall(psh);
+		exraise(psh, EXERROR);
+	}
+	return done;
+}
+
+/*
+ * XXX - should get rid of.  have all builtins use getopt(3).  the
+ * library getopt must have the BSD extension static variable "optreset"
+ * otherwise it can't be used within the shell safely.
+ *
+ * Standard option processing (a la getopt) for builtin routines.  The
+ * only argument that is passed to nextopt is the option string; the
+ * other arguments are unnecessary.  It return the character, or '\0' on
+ * end of input.
+ */
+
+int
+nextopt(shinstance *psh, const char *optstring)
+{
+	char *p;
+	const char *q;
+	char c;
+
+	if ((p = psh->optptr) == NULL || *p == '\0') {
+		p = *psh->argptr;
+		if (p == NULL || *p != '-' || *++p == '\0')
+			return '\0';
+		psh->argptr++;
+		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+			return '\0';
+	}
+	c = *p++;
+	for (q = optstring ; *q != c ; ) {
+		if (*q == '\0')
+			error(psh, "Illegal option -%c", c);
+		if (*++q == ':')
+			q++;
+	}
+	if (*++q == ':') {
+		if (*p == '\0' && (p = *psh->argptr++) == NULL)
+			error(psh, "No arg for -%c option", c);
+		psh->optionarg = p;
+		p = NULL;
+	}
+	psh->optptr = p;
+	return c;
+}
Index: /tags/kBuild-0.1.4/src/kash/options.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/options.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/options.h	(revision 1780)
@@ -0,0 +1,142 @@
+/*	$NetBSD: options.h,v 1.18 2005/05/07 19:52:17 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)options.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef ___options_h
+#define ___options_h
+
+struct shparam {
+	int nparam;		/* # of positional parameters (without $0) */
+	unsigned char malloc;	/* if parameter list dynamically allocated */
+	unsigned char reset;	/* if getopts has been reset */
+	char **p;		/* parameter list */
+	char **optnext;		/* next parameter to be processed by getopts */
+	char *optptr;		/* used by getopts */
+};
+
+
+struct optent {
+	const char *name;		/* for set -o <name> */
+	const char letter;		/* set [+/-]<letter> and $- */
+	const char opt_set;		/* mutually exclusive option set */
+	char val;			/* value of <letter>flag */
+};
+
+/* Those marked [U] are required by posix, but have no effect! */
+
+#ifdef DEBUG
+# define NOPTS 21
+#else
+# define NOPTS 20
+#endif
+
+#ifdef DEFINE_OPTIONS
+# define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0},
+const struct optent ro_optlist[NOPTS] = {
+#else
+# define DEF_OPTS(name, letter, opt_set)
+#endif
+#define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0)
+
+DEF_OPT( "errexit",	'e' )	/* exit on error */
+#define eflag(psh) (psh)->optlist[0].val
+DEF_OPT( "noglob",	'f' )	/* no pathname expansion */
+#define fflag(psh) (psh)->optlist[1].val
+DEF_OPT( "ignoreeof",	'I' )	/* do not exit on EOF */
+#define Iflag(psh) (psh)->optlist[2].val
+DEF_OPT( "interactive",'i' )	/* interactive shell */
+#define iflag(psh) (psh)->optlist[3].val
+DEF_OPT( "monitor",	'm' )	/* job control */
+#define mflag(psh) (psh)->optlist[4].val
+DEF_OPT( "noexec",	'n' )	/* [U] do not exec commands */
+#define nflag(psh) (psh)->optlist[5].val
+DEF_OPT( "stdin",	's' )	/* read from stdin */
+#define sflag(psh) (psh)->optlist[6].val
+DEF_OPT( "xtrace",	'x' )	/* trace after expansion */
+#define xflag(psh) (psh)->optlist[7].val
+DEF_OPT( "verbose",	'v' )	/* trace read input */
+#define vflag(psh) (psh)->optlist[8].val
+DEF_OPTS( "vi",		'V', 'V' )	/* vi style editing */
+#define Vflag(psh) (psh)->optlist[9].val
+DEF_OPTS( "emacs",	'E', 'V' )	/* emacs style editing */
+#define	Eflag(psh) (psh)->optlist[10].val
+DEF_OPT( "noclobber",	'C' )	/* do not overwrite files with > */
+#define	Cflag(psh) (psh)->optlist[11].val
+DEF_OPT( "allexport",	'a' )	/* export all variables */
+#define	aflag(psh) (psh)->optlist[12].val
+DEF_OPT( "notify",	'b' )	/* [U] report completion of background jobs */
+#define	bflag(psh) (psh)->optlist[13].val
+DEF_OPT( "nounset",	'u' )	/* error expansion of unset variables */
+#define	uflag(psh) (psh)->optlist[14].val
+DEF_OPT( "quietprofile", 'q' )
+#define	qflag(psh) (psh)->optlist[15].val
+DEF_OPT( "nolog",	0 )	/* [U] no functon defs in command history */
+#define	nolog(psh) (psh)->optlist[16].val
+DEF_OPT( "cdprint",	0 )	/* always print result of cd */
+#define	cdprint(psh) (psh)->optlist[17].val
+DEF_OPT( "tabcomplete",	0 )	/* <tab> causes filename expansion */
+#define	tabcomplete(psh) (psh)->optlist[18].val
+#ifdef DEBUG
+DEF_OPT( "debug",	0 )	/* enable debug prints */
+#define	debug(psh) (psh)->optlist[19].val
+#endif
+
+#ifdef DEFINE_OPTIONS
+	{ 0, 0, 0, 0 },
+};
+#else
+extern const struct optent ro_optlist[];
+#endif
+#define sizeof_optlist (NOPTS * sizeof(struct optent))
+
+
+/*extern char *minusc;*/		/* argument to -c option */
+/*extern char *arg0;*/		/* $0 */
+/*extern struct shparam shellparam;*/  /* $@ */
+/*extern char **argptr;*/		/* argument list for builtin commands */
+/*extern char *optionarg;*/		/* set by nextopt */
+/*extern char *optptr;*/		/* used by nextopt */
+
+void procargs(struct shinstance *, int, char **);
+void optschanged(struct shinstance *);
+void setparam(struct shinstance *, char **);
+void freeparam(volatile struct shparam *);
+int shiftcmd(struct shinstance *, int, char **);
+int setcmd(struct shinstance *, int, char **);
+int getoptscmd(struct shinstance *, int, char **);
+int nextopt(struct shinstance *, const char *);
+void getoptsreset(struct shinstance *, const char *);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/output.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/output.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/output.c	(revision 1780)
@@ -0,0 +1,493 @@
+/*	$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $");
+#endif /* not lint */
+#endif
+
+/*
+ * Shell output routines.  We use our own output routines because:
+ *	When a builtin command is interrupted we have to discard
+ *		any pending output.
+ *	When a builtin command appears in back quotes, we want to
+ *		save the output of the command in a region obtained
+ *		via malloc, rather than doing a fork and reading the
+ *		output of the command via a pipe.
+ *	Our output routines may be smaller than the stdio routines.
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>	/* defines BUFSIZ */
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "syntax.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "shinstance.h"
+
+//#define OUTBUFSIZ BUFSIZ
+#define BLOCK_OUT -2		/* output to a fixed block of memory */
+//#define MEM_OUT -3		/* output to dynamically allocated memory */
+#define OUTPUT_ERR 01		/* error occurred on output */
+
+
+//struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
+//struct output errout = {NULL, 0, NULL, 100, 2, 0};
+//struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
+//struct output *out1 = &output;
+//struct output *out2 = &errout;
+
+
+
+#ifdef mkinit
+
+INCLUDE "output.h"
+INCLUDE "memalloc.h"
+
+RESET {
+	psh->out1 = &psh->output;
+	psh->out2 = &psh->errout;
+	if (psh->memout.buf != NULL) {
+		ckfree(psh->memout.buf);
+		psh->memout.buf = NULL;
+	}
+}
+
+#endif
+
+
+#ifdef notdef	/* no longer used */
+/*
+ * Set up an output file to write to memory rather than a file.
+ */
+
+void
+open_mem(char *block, int length, struct output *file)
+{
+	file->nextc = block;
+	file->nleft = --length;
+	file->fd = BLOCK_OUT;
+	file->flags = 0;
+	file->psh = psh;
+}
+#endif
+
+
+void
+out1str(shinstance *psh, const char *p)
+{
+	outstr(p, psh->out1);
+}
+
+
+void
+out2str(shinstance *psh, const char *p)
+{
+	outstr(p, psh->out2);
+}
+
+
+void
+outstr(const char *p, struct output *file)
+{
+	while (*p)
+		outc(*p++, file);
+	if (file == file->psh->out2)
+		flushout(file);
+}
+
+
+char out_junk[16];
+
+
+void
+emptyoutbuf(struct output *dest)
+{
+	int offset;
+	shinstance *psh = dest->psh;
+
+	if (dest->fd == BLOCK_OUT) {
+		dest->nextc = out_junk;
+		dest->nleft = sizeof out_junk;
+		dest->flags |= OUTPUT_ERR;
+	} else if (dest->buf == NULL) {
+		INTOFF;
+		dest->buf = ckmalloc(dest->bufsize);
+		dest->nextc = dest->buf;
+		dest->nleft = dest->bufsize;
+		INTON;
+	} else if (dest->fd == MEM_OUT) {
+		offset = dest->bufsize;
+		INTOFF;
+		dest->bufsize <<= 1;
+		dest->buf = ckrealloc(dest->buf, dest->bufsize);
+		dest->nleft = dest->bufsize - offset;
+		dest->nextc = dest->buf + offset;
+		INTON;
+	} else {
+		flushout(dest);
+	}
+	dest->nleft--;
+}
+
+
+void
+output_flushall(shinstance *psh)
+{
+	flushout(&psh->output);
+	flushout(&psh->errout);
+}
+
+
+void
+flushout(struct output *dest)
+{
+
+	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
+		return;
+	if (xwrite(dest->psh, dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
+		dest->flags |= OUTPUT_ERR;
+	dest->nextc = dest->buf;
+	dest->nleft = dest->bufsize;
+}
+
+
+void
+freestdout(shinstance *psh)
+{
+	INTOFF;
+	if (psh->output.buf) {
+		ckfree(psh->output.buf);
+		psh->output.buf = NULL;
+		psh->output.nleft = 0;
+	}
+	INTON;
+}
+
+
+void
+outfmt(struct output *file, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(file, fmt, ap);
+	va_end(ap);
+}
+
+
+void
+out1fmt(shinstance *psh, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(psh->out1, fmt, ap);
+	va_end(ap);
+}
+
+void
+dprintf(shinstance *psh, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(psh->out2, fmt, ap);
+	va_end(ap);
+	flushout(psh->out2);
+}
+
+void
+fmtstr(char *outbuf, size_t length, const char *fmt, ...)
+{
+	va_list ap;
+	struct output strout;
+
+	va_start(ap, fmt);
+	strout.nextc = outbuf;
+	strout.nleft = (int)length;
+	strout.fd = BLOCK_OUT;
+	strout.flags = 0;
+        strout.psh = NULL;
+	doformat(&strout, fmt, ap);
+	outc('\0', &strout);
+	if (strout.flags & OUTPUT_ERR)
+		outbuf[length - 1] = '\0';
+	va_end(ap);
+}
+
+/*
+ * Formatted output.  This routine handles a subset of the printf formats:
+ * - Formats supported: d, u, o, p, X, s, and c.
+ * - The x format is also accepted but is treated like X.
+ * - The l, ll and q modifiers are accepted.
+ * - The - and # flags are accepted; # only works with the o format.
+ * - Width and precision may be specified with any format except c.
+ * - An * may be given for the width or precision.
+ * - The obsolete practice of preceding the width with a zero to get
+ *   zero padding is not supported; use the precision field.
+ * - A % may be printed by writing %% in the format string.
+ */
+
+#define TEMPSIZE 32
+
+#ifdef BSD4_4
+#define HAVE_VASPRINTF 1
+#endif
+
+void
+doformat(struct output *dest, const char *f, va_list ap)
+{
+#ifdef HAVE_VASPRINTF
+	char *s;
+
+	vasprintf(&s, f, ap);
+	outstr(s, dest);
+	free(s);
+#else	/* !HAVE_VASPRINTF */
+	static const char digit_lower[] = "0123456789abcdef";
+	static const char digit_upper[] = "0123456789ABCDEF";
+	const char *digit;
+	char c;
+	char temp[TEMPSIZE];
+	int flushleft;
+	int sharp;
+	int width;
+	int prec;
+	int islong;
+	int isquad;
+	char *p;
+	int sign;
+	int64_t l;
+	uint64_t num;
+	unsigned base;
+	int len;
+	int size;
+	int pad;
+
+	while ((c = *f++) != '\0') {
+		if (c != '%') {
+			outc(c, dest);
+			continue;
+		}
+		flushleft = 0;
+		sharp = 0;
+		width = 0;
+		prec = -1;
+		islong = 0;
+		isquad = 0;
+		for (;;) {
+			if (*f == '-')
+				flushleft++;
+			else if (*f == '#')
+				sharp++;
+			else
+				break;
+			f++;
+		}
+		if (*f == '*') {
+			width = va_arg(ap, int);
+			f++;
+		} else {
+			while (is_digit(*f)) {
+				width = 10 * width + digit_val(*f++);
+			}
+		}
+		if (*f == '.') {
+			if (*++f == '*') {
+				prec = va_arg(ap, int);
+				f++;
+			} else {
+				prec = 0;
+				while (is_digit(*f)) {
+					prec = 10 * prec + digit_val(*f++);
+				}
+			}
+		}
+		if (*f == 'l') {
+			f++;
+			if (*f == 'l') {
+				isquad++;
+				f++;
+			} else
+				islong++;
+		} else if (*f == 'q') {
+			isquad++;
+			f++;
+		}
+		digit = digit_upper;
+		switch (*f) {
+		case 'd':
+			if (isquad)
+				l = va_arg(ap, int64_t);
+			else if (islong)
+				l = va_arg(ap, long);
+			else
+				l = va_arg(ap, int);
+			sign = 0;
+			num = l;
+			if (l < 0) {
+				num = -l;
+				sign = 1;
+			}
+			base = 10;
+			goto number;
+		case 'u':
+			base = 10;
+			goto uns_number;
+		case 'o':
+			base = 8;
+			goto uns_number;
+		case 'p':
+			outc('0', dest);
+			outc('x', dest);
+			/*FALLTHROUGH*/
+		case 'x':
+			/* we don't implement 'x'; treat like 'X' */
+			digit = digit_lower;
+		case 'X':
+			base = 16;
+uns_number:	  /* an unsigned number */
+			sign = 0;
+			if (isquad)
+				num = va_arg(ap, uint64_t);
+			else if (islong)
+				num = va_arg(ap, unsigned long);
+			else
+				num = va_arg(ap, unsigned int);
+number:		  /* process a number */
+			p = temp + TEMPSIZE - 1;
+			*p = '\0';
+			while (num) {
+				*--p = digit[num % base];
+				num /= base;
+			}
+			len = (int)((temp + TEMPSIZE - 1) - p);
+			if (prec < 0)
+				prec = 1;
+			if (sharp && *f == 'o' && prec <= len)
+				prec = len + 1;
+			pad = 0;
+			if (width) {
+				size = len;
+				if (size < prec)
+					size = prec;
+				size += sign;
+				pad = width - size;
+				if (flushleft == 0) {
+					while (--pad >= 0)
+						outc(' ', dest);
+				}
+			}
+			if (sign)
+				outc('-', dest);
+			prec -= len;
+			while (--prec >= 0)
+				outc('0', dest);
+			while (*p)
+				outc(*p++, dest);
+			while (--pad >= 0)
+				outc(' ', dest);
+			break;
+		case 's':
+			p = va_arg(ap, char *);
+			pad = 0;
+			if (width) {
+				len = (int)strlen(p);
+				if (prec >= 0 && len > prec)
+					len = prec;
+				pad = width - len;
+				if (flushleft == 0) {
+					while (--pad >= 0)
+						outc(' ', dest);
+				}
+			}
+			prec++;
+			while (--prec != 0 && *p)
+				outc(*p++, dest);
+			while (--pad >= 0)
+				outc(' ', dest);
+			break;
+		case 'c':
+			c = va_arg(ap, int);
+			outc(c, dest);
+			break;
+		default:
+			outc(*f, dest);
+			break;
+		}
+		f++;
+	}
+#endif	/* !HAVE_VASPRINTF */
+}
+
+
+
+/*
+ * Version of write which resumes after a signal is caught.
+ */
+
+int
+xwrite(shinstance *psh, int fd, char *buf, size_t nbytes)
+{
+	int ntry;
+	long i;
+	size_t n;
+
+	n = nbytes;
+	ntry = 0;
+	for (;;) {
+		i = shfile_write(&psh->fdtab, fd, buf, n);
+		if (i > 0) {
+			if ((n -= i) <= 0)
+				return (int)nbytes;
+			buf += i;
+			ntry = 0;
+		} else if (i == 0) {
+			if (++ntry > 10)
+				return (int)(nbytes - n);
+		} else if (errno != EINTR) {
+			return -1;
+		}
+	}
+}
Index: /tags/kBuild-0.1.4/src/kash/output.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/output.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/output.h	(revision 1780)
@@ -0,0 +1,85 @@
+/*	$NetBSD: output.h,v 1.17 2003/08/07 09:05:36 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)output.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef OUTPUT_INCL
+
+#include <stdarg.h>
+
+struct output {
+	char *nextc;
+	int nleft;
+	char *buf;
+	int bufsize;
+	short fd;
+	short flags;
+	struct shinstance *psh;
+};
+
+/*extern struct output output;
+extern struct output errout;
+extern struct output memout;
+extern struct output *out1;
+extern struct output *out2;*/
+#if !defined(__GNUC__) && !defined(__attribute__)
+# define __attribute__(a)
+#endif
+
+void open_mem(char *, int, struct output *);
+void out1str(struct shinstance *, const char *);
+void out2str(struct shinstance *, const char *);
+void outstr(const char *, struct output *);
+void emptyoutbuf(struct output *);
+void output_flushall(struct shinstance *);
+void flushout(struct output *);
+void freestdout(struct shinstance *);
+void outfmt(struct output *, const char *, ...)
+    __attribute__((__format__(__printf__,2,3)));
+void out1fmt(struct shinstance *, const char *, ...)
+    __attribute__((__format__(__printf__,2,3)));
+void dprintf(struct shinstance *, const char *, ...)
+    __attribute__((__format__(__printf__,2,3)));
+void fmtstr(char *, size_t, const char *, ...)
+    __attribute__((__format__(__printf__,3,4)));
+void doformat(struct output *, const char *, va_list);
+int xwrite(struct shinstance *, int, char *, size_t);
+int xioctl(struct shinstance *, int, unsigned long, char *);
+
+#define outc(c, file)	(--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
+#define out1c(psh, c)	outc(c, (psh)->out1);
+#define out2c(psh, c)	outc(c, (psh)->out2);
+
+#define OUTPUT_INCL
+#endif
Index: /tags/kBuild-0.1.4/src/kash/parser.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/parser.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/parser.c	(revision 1780)
@@ -0,0 +1,1775 @@
+/*	$NetBSD: parser.c,v 1.59 2005/03/21 20:10:29 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)parser.c	8.7 (Berkeley) 5/16/95";
+#else
+__RCSID("$NetBSD: parser.c,v 1.59 2005/03/21 20:10:29 dsl Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdlib.h>
+
+#include "shell.h"
+#include "parser.h"
+#include "nodes.h"
+#include "expand.h"	/* defines rmescapes() */
+#include "eval.h"	/* defines commandname */
+#include "redir.h"	/* defines copyfd() */
+#include "syntax.h"
+#include "options.h"
+#include "input.h"
+#include "output.h"
+#include "var.h"
+#include "error.h"
+#include "memalloc.h"
+#include "mystring.h"
+#include "alias.h"
+#include "show.h"
+#ifndef SMALL
+# include "myhistedit.h"
+#endif
+#include "cd.h"
+#include "shinstance.h"
+
+/*
+ * Shell command parser.
+ */
+
+#define EOFMARKLEN 79
+
+/* values returned by readtoken */
+#include "token.h"
+
+#define OPENBRACE '{'
+#define CLOSEBRACE '}'
+
+
+struct heredoc {
+	struct heredoc *next;	/* next here document in list */
+	union node *here;		/* redirection node */
+	char *eofmark;		/* string indicating end of input */
+	int striptabs;		/* if set, strip leading tabs */
+};
+
+
+
+//static int noalias = 0;		/* when set, don't handle aliases */
+//struct heredoc *heredoclist;	/* list of here documents to read */
+//int parsebackquote;		/* nonzero if we are inside backquotes */
+//int doprompt;			/* if set, prompt the user */
+//int needprompt;			/* true if interactive and at start of line */
+//int lasttoken;			/* last token read */
+//MKINIT int tokpushback;		/* last token pushed back */
+//char *wordtext;			/* text of last word returned by readtoken */
+//MKINIT int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
+//struct nodelist *backquotelist;
+//union node *redirnode;
+//struct heredoc *heredoc;
+//int quoteflag;			/* set if (part of) last token was quoted */
+//int startlinno;			/* line # where last token started */
+
+
+STATIC union node *list(shinstance *, int);
+STATIC union node *andor(shinstance *);
+STATIC union node *pipeline(shinstance *);
+STATIC union node *command(shinstance *);
+STATIC union node *simplecmd(shinstance *, union node **, union node *);
+STATIC union node *makename(shinstance *);
+STATIC void parsefname(shinstance *);
+STATIC void parseheredoc(shinstance *);
+STATIC int peektoken(shinstance *);
+STATIC int readtoken(shinstance *);
+STATIC int xxreadtoken(shinstance *);
+STATIC int readtoken1(shinstance *, int, char const *, char *, int);
+STATIC int noexpand(shinstance *, char *);
+STATIC void synexpect(shinstance *, int) __attribute__((__noreturn__));
+STATIC void synerror(shinstance *, const char *) __attribute__((__noreturn__));
+STATIC void setprompt(shinstance *, int);
+
+
+/*
+ * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
+ * valid parse tree indicating a blank line.)
+ */
+
+union node *
+parsecmd(shinstance *psh, int interact)
+{
+	int t;
+
+	psh->tokpushback = 0;
+	psh->doprompt = interact;
+	if (psh->doprompt)
+		setprompt(psh, 1);
+	else
+		setprompt(psh, 0);
+	psh->needprompt = 0;
+	t = readtoken(psh);
+	if (t == TEOF)
+		return NEOF;
+	if (t == TNL)
+		return NULL;
+	psh->tokpushback++;
+	return list(psh, 1);
+}
+
+
+STATIC union node *
+list(shinstance *psh, int nlflag)
+{
+	union node *n1, *n2, *n3;
+	int tok;
+
+	psh->checkkwd = 2;
+	if (nlflag == 0 && tokendlist[peektoken(psh)])
+		return NULL;
+	n1 = NULL;
+	for (;;) {
+		n2 = andor(psh);
+		tok = readtoken(psh);
+		if (tok == TBACKGND) {
+			if (n2->type == NCMD || n2->type == NPIPE) {
+				n2->ncmd.backgnd = 1;
+			} else if (n2->type == NREDIR) {
+				n2->type = NBACKGND;
+			} else {
+				n3 = (union node *)stalloc(psh, sizeof (struct nredir));
+				n3->type = NBACKGND;
+				n3->nredir.n = n2;
+				n3->nredir.redirect = NULL;
+				n2 = n3;
+			}
+		}
+		if (n1 == NULL) {
+			n1 = n2;
+		}
+		else {
+			n3 = (union node *)stalloc(psh, sizeof (struct nbinary));
+			n3->type = NSEMI;
+			n3->nbinary.ch1 = n1;
+			n3->nbinary.ch2 = n2;
+			n1 = n3;
+		}
+		switch (tok) {
+		case TBACKGND:
+		case TSEMI:
+			tok = readtoken(psh);
+			/* fall through */
+		case TNL:
+			if (tok == TNL) {
+				parseheredoc(psh);
+				if (nlflag)
+					return n1;
+			} else {
+				psh->tokpushback++;
+			}
+			psh->checkkwd = 2;
+			if (tokendlist[peektoken(psh)])
+				return n1;
+			break;
+		case TEOF:
+			if (psh->heredoclist)
+				parseheredoc(psh);
+			else
+				pungetc(psh);		/* push back EOF on input */
+			return n1;
+		default:
+			if (nlflag)
+				synexpect(psh, -1);
+			psh->tokpushback++;
+			return n1;
+		}
+	}
+}
+
+
+
+STATIC union node *
+andor(shinstance *psh)
+{
+	union node *n1, *n2, *n3;
+	int t;
+
+	n1 = pipeline(psh);
+	for (;;) {
+		if ((t = readtoken(psh)) == TAND) {
+			t = NAND;
+		} else if (t == TOR) {
+			t = NOR;
+		} else {
+			psh->tokpushback++;
+			return n1;
+		}
+		n2 = pipeline(psh);
+		n3 = (union node *)stalloc(psh, sizeof (struct nbinary));
+		n3->type = t;
+		n3->nbinary.ch1 = n1;
+		n3->nbinary.ch2 = n2;
+		n1 = n3;
+	}
+}
+
+
+
+STATIC union node *
+pipeline(shinstance *psh)
+{
+	union node *n1, *n2, *pipenode;
+	struct nodelist *lp, *prev;
+	int negate;
+
+	negate = 0;
+	TRACE((psh, "pipeline: entered\n"));
+	while (readtoken(psh) == TNOT)
+		negate = !negate;
+	psh->tokpushback++;
+	n1 = command(psh);
+	if (readtoken(psh) == TPIPE) {
+		pipenode = (union node *)stalloc(psh, sizeof (struct npipe));
+		pipenode->type = NPIPE;
+		pipenode->npipe.backgnd = 0;
+		lp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist));
+		pipenode->npipe.cmdlist = lp;
+		lp->n = n1;
+		do {
+			prev = lp;
+			lp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist));
+			lp->n = command(psh);
+			prev->next = lp;
+		} while (readtoken(psh) == TPIPE);
+		lp->next = NULL;
+		n1 = pipenode;
+	}
+	psh->tokpushback++;
+	if (negate) {
+		n2 = (union node *)stalloc(psh, sizeof (struct nnot));
+		n2->type = NNOT;
+		n2->nnot.com = n1;
+		return n2;
+	} else
+		return n1;
+}
+
+
+
+STATIC union node *
+command(shinstance *psh)
+{
+	union node *n1, *n2;
+	union node *ap, **app;
+	union node *cp, **cpp;
+	union node *redir, **rpp;
+	int t, negate = 0;
+
+	psh->checkkwd = 2;
+	redir = NULL;
+	n1 = NULL;
+	rpp = &redir;
+
+	/* Check for redirection which may precede command */
+	while (readtoken(psh) == TREDIR) {
+		*rpp = n2 = psh->redirnode;
+		rpp = &n2->nfile.next;
+		parsefname(psh);
+	}
+	psh->tokpushback++;
+
+	while (readtoken(psh) == TNOT) {
+		TRACE((psh, "command: TNOT recognized\n"));
+		negate = !negate;
+	}
+	psh->tokpushback++;
+
+	switch (readtoken(psh)) {
+	case TIF:
+		n1 = (union node *)stalloc(psh, sizeof (struct nif));
+		n1->type = NIF;
+		n1->nif.test = list(psh, 0);
+		if (readtoken(psh) != TTHEN)
+			synexpect(psh, TTHEN);
+		n1->nif.ifpart = list(psh, 0);
+		n2 = n1;
+		while (readtoken(psh) == TELIF) {
+			n2->nif.elsepart = (union node *)stalloc(psh, sizeof (struct nif));
+			n2 = n2->nif.elsepart;
+			n2->type = NIF;
+			n2->nif.test = list(psh, 0);
+			if (readtoken(psh) != TTHEN)
+				synexpect(psh, TTHEN);
+			n2->nif.ifpart = list(psh, 0);
+		}
+		if (psh->lasttoken == TELSE)
+			n2->nif.elsepart = list(psh, 0);
+		else {
+			n2->nif.elsepart = NULL;
+			psh->tokpushback++;
+		}
+		if (readtoken(psh) != TFI)
+			synexpect(psh, TFI);
+		psh->checkkwd = 1;
+		break;
+	case TWHILE:
+	case TUNTIL: {
+		int got;
+		n1 = (union node *)stalloc(psh, sizeof (struct nbinary));
+		n1->type = (psh->lasttoken == TWHILE)? NWHILE : NUNTIL;
+		n1->nbinary.ch1 = list(psh, 0);
+		if ((got=readtoken(psh)) != TDO) {
+TRACE((psh, "expecting DO got %s %s\n", tokname[got], got == TWORD ? psh->wordtext : ""));
+			synexpect(psh, TDO);
+		}
+		n1->nbinary.ch2 = list(psh, 0);
+		if (readtoken(psh) != TDONE)
+			synexpect(psh, TDONE);
+		psh->checkkwd = 1;
+		break;
+	}
+	case TFOR:
+		if (readtoken(psh) != TWORD || psh->quoteflag || ! goodname(psh->wordtext))
+			synerror(psh, "Bad for loop variable");
+		n1 = (union node *)stalloc(psh, sizeof (struct nfor));
+		n1->type = NFOR;
+		n1->nfor.var = psh->wordtext;
+		if (readtoken(psh) == TWORD && ! psh->quoteflag && equal(psh->wordtext, "in")) {
+			app = &ap;
+			while (readtoken(psh) == TWORD) {
+				n2 = (union node *)stalloc(psh, sizeof (struct narg));
+				n2->type = NARG;
+				n2->narg.text = psh->wordtext;
+				n2->narg.backquote = psh->backquotelist;
+				*app = n2;
+				app = &n2->narg.next;
+			}
+			*app = NULL;
+			n1->nfor.args = ap;
+			if (psh->lasttoken != TNL && psh->lasttoken != TSEMI)
+				synexpect(psh, -1);
+		} else {
+			static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
+								   '@', '=', '\0'};
+			n2 = (union node *)stalloc(psh, sizeof (struct narg));
+			n2->type = NARG;
+			n2->narg.text = argvars;
+			n2->narg.backquote = NULL;
+			n2->narg.next = NULL;
+			n1->nfor.args = n2;
+			/*
+			 * Newline or semicolon here is optional (but note
+			 * that the original Bourne shell only allowed NL).
+			 */
+			if (psh->lasttoken != TNL && psh->lasttoken != TSEMI)
+				psh->tokpushback++;
+		}
+		psh->checkkwd = 2;
+		if ((t = readtoken(psh)) == TDO)
+			t = TDONE;
+		else if (t == TBEGIN)
+			t = TEND;
+		else
+			synexpect(psh, -1);
+		n1->nfor.body = list(psh, 0);
+		if (readtoken(psh) != t)
+			synexpect(psh, t);
+		psh->checkkwd = 1;
+		break;
+	case TCASE:
+		n1 = (union node *)stalloc(psh, sizeof (struct ncase));
+		n1->type = NCASE;
+		if (readtoken(psh) != TWORD)
+			synexpect(psh, TWORD);
+		n1->ncase.expr = n2 = (union node *)stalloc(psh, sizeof (struct narg));
+		n2->type = NARG;
+		n2->narg.text = psh->wordtext;
+		n2->narg.backquote = psh->backquotelist;
+		n2->narg.next = NULL;
+		while (readtoken(psh) == TNL);
+		if (psh->lasttoken != TWORD || ! equal(psh->wordtext, "in"))
+			synerror(psh, "expecting \"in\"");
+		cpp = &n1->ncase.cases;
+		psh->noalias = 1;
+		psh->checkkwd = 2, readtoken(psh);
+		do {
+			*cpp = cp = (union node *)stalloc(psh, sizeof (struct nclist));
+			cp->type = NCLIST;
+			app = &cp->nclist.pattern;
+			for (;;) {
+				*app = ap = (union node *)stalloc(psh, sizeof (struct narg));
+				ap->type = NARG;
+				ap->narg.text = psh->wordtext;
+				ap->narg.backquote = psh->backquotelist;
+				if (psh->checkkwd = 2, readtoken(psh) != TPIPE)
+					break;
+				app = &ap->narg.next;
+				readtoken(psh);
+			}
+			ap->narg.next = NULL;
+			psh->noalias = 0;
+			if (psh->lasttoken != TRP) {
+				synexpect(psh, TRP);
+			}
+			cp->nclist.body = list(psh, 0);
+
+			psh->checkkwd = 2;
+			if ((t = readtoken(psh)) != TESAC) {
+				if (t != TENDCASE) {
+					psh->noalias = 0;
+					synexpect(psh, TENDCASE);
+				} else {
+					psh->noalias = 1;
+					psh->checkkwd = 2;
+					readtoken(psh);
+				}
+			}
+			cpp = &cp->nclist.next;
+		} while(psh->lasttoken != TESAC);
+		psh->noalias = 0;
+		*cpp = NULL;
+		psh->checkkwd = 1;
+		break;
+	case TLP:
+		n1 = (union node *)stalloc(psh, sizeof (struct nredir));
+		n1->type = NSUBSHELL;
+		n1->nredir.n = list(psh, 0);
+		n1->nredir.redirect = NULL;
+		if (readtoken(psh) != TRP)
+			synexpect(psh, TRP);
+		psh->checkkwd = 1;
+		break;
+	case TBEGIN:
+		n1 = list(psh, 0);
+		if (readtoken(psh) != TEND)
+			synexpect(psh, TEND);
+		psh->checkkwd = 1;
+		break;
+	/* Handle an empty command like other simple commands.  */
+	case TSEMI:
+		/*
+		 * An empty command before a ; doesn't make much sense, and
+		 * should certainly be disallowed in the case of `if ;'.
+		 */
+		if (!redir)
+			synexpect(psh, -1);
+	case TAND:
+	case TOR:
+	case TNL:
+	case TEOF:
+	case TWORD:
+	case TRP:
+		psh->tokpushback++;
+		n1 = simplecmd(psh, rpp, redir);
+		goto checkneg;
+	default:
+		synexpect(psh, -1);
+		/* NOTREACHED */
+	}
+
+	/* Now check for redirection which may follow command */
+	while (readtoken(psh) == TREDIR) {
+		*rpp = n2 = psh->redirnode;
+		rpp = &n2->nfile.next;
+		parsefname(psh);
+	}
+	psh->tokpushback++;
+	*rpp = NULL;
+	if (redir) {
+		if (n1->type != NSUBSHELL) {
+			n2 = (union node *)stalloc(psh, sizeof (struct nredir));
+			n2->type = NREDIR;
+			n2->nredir.n = n1;
+			n1 = n2;
+		}
+		n1->nredir.redirect = redir;
+	}
+
+checkneg:
+	if (negate) {
+		n2 = (union node *)stalloc(psh, sizeof (struct nnot));
+		n2->type = NNOT;
+		n2->nnot.com = n1;
+		return n2;
+	}
+	else
+		return n1;
+}
+
+
+STATIC union node *
+simplecmd(shinstance *psh, union node **rpp, union node *redir)
+{
+	union node *args, **app;
+	union node **orig_rpp = rpp;
+	union node *n = NULL, *n2;
+	int negate = 0;
+
+	/* If we don't have any redirections already, then we must reset */
+	/* rpp to be the address of the local redir variable.  */
+	if (redir == 0)
+		rpp = &redir;
+
+	args = NULL;
+	app = &args;
+	/*
+	 * We save the incoming value, because we need this for shell
+	 * functions.  There can not be a redirect or an argument between
+	 * the function name and the open parenthesis.
+	 */
+	orig_rpp = rpp;
+
+	while (readtoken(psh) == TNOT) {
+		TRACE((psh, "command: TNOT recognized\n"));
+		negate = !negate;
+	}
+	psh->tokpushback++;
+
+	for (;;) {
+		if (readtoken(psh) == TWORD) {
+			n = (union node *)stalloc(psh, sizeof (struct narg));
+			n->type = NARG;
+			n->narg.text = psh->wordtext;
+			n->narg.backquote = psh->backquotelist;
+			*app = n;
+			app = &n->narg.next;
+		} else if (psh->lasttoken == TREDIR) {
+			*rpp = n = psh->redirnode;
+			rpp = &n->nfile.next;
+			parsefname(psh);	/* read name of redirection file */
+		} else if (psh->lasttoken == TLP && app == &args->narg.next
+					    && rpp == orig_rpp) {
+			/* We have a function */
+			if (readtoken(psh) != TRP)
+				synexpect(psh, TRP);
+#ifdef notdef
+			if (! goodname(n->narg.text))
+				synerror(psh, "Bad function name");
+#endif
+			n->type = NDEFUN;
+			n->narg.next = command(psh);
+			goto checkneg;
+		} else {
+			psh->tokpushback++;
+			break;
+		}
+	}
+	*app = NULL;
+	*rpp = NULL;
+	n = (union node *)stalloc(psh, sizeof (struct ncmd));
+	n->type = NCMD;
+	n->ncmd.backgnd = 0;
+	n->ncmd.args = args;
+	n->ncmd.redirect = redir;
+
+checkneg:
+	if (negate) {
+		n2 = (union node *)stalloc(psh, sizeof (struct nnot));
+		n2->type = NNOT;
+		n2->nnot.com = n;
+		return n2;
+	}
+	else
+		return n;
+}
+
+STATIC union node *
+makename(shinstance *psh)
+{
+	union node *n;
+
+	n = (union node *)stalloc(psh, sizeof (struct narg));
+	n->type = NARG;
+	n->narg.next = NULL;
+	n->narg.text = psh->wordtext;
+	n->narg.backquote = psh->backquotelist;
+	return n;
+}
+
+void fixredir(shinstance *psh, union node *n, const char *text, int err)
+	{
+	TRACE((psh, "Fix redir %s %d\n", text, err));
+	if (!err)
+		n->ndup.vname = NULL;
+
+	if (is_digit(text[0]) && text[1] == '\0')
+		n->ndup.dupfd = digit_val(text[0]);
+	else if (text[0] == '-' && text[1] == '\0')
+		n->ndup.dupfd = -1;
+	else {
+
+		if (err)
+			synerror(psh, "Bad fd number");
+		else
+			n->ndup.vname = makename(psh);
+	}
+}
+
+
+STATIC void
+parsefname(shinstance *psh)
+{
+	union node *n = psh->redirnode;
+
+	if (readtoken(psh) != TWORD)
+		synexpect(psh, -1);
+	if (n->type == NHERE) {
+		struct heredoc *here = psh->heredoc;
+		struct heredoc *p;
+		size_t i;
+
+		if (psh->quoteflag == 0)
+			n->type = NXHERE;
+		TRACE((psh, "Here document %d\n", n->type));
+		if (here->striptabs) {
+			while (*psh->wordtext == '\t')
+				psh->wordtext++;
+		}
+		if (! noexpand(psh, psh->wordtext) || (i = strlen(psh->wordtext)) == 0 || i > EOFMARKLEN)
+			synerror(psh, "Illegal eof marker for << redirection");
+		rmescapes(psh, psh->wordtext);
+		here->eofmark = psh->wordtext;
+		here->next = NULL;
+		if (psh->heredoclist == NULL)
+			psh->heredoclist = here;
+		else {
+			for (p = psh->heredoclist ; p->next ; p = p->next);
+			p->next = here;
+		}
+	} else if (n->type == NTOFD || n->type == NFROMFD) {
+		fixredir(psh, n, psh->wordtext, 0);
+	} else {
+		n->nfile.fname = makename(psh);
+	}
+}
+
+
+/*
+ * Input any here documents.
+ */
+
+STATIC void
+parseheredoc(shinstance *psh)
+{
+	struct heredoc *here;
+	union node *n;
+
+	while (psh->heredoclist) {
+		here = psh->heredoclist;
+		psh->heredoclist = here->next;
+		if (psh->needprompt) {
+			setprompt(psh, 2);
+			psh->needprompt = 0;
+		}
+		readtoken1(psh, pgetc(psh), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
+				here->eofmark, here->striptabs);
+		n = (union node *)stalloc(psh, sizeof (struct narg));
+		n->narg.type = NARG;
+		n->narg.next = NULL;
+		n->narg.text = psh->wordtext;
+		n->narg.backquote = psh->backquotelist;
+		here->here->nhere.doc = n;
+	}
+}
+
+STATIC int
+peektoken(shinstance *psh)
+{
+	int t;
+
+	t = readtoken(psh);
+	psh->tokpushback++;
+	return (t);
+}
+
+STATIC int
+readtoken(shinstance *psh)
+{
+	int t;
+	int savecheckkwd = psh->checkkwd;
+#ifdef DEBUG
+	int alreadyseen = psh->tokpushback;
+#endif
+	struct alias *ap;
+
+	top:
+	t = xxreadtoken(psh);
+
+	if (psh->checkkwd) {
+		/*
+		 * eat newlines
+		 */
+		if (psh->checkkwd == 2) {
+			psh->checkkwd = 0;
+			while (t == TNL) {
+				parseheredoc(psh);
+				t = xxreadtoken(psh);
+			}
+		} else
+			psh->checkkwd = 0;
+		/*
+		 * check for keywords and aliases
+		 */
+		if (t == TWORD && !psh->quoteflag)
+		{
+			const char *const *pp;
+
+			for (pp = parsekwd; *pp; pp++) {
+				if (**pp == *psh->wordtext && equal(*pp, psh->wordtext))
+				{
+					psh->lasttoken = t = (int)(pp -
+					    parsekwd + KWDOFFSET);
+					TRACE((psh, "keyword %s recognized\n", tokname[t]));
+					goto out;
+				}
+			}
+			if(!psh->noalias &&
+			    (ap = lookupalias(psh, psh->wordtext, 1)) != NULL) {
+				pushstring(psh, ap->val, strlen(ap->val), ap);
+				psh->checkkwd = savecheckkwd;
+				goto top;
+			}
+		}
+out:
+		psh->checkkwd = (t == TNOT) ? savecheckkwd : 0;
+	}
+#ifdef DEBUG
+	if (!alreadyseen)
+	    TRACE((psh, "token %s %s\n", tokname[t], t == TWORD ? psh->wordtext : ""));
+	else
+	    TRACE((psh, "reread token %s %s\n", tokname[t], t == TWORD ? psh->wordtext : ""));
+#endif
+	return (t);
+}
+
+
+/*
+ * Read the next input token.
+ * If the token is a word, we set psh->backquotelist to the list of cmds in
+ *	backquotes.  We set psh->quoteflag to true if any part of the word was
+ *	quoted.
+ * If the token is TREDIR, then we set psh->redirnode to a structure containing
+ *	the redirection.
+ * In all cases, the variable psh->startlinno is set to the number of the line
+ *	on which the token starts.
+ *
+ * [Change comment:  here documents and internal procedures]
+ * [Readtoken shouldn't have any arguments.  Perhaps we should make the
+ *  word parsing code into a separate routine.  In this case, readtoken
+ *  doesn't need to have any internal procedures, but parseword does.
+ *  We could also make parseoperator in essence the main routine, and
+ *  have parseword (readtoken1?) handle both words and redirection.]
+ */
+
+#define RETURN(token)	return psh->lasttoken = token
+
+STATIC int
+xxreadtoken(shinstance *psh)
+{
+	int c;
+
+	if (psh->tokpushback) {
+		psh->tokpushback = 0;
+		return psh->lasttoken;
+	}
+	if (psh->needprompt) {
+		setprompt(psh, 2);
+		psh->needprompt = 0;
+	}
+	psh->startlinno = psh->plinno;
+	for (;;) {	/* until token or start of word found */
+		c = pgetc_macro(psh);
+		if (c == ' ' || c == '\t')
+			continue;		/* quick check for white space first */
+		switch (c) {
+		case ' ': case '\t':
+			continue;
+		case '#':
+			while ((c = pgetc(psh)) != '\n' && c != PEOF);
+			pungetc(psh);
+			continue;
+		case '\\':
+			if (pgetc(psh) == '\n') {
+				psh->startlinno = ++psh->plinno;
+				if (psh->doprompt)
+					setprompt(psh, 2);
+				else
+					setprompt(psh, 0);
+				continue;
+			}
+			pungetc(psh);
+			goto breakloop;
+		case '\n':
+			psh->plinno++;
+			psh->needprompt = psh->doprompt;
+			RETURN(TNL);
+		case PEOF:
+			RETURN(TEOF);
+		case '&':
+			if (pgetc(psh) == '&')
+				RETURN(TAND);
+			pungetc(psh);
+			RETURN(TBACKGND);
+		case '|':
+			if (pgetc(psh) == '|')
+				RETURN(TOR);
+			pungetc(psh);
+			RETURN(TPIPE);
+		case ';':
+			if (pgetc(psh) == ';')
+				RETURN(TENDCASE);
+			pungetc(psh);
+			RETURN(TSEMI);
+		case '(':
+			RETURN(TLP);
+		case ')':
+			RETURN(TRP);
+		default:
+			goto breakloop;
+		}
+	}
+breakloop:
+	return readtoken1(psh, c, BASESYNTAX, (char *)NULL, 0);
+#undef RETURN
+}
+
+
+
+/*
+ * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
+ * is not NULL, read a here document.  In the latter case, eofmark is the
+ * word which marks the end of the document and striptabs is true if
+ * leading tabs should be stripped from the document.  The argument firstc
+ * is the first character of the input token or document.
+ *
+ * Because C does not have internal subroutines, I have simulated them
+ * using goto's to implement the subroutine linkage.  The following macros
+ * will run code that appears at the end of readtoken1.
+ */
+
+#define CHECKEND()	{goto checkend; checkend_return:;}
+#define PARSEREDIR()	{goto parseredir; parseredir_return:;}
+#define PARSESUB()	{goto parsesub; parsesub_return:;}
+#define PARSEBACKQOLD()	{oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
+#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
+#define	PARSEARITH()	{goto parsearith; parsearith_return:;}
+
+/*
+ * Keep track of nested doublequotes in dblquote and doublequotep.
+ * We use dblquote for the first 32 levels, and we expand to a malloc'ed
+ * region for levels above that. Usually we never need to malloc.
+ * This code assumes that an int is 32 bits. We don't use uint32_t,
+ * because the rest of the code does not.
+ */
+#define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \
+    (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32))))
+
+#define SETDBLQUOTE() \
+    if (varnest < 32) \
+	dblquote |= (1 << varnest); \
+    else \
+	dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32))
+
+#define CLRDBLQUOTE() \
+    if (varnest < 32) \
+	dblquote &= ~(1 << varnest); \
+    else \
+	dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32))
+
+STATIC int
+readtoken1(shinstance *psh, int firstc, char const *syntax, char *eofmark, int striptabs)
+{
+	int c = firstc;
+	char *out;
+	int len;
+	char line[EOFMARKLEN + 1];
+	struct nodelist *bqlist;
+	int quotef;
+	int *dblquotep = NULL;
+	size_t maxnest = 32;
+	int dblquote;
+	int varnest;	/* levels of variables expansion */
+	int arinest;	/* levels of arithmetic expansion */
+	int parenlevel;	/* levels of parens in arithmetic */
+	int oldstyle;
+	char const *prevsyntax;	/* syntax before arithmetic */
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &maxnest;
+	(void) &dblquotep;
+	(void) &out;
+	(void) &quotef;
+	(void) &dblquote;
+	(void) &varnest;
+	(void) &arinest;
+	(void) &parenlevel;
+	(void) &oldstyle;
+	(void) &prevsyntax;
+	(void) &syntax;
+#endif
+
+	psh->startlinno = psh->plinno;
+	dblquote = 0;
+	varnest = 0;
+	if (syntax == DQSYNTAX) {
+		SETDBLQUOTE();
+	}
+	quotef = 0;
+	bqlist = NULL;
+	arinest = 0;
+	parenlevel = 0;
+
+	STARTSTACKSTR(psh, out);
+	loop: {	/* for each line, until end of word */
+#if ATTY
+		if (c == '\034' && psh->doprompt
+		 && attyset() && ! equal(termval(), "emacs")) {
+			attyline();
+			if (syntax == BASESYNTAX)
+				return readtoken(psh);
+			c = pgetc(psh);
+			goto loop;
+		}
+#endif
+		CHECKEND();	/* set c to PEOF if at end of here document */
+		for (;;) {	/* until end of line or end of word */
+			CHECKSTRSPACE(psh, 4, out);	/* permit 4 calls to USTPUTC */
+			switch(syntax[c]) {
+			case CNL:	/* '\n' */
+				if (syntax == BASESYNTAX)
+					goto endword;	/* exit outer loop */
+				USTPUTC(psh, c, out);
+				psh->plinno++;
+				if (psh->doprompt)
+					setprompt(psh, 2);
+				else
+					setprompt(psh, 0);
+				c = pgetc(psh);
+				goto loop;		/* continue outer loop */
+			case CWORD:
+				USTPUTC(psh, c, out);
+				break;
+			case CCTL:
+				if (eofmark == NULL || ISDBLQUOTE())
+					USTPUTC(psh, CTLESC, out);
+				USTPUTC(psh, c, out);
+				break;
+			case CBACK:	/* backslash */
+				c = pgetc(psh);
+				if (c == PEOF) {
+					USTPUTC(psh, '\\', out);
+					pungetc(psh);
+					break;
+				}
+				if (c == '\n') {
+					if (psh->doprompt)
+						setprompt(psh, 2);
+					else
+						setprompt(psh, 0);
+					break;
+				}
+				quotef = 1;
+				if (ISDBLQUOTE() && c != '\\' &&
+				    c != '`' && c != '$' &&
+				    (c != '"' || eofmark != NULL))
+					USTPUTC(psh, '\\', out);
+				if (SQSYNTAX[c] == CCTL)
+					USTPUTC(psh, CTLESC, out);
+				else if (eofmark == NULL) {
+					USTPUTC(psh, CTLQUOTEMARK, out);
+					USTPUTC(psh, c, out);
+					if (varnest != 0)
+						USTPUTC(psh, CTLQUOTEEND, out);
+					break;
+				}
+				USTPUTC(psh, c, out);
+				break;
+			case CSQUOTE:
+				if (syntax != SQSYNTAX) {
+					if (eofmark == NULL)
+						USTPUTC(psh, CTLQUOTEMARK, out);
+					quotef = 1;
+					syntax = SQSYNTAX;
+					break;
+				}
+				if (eofmark != NULL && arinest == 0 &&
+				    varnest == 0) {
+					/* Ignore inside quoted here document */
+					USTPUTC(psh, c, out);
+					break;
+				}
+				/* End of single quotes... */
+				if (arinest)
+					syntax = ARISYNTAX;
+				else {
+					syntax = BASESYNTAX;
+					if (varnest != 0)
+						USTPUTC(psh, CTLQUOTEEND, out);
+				}
+				break;
+			case CDQUOTE:
+				if (eofmark != NULL && arinest == 0 &&
+				    varnest == 0) {
+					/* Ignore inside here document */
+					USTPUTC(psh, c, out);
+					break;
+				}
+				quotef = 1;
+				if (arinest) {
+					if (ISDBLQUOTE()) {
+						syntax = ARISYNTAX;
+						CLRDBLQUOTE();
+					} else {
+						syntax = DQSYNTAX;
+						SETDBLQUOTE();
+						USTPUTC(psh, CTLQUOTEMARK, out);
+					}
+					break;
+				}
+				if (eofmark != NULL)
+					break;
+				if (ISDBLQUOTE()) {
+					if (varnest != 0)
+						USTPUTC(psh, CTLQUOTEEND, out);
+					syntax = BASESYNTAX;
+					CLRDBLQUOTE();
+				} else {
+					syntax = DQSYNTAX;
+					SETDBLQUOTE();
+					USTPUTC(psh, CTLQUOTEMARK, out);
+				}
+				break;
+			case CVAR:	/* '$' */
+				PARSESUB();		/* parse substitution */
+				break;
+			case CENDVAR:	/* CLOSEBRACE */
+				if (varnest > 0 && !ISDBLQUOTE()) {
+					varnest--;
+					USTPUTC(psh, CTLENDVAR, out);
+				} else {
+					USTPUTC(psh, c, out);
+				}
+				break;
+			case CLP:	/* '(' in arithmetic */
+				parenlevel++;
+				USTPUTC(psh, c, out);
+				break;
+			case CRP:	/* ')' in arithmetic */
+				if (parenlevel > 0) {
+					USTPUTC(psh, c, out);
+					--parenlevel;
+				} else {
+					if (pgetc(psh) == ')') {
+						if (--arinest == 0) {
+							USTPUTC(psh, CTLENDARI, out);
+							syntax = prevsyntax;
+							if (syntax == DQSYNTAX)
+								SETDBLQUOTE();
+							else
+								CLRDBLQUOTE();
+						} else
+							USTPUTC(psh, ')', out);
+					} else {
+						/*
+						 * unbalanced parens
+						 *  (don't 2nd guess - no error)
+						 */
+						pungetc(psh);
+						USTPUTC(psh, ')', out);
+					}
+				}
+				break;
+			case CBQUOTE:	/* '`' */
+				PARSEBACKQOLD();
+				break;
+			case CSHEOF:
+				goto endword;		/* exit outer loop */
+			default:
+				if (varnest == 0)
+					goto endword;	/* exit outer loop */
+				USTPUTC(psh, c, out);
+			}
+			c = pgetc_macro(psh);
+		}
+	}
+endword:
+	if (syntax == ARISYNTAX)
+		synerror(psh, "Missing '))'");
+	if (syntax != BASESYNTAX && ! psh->parsebackquote && eofmark == NULL)
+		synerror(psh, "Unterminated quoted string");
+	if (varnest != 0) {
+		psh->startlinno = psh->plinno;
+		/* { */
+		synerror(psh, "Missing '}'");
+	}
+	USTPUTC(psh, '\0', out);
+	len = (int)(out - stackblock(psh));
+	out = stackblock(psh);
+	if (eofmark == NULL) {
+		if ((c == '>' || c == '<')
+		 && quotef == 0
+		 && len <= 2
+		 && (*out == '\0' || is_digit(*out))) {
+			PARSEREDIR();
+			return psh->lasttoken = TREDIR;
+		} else {
+			pungetc(psh);
+		}
+	}
+	psh->quoteflag = quotef;
+	psh->backquotelist = bqlist;
+	grabstackblock(psh, len);
+	psh->wordtext = out;
+	if (dblquotep != NULL)
+	    ckfree(dblquotep);
+	return psh->lasttoken = TWORD;
+/* end of readtoken routine */
+
+
+
+/*
+ * Check to see whether we are at the end of the here document.  When this
+ * is called, c is set to the first character of the next input line.  If
+ * we are at the end of the here document, this routine sets the c to PEOF.
+ */
+
+checkend: {
+	if (eofmark) {
+		if (striptabs) {
+			while (c == '\t')
+				c = pgetc(psh);
+		}
+		if (c == *eofmark) {
+			if (pfgets(psh, line, sizeof line) != NULL) {
+				char *p, *q;
+
+				p = line;
+				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
+				if (*p == '\n' && *q == '\0') {
+					c = PEOF;
+					psh->plinno++;
+					psh->needprompt = psh->doprompt;
+				} else {
+					pushstring(psh, line, strlen(line), NULL);
+				}
+			}
+		}
+	}
+	goto checkend_return;
+}
+
+
+/*
+ * Parse a redirection operator.  The variable "out" points to a string
+ * specifying the fd to be redirected.  The variable "c" contains the
+ * first character of the redirection operator.
+ */
+
+parseredir: {
+	char fd = *out;
+	union node *np;
+
+	np = (union node *)stalloc(psh, sizeof (struct nfile));
+	if (c == '>') {
+		np->nfile.fd = 1;
+		c = pgetc(psh);
+		if (c == '>')
+			np->type = NAPPEND;
+		else if (c == '|')
+			np->type = NCLOBBER;
+		else if (c == '&')
+			np->type = NTOFD;
+		else {
+			np->type = NTO;
+			pungetc(psh);
+		}
+	} else {	/* c == '<' */
+		np->nfile.fd = 0;
+		switch (c = pgetc(psh)) {
+		case '<':
+			if (sizeof (struct nfile) != sizeof (struct nhere)) {
+				np = (union node *)stalloc(psh, sizeof (struct nhere));
+				np->nfile.fd = 0;
+			}
+			np->type = NHERE;
+			psh->heredoc = (struct heredoc *)stalloc(psh, sizeof (struct heredoc));
+			psh->heredoc->here = np;
+			if ((c = pgetc(psh)) == '-') {
+				psh->heredoc->striptabs = 1;
+			} else {
+				psh->heredoc->striptabs = 0;
+				pungetc(psh);
+			}
+			break;
+
+		case '&':
+			np->type = NFROMFD;
+			break;
+
+		case '>':
+			np->type = NFROMTO;
+			break;
+
+		default:
+			np->type = NFROM;
+			pungetc(psh);
+			break;
+		}
+	}
+	if (fd != '\0')
+		np->nfile.fd = digit_val(fd);
+	psh->redirnode = np;
+	goto parseredir_return;
+}
+
+
+/*
+ * Parse a substitution.  At this point, we have read the dollar sign
+ * and nothing else.
+ */
+
+parsesub: {
+	int subtype;
+	int typeloc;
+	int flags;
+	char *p;
+	static const char types[] = "}-+?=";
+
+	c = pgetc(psh);
+	if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
+		USTPUTC(psh, '$', out);
+		pungetc(psh);
+	} else if (c == '(') {	/* $(command) or $((arith)) */
+		if (pgetc(psh) == '(') {
+			PARSEARITH();
+		} else {
+			pungetc(psh);
+			PARSEBACKQNEW();
+		}
+	} else {
+		USTPUTC(psh, CTLVAR, out);
+		typeloc = (int)(out - stackblock(psh));
+		USTPUTC(psh, VSNORMAL, out);
+		subtype = VSNORMAL;
+		if (c == OPENBRACE) {
+			c = pgetc(psh);
+			if (c == '#') {
+				if ((c = pgetc(psh)) == CLOSEBRACE)
+					c = '#';
+				else
+					subtype = VSLENGTH;
+			}
+			else
+				subtype = 0;
+		}
+		if (is_name(c)) {
+			do {
+				STPUTC(psh, c, out);
+				c = pgetc(psh);
+			} while (is_in_name(c));
+		} else if (is_digit(c)) {
+			do {
+				USTPUTC(psh, c, out);
+				c = pgetc(psh);
+			} while (is_digit(c));
+		}
+		else if (is_special(c)) {
+			USTPUTC(psh, c, out);
+			c = pgetc(psh);
+		}
+		else
+badsub:			synerror(psh, "Bad substitution");
+
+		STPUTC(psh, '=', out);
+		flags = 0;
+		if (subtype == 0) {
+			switch (c) {
+			case ':':
+				flags = VSNUL;
+				c = pgetc(psh);
+				/*FALLTHROUGH*/
+			default:
+				p = strchr(types, c);
+				if (p == NULL)
+					goto badsub;
+				subtype = (int)(p - types + VSNORMAL);
+				break;
+			case '%':
+			case '#':
+				{
+					int cc = c;
+					subtype = c == '#' ? VSTRIMLEFT :
+							     VSTRIMRIGHT;
+					c = pgetc(psh);
+					if (c == cc)
+						subtype++;
+					else
+						pungetc(psh);
+					break;
+				}
+			}
+		} else {
+			pungetc(psh);
+		}
+		if (ISDBLQUOTE() || arinest)
+			flags |= VSQUOTE;
+		*(stackblock(psh) + typeloc) = subtype | flags;
+		if (subtype != VSNORMAL) {
+			varnest++;
+			if (varnest >= maxnest) {
+				dblquotep = ckrealloc(dblquotep, maxnest / 8);
+				dblquotep[(maxnest / 32) - 1] = 0;
+				maxnest += 32;
+			}
+		}
+	}
+	goto parsesub_return;
+}
+
+
+/*
+ * Called to parse command substitutions.  Newstyle is set if the command
+ * is enclosed inside $(...); nlpp is a pointer to the head of the linked
+ * list of commands (passed by reference), and savelen is the number of
+ * characters on the top of the stack which must be preserved.
+ */
+
+parsebackq: {
+	struct nodelist **nlpp;
+	int savepbq;
+	union node *n;
+	char *volatile str;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	int savelen;
+	int saveprompt;
+#ifdef __GNUC__
+	(void) &saveprompt;
+#endif
+
+	savepbq = psh->parsebackquote;
+	if (setjmp(jmploc.loc)) {
+		if (str)
+			ckfree(str);
+		psh->parsebackquote = 0;
+		psh->handler = savehandler;
+		longjmp(psh->handler->loc, 1);
+	}
+	INTOFF;
+	str = NULL;
+	savelen = (int)(out - stackblock(psh));
+	if (savelen > 0) {
+		str = ckmalloc(savelen);
+		memcpy(str, stackblock(psh), savelen);
+	}
+	savehandler = psh->handler;
+	psh->handler = &jmploc;
+	INTON;
+        if (oldstyle) {
+                /* We must read until the closing backquote, giving special
+                   treatment to some slashes, and then push the string and
+                   reread it as input, interpreting it normally.  */
+                char *pout;
+                int pc;
+                int psavelen;
+                char *pstr;
+
+
+                STARTSTACKSTR(psh, pout);
+		for (;;) {
+			if (psh->needprompt) {
+				setprompt(psh, 2);
+				psh->needprompt = 0;
+			}
+			switch (pc = pgetc(psh)) {
+			case '`':
+				goto done;
+
+			case '\\':
+                                if ((pc = pgetc(psh)) == '\n') {
+					psh->plinno++;
+					if (psh->doprompt)
+						setprompt(psh, 2);
+					else
+						setprompt(psh, 0);
+					/*
+					 * If eating a newline, avoid putting
+					 * the newline into the new character
+					 * stream (via the STPUTC after the
+					 * switch).
+					 */
+					continue;
+				}
+                                if (pc != '\\' && pc != '`' && pc != '$'
+                                    && (!ISDBLQUOTE() || pc != '"'))
+                                        STPUTC(psh, '\\', pout);
+				break;
+
+			case '\n':
+				psh->plinno++;
+				psh->needprompt = psh->doprompt;
+				break;
+
+			case PEOF:
+			        psh->startlinno = psh->plinno;
+				synerror(psh, "EOF in backquote substitution");
+ 				break;
+
+			default:
+				break;
+			}
+			STPUTC(psh, pc, pout);
+                }
+done:
+                STPUTC(psh, '\0', pout);
+                psavelen = (int)(pout - stackblock(psh));
+                if (psavelen > 0) {
+			pstr = grabstackstr(psh, pout);
+			setinputstring(psh, pstr, 1);
+                }
+        }
+	nlpp = &bqlist;
+	while (*nlpp)
+		nlpp = &(*nlpp)->next;
+	*nlpp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist));
+	(*nlpp)->next = NULL;
+	psh->parsebackquote = oldstyle;
+
+	if (oldstyle) {
+		saveprompt = psh->doprompt;
+		psh->doprompt = 0;
+	}
+
+	n = list(psh, 0);
+
+	if (oldstyle)
+		psh->doprompt = saveprompt;
+	else {
+		if (readtoken(psh) != TRP)
+			synexpect(psh, TRP);
+	}
+
+	(*nlpp)->n = n;
+        if (oldstyle) {
+		/*
+		 * Start reading from old file again, ignoring any pushed back
+		 * tokens left from the backquote parsing
+		 */
+                popfile(psh);
+		psh->tokpushback = 0;
+	}
+	while (stackblocksize(psh) <= savelen)
+		growstackblock(psh);
+	STARTSTACKSTR(psh, out);
+	if (str) {
+		memcpy(out, str, savelen);
+		STADJUST(psh, savelen, out);
+		INTOFF;
+		ckfree(str);
+		str = NULL;
+		INTON;
+	}
+	psh->parsebackquote = savepbq;
+	psh->handler = savehandler;
+	if (arinest || ISDBLQUOTE())
+		USTPUTC(psh, CTLBACKQ | CTLQUOTE, out);
+	else
+		USTPUTC(psh, CTLBACKQ, out);
+	if (oldstyle)
+		goto parsebackq_oldreturn;
+	else
+		goto parsebackq_newreturn;
+}
+
+/*
+ * Parse an arithmetic expansion (indicate start of one and set state)
+ */
+parsearith: {
+
+	if (++arinest == 1) {
+		prevsyntax = syntax;
+		syntax = ARISYNTAX;
+		USTPUTC(psh, CTLARI, out);
+		if (ISDBLQUOTE())
+			USTPUTC(psh, '"',out);
+		else
+			USTPUTC(psh, ' ',out);
+	} else {
+		/*
+		 * we collapse embedded arithmetic expansion to
+		 * parenthesis, which should be equivalent
+		 */
+		USTPUTC(psh, '(', out);
+	}
+	goto parsearith_return;
+}
+
+} /* end of readtoken */
+
+
+
+#ifdef mkinit
+RESET {
+	psh->tokpushback = 0;
+	psh->checkkwd = 0;
+}
+#endif
+
+/*
+ * Returns true if the text contains nothing to expand (no dollar signs
+ * or backquotes).
+ */
+
+STATIC int
+noexpand(shinstance *psh, char *text)
+{
+	char *p;
+	char c;
+
+	p = text;
+	while ((c = *p++) != '\0') {
+		if (c == CTLQUOTEMARK)
+			continue;
+		if (c == CTLESC)
+			p++;
+		else if (BASESYNTAX[(int)c] == CCTL)
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Return true if the argument is a legal variable name (a letter or
+ * underscore followed by zero or more letters, underscores, and digits).
+ */
+
+int
+goodname(const char *name)
+{
+	const char *p;
+
+	p = name;
+	if (! is_name(*p))
+		return 0;
+	while (*++p) {
+		if (! is_in_name(*p))
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Called when an unexpected token is read during the parse.  The argument
+ * is the token that is expected, or -1 if more than one type of token can
+ * occur at this point.
+ */
+
+STATIC void
+synexpect(shinstance *psh, int token)
+{
+	char msg[64];
+
+	if (token >= 0) {
+		fmtstr(msg, 64, "%s unexpected (expecting %s)",
+			tokname[psh->lasttoken], tokname[token]);
+	} else {
+		fmtstr(msg, 64, "%s unexpected", tokname[psh->lasttoken]);
+	}
+	synerror(psh, msg);
+	/* NOTREACHED */
+}
+
+
+STATIC void
+synerror(shinstance *psh, const char *msg)
+{
+	if (psh->commandname)
+		outfmt(&psh->errout, "%s: %d: ", psh->commandname, psh->startlinno);
+	outfmt(&psh->errout, "Syntax error: %s\n", msg);
+	error(psh, (char *)NULL);
+	/* NOTREACHED */
+}
+
+STATIC const char *
+my_basename(const char *argv0, unsigned *lenp)
+{
+	const char *tmp;
+
+    /* skip the path */
+    for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:"))
+        argv0 = tmp + 1;
+
+	if (lenp) {
+		/* find the end, ignoring extenions */
+		tmp = strrchr(argv0, '.');
+		if (!tmp)
+			tmp = strchr(argv0, '\0');
+		*lenp = (unsigned)(tmp - argv0);
+	}
+	return argv0;
+}
+
+
+STATIC void
+setprompt(shinstance *psh, int which)
+{
+	psh->whichprompt = which;
+
+#ifndef SMALL
+	if (!el)
+#endif
+	{
+		/* deal with bash prompts */
+		const char *prompt = getprompt(psh, NULL);
+		if (!strchr(prompt, '\\')) {
+			out2str(psh, prompt);
+		} else {
+			while (*prompt) {
+				if (*prompt != '\\') {
+					out2c(psh, *prompt++);
+				} else {
+					prompt++;
+					switch (*prompt++)
+					{
+						/* simple */
+						case '$':	out2c(psh, sh_geteuid(psh) ? '$' : '#'); break;
+						case '\\': 	out2c(psh, '\\'); break;
+						case 'a':	out2c(psh, '\a'); break;
+						case 'e':	out2c(psh, 033); break;
+						case 'n': 	out2c(psh, '\n'); break;
+						case 'r': 	out2c(psh, '\r'); break;
+
+						/* complicated */
+						case 's': {
+							unsigned len;
+							const char *arg0 = my_basename(psh->arg0, &len);
+							outfmt(psh->out2, "%.*s", len, arg0);
+							break;
+						}
+						case 'v':
+							outfmt(psh->out2, "%d.%d", KBUILD_VERSION_MAJOR,
+								   KBUILD_VERSION_MINOR);
+							break;
+						case 'V':
+							outfmt(psh->out2, "%d.%d.%d", KBUILD_VERSION_MAJOR,
+								   KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH);
+							break;
+							out2str(psh, getpwd(psh, 1) ? getpwd(psh, 1) : "?");
+							break;
+						case 'w':
+						case 'W': {
+							const char *cwd = getpwd(psh, 1);
+							const char *home = bltinlookup(psh, "HOME", 1);
+							size_t home_len = home ? strlen(home) : 0;
+							if (!cwd) cwd = "?";
+							if (!strncmp(cwd, home, home_len)
+							  && (    cwd[home_len] == '\0'
+							      || (cwd[home_len] == '/' && prompt[-1] == 'w'))) {
+								out2c(psh, '~');
+								if (prompt[-1] == 'w' && cwd[home_len]) {
+									out2str(psh, cwd + home_len);
+								}
+							} else if (prompt[-1] == 'w') {
+								out2str(psh, cwd);
+							} else {
+								out2str(psh, my_basename(cwd, NULL));
+							}
+							break;
+						}
+						case '0':
+						case '1':
+						case '2':
+						case '3': {
+							unsigned int ch = prompt[-1] - '0';
+							if (isdigit(*prompt)) {
+								ch *= 8;
+								ch += *prompt++ - '0';
+							}
+							if (isdigit(*prompt)) {
+								ch *= 8;
+								ch += *prompt++ - '0';
+							}
+							out2c(psh, ch);
+							break;
+						}
+
+						/* ignore */
+							break;
+						case '!':
+						case '#':
+						case '@':
+						case 'A':
+						case 'h':
+						case 'H':
+						case 'j':
+						case 'l':
+						case 't':
+						case 'T':
+						case 'u':
+						case '[':
+							if (strchr(prompt, ']')) {
+								prompt = strchr(prompt, ']') + 1;
+							}
+							break;
+						case 'D':
+							if (*prompt == '{' && strchr(prompt, '}')) {
+								prompt = strchr(prompt, '}') + 1;
+							}
+							break;
+					}
+
+				}
+			}
+		}
+	}
+}
+
+/*
+ * called by editline -- any expansions to the prompt
+ *    should be added here.
+ */
+const char *
+getprompt(shinstance *psh, void *unused)
+{
+	switch (psh->whichprompt) {
+	case 0:
+		return "";
+	case 1:
+		return ps1val(psh);
+	case 2:
+		return ps2val(psh);
+	default:
+		return "<internal prompt error>";
+	}
+}
Index: /tags/kBuild-0.1.4/src/kash/parser.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/parser.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/parser.h	(revision 1780)
@@ -0,0 +1,87 @@
+/*	$NetBSD: parser.h,v 1.17 2004/06/26 22:09:49 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)parser.h	8.3 (Berkeley) 5/4/95
+ */
+
+#ifndef ___parse_h
+#define ___parse_h
+
+/* control characters in argument strings */
+#define CTL_FIRST '\201'	/* first 'special' character */
+#define CTLESC '\201'		/* escape next character */
+#define CTLVAR '\202'		/* variable defn */
+#define CTLENDVAR '\203'
+#define CTLBACKQ '\204'
+#define CTLQUOTE 01		/* ored with CTLBACKQ code if in quotes */
+/*	CTLBACKQ | CTLQUOTE == '\205' */
+#define	CTLARI	'\206'		/* arithmetic expression */
+#define	CTLENDARI '\207'
+#define	CTLQUOTEMARK '\210'
+#define	CTLQUOTEEND '\211'	/* only inside ${...} */
+#define	CTL_LAST '\211'		/* last 'special' character */
+
+/* variable substitution byte (follows CTLVAR) */
+#define VSTYPE	0x0f		/* type of variable substitution */
+#define VSNUL	0x10		/* colon--treat the empty string as unset */
+#define VSQUOTE 0x80		/* inside double quotes--suppress splitting */
+
+/* values of VSTYPE field */
+#define VSNORMAL	0x1		/* normal variable:  $var or ${var} */
+#define VSMINUS		0x2		/* ${var-text} */
+#define VSPLUS		0x3		/* ${var+text} */
+#define VSQUESTION	0x4		/* ${var?message} */
+#define VSASSIGN	0x5		/* ${var=text} */
+#define VSTRIMLEFT	0x6		/* ${var#pattern} */
+#define VSTRIMLEFTMAX	0x7		/* ${var##pattern} */
+#define VSTRIMRIGHT	0x8		/* ${var%pattern} */
+#define VSTRIMRIGHTMAX 	0x9		/* ${var%%pattern} */
+#define VSLENGTH	0xa		/* ${#var} */
+
+
+/*
+ * NEOF is returned by parsecmd when it encounters an end of file.  It
+ * must be distinct from NULL, so we use the address of a variable that
+ * happens to be handy.
+ */
+/*extern int tokpushback;*/
+#define NEOF ((union node *)&psh->tokpushback)
+/*extern int whichprompt;*/		/* 1 == PS1, 2 == PS2 */
+
+
+union node *parsecmd(struct shinstance *, int);
+void fixredir(struct shinstance *, union node *, const char *, int);
+int goodname(const char *);
+const char *getprompt(struct shinstance *, void *);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/redir.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/redir.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/redir.c	(revision 1780)
@@ -0,0 +1,384 @@
+/*	$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)redir.c	8.2 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $");
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <limits.h>         /* PIPE_BUF */
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * Code for dealing with input/output redirection.
+ */
+
+#include "main.h"
+#include "shell.h"
+#include "nodes.h"
+#include "jobs.h"
+#include "options.h"
+#include "expand.h"
+#include "redir.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "shinstance.h"
+
+
+#define EMPTY -2		/* marks an unused slot in redirtab */
+#ifndef PIPE_BUF
+# define PIPESIZE 4096		/* amount of buffering in a pipe */
+#else
+# define PIPESIZE PIPE_BUF
+#endif
+
+
+MKINIT
+struct redirtab {
+	struct redirtab *next;
+	short renamed[10];
+};
+
+
+//MKINIT struct redirtab *redirlist;
+
+/*
+ * We keep track of whether or not fd0 has been redirected.  This is for
+ * background commands, where we want to redirect fd0 to /dev/null only
+ * if it hasn't already been redirected.
+*/
+//int fd0_redirected = 0;
+
+STATIC void openredirect(shinstance *, union node *, char[10], int);
+STATIC int openhere(shinstance *, union node *);
+
+
+/*
+ * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
+ * old file descriptors are stashed away so that the redirection can be
+ * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
+ * standard output, and the standard error if it becomes a duplicate of
+ * stdout, is saved in memory.
+ */
+
+void
+redirect(shinstance *psh, union node *redir, int flags)
+{
+	union node *n;
+	struct redirtab *sv = NULL;
+	int i;
+	int fd;
+	int try;
+	char memory[10];	/* file descriptors to write to memory */
+
+	for (i = 10 ; --i >= 0 ; )
+		memory[i] = 0;
+	memory[1] = flags & REDIR_BACKQ;
+	if (flags & REDIR_PUSH) {
+		/* We don't have to worry about REDIR_VFORK here, as
+		 * flags & REDIR_PUSH is never true if REDIR_VFORK is set.
+		 */
+		sv = ckmalloc(sizeof (struct redirtab));
+		for (i = 0 ; i < 10 ; i++)
+			sv->renamed[i] = EMPTY;
+		sv->next = psh->redirlist;
+		psh->redirlist = sv;
+	}
+	for (n = redir ; n ; n = n->nfile.next) {
+		fd = n->nfile.fd;
+		try = 0;
+		if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
+		    n->ndup.dupfd == fd)
+			continue; /* redirect from/to same file descriptor */
+
+		if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
+			INTOFF;
+again:
+			if ((i = shfile_fcntl(&psh->fdtab, fd, F_DUPFD, 10)) == -1) {
+				switch (errno) {
+				case EBADF:
+					if (!try) {
+						openredirect(psh, n, memory, flags);
+						try++;
+						goto again;
+					}
+					/* FALLTHROUGH*/
+				default:
+					INTON;
+					error(psh, "%d: %s", fd, strerror(errno));
+					/* NOTREACHED */
+				}
+			}
+			if (!try) {
+				sv->renamed[fd] = i;
+				shfile_close(&psh->fdtab, fd);
+			}
+			INTON;
+		} else {
+			shfile_close(&psh->fdtab, fd);
+		}
+                if (fd == 0)
+                        psh->fd0_redirected++;
+		if (!try)
+			openredirect(psh, n, memory, flags);
+	}
+	if (memory[1])
+		psh->out1 = &psh->memout;
+	if (memory[2])
+		psh->out2 = &psh->memout;
+}
+
+
+STATIC void
+openredirect(shinstance *psh, union node *redir, char memory[10], int flags)
+{
+	int fd = redir->nfile.fd;
+	char *fname;
+	int f;
+	int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags;
+
+	/*
+	 * We suppress interrupts so that we won't leave open file
+	 * descriptors around.  This may not be such a good idea because
+	 * an open of a device or a fifo can block indefinitely.
+	 */
+	INTOFF;
+	memory[fd] = 0;
+	switch (redir->nfile.type) {
+	case NFROM:
+		fname = redir->nfile.expfname;
+		if (flags & REDIR_VFORK)
+			eflags = O_NONBLOCK;
+		else
+			eflags = 0;
+		if ((f = shfile_open(&psh->fdtab, fname, O_RDONLY|eflags, 0)) < 0)
+			goto eopen;
+		if (eflags)
+			(void)shfile_fcntl(&psh->fdtab, f, F_SETFL, shfile_fcntl(&psh->fdtab, f, F_GETFL, 0) & ~eflags);
+		break;
+	case NFROMTO:
+		fname = redir->nfile.expfname;
+		if ((f = shfile_open(&psh->fdtab, fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NTO:
+		if (Cflag(psh))
+			oflags |= O_EXCL;
+		/* FALLTHROUGH */
+	case NCLOBBER:
+		fname = redir->nfile.expfname;
+		if ((f = shfile_open(&psh->fdtab, fname, oflags, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NAPPEND:
+		fname = redir->nfile.expfname;
+		if ((f = shfile_open(&psh->fdtab, fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NTOFD:
+	case NFROMFD:
+		if (redir->ndup.dupfd >= 0) {	/* if not ">&-" */
+			if (memory[redir->ndup.dupfd])
+				memory[fd] = 1;
+			else
+				copyfd(psh, redir->ndup.dupfd, fd);
+		}
+		INTON;
+		return;
+	case NHERE:
+	case NXHERE:
+		f = openhere(psh, redir);
+		break;
+	default:
+		sh_abort(psh);
+	}
+
+	if (f != fd) {
+		copyfd(psh, f, fd);
+		shfile_close(&psh->fdtab, f);
+	}
+	INTON;
+	return;
+ecreate:
+	error(psh, "cannot create %s: %s", fname, errmsg(psh, errno, E_CREAT));
+eopen:
+	error(psh, "cannot open %s: %s", fname, errmsg(psh, errno, E_OPEN));
+}
+
+
+/*
+ * Handle here documents.  Normally we fork off a process to write the
+ * data to a pipe.  If the document is short, we can stuff the data in
+ * the pipe without forking.
+ */
+
+STATIC int
+openhere(shinstance *psh, union node *redir)
+{
+	int pip[2];
+	size_t len = 0;
+
+	if (shfile_pipe(&psh->fdtab, pip) < 0)
+		error(psh, "Pipe call failed");
+	if (redir->type == NHERE) {
+		len = strlen(redir->nhere.doc->narg.text);
+		if (len <= PIPESIZE) {
+			xwrite(psh, pip[1], redir->nhere.doc->narg.text, len);
+			goto out;
+		}
+	}
+	if (forkshell(psh, (struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
+		shfile_close(&psh->fdtab, pip[0]);
+		sh_signal(psh, SIGINT, SH_SIG_IGN);
+		sh_signal(psh, SIGQUIT, SH_SIG_IGN);
+		sh_signal(psh, SIGHUP, SH_SIG_IGN);
+#ifdef SIGTSTP
+		sh_signal(psh, SIGTSTP, SH_SIG_IGN);
+#endif
+		sh_signal(psh, SIGPIPE, SH_SIG_DFL);
+		if (redir->type == NHERE)
+			xwrite(psh, pip[1], redir->nhere.doc->narg.text, len);
+		else
+			expandhere(psh, redir->nhere.doc, pip[1]);
+		sh__exit(psh, 0);
+	}
+out:
+	shfile_close(&psh->fdtab, pip[1]);
+	return pip[0];
+}
+
+
+
+/*
+ * Undo the effects of the last redirection.
+ */
+
+void
+popredir(shinstance *psh)
+{
+	struct redirtab *rp = psh->redirlist;
+	int i;
+
+	for (i = 0 ; i < 10 ; i++) {
+		if (rp->renamed[i] != EMPTY) {
+                        if (i == 0)
+                                psh->fd0_redirected--;
+			shfile_close(&psh->fdtab, i);
+			if (rp->renamed[i] >= 0) {
+				copyfd(psh, rp->renamed[i], i);
+				shfile_close(&psh->fdtab, rp->renamed[i]);
+			}
+		}
+	}
+	INTOFF;
+	psh->redirlist = rp->next;
+	ckfree(rp);
+	INTON;
+}
+
+/*
+ * Undo all redirections.  Called on error or interrupt.
+ */
+
+#ifdef mkinit
+
+INCLUDE "redir.h"
+
+RESET {
+	while (psh->redirlist)
+		popredir(psh);
+}
+
+SHELLPROC {
+	clearredir(psh, 0);
+}
+
+#endif
+
+/* Return true if fd 0 has already been redirected at least once.  */
+int
+fd0_redirected_p(shinstance *psh) {
+        return psh->fd0_redirected != 0;
+}
+
+/*
+ * Discard all saved file descriptors.
+ */
+
+void
+clearredir(shinstance *psh, int vforked)
+{
+	struct redirtab *rp;
+	int i;
+
+	for (rp = psh->redirlist ; rp ; rp = rp->next) {
+		for (i = 0 ; i < 10 ; i++) {
+			if (rp->renamed[i] >= 0) {
+				shfile_close(&psh->fdtab, rp->renamed[i]);
+			}
+			if (!vforked)
+				rp->renamed[i] = EMPTY;
+		}
+	}
+}
+
+
+
+/*
+ * Copy a file descriptor to be >= to.  Returns -1
+ * if the source file descriptor is closed, EMPTY if there are no unused
+ * file descriptors left.
+ */
+
+int
+copyfd(shinstance *psh, int from, int to)
+{
+	int newfd;
+
+	newfd = shfile_fcntl(&psh->fdtab, from, F_DUPFD, to);
+	if (newfd < 0) {
+		if (errno == EMFILE)
+			return EMPTY;
+		else
+			error(psh, "%d: %s", from, strerror(errno));
+	}
+	return newfd;
+}
Index: /tags/kBuild-0.1.4/src/kash/redir.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/redir.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/redir.h	(revision 1780)
@@ -0,0 +1,48 @@
+/*	$NetBSD: redir.h,v 1.15 2003/08/07 09:05:37 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)redir.h	8.2 (Berkeley) 5/4/95
+ */
+
+/* flags passed to redirect */
+#define REDIR_PUSH 01		/* save previous values of file descriptors */
+#define REDIR_BACKQ 02		/* save the command output in memory */
+#define REDIR_VFORK 04		/* running under vfork(2), be careful */
+
+union node;
+void redirect(struct shinstance *, union node *, int);
+void popredir(struct shinstance *);
+int fd0_redirected_p(struct shinstance *);
+void clearredir(struct shinstance *, int);
+int copyfd(struct shinstance *, int, int);
+
Index: /tags/kBuild-0.1.4/src/kash/setmode.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/setmode.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/setmode.c	(revision 1780)
@@ -0,0 +1,473 @@
+/*	$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Dave Borman at Cray Research, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setmode.c	8.2 (Berkeley) 3/25/94";
+#else
+__RCSID("$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "shinstance.h" /* for unistd.h types/defines */
+
+#ifdef SETMODE_DEBUG
+#include <stdio.h>
+#endif
+
+#define	SET_LEN	6		/* initial # of bitcmd struct to malloc */
+#define	SET_LEN_INCR 4		/* # of bitcmd structs to add as needed */
+
+typedef struct bitcmd {
+	char	cmd;
+	char	cmd2;
+	mode_t	bits;
+} BITCMD;
+
+#define	CMD2_CLR	0x01
+#define	CMD2_SET	0x02
+#define	CMD2_GBITS	0x04
+#define	CMD2_OBITS	0x08
+#define	CMD2_UBITS	0x10
+
+static BITCMD	*addcmd(BITCMD *, int, int, int, unsigned int);
+static void	 compress_mode(BITCMD *);
+#ifdef SETMODE_DEBUG
+static void	 dumpmode(BITCMD *);
+#endif
+
+#ifndef _DIAGASSERT
+# define _DIAGASSERT assert
+#endif
+
+#ifndef S_ISTXT
+# ifdef S_ISVTX
+#  define S_ISTXT S_ISVTX
+# else
+#  define S_ISTXT 0
+# endif
+#endif /* !S_ISTXT */
+
+/*
+ * Given the old mode and an array of bitcmd structures, apply the operations
+ * described in the bitcmd structures to the old mode, and return the new mode.
+ * Note that there is no '=' command; a strict assignment is just a '-' (clear
+ * bits) followed by a '+' (set bits).
+ */
+mode_t
+bsd_getmode(const void *bbox, mode_t omode)
+{
+	const BITCMD *set;
+	mode_t clrval, newmode, value;
+
+	_DIAGASSERT(bbox != NULL);
+
+	set = (const BITCMD *)bbox;
+	newmode = omode;
+	for (value = 0;; set++)
+		switch(set->cmd) {
+		/*
+		 * When copying the user, group or other bits around, we "know"
+		 * where the bits are in the mode so that we can do shifts to
+		 * copy them around.  If we don't use shifts, it gets real
+		 * grundgy with lots of single bit checks and bit sets.
+		 */
+		case 'u':
+			value = (newmode & S_IRWXU) >> 6;
+			goto common;
+
+		case 'g':
+			value = (newmode & S_IRWXG) >> 3;
+			goto common;
+
+		case 'o':
+			value = newmode & S_IRWXO;
+common:			if (set->cmd2 & CMD2_CLR) {
+				clrval =
+				    (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
+				if (set->cmd2 & CMD2_UBITS)
+					newmode &= ~((clrval<<6) & set->bits);
+				if (set->cmd2 & CMD2_GBITS)
+					newmode &= ~((clrval<<3) & set->bits);
+				if (set->cmd2 & CMD2_OBITS)
+					newmode &= ~(clrval & set->bits);
+			}
+			if (set->cmd2 & CMD2_SET) {
+				if (set->cmd2 & CMD2_UBITS)
+					newmode |= (value<<6) & set->bits;
+				if (set->cmd2 & CMD2_GBITS)
+					newmode |= (value<<3) & set->bits;
+				if (set->cmd2 & CMD2_OBITS)
+					newmode |= value & set->bits;
+			}
+			break;
+
+		case '+':
+			newmode |= set->bits;
+			break;
+
+		case '-':
+			newmode &= ~set->bits;
+			break;
+
+		case 'X':
+			if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
+				newmode |= set->bits;
+			break;
+
+		case '\0':
+		default:
+#ifdef SETMODE_DEBUG
+			(void)printf("getmode:%04o -> %04o\n", omode, newmode);
+#endif
+			return (newmode);
+		}
+}
+
+#define	ADDCMD(a, b, c, d) do {						\
+	if (set >= endset) {						\
+		BITCMD *newset;						\
+		setlen += SET_LEN_INCR;					\
+		newset = realloc(saveset, sizeof(BITCMD) * setlen);	\
+		if (newset == NULL) {					\
+			free(saveset);					\
+			return (NULL);					\
+		}							\
+		set = newset + (set - saveset);				\
+		saveset = newset;					\
+		endset = newset + (setlen - 2);				\
+	}								\
+	set = addcmd(set, (a), (b), (c), (d));				\
+} while (/*CONSTCOND*/0)
+
+#define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+
+void *
+bsd_setmode(shinstance *psh, const char *p)
+{
+	int perm, who;
+	char op, *ep;
+	BITCMD *set, *saveset, *endset;
+	mode_t mask;
+	int equalopdone = 0;	/* pacify gcc */
+	int permXbits, setlen;
+
+	if (!*p)
+		return (NULL);
+
+	/*
+	 * Get a copy of the mask for the permissions that are mask relative.
+	 * Flip the bits, we want what's not set.
+	 */
+        mask = shfile_get_umask(&psh->fdtab);
+
+	setlen = SET_LEN + 2;
+
+	if ((set = malloc(sizeof(BITCMD) * setlen)) == NULL)
+		return (NULL);
+	saveset = set;
+	endset = set + (setlen - 2);
+
+	/*
+	 * If an absolute number, get it and return; disallow non-octal digits
+	 * or illegal bits.
+	 */
+	if (isdigit((unsigned char)*p)) {
+		perm = (mode_t)strtol(p, &ep, 8);
+		if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
+			free(saveset);
+			return (NULL);
+		}
+		ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
+		set->cmd = 0;
+		return (saveset);
+	}
+
+	/*
+	 * Build list of structures to set/clear/copy bits as described by
+	 * each clause of the symbolic mode.
+	 */
+	for (;;) {
+		/* First, find out which bits might be modified. */
+		for (who = 0;; ++p) {
+			switch (*p) {
+			case 'a':
+				who |= STANDARD_BITS;
+				break;
+			case 'u':
+				who |= S_ISUID|S_IRWXU;
+				break;
+			case 'g':
+				who |= S_ISGID|S_IRWXG;
+				break;
+			case 'o':
+				who |= S_IRWXO;
+				break;
+			default:
+				goto getop;
+			}
+		}
+
+getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
+			free(saveset);
+			return (NULL);
+		}
+		if (op == '=')
+			equalopdone = 0;
+
+		who &= ~S_ISTXT;
+		for (perm = 0, permXbits = 0;; ++p) {
+			switch (*p) {
+			case 'r':
+				perm |= S_IRUSR|S_IRGRP|S_IROTH;
+				break;
+			case 's':
+				/*
+				 * If specific bits where requested and
+				 * only "other" bits ignore set-id.
+				 */
+				if (who == 0 || (who & ~S_IRWXO))
+					perm |= S_ISUID|S_ISGID;
+				break;
+			case 't':
+				/*
+				 * If specific bits where requested and
+				 * only "other" bits ignore set-id.
+				 */
+				if (who == 0 || (who & ~S_IRWXO)) {
+					who |= S_ISTXT;
+					perm |= S_ISTXT;
+				}
+				break;
+			case 'w':
+				perm |= S_IWUSR|S_IWGRP|S_IWOTH;
+				break;
+			case 'X':
+				permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
+				break;
+			case 'x':
+				perm |= S_IXUSR|S_IXGRP|S_IXOTH;
+				break;
+			case 'u':
+			case 'g':
+			case 'o':
+				/*
+				 * When ever we hit 'u', 'g', or 'o', we have
+				 * to flush out any partial mode that we have,
+				 * and then do the copying of the mode bits.
+				 */
+				if (perm) {
+					ADDCMD(op, who, perm, mask);
+					perm = 0;
+				}
+				if (op == '=')
+					equalopdone = 1;
+				if (op == '+' && permXbits) {
+					ADDCMD('X', who, permXbits, mask);
+					permXbits = 0;
+				}
+				ADDCMD(*p, who, op, mask);
+				break;
+
+			default:
+				/*
+				 * Add any permissions that we haven't already
+				 * done.
+				 */
+				if (perm || (op == '=' && !equalopdone)) {
+					if (op == '=')
+						equalopdone = 1;
+					ADDCMD(op, who, perm, mask);
+					perm = 0;
+				}
+				if (permXbits) {
+					ADDCMD('X', who, permXbits, mask);
+					permXbits = 0;
+				}
+				goto apply;
+			}
+		}
+
+apply:		if (!*p)
+			break;
+		if (*p != ',')
+			goto getop;
+		++p;
+	}
+	set->cmd = 0;
+#ifdef SETMODE_DEBUG
+	(void)printf("Before compress_mode()\n");
+	dumpmode(saveset);
+#endif
+	compress_mode(saveset);
+#ifdef SETMODE_DEBUG
+	(void)printf("After compress_mode()\n");
+	dumpmode(saveset);
+#endif
+	return (saveset);
+}
+
+static BITCMD *
+addcmd(set, op, who, oparg, mask)
+	BITCMD *set;
+	int oparg, who;
+	int op;
+	unsigned int mask;
+{
+
+	_DIAGASSERT(set != NULL);
+
+	switch (op) {
+	case '=':
+		set->cmd = '-';
+		set->bits = who ? who : STANDARD_BITS;
+		set++;
+
+		op = '+';
+		/* FALLTHROUGH */
+	case '+':
+	case '-':
+	case 'X':
+		set->cmd = op;
+		set->bits = (who ? who : mask) & oparg;
+		break;
+
+	case 'u':
+	case 'g':
+	case 'o':
+		set->cmd = op;
+		if (who) {
+			set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
+				    ((who & S_IRGRP) ? CMD2_GBITS : 0) |
+				    ((who & S_IROTH) ? CMD2_OBITS : 0);
+			set->bits = (mode_t)~0;
+		} else {
+			set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
+			set->bits = mask;
+		}
+
+		if (oparg == '+')
+			set->cmd2 |= CMD2_SET;
+		else if (oparg == '-')
+			set->cmd2 |= CMD2_CLR;
+		else if (oparg == '=')
+			set->cmd2 |= CMD2_SET|CMD2_CLR;
+		break;
+	}
+	return (set + 1);
+}
+
+#ifdef SETMODE_DEBUG
+static void
+dumpmode(set)
+	BITCMD *set;
+{
+
+	_DIAGASSERT(set != NULL);
+
+	for (; set->cmd; ++set)
+		(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
+		    set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
+		    set->cmd2 & CMD2_CLR ? " CLR" : "",
+		    set->cmd2 & CMD2_SET ? " SET" : "",
+		    set->cmd2 & CMD2_UBITS ? " UBITS" : "",
+		    set->cmd2 & CMD2_GBITS ? " GBITS" : "",
+		    set->cmd2 & CMD2_OBITS ? " OBITS" : "");
+}
+#endif
+
+/*
+ * Given an array of bitcmd structures, compress by compacting consecutive
+ * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
+ * 'g' and 'o' commands continue to be separate.  They could probably be
+ * compacted, but it's not worth the effort.
+ */
+static void
+compress_mode(set)
+	BITCMD *set;
+{
+	BITCMD *nset;
+	int setbits, clrbits, Xbits, op;
+
+	_DIAGASSERT(set != NULL);
+
+	for (nset = set;;) {
+		/* Copy over any 'u', 'g' and 'o' commands. */
+		while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
+			*set++ = *nset++;
+			if (!op)
+				return;
+		}
+
+		for (setbits = clrbits = Xbits = 0;; nset++) {
+			if ((op = nset->cmd) == '-') {
+				clrbits |= nset->bits;
+				setbits &= ~nset->bits;
+				Xbits &= ~nset->bits;
+			} else if (op == '+') {
+				setbits |= nset->bits;
+				clrbits &= ~nset->bits;
+				Xbits &= ~nset->bits;
+			} else if (op == 'X')
+				Xbits |= nset->bits & ~setbits;
+			else
+				break;
+		}
+		if (clrbits) {
+			set->cmd = '-';
+			set->cmd2 = 0;
+			set->bits = clrbits;
+			set++;
+		}
+		if (setbits) {
+			set->cmd = '+';
+			set->cmd2 = 0;
+			set->bits = setbits;
+			set++;
+		}
+		if (Xbits) {
+			set->cmd = 'X';
+			set->cmd2 = 0;
+			set->bits = Xbits;
+			set++;
+		}
+	}
+}
Index: /tags/kBuild-0.1.4/src/kash/sh.1
===================================================================
--- /tags/kBuild-0.1.4/src/kash/sh.1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/sh.1	(revision 1780)
@@ -0,0 +1,1949 @@
+.\"	$NetBSD: sh.1,v 1.80 2005/05/24 00:03:52 wiz Exp $
+.\" Copyright (c) 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Kenneth Almquist.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)sh.1	8.6 (Berkeley) 5/4/95
+.\"
+.Dd May 7, 2005
+.Os
+.Dt SH 1
+.Sh NAME
+.Nm sh
+.Nd command interpreter (shell)
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Op Ar command_file Oo Ar argument ... Oc
+.Ek
+.Nm
+.Fl c
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Ar command_string
+.Op Ar command_name Oo Ar argument ... Oc
+.Ek
+.Nm
+.Fl s
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Op Ar argument ...
+.Ek
+.Sh DESCRIPTION
+.Nm
+is the standard command interpreter for the system.
+The current version of
+.Nm
+is in the process of being changed to conform with the
+.Tn POSIX
+1003.2 and 1003.2a specifications for the shell.
+This version has many
+features which make it appear similar in some respects to the Korn shell,
+but it is not a Korn shell clone (see
+.Xr ksh 1 ) .
+Only features designated by
+.Tn POSIX ,
+plus a few Berkeley extensions, are being incorporated into this shell.
+.\" We expect
+.\" .Tn POSIX
+.\" conformance by the time 4.4 BSD is released.
+This man page is not intended
+to be a tutorial or a complete specification of the shell.
+.Ss Overview
+The shell is a command that reads lines from either a file or the
+terminal, interprets them, and generally executes other commands.
+It is the program that is running when a user logs into the system
+(although a user can select a different shell with the
+.Xr chsh 1
+command).
+The shell implements a language that has flow control
+constructs, a macro facility that provides a variety of features in
+addition to data storage, along with built in history and line editing
+capabilities.
+It incorporates many features to aid interactive use and
+has the advantage that the interpretative language is common to both
+interactive and non-interactive use (shell scripts).
+That is, commands
+can be typed directly to the running shell or can be put into a file and
+the file can be executed directly by the shell.
+.Ss Invocation
+If no args are present and if the standard input of the shell
+is connected to a terminal (or if the
+.Fl i
+flag is set),
+and the
+.Fl c
+option is not present, the shell is considered an interactive shell.
+An interactive shell generally prompts before each command and handles
+programming and command errors differently (as described below).
+When first starting,
+the shell inspects argument 0, and if it begins with a dash
+.Sq - ,
+the shell is also considered
+a login shell.
+This is normally done automatically by the system
+when the user first logs in.
+A login shell first reads commands
+from the files
+.Pa /etc/profile
+and
+.Pa .profile
+if they exist.
+If the environment variable
+.Ev ENV
+is set on entry to a shell, or is set in the
+.Pa .profile
+of a login shell, the shell next reads
+commands from the file named in
+.Ev ENV .
+Therefore, a user should place commands that are to be executed only at
+login time in the
+.Pa .profile
+file, and commands that are executed for every shell inside the
+.Ev ENV
+file.
+To set the
+.Ev ENV
+variable to some file, place the following line in your
+.Pa .profile
+of your home directory
+.Pp
+.Dl ENV=$HOME/.shinit; export ENV
+.Pp
+substituting for
+.Dq .shinit
+any filename you wish.
+Since the
+.Ev ENV
+file is read for every invocation of the shell, including shell scripts
+and non-interactive shells, the following paradigm is useful for
+restricting commands in the
+.Ev ENV
+file to interactive invocations.
+Place commands within the
+.Dq case
+and
+.Dq esac
+below (these commands are described later):
+.Pp
+.Bl -item -compact -offset indent
+.It
+.Li case $- in *i*)
+.Bl -item -compact -offset indent
+.It
+.Li # commands for interactive use only
+.It
+.Li ...
+.El
+.It
+.Li esac
+.El
+.Pp
+If command line arguments besides the options have been specified, then
+the shell treats the first argument as the name of a file from which to
+read commands (a shell script), and the remaining arguments are set as the
+positional parameters of the shell ($1, $2, etc).
+Otherwise, the shell
+reads commands from its standard input.
+.Ss Argument List Processing
+All of the single letter options have a corresponding name that can be
+used as an argument to the
+.Fl o
+option.
+The set
+.Fl o
+name is provided next to the single letter option in
+the description below.
+Specifying a dash
+.Dq -
+turns the option on, while using a plus
+.Dq +
+disables the option.
+The following options can be set from the command line or
+with the
+.Ic set
+builtin (described later).
+.Bl -tag -width aaaallexportfoo -offset indent
+.It Fl a Em allexport
+Export all variables assigned to.
+.It Fl c
+Read commands from the
+.Ar command_string
+operand instead of from the standard input.
+Special parameter 0 will be set from the
+.Ar command_name
+operand and the positional parameters ($1, $2, etc.)
+set from the remaining argument operands.
+.It Fl C Em noclobber
+Don't overwrite existing files with
+.Dq \*[Gt] .
+.It Fl e Em errexit
+If not interactive, exit immediately if any untested command fails.
+The exit status of a command is considered to be
+explicitly tested if the command is used to control an
+.Ic if ,
+.Ic elif ,
+.Ic while ,
+or
+.Ic until ;
+or if the command is the left hand operand of an
+.Dq \*[Am]\*[Am]
+or
+.Dq ||
+operator.
+.It Fl f Em noglob
+Disable pathname expansion.
+.It Fl n Em noexec
+If not interactive, read commands but do not execute them.
+This is useful for checking the syntax of shell scripts.
+.It Fl u Em nounset
+Write a message to standard error when attempting to expand a variable
+that is not set, and if the shell is not interactive, exit immediately.
+.It Fl v Em verbose
+The shell writes its input to standard error as it is read.
+Useful for debugging.
+.It Fl x Em xtrace
+Write each command to standard error (preceded by a
+.Sq +\  )
+before it is executed.
+Useful for debugging.
+.It Fl q Em quietprofile
+If the
+.Fl v
+or
+.Fl x
+options have been set, do not apply them when reading
+initialization files, these being
+.Pa /etc/profile ,
+.Pa .profile ,
+and the file specified by the
+.Ev ENV
+environment variable.
+.It Fl I Em ignoreeof
+Ignore EOF's from input when interactive.
+.It Fl i Em interactive
+Force the shell to behave interactively.
+.It Fl m Em monitor
+Turn on job control (set automatically when interactive).
+.It Fl s Em stdin
+Read commands from standard input (set automatically if no file arguments
+are present).
+This option has no effect when set after the shell has
+already started running (i.e. with
+.Ic set ) .
+.It Fl V Em vi
+Enable the built-in
+.Xr vi 1
+command line editor (disables
+.Fl E
+if it has been set).
+(See the
+.Sx Command Line Editing
+section below.)
+.It Fl E Em emacs
+Enable the built-in emacs style
+command line editor (disables
+.Fl V
+if it has been set).
+(See the
+.Sx Command Line Editing
+section below.)
+.It Fl b Em notify
+Enable asynchronous notification of background job completion.
+(UNIMPLEMENTED for 4.4alpha)
+.It "\ \ " Em cdprint
+Make an interactive shell always print the new directory name when
+changed by the
+.Ic cd
+command.
+.It "\ \ " Em tabcomplete
+Enables filename completion in the command line editor.
+Typing a tab character will extend the current input word to match a
+filename.
+If more than one filename matches it is only extended to be the common prefix.
+Typing a second tab character will list all the matching names.
+.El
+.Ss Lexical Structure
+The shell reads input in terms of lines from a file and breaks it up into
+words at whitespace (blanks and tabs), and at certain sequences of
+characters that are special to the shell called
+.Dq operators .
+There are two types of operators: control operators and redirection
+operators (their meaning is discussed later).
+Following is a list of operators:
+.Bl -ohang -offset indent
+.It "Control operators:"
+.Dl \*[Am]  \*[Am]\*[Am]  \&(  \&)  \&;  ;; | || \*[Lt]newline\*[Gt]
+.It "Redirection operators:"
+.Dl \*[Lt]  \*[Gt]  \*[Gt]|  \*[Lt]\*[Lt]  \*[Gt]\*[Gt]  \*[Lt]\*[Am]  \*[Gt]\*[Am]  \*[Lt]\*[Lt]-  \*[Lt]\*[Gt]
+.El
+.Ss Quoting
+Quoting is used to remove the special meaning of certain characters or
+words to the shell, such as operators, whitespace, or keywords.
+There are three types of quoting: matched single quotes,
+matched double quotes, and backslash.
+.Ss Backslash
+A backslash preserves the literal meaning of the following
+character, with the exception of
+.Aq newline .
+A backslash preceding a
+.Aq newline
+is treated as a line continuation.
+.Ss Single Quotes
+Enclosing characters in single quotes preserves the literal meaning of all
+the characters (except single quotes, making it impossible to put
+single-quotes in a single-quoted string).
+.Ss Double Quotes
+Enclosing characters within double quotes preserves the literal
+meaning of all characters except dollarsign
+.Pq $ ,
+backquote
+.Pq ` ,
+and backslash
+.Pq \e .
+The backslash inside double quotes is historically weird, and serves to
+quote only the following characters:
+.Dl $  `  \*q  \e  \*[Lt]newline\*[Gt] .
+Otherwise it remains literal.
+.Ss Reserved Words
+Reserved words are words that have special meaning to the
+shell and are recognized at the beginning of a line and
+after a control operator.
+The following are reserved words:
+.Bl -column while while while while while -offset indent
+.It ! Ta elif Ta fi Ta while Ta case
+.It else Ta for Ta then Ta { Ta }
+.It do Ta done Ta until Ta if Ta esac
+.El
+.Pp
+Their meaning is discussed later.
+.Ss Aliases
+An alias is a name and corresponding value set using the
+.Ic alias
+builtin command.
+Whenever a reserved word may occur (see above),
+and after checking for reserved words, the shell
+checks the word to see if it matches an alias.
+If it does, it replaces it in the input stream with its value.
+For example, if there is an alias called
+.Dq lf
+with the value
+.Dq "ls -F" ,
+then the input:
+.Pp
+.Dl lf foobar Aq return
+.Pp
+would become
+.Pp
+.Dl ls -F foobar Aq return
+.Pp
+Aliases provide a convenient way for naive users to create shorthands for
+commands without having to learn how to create functions with arguments.
+They can also be used to create lexically obscure code.
+This use is discouraged.
+.Ss Commands
+The shell interprets the words it reads according to a language, the
+specification of which is outside the scope of this man page (refer to the
+BNF in the
+.Tn POSIX
+1003.2 document).
+Essentially though, a line is read and if the first
+word of the line (or after a control operator) is not a reserved word,
+then the shell has recognized a simple command.
+Otherwise, a complex
+command or some other special construct may have been recognized.
+.Ss Simple Commands
+If a simple command has been recognized, the shell performs
+the following actions:
+.Bl -enum -offset indent
+.It
+Leading words of the form
+.Dq name=value
+are stripped off and assigned to the environment of the simple command.
+Redirection operators and their arguments (as described below) are
+stripped off and saved for processing.
+.It
+The remaining words are expanded as described in
+the section called
+.Dq Expansions ,
+and the first remaining word is considered the command name and the
+command is located.
+The remaining words are considered the arguments of the command.
+If no command name resulted, then the
+.Dq name=value
+variable assignments recognized in item 1 affect the current shell.
+.It
+Redirections are performed as described in the next section.
+.El
+.Ss Redirections
+Redirections are used to change where a command reads its input or sends
+its output.
+In general, redirections open, close, or duplicate an
+existing reference to a file.
+The overall format used for redirection is:
+.Pp
+.Dl [n] Va redir-op Ar file
+.Pp
+where
+.Va redir-op
+is one of the redirection operators mentioned previously.
+Following is a list of the possible redirections.
+The
+.Bq n
+is an optional number, as in
+.Sq 3
+(not
+.Sq Bq 3 ) ,
+that refers to a file descriptor.
+.Bl -tag -width aaabsfiles -offset indent
+.It [n] Ns \*[Gt] file
+Redirect standard output (or n) to file.
+.It [n] Ns \*[Gt]| file
+Same, but override the
+.Fl C
+option.
+.It [n] Ns \*[Gt]\*[Gt] file
+Append standard output (or n) to file.
+.It [n] Ns \*[Lt] file
+Redirect standard input (or n) from file.
+.It [n1] Ns \*[Lt]\*[Am] Ns n2
+Duplicate standard input (or n1) from file descriptor n2.
+.It [n] Ns \*[Lt]\*[Am]-
+Close standard input (or n).
+.It [n1] Ns \*[Gt]\*[Am] Ns n2
+Duplicate standard output (or n1) to n2.
+.It [n] Ns \*[Gt]\*[Am]-
+Close standard output (or n).
+.It [n] Ns \*[Lt]\*[Gt] file
+Open file for reading and writing on standard input (or n).
+.El
+.Pp
+The following redirection is often called a
+.Dq here-document .
+.Bl -item -offset indent
+.It
+.Li [n]\*[Lt]\*[Lt] delimiter
+.Dl here-doc-text ...
+.Li delimiter
+.El
+.Pp
+All the text on successive lines up to the delimiter is saved away and
+made available to the command on standard input, or file descriptor n if
+it is specified.
+If the delimiter as specified on the initial line is
+quoted, then the here-doc-text is treated literally, otherwise the text is
+subjected to parameter expansion, command substitution, and arithmetic
+expansion (as described in the section on
+.Dq Expansions ) .
+If the operator is
+.Dq \*[Lt]\*[Lt]-
+instead of
+.Dq \*[Lt]\*[Lt] ,
+then leading tabs in the here-doc-text are stripped.
+.Ss Search and Execution
+There are three types of commands: shell functions, builtin commands, and
+normal programs -- and the command is searched for (by name) in that order.
+They each are executed in a different way.
+.Pp
+When a shell function is executed, all of the shell positional parameters
+(except $0, which remains unchanged) are set to the arguments of the shell
+function.
+The variables which are explicitly placed in the environment of
+the command (by placing assignments to them before the function name) are
+made local to the function and are set to the values given.
+Then the command given in the function definition is executed.
+The positional parameters are restored to their original values
+when the command completes.
+This all occurs within the current shell.
+.Pp
+Shell builtins are executed internally to the shell, without spawning a
+new process.
+.Pp
+Otherwise, if the command name doesn't match a function or builtin, the
+command is searched for as a normal program in the file system (as
+described in the next section).
+When a normal program is executed, the shell runs the program,
+passing the arguments and the environment to the program.
+If the program is not a normal executable file (i.e., if it does
+not begin with the "magic number" whose
+.Tn ASCII
+representation is "#!", so
+.Xr execve 2
+returns
+.Er ENOEXEC
+then) the shell will interpret the program in a subshell.
+The child shell will reinitialize itself in this case,
+so that the effect will be as if a
+new shell had been invoked to handle the ad-hoc shell script, except that
+the location of hashed commands located in the parent shell will be
+remembered by the child.
+.Pp
+Note that previous versions of this document and the source code itself
+misleadingly and sporadically refer to a shell script without a magic
+number as a "shell procedure".
+.Ss Path Search
+When locating a command, the shell first looks to see if it has a shell
+function by that name.
+Then it looks for a builtin command by that name.
+If a builtin command is not found, one of two things happen:
+.Bl -enum
+.It
+Command names containing a slash are simply executed without performing
+any searches.
+.It
+The shell searches each entry in
+.Ev PATH
+in turn for the command.
+The value of the
+.Ev PATH
+variable should be a series of entries separated by colons.
+Each entry consists of a directory name.
+The current directory may be indicated
+implicitly by an empty directory name, or explicitly by a single period.
+.El
+.Ss Command Exit Status
+Each command has an exit status that can influence the behavior
+of other shell commands.
+The paradigm is that a command exits
+with zero for normal or success, and non-zero for failure,
+error, or a false indication.
+The man page for each command
+should indicate the various exit codes and what they mean.
+Additionally, the builtin commands return exit codes, as does
+an executed shell function.
+.Pp
+If a command consists entirely of variable assignments then the
+exit status of the command is that of the last command substitution
+if any, otherwise 0.
+.Ss Complex Commands
+Complex commands are combinations of simple commands with control
+operators or reserved words, together creating a larger complex command.
+More generally, a command is one of the following:
+.Bl -bullet
+.It
+simple command
+.It
+pipeline
+.It
+list or compound-list
+.It
+compound command
+.It
+function definition
+.El
+.Pp
+Unless otherwise stated, the exit status of a command is that of the last
+simple command executed by the command.
+.Ss Pipelines
+A pipeline is a sequence of one or more commands separated
+by the control operator |.
+The standard output of all but
+the last command is connected to the standard input
+of the next command.
+The standard output of the last
+command is inherited from the shell, as usual.
+.Pp
+The format for a pipeline is:
+.Pp
+.Dl [!] command1 [ | command2 ...]
+.Pp
+The standard output of command1 is connected to the standard input of
+command2.
+The standard input, standard output, or both of a command is
+considered to be assigned by the pipeline before any redirection specified
+by redirection operators that are part of the command.
+.Pp
+If the pipeline is not in the background (discussed later), the shell
+waits for all commands to complete.
+.Pp
+If the reserved word ! does not precede the pipeline, the exit status is
+the exit status of the last command specified in the pipeline.
+Otherwise, the exit status is the logical NOT of the exit status of the
+last command.
+That is, if the last command returns zero, the exit status
+is 1; if the last command returns greater than zero, the exit status is
+zero.
+.Pp
+Because pipeline assignment of standard input or standard output or both
+takes place before redirection, it can be modified by redirection.
+For example:
+.Pp
+.Dl $ command1 2\*[Gt]\*[Am]1 | command2
+.Pp
+sends both the standard output and standard error of command1
+to the standard input of command2.
+.Pp
+A ; or
+.Aq newline
+terminator causes the preceding AND-OR-list (described
+next) to be executed sequentially; a \*[Am] causes asynchronous execution of
+the preceding AND-OR-list.
+.Pp
+Note that unlike some other shells, each process in the pipeline is a
+child of the invoking shell (unless it is a shell builtin, in which case
+it executes in the current shell -- but any effect it has on the
+environment is wiped).
+.Ss Background Commands -- \*[Am]
+If a command is terminated by the control operator ampersand (\*[Am]), the
+shell executes the command asynchronously -- that is, the shell does not
+wait for the command to finish before executing the next command.
+.Pp
+The format for running a command in background is:
+.Pp
+.Dl command1 \*[Am] [command2 \*[Am] ...]
+.Pp
+If the shell is not interactive, the standard input of an asynchronous
+command is set to
+.Pa /dev/null .
+.Ss Lists -- Generally Speaking
+A list is a sequence of zero or more commands separated by newlines,
+semicolons, or ampersands, and optionally terminated by one of these three
+characters.
+The commands in a list are executed in the order they are written.
+If command is followed by an ampersand, the shell starts the
+command and immediately proceed onto the next command; otherwise it waits
+for the command to terminate before proceeding to the next one.
+.Ss Short-Circuit List Operators
+.Dq \*[Am]\*[Am]
+and
+.Dq ||
+are AND-OR list operators.
+.Dq \*[Am]\*[Am]
+executes the first command, and then executes the second command if and only
+if the exit status of the first command is zero.
+.Dq ||
+is similar, but executes the second command if and only if the exit status
+of the first command is nonzero.
+.Dq \*[Am]\*[Am]
+and
+.Dq ||
+both have the same priority.
+Note that these operators are left-associative, so
+.Dq true || echo bar && echo baz
+writes
+.Dq baz
+and nothing else.
+This is not the way it works in C.
+.Ss Flow-Control Constructs -- if, while, for, case
+The syntax of the if command is
+.Bd -literal -offset indent
+if list
+then list
+[ elif list
+then    list ] ...
+[ else list ]
+fi
+.Ed
+.Pp
+The syntax of the while command is
+.Bd -literal -offset indent
+while list
+do   list
+done
+.Ed
+.Pp
+The two lists are executed repeatedly while the exit status of the
+first list is zero.
+The until command is similar, but has the word
+until in place of while, which causes it to
+repeat until the exit status of the first list is zero.
+.Pp
+The syntax of the for command is
+.Bd -literal -offset indent
+for variable in word ...
+do   list
+done
+.Ed
+.Pp
+The words are expanded, and then the list is executed repeatedly with the
+variable set to each word in turn.
+do and done may be replaced with
+.Dq {
+and
+.Dq } .
+.Pp
+The syntax of the break and continue command is
+.Bd -literal -offset indent
+break [ num ]
+continue [ num ]
+.Ed
+.Pp
+Break terminates the num innermost for or while loops.
+Continue continues with the next iteration of the innermost loop.
+These are implemented as builtin commands.
+.Pp
+The syntax of the case command is
+.Bd -literal -offset indent
+case word in
+pattern) list ;;
+\&...
+esac
+.Ed
+.Pp
+The pattern can actually be one or more patterns (see
+.Sx Shell Patterns
+described later), separated by
+.Dq \*(Ba
+characters.
+.Ss Grouping Commands Together
+Commands may be grouped by writing either
+.Pp
+.Dl (list)
+.Pp
+or
+.Pp
+.Dl { list; }
+.Pp
+The first of these executes the commands in a subshell.
+Builtin commands grouped into a (list) will not affect the current shell.
+The second form does not fork another shell so is slightly more efficient.
+Grouping commands together this way allows you to redirect
+their output as though they were one program:
+.Pp
+.Bd -literal -offset indent
+{ echo -n \*q hello \*q ; echo \*q world" ; } \*[Gt] greeting
+.Ed
+.Pp
+Note that
+.Dq }
+must follow a control operator (here,
+.Dq \&; )
+so that it is recognized as a reserved word and not as another command argument.
+.Ss Functions
+The syntax of a function definition is
+.Pp
+.Dl name ( ) command
+.Pp
+A function definition is an executable statement; when executed it
+installs a function named name and returns an exit status of zero.
+The command is normally a list enclosed between
+.Dq {
+and
+.Dq } .
+.Pp
+Variables may be declared to be local to a function by using a local
+command.
+This should appear as the first statement of a function, and the syntax is
+.Pp
+.Dl local [ variable | - ] ...
+.Pp
+Local is implemented as a builtin command.
+.Pp
+When a variable is made local, it inherits the initial value and exported
+and readonly flags from the variable with the same name in the surrounding
+scope, if there is one.
+Otherwise, the variable is initially unset.
+The shell uses dynamic scoping, so that if you make the variable x local to
+function f, which then calls function g, references to the variable x made
+inside g will refer to the variable x declared inside f, not to the global
+variable named x.
+.Pp
+The only special parameter that can be made local is
+.Dq - .
+Making
+.Dq -
+local any shell options that are changed via the set command inside the
+function to be restored to their original values when the function
+returns.
+.Pp
+The syntax of the return command is
+.Pp
+.Dl return [ exitstatus ]
+.Pp
+It terminates the currently executing function.
+Return is implemented as a builtin command.
+.Ss Variables and Parameters
+The shell maintains a set of parameters.
+A parameter denoted by a name is called a variable.
+When starting up, the shell turns all the environment
+variables into shell variables.
+New variables can be set using the form
+.Pp
+.Dl name=value
+.Pp
+Variables set by the user must have a name consisting solely of
+alphabetics, numerics, and underscores - the first of which must not be
+numeric.
+A parameter can also be denoted by a number or a special
+character as explained below.
+.Ss Positional Parameters
+A positional parameter is a parameter denoted by a number (n \*[Gt] 0).
+The shell sets these initially to the values of its command line arguments
+that follow the name of the shell script.
+The
+.Ic set
+builtin can also be used to set or reset them.
+.Ss Special Parameters
+A special parameter is a parameter denoted by one of the following special
+characters.
+The value of the parameter is listed next to its character.
+.Bl -tag -width thinhyphena
+.It *
+Expands to the positional parameters, starting from one.
+When the
+expansion occurs within a double-quoted string it expands to a single
+field with the value of each parameter separated by the first character of
+the
+.Ev IFS
+variable, or by a
+.Aq space
+if
+.Ev IFS
+is unset.
+.It @
+Expands to the positional parameters, starting from one.
+When the expansion occurs within double-quotes, each positional
+parameter expands as a separate argument.
+If there are no positional parameters, the
+expansion of @ generates zero arguments, even when @ is
+double-quoted.
+What this basically means, for example, is
+if $1 is
+.Dq abc
+and $2 is
+.Dq def ghi ,
+then
+.Qq $@
+expands to
+the two arguments:
+.Pp
+.Sm off
+.Dl \*q abc \*q \  \*q def\ ghi \*q
+.Sm on
+.It #
+Expands to the number of positional parameters.
+.It \&?
+Expands to the exit status of the most recent pipeline.
+.It - (Hyphen.)
+Expands to the current option flags (the single-letter
+option names concatenated into a string) as specified on
+invocation, by the set builtin command, or implicitly
+by the shell.
+.It $
+Expands to the process ID of the invoked shell.
+A subshell retains the same value of $ as its parent.
+.It \&!
+Expands to the process ID of the most recent background
+command executed from the current shell.
+For a pipeline, the process ID is that of the last command in the pipeline.
+.It 0 (Zero.)
+Expands to the name of the shell or shell script.
+.El
+.Ss Word Expansions
+This clause describes the various expansions that are performed on words.
+Not all expansions are performed on every word, as explained later.
+.Pp
+Tilde expansions, parameter expansions, command substitutions, arithmetic
+expansions, and quote removals that occur within a single word expand to a
+single field.
+It is only field splitting or pathname expansion that can
+create multiple fields from a single word.
+The single exception to this
+rule is the expansion of the special parameter @ within double-quotes, as
+was described above.
+.Pp
+The order of word expansion is:
+.Bl -enum
+.It
+Tilde Expansion, Parameter Expansion, Command Substitution,
+Arithmetic Expansion (these all occur at the same time).
+.It
+Field Splitting is performed on fields
+generated by step (1) unless the
+.Ev IFS
+variable is null.
+.It
+Pathname Expansion (unless set
+.Fl f
+is in effect).
+.It
+Quote Removal.
+.El
+.Pp
+The $ character is used to introduce parameter expansion, command
+substitution, or arithmetic evaluation.
+.Ss Tilde Expansion (substituting a user's home directory)
+A word beginning with an unquoted tilde character (~) is
+subjected to tilde expansion.
+All the characters up to
+a slash (/) or the end of the word are treated as a username
+and are replaced with the user's home directory.
+If the username is missing (as in
+.Pa ~/foobar ) ,
+the tilde is replaced with the value of the
+.Va HOME
+variable (the current user's home directory).
+.Ss Parameter Expansion
+The format for parameter expansion is as follows:
+.Pp
+.Dl ${expression}
+.Pp
+where expression consists of all characters until the matching
+.Dq } .
+Any
+.Dq }
+escaped by a backslash or within a quoted string, and characters in
+embedded arithmetic expansions, command substitutions, and variable
+expansions, are not examined in determining the matching
+.Dq } .
+.Pp
+The simplest form for parameter expansion is:
+.Pp
+.Dl ${parameter}
+.Pp
+The value, if any, of parameter is substituted.
+.Pp
+The parameter name or symbol can be enclosed in braces, which are
+optional except for positional parameters with more than one digit or
+when parameter is followed by a character that could be interpreted as
+part of the name.
+If a parameter expansion occurs inside double-quotes:
+.Bl -enum
+.It
+Pathname expansion is not performed on the results of the expansion.
+.It
+Field splitting is not performed on the results of the
+expansion, with the exception of the special rules for @.
+.El
+.Pp
+In addition, a parameter expansion can be modified by using one of the
+following formats.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${parameter:-word}
+Use Default Values.
+If parameter is unset or null, the expansion of word
+is substituted; otherwise, the value of parameter is substituted.
+.It ${parameter:=word}
+Assign Default Values.
+If parameter is unset or null, the expansion of
+word is assigned to parameter.
+In all cases, the final value of parameter is substituted.
+Only variables, not positional parameters or special
+parameters, can be assigned in this way.
+.It ${parameter:?[word]}
+Indicate Error if Null or Unset.
+If parameter is unset or null, the
+expansion of word (or a message indicating it is unset if word is omitted)
+is written to standard error and the shell exits with a nonzero exit status.
+Otherwise, the value of parameter is substituted.
+An interactive shell need not exit.
+.It ${parameter:+word}
+Use Alternative Value.
+If parameter is unset or null, null is
+substituted; otherwise, the expansion of word is substituted.
+.El
+.Pp
+In the parameter expansions shown previously, use of the colon in the
+format results in a test for a parameter that is unset or null; omission
+of the colon results in a test for a parameter that is only unset.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${#parameter}
+String Length.
+The length in characters of the value of parameter.
+.El
+.Pp
+The following four varieties of parameter expansion provide for substring
+processing.
+In each case, pattern matching notation (see
+.Sx Shell Patterns ) ,
+rather than regular expression notation, is used to evaluate the patterns.
+If parameter is * or @, the result of the expansion is unspecified.
+Enclosing the full parameter expansion string in double-quotes does not
+cause the following four varieties of pattern characters to be quoted,
+whereas quoting characters within the braces has this effect.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${parameter%word}
+Remove Smallest Suffix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the
+smallest portion of the suffix matched by the pattern deleted.
+.It ${parameter%%word}
+Remove Largest Suffix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the largest
+portion of the suffix matched by the pattern deleted.
+.It ${parameter#word}
+Remove Smallest Prefix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the
+smallest portion of the prefix matched by the pattern deleted.
+.It ${parameter##word}
+Remove Largest Prefix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the largest
+portion of the prefix matched by the pattern deleted.
+.El
+.Ss Command Substitution
+Command substitution allows the output of a command to be substituted in
+place of the command name itself.
+Command substitution occurs when the command is enclosed as follows:
+.Pp
+.Dl $(command)
+.Pp
+or
+.Po
+.Dq backquoted
+version
+.Pc :
+.Pp
+.Dl `command`
+.Pp
+The shell expands the command substitution by executing command in a
+subshell environment and replacing the command substitution with the
+standard output of the command, removing sequences of one or more
+.Ao newline Ac Ns s
+at the end of the substitution.
+(Embedded
+.Ao newline Ac Ns s
+before
+the end of the output are not removed; however, during field splitting,
+they may be translated into
+.Ao space Ac Ns s ,
+depending on the value of
+.Ev IFS
+and quoting that is in effect.)
+.Ss Arithmetic Expansion
+Arithmetic expansion provides a mechanism for evaluating an arithmetic
+expression and substituting its value.
+The format for arithmetic expansion is as follows:
+.Pp
+.Dl $((expression))
+.Pp
+The expression is treated as if it were in double-quotes, except
+that a double-quote inside the expression is not treated specially.
+The shell expands all tokens in the expression for parameter expansion,
+command substitution, and quote removal.
+.Pp
+Next, the shell treats this as an arithmetic expression and
+substitutes the value of the expression.
+.Ss White Space Splitting (Field Splitting)
+After parameter expansion, command substitution, and
+arithmetic expansion the shell scans the results of
+expansions and substitutions that did not occur in double-quotes for
+field splitting and multiple fields can result.
+.Pp
+The shell treats each character of the
+.Ev IFS
+as a delimiter and use the delimiters to split the results of parameter
+expansion and command substitution into fields.
+.Pp
+Non-whitespace characters in
+.Ev IFS
+are treated strictly as parameter terminators.
+So adjacent non-whitespace
+.Ev IFS
+characters will produce empty parameters.
+.Pp
+If
+.Ev IFS
+is unset it is assumed to contain space, tab, and newline.
+.Ss Pathname Expansion (File Name Generation)
+Unless the
+.Fl f
+flag is set, file name generation is performed after word splitting is
+complete.
+Each word is viewed as a series of patterns, separated by slashes.
+The process of expansion replaces the word with the names of all
+existing files whose names can be formed by replacing each pattern with a
+string that matches the specified pattern.
+There are two restrictions on
+this: first, a pattern cannot match a string containing a slash, and
+second, a pattern cannot match a string starting with a period unless the
+first character of the pattern is a period.
+The next section describes the
+patterns used for both Pathname Expansion and the
+.Ic case
+command.
+.Ss Shell Patterns
+A pattern consists of normal characters, which match themselves,
+and meta-characters.
+The meta-characters are
+.Dq \&! ,
+.Dq * ,
+.Dq \&? ,
+and
+.Dq \&[ .
+These characters lose their special meanings if they are quoted.
+When command or variable substitution is performed
+and the dollar sign or back quotes are not double quoted,
+the value of the variable or the output of
+the command is scanned for these characters and they are turned into
+meta-characters.
+.Pp
+An asterisk
+.Pq Dq *
+matches any string of characters.
+A question mark matches any single character.
+A left bracket
+.Pq Dq \&[
+introduces a character class.
+The end of the character class is indicated by a
+.Pq Dq \&] ;
+if the
+.Dq \&]
+is missing then the
+.Dq \&[
+matches a
+.Dq \&[
+rather than introducing a character class.
+A character class matches any of the characters between the square brackets.
+A range of characters may be specified using a minus sign.
+The character class may be complemented
+by making an exclamation point the first character of the character class.
+.Pp
+To include a
+.Dq \&]
+in a character class, make it the first character listed (after the
+.Dq \&! ,
+if any).
+To include a minus sign, make it the first or last character listed.
+.Ss Builtins
+This section lists the builtin commands which are builtin because they
+need to perform some operation that can't be performed by a separate
+process.
+In addition to these, there are several other commands that may
+be builtin for efficiency (e.g.
+.Xr printf 1 ,
+.Xr echo 1 ,
+.Xr test 1 ,
+etc).
+.Bl -tag -width 5n
+.It :
+A null command that returns a 0 (true) exit value.
+.It \&. file
+The commands in the specified file are read and executed by the shell.
+.It alias Op Ar name Ns Op Ar "=string ..."
+If
+.Ar name=string
+is specified, the shell defines the alias
+.Ar name
+with value
+.Ar string .
+If just
+.Ar name
+is specified, the value of the alias
+.Ar name
+is printed.
+With no arguments, the
+.Ic alias
+builtin prints the
+names and values of all defined aliases (see
+.Ic unalias ) .
+.It bg [ Ar job ] ...
+Continue the specified jobs (or the current job if no
+jobs are given) in the background.
+.It Xo command
+.Op Fl p
+.Op Fl v
+.Op Fl V
+.Ar command
+.Op Ar arg ...
+.Xc
+Execute the specified command but ignore shell functions when searching
+for it.
+(This is useful when you
+have a shell function with the same name as a builtin command.)
+.Bl -tag -width 5n
+.It Fl p
+search for command using a
+.Ev PATH
+that guarantees to find all the standard utilities.
+.It Fl V
+Do not execute the command but
+search for the command and print the resolution of the
+command search.
+This is the same as the type builtin.
+.It Fl v
+Do not execute the command but
+search for the command and print the absolute pathname
+of utilities, the name for builtins or the expansion of aliases.
+.El
+.It cd Op Ar directory Op Ar replace
+Switch to the specified directory (default
+.Ev $HOME ) .
+If
+.Ar replace
+is specified, then the new directory name is generated by replacing
+the first occurrence of
+.Ar directory
+in the current directory name with
+.Ar replace .
+Otherwise if an entry for
+.Ev CDPATH
+appears in the environment of the
+.Ic cd
+command or the shell variable
+.Ev CDPATH
+is set and the directory name does not begin with a slash, then the
+directories listed in
+.Ev CDPATH
+will be searched for the specified directory.
+The format of
+.Ev CDPATH
+is the same as that of
+.Ev PATH .
+In an interactive shell, the
+.Ic cd
+command will print out the name of the
+directory that it actually switched to if this is different from the name
+that the user gave.
+These may be different either because the
+.Ev CDPATH
+mechanism was used or because a symbolic link was crossed.
+.It eval Ar string ...
+Concatenate all the arguments with spaces.
+Then re-parse and execute the command.
+.It exec Op Ar command arg ...
+Unless command is omitted, the shell process is replaced with the
+specified program (which must be a real program, not a shell builtin or
+function).
+Any redirections on the
+.Ic exec
+command are marked as permanent, so that they are not undone when the
+.Ic exec
+command finishes.
+.It exit Op Ar exitstatus
+Terminate the shell process.
+If
+.Ar exitstatus
+is given it is used as the exit status of the shell; otherwise the
+exit status of the preceding command is used.
+.It export Ar name ...
+.It export Fl p
+The specified names are exported so that they will appear in the
+environment of subsequent commands.
+The only way to un-export a variable is to unset it.
+The shell allows the value of a variable to be set at the
+same time it is exported by writing
+.Pp
+.Dl export name=value
+.Pp
+With no arguments the export command lists the names of all exported variables.
+With the
+.Fl p
+option specified the output will be formatted suitably for non-interactive use.
+.It Xo fc Op Fl e Ar editor
+.Op Ar first Op Ar last
+.Xc
+.It Xo fc Fl l
+.Op Fl nr
+.Op Ar first Op Ar last
+.Xc
+.It Xo fc Fl s Op Ar old=new
+.Op Ar first
+.Xc
+The
+.Ic fc
+builtin lists, or edits and re-executes, commands previously entered
+to an interactive shell.
+.Bl -tag -width 5n
+.It Fl e No editor
+Use the editor named by editor to edit the commands.
+The editor string is a command name, subject to search via the
+.Ev PATH
+variable.
+The value in the
+.Ev FCEDIT
+variable is used as a default when
+.Fl e
+is not specified.
+If
+.Ev FCEDIT
+is null or unset, the value of the
+.Ev EDITOR
+variable is used.
+If
+.Ev EDITOR
+is null or unset,
+.Xr ed 1
+is used as the editor.
+.It Fl l No (ell)
+List the commands rather than invoking an editor on them.
+The commands are written in the sequence indicated by
+the first and last operands, as affected by
+.Fl r ,
+with each command preceded by the command number.
+.It Fl n
+Suppress command numbers when listing with -l.
+.It Fl r
+Reverse the order of the commands listed (with
+.Fl l )
+or edited (with neither
+.Fl l
+nor
+.Fl s ) .
+.It Fl s
+Re-execute the command without invoking an editor.
+.It first
+.It last
+Select the commands to list or edit.
+The number of previous commands that
+can be accessed are determined by the value of the
+.Ev HISTSIZE
+variable.
+The value of first or last or both are one of the following:
+.Bl -tag -width 5n
+.It [+]number
+A positive number representing a command number; command numbers can be
+displayed with the
+.Fl l
+option.
+.It Fl number
+A negative decimal number representing the command that was executed
+number of commands previously.
+For example, \-1 is the immediately previous command.
+.El
+.It string
+A string indicating the most recently entered command that begins with
+that string.
+If the old=new operand is not also specified with
+.Fl s ,
+the string form of the first operand cannot contain an embedded equal sign.
+.El
+.Pp
+The following environment variables affect the execution of fc:
+.Bl -tag -width HISTSIZE
+.It Ev FCEDIT
+Name of the editor to use.
+.It Ev HISTSIZE
+The number of previous commands that are accessible.
+.El
+.It fg Op Ar job
+Move the specified job or the current job to the foreground.
+.It getopts Ar optstring var
+The
+.Tn POSIX
+.Ic getopts
+command, not to be confused with the
+.Em Bell Labs
+-derived
+.Xr getopt 1 .
+.Pp
+The first argument should be a series of letters, each of which may be
+optionally followed by a colon to indicate that the option requires an
+argument.
+The variable specified is set to the parsed option.
+.Pp
+The
+.Ic getopts
+command deprecates the older
+.Xr getopt 1
+utility due to its handling of arguments containing whitespace.
+.Pp
+The
+.Ic getopts
+builtin may be used to obtain options and their arguments
+from a list of parameters.
+When invoked,
+.Ic getopts
+places the value of the next option from the option string in the list in
+the shell variable specified by
+.Va var
+and its index in the shell variable
+.Ev OPTIND .
+When the shell is invoked,
+.Ev OPTIND
+is initialized to 1.
+For each option that requires an argument, the
+.Ic getopts
+builtin will place it in the shell variable
+.Ev OPTARG .
+If an option is not allowed for in the
+.Va optstring ,
+then
+.Ev OPTARG
+will be unset.
+.Pp
+.Va optstring
+is a string of recognized option letters (see
+.Xr getopt 3 ) .
+If a letter is followed by a colon, the option is expected to have an
+argument which may or may not be separated from it by whitespace.
+If an option character is not found where expected,
+.Ic getopts
+will set the variable
+.Va var
+to a
+.Dq \&? ;
+.Ic getopts
+will then unset
+.Ev OPTARG
+and write output to standard error.
+By specifying a colon as the first character of
+.Va optstring
+all errors will be ignored.
+.Pp
+A nonzero value is returned when the last option is reached.
+If there are no remaining arguments,
+.Ic getopts
+will set
+.Va var
+to the special option,
+.Dq -- ,
+otherwise, it will set
+.Va var
+to
+.Dq \&? .
+.Pp
+The following code fragment shows how one might process the arguments
+for a command that can take the options
+.Op a
+and
+.Op b ,
+and the option
+.Op c ,
+which requires an argument.
+.Pp
+.Bd -literal -offset indent
+while getopts abc: f
+do
+	case $f in
+	a | b)	flag=$f;;
+	c)	carg=$OPTARG;;
+	\\?)	echo $USAGE; exit 1;;
+	esac
+done
+shift `expr $OPTIND - 1`
+.Ed
+.Pp
+This code will accept any of the following as equivalent:
+.Pp
+.Bd -literal -offset indent
+cmd \-acarg file file
+cmd \-a \-c arg file file
+cmd \-carg -a file file
+cmd \-a \-carg \-\- file file
+.Ed
+.It hash Fl rv Ar command ...
+The shell maintains a hash table which remembers the
+locations of commands.
+With no arguments whatsoever,
+the
+.Ic hash
+command prints out the contents of this table.
+Entries which have not been looked at since the last
+.Ic cd
+command are marked with an asterisk; it is possible for these entries
+to be invalid.
+.Pp
+With arguments, the
+.Ic hash
+command removes the specified commands from the hash table (unless
+they are functions) and then locates them.
+With the
+.Fl v
+option, hash prints the locations of the commands as it finds them.
+The
+.Fl r
+option causes the hash command to delete all the entries in the hash table
+except for functions.
+.It inputrc Ar file
+Read the
+.Va file
+to set keybindings as defined by
+.Xr editrc 5 .
+.It jobid Op Ar job
+Print the process id's of the processes in the job.
+If the
+.Ar job
+argument is omitted, the current job is used.
+.It jobs
+This command lists out all the background processes
+which are children of the current shell process.
+.It pwd Op Fl LP
+Print the current directory.
+If 
+.Fl L
+is specified the cached value (initially set from
+.Ev PWD )
+is checked to see if it refers to the current directory, if it does
+the value is printed.
+Otherwise the current directory name is found using
+.Xr getcwd(3) .
+The environment variable
+.Ev PWD
+is set to printed value.
+.Pp
+The default is
+.Ic pwd
+.Fl L ,
+but note that the builtin
+.Ic cd
+command doesn't currently support
+.Fl L
+or
+.Fl P
+and will cache (almost) the absolute path.
+If
+.Ic cd
+is changed,
+.Ic pwd
+may be changed to default to
+.Ic pwd
+.Fl P .
+.Pp
+If the current directory is renamed and replaced by a symlink to the
+same directory, or the initial
+.Ev PWD
+value followed a symbolic link, then the cached value may not
+be the absolute path.
+.Pp
+The builtin command may differ from the program of the same name because
+the program will use
+.Ev PWD
+and the builtin uses a separately cached value.
+.It Xo read Op Fl p Ar prompt
+.Op Fl r
+.Ar variable
+.Op Ar ...
+.Xc
+The prompt is printed if the
+.Fl p
+option is specified and the standard input is a terminal.
+Then a line is read from the standard input.
+The trailing newline is deleted from the
+line and the line is split as described in the section on word splitting
+above, and the pieces are assigned to the variables in order.
+If there are more pieces than variables, the remaining pieces
+(along with the characters in
+.Ev IFS
+that separated them) are assigned to the last variable.
+If there are more variables than pieces,
+the remaining variables are assigned the null string.
+The
+.Ic read
+builtin will indicate success unless EOF is encountered on input, in
+which case failure is returned.
+.Pp
+By default, unless the
+.Fl r
+option is specified, the backslash
+.Dq \e
+acts as an escape character, causing the following character to be treated
+literally.
+If a backslash is followed by a newline, the backslash and the
+newline will be deleted.
+.It readonly Ar name ...
+.It readonly Fl p
+The specified names are marked as read only, so that they cannot be
+subsequently modified or unset.
+The shell allows the value of a variable
+to be set at the same time it is marked read only by writing
+.Pp
+.Dl readonly name=value
+.Pp
+With no arguments the readonly command lists the names of all read only
+variables.
+With the
+.Fl p
+option specified the output will be formatted suitably for non-interactive use.
+.Pp
+.It Xo set
+.Oo {
+.Fl options | Cm +options | Cm -- }
+.Oc Ar arg ...
+.Xc
+The
+.Ic set
+command performs three different functions.
+.Pp
+With no arguments, it lists the values of all shell variables.
+.Pp
+If options are given, it sets the specified option
+flags, or clears them as described in the section called
+.Sx Argument List Processing .
+.Pp
+The third use of the set command is to set the values of the shell's
+positional parameters to the specified args.
+To change the positional
+parameters without changing any options, use
+.Dq --
+as the first argument to set.
+If no args are present, the set command
+will clear all the positional parameters (equivalent to executing
+.Dq shift $# . )
+.It setvar Ar variable Ar value
+Assigns value to variable.
+(In general it is better to write
+variable=value rather than using
+.Ic setvar .
+.Ic setvar
+is intended to be used in
+functions that assign values to variables whose names are passed as
+parameters.)
+.It shift Op Ar n
+Shift the positional parameters n times.
+A
+.Ic shift
+sets the value of
+.Va $1
+to the value of
+.Va $2 ,
+the value of
+.Va $2
+to the value of
+.Va $3 ,
+and so on, decreasing
+the value of
+.Va $#
+by one.
+If there are zero positional parameters,
+.Ic shift
+does nothing.
+.It Xo trap
+.Op Fl l
+.Xc
+.It Xo trap
+.Op Ar action
+.Ar signal ...
+.Xc
+Cause the shell to parse and execute action when any of the specified
+signals are received.
+The signals are specified by signal number or as the name of the signal.
+If
+.Ar signal
+is
+.Li 0 ,
+the action is executed when the shell exits.
+.Ar action
+may be null, which cause the specified signals to be ignored.
+With
+.Ar action
+omitted or set to `-' the specified signals are set to their default action.
+When the shell forks off a subshell, it resets trapped (but not ignored)
+signals to the default action.
+The
+.Ic trap
+command has no effect on signals that were
+ignored on entry to the shell.
+Issuing
+.Ic trap
+with option
+.Ar -l
+will print a list of valid signal names.
+.Ic trap
+without any arguments cause it to write a list of signals and their
+associated action to the standard output in a format that is suitable
+as an input to the shell that achieves the same trapping results.
+.Pp
+Examples:
+.Pp
+.Dl trap
+.Pp
+List trapped signals and their corresponding action
+.Pp
+.Dl trap -l
+.Pp
+Print a list of valid signals
+.Pp
+.Dl trap '' INT QUIT tstp 30
+.Pp
+Ignore signals INT QUIT TSTP USR1
+.Pp
+.Dl trap date INT
+.Pp
+Print date upon receiving signal INT
+.It type Op Ar name ...
+Interpret each name as a command and print the resolution of the command
+search.
+Possible resolutions are:
+shell keyword, alias, shell builtin,
+command, tracked alias and not found.
+For aliases the alias expansion is
+printed; for commands and tracked aliases the complete pathname of the
+command is printed.
+.It ulimit Xo
+.Op Fl H \*(Ba Fl S
+.Op Fl a \*(Ba Fl tfdscmlpn Op Ar value
+.Xc
+Inquire about or set the hard or soft limits on processes or set new
+limits.
+The choice between hard limit (which no process is allowed to
+violate, and which may not be raised once it has been lowered) and soft
+limit (which causes processes to be signaled but not necessarily killed,
+and which may be raised) is made with these flags:
+.Bl -tag -width Fl
+.It Fl H
+set or inquire about hard limits
+.It Fl S
+set or inquire about soft limits.
+If neither
+.Fl H
+nor
+.Fl S
+is specified, the soft limit is displayed or both limits are set.
+If both are specified, the last one wins.
+.El
+.Pp
+.Bl -tag -width Fl
+The limit to be interrogated or set, then, is chosen by specifying
+any one of these flags:
+.It Fl a
+show all the current limits
+.It Fl b
+show or set the limit on the socket buffer size of a process (in bytes)
+.It Fl t
+show or set the limit on CPU time (in seconds)
+.It Fl f
+show or set the limit on the largest file that can be created
+(in 512-byte blocks)
+.It Fl d
+show or set the limit on the data segment size of a process (in kilobytes)
+.It Fl s
+show or set the limit on the stack size of a process (in kilobytes)
+.It Fl c
+show or set the limit on the largest core dump size that can be produced
+(in 512-byte blocks)
+.It Fl m
+show or set the limit on the total physical memory that can be
+in use by a process (in kilobytes)
+.It Fl l
+show or set the limit on how much memory a process can lock with
+.Xr mlock 2
+(in kilobytes)
+.It Fl p
+show or set the limit on the number of processes this user can
+have at one time
+.It Fl n
+show or set the limit on the number of files a process can have open at once
+.El
+.Pp
+If none of these is specified, it is the limit on file size that is shown
+or set.
+If value is specified, the limit is set to that number; otherwise
+the current limit is displayed.
+.Pp
+Limits of an arbitrary process can be displayed or set using the
+.Xr sysctl 8
+utility.
+.Pp
+.It umask Op Ar mask
+Set the value of umask (see
+.Xr umask 2 )
+to the specified octal value.
+If the argument is omitted, the umask value is printed.
+.It unalias Xo
+.Op Fl a
+.Op Ar name
+.Xc
+If
+.Ar name
+is specified, the shell removes that alias.
+If
+.Fl a
+is specified, all aliases are removed.
+.It unset Ar name ...
+The specified variables and functions are unset and unexported.
+If a given name corresponds to both a variable and a function, both
+the variable and the function are unset.
+.It wait Op Ar job
+Wait for the specified job to complete and return the exit status of the
+last process in the job.
+If the argument is omitted, wait for all jobs to
+complete and then return an exit status of zero.
+.El
+.Ss Command Line Editing
+When
+.Nm
+is being used interactively from a terminal, the current command
+and the command history (see
+.Ic fc
+in
+.Sx Builtins )
+can be edited using emacs-mode or vi-mode command-line editing.
+The command
+.Ql set -o emacs
+enables emacs-mode editing.
+The command
+.Ql set -o vi
+enables vi-mode editing and places sh into vi insert mode.
+(See the
+.Sx Argument List Processing
+section above.)
+.Pp
+The vi mode uses commands similar to a subset of those described in the
+.Xr vi 1
+man page.
+With vi-mode
+enabled, sh can be switched between insert mode and command mode.
+It's similar to vi: typing
+.Aq ESC
+will throw you into command VI command mode.
+Hitting
+.Aq return
+while in command mode will pass the line to the shell.
+.Pp
+The emacs mode uses commands similar to a subset available in
+the emacs editor.
+With emacs-mode enabled, special keys can be used to modify the text
+in the buffer using the control key.
+.Pp
+.Nm
+uses the
+.Xr editline 3
+library.
+.Sh EXIT STATUS
+Errors that are detected by the shell, such as a syntax error, will cause the
+shell to exit with a non-zero exit status.
+If the shell is not an
+interactive shell, the execution of the shell file will be aborted.
+Otherwise
+the shell will return the exit status of the last command executed, or
+if the exit builtin is used with a numeric argument, it will return the
+argument.
+.Sh ENVIRONMENT
+.Bl -tag -width MAILCHECK
+.It Ev HOME
+Set automatically by
+.Xr login 1
+from the user's login directory in the password file
+.Pq Xr passwd 5 .
+This environment variable also functions as the default argument for the
+cd builtin.
+.It Ev PATH
+The default search path for executables.
+See the above section
+.Sx Path Search .
+.It Ev CDPATH
+The search path used with the cd builtin.
+.It Ev LANG
+The string used to specify localization information that allows users
+to work with different culture-specific and language conventions.
+See
+.Xr nls 7 .
+.It Ev MAIL
+The name of a mail file, that will be checked for the arrival of new mail.
+Overridden by
+.Ev MAILPATH .
+.It Ev MAILCHECK
+The frequency in seconds that the shell checks for the arrival of mail
+in the files specified by the
+.Ev MAILPATH
+or the
+.Ev MAIL
+file.
+If set to 0, the check will occur at each prompt.
+.It Ev MAILPATH
+A colon
+.Dq \&:
+separated list of file names, for the shell to check for incoming mail.
+This environment setting overrides the
+.Ev MAIL
+setting.
+There is a maximum of 10 mailboxes that can be monitored at once.
+.It Ev PS1
+The primary prompt string, which defaults to
+.Dq $ \  ,
+unless you are the superuser, in which case it defaults to
+.Dq # \  .
+.It Ev PS2
+The secondary prompt string, which defaults to
+.Dq \*[Gt] \  .
+.It Ev PS4
+Output before each line when execution trace (set -x) is enabled,
+defaults to
+.Dq + \  .
+.It Ev IFS
+Input Field Separators.
+This is normally set to
+.Aq space ,
+.Aq tab ,
+and
+.Aq newline .
+See the
+.Sx White Space Splitting
+section for more details.
+.It Ev TERM
+The default terminal setting for the shell.
+This is inherited by
+children of the shell, and is used in the history editing modes.
+.It Ev HISTSIZE
+The number of lines in the history buffer for the shell.
+.El
+.Sh FILES
+.Bl -item -width HOMEprofilexxxx
+.It
+.Pa $HOME/.profile
+.It
+.Pa /etc/profile
+.El
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr echo 1 ,
+.Xr getopt 1 ,
+.Xr ksh 1 ,
+.Xr login 1 ,
+.Xr printf 1 ,
+.Xr test 1 ,
+.Xr editline 3 ,
+.Xr getopt 3 ,
+.\" .Xr profile 4 ,
+.Xr editrc 5 ,
+.Xr passwd 5 ,
+.Xr environ 7 ,
+.Xr nls 7 ,
+.Xr sysctl 8
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
+It was, however, unmaintainable so we wrote this one.
+.Sh BUGS
+Setuid shell scripts should be avoided at all costs, as they are a
+significant security risk.
+.Pp
+PS1, PS2, and PS4 should be subject to parameter expansion before
+being displayed.
+.Pp
+The characters generated by filename completion should probably be quoted
+to ensure that the filename is still valid after the input line has been
+processed.
Index: /tags/kBuild-0.1.4/src/kash/shell.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/shell.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/shell.h	(revision 1780)
@@ -0,0 +1,94 @@
+/*	$NetBSD: shell.h,v 1.17 2003/08/07 09:05:38 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)shell.h	8.2 (Berkeley) 5/4/95
+ */
+
+/*
+ * The follow should be set to reflect the type of system you have:
+ *	JOBS -> 1 if you have Berkeley job control, 0 otherwise.
+ *	SHORTNAMES -> 1 if your linker cannot handle long names.
+ *	define BSD if you are running 4.2 BSD or later.
+ *	define SYSV if you are running under System V.
+ *	define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
+ *	define DEBUG=2 to compile in and turn on debugging.
+ *	define DO_SHAREDVFORK to indicate that vfork(2) shares its address
+ *	       with its parent.
+ *
+ * When debugging is on, debugging info will be written to ./trace and
+ * a quit signal will generate a core dump.
+ */
+
+#ifndef ___shell_h
+#define ___shell_h
+
+#ifndef _MSC_VER
+# include <sys/param.h>
+#endif
+
+#define JOBS 1
+#ifndef BSD
+# define BSD 1
+#endif
+
+#ifndef DO_SHAREDVFORK
+# if __NetBSD_Version__ >= 104000000
+#  define DO_SHAREDVFORK
+# endif
+#endif
+
+typedef void *pointer;
+#ifndef NULL
+# define NULL (void *)0
+#endif
+#define STATIC	/* empty */
+#define MKINIT	/* empty */
+
+#ifdef HAVE_SYS_CDEFS_H
+# include <sys/cdefs.h>
+#endif
+
+extern char nullstr[1];		/* null string */
+
+
+#ifdef DEBUG
+# define TRACE(param)	trace param
+# define TRACEV(param)	tracev param
+#else
+# define TRACE(param)
+# define TRACEV(param)
+#endif
+
+#include "shtypes.h"
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/shfile.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/shfile.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/shfile.c	(revision 1780)
@@ -0,0 +1,299 @@
+/* $Id$ */
+/** @file
+ *
+ * File management.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "shfile.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if K_OS == K_OS_WINDOWS
+# include <limits.h>
+# ifndef PIPE_BUF
+#  define PIPE_BUF 512
+# endif
+#else
+# include <unistd.h>
+# include <fcntl.h>
+# include <dirent.h>
+#endif
+
+
+int shfile_open(shfdtab *pfdtab, const char *name, unsigned flags, mode_t mode)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+    return open(name, flags, mode);
+#else
+#endif
+}
+
+int shfile_pipe(shfdtab *pfdtab, int fds[2])
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return _pipe(fds, PIPE_BUF, O_BINARY);
+# else
+    return pipe(fds);
+# endif
+#else
+#endif
+}
+
+int shfile_dup(shfdtab *pfdtab, int fd)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+    return dup(fd);
+#else
+#endif
+}
+
+int shfile_close(shfdtab *pfdtab, unsigned fd)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+    return close(fd);
+#else
+#endif
+}
+
+long shfile_read(shfdtab *pfdtab, int fd, void *buf, size_t len)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return read(fd, buf, (unsigned)len);
+# else
+    return read(fd, buf, len);
+# endif
+#else
+#endif
+}
+
+long shfile_write(shfdtab *pfdtab, int fd, const void *buf, size_t len)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return write(fd, buf, (unsigned)len);
+# else
+    return write(fd, buf, len);
+# endif
+#else
+#endif
+}
+
+long shfile_lseek(shfdtab *pfdtab, int fd, long off, int whench)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+    return lseek(fd, off, whench);
+#else
+#endif
+}
+
+int shfile_fcntl(shfdtab *pfdtab, int fd, int cmd, int arg)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    return fcntl(fd, cmd, arg);
+# endif
+#else
+#endif
+}
+
+int shfile_stat(shfdtab *pfdtab, const char *path, struct stat *pst)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+    return stat(path, pst);
+#else
+#endif
+}
+
+int shfile_lstat(shfdtab *pfdtab, const char *link, struct stat *pst)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return stat(link, pst);
+# else
+    return lstat(link, pst);
+# endif
+#else
+#endif
+}
+
+int shfile_chdir(shfdtab *pfdtab, const char *path)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER //???
+    return chdir(path);
+# else
+    return chdir(path);
+# endif
+#else
+#endif
+}
+
+char *shfile_getcwd(shfdtab *pfdtab, char *buf, int len)
+{
+#ifdef SH_PURE_STUB_MODE
+    return NULL;
+#elif defined(SH_STUB_MODE)
+    return getcwd(buf, len);
+#else
+#endif
+}
+
+int shfile_access(shfdtab *pfdtab, const char *path, int type)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    type &= ~X_OK;
+    return access(path, type);
+# else
+    return access(path, type);
+# endif
+#else
+#endif
+}
+
+int shfile_isatty(shfdtab *pfdtab, int fd)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 0;
+#elif defined(SH_STUB_MODE)
+    return isatty(fd);
+#else
+#endif
+}
+
+
+int shfile_cloexec(shfdtab *pfdtab, int fd, int closeit)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    int rc = fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0)
+                              | (closeit ? FD_CLOEXEC : 0));
+    //fprintf(stderr, "shfile_cloexec(%d, %d) -> %d\n", fd, closeit, rc);
+    return rc;
+# endif
+#else
+#endif
+
+}
+
+
+int shfile_ioctl(shfdtab *pfdtab, int fd, unsigned long request, void *buf)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    int rc = ioctl(fd, request, buf);
+    //fprintf(stderr, "ioctl(%d, %#x, %p) -> %d\n", fd, request, buf, rc);
+    return rc;
+# endif
+#else
+#endif
+}
+
+
+mode_t shfile_get_umask(shfdtab *pfdtab)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 022;
+#elif defined(SH_STUB_MODE)
+    return 022;
+#else
+#endif
+}
+
+
+shdir *shfile_opendir(shfdtab *pfdtab, const char *dir)
+{
+#ifdef SH_PURE_STUB_MODE
+    return NULL;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return NULL;
+# else
+    return (shdir *)opendir(dir);
+# endif
+#else
+#endif
+}
+
+shdirent *shfile_readdir(struct shdir *pdir)
+{
+#ifdef SH_PURE_STUB_MODE
+    return NULL;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return NULL;
+# else
+    struct dirent *pde = readdir((DIR *)pdir);
+    return pde ? (shdirent *)&pde->d_name[0] : NULL;
+# endif
+#else
+#endif
+}
+
+void shfile_closedir(struct shdir *pdir)
+{
+#ifdef SH_PURE_STUB_MODE
+    return NULL;
+#elif defined(SH_STUB_MODE)
+# ifndef _MSC_VER
+    closedir((DIR *)pdir);
+# endif
+#else
+#endif
+}
Index: /tags/kBuild-0.1.4/src/kash/shfile.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/shfile.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/shfile.h	(revision 1780)
@@ -0,0 +1,168 @@
+/* $Id$ */
+/** @file
+ *
+ * File management.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___shfile_h
+#define ___shfile_h
+
+#include "shtypes.h"
+#include "shthread.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef _MSC_VER
+# define _PATH_DEVNULL  "nul"
+# define _PATH_DEFPATH  "."
+#else
+# if !defined(__sun__)
+#  include <paths.h>
+# endif
+# ifdef _PATH_DEVNULL
+#  define _PATH_DEVNULL "/dev/null"
+# endif
+# ifndef _PATH_DEFPATH
+#  define _PATH_DEFPATH "/bin:/usr/bin:/sbin:/usr/sbin"
+# endif
+#endif
+#ifndef _MSC_VER
+# include <sys/fcntl.h>
+# include <unistd.h>
+# ifndef O_BINARY
+#  define O_BINARY  0
+# endif
+# ifndef O_TEXT
+#  define O_TEXT    0
+# endif
+
+#else
+# include <io.h>
+# include <direct.h>
+
+# define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
+# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
+# define S_ISLNK(m) 0
+# define S_IRWXU    (_S_IREAD | _S_IWRITE | _S_IEXEC)
+# define S_IXUSR    _S_IEXEC
+# define S_IWUSR    _S_IWRITE
+# define S_IRUSR    _S_IREAD
+# define S_IRWXG    0000070
+# define S_IRGRP    0000040
+# define S_IWGRP    0000020
+# define S_IXGRP    0000010
+# define S_IRWXO    0000007
+# define S_IROTH    0000004
+# define S_IWOTH    0000002
+# define S_IXOTH    0000001
+# define S_ISUID    0004000
+# define S_ISGID    0002000
+# define ALLPERMS   0000777
+
+# define F_DUPFD    0
+# define F_GETFD    1
+# define F_SETFD    2
+# define F_GETFL    3
+# define F_SETFL    4
+# define FD_CLOEXEC 1
+
+# define F_OK       0
+# define X_OK       1
+# define W_OK       2
+# define R_OK       4
+
+# define O_NONBLOCK 0 /// @todo
+
+#endif
+
+
+/**
+ * One file.
+ */
+typedef struct shfile
+{
+    int                 fd;             /**< The shell file descriptor number. */
+    int                 flags;          /**< Open flags. */
+    intptr_t            native;         /**< The native file descriptor number. */
+} shfile;
+
+/**
+ * The file descriptor table for a shell.
+ */
+typedef struct shfdtab
+{
+    shmtx               mtx;            /**< Mutex protecting any operations on the table and it's handles. */
+    char               *cwd;            /**< The current directory for this shell instance. */
+    unsigned            size;           /**< The size of the table (number of entries). */
+    shfile             *tab;            /**< Pointer to the table. */
+} shfdtab;
+
+int shfile_open(shfdtab *, const char *, unsigned, mode_t);
+int shfile_pipe(shfdtab *, int [2]);
+int shfile_close(shfdtab *, unsigned);
+long shfile_read(shfdtab *, int, void *, size_t);
+long shfile_write(shfdtab *, int, const void *, size_t);
+long shfile_lseek(shfdtab *, int, long, int);
+int shfile_fcntl(shfdtab *, int fd, int cmd, int arg);
+int shfile_dup(shfdtab *, int fd);
+
+int shfile_stat(shfdtab *, const char *, struct stat *);
+int shfile_lstat(shfdtab *, const char *, struct stat *);
+int shfile_chdir(shfdtab *, const char *);
+char *shfile_getcwd(shfdtab *, char *, int);
+int shfile_access(shfdtab *, const char *, int);
+int shfile_isatty(shfdtab *, int);
+int shfile_cloexec(shfdtab *, int, int);
+int shfile_ioctl(shfdtab *, int, unsigned long, void *);
+#ifdef _MSC_VER
+# define TIOCGWINSZ         0x4201
+typedef struct sh_winsize
+{
+    unsigned ws_row;        /**< Rows, in characters. */
+    unsigned ws_col;        /**< Columns, in characters. */
+    unsigned ws_xpixel;     /**< Horizontal size, pixels. */
+    unsigned ws_ypixel;     /**< Vertical size, pixels. */
+} sh_winsize;
+#else
+typedef struct winsize sh_winsize;
+#endif
+mode_t shfile_get_umask(shfdtab *);
+
+
+typedef struct sh_dirent
+{
+    char name[260];
+} shdirent;
+
+typedef struct shdir
+{
+    shfdtab    *shfdtab;
+    void       *native;
+    shdirent    ent;
+} shdir;
+
+shdir *shfile_opendir(shfdtab *, const char *);
+shdirent *shfile_readdir(struct shdir *);
+void shfile_closedir(struct shdir *);
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/kash/shinstance.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/shinstance.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/shinstance.c	(revision 1780)
@@ -0,0 +1,473 @@
+/* $Id$ */
+/** @file
+ *
+ * The shell instance methods.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#ifndef _MSC_VER
+# include <unistd.h>
+# include <pwd.h>
+extern char **environ;
+#endif
+#include "shinstance.h"
+
+
+/**
+ * Creates a root shell instance.
+ *
+ * @param   inherit     The shell to inherit from. If NULL inherit from environment and such.
+ * @param   argc        The argument count.
+ * @param   argv        The argument vector.
+ *
+ * @returns pointer to root shell on success, NULL on failure.
+ */
+shinstance *sh_create_root_shell(shinstance *inherit, int argc, char **argv)
+{
+    shinstance *psh;
+
+    psh = calloc(sizeof(*psh), 1);
+    if (psh)
+    {
+        /* the special stuff. */
+#ifdef _MSC_VER
+        psh->pid = _getpid();
+#else
+        psh->pid = getpid();
+#endif
+
+        /* memalloc.c */
+        psh->stacknleft = MINSIZE;
+        psh->herefd = -1;
+        psh->stackp = &psh->stackbase;
+        psh->stacknxt = psh->stackbase.space;
+
+        /* input.c */
+        psh->plinno = 1;
+        psh->init_editline = 0;
+        psh->parsefile = &psh->basepf;
+
+        /* output.c */
+        psh->output.bufsize = OUTBUFSIZ;
+        psh->output.fd = 1;
+        psh->output.psh = psh;
+        psh->errout.bufsize = 100;
+        psh->errout.fd = 2;
+        psh->errout.psh = psh;
+        psh->memout.fd = MEM_OUT;
+        psh->memout.psh = psh;
+        psh->out1 = &psh->output;
+        psh->out2 = &psh->errout;
+
+        /* jobs.c */
+        psh->backgndpid = -1;
+#if JOBS
+        psh->curjob = -1;
+#endif
+        psh->ttyfd = -1;
+
+    }
+    return psh;
+}
+
+
+char *sh_getenv(shinstance *psh, const char *var)
+{
+#ifdef SH_PURE_STUB_MODE
+    return NULL;
+#elif defined(SH_STUB_MODE)
+    return getenv(var);
+#else
+#endif
+}
+
+char **sh_environ(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+    static char *s_null[2] = {0,0};
+    return &s_null[0];
+#elif defined(SH_STUB_MODE)
+    return environ;
+#else
+#endif
+}
+
+const char *sh_gethomedir(shinstance *psh, const char *user)
+{
+#ifdef SH_PURE_STUB_MODE
+    return NULL;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return NULL;
+# else
+    struct passwd *pwd = getpwnam(user);
+    return pwd ? pwd->pw_dir : NULL;
+# endif
+#else
+#endif
+}
+
+int sh_sigaction(shinstance *psh, int signo, const struct shsigaction *newp, struct shsigaction *oldp)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    struct sigaction old;
+    if (newp)
+        return -1;
+    if (sigaction(signo, NULL, &old))
+        return -1;
+    oldp->sh_flags = old.sa_flags;
+    oldp->sh_handler = old.sa_handler;
+    oldp->sh_mask = old.sa_mask;
+    return 0;
+# endif
+#else
+#endif
+}
+
+shsig_t sh_signal(shinstance *psh, int signo, shsig_t handler)
+{
+    return (shsig_t)-1;
+}
+
+int sh_siginterrupt(shinstance *psh, int signo, int interrupt)
+{
+    return -1;
+}
+
+void sh_sigemptyset(shsigset_t *setp)
+{
+    memset(setp, 0, sizeof(*setp));
+}
+
+int sh_sigprocmask(shinstance *psh, int operation, shsigset_t const *newp, shsigset_t *oldp)
+{
+    return -1;
+}
+
+void sh_abort(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+#elif defined(SH_STUB_MODE)
+    abort();
+#else
+#endif
+}
+
+void sh_raise_sigint(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+#elif defined(SH_STUB_MODE)
+    raise(SIGINT);
+#else
+#endif
+}
+
+int sh_kill(shinstance *psh, pid_t pid, int signo)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    //fprintf(stderr, "kill(%d, %d)\n", pid, signo);
+    return kill(pid, signo);
+# endif
+#else
+#endif
+}
+
+int sh_killpg(shinstance *psh, pid_t pgid, int signo)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    //fprintf(stderr, "killpg(%d, %d)\n", pgid, signo);
+    return killpg(pgid, signo);
+# endif
+#else
+#endif
+}
+
+clock_t sh_times(shinstance *psh, shtms *tmsp)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 0;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return 0;
+# else
+    return times(tmsp);
+# endif
+#else
+#endif
+}
+
+int sh_sysconf_clk_tck(void)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 1;
+#else
+# ifdef _MSC_VER
+    return CLK_TCK;
+# else
+    return sysconf(_SC_CLK_TCK);
+# endif
+#endif
+}
+
+pid_t sh_fork(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    return fork();
+# endif
+#else
+#endif
+}
+
+pid_t sh_waitpid(shinstance *psh, pid_t pid, int *statusp, int flags)
+{
+    *statusp = 0;
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    pid = waitpid(pid, statusp, flags);
+    //fprintf(stderr, "waitpid -> %d *statusp=%d (rc=%d) flags=%#x\n",  pid, *statusp, WEXITSTATUS(*statusp), flags);
+    return pid;
+# endif
+#else
+#endif
+}
+
+void sh__exit(shinstance *psh, int rc)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+    _exit(rc);
+#else
+#endif
+}
+
+int sh_execve(shinstance *psh, const char *exe, const char * const *argv, const char * const *envp)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    return execve(exe, (char **)argv, (char **)envp);
+# endif
+#else
+#endif
+}
+
+uid_t sh_getuid(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 0;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return 0;
+# else
+    return getuid();
+# endif
+#else
+#endif
+}
+
+uid_t sh_geteuid(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 0;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return 0;
+# else
+    return geteuid();
+# endif
+#else
+#endif
+}
+
+gid_t sh_getgid(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 0;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return 0;
+# else
+    return getgid();
+# endif
+#else
+#endif
+}
+
+gid_t sh_getegid(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 0;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return 0;
+# else
+    return getegid();
+# endif
+#else
+#endif
+}
+
+pid_t sh_getpid(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 0;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return _getpid();
+# else
+    return getpid();
+# endif
+#else
+#endif
+}
+
+pid_t sh_getpgrp(shinstance *psh)
+{
+#ifdef SH_PURE_STUB_MODE
+    return 0;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return _getpid();
+# else
+    return getpgrp();
+# endif
+#else
+#endif
+}
+
+pid_t sh_getpgid(shinstance *psh, pid_t pid)
+{
+#ifdef SH_PURE_STUB_MODE
+    return pid;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return pid;
+# else
+    return getpgid(pid);
+# endif
+#else
+#endif
+}
+
+int sh_setpgid(shinstance *psh, pid_t pid, pid_t pgid)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    int rc;
+    rc = setpgid(pid, pgid);
+    //fprintf(stderr, "setpgid(%d,%d) -> %d\n",  pid, pgid, rc);
+    return rc;
+# endif
+#else
+#endif
+}
+
+pid_t sh_tcgetpgrp(shinstance *psh, int fd)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    return tcgetpgrp(fd);
+# endif
+#else
+#endif
+}
+
+int sh_tcsetpgrp(shinstance *psh, int fd, pid_t pgrp)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    return tcsetpgrp(fd, pgrp);
+# endif
+#else
+#endif
+}
+
+int sh_getrlimit(shinstance *psh, int resid, shrlimit *limp)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    return getrlimit(resid, limp);
+# endif
+#else
+#endif
+}
+
+int sh_setrlimit(shinstance *psh, int resid, const shrlimit *limp)
+{
+#ifdef SH_PURE_STUB_MODE
+    return -1;
+#elif defined(SH_STUB_MODE)
+# ifdef _MSC_VER
+    return -1;
+# else
+    return setrlimit(resid, limp);
+# endif
+#else
+#endif
+}
+
Index: /tags/kBuild-0.1.4/src/kash/shinstance.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/shinstance.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/shinstance.h	(revision 1780)
@@ -0,0 +1,463 @@
+/* $Id$ */
+/** @file
+ *
+ * The shell instance and it's methods.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___shinstance_h
+#define ___shinstance_h
+
+#include <stdio.h> /* BUFSIZ */
+#include <signal.h> /* NSIG */
+#ifndef _MSC_VER
+# include <termios.h>
+# include <sys/ioctl.h>
+# include <sys/resource.h>
+#endif
+#include <errno.h>
+#ifdef _MSC_VER
+# define EWOULDBLOCK    512
+#endif
+
+#include "shtypes.h"
+#include "shthread.h"
+#include "shfile.h"
+#include "output.h"
+#include "options.h"
+
+#include "expand.h"
+#include "exec.h"
+#include "var.h"
+
+#ifdef _MSC_VER
+# define strcasecmp stricmp
+# define strncasecmp strnicmp
+#endif
+
+
+/* memalloc.c */
+#define MINSIZE 504		/* minimum size of a block */
+struct stack_block {
+	struct stack_block *prev;
+	char space[MINSIZE];
+};
+
+/* input.c */
+struct strpush {
+	struct strpush *prev;	/* preceding string on stack */
+	char *prevstring;
+	int prevnleft;
+	int prevlleft;
+	struct alias *ap;	/* if push was associated with an alias */
+};
+
+/*
+ * The parsefile structure pointed to by the global variable parsefile
+ * contains information about the current file being read.
+ */
+struct parsefile {
+	struct parsefile *prev;	/* preceding file on stack */
+	int linno;		/* current line */
+	int fd;			/* file descriptor (or -1 if string) */
+	int nleft;		/* number of chars left in this line */
+	int lleft;		/* number of chars left in this buffer */
+	char *nextc;		/* next char in buffer */
+	char *buf;		/* input buffer */
+	struct strpush *strpush; /* for pushing strings at this level */
+	struct strpush basestrpush; /* so pushing one is fast */
+};
+
+/* exec.c */
+#define CMDTABLESIZE 31		/* should be prime */
+#define ARB 1			/* actual size determined at run time */
+
+struct tblentry {
+	struct tblentry *next;	/* next entry in hash chain */
+	union param param;	/* definition of builtin function */
+	short cmdtype;		/* index identifying command */
+	char rehash;		/* if set, cd done since entry created */
+	char cmdname[ARB];	/* name of command */
+};
+
+/* expand.c */
+/*
+ * Structure specifying which parts of the string should be searched
+ * for IFS characters.
+ */
+struct ifsregion {
+	struct ifsregion *next;	/* next region in list */
+	int begoff;		/* offset of start of region */
+	int endoff;		/* offset of end of region */
+	int inquotes;		/* search for nul bytes only */
+};
+
+
+/**
+ * A shell instance.
+ *
+ * This is the core structure of the shell, it contains all
+ * the data associated with a shell process except that it's
+ * running in a thread and not a separate process.
+ */
+struct shinstance
+{
+    struct shinstance  *next;           /**< The next shell instance. */
+    struct shinstance  *prev;           /**< The previous shell instance. */
+    struct shinstance  *parent;         /**< The parent shell instance. */
+    pid_t               pid;            /**< The (fake) process id of this shell instance. */
+    shtid               tid;            /**< The thread identifier of the thread for this shell. */
+    shfdtab             fdtab;          /**< The file descriptor table. */
+
+    /* alias.c */
+#define ATABSIZE 39
+    struct alias       *atab[ATABSIZE];
+
+    /* cd.c */
+    char               *curdir;         /**< current working directory */
+    char               *prevdir;        /**< previous working directory */
+    char               *cdcomppath;
+    int                 getpwd_first;   /**< static in getpwd. (initialized to 1!) */
+
+    /* error.h */
+    struct jmploc      *handler;
+    int                 exception;
+    int                 exerrno/* = 0 */; /**< Last exec error */
+    int volatile        suppressint;
+    int volatile        intpending;
+
+    /* error.c */
+    char                errmsg_buf[16]; /**< static in errmsg. (bss) */
+
+    /* eval.h */
+    char               *commandname;    /**< currently executing command */
+    int                 exitstatus;     /**< exit status of last command */
+    int                 back_exitstatus;/**< exit status of backquoted command */
+    struct strlist     *cmdenviron;     /**< environment for builtin command */
+    int                 funcnest;       /**< depth of function calls */
+    int                 evalskip;       /**< set if we are skipping commands */
+    int                 skipcount;      /**< number of levels to skip */
+    int                 loopnest;       /**< current loop nesting level */
+
+    /* eval.c */
+    int                 vforked;
+
+    /* expand.c */
+    char               *expdest;        /**< output of current string */
+    struct nodelist    *argbackq;       /**< list of back quote expressions */
+    struct ifsregion    ifsfirst;       /**< first struct in list of ifs regions */
+    struct ifsregion   *ifslastp;       /**< last struct in list */
+    struct arglist      exparg;         /**< holds expanded arg list */
+    char               *expdir;         /**< Used by expandmeta. */
+
+    /* exec.h */
+    const char         *pathopt;        /**< set by padvance */
+
+    /* exec.c */
+    struct tblentry    *cmdtable[CMDTABLESIZE];
+    int                 builtinloc/* = -1*/;    /**< index in path of %builtin, or -1 */
+
+    /* input.h */
+    int                 plinno/* = 1 */;/**< input line number */
+    int                 parsenleft;     /**< number of characters left in input buffer */
+    char               *parsenextc;     /**< next character in input buffer */
+    int                 init_editline/* = 0 */;     /**< 0 == not setup, 1 == OK, -1 == failed */
+
+    /* input.c */
+    int                 parselleft;     /**< copy of parsefile->lleft */
+    struct parsefile    basepf;         /**< top level input file */
+    char                basebuf[BUFSIZ];/**< buffer for top level input file */
+    struct parsefile   *parsefile/* = &basepf*/;    /**< current input file */
+#ifndef SMALL
+    EditLine           *el;             /**< cookie for editline package */
+#endif
+
+    /* jobs.h */
+    pid_t               backgndpid/* = -1 */;   /**< pid of last background process */
+    int                 job_warning;    /**< user was warned about stopped jobs */
+
+    /* jobs.c */
+    struct job         *jobtab;         /**< array of jobs */
+    int                 njobs;          /**< size of array */
+    int                 jobs_invalid;   /**< set in child */
+    int                 initialpgrp;    /**< pgrp of shell on invocation */
+    int                 curjob/* = -1*/;/**< current job */
+    int                 ttyfd/* = -1*/;
+    int                 jobctl;         /**< job control enabled / disabled */
+    char               *cmdnextc;
+    int                 cmdnleft;
+
+
+    /* mail.c */
+#define MAXMBOXES 10
+    int                 nmboxes;        /**< number of mailboxes */
+    time_t              mailtime[MAXMBOXES]; /**< times of mailboxes */
+
+    /* main.h */
+    int                 rootpid;        /**< pid of main shell. */
+    int                 rootshell;      /**< true if we aren't a child of the main shell. */
+    struct shinstance  *psh_rootshell;  /**< The root shell pointer. (!rootshell) */
+
+    /* memalloc.h */
+    char               *stacknxt/* = stackbase.space*/;
+    int                 stacknleft/* = MINSIZE*/;
+    int                 sstrnleft;
+    int                 herefd/* = -1 */;
+
+    /* memalloc.c */
+    struct stack_block  stackbase;
+    struct stack_block *stackp/* = &stackbase*/;
+    struct stackmark   *markp;
+
+    /* myhistedit.h */
+    int                 displayhist;
+#ifndef SMALL
+    History            *hist;
+    EditLine           *el;
+#endif
+
+    /* output.h */
+    struct output       output;
+    struct output       errout;
+    struct output       memout;
+    struct output      *out1;
+    struct output      *out2;
+
+    /* output.c */
+#define OUTBUFSIZ BUFSIZ
+#define MEM_OUT -3                      /**< output to dynamically allocated memory */
+
+    /* options.h */
+    struct optent       optlist[NOPTS];
+    char               *minusc;         /**< argument to -c option */
+    char               *arg0;           /**< $0 */
+    struct shparam      shellparam;     /**< $@ */
+    char              **argptr;         /**< argument list for builtin commands */
+    char               *optionarg;      /**< set by nextopt */
+    char               *optptr;         /**< used by nextopt */
+
+    /* parse.h */
+    int                 tokpushback;
+    int                 whichprompt;    /**< 1 == PS1, 2 == PS2 */
+
+    /* parser.c */
+    int                 noalias/* = 0*/;/**< when set, don't handle aliases */
+    struct heredoc     *heredoclist;    /**< list of here documents to read */
+    int                 parsebackquote; /**< nonzero if we are inside backquotes */
+    int                 doprompt;       /**< if set, prompt the user */
+    int                 needprompt;     /**< true if interactive and at start of line */
+    int                 lasttoken;      /**< last token read */
+    char               *wordtext;       /**< text of last word returned by readtoken */
+    int                 checkkwd;       /**< 1 == check for kwds, 2 == also eat newlines */
+    struct nodelist    *backquotelist;
+    union node         *redirnode;
+    struct heredoc     *heredoc;
+    int                 quoteflag;      /**< set if (part of) last token was quoted */
+    int                 startlinno;     /**< line # where last token started */
+
+    /* redir.c */
+    struct redirtab    *redirlist;
+    int                 fd0_redirected/* = 0*/;
+
+    /* trap.h */
+    int                 pendingsigs;    /**< indicates some signal received */
+
+    /* trap.c */
+    char                gotsig[NSIG];   /**< indicates specified signal received */
+    char               *trap[NSIG+1];   /**< trap handler commands */
+    char                sigmode[NSIG];  /**< current value of signal */
+
+    /* var.h */
+    struct localvar    *localvars;
+    struct var          vatty;
+    struct var          vifs;
+    struct var          vmail;
+    struct var          vmpath;
+    struct var          vpath;
+#ifdef _MSC_VER
+    struct var          vpath2;
+#endif
+    struct var          vps1;
+    struct var          vps2;
+    struct var          vps4;
+#ifndef SMALL
+    struct var          vterm;
+    struct var          vhistsize;
+#endif
+    struct var          voptind;
+#ifdef PC_OS2_LIBPATHS
+    struct var          libpath_vars[4];
+#endif
+#ifdef SMALL
+# define VTABSIZE 39
+#else
+# define VTABSIZE 517
+#endif
+    struct var         *vartab[VTABSIZE];
+
+    /* builtins.h */
+
+    /* bltin/test.c */
+    char              **t_wp;
+    struct t_op const  *t_wp_op;
+
+};
+
+
+extern shinstance *sh_create_root_shell(shinstance *, int, char **);
+
+/* environment & pwd.h */
+char *sh_getenv(shinstance *, const char *);
+char **sh_environ(shinstance *);
+const char *sh_gethomedir(shinstance *, const char *);
+
+/* signals */
+typedef void (*shsig_t)(shinstance *, int);
+#ifdef _MSC_VER
+    typedef uint32_t shsigset_t;
+#else
+    typedef sigset_t shsigset_t;
+#endif
+struct shsigaction
+{
+    shsig_t     sh_handler;
+    shsigset_t  sh_mask;
+    int         sh_flags;
+};
+#define SH_SIG_DFL ((shsig_t)SIG_DFL)
+#define SH_SIG_IGN ((shsig_t)SIG_IGN)
+#ifdef _MSC_VER
+#   define SIG_BLOCK         1
+#   define SIG_UNBLOCK       2
+#   define SIG_SETMASK       3
+#   define SIGHUP            5
+#   define SIGQUIT           9
+#   define SIGPIPE          12
+#   define SIGTTOU          17
+#   define SIGTSTP          18
+#   define SIGTTIN          19
+#   define SIGCONT          20
+#   define sys_siglist      sys_signame
+#endif /* _MSC_VER */
+#ifdef __sun__
+#   define sys_siglist      _sys_siglist
+#endif
+#ifndef HAVE_SYS_SIGNAME
+extern char sys_signame[NSIG][16];
+#endif
+
+int sh_sigaction(shinstance *, int, const struct shsigaction *, struct shsigaction *);
+shsig_t sh_signal(shinstance *, int, shsig_t);
+int sh_siginterrupt(shinstance *, int, int);
+void sh_sigemptyset(shsigset_t *);
+int sh_sigprocmask(shinstance *, int, shsigset_t const *, shsigset_t *);
+void sh_abort(shinstance *) __attribute__((__noreturn__));
+void sh_raise_sigint(shinstance *);
+int sh_kill(shinstance *, pid_t, int);
+int sh_killpg(shinstance *, pid_t, int);
+
+/* times */
+#include <time.h>
+#ifdef _MSC_VER
+    typedef struct shtms
+    {
+        clock_t tms_utime;
+        clock_t tms_stime;
+        clock_t tms_cutime;
+        clock_t tms_cstime;
+    } shtms;
+#else
+#   include <sys/times.h>
+    typedef struct tms shtms;
+#endif
+clock_t sh_times(shinstance *, shtms *);
+int sh_sysconf_clk_tck(void);
+
+/* wait / process */
+#ifdef _MSC_VER
+#   include <process.h>
+#   define WNOHANG         1       /* Don't hang in wait. */
+#   define WUNTRACED       2       /* Tell about stopped, untraced children. */
+#   define WCONTINUED      4       /* Report a job control continued process. */
+#   define _W_INT(w)       (*(int *)&(w))  /* Convert union wait to int. */
+#   define WCOREFLAG       0200
+#   define _WSTATUS(x)     (_W_INT(x) & 0177)
+#   define _WSTOPPED       0177            /* _WSTATUS if process is stopped */
+#   define WIFSTOPPED(x)   (_WSTATUS(x) == _WSTOPPED)
+#   define WSTOPSIG(x)     (_W_INT(x) >> 8)
+#   define WIFSIGNALED(x)  (_WSTATUS(x) != 0 && !WIFSTOPPED(x) && !WIFCONTINUED(x)) /* bird: made GLIBC tests happy. */
+#   define WTERMSIG(x)     (_WSTATUS(x))
+#   define WIFEXITED(x)    (_WSTATUS(x) == 0)
+#   define WEXITSTATUS(x)  (_W_INT(x) >> 8)
+#   define WIFCONTINUED(x) (x == 0x13)     /* 0x13 == SIGCONT */
+#   define WCOREDUMP(x)    (_W_INT(x) & WCOREFLAG)
+#   define W_EXITCODE(ret, sig)    ((ret) << 8 | (sig))
+#   define W_STOPCODE(sig)         ((sig) << 8 | _WSTOPPED)
+#else
+#   include <sys/wait.h>
+#endif
+pid_t sh_fork(shinstance *);
+pid_t sh_waitpid(shinstance *, pid_t, int *, int);
+void sh__exit(shinstance *, int) __attribute__((__noreturn__));;
+int sh_execve(shinstance *, const char *, const char * const*, const char * const *);
+uid_t sh_getuid(shinstance *);
+uid_t sh_geteuid(shinstance *);
+gid_t sh_getgid(shinstance *);
+gid_t sh_getegid(shinstance *);
+pid_t sh_getpid(shinstance *);
+pid_t sh_getpgrp(shinstance *);
+pid_t sh_getpgid(shinstance *, pid_t);
+int sh_setpgid(shinstance *, pid_t, pid_t);
+
+/* tc* */
+pid_t sh_tcgetpgrp(shinstance *, int);
+int sh_tcsetpgrp(shinstance *, int, pid_t);
+
+/* sys/resource.h */
+#ifdef _MSC_VER
+    typedef int64_t shrlim_t;
+    typedef struct shrlimit
+    {
+        shrlim_t   rlim_cur;
+        shrlim_t   rlim_max;
+    } shrlimit;
+#   define RLIMIT_CPU     0
+#   define RLIMIT_FSIZE   1
+#   define RLIMIT_DATA    2
+#   define RLIMIT_STACK   3
+#   define RLIMIT_CORE    4
+#   define RLIMIT_RSS     5
+#   define RLIMIT_MEMLOCK 6
+#   define RLIMIT_NPROC   7
+#   define RLIMIT_NOFILE  8
+#   define RLIMIT_SBSIZE  9
+#   define RLIMIT_VMEM    10
+#   define RLIM_NLIMITS   11
+#   define RLIM_INFINITY  (0x7fffffffffffffffLL)
+#else
+    typedef rlim_t          shrlim_t;
+    typedef struct rlimit   shrlimit;
+#endif
+int sh_getrlimit(shinstance *, int, shrlimit *);
+int sh_setrlimit(shinstance *, int, const shrlimit *);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/show.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/show.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/show.c	(revision 1780)
@@ -0,0 +1,427 @@
+/*	$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "parser.h"
+#include "nodes.h"
+#include "mystring.h"
+#include "show.h"
+#include "options.h"
+#include "shinstance.h"
+
+
+#ifdef DEBUG
+static void shtree(union node *, int, char *, FILE*);
+static void shcmd(union node *, FILE *);
+static void sharg(union node *, FILE *);
+static void indent(int, char *, FILE *);
+static void trstring(shinstance *, char *);
+
+
+void
+showtree(shinstance *psh, union node *n)
+{
+	trputs(psh, "showtree called\n");
+	shtree(n, 1, NULL, stdout);
+}
+
+
+static void
+shtree(union node *n, int ind, char *pfx, FILE *fp)
+{
+	struct nodelist *lp;
+	const char *s;
+
+	if (n == NULL)
+		return;
+
+	indent(ind, pfx, fp);
+	switch(n->type) {
+	case NSEMI:
+		s = "; ";
+		goto binop;
+	case NAND:
+		s = " && ";
+		goto binop;
+	case NOR:
+		s = " || ";
+binop:
+		shtree(n->nbinary.ch1, ind, NULL, fp);
+	   /*    if (ind < 0) */
+			fputs(s, fp);
+		shtree(n->nbinary.ch2, ind, NULL, fp);
+		break;
+	case NCMD:
+		shcmd(n, fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	case NPIPE:
+		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+			shcmd(lp->n, fp);
+			if (lp->next)
+				fputs(" | ", fp);
+		}
+		if (n->npipe.backgnd)
+			fputs(" &", fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	default:
+		fprintf(fp, "<node type %d>", n->type);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	}
+}
+
+
+
+static void
+shcmd(union node *cmd, FILE *fp)
+{
+	union node *np;
+	int first;
+	const char *s;
+	int dftfd;
+
+	first = 1;
+	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
+		if (! first)
+			putchar(' ');
+		sharg(np, fp);
+		first = 0;
+	}
+	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
+		if (! first)
+			putchar(' ');
+		switch (np->nfile.type) {
+			case NTO:	s = ">";  dftfd = 1; break;
+			case NCLOBBER:	s = ">|"; dftfd = 1; break;
+			case NAPPEND:	s = ">>"; dftfd = 1; break;
+			case NTOFD:	s = ">&"; dftfd = 1; break;
+			case NFROM:	s = "<";  dftfd = 0; break;
+			case NFROMFD:	s = "<&"; dftfd = 0; break;
+			case NFROMTO:	s = "<>"; dftfd = 0; break;
+			default:  	s = "*error*"; dftfd = 0; break;
+		}
+		if (np->nfile.fd != dftfd)
+			fprintf(fp, "%d", np->nfile.fd);
+		fputs(s, fp);
+		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
+			fprintf(fp, "%d", np->ndup.dupfd);
+		} else {
+			sharg(np->nfile.fname, fp);
+		}
+		first = 0;
+	}
+}
+
+
+
+static void
+sharg(union node *arg, FILE *fp)
+{
+	char *p;
+	struct nodelist *bqlist;
+	int subtype;
+
+	if (arg->type != NARG) {
+		printf("<node type %d>\n", arg->type);
+		abort();
+	}
+	bqlist = arg->narg.backquote;
+	for (p = arg->narg.text ; *p ; p++) {
+		switch (*p) {
+		case CTLESC:
+			putc(*++p, fp);
+			break;
+		case CTLVAR:
+			putc('$', fp);
+			putc('{', fp);
+			subtype = *++p;
+			if (subtype == VSLENGTH)
+				putc('#', fp);
+
+			while (*p != '=')
+				putc(*p++, fp);
+
+			if (subtype & VSNUL)
+				putc(':', fp);
+
+			switch (subtype & VSTYPE) {
+			case VSNORMAL:
+				putc('}', fp);
+				break;
+			case VSMINUS:
+				putc('-', fp);
+				break;
+			case VSPLUS:
+				putc('+', fp);
+				break;
+			case VSQUESTION:
+				putc('?', fp);
+				break;
+			case VSASSIGN:
+				putc('=', fp);
+				break;
+			case VSTRIMLEFT:
+				putc('#', fp);
+				break;
+			case VSTRIMLEFTMAX:
+				putc('#', fp);
+				putc('#', fp);
+				break;
+			case VSTRIMRIGHT:
+				putc('%', fp);
+				break;
+			case VSTRIMRIGHTMAX:
+				putc('%', fp);
+				putc('%', fp);
+				break;
+			case VSLENGTH:
+				break;
+			default:
+				printf("<subtype %d>", subtype);
+			}
+			break;
+		case CTLENDVAR:
+		     putc('}', fp);
+		     break;
+		case CTLBACKQ:
+		case CTLBACKQ|CTLQUOTE:
+			putc('$', fp);
+			putc('(', fp);
+			shtree(bqlist->n, -1, NULL, fp);
+			putc(')', fp);
+			break;
+		default:
+			putc(*p, fp);
+			break;
+		}
+	}
+}
+
+
+static void
+indent(int amount, char *pfx, FILE *fp)
+{
+	int i;
+
+	for (i = 0 ; i < amount ; i++) {
+		if (pfx && i == amount - 1)
+			fputs(pfx, fp);
+		putc('\t', fp);
+	}
+}
+#endif
+
+
+
+/*
+ * Debugging stuff.
+ */
+
+
+FILE *tracefile;
+
+
+#ifdef DEBUG
+void
+trputc(shinstance *psh, int c)
+{
+	if (debug(psh) != 1)
+		return;
+	putc(c, tracefile);
+}
+#endif
+
+void
+trace(shinstance *psh, const char *fmt, ...)
+{
+#ifdef DEBUG
+	va_list va;
+
+	if (debug(psh) != 1)
+		return;
+        fprintf(tracefile, "[%d] ", sh_getpid(psh));
+	va_start(va, fmt);
+	(void) vfprintf(tracefile, fmt, va);
+	va_end(va);
+#endif
+}
+
+void
+tracev(shinstance *psh, const char *fmt, va_list va)
+{
+#ifdef DEBUG
+	if (debug(psh) != 1)
+		return;
+        fprintf(tracefile, "[%d] ", sh_getpid(psh));
+	(void) vfprintf(tracefile, fmt, va);
+#endif
+}
+
+
+#ifdef DEBUG
+void
+trputs(shinstance *psh, const char *s)
+{
+	if (debug(psh) != 1)
+		return;
+	fputs(s, tracefile);
+}
+
+
+static void
+trstring(shinstance *psh, char *s)
+{
+	char *p;
+	char c;
+
+	if (debug(psh) != 1)
+		return;
+	putc('"', tracefile);
+	for (p = s ; *p ; p++) {
+		switch (*p) {
+		case '\n':  c = 'n';  goto backslash;
+		case '\t':  c = 't';  goto backslash;
+		case '\r':  c = 'r';  goto backslash;
+		case '"':  c = '"';  goto backslash;
+		case '\\':  c = '\\';  goto backslash;
+		case CTLESC:  c = 'e';  goto backslash;
+		case CTLVAR:  c = 'v';  goto backslash;
+		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
+		case CTLBACKQ:  c = 'q';  goto backslash;
+		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
+backslash:	  putc('\\', tracefile);
+			putc(c, tracefile);
+			break;
+		default:
+			if (*p >= ' ' && *p <= '~')
+				putc(*p, tracefile);
+			else {
+				putc('\\', tracefile);
+				putc(*p >> 6 & 03, tracefile);
+				putc(*p >> 3 & 07, tracefile);
+				putc(*p & 07, tracefile);
+			}
+			break;
+		}
+	}
+	putc('"', tracefile);
+}
+#endif
+
+
+void
+trargs(shinstance *psh, char **ap)
+{
+#ifdef DEBUG
+	if (debug(psh) != 1)
+		return;
+	while (*ap) {
+		trstring(psh, *ap++);
+		if (*ap)
+			putc(' ', tracefile);
+		else
+			putc('\n', tracefile);
+	}
+#endif
+}
+
+
+#ifdef DEBUG
+void
+opentrace(shinstance *psh)
+{
+	char s[100];
+#if defined(O_APPEND) && !defined(_MSC_VER)
+	int flags;
+#endif
+
+	if (debug(psh) != 1) {
+		if (tracefile)
+			fflush(tracefile);
+		/* leave open because libedit might be using it */
+		return;
+	}
+#ifdef not_this_way
+	{
+		char *p;
+		if ((p = getenv("HOME")) == NULL) {
+			if (sh_geteuid(psh) == 0)
+				p = "/";
+			else
+				p = "/tmp";
+		}
+		scopy(p, s);
+		strcat(s, "/trace");
+	}
+#else
+	scopy("./trace", s);
+#endif /* not_this_way */
+	if (tracefile) {
+		if (!freopen(s, "a", tracefile)) {
+			fprintf(stderr, "Can't re-open %s\n", s);
+			debug(psh) = 0;
+			return;
+		}
+	} else {
+		if ((tracefile = fopen(s, "a")) == NULL) {
+			fprintf(stderr, "Can't open %s\n", s);
+			debug(psh) = 0;
+			return;
+		}
+	}
+#if defined(O_APPEND) && !defined(_MSC_VER)
+	if ((flags = shfile_fcntl(&psh->fdtab, fileno(tracefile), F_GETFL, 0)) >= 0)
+		shfile_fcntl(&psh->fdtab, fileno(tracefile), F_SETFL, flags | O_APPEND);
+#endif
+	setvbuf(tracefile, (char *)NULL, _IOLBF, 0); //setlinebuf(tracefile);
+	fputs("\nTracing started.\n", tracefile);
+}
+#endif /* DEBUG */
Index: /tags/kBuild-0.1.4/src/kash/show.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/show.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/show.h	(revision 1780)
@@ -0,0 +1,50 @@
+/*	$NetBSD: show.h,v 1.7 2003/08/07 09:05:38 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1995
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)show.h	1.1 (Berkeley) 5/4/95
+ */
+
+#ifndef ___show_h
+#define ___show_h
+
+#include <stdarg.h>
+
+union node;
+void showtree(struct shinstance *, union node *);
+void trace(struct shinstance *, const char *, ...);
+void tracev(struct shinstance *, const char *, va_list);
+void trargs(struct shinstance *, char **);
+#ifdef DEBUG
+void trputc(struct shinstance *, int);
+void trputs(struct shinstance *, const char *);
+void opentrace(struct shinstance *);
+#endif
+
+#endif
Index: /tags/kBuild-0.1.4/src/kash/shthread.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/shthread.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/shthread.c	(revision 1780)
@@ -0,0 +1,48 @@
+/* $Id$ */
+/** @file
+ *
+ * Shell Thread Management.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "shthread.h"
+#include "shinstance.h"
+
+#if defined(_MSC_VER) || defined(__EMX__)
+# include <process.h>
+#else
+# include <pthread.h>
+#endif 
+
+
+void shthread_set_shell(struct shinstance *psh)
+{
+
+}
+
+struct shinstance *shthread_get_shell(void)
+{
+    shinstance *psh = NULL;
+    return psh;
+}
+
+
Index: /tags/kBuild-0.1.4/src/kash/shthread.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/shthread.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/shthread.h	(revision 1780)
@@ -0,0 +1,43 @@
+/* $Id$ */
+/** @file
+ *
+ * Shell thread methods.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___shthread_h___
+#define ___shthread_h___
+
+#include "shtypes.h"
+
+typedef struct shmtx
+{
+    char b[64];
+} shmtx;
+
+typedef uintptr_t shtid;
+
+void shthread_set_shell(struct shinstance *);
+struct shinstance *shthread_get_shell(void);
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/kash/shtypes.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/shtypes.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/shtypes.h	(revision 1780)
@@ -0,0 +1,99 @@
+/* $Id$ */
+/** @file
+ *
+ * Wrapper for missing types and such.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___shtypes_h___
+#define ___shtypes_h___
+
+#include "k/kTypes.h" /* Use these, not the ones below. */
+
+#include <sys/types.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+# include <io.h> /* intptr_t and uintptr_t */
+typedef signed char     int8_t;
+typedef unsigned char   uint8_t;
+typedef short           int16_t;
+typedef unsigned short  uint16_t;
+typedef int             int32_t;
+typedef unsigned int    uint32_t;
+typedef _int64          int64_t;
+typedef unsigned _int64 uint64_t;
+
+#define INT16_C(c)      (c)
+#define INT32_C(c)      (c)
+#define INT64_C(c)      (c ## LL)
+
+#define UINT8_C(c)      (c)
+#define UINT16_C(c)     (c)
+#define UINT32_C(c)     (c ## U)
+#define UINT64_C(c)     (c ## ULL)
+
+#define INTMAX_C(c)     (c ## LL)
+#define UINTMAX_C(c)    (c ## ULL)
+
+#undef  INT8_MIN
+#define INT8_MIN        (-0x7f-1)
+#undef  INT16_MIN
+#define INT16_MIN       (-0x7fff-1)
+#undef  INT32_MIN
+#define INT32_MIN       (-0x7fffffff-1)
+#undef  INT64_MIN
+#define INT64_MIN       (-0x7fffffffffffffffLL-1)
+
+#undef  INT8_MAX
+#define INT8_MAX        0x7f
+#undef  INT16_MAX
+#define INT16_MAX       0x7fff
+#undef  INT32_MAX
+#define INT32_MAX       0x7fffffff
+#undef  INT64_MAX
+#define INT64_MAX       0x7fffffffffffffffLL
+
+#undef  UINT8_MAX
+#define UINT8_MAX       0xff
+#undef  UINT16_MAX
+#define UINT16_MAX      0xffff
+#undef  UINT32_MAX
+#define UINT32_MAX      0xffffffffU
+#undef  UINT64_MAX
+#define UINT64_MAX      0xffffffffffffffffULL
+
+typedef int             pid_t;
+typedef unsigned short  uid_t;
+typedef unsigned short  gid_t;
+typedef int             mode_t;
+typedef intptr_t        ssize_t;
+
+#else
+# include <stdint.h>
+#endif
+
+struct shinstance;
+typedef struct shinstance shinstance;
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/kash/strlcpy.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/strlcpy.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/strlcpy.c	(revision 1780)
@@ -0,0 +1,72 @@
+/*	$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $");
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.7 2003/05/01 19:03:14 nectar Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t strlcpy(dst, src, siz)
+	char *dst;
+	const char *src;
+	size_t siz;
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
Index: /tags/kBuild-0.1.4/src/kash/syntax.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/syntax.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/syntax.c	(revision 1780)
@@ -0,0 +1,202 @@
+/*	$NetBSD: syntax.c,v 1.1 2004/01/17 17:38:12 dsl Exp $	*/
+
+#include "shell.h"
+#include "syntax.h"
+#include "parser.h"
+#include "shinstance.h"
+
+#ifdef _MSC_VER /* doesn't implement the fancy initializers I think... */
+
+char basesyntax[257] = {CSHEOF};
+char dqsyntax[257] = {CSHEOF};
+char sqsyntax[257] = {CSHEOF};
+char arisyntax[257] = {CSHEOF};
+char is_type[257] = {0};
+
+void init_syntax(void)
+{
+    char *tab;
+    int i;
+
+#define ndx(ch) (ch + 1 - CHAR_MIN)
+#define set(ch, val) tab[ndx(ch)] = val
+#define set_range(s, e, val) for (i = ndx(s); i <= ndx(e); i++) tab[i] = val
+
+    /*basesyntax*/
+    tab = basesyntax;
+    set_range(CTL_FIRST, CTL_LAST, CCTL);
+    set('\n', CNL);
+    set('\\', CBACK);
+    set('\'', CSQUOTE);
+    set('"', CDQUOTE);
+    set('`', CBQUOTE);
+    set('$', CVAR);
+    set('}', CENDVAR);
+    set('<', CSPCL);
+    set('>', CSPCL);
+    set('(', CSPCL);
+    set(')', CSPCL);
+    set(';', CSPCL);
+    set('&', CSPCL);
+    set('|', CSPCL);
+    set(' ', CSPCL);
+    set('\t', CSPCL);
+
+    tab = dqsyntax;
+    set_range(CTL_FIRST, CTL_LAST, CCTL);
+    set('\n', CNL);
+    set('\\', CBACK);
+    set('"', CDQUOTE);
+    set('`', CBQUOTE);
+    set('$', CVAR);
+    set('}', CENDVAR);
+    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+    set('!', CCTL);
+    set('*', CCTL);
+    set('?', CCTL);
+    set('[', CCTL);
+    set('=', CCTL);
+    set('~', CCTL);
+    set(':', CCTL);
+    set('/', CCTL);
+    set('-', CCTL);
+
+    tab = sqsyntax;
+    set_range(CTL_FIRST, CTL_LAST, CCTL);
+    set('\n', CNL);
+    set('\'', CSQUOTE);
+    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+    set('!', CCTL);
+    set('*', CCTL) ;
+    set('?', CCTL);
+    set('[', CCTL);
+    set('=', CCTL);
+    set('~', CCTL);
+    set(':', CCTL);
+    set('/', CCTL);
+    set('-', CCTL);
+
+    tab = arisyntax;
+    set_range(CTL_FIRST, CTL_LAST, CCTL);
+    set('\n', CNL);
+    set('\\', CBACK);
+    set('`', CBQUOTE);
+    set('\'', CSQUOTE);
+    set('"', CDQUOTE);
+    set('$', CVAR);
+    set('}', CENDVAR);
+    set('(', CLP);
+    set(')', CRP);
+
+    tab = is_type;
+    set_range('0', '9', ISDIGIT);
+    set_range('a', 'z', ISLOWER);
+    set_range('A', 'Z', ISUPPER);
+    set('_', ISUNDER);
+    set('#', ISSPECL);
+    set('?', ISSPECL);
+    set('$', ISSPECL);
+    set('!', ISSPECL);
+    set('-', ISSPECL);
+    set('*', ISSPECL);
+    set('@', ISSPECL);
+}
+
+#else /* !_MSC_VER */
+
+#if CWORD != 0
+#error initialisation assumes 'CWORD' is zero
+#endif
+
+#define ndx(ch) (ch + 1 - CHAR_MIN)
+#define set(ch, val) [ndx(ch)] = val,
+#define set_range(s, e, val) [ndx(s) ... ndx(e)] = val,
+
+/* syntax table used when not in quotes */
+const char basesyntax[257] = { CSHEOF,
+    set_range(CTL_FIRST, CTL_LAST, CCTL)
+    set('\n', CNL)
+    set('\\', CBACK)
+    set('\'', CSQUOTE)
+    set('"', CDQUOTE)
+    set('`', CBQUOTE)
+    set('$', CVAR)
+    set('}', CENDVAR)
+    set('<', CSPCL)
+    set('>', CSPCL)
+    set('(', CSPCL)
+    set(')', CSPCL)
+    set(';', CSPCL)
+    set('&', CSPCL)
+    set('|', CSPCL)
+    set(' ', CSPCL)
+    set('\t', CSPCL)
+};
+
+/* syntax table used when in double quotes */
+const char dqsyntax[257] = { CSHEOF,
+    set_range(CTL_FIRST, CTL_LAST, CCTL)
+    set('\n', CNL)
+    set('\\', CBACK)
+    set('"', CDQUOTE)
+    set('`', CBQUOTE)
+    set('$', CVAR)
+    set('}', CENDVAR)
+    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+    set('!', CCTL)
+    set('*', CCTL)
+    set('?', CCTL)
+    set('[', CCTL)
+    set('=', CCTL)
+    set('~', CCTL)
+    set(':', CCTL)
+    set('/', CCTL)
+    set('-', CCTL)
+};
+
+/* syntax table used when in single quotes */
+const char sqsyntax[257] = { CSHEOF,
+    set_range(CTL_FIRST, CTL_LAST, CCTL)
+    set('\n', CNL)
+    set('\'', CSQUOTE)
+    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+    set('!', CCTL)
+    set('*', CCTL)
+    set('?', CCTL)
+    set('[', CCTL)
+    set('=', CCTL)
+    set('~', CCTL)
+    set(':', CCTL)
+    set('/', CCTL)
+    set('-', CCTL)
+};
+
+/* syntax table used when in arithmetic */
+const char arisyntax[257] = { CSHEOF,
+    set_range(CTL_FIRST, CTL_LAST, CCTL)
+    set('\n', CNL)
+    set('\\', CBACK)
+    set('`', CBQUOTE)
+    set('\'', CSQUOTE)
+    set('"', CDQUOTE)
+    set('$', CVAR)
+    set('}', CENDVAR)
+    set('(', CLP)
+    set(')', CRP)
+};
+
+/* character classification table */
+const char is_type[257] = { 0,
+    set_range('0', '9', ISDIGIT)
+    set_range('a', 'z', ISLOWER)
+    set_range('A', 'Z', ISUPPER)
+    set('_', ISUNDER)
+    set('#', ISSPECL)
+    set('?', ISSPECL)
+    set('$', ISSPECL)
+    set('!', ISSPECL)
+    set('-', ISSPECL)
+    set('*', ISSPECL)
+    set('@', ISSPECL)
+};
+#endif /* !_MSC_VER */
Index: /tags/kBuild-0.1.4/src/kash/syntax.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/syntax.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/syntax.h	(revision 1780)
@@ -0,0 +1,90 @@
+/*	$NetBSD: syntax.h,v 1.2 2004/01/17 17:38:12 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+
+/* Syntax classes */
+#define CWORD 0			/* character is nothing special */
+#define CNL 1			/* newline character */
+#define CBACK 2			/* a backslash character */
+#define CSQUOTE 3		/* single quote */
+#define CDQUOTE 4		/* double quote */
+#define CBQUOTE 5		/* backwards single quote */
+#define CVAR 6			/* a dollar sign */
+#define CENDVAR 7		/* a '}' character */
+#define CLP 8			/* a left paren in arithmetic */
+#define CRP 9			/* a right paren in arithmetic */
+#define CSHEOF 10		/* end of file */
+#define CCTL 11			/* like CWORD, except it must be escaped */
+#define CSPCL 12		/* these terminate a word */
+
+/* Syntax classes for is_ functions */
+#define ISDIGIT 01		/* a digit */
+#define ISUPPER 02		/* an upper case letter */
+#define ISLOWER 04		/* a lower case letter */
+#define ISUNDER 010		/* an underscore */
+#define ISSPECL 020		/* the name of a special parameter */
+
+#define PEOF (CHAR_MIN - 1)
+#define SYNBASE (-PEOF)
+/* XXX UPEOF is CHAR_MAX, so is a valid 'char' value... */
+#define UPEOF ((char)PEOF)
+
+
+#define BASESYNTAX (basesyntax + SYNBASE)
+#define DQSYNTAX (dqsyntax + SYNBASE)
+#define SQSYNTAX (sqsyntax + SYNBASE)
+#define ARISYNTAX (arisyntax + SYNBASE)
+
+/* These defines assume that the digits are contiguous */
+#define is_digit(c)	((unsigned)((c) - '0') <= 9)
+#define is_alpha(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char)(c)))
+#define is_name(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char)(c))))
+#define is_in_name(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char)(c))))
+#define is_special(c)	((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
+#define digit_val(c)	((c) - '0')
+
+#ifdef _MSC_VER
+extern char basesyntax[];
+extern char dqsyntax[];
+extern char sqsyntax[];
+extern char arisyntax[];
+extern char is_type[];
+#else
+extern const char basesyntax[];
+extern const char dqsyntax[];
+extern const char sqsyntax[];
+extern const char arisyntax[];
+extern const char is_type[];
+#endif
Index: /tags/kBuild-0.1.4/src/kash/sys_signame.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/sys_signame.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/sys_signame.c	(revision 1780)
@@ -0,0 +1,121 @@
+/*
+ * Fake sys_signame.
+ */
+
+#include "shinstance.h" /* for MSC */
+#include <string.h>
+#include <stdio.h>
+
+static char sys_signame_initialized = 0;
+char sys_signame[NSIG][16];
+
+void init_sys_signame(void)
+{
+    unsigned i;
+	if (sys_signame_initialized)
+		return;
+	for (i = 0; i < NSIG; ++i)
+		sprintf(sys_signame[i], "%d", i);
+#define SET_SIG_STR(sig) strcpy(sys_signame[SIG##sig], #sig);
+#ifdef SIGHUP
+	SET_SIG_STR(HUP);
+#endif
+#ifdef SIGINT
+	SET_SIG_STR(INT);
+#endif
+#ifdef SIGQUIT
+	SET_SIG_STR(QUIT);
+#endif
+#ifdef SIGILL
+	SET_SIG_STR(ILL);
+#endif
+#ifdef SIGTRAP
+	SET_SIG_STR(TRAP);
+#endif
+#ifdef SIGABRT
+	SET_SIG_STR(ABRT);
+#endif
+#ifdef SIGIOT
+	SET_SIG_STR(IOT);
+#endif
+#ifdef SIGBUS
+	SET_SIG_STR(BUS);
+#endif
+#ifdef SIGFPE
+	SET_SIG_STR(FPE);
+#endif
+#ifdef SIGKILL
+	SET_SIG_STR(KILL);
+#endif
+#ifdef SIGUSR1
+	SET_SIG_STR(USR1);
+#endif
+#ifdef SIGSEGV
+	SET_SIG_STR(SEGV);
+#endif
+#ifdef SIGUSR2
+	SET_SIG_STR(USR2);
+#endif
+#ifdef SIGPIPE
+	SET_SIG_STR(PIPE);
+#endif
+#ifdef SIGALRM
+	SET_SIG_STR(ALRM);
+#endif
+#ifdef SIGTERM
+	SET_SIG_STR(TERM);
+#endif
+#ifdef SIGSTKFLT
+	SET_SIG_STR(STKFLT);
+#endif
+#ifdef SIGCHLD
+	SET_SIG_STR(CHLD);
+#endif
+#ifdef SIGCONT
+	SET_SIG_STR(CONT);
+#endif
+#ifdef SIGSTOP
+	SET_SIG_STR(STOP);
+#endif
+#ifdef SIGTSTP
+	SET_SIG_STR(TSTP);
+#endif
+#ifdef SIGTTIN
+	SET_SIG_STR(TTIN);
+#endif
+#ifdef SIGTTOU
+	SET_SIG_STR(TTOU);
+#endif
+#ifdef SIGURG
+	SET_SIG_STR(URG);
+#endif
+#ifdef SIGXCPU
+	SET_SIG_STR(XCPU);
+#endif
+#ifdef SIGXFSZ
+	SET_SIG_STR(XFSZ);
+#endif
+#ifdef SIGVTALRM
+	SET_SIG_STR(VTALRM);
+#endif
+#ifdef SIGPROF
+	SET_SIG_STR(PROF);
+#endif
+#ifdef SIGWINCH
+	SET_SIG_STR(WINCH);
+#endif
+#ifdef SIGIO
+	SET_SIG_STR(IO);
+#endif
+#ifdef SIGPWR
+	SET_SIG_STR(PWR);
+#endif
+#ifdef SIGSYS
+	SET_SIG_STR(SYS);
+#endif
+#ifdef SIGBREAK
+	SET_SIG_STR(BREAK);
+#endif
+#undef SET_SIG_STR
+	sys_signame_initialized = 1;
+}
Index: /tags/kBuild-0.1.4/src/kash/trap.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/trap.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/trap.c	(revision 1780)
@@ -0,0 +1,461 @@
+/*	$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)trap.c	8.5 (Berkeley) 6/5/95";
+#else
+__RCSID("$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $");
+#endif /* not lint */
+#endif
+
+#include <stdlib.h>
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"	/* for other headers */
+#include "eval.h"
+#include "jobs.h"
+#include "show.h"
+#include "options.h"
+#include "syntax.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "trap.h"
+#include "mystring.h"
+#include "var.h"
+#include "shinstance.h"
+
+#ifndef HAVE_SYS_SIGNAME
+extern void init_sys_signame(void);
+extern char sys_signame[NSIG][16];
+#endif
+
+/*
+ * Sigmode records the current value of the signal handlers for the various
+ * modes.  A value of zero means that the current handler is not known.
+ * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
+ */
+
+#define S_DFL 1			/* default signal handling (SIG_DFL) */
+#define S_CATCH 2		/* signal is caught */
+#define S_IGN 3			/* signal is ignored (SIG_IGN) */
+#define S_HARD_IGN 4		/* signal is ignored permenantly */
+#define S_RESET 5		/* temporary - to reset a hard ignored sig */
+
+
+//char *trap[NSIG+1];		/* trap handler commands */
+//MKINIT char sigmode[NSIG];	/* current value of signal */
+//char gotsig[NSIG];		/* indicates specified signal received */
+//int pendingsigs;		/* indicates some signal received */
+
+static int getsigaction(shinstance *, int, shsig_t *);
+
+/*
+ * return the signal number described by `p' (as a number or a name)
+ * or -1 if it isn't one
+ */
+
+static int
+signame_to_signum(shinstance *psh, const char *p)
+{
+	int i;
+
+	if (is_number(p))
+		return number(psh, p);
+
+	if (strcasecmp(p, "exit") == 0 )
+		return 0;
+
+	if (strncasecmp(p, "sig", 3) == 0)
+		p += 3;
+
+#ifndef HAVE_SYS_SIGNAME
+	init_sys_signame();
+#endif
+	for (i = 0; i < NSIG; ++i)
+		if (strcasecmp(p, sys_signame[i]) == 0)
+			return i;
+	return -1;
+}
+
+/*
+ * Print a list of valid signal names
+ */
+static void
+printsignals(shinstance *psh)
+{
+	int n;
+
+	out1str(psh, "EXIT ");
+#ifndef HAVE_SYS_SIGNAME
+	init_sys_signame();
+#endif
+
+	for (n = 1; n < NSIG; n++) {
+		out1fmt(psh, "%s", sys_signame[n]);
+		if ((n == NSIG/2) ||  n == (NSIG - 1))
+			out1str(psh, "\n");
+		else
+			out1c(psh, ' ');
+	}
+}
+
+/*
+ * The trap builtin.
+ */
+
+int
+trapcmd(shinstance *psh, int argc, char **argv)
+{
+	char *action;
+	char **ap;
+	int signo;
+#ifndef HAVE_SYS_SIGNAME
+	init_sys_signame();
+#endif
+
+	if (argc <= 1) {
+		for (signo = 0 ; signo <= NSIG ; signo++)
+			if (psh->trap[signo] != NULL) {
+				out1fmt(psh, "trap -- ");
+				print_quoted(psh, psh->trap[signo]);
+				out1fmt(psh, " %s\n",
+				    (signo) ? sys_signame[signo] : "EXIT");
+			}
+		return 0;
+	}
+	ap = argv + 1;
+
+	action = NULL;
+
+	if (strcmp(*ap, "--") == 0)
+		if (*++ap == NULL)
+			return 0;
+
+	if (signame_to_signum(psh, *ap) == -1) {
+		if ((*ap)[0] == '-') {
+			if ((*ap)[1] == '\0')
+				ap++;
+			else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') {
+				printsignals(psh);
+				return 0;
+			}
+			else
+				error(psh, "bad option %s\n", *ap);
+		}
+		else
+			action = *ap++;
+	}
+
+	while (*ap) {
+		if (is_number(*ap))
+			signo = number(psh, *ap);
+		else
+			signo = signame_to_signum(psh, *ap);
+
+		if (signo < 0 || signo > NSIG)
+			error(psh, "%s: bad trap", *ap);
+
+		INTOFF;
+		if (action)
+			action = savestr(action);
+
+		if (psh->trap[signo])
+			ckfree(psh->trap[signo]);
+
+		psh->trap[signo] = action;
+
+		if (signo != 0)
+			setsignal(psh, signo, 0);
+		INTON;
+		ap++;
+	}
+	return 0;
+}
+
+
+
+/*
+ * Clear traps on a fork or vfork.
+ * Takes one arg vfork, to tell it to not be destructive of
+ * the parents variables.
+ */
+
+void
+clear_traps(shinstance *psh, int vforked)
+{
+	char **tp;
+
+	for (tp = psh->trap ; tp <= &psh->trap[NSIG] ; tp++) {
+		if (*tp && **tp) {	/* trap not NULL or SIG_IGN */
+			INTOFF;
+			if (!vforked) {
+				ckfree(*tp);
+				*tp = NULL;
+			}
+			if (tp != &psh->trap[0])
+				setsignal(psh, (int)(tp - psh->trap), vforked);
+			INTON;
+		}
+	}
+}
+
+
+
+/*
+ * Set the signal handler for the specified signal.  The routine figures
+ * out what it should be set to.
+ */
+
+void
+setsignal(shinstance *psh, int signo, int vforked)
+{
+	int action;
+	shsig_t sigact = SH_SIG_DFL;
+	char *t, tsig;
+
+	if ((t = psh->trap[signo]) == NULL)
+		action = S_DFL;
+	else if (*t != '\0')
+		action = S_CATCH;
+	else
+		action = S_IGN;
+	if (psh->rootshell && !vforked && action == S_DFL) {
+		switch (signo) {
+		case SIGINT:
+			if (iflag(psh) || psh->minusc || sflag(psh) == 0)
+				action = S_CATCH;
+			break;
+		case SIGQUIT:
+#ifdef DEBUG
+			if (debug(psh))
+				break;
+#endif
+			/* FALLTHROUGH */
+		case SIGTERM:
+			if (iflag(psh))
+				action = S_IGN;
+			break;
+#if JOBS
+		case SIGTSTP:
+		case SIGTTOU:
+			if (mflag(psh))
+				action = S_IGN;
+			break;
+#endif
+		}
+	}
+
+	t = &psh->sigmode[signo - 1];
+	tsig = *t;
+	if (tsig == 0) {
+		/*
+		 * current setting unknown
+		 */
+		if (!getsigaction(psh, signo, &sigact)) {
+			/*
+			 * Pretend it worked; maybe we should give a warning
+			 * here, but other shells don't. We don't alter
+			 * sigmode, so that we retry every time.
+			 */
+			return;
+		}
+		if (sigact == SH_SIG_IGN) {
+			if (mflag(psh) && (signo == SIGTSTP ||
+			     signo == SIGTTIN || signo == SIGTTOU)) {
+				tsig = S_IGN;	/* don't hard ignore these */
+			} else
+				tsig = S_HARD_IGN;
+		} else {
+			tsig = S_RESET;	/* force to be set */
+		}
+	}
+	if (tsig == S_HARD_IGN || tsig == action)
+		return;
+	switch (action) {
+		case S_DFL:	sigact = SH_SIG_DFL;	break;
+		case S_CATCH:  	sigact = onsig;		break;
+		case S_IGN:	sigact = SH_SIG_IGN;	break;
+	}
+	if (!vforked)
+		*t = action;
+	sh_siginterrupt(psh, signo, 1);
+	sh_signal(psh, signo, sigact);
+}
+
+/*
+ * Return the current setting for sig w/o changing it.
+ */
+static int
+getsigaction(shinstance *psh, int signo, shsig_t *sigact)
+{
+	struct shsigaction sa;
+
+	if (sh_sigaction(psh, signo, NULL, &sa) == -1)
+		return 0;
+	*sigact = (shsig_t)sa.sh_handler;
+	return 1;
+}
+
+/*
+ * Ignore a signal.
+ */
+
+void
+ignoresig(shinstance *psh, int signo, int vforked)
+{
+	if (psh->sigmode[signo - 1] != S_IGN && psh->sigmode[signo - 1] != S_HARD_IGN) {
+		sh_signal(psh, signo, SH_SIG_IGN);
+	}
+	if (!vforked)
+		psh->sigmode[signo - 1] = S_HARD_IGN;
+}
+
+
+#ifdef mkinit
+INCLUDE <signal.h>
+INCLUDE "trap.h"
+
+SHELLPROC {
+	char *sm;
+
+	clear_traps(psh, 0);
+	for (sm = psh->sigmode ; sm < psh->sigmode + NSIG ; sm++) {
+		if (*sm == S_IGN)
+			*sm = S_HARD_IGN;
+	}
+}
+#endif
+
+
+
+/*
+ * Signal handler.
+ */
+
+void
+onsig(shinstance *psh, int signo)
+{
+	sh_signal(psh, signo, onsig);
+	if (signo == SIGINT && psh->trap[SIGINT] == NULL) {
+		onint(psh);
+		return;
+	}
+	psh->gotsig[signo - 1] = 1;
+	psh->pendingsigs++;
+}
+
+
+
+/*
+ * Called to execute a trap.  Perhaps we should avoid entering new trap
+ * handlers while we are executing a trap handler.
+ */
+
+void
+dotrap(shinstance *psh)
+{
+	int i;
+	int savestatus;
+
+	for (;;) {
+		for (i = 1 ; ; i++) {
+			if (psh->gotsig[i - 1])
+				break;
+			if (i >= NSIG)
+				goto done;
+		}
+		psh->gotsig[i - 1] = 0;
+		savestatus=psh->exitstatus;
+		evalstring(psh, psh->trap[i], 0);
+		psh->exitstatus=savestatus;
+	}
+done:
+	psh->pendingsigs = 0;
+}
+
+
+
+/*
+ * Controls whether the shell is interactive or not.
+ */
+
+
+void
+setinteractive(shinstance *psh, int on)
+{
+	static int is_interactive;
+
+	if (on == is_interactive)
+		return;
+	setsignal(psh, SIGINT, 0);
+	setsignal(psh, SIGQUIT, 0);
+	setsignal(psh, SIGTERM, 0);
+	is_interactive = on;
+}
+
+
+
+/*
+ * Called to exit the shell.
+ */
+
+void
+exitshell(shinstance *psh, int status)
+{
+	struct jmploc loc1, loc2;
+	char *p;
+
+	TRACE((psh, "pid %d, exitshell(%d)\n", sh_getpid(psh), status));
+	if (setjmp(loc1.loc)) {
+		goto l1;
+	}
+	if (setjmp(loc2.loc)) {
+		goto l2;
+	}
+	psh->handler = &loc1;
+	if ((p = psh->trap[0]) != NULL && *p != '\0') {
+		psh->trap[0] = NULL;
+		evalstring(psh, p, 0);
+	}
+l1:   psh->handler = &loc2;			/* probably unnecessary */
+	output_flushall(psh);
+#if JOBS
+	setjobctl(psh, 0);
+#endif
+l2: sh__exit(psh, status);
+	/* NOTREACHED */
+}
Index: /tags/kBuild-0.1.4/src/kash/trap.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/trap.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/trap.h	(revision 1780)
@@ -0,0 +1,46 @@
+/*	$NetBSD: trap.h,v 1.17 2003/08/07 09:05:39 agc Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)trap.h	8.3 (Berkeley) 6/5/95
+ */
+
+/*extern int pendingsigs;*/
+
+int trapcmd(struct shinstance *, int, char **);
+void clear_traps(struct shinstance *, int);
+void setsignal(struct shinstance *, int, int);
+void ignoresig(struct shinstance *, int, int);
+void onsig(struct shinstance *, int);
+void dotrap(struct shinstance *);
+void setinteractive(struct shinstance *, int);
+void exitshell(struct shinstance *, int) __attribute__((__noreturn__));
Index: /tags/kBuild-0.1.4/src/kash/var.c
===================================================================
--- /tags/kBuild-0.1.4/src/kash/var.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/var.c	(revision 1780)
@@ -0,0 +1,926 @@
+/*	$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $");
+#endif /* not lint */
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef PC_OS2_LIBPATHS
+#define INCL_BASE
+#include <os2.h>
+
+#ifndef LIBPATHSTRICT
+#define LIBPATHSTRICT 3
+#endif
+
+extern APIRET
+#ifdef APIENTRY
+    APIENTRY
+#endif
+    DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
+#define QHINF_EXEINFO       1 /* NE exeinfo. */
+#define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
+#define QHINF_READFILE      3 /* Reads from the executable file. */
+#define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
+#define QHINF_LIBPATH       5 /* Gets the entire libpath. */
+#define QHINF_FIXENTRY      6 /* NE only */
+#define QHINF_STE           7 /* NE only */
+#define QHINF_MAPSEL        8 /* NE only */
+
+#endif
+
+
+/*
+ * Shell variables.
+ */
+
+#include "shell.h"
+#include "output.h"
+#include "expand.h"
+#include "nodes.h"	/* for other headers */
+#include "eval.h"	/* defines cmdenviron */
+#include "exec.h"
+#include "syntax.h"
+#include "options.h"
+#include "mail.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "parser.h"
+#include "show.h"
+#ifndef SMALL
+# include "myhistedit.h"
+#endif
+#include "shinstance.h"
+
+//#ifdef SMALL
+//#define VTABSIZE 39
+//#else
+//#define VTABSIZE 517
+//#endif
+
+
+struct varinit {
+	unsigned var_off;
+	int flags;
+	const char *text;
+	void (*func)(shinstance *, const char *);
+};
+
+
+//#if ATTY
+//struct var vatty;
+//#endif
+//#ifndef SMALL
+//struct var vhistsize;
+//struct var vterm;
+//#endif
+//struct var vifs;
+//struct var vmail;
+//struct var vmpath;
+//struct var vpath;
+//#ifdef _MSC_VER
+//struct var vpath2;
+//#endif
+//struct var vps1;
+//struct var vps2;
+//struct var vps4;
+//struct var vvers; - unused
+//struct var voptind;
+
+#ifdef PC_OS2_LIBPATHS
+//static struct var libpath_vars[4];
+static const char * const libpath_envs[4] = {"LIBPATH=", "BEGINLIBPATH=", "ENDLIBPATH=", "LIBPATHSTRICT="};
+#endif
+
+const struct varinit varinit[] = {
+#if ATTY
+	{ offsetof(shinstance, vatty),	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",
+	  NULL },
+#endif
+#ifndef SMALL
+	{ offsetof(shinstance, vhistsize),	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",
+	  sethistsize },
+#endif
+	{ offsetof(shinstance, vifs),	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n",
+	  NULL },
+	{ offsetof(shinstance, vmail),	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL=",
+	  NULL },
+	{ offsetof(shinstance, vmpath),	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",
+	  NULL },
+	{ offsetof(shinstance, vpath),	VSTRFIXED|VTEXTFIXED,		"PATH=" _PATH_DEFPATH,
+	  changepath },
+#ifdef _MSC_VER
+	{ offsetof(shinstance, vpath2),	VSTRFIXED|VTEXTFIXED,		"Path=",
+	  changepath },
+#endif
+	/*
+	 * vps1 depends on uid
+	 */
+	{ offsetof(shinstance, vps2),	VSTRFIXED|VTEXTFIXED,		"PS2=> ",
+	  NULL },
+	{ offsetof(shinstance, vps4),	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",
+	  NULL },
+#ifndef SMALL
+	{ offsetof(shinstance, vterm),	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM=",
+	  setterm },
+#endif
+	{ offsetof(shinstance, voptind),	VSTRFIXED|VTEXTFIXED|VNOFUNC,	"OPTIND=1",
+	  getoptsreset },
+	{ 0,	0,				NULL,
+	  NULL }
+};
+
+//struct var *vartab[VTABSIZE];
+
+STATIC int strequal(const char *, const char *);
+STATIC struct var *find_var(shinstance *, const char *, struct var ***, int *);
+
+/*
+ * Initialize the varable symbol tables and import the environment
+ */
+
+#ifdef mkinit
+INCLUDE "var.h"
+
+INIT {
+	char **envp;
+
+	initvar(psh);
+	for (envp = sh_environ(psh) ; *envp ; envp++) {
+		if (strchr(*envp, '=')) {
+			setvareq(psh, *envp, VEXPORT|VTEXTFIXED);
+		}
+	}
+}
+#endif
+
+
+/*
+ * This routine initializes the builtin variables.  It is called when the
+ * shell is initialized and again when a shell procedure is spawned.
+ */
+
+void
+initvar(shinstance *psh)
+{
+	const struct varinit *ip;
+	struct var *vp;
+	struct var **vpp;
+#ifdef PC_OS2_LIBPATHS
+	char *psz = ckmalloc(2048);
+	int rc;
+	int i;
+
+	for (i = 0; i < 4; i++)
+	{
+		psh->libpath_vars[i].flags = VSTRFIXED | VOS2LIBPATH;
+		psh->libpath_vars[i].func = NULL;
+
+		if (i > 0)
+		{
+			psz[0] = psz[1] = psz[2] = psz[3] = '\0';
+			rc = DosQueryExtLIBPATH(psz, i);
+		}
+		else
+		{
+			rc = DosQueryHeaderInfo(NULLHANDLE, 0, psz, 2048, QHINF_LIBPATH);
+			psh->libpath_vars[i].flags |= VREADONLY;
+		}
+		if (!rc && *psz)
+		{
+			int cch1 = strlen(libpath_envs[i]);
+			int cch2 = strlen(psz) + 1;
+			psh->libpath_vars[i].text = ckmalloc(cch1 + cch2);
+			memcpy(psh->libpath_vars[i].text, libpath_envs[i], cch1);
+			memcpy(psh->libpath_vars[i].text + cch1, psz, cch2);
+		}
+		else
+		{
+			psh->libpath_vars[i].flags |= VUNSET | VTEXTFIXED;
+			psh->libpath_vars[i].text = (char*)libpath_envs[i];
+		}
+		if (find_var(psh, psh->libpath_vars[i].text, &vpp, &psh->libpath_vars[i].name_len) != NULL)
+			continue;
+		psh->libpath_vars[i].next = *vpp;
+		*vpp = &psh->libpath_vars[i];
+	}
+	free(psz);
+#endif
+
+	for (ip = varinit; ip->text; ip++) {
+		vp = (struct var *)((char *)psh + ip->var_off);
+		if (find_var(psh, ip->text, &vpp, &vp->name_len) != NULL)
+			continue;
+		vp->next = *vpp;
+		*vpp = vp;
+		vp->text = strdup(ip->text);
+		vp->flags = ip->flags;
+		vp->func = ip->func;
+	}
+	/*
+	 * PS1 depends on uid
+	 */
+	if (find_var(psh, "PS1", &vpp, &psh->vps1.name_len) == NULL) {
+		psh->vps1.next = *vpp;
+		*vpp = &psh->vps1;
+		psh->vps1.text = strdup(sh_geteuid(psh) ? "PS1=$ " : "PS1=# ");
+		psh->vps1.flags = VSTRFIXED|VTEXTFIXED;
+	}
+}
+
+/*
+ * Safe version of setvar, returns 1 on success 0 on failure.
+ */
+
+int
+setvarsafe(shinstance *psh, const char *name, const char *val, int flags)
+{
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler = psh->handler;
+	int err = 0;
+#ifdef __GNUC__
+	(void) &err;
+#endif
+
+	if (setjmp(jmploc.loc))
+		err = 1;
+	else {
+		psh->handler = &jmploc;
+		setvar(psh, name, val, flags);
+	}
+	psh->handler = savehandler;
+	return err;
+}
+
+/*
+ * Set the value of a variable.  The flags argument is ored with the
+ * flags of the variable.  If val is NULL, the variable is unset.
+ */
+
+void
+setvar(shinstance *psh, const char *name, const char *val, int flags)
+{
+	const char *p;
+	const char *q;
+	char *d;
+	size_t len;
+	int namelen;
+	char *nameeq;
+	int isbad;
+
+	isbad = 0;
+	p = name;
+	if (! is_name(*p))
+		isbad = 1;
+	p++;
+	for (;;) {
+		if (! is_in_name(*p)) {
+			if (*p == '\0' || *p == '=')
+				break;
+			isbad = 1;
+		}
+		p++;
+	}
+	namelen = (int)(p - name);
+	if (isbad)
+		error(psh, "%.*s: bad variable name", namelen, name);
+	len = namelen + 2;		/* 2 is space for '=' and '\0' */
+	if (val == NULL) {
+		flags |= VUNSET;
+	} else {
+		len += strlen(val);
+	}
+	d = nameeq = ckmalloc(len);
+	q = name;
+	while (--namelen >= 0)
+		*d++ = *q++;
+	*d++ = '=';
+	*d = '\0';
+	if (val)
+		scopy(val, d);
+	setvareq(psh, nameeq, flags);
+}
+
+
+
+/*
+ * Same as setvar except that the variable and value are passed in
+ * the first argument as name=value.  Since the first argument will
+ * be actually stored in the table, it should not be a string that
+ * will go away.
+ */
+
+void
+setvareq(shinstance *psh, char *s, int flags)
+{
+	struct var *vp, **vpp;
+	int nlen;
+
+	if (aflag(psh))
+		flags |= VEXPORT;
+	vp = find_var(psh, s, &vpp, &nlen);
+	if (vp != NULL) {
+		if (vp->flags & VREADONLY)
+			error(psh, "%.*s: is read only", vp->name_len, s);
+		if (flags & VNOSET)
+			return;
+		INTOFF;
+
+		if (vp->func && (flags & VNOFUNC) == 0)
+			(*vp->func)(psh, s + vp->name_len + 1);
+
+		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
+			ckfree(vp->text);
+
+		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
+		vp->flags |= flags & ~VNOFUNC;
+		vp->text = s;
+#ifdef PC_OS2_LIBPATHS
+		if ((vp->flags & VOS2LIBPATH) && (vp->flags & VEXPORT))
+			vp->flags &= ~VEXPORT;
+#endif
+
+		/*
+		 * We could roll this to a function, to handle it as
+		 * a regular variable function callback, but why bother?
+		 */
+		if (vp == &psh->vmpath || (vp == &psh->vmail && ! mpathset(psh)))
+			chkmail(psh, 1);
+		INTON;
+		return;
+	}
+	/* not found */
+	if (flags & VNOSET)
+		return;
+	vp = ckmalloc(sizeof (*vp));
+	vp->flags = flags & ~VNOFUNC;
+	vp->text = s;
+	vp->name_len = nlen;
+	vp->next = *vpp;
+	vp->func = NULL;
+	*vpp = vp;
+}
+
+
+
+/*
+ * Process a linked list of variable assignments.
+ */
+
+void
+listsetvar(shinstance *psh, struct strlist *list, int flags)
+{
+	struct strlist *lp;
+
+	INTOFF;
+	for (lp = list ; lp ; lp = lp->next) {
+		setvareq(psh, savestr(lp->text), flags);
+	}
+	INTON;
+}
+
+void
+listmklocal(shinstance *psh, struct strlist *list, int flags)
+{
+	struct strlist *lp;
+
+	for (lp = list ; lp ; lp = lp->next)
+		mklocal(psh, lp->text, flags);
+}
+
+
+/*
+ * Find the value of a variable.  Returns NULL if not set.
+ */
+
+char *
+lookupvar(shinstance *psh, const char *name)
+{
+	struct var *v;
+
+	v = find_var(psh, name, NULL, NULL);
+	if (v == NULL || v->flags & VUNSET)
+		return NULL;
+	return v->text + v->name_len + 1;
+}
+
+
+
+/*
+ * Search the environment of a builtin command.  If the second argument
+ * is nonzero, return the value of a variable even if it hasn't been
+ * exported.
+ */
+
+char *
+bltinlookup(shinstance *psh, const char *name, int doall)
+{
+	struct strlist *sp;
+	struct var *v;
+
+	for (sp = psh->cmdenviron ; sp ; sp = sp->next) {
+		if (strequal(sp->text, name))
+			return strchr(sp->text, '=') + 1;
+	}
+
+	v = find_var(psh, name, NULL, NULL);
+
+	if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT)))
+		return NULL;
+	return v->text + v->name_len + 1;
+}
+
+
+
+/*
+ * Generate a list of exported variables.  This routine is used to construct
+ * the third argument to execve when executing a program.
+ */
+
+char **
+environment(shinstance *psh)
+{
+	int nenv;
+	struct var **vpp;
+	struct var *vp;
+	char **env;
+	char **ep;
+
+	nenv = 0;
+	for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next)
+			if (vp->flags & VEXPORT)
+				nenv++;
+	}
+	ep = env = stalloc(psh, (nenv + 1) * sizeof *env);
+	for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next)
+			if (vp->flags & VEXPORT)
+				*ep++ = vp->text;
+	}
+	*ep = NULL;
+
+#ifdef PC_OS2_LIBPATHS
+	/*
+	 * Set the libpaths now as this is exec() time.
+	 */
+	for (nenv = 0; nenv < 3; nenv++)
+		DosSetExtLIBPATH(strchr(psh->libpath_vars[nenv].text, '=') + 1, nenv);
+#endif
+
+	return env;
+}
+
+
+/*
+ * Called when a shell procedure is invoked to clear out nonexported
+ * variables.  It is also necessary to reallocate variables of with
+ * VSTACK set since these are currently allocated on the stack.
+ */
+
+#ifdef mkinit
+void shprocvar(shinstance *psh);
+
+SHELLPROC {
+	shprocvar(psh);
+}
+#endif
+
+void
+shprocvar(shinstance *psh)
+{
+	struct var **vpp;
+	struct var *vp, **prev;
+
+	for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) {
+		for (prev = vpp ; (vp = *prev) != NULL ; ) {
+			if ((vp->flags & VEXPORT) == 0) {
+				*prev = vp->next;
+				if ((vp->flags & VTEXTFIXED) == 0)
+					ckfree(vp->text);
+				if ((vp->flags & VSTRFIXED) == 0)
+					ckfree(vp);
+			} else {
+				if (vp->flags & VSTACK) {
+					vp->text = savestr(vp->text);
+					vp->flags &=~ VSTACK;
+				}
+				prev = &vp->next;
+			}
+		}
+	}
+	initvar(psh);
+}
+
+
+
+/*
+ * Command to list all variables which are set.  Currently this command
+ * is invoked from the set command when the set command is called without
+ * any variables.
+ */
+
+void
+print_quoted(shinstance *psh, const char *p)
+{
+	const char *q;
+
+	if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) {
+		out1fmt(psh, "%s", p);
+		return;
+	}
+	while (*p) {
+		if (*p == '\'') {
+			out1fmt(psh, "\\'");
+			p++;
+			continue;
+		}
+		q = strchr(p, '\'');
+		if (!q) {
+			out1fmt(psh, "'%s'", p );
+			return;
+		}
+		out1fmt(psh, "'%.*s'", (int)(q - p), p );
+		p = q;
+	}
+}
+
+static int
+sort_var(const void *v_v1, const void *v_v2)
+{
+	const struct var * const *v1 = v_v1;
+	const struct var * const *v2 = v_v2;
+
+	/* XXX Will anyone notice we include the '=' of the shorter name? */
+	return strcoll((*v1)->text, (*v2)->text);
+}
+
+/*
+ * POSIX requires that 'set' (but not export or readonly) output the
+ * variables in lexicographic order - by the locale's collating order (sigh).
+ * Maybe we could keep them in an ordered balanced binary tree
+ * instead of hashed lists.
+ * For now just roll 'em through qsort for printing...
+ */
+
+int
+showvars(shinstance *psh, const char *name, int flag, int show_value)
+{
+	struct var **vpp;
+	struct var *vp;
+	const char *p;
+
+	static struct var **list;	/* static in case we are interrupted */
+	static int list_len;
+	int count = 0;
+
+	if (!list) {
+		list_len = 32;
+		list = ckmalloc(list_len * sizeof(*list));
+	}
+
+	for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) {
+		for (vp = *vpp ; vp ; vp = vp->next) {
+			if (flag && !(vp->flags & flag))
+				continue;
+			if (vp->flags & VUNSET && !(show_value & 2))
+				continue;
+			if (count >= list_len) {
+				list = ckrealloc(list,
+					(list_len << 1) * sizeof(*list));
+				list_len <<= 1;
+			}
+			list[count++] = vp;
+		}
+	}
+
+	qsort(list, count, sizeof(*list), sort_var);
+
+	for (vpp = list; count--; vpp++) {
+		vp = *vpp;
+		if (name)
+			out1fmt(psh, "%s ", name);
+		for (p = vp->text ; *p != '=' ; p++)
+			out1c(psh, *p);
+		if (!(vp->flags & VUNSET) && show_value) {
+			out1fmt(psh, "=");
+			print_quoted(psh, ++p);
+		}
+		out1c(psh, '\n');
+	}
+	return 0;
+}
+
+
+
+/*
+ * The export and readonly commands.
+ */
+
+int
+exportcmd(shinstance *psh, int argc, char **argv)
+{
+	struct var *vp;
+	char *name;
+	const char *p;
+	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
+	int pflag;
+
+	pflag = nextopt(psh, "p") == 'p' ? 3 : 0;
+	if (argc <= 1 || pflag) {
+		showvars(psh, pflag ? argv[0] : 0, flag, pflag );
+		return 0;
+	}
+
+	while ((name = *psh->argptr++) != NULL) {
+		if ((p = strchr(name, '=')) != NULL) {
+			p++;
+		} else {
+			vp = find_var(psh, name, NULL, NULL);
+			if (vp != NULL) {
+				vp->flags |= flag;
+				continue;
+			}
+		}
+		setvar(psh, name, p, flag);
+	}
+	return 0;
+}
+
+
+/*
+ * The "local" command.
+ */
+
+int
+localcmd(shinstance *psh, int argc, char **argv)
+{
+	char *name;
+
+	if (! in_function(psh))
+		error(psh, "Not in a function");
+	while ((name = *psh->argptr++) != NULL) {
+		mklocal(psh, name, 0);
+	}
+	return 0;
+}
+
+
+/*
+ * Make a variable a local variable.  When a variable is made local, it's
+ * value and flags are saved in a localvar structure.  The saved values
+ * will be restored when the shell function returns.  We handle the name
+ * "-" as a special case.
+ */
+
+void
+mklocal(shinstance *psh, const char *name, int flags)
+{
+	struct localvar *lvp;
+	struct var **vpp;
+	struct var *vp;
+
+	INTOFF;
+	lvp = ckmalloc(sizeof (struct localvar));
+	if (name[0] == '-' && name[1] == '\0') {
+		char *p;
+		p = ckmalloc(sizeof_optlist);
+		lvp->text = memcpy(p, psh->optlist, sizeof_optlist);
+		vp = NULL;
+	} else {
+		vp = find_var(psh, name, &vpp, NULL);
+		if (vp == NULL) {
+			if (strchr(name, '='))
+				setvareq(psh, savestr(name), VSTRFIXED|flags);
+			else
+				setvar(psh, name, NULL, VSTRFIXED|flags);
+			vp = *vpp;	/* the new variable */
+			lvp->text = NULL;
+			lvp->flags = VUNSET;
+		} else {
+			lvp->text = vp->text;
+			lvp->flags = vp->flags;
+			vp->flags |= VSTRFIXED|VTEXTFIXED;
+			if (name[vp->name_len] == '=')
+				setvareq(psh, savestr(name), flags);
+		}
+	}
+	lvp->vp = vp;
+	lvp->next = psh->localvars;
+	psh->localvars = lvp;
+	INTON;
+}
+
+
+/*
+ * Called after a function returns.
+ */
+
+void
+poplocalvars(shinstance *psh)
+{
+	struct localvar *lvp;
+	struct var *vp;
+
+	while ((lvp = psh->localvars) != NULL) {
+		psh->localvars = lvp->next;
+		vp = lvp->vp;
+		TRACE((psh, "poplocalvar %s", vp ? vp->text : "-"));
+		if (vp == NULL) {	/* $- saved */
+			memcpy(psh->optlist, lvp->text, sizeof_optlist);
+			ckfree(lvp->text);
+		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
+			(void)unsetvar(psh, vp->text, 0);
+		} else {
+			if (vp->func && (vp->flags & VNOFUNC) == 0)
+				(*vp->func)(psh, lvp->text + vp->name_len + 1);
+			if ((vp->flags & VTEXTFIXED) == 0)
+				ckfree(vp->text);
+			vp->flags = lvp->flags;
+			vp->text = lvp->text;
+		}
+		ckfree(lvp);
+	}
+}
+
+
+int
+setvarcmd(shinstance *psh, int argc, char **argv)
+{
+	if (argc <= 2)
+		return unsetcmd(psh, argc, argv);
+	else if (argc == 3)
+		setvar(psh, argv[1], argv[2], 0);
+	else
+		error(psh, "List assignment not implemented");
+	return 0;
+}
+
+
+/*
+ * The unset builtin command.  We unset the function before we unset the
+ * variable to allow a function to be unset when there is a readonly variable
+ * with the same name.
+ */
+
+int
+unsetcmd(shinstance *psh, int argc, char **argv)
+{
+	char **ap;
+	int i;
+	int flg_func = 0;
+	int flg_var = 0;
+	int ret = 0;
+
+	while ((i = nextopt(psh, "evf")) != '\0') {
+		if (i == 'f')
+			flg_func = 1;
+		else
+			flg_var = i;
+	}
+	if (flg_func == 0 && flg_var == 0)
+		flg_var = 1;
+
+	for (ap = psh->argptr; *ap ; ap++) {
+		if (flg_func)
+			ret |= unsetfunc(psh, *ap);
+		if (flg_var)
+			ret |= unsetvar(psh, *ap, flg_var == 'e');
+	}
+	return ret;
+}
+
+
+/*
+ * Unset the specified variable.
+ */
+
+int
+unsetvar(shinstance *psh, const char *s, int unexport)
+{
+	struct var **vpp;
+	struct var *vp;
+
+	vp = find_var(psh, s, &vpp, NULL);
+	if (vp == NULL)
+		return 1;
+
+	if (vp->flags & VREADONLY)
+		return (1);
+
+	INTOFF;
+	if (unexport) {
+		vp->flags &= ~VEXPORT;
+	} else {
+		if (vp->text[vp->name_len + 1] != '\0')
+			setvar(psh, s, nullstr, 0);
+		vp->flags &= ~VEXPORT;
+		vp->flags |= VUNSET;
+		if ((vp->flags & VSTRFIXED) == 0) {
+			if ((vp->flags & VTEXTFIXED) == 0)
+				ckfree(vp->text);
+			*vpp = vp->next;
+			ckfree(vp);
+		}
+	}
+	INTON;
+	return 0;
+}
+
+
+/*
+ * Returns true if the two strings specify the same varable.  The first
+ * variable name is terminated by '='; the second may be terminated by
+ * either '=' or '\0'.
+ */
+
+STATIC int
+strequal(const char *p, const char *q)
+{
+	while (*p == *q++) {
+		if (*p++ == '=')
+			return 1;
+	}
+	if (*p == '=' && *(q - 1) == '\0')
+		return 1;
+	return 0;
+}
+
+/*
+ * Search for a variable.
+ * 'name' may be terminated by '=' or a NUL.
+ * vppp is set to the pointer to vp, or the list head if vp isn't found
+ * lenp is set to the number of charactets in 'name'
+ */
+
+STATIC struct var *
+find_var(shinstance *psh, const char *name, struct var ***vppp, int *lenp)
+{
+	unsigned int hashval;
+	int len;
+	struct var *vp, **vpp;
+	const char *p = name;
+
+	hashval = 0;
+	while (*p && *p != '=')
+		hashval = 2 * hashval + (unsigned char)*p++;
+	len = (int)(p - name);
+
+	if (lenp)
+		*lenp = len;
+	vpp = &psh->vartab[hashval % VTABSIZE];
+	if (vppp)
+		*vppp = vpp;
+
+	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
+		if (vp->name_len != len)
+			continue;
+		if (memcmp(vp->text, name, len) != 0)
+			continue;
+		if (vppp)
+			*vppp = vpp;
+		return vp;
+	}
+	return NULL;
+}
Index: /tags/kBuild-0.1.4/src/kash/var.h
===================================================================
--- /tags/kBuild-0.1.4/src/kash/var.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kash/var.h	(revision 1780)
@@ -0,0 +1,149 @@
+/*	$NetBSD: var.h,v 1.23 2004/10/02 12:16:53 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)var.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef ___var_h___
+#define ___var_h___
+
+/*
+ * Shell variables.
+ */
+
+/* flags */
+#define VEXPORT		0x01	/* variable is exported */
+#define VREADONLY	0x02	/* variable cannot be modified */
+#define VSTRFIXED	0x04	/* variable struct is statically allocated */
+#define VTEXTFIXED	0x08	/* text is statically allocated */
+#define VSTACK		0x10	/* text is allocated on the stack */
+#define VUNSET		0x20	/* the variable is not set */
+#define VNOFUNC		0x40	/* don't call the callback function */
+#define VNOSET		0x80	/* do not set variable - just readonly test */
+#ifdef PC_OS2_LIBPATHS
+#define VOS2LIBPATH     0x8000  /* OS/2 LIBPATH related variable. */
+#endif
+
+
+struct var {
+	struct var *next;		/* next entry in hash list */
+	int flags;			/* flags are defined above */
+	char *text;			/* name=value */
+	int name_len;			/* length of name */
+	void (*func)(struct shinstance *, const char *);
+					/* function to be called when  */
+					/* the variable gets set/unset */
+};
+
+
+struct localvar {
+	struct localvar *next;		/* next local variable in list */
+	struct var *vp;			/* the variable that was made local */
+	int flags;			/* saved flags */
+	char *text;			/* saved text */
+};
+
+/*
+struct localvar *localvars;
+
+#if ATTY
+extern struct var vatty;
+#endif
+extern struct var vifs;
+extern struct var vmail;
+extern struct var vmpath;
+extern struct var vpath;
+#ifdef _MSC_VER
+extern struct var vpath2;
+#endif
+extern struct var vps1;
+extern struct var vps2;
+extern struct var vps4;
+#ifndef SMALL
+extern struct var vterm;
+extern struct var vtermcap;
+extern struct var vhistsize;
+#endif
+*/
+
+/*
+ * The following macros access the values of the above variables.
+ * They have to skip over the name.  They return the null string
+ * for unset variables.
+ */
+
+#define ifsval(psh)	((psh)->vifs.text + 4)
+#define ifsset(psh)	(((psh)->vifs.flags & VUNSET) == 0)
+#define mailval(psh)	((psh)->vmail.text + 5)
+#define mpathval(psh)	((psh)->vmpath.text + 9)
+#ifdef _MSC_VER
+#define pathval(psh)	((psh)->vpath.text[5] ? &(psh)->vpath.text[5] : &(psh)->vpath2.text[5])
+#else
+#define pathval(psh)	((psh)->vpath.text + 5)
+#endif
+#define ps1val(psh)	((psh)->vps1.text + 4)
+#define ps2val(psh)	((psh)->vps2.text + 4)
+#define ps4val(psh)	((psh)->vps4.text + 4)
+#define optindval(psh)	((psh)->voptind.text + 7)
+#ifndef SMALL
+#define histsizeval(psh) ((psh)->vhistsize.text + 9)
+#define termval(psh)	((psh)->vterm.text + 5)
+#endif
+
+#if ATTY
+#define attyset(psh)	(((psh)->vatty.flags & VUNSET) == 0)
+#endif
+#define mpathset(psh)	(((psh)->vmpath.flags & VUNSET) == 0)
+
+void initvar(struct shinstance *);
+void setvar(struct shinstance *, const char *, const char *, int);
+void setvareq(struct shinstance *, char *, int);
+struct strlist;
+void listsetvar(struct shinstance *, struct strlist *, int);
+char *lookupvar(struct shinstance *, const char *);
+char *bltinlookup(struct shinstance *, const char *, int);
+char **environment(struct shinstance *);
+void shprocvar(struct shinstance *);
+int showvars(struct shinstance *, const char *, int, int);
+int exportcmd(struct shinstance *, int, char **);
+int localcmd(struct shinstance *, int, char **);
+void mklocal(struct shinstance *, const char *, int);
+void listmklocal(struct shinstance *, struct strlist *, int);
+void poplocalvars(struct shinstance *);
+int setvarcmd(struct shinstance *, int, char **);
+int unsetcmd(struct shinstance *, int, char **);
+int unsetvar(struct shinstance *, const char *, int);
+int setvarsafe(struct shinstance *, const char *, const char *, int);
+void print_quoted(struct shinstance *, const char *);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/.purify
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/.purify	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/.purify	(revision 1780)
@@ -0,0 +1,12 @@
+# Solaris (2.5.1) has a couple if issues.
+#
+suppress plk malloc; setvbuf "libc*"; main "main.c"
+suppress umr kstat_read; kstat_chain_update; kstat_open; getloadavg
+suppress umr kstat_chain_update; kstat_open; getloadavg
+
+# The command line options stuff leaks a little bit.  No big deal.
+#
+suppress mlk malloc; xmalloc "misc.c"; decode_env_switches "main.c"
+suppress plk malloc; xmalloc "misc.c"; decode_env_switches "main.c"
+suppress mlk malloc; xmalloc "misc.c"; concat "misc.c"; decode_env_switches "main.c"
+suppress plk malloc; xmalloc "misc.c"; concat "misc.c"; decode_env_switches "main.c"
Index: /tags/kBuild-0.1.4/src/kmk/AUTHORS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/AUTHORS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/AUTHORS	(revision 1780)
@@ -0,0 +1,82 @@
+-----------------------------------
+
+GNU make development up to version 3.75 by:
+    Roland McGrath <roland@gnu.org>
+
+
+Development starting with GNU make 3.76 by:
+    Paul D. Smith <psmith@gnu.org>
+
+    Additional development starting with GNU make 3.81 by:
+        Boris Kolpackov <boris@kolpackov.net>
+
+
+GNU Make User's Manual
+  Written by:
+    Richard M. Stallman <rms@gnu.org>
+
+  Edited by:
+    Roland McGrath <roland@gnu.org>
+    Bob Chassell <bob@gnu.org>
+    Melissa Weisshaus <melissa@gnu.org>
+    Paul D. Smith <psmith@gnu.org>
+
+-----------------------------------
+GNU make porting efforts:
+
+  Port to VMS by:
+      Klaus Kaempf <kkaempf@progis.de>
+      Hartmut Becker <Hartmut.Becker@hp.com>
+      Archive support/Bug fixes by:
+        John W. Eaton <jwe@bevo.che.wisc.edu>
+        Martin Zinser <zinser@decus.decus.de>
+
+  Port to Amiga by:
+      Aaron Digulla <digulla@fh-konstanz.de>
+
+  Port to MS-DOS (DJGPP), OS/2, and MS-Windows (native/MinGW) by:
+      DJ Delorie <dj@delorie.com>
+      Rob Tulloh <rob_tulloh@tivoli.com>
+      Eli Zaretskii <eliz@is.elta.co.il>
+      Jonathan Grant <jg@jguk.org>
+      Andreas Beuning <andreas.buening@nexgo.de>
+      Earnie Boyd <earnie@uses.sf.net>
+
+-----------------------------------
+Other contributors:
+
+  Janet Carson <janet_carson@tivoli.com>
+  Howard Chu <hyc@highlandsun.com>
+  Paul Eggert <eggert@twinsun.com>
+  Klaus Heinz <kamar@ease.rhein-main.de>
+  Michael Joosten
+  Jim Kelton <jim_kelton@tivoli.com>
+  David Lubbren <uhay@rz.uni-karlsruhe.de>
+  Tim Magill <tim.magill@telops.gte.com>
+  Markus Mauhart <qwe123@chello.at>
+  Greg McGary <greg@mcgary.org>
+  Thomas Riedl <thomas.riedl@siemens.com>
+  Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+  Carl Staelin (Princeton University)
+  Ian Stewartson (Data Logic Limited)
+
+With suggestions/comments/bug reports from a cast of ... well ...
+hundreds, anyway :)
+
+-------------------------------------------------------------------------------
+Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/COPYING
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/COPYING	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/COPYING	(revision 1780)
@@ -0,0 +1,345 @@
+		    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.
+
+
+		    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.)
+
+
+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.
+
+
+  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.
+
+
+  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
+
+
+	Appendix: 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.
Index: /tags/kBuild-0.1.4/src/kmk/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/ChangeLog	(revision 1780)
@@ -0,0 +1,2971 @@
+2007-05-11  Paul Smith  <psmith@gnu.org>
+
+	* job.c (new_job): Add debug info to specify where make found the
+	command script it is running to build a target.
+	Fixes Savannah bug #18617.
+
+	* default.c (default_suffixes,default_suffix_rules,default_variables):
+	Add support for Objective C.  Fixes Savannah bug #16389.
+	Based on a patch provided by Peter O'Gorman <peter@pogma.com>.
+
+	* function.c (func_lastword): Initialize p.
+
+	* doc/make.texi (Eval Function, Implicit Variables, Special Targets):
+	Doc fixes noticed by Bob <twobanjobob@sbcglobal.net>.  Patch from
+	Dave Korn <dave.korn@artimi.com>
+
+2007-05-08  Paul Smith  <psmith@gnu.org>
+
+	Fix Savannah bug #19656:
+
+	* configure.in: Check for strcasecmp(), strcmpi(), and stricmp().
+
+	* make.h: Change all case-insensitive string compares to use
+	strcasecmp() (from POSIX).  If we don't have that but do have one
+	of the others, define strcasecmp to be one of those instead.  If
+	we don't have any, declare a prototype for our own version.
+
+	* misc.c (strcasecmp): Use this if we can't find any native
+	case-insensitive string comparison function.
+	* vmsfunctions.c: Remove strcmpi(); we'll use misc.c:strcasecmp().
+	* main.c (find_and_set_default_shell): Use strcasecmp() instead of
+	strcmpi().
+	* job.c (_is_unixy_shell, construct_command_argv_internal): Use
+	strcasecmp() instead of stricmp().
+	* hash.h (ISTRING_COMPARE, return_ISTRING_COMPARE): Use strcasecmp()
+	instead of strcmpi().
+	* acinclude.m4: Remove the strcasecmp() check from here.
+
+2007-03-21  Paul Smith  <psmith@gnu.org>
+
+	* configure.in: Don't turn on case-insensitive file system support
+	if --disable-... is given.  Fixes Savannah bug #19348.
+
+2007-03-19  Paul Smith  <psmith@gnu.org>
+
+	* ALL: Use the strcache for all file name strings, or other
+	strings which we will never free.  The goal is to save memory by
+	avoiding duplicate copies of strings.  However, at the moment this
+	doesn't save much memory in most situations: due to secondary
+	expansion we actually save prerequisite lists twice (once before
+	the secondary expansion, and then again after it's been parsed
+	into individual file names in the dep list).  We will resolve this
+	in a future change, by doing the parsing up-front for targets
+	where secondary expansion is not set.
+
+	Moving things into the strcache also allows us to use const
+	pointers in many more places.
+
+2007-01-03  Paul Smith  <psmith@gnu.org>
+
+	* make.h (ENULLLOOP): Reset errno after each failed invocation of
+	the function, not just the first.  Fixes Savannah bug #18680.
+
+2006-11-18  Paul Smith  <psmith@gnu.org>
+
+	* strcache.c (strcache_add_len): Don't allocate a new buffer
+	unless the string is not already nil-terminated.  Technically this
+	is a violation of the standard, since we may be passed an array
+	that is not long enough to test one past.  However, in make this
+	is never true since we only use nil-terminated strings or
+	sub-strings thereof.
+
+	* read.c (eval, do_define): Use cmd_prefix instead of '\t'.
+
+	* main.c: New global cmd_prefix, defaults to '\t'.
+	* job.c (construct_command_argv_internal): Use cmd_prefix instead
+	of '\t'.
+
+	* dir.c: Constified.
+	(dir_contents_file_exists_p): Check for an error return	from
+	readdir(), just in case.
+
+	* commands.c: Constified.
+	* default.c: Constified.
+	* expand.c: Constified.
+	* function.c: Partial constification.
+	* variable.c: Partial constification.
+	* vmsify.c: Constification.  Hard to test this but I hope I didn't
+	screw it up!
+	* vpath.c: Partial constification.
+	* w32/pathstuff.c: Partial constification.
+
+2006-11-16  Eli Zaretskii  <eliz@gnu.org>
+
+	* main.c (main) [HAVE_DOS_PATHS]: Treat DOS style argv[0] with
+	backslashes and drive letters as absolute.
+
+2006-10-22  Paul Smith  <psmith@gnu.org>
+
+	* main.c (struct command_switch): Use const and void*.
+
+2006-10-21  Paul Smith  <psmith@gnu.org>
+
+	* ar.c: Constified.
+	* arscan.c: Constified.
+
+2006-09-30  Paul Smith  <psmith@gnu.org>
+
+	* doc/make.texi (MAKEFILE_LIST Variable): Modify reference to
+	point to lastword since the example was updated.
+	Fixes Savannah bug #16304.
+	(Secondary Expansion): Correct example description.
+	Fixes Savannah bug #16468.
+	(Makefile Contents): Clarify that comments cannot appear within
+	variable references or function calls.
+	Fixes Savannah bug #16577.
+	(Special Targets): Clarify how .NOTPARALLEL works in recursion.
+	Fixes Savannah bug #17701.
+	Reported by Ralf Wildenhues <Ralf.Wildenhues@gmx.de>:
+	(Prerequisite Types): Added an example of using	order-only
+	prerequisites.  Fixes Savannah bug #17880.
+	(Rule Syntax): "lise" -> "list"
+	(Multiple Rules): ... -> @dots{}
+	(Splitting Lines): ditto.
+
+	* remake.c (update_file_1): Prereqs that don't exist should be
+	considered changed, for the purposes of $?.
+	Fixes Savannah bug #16051.
+
+	* make.1: Remove extraneous "+".
+	Fixes Savannah bug #16652.
+
+2006-09-06  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Include sys/types.h when checking for sys/wait.h.
+
+2006-08-18  Eli Zaretskii  <eliz@gnu.org>
+
+	* configure.in (PATH_SEPARATOR_CHAR): Define to the value of
+	$PATH_SEPARATOR.
+
+	* make.h (PATH_SEPARATOR_CHAR): Define only if still undefined.
+	Normally, it is defined in config.h.
+
+	* config/dospaths.m4 <ac_cv_dos_paths>: Define to yes on Cygwin as
+	well.
+
+	* job.c (construct_command_argv_internal) [HAVE_DOS_PATHS]: Define
+	sh_chars_sh for Windows platforms that emulate Unix.
+
+2006-05-07  Paul D. Smith  <psmith@gnu.org>
+
+	* README.OS2.template: Updates provided by Andreas Buening
+	<andreas.buening@nexgo.de>.
+
+2006-04-30  Paul D. Smith  <psmith@gnu.org>
+
+	* make.h: Include <direct.h> if HAVE_DIRECT_H.
+	* config.h.W32.template (HAVE_DIRECT_H): Set it if it's available.
+
+2006-04-26  Paul D. Smith  <psmith@gnu.org>
+
+	* README.cvs: Add a reminder to notify the GNU translation robot.
+
+	* doc/make.texi: Change @direcategory (requested by Karl Berry).
+
+2006-04-20  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile (po-check): Use Perl instead of grep -E, for systems
+	that don't have extended grep.
+	(cvsclean): Use $(PERL) instead of perl.
+
+2006-04-09  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile: Add some extra warning options (GCC 4.1 only?)
+
+	* expand.c, implicit.c, main.c, read.c: Rename variables so that
+	inner-scope variables don't mask outer-scope variables.
+
+	* ar.c, arscan.c, commands.c, default.c, dir.c, expand.c, file.c:
+	* function.c, getloadavg.c, implicit.c, job.c, main.c, misc.c, read.c:
+	* remake.c, remote-cstms.c, rule.c, strcache.c, variable.c:
+	* vmsfunctions.c, vmsify.c, vpath.c: Remove all casts of returned
+	values from memory allocation functions: they return void* and so
+	don't need to be cast.  Also remove (char *) casts of arguments to
+	xrealloc().
+
+	* configure.in: Remove checks for memcpy/memmove/strchr.
+
+	* make.h: Remove bcmp/bcopy/bzero/strchr/strrchr macros.
+
+	* ar.c, arscan.c, commands.c, dir.c: Convert all bzero/bcopy/bcmp
+	calls to memset/memcpy/memmove/memcmp calls.
+	* expand.c, file.c, function.c, getloadavg.c, implicit.c: Ditto.
+	* job.c, main.c, misc.c, read.c, remake.c, rule.c: Ditto.
+	* variable.c, vpath.c: Ditto.
+
+	* make.h (EXIT_FAILURE): Should be 1, not 0.
+
+2006-04-06  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Removed AM_C_PROTOTYPES.  Starting now on we
+	require an ISO C 1989 standard compiler and runtime library.
+
+	* Makefile.am: Remove the ansi2knr feature.
+
+	* make.h: Remove the PARAMS() macro definition and all uses of it.
+
+	* amiga.h, ar.c, arscan.c: Remove all uses of the PARAMS() macro.
+	* commands.c, commands.h, config.h-vms.template: Ditto.
+	* dep.h, dir.c, expand.c, filedef.h, function.c: Ditto.
+	* implicit.c, job.c, job.h, main.c, read.c, remake.c: Ditto.
+	* rule.c, rule.h, variable.h, vmsdir.h, vmsjobs.c, vpath.c: Ditto.
+
+	* NEWS: Update.
+
+2006-04-01  Paul D. Smith  <psmith@gnu.org>
+
+	Version 3.81 released.
+
+	* NEWS: Updated for 3.81.
+
+	* README.cvs: Mention that vpath builds are not supported out of
+	CVS.  Fixes Savannah bug #16236.
+	Remove update of make.texi from the list of things to do; we use
+	version.texi now.
+
+2006-03-26  Paul D. Smith  <psmith@gnu.org>
+
+	* doc/make.texi: Clean up licensing.  Use @copying and version.texi
+	support from automake, as described in the Texinfo manual.
+
+2006-03-25  Eli Zaretskii  <eliz@gnu.org>
+
+	* implicit.c (pattern_search) [HAVE_DOS_PATHS]: Don't compare b
+	with lastslash, since the latter points to filename, not to
+	target.
+	* job.c (construct_command_argv_internal) [HAVE_DOS_PATHS]:
+	Declare and define sh_chars_sh[].
+
+2006-03-23  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Look for build.sh.in in $srcdir so it will be
+	built for remote configurations as well.
+
+	* Makefile.am: Make sure to clean up build.sh during distclean.
+	Fixes Savannah bug #16166.
+
+	* misc.c (log_access): Takes a const char *.
+	* function.c (fold_newlines): Takes an unsigned int *.
+	Both fixes for Savannah bug #16170.
+
+2006-03-22  Boris Kolpackov  <boris@kolpackov.net>
+
+	* implicit.c (pattern_search): Call set_file_variables only
+	if we have prerequisites that need second expansion. Fixes
+	Savannah bug #16140.
+
+2006-03-19  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_file): Add alloca(0) to clean up alloca'd
+	memory on hosts that don't support it directly.
+
+	* README.cvs: Add information on steps for making a release (to
+	make sure I don't forget any).
+
+	* main.c (clean_jobserver): Move jobserver cleanup code into a new
+	function.
+	(die): Cleanup code was removed from here; call the new function.
+	(main): If we are re-execing, clean up the jobserver first so we
+	don't leak file descriptors.
+	Reported by Craig Fithian <craig.fithian@citigroup.com>
+
+2006-03-17  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile (do-po-update): Rewrite this rule to clean up and
+	allow multiple concurrent runs.
+	Patch from Joseph Myers <joseph@codesourcery.com>
+
+2006-03-17  Boris Kolpackov  <boris@kolpackov.net>
+
+	* dep.h (struct dep): Add the stem field.
+	* misc.c (alloc_dep, free_dep): New functions.
+	(copy_dep_chain): Copy stem.
+	(free_dep_chain): Use free_dep.
+	* read.c (record_files): Store stem in the dependency line.
+	* file.c (expand_deps): Use stem stored in the dependency line. Use
+	free_dep_chain instead of free_ns_chain.
+	* implicit.c (pattern_search): Use alloc_dep and free_dep.
+	* read.c (read_all_makefiles, eval_makefile, eval): Ditto.
+	* main.c (main, handle_non_switch_argument): Ditto.
+	* remake.c (check_dep): Ditto.
+	* rule.c (convert_suffix_rule, freerule): Ditto.
+
+2006-03-14  Paul D. Smith  <psmith@gnu.org>
+
+	* expand.c (variable_append): Instead of appending everything then
+	expanding the result, we expand (or not, if it's simple) each part
+	as we add it.
+	(allocated_variable_append): Don't expand the final result.
+	Fixes Savannah bug #15913.
+
+2006-03-09  Paul Smith  <psmith@gnu.org>
+
+	* remake.c (update_file_1): Revert the change of 3 Jan 2006 which
+	listed non-existent files as changed.  Turns out there's a bug in
+	the Linux kernel builds which means that this change causes
+	everything to rebuild every time.  We will re-introduce this fix
+	in the next release, to give them time to fix their build system.
+	Fixes Savannah bug #16002.
+	Introduces Savannah bug #16051.
+
+	* implicit.c (pattern_search) [DOS_PATHS]: Look for DOS paths if
+	we *don't* find UNIX "/".
+	Reported by David Ergo <david.ergo@alterface.com>
+
+2006-03-04  Eli Zaretskii  <eliz@gnu.org>
+
+	* variable.c (do_variable_definition) [WINDOWS32]: Call the shell
+	locator function find_and_set_default_shell if SHELL came from the
+	command line.
+
+2006-02-20  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (merge_variable_set_lists): It's legal for *setlist0
+	to be null; don't core in that case.
+
+2006-02-19  Paul D. Smith  <psmith@gnu.org>
+
+	* commands.c (set_file_variables): Realloc, not malloc, the static
+	string values to avoid memory leaks.
+
+	* expand.c (recursively_expand_for_file): Only set reading_file to
+	an initialized value.
+
+	* implicit.c (pattern_search): We need to make a copy of the stem
+	if we get it from an intermediate dep, since those get freed.
+
+	* file.c (lookup_file) [VMS]: Don't lowercase special targets that
+	begin with ".".
+	(enter_file) [VMS]: Ditto.
+	Patch provided by Hartmut Becker <Hartmut.Becker@hp.com>.
+
+2006-02-24  Eli Zaretskii  <eliz@gnu.org>
+
+	* job.c (construct_command_argv_internal): Fix last change.
+
+	* w32/subproc/sub_proc.c (process_pipe_io): Make dwStdin,
+        dwStdout, and dwStderr unsigned int: avoids compiler warnings in
+        the calls to _beginthreadex.
+
+	* expand.c (recursively_expand_for_file): Initialize `save' to
+        prevent compiler warnings.
+
+2006-02-18  Eli Zaretskii  <eliz@gnu.org>
+
+        * job.c (construct_command_argv_internal): Don't create a temporary
+	script/batch file if we are under -n.  Call _setmode to switch the
+	script file stream to text mode.
+
+2006-02-17  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (merge_variable_set_lists): Don't try to merge the
+	global_setlist.  Not only is this useless, but it can lead to
+	circularities in the linked list, if global_setlist->next in one
+	list gets set to point to another list which also ends in
+	global_setlist.
+	Fixes Savannah bug #15757.
+
+2006-02-15  Paul D. Smith  <psmith@gnu.org>
+
+	Fix for Savannah bug #106.
+
+	* expand.c (expanding_var): Keep track of which variable we're
+	expanding.  If no variable is being expanded, it's the same as
+	reading_file.
+	* make.h (expanding_var): Declare it.
+	* expand.c (recursively_expand_for_file): Set expanding_var to the
+	current variable we're expanding, unless there's no file info in
+	it (could happen if it comes from the command line or a default
+	variable).  Restore it before we exit.
+	* expand.c (variable_expand_string): Use the expanding_var file
+	info instead of the reading_file info.
+	* function.c (check_numeric): Ditto.
+	(func_word): Ditto.
+	(func_wordlist): Ditto.
+	(func_error): Ditto.
+	(expand_builtin_function): Ditto.
+	(handle_function): Ditto.
+
+2006-02-14  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (eval): Even if the included filenames expands to the
+	empty string we still need to free the allocated buffer.
+
+	* implicit.c (pattern_search): If we allocated a variable set for
+	an impossible file, free it.
+	* variable.c (free_variable_set): New function.
+	* variable.h: Declare it.
+
+	* read.c (read_all_makefiles): Makefile names are kept in the
+	strcache, so there's never any need to alloc/free them.
+	(eval): Ditto.
+
+	* main.c (main): Add "archives" to the .FEATURES variable if
+	archive support is enabled.
+	* doc/make.texi (Special Variables): Document it.
+
+2006-02-13  Paul D. Smith  <psmith@gnu.org>
+
+	* implicit.c (pattern_search): Add checking for DOS pathnames to
+	the pattern rule target LASTSLASH manipulation.
+	Fixes Savannah bug #11183.
+
+2006-02-11  Paul D. Smith  <psmith@gnu.org>
+
+	* (ALL FILES): Updated copyright and license notices.
+
+2006-02-10  Paul D. Smith  <psmith@gnu.org>
+
+	A new internal capability: the string cache is a read-only cache
+	of strings, with a hash table interface for fast lookup.  Nothing
+	in the cache will ever be freed, so there's no need for reference
+	counting, etc.  This is the beginning of a full solution for
+	Savannah bug #15182, but for now we only store makefile names here.
+
+	* strcache.c: New file.  Implement a read-only string cache.
+	* make.h: Add prototypes for new functions.
+	* main.c (initialize_global_hash_tables): Initialize the string cache.
+	(print_data_base): Print string cache stats.
+	* read.c (eval_makefile): Use the string cache to store makefile
+	names.  Rewrite the string allocation to be sure we free everything.
+
+2006-02-10  Eli Zaretskii  <eliz@gnu.org>
+
+	* dir.c (dir_contents_file_exists_p): Don't opendir if the
+	directory time stamp didn't change, except on FAT filesystems.
+	Suggested by J. David Bryan <jdbryan@acm.org>.
+
+2006-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (func_or): Implement a short-circuiting OR function.
+	(func_and): Implement a short-circuiting AND function.
+	(function_table_init): Update the table with the new functions.
+	* doc/make.texi (Conditional Functions): Changed the "if" section
+	to one on general conditional functions.  Added documentation for
+	$(and ...) and $(or ...) functions.
+	* NEWS: Note new $(and ...) and $(or ...) functions.
+
+2006-02-08  Boris Kolpackov  <boris@kolpackov.net>
+
+	* job.h (struct child): Add the dontcare bitfield.
+	* job.c (new_job): Cache dontcare flag.
+	* job.c (reap_children): Use cached dontcare flag instead of the
+	one in struct file. Fixes Savannah bug #15641.
+
+2006-02-06  Paul D. Smith  <psmith@gnu.org>
+
+	* vpath.c (selective_vpath_search): If the file we find has a
+	timestamp from -o or -W, use that instead of the real time.
+	* remake.c (f_mtime): If the mtime is a special token from -o or
+	-W, don't overwrite it with the real mtime.
+	Fixes Savannah bug #15341.
+
+	Updates from Markus Mauhart <qwe123@chello.at>:
+
+	* w32/subproc/sub_proc.c (process_begin): Remove no-op tests.
+	(process_signal, process_last_err, process_exit_code): Manage
+	invalid handle values.
+	(process_{outbuf,errbuf,outcnt,errcnt,pipes}): Unused and don't
+	manage invalid handles; remove them.
+	* job.c (start_job_command) [WINDOWS32]: Jump out on error.
+	* config.h.W32.template [WINDOWS32]: Set flags for Windows builds.
+	* README.cvs: Updates for building from CVS.
+
+2006-02-05  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (enter_file): Keep track of the last double_colon entry,
+	to avoid walking the list every time we want to add a new one.
+	Fixes Savannah bug #15533.
+	* filedef.h (struct file): Add a new LAST pointer.
+
+	* dir.c (directory_contents_hash_cmp): Don't use subtraction to do
+	the comparison.  For 64-bits systems the result of the subtraction
+	might not fit into an int.  Use comparison instead.
+	Fixes Savannah bug #15534.
+
+	* doc/make.texi: Update the chapter on writing commands to reflect
+	the changes made in 3.81 for backslash/newline and SHELL handling.
+
+2006-02-01  Paul D. Smith  <psmith@gnu.org>
+
+	* dir.c (dir_contents_file_exists_p) [WINDOWS32]: Make sure
+	variable st is not used when it's not initialized.
+	Patch from Eli Zaretskii <eliz@gnu.org>.
+
+2006-01-31  Paul D. Smith  <psmith@gnu.org>
+
+	* README.W32.template: Applied patch #4785 from
+	Markus Mauhart <qwe123@chello.at>.
+	* README.cvs: Applied patch #4786 from
+	Markus Mauhart <qwe123@chello.at>.
+	* make_msvc_net2003.vcproj [WINDOWS32]: New version from
+	J. Grant <jg@jguk.org>.
+
+	* main.c: Update the copyright year in the version output.
+	* prepare_w32.bat: Remove this file from the distribution.
+
+2006-01-21  Eli Zaretskii  <eliz@gnu.org>
+
+	* remake.c (update_goal_chain): Set g->changed instead of
+	incrementing it, as it is only 8-bit wide, and could overflow if
+	many commands got started in update_file.
+
+	* w32/include/sub_proc.h: Add a prototype for process_used_slots.
+
+	* w32/subproc/sub_proc.c: Change dimension of proc_array[] to
+	MAXIMUM_WAIT_OBJECTS.
+	(process_wait_for_any_private): Change dimension of handles[]
+	array to MAXIMUM_WAIT_OBJECTS.
+	(process_used_slots): New function.
+	(process_register): Don't register more processes than the
+	available number of slots.
+	(process_easy): Don't start new processes if all slots are used	up.
+
+	* job.c (load_too_high, start_waiting_jobs) [WINDOWS32]: If there
+	are already more children than sub_proc.c can handle, behave as if
+	the load were too high.
+	(start_job_command): Fix a typo in error message when process_easy
+	fails.
+
+2006-01-14  Eli Zaretskii  <eliz@gnu.org>
+
+	* main.c (main) [WINDOWS32]: Don't refuse to run with -jN, even if
+	the shell is not sh.exe.
+
+	* job.c (create_batch_file): Renamed from create_batch_filename;
+	all callers changed.  Don't close the temporary file; return its
+	file descriptor instead.  New arg FD allows to return the file
+	descriptor.
+	(construct_command_argv_internal): Use _fdopen instead of fopen to
+	open the batch file.
+
+2006-01-04  Paul D. Smith  <psmith@gnu.org>
+
+	* readme.vms: Updates for case-insensitive VMS file systems from
+	Hartmut Becker <Hartmut.Becker@hp.com>.
+	* dir.c (vms_hash): Ditto.
+	* vmsify.c (copyto): Ditto.
+	* vmsfunctions.c (readdir): Ditto.
+
+	* make.1: Add a section on the exit codes for make.
+
+	* doc/make.texi: A number of minor updates to the documentation.
+
+2006-01-03  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_file_1): Mark a prerequisite changed if it
+	doesn't exist.
+
+	* read.c (eval): Be sure to strip off trailing whitespace from the
+	prerequisites list properly.  Also, initialize all fields in
+	struct dep when creating a new one.
+
+2005-12-28  Paul D. Smith  <psmith@gnu.org>
+
+	* config.h.W32.template [WINDOWS32]: Add in some pragmas to
+	disable warnings for MSC.
+	Patch by Rob Tulloh <rtulloh@yahoo.com>.
+
+2005-12-17  Eli Zaretskii  <eliz@gnu.org>
+
+	* doc/make.texi (Execution): Add a footnote about changes in
+	handling of backslash-newline sequences.  Mention the differences
+	on MS-DOS and MS-Windows.
+
+	* NEWS: More details about building the MinGW port and a pointer
+	to README.W32.  Fix the section name that describes the new
+	backward-incompatible processing of backslash-newline sequences.
+	The special processing of SHELL set to "cmd" is only relevant to
+	MS-Windows, not MS-DOS.
+
+2005-12-17  Eli Zaretskii  <eliz@gnu.org>
+
+	* main.c (handle_runtime_exceptions): Cast exrec->ExceptionAddress
+	to DWORD, to avoid compiler warnings.
+	* job.c (exec_command): Cast hWaitPID and hPID to DWORD, and
+	use %ld in format, to avoid compiler warnings.
+
+	* doc/make.texi (Special Targets): Fix a typo.
+	(Appending): Fix cross-reference to Setting.
+	(Special Variables, Secondary Expansion, File Name Functions)
+	(Flavor Function, Pattern Match, Quick Reference): Ensure two
+	periods after a sentence.
+	(Execution): Add @: after "e.g.".
+	(Environment): Fix punctuation.
+	(Target-specific, Call Function, Quick Reference): Add @: after "etc."
+	(Shell Function, Target-specific): Add @: after "vs."
+
+2005-12-14  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (record_target_var): Initialize variable's export field
+	with v_default instead of leaving it "initialized" by whatever
+	garbage happened to be on the heap.
+
+2005-12-12  Paul D. Smith  <psmith@gnu.org>
+
+	* make.1: Fix some display errors and document all existing options.
+	Patch provided by Mike Frysinger <vapier@gentoo.org>.
+
+2005-12-11  Paul D. Smith  <psmith@gnu.org>
+
+	* implicit.c (pattern_search): If 2nd expansion is not set for
+	this implicit rule, replace the pattern with the stem directly,
+	and don't re-expand the variable list.  Along with the other
+	.SECONDEXPANSION changes below, fixes bug #13781.
+
+2005-12-09  Boris Kolpackov  <boris@kolpackov.net>
+
+	* implicit.c (pattern_search): Mark other files that this rule
+	builds as targets so that they are not treated as intermediates
+	by the pattern rule search algorithm. Fixes bug #13022.
+
+2005-12-07  Boris Kolpackov  <boris@kolpackov.net>
+
+	* remake.c (notice_finished_file): Propagate the change of
+	modification time to all the double-colon entries only if
+	it is the last one to be updated. Fixes bug #14334.
+
+2005-11-17  Boris Kolpackov  <boris@kolpackov.net>
+
+	* function.c (func_flavor): Implement the flavor function which
+	returns the flavor of a variable.
+	* doc/make.texi (Functions for Transforming Text): Document it.
+	* NEWS: Add it to the list of new functions.
+
+2005-11-14  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (construct_include_path): Set the .INCLUDE_DIRS special
+	variable.
+	* doc/make.texi (Special Variables): Document .INCLUDE_DIRS.
+	* NEWS: Add .INCLUDE_DIRS to the list of new special variables.
+
+2005-10-26  Paul Smith  <psmith@gnu.org>
+
+	* read.c (record_files): Don't set deps flags if there are no deps.
+	* maintMakefile: We only need to build the templates when we are
+	creating a distribution, so don't do it for "all".
+
+2005-10-24  Paul D. Smith  <psmith@gnu.org>
+
+	Make secondary expansion optional: its enabled by declaring the
+	special target .SECONDEXPANSION.
+
+	* NEWS: Update information on second expansion capabilities.
+	* doc/make.texi (Secondary Expansion): Document the
+	.SECONDEXPANSION special target and its behavior.
+	* dep.h (struct dep): Add a flag STATICPATTERN, set to true if the
+	prerequisite list was found in a static pattern rule.
+	(free_dep_chain): Declare a prototype.
+	* file.c (parse_prereqs): New function: break out some complexity
+	from expand_deps().
+	(expand_deps): If we aren't doing second expansion, replace % with
+	the stem for static pattern rules.  Call the new function.
+	* filedef.h (parse_prereqs): Declare a prototype.
+	* implicit.c (pattern_search): Initialize the new staticpattern
+	field.
+	* main.c (second_expansion): Declare a global variable to remember
+	if the special target has been seen.  Initialize the new
+	staticpattern field for prerequisites.
+	* make.h: Extern for second_expansion.
+	* misc.c (free_dep_chain): New function: frees a struct dep list.
+	* read.c (read_all_makefiles): Initialize the staticpattern field.
+	(eval_makefile): Ditto.
+	(record_files): Check for the .SECONDEXPANSION target and set
+	second_expansion global if it's found.
+	Use the new free_dep_chain() instead of doing it by hand.
+	Set the staticpattern field for prereqs of static pattern targets.
+
+2005-10-16  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Set CURDIR to be a file variable instead of a
+	default, so that values of CURDIR inherited from the environment
+	won't override the make value.
+
+2005-09-26  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (construct_command_argv_internal): If the line is empty
+	remember to free the temporary argv strings.
+	Fixes bug # 14527.
+
+2005-09-16  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (start_job_command): The noerror flag is a boolean (single
+	bit); set it appropriately.
+	Reported by Mark Eichin <eichin@metacarta.com>
+
+2005-08-29  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (func_error): On Windows, output from $(info ...)
+	seems to come in the wrong order.  Try to force it with fflush().
+
+2005-08-10  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (record_files): Move code that sets stem for static
+	pattern rules out of the if (!two_colon) condition so it is
+	also executed for two-colon rules. Fixes Savannah bug #13881.
+
+2005-08-08  Paul D. Smith  <psmith@gnu.org>
+
+	* make.h: Don't test that __STDC__ is non-0.  Some compilers
+	(Windows for example) set it to 0 to denote "ISO C + extensions".
+	Fixes bug # 13594.
+
+2005-08-07  Paul D. Smith  <psmith@gnu.org>
+
+	* w32/pathstuff.c (getcwd_fs): Fix warning about assignment in a
+	conditional (slightly different version of a fix from Eli).
+
+	Fix a bug reported by Michael Matz <matz@suse.de>: patch included.
+	If make is running in parallel without -k and two jobs die in a
+	row, but not too close to each other, then make will quit without
+	waiting for the rest of the jobs to die.
+
+	* main.c (die): Don't reset err before calling reap_children() the
+	second time: we still want it to be in the error condition.
+	* job.c (reap_children): Use a static variable, rather than err,
+	to control whether or not the error message should be printed.
+
+2005-08-06  Eli Zaretskii  <eliz@gnu.org>
+
+	* w32/subproc/sub_proc.c: Include signal.h.
+	(process_pipe_io, process_file_io): Pass a pointer to a local
+	DWORD variable to GetExitCodeProcess.  If the exit code is
+	CONTROL_C_EXIT, put SIGINT into pproc->signal.
+
+	* job.c [WINDOWS32]: Include windows.h.
+	(main_thread) [WINDOWS32]: New global variable.
+	(reap_children) [WINDOWS32]: Get the handle for the main thread
+	and store it in main_thread.
+
+	* commands.c [WINDOWS32]: Include windows.h and w32err.h.
+	(fatal_error_signal) [WINDOWS32]: Suspend the main thread before
+	doing anything else.  When we are done, close the main thread
+	handle and exit with status 130.
+
+2005-07-30  Eli Zaretskii  <eliz@gnu.org>
+
+	* w32/subproc/sub_proc.c (process_begin): Don't pass a NULL
+	pointer to fprintf.
+
+	* main.c (find_and_set_default_shell): If found a DOSish shell,
+	set sh_found and the value of default_shell, and report the
+	findings in debug mode.
+
+	* job.c (construct_command_argv_internal): Check unixy_shell, not
+	no_default_sh_exe, to decide whether to use Unixy or DOSish
+	builtin commands.
+
+	* README.W32: Update with info about the MinGW build.
+
+	* build_w32.bat: Support MinGW.
+
+	* w32/subproc/build.bat: Likewise.
+
+	* w32/subproc/sub_proc.c (process_easy): Fix format strings for
+	printing DWORD args.
+
+	* function.c (windows32_openpipe): Fix format strings for printing
+	DWORD args.
+
+	* job.c (reap_children) [WINDOWS32]: Don't declare 'status' and
+	'reap_mode'.
+	(start_job_command): Fix format string for printing the result of
+	process_easy.
+	(start_job_command) [WINDOWS32]: Do not define.
+	(exec_command): Fix format string for printing HANDLE args.
+
+	* main.c (handle_runtime_exceptions): Fix sprintf format strings
+	to avoid compiler warnings.
+	(open_tmpfile): Declare fd only if HAVE_FDOPEN is defined.
+	(Note: some of these fixes were submitted independently by J. Grant)
+
+2005-07-30  J. Grant <jg@jguk.org>
+
+	* prepare_w32.bat: Copy config.h.w32 to config.h if not exist.
+	* make_msvc_net2003.vcproj, make_msvc_net2003.sln: MSVC Project files.
+	* Makefile.am (EXTRA_DIST): Add MSVC Project files.
+
+2005-07-15  Paul Smith  <psmith@gnu.org>
+
+	* job.c (construct_command_argv_internal) [DOS,WINDOWS32,OS/2]: If
+	we don't have a POSIX shell, then revert to the old
+	backslash-newline behavior (where they are stripped).
+	Fixes bug #13665.
+
+2005-07-08  Paul D. Smith  <psmith@gnu.org>
+
+	* config.h.W32.template: Reorder to match the standard config.h,
+	for easier comparisons.
+	From J. Grant <jg@jguk.org>
+
+	* maintMakefile: Remove .dep_segment before overwriting it, in
+	case it's not writable or noclobber is set.
+	* expand.c (variable_expand_string): Cast result of pointer
+	arithmetic to avoid a warning.
+	* main.c (switches): Add full-fledged final initializer.
+
+2005-07-06  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: IRIX has _sys_siglist.  Tru64 UNIX has __sys_siglist.
+	* signame.c (strsignal): If we found _sys_siglist[] or
+	__sys_siglist[] use those instead of sys_siglist[].
+	From Albert Chin <china@thewrittenword.com>
+
+2005-07-04  Paul D. Smith  <psmith@gnu.org>
+
+	* config.h-vms.template [VMS]: Latest VMS has its own glob() and
+	globfree(); set up to use the GNU versions.
+	From Martin Zinser <zinser@zinser.no-ip.info>
+
+2005-07-03  Paul D. Smith  <psmith@gnu.org>
+
+	From J. Grant <jg@jguk.org>:
+
+	* README.W32.template: Update the Windows and tested MSVC versions.
+	* NMakefile.template (CFLAGS_any): Change warning level from W3 to W4.
+	* w32/subproc/NMakefile (CFLAGS_any): Ditto.
+	* build_w32.bat: Ditto.
+	* w32/subproc/build.bat: Ditto.
+
+2005-06-28  Paul D. Smith  <psmith@gnu.org>
+
+	* signame.c: HAVE_DECL_* macros are set to 0, not undef, if the
+	declaration was checked but not present.
+
+2005-06-27  Paul D. Smith  <psmith@gnu.org>
+
+	* dir.c (find_directory): Change type of fs_serno/fs_flags/fs_len
+	to unsigned long.  Fixes Savannah bug #13550.
+
+	* w32/subproc/sub_proc.c: Remove (HANDLE) casts on lvalues.
+	(process_pipe_io): Initialize tStdin/tStdout/tStderr variables.
+	Fixes Savannah bug #13551.
+
+2005-06-26  Paul D. Smith  <psmith@gnu.org>
+
+	* make.h: Fix bug in ANSI_STRING/strerror() handling; only define
+	it if ANSI_STRING is not set.
+
+2005-06-25  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (eval): If no filenames are passed to any of the
+	"include" variants, don't print an error.
+	* doc/make.texi (Include): Document this.
+	Fixes Savannah bug #1761.
+
+	* job.c (construct_command_argv_internal): Sanitize handling of
+	backslash/newline pairs according to POSIX: that is, keep the
+	backslash-newline in the command script, but remove a following
+	TAB character, if present.  In the fast path, make sure that the
+	behavior matches what the shell would do both inside and outside
+	of quotes.  In the slow path, quote the backslash and put a
+	literal newline in the string.
+	Fixes Savannah bug #1332.
+	* doc/make.texi (Execution): Document the new behavior and give
+	some examples.
+	* NEWS: Make a note of the new behavior.
+
+	* make.h [WINDOWS32]: #include <direct.h>.
+	Fixes Savannah bug #13478.
+
+	* remake.c (name_mtime): If the stat() of a file fails and the -L
+	option was given and the file is a symlink, take the best mtime of
+	the symlink we can get as the mtime of the file and don't fail.
+	Fixes Savannah bug #13280.
+
+	* read.c (find_char_unquote): Accept a new argument IGNOREVARS.
+	If it's set, then don't	stop on STOPCHARs or BLANKs if they're
+	inside a variable reference.  Make this function static as it's
+	only used here.
+	(eval): Call find_char_unquote() with IGNOREVARS set when we're
+	parsing an unexpanded line looking for semicolons.
+	Fixes Savannah bug #1454.
+	* misc.c (remove_comments): Move this to read.c and make it static
+	as it's only used there.  Call find_char_unquote() with new arg.
+	* make.h: Remove prototypes for find_char_unquote() and
+	remove_comments() since they're static now.
+
+	* main.c (main): If we see MAKE_RESTARTS in the environment, unset
+	its export flag and obtain its value.  When we need to re-exec,
+	increment the value and add it into the environment.
+	* doc/make.texi (Special Variables): Document MAKE_RESTARTS.
+	* NEWS: Mention MAKE_RESTARTS.
+	* main.c (always_make_set): New variable.  Change the -B option to
+	set this one instead.
+	(main): When checking makefiles, only set always_make_flag if
+	always_make_set is set AND the restarts flag is 0.  When building
+	normal targets, set it IFF always_make_set is set.
+	(main): Avoid infinite recursion with -W, too: only set what-if
+	files to NEW before we check makefiles if we've never restarted
+	before.  If we have restarted, set what-if files to NEW _after_ we
+	check makefiles.
+	Fixes Savannah bug #7566:
+
+2005-06-17  Paul D. Smith  <psmith@gnu.org>
+
+	* default.c: Change VMS implicit rules to use $$$$ instead of $$
+	in the prerequisites list.
+
+2005-06-12  Paul D. Smith  <psmith@gnu.org>
+
+	Fix Savannah bug # 1328.
+
+	* configure.in: Check for atexit().
+	* misc.c (close_stdout): Test stdout to see if writes to it have
+	failed.  If so, be sure to exit with a non-0 error code.  Based on
+	code found in gnulib.
+	* make.h: Prototype.
+	* main.c (main): Install close_stdout() with atexit().
+
+2005-06-10  Paul D. Smith  <psmith@gnu.org>
+
+	VMS build updates from Hartmut Becker <Hartmut.Becker@hp.com>:
+
+	* vmsjobs.c [VMS]: Updates to compile on VMS: add some missing
+	headers; make vmsWaitForChildren() static; extern vmsify().
+	* job.c [VMS]: Move vmsWaitForChildren() prototype to be global.
+	Don't create child_execute_job() here (it's in vmsjobs.c).
+	* makefile.vms (job.obj) [VMS]: Add vmsjobs.c as a prerequisite.
+
+2005-06-09  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (push_new_variable_scope): File variables point
+	directly to the global_setlist variable.  So, inserting a new
+	scope in front of that has no effect on those variables: they
+	don't go through current_variable_set_list.  If we're pushing a
+	scope and the current scope is global, push it "the other way" so
+	that the new setlist is in the global_setlist variable, and
+	next points to a new setlist with the global variable set.
+	(pop_variable_scope): Properly undo a push with the new
+	semantics.
+	Fixes Savannah bug #11913.
+
+2005-05-31  Boris Kolpackov  <boris@kolpackov.net>
+
+	* job.c (reap_children): Don't die of the command failed but
+	the dontcare flag is set. Fixes Savannah bug #13216.
+
+	* implicit.c (pattern_search): When creating a target from
+	an implicit rule match, lookup pattern target and set precious
+	flag in a newly created target. Fixes Savannah bug #13218.
+
+2005-05-13  Paul D. Smith  <psmith@gnu.org>
+
+	Implement "if... else if... endif" syntax.
+
+	* read.c (eval): Push all checks for conditional words ("ifeq",
+	"else", etc.) down into the conditional_line() function.
+	(conditional_line): Rework to allow "else if..." clause.  New
+	return value -2 for lines which are not conditionals.  The
+	ignoring flag can now also be 2, which means "already parsed a
+	true branch".  If that value is seen no other branch of this
+	conditional can be considered true.  In the else parsing if there
+	is extra text after the else, invoke conditional_line()
+	recursively to see if it's another conditional.  If not, it's an
+	error.  If so, raise the conditional value to this level instead
+	of creating a new conditional nesting level.  Special check for
+	"else" and "endif", which aren't allowed on the "else" line.
+	* doc/make.texi (Conditional Syntax): Document the new syntax.
+
+2005-05-09  Paul D. Smith  <psmith@gnu.org>
+
+	* Makefile.am (EXTRA_make_SOURCES): Add vmsjobs.c
+	(MAYBE_W32): Rework how SUBDIRS are handled so that "make dist"
+	recurses to the w32 directory, even on non-Windows systems.  Use
+	the method suggested in the automake manual.
+	* configure.in: Add w32/Makefile to AC_CONFIG_FILES.
+	* maintMakefile (gnulib-url): They moved the texinfo.tex files.
+
+2005-05-07  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (die): If we're dying with a fatal error (not that a
+	command has failed), write back any leftover tokens before we go.
+
+	* job.c (set_child_handler_action_flags): If there are jobs
+	waiting for the load to go down, set an alarm to go off in 1
+	second.  This allows us to wake up from a potentially long-lasting
+	read() and start a new job if the load has gone down.  Turn it off
+	after the read.
+	(job_noop): Dummy signal handler function.
+	(new_job): Invoke it with the new semantics.
+
+	* docs/make.texi: Document secondary expansion.  Various cleanups
+	and random work.
+
+2005-05-03  Paul D. Smith  <psmith@gnu.org>
+
+	Rename .DEFAULT_TARGET to .DEFAULT_GOAL: in GNU make terminology
+	the targets which are to ultimately be made are called "goals";
+	see the GNU make manual.  Also, MAKECMDGOALS, etc.
+
+	* filedef.h, read.c, main.c: Change .DEFAULT_TARGET to
+	.DEFAULT_GOAL, and default_target_name to default_goal_name.
+	* doc/make.texi (Special Variables): Document .DEFAULT_GOAL.
+
+2005-05-02  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c, vmsjobs.c (vmsWaitForChildren, vms_redirect,
+	vms_handle_apos, vmsHandleChildTerm, reEnableAst, astHandler,
+	tryToSetupYAst, child_execute_job) [VMS]: Move VMS-specific
+	functions to vmsjobs.c.  #include it into jobs.c.
+
+	Grant Taylor <gtaylor@picante.com> reports that -j# can lose
+	jobserver tokens.  I found that this happens when an exported
+	recursive variable contains a $(shell ...) function reference: in
+	this situation we could "forget" to write back a token.
+
+	* job.c, job.h: Add variable jobserver_tokens: counts the tokens
+	we have.  It's not reliable to depend on the number of children in
+	our linked list so keep a separate count.
+	(new_job): Check jobserver_tokens rather than children &&
+	waiting_jobs.  Increment jobserver_tokens when we get one.
+	(free_child): If jobserver_tokens is 0, internal error.  If it's
+	>1, write a token back to the jobserver pipe (we don't write a
+	token for the "free" job).  Decrement jobserver_tokens.
+
+	* main.c: Add variable master_job_slots.
+	(main): Set it to hold the number of jobs requested if we're the
+	master process, when using the jobserver.
+	(die): Sanity checks: first test jobserver_tokens to make sure
+	this process isn't holding any tokens we didn't write back.
+	Second, if master_job_slots is set count the tokens left in the
+	jobserver pipe and ensure it's the same as master_job_slots (- 1).
+
+2005-04-24  Paul D. Smith  <psmith@gnu.org>
+
+	Grant Taylor <gtaylor@picante.com> reports that -j# in conjunction
+	with -l# can lose jobserver tokens, because waiting jobs are not
+	consulted properly when checking for the "free" token.
+
+	* job.c (free_child): Count waiting_jobs as having tokens.
+	* job.c (new_job): Ditto.  Plus, call start_waiting_jobs() here to
+	handle jobs waiting for the load to drop.
+
+2005-04-23  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Be careful to not core if a variable setting in
+	the environment doesn't contain an '='.  This is illegal but can
+	happen in broken setups.
+	Reported by Joerg Schilling <schilling@fokus.fraunhofer.de>.
+
+2005-04-12  Paul D. Smith  <psmith@gnu.org>
+
+	The second expansion feature causes significant slowdown.  Timing
+	a complex makefile (GCC 4.1) shows a slowdown from .25s to just
+	read the makefile before the feature, to 11+s to do the same
+	operations after the feature.  Additionally, memory usage
+	increased drastically.  To fix this I added some intelligence that
+	avoids the overhead of the second expansion unless it's required.
+
+	* dep.h: Add a new boolean field, need_2nd_expansion.
+
+	* read.c (eval): When creating the struct dep for the target,
+	check if the name contains a "$"; if so set need_2nd_expansion to 1.
+	(record_files): If there's a "%" in a static pattern rule, it gets
+	converted to "$*" so set need_2nd_expansion to 1.
+
+	* file.c (expand_deps): Rework to be more efficient.  Only perform
+	initialize_file_variables(), set_file_variables(), and
+	variable_expand_for_file() if the need_2nd_expansion is set.
+
+	* implicit.c (pattern_search): Default need_2nd_expansion to 0.
+	(pattern_search): Ditto.
+	* main.c (handle_non_switch_argument): Ditto.
+	(main): Ditto.
+	* read.c (read_all_makefiles): Ditto.
+	(eval_makefile): Ditto.
+
+2005-04-07  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main) [WINDOWS32]: Export PATH to sub-shells, not Path.
+	* variable.c (sync_Path_environment): Ditto.
+	Patch by Alessandro Vesely.  Fixes Savannah bug #12209.
+
+	* main.c (main): Define the .FEATURES variable.
+	* NEWS: Announce .FEATURES.
+	* doc/make.texi (Special Variables): Document .FEATURES.
+
+	* remake.c (check_dep): If a file is .PHONY, update it even if
+	it's marked intermediate.  Fixes Savannah bug #12331.
+
+2005-03-15  Boris Kolpackov  <boris@kolpackov.net>
+
+	* file.c (expand_deps): Factor out the second expansion and
+	prerequisite line parsing logic from snap_deps().
+
+	* file.c (snap_deps): Use expand_deps(). Expand and parse
+	prerequisites of the .SUFFIXES special target first. Fixes
+	Savannah bug #12320.
+
+2005-03-13  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main) [MSDOS]: Export SHELL in MSDOS.  Requested by Eli
+	Zaretskii.
+
+2005-03-11  Paul D. Smith  <psmith@gnu.org>
+
+	* signame.c (strsignal): HAVE_DECL_SYS_SIGLIST is 0 when not
+	available, not undefined (from Earnie Boyd).
+
+2005-03-10  Boris Kolpackov  <boris@kolpackov.net>
+
+	* implicit.c (pattern_search): Mark an intermediate target as
+	precious if it happened to be a prerequisite of some (other)
+	target. Fixes Savannah bug #12267.
+
+2005-03-09  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (eval_makefile): Add alloca(0).
+	(eval_buffer): Ditto.
+
+2005-03-09  Boris Kolpackov  <boris@kolpackov.net>
+
+	* main.c (main): Use o_file instead of o_default when defining
+	the .DEFAULT_TARGET special variable.
+	* read.c (eval): Use define_variable_global() instead of
+	define_variable() when setting new value for the .DEFAULT_TARGET
+	special variable.  Fixes Savannah bug #12266.
+
+2005-03-04  Boris Kolpackov  <boris@kolpackov.net>
+
+	* imlicit.c (pattern_search): Mark files for which an implicit
+	rule has been found as targets. Fixes Savannah bug #12202.
+
+2005-03-04  Paul D. Smith  <psmith@gnu.org>
+
+	* AUTHORS: Update.
+	* doc/make.texi (Automatic Variables): Document $|.
+
+2005-03-03  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (record_files): Instead of substituting % with
+	actual stem value in dependency list replace it with $*.
+	This fixes stem triple expansion bug.
+
+	* implicit.c (pattern_search): Copy stem to a separate
+	buffer and make it a properly terminated string. Assign
+	this buffer instead of STEM (which is not terminated) to
+	f->stem. Instead of substituting % with actual stem value
+	in dependency list replace it with $*. This fixes stem
+	triple expansion bug.
+
+2005-03-01  Paul D. Smith  <psmith@gnu.org>
+
+	* commands.c (fatal_error_signal) [WINDOWS32]: Don't call kill()
+	on Windows, as it takes a handle not a pid.  Just exit.
+	Fix from patch #3679, provided by Alessandro Vesely.
+
+	* configure.in: Update check for sys_siglist[] from autoconf manual.
+	* signame.c (strsignal): Update to use the new autoconf macro.
+
+2005-03-01  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (record_files): Add a check for the list of prerequisites
+	of a static pattern rule being empty. Fixes Savannah bug #12180.
+
+2005-02-28  Paul D. Smith  <psmith@gnu.org>
+
+	* doc/make.texi (Text Functions): Update docs to allow the end
+	ordinal for $(wordlist ...) to be 0.
+	* function.c (func_wordlist): Fail if the start ordinal for
+	$(wordlist ...) is <1.  Matches documentation.
+	Resolves Savannah support request #103195.
+
+	* remake.c (update_goal_chain): Fix logic for stopping in -q:
+	previously we were stopping when !-q, exactly the opposite.  This
+	has been wrong since version 1.34, in 1994!
+	(update_file): If we got an error don't break out to run more
+	double-colon rules: just return immediately.
+	Fixes Savannah bug #7144.
+
+2005-02-27  Paul D. Smith  <psmith@gnu.org>
+
+	* misc.c (end_of_token): Make argument const.
+	* make.h: Update prototype.
+
+	* function.c (abspath, func_realpath, func_abspath): Use
+	PATH_VAR() and GET_PATH_MAX instead of PATH_MAX.
+	* dir.c (downcase): Use PATH_VAR() instead of PATH_MAX.
+	* read.c (record_files): Ditto.
+	* variable.c (do_variable_definition): Ditto.
+
+	* function.c (func_error): Create a new function $(info ...) that
+	simply prints the message to stdout with no extras.
+	(function_table_init): Add new function to the table.
+	* NEWS: Add $(info ...) reference.
+	* doc/make.texi (Make Control Functions): Document it.
+
+	New feature: if the system supports symbolic links, and the user
+	provides the -L/--check-symlink-time flag, then use the latest
+	mtime between the symlink(s) and the target file.
+
+	* configure.in (MAKE_SYMLINKS): Check for lstat() and
+	readlink().  If both are available, define MAKE_SYMLINKS.
+	* main.c: New variable: check_symlink_flag.
+	(usage): Add a line for -L/--check-symlink-times to the help string.
+	(switches): Add -L/--check-symlink-times command line argument.
+	(main): If MAKE_SYMLINKS is not defined but the user specified -L,
+	print a warning and disable it again.
+	* make.h: Declare check_symlink_flag.
+	* remake.c (name_mtime): If MAKE_SYMLINKS and check_symlink_flag,
+	if the file is a symlink then check each link in the chain and
+	choose the NEWEST mtime we find as the mtime for the file.  The
+	newest mtime might be the file itself!
+	* NEWS: Add information about this new feature.
+	* doc/make.texi (Options Summary): Add -L/--check-symlink-times docs.
+
+	Avoid core dumps described in Savannah bug # 12124:
+
+	* file.c: New variable snapped_deps remember whether we've run
+	snap_deps().
+	(snap_deps): Set it.
+	* filedef.h: Extern it.
+	* read.c (record_files): Check snapped_deps; if it's set then
+	we're trying to eval a new target/prerequisite relationship from
+	within a command script, which we don't support.  Fatal.
+
+2005-02-28  Boris Kolpackov  <boris@kolpackov.net>
+
+	Implementation of the .DEFAULT_TARGET special variable.
+
+	* read.c (eval): If necessary, update default_target_name when
+	reading rules.
+	* read.c (record_files): Update default_target_file if
+	default_target_name has changed.
+	* main.c (default_target_name): Define.
+	* main.c (main): Enter .DEFAULT_TARGET as make variable. If
+	default_target_name is set use default_target_file as a root
+	target to make.
+	* filedef.h (default_target_name): Declare.
+	* dep.h (free_dep_chain):
+	* misc.c (free_dep_chain): Change to operate on struct nameseq
+	and change name to free_ns_chain.
+	* file.c (snap_deps): Update to use free_ns_chain.
+
+2005-02-27  Boris Kolpackov  <boris@kolpackov.net>
+
+	Implementation of the second expansion in explicit rules,
+	static pattern rules and implicit rules.
+
+	* read.c (eval): Refrain from chopping up rule's dependencies.
+	Store them in a struct dep as a single dependency line. Remove
+	the code that implements SySV-style automatic variables.
+
+	* read.c (record_files): Adjust the code that handles static
+	pattern rules to expand all percents instead of only the first
+	one. Reverse the order in which dependencies are stored so that
+	when the second expansion reverses them again they appear in
+	the makefile order (with some exceptions, see comments in
+	the code). Remove the code that implements SySV-style automatic
+	variables.
+
+	* file.c (snap_deps): Implement the second expansion and chopping
+	of dependency lines for explicit rules.
+
+	* implicit.c (struct idep): Define an auxiliary data type to hold
+	implicit rule's dependencies after stem substitution and
+	expansion.
+
+	* implicit.c (free_idep_chain): Implement.
+
+	* implicit.c (get_next_word): Implement helper function for
+	parsing implicit rule's dependency lines into words taking
+	into account variable expansion requests. Used in the stem
+	splitting code.
+
+	* implicit.c (pattern_search): Implement the second expansion
+	for implicit rules. Also fixes bug #12091.
+
+	* commands.h (set_file_variables): Declare.
+	* commands.c (set_file_variables): Remove static specifier.
+
+	* dep.h (free_dep_chain): Declare.
+	* misc.c (free_dep_chain): Implement.
+
+	* variable.h (variable_expand_for_file): Declare.
+	* expand.c (variable_expand_for_file): Remove static specifier.
+
+	* make.h (strip_whitespace): Declare.
+	* function.c (strip_whitespace): Remove static specifier.
+
+2005-02-26  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Check for ferror() when reading makefiles from stdin.
+	Apparently some shells in Windows don't close pipes properly and
+	require this check.
+
+2005-02-24  Jonathan Grant  <jg@jguk.org>
+
+	* configure.in: Add MinGW configuration options, and extra w32 code
+	directory.
+	* Makefile.am: Add MinGW configuration options, and extra w32 code
+	directory.
+	* main.c: Determine correct program string (after last \ without .exe).
+	* subproc/sub_proc.c: `GetExitCodeProcess' from incompatible pointer
+	type fix x2
+	* w32/Makefile.am: Import to build win32 lib of sub_proc etc.
+	* subproc/w32err.c: MSVC thread directive not applied to MinGW builds.
+	* tests/run_make_tests.pl, tests/test_driver.pl: MSYS testing
+	environment support.
+
+2004-04-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* function.c (func_shell): When initializing error_prefix, check
+	that reading file name is not null.  This fixes long-standing
+	segfault in cases like "make 'a1=$(shell :)' 'a2:=$(a1)'".
+
+2005-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile: Update the CVS download URL to simplify them.
+	Also, the ftp://ftp.gnu.org/GNUinfo site was removed so I'm
+	downloading the .texi files from Savannah now.
+
+	Fixed these issues reported by Markus Mauhart <qwe123@chello.at>:
+
+	* main.c (handle_non_switch_argument): Only add variables to
+	command_variables if they're not already there: duplicate settings
+	waste space and can be confusing to read.
+
+	* w32/include/sub_proc.h: Remove WINDOWS32.  It's not needed since
+	this header is never included by non-WINDOWS32 code, and it
+	requires <config.h> to define which isn't always included first.
+
+	* dir.c (read_dirstream) [MINGW]: Use proper macro names when
+	testing MINGW32 versions.
+
+	* main.c (log_working_directory): flush stdout to be sure the WD
+	change is printed before any stderr messages show up.
+
+2005-02-01  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile (po_repo): Update the GNU translation site URL.
+
+2004-12-01  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Change char* env_shell to struct variable shell_var.
+	* variable.c (target_environment): Use new shell_var.
+
+2004-11-30  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: The old way we avoided creating build.sh from
+	build.sh.in before build.sh.in exists doesn't work anymore; we
+	have to use raw M4 (thanks to Andreas Schwab <schwab@suse.de> for
+	the help!).  This also keeps automake from complaining.
+	* Makefile.am (README): Add a dummy target so automake won't
+	complain that this file doesn't exist when we checkout from CVS.
+	* maintMakefile (.dep_segment): Rewrite this rule since newer
+	versions of automake don't provide DEP_FILES.
+
+2004-11-30  Boris Kolpackov  <boris@kolpackov.net>
+
+	Implementation of `realpath' and `abspath' built-in functions.
+
+	* configure.in: Check for realpath.
+	* function.c (abspath): Return an absolute file name that does
+	not contain any `.' or `..' components, nor repeated `/'.
+	* function.c (func_abspath): For each name call abspath.
+	* function.c (func_realpath): For each name call realpath
+	from libc or delegate to abspath if realpath is not available.
+	* doc/make.texi (Functions for File Names): Document new functions.
+	* doc/make.texi (Quick Reference): Ditto.
+
+2004-11-28  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main) [WINDOWS32]: Remove any trailing slashes from -C
+	arguments.  Fixes bug #10252.
+
+	Fix for bug #1276: Handle SHELL according to POSIX requirements.
+
+	* main.c (main): Set SHELL to v_noexport by default.  Remember the
+	original environment setting of SHELL in the env_shell variable.
+	* main.h: Export new env_shell variable.
+	* variable.c (target_environment): If we find a v_noexport
+	variable for SHELL, add a SHELL variable with the env_shell value.
+	* doc/make.texi (Quick Reference): Document the POSIX behavior.
+	* doc/make.texi (Variables/Recursion): Ditto.
+
+2004-11-28  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (find_and_set_default_shell) [WINDOWS32]: check for
+	equality of "cmd"/"cmd.exe", not inequality.  Fixes bug #11155.
+	Patch by Alessandro Vesely.
+
+2004-11-12  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (child_execute_job) [VMS]: Don't treat "#" as a comment on
+	the command line if it's inside a string.
+	Patch by: Hartmut Becker <Hartmut.Becker@hp.com>
+
+2004-10-21  Boris Kolpackov  <boris@kolpackov.net>
+
+	* function.c (func_lastword): New function: return last word
+	from the list of words.
+	* doc/make.texi: Document $(lastword ). Fix broken links in
+	Quick Reference section.
+
+2004-10-06  Paul D. Smith  <psmith@gnu.org>
+
+	Apply patch from Alessandro Vesely, provided with bug # 9748.
+	Fix use of tmpnam() to work with Borland C.
+
+	* job.c (construct_command_argv_internal) [WINDOWS32]: Remove
+	construction of a temporary filename, and call new function
+	create_batch_filename().
+	(create_batch_filename) [WINDOWS32]: New function to create a
+	temporary filename.
+
+2004-10-05  Boris Kolpackov  <boris@kolpackov.net>
+
+	* read.c (record_target_var): Expand simple pattern-specific
+	variable.
+	* variable.c (initialize_file_variables): Do not expand simple
+	pattern-specific variable.
+
+2004-09-28  Boris Kolpackov  <boris@kolpackov.net>
+
+	* remake.c (update_file_1): When rebuilding makefiles inherit
+	dontcare flag from a target that triggered update.
+
+2004-09-27  Boris Kolpackov  <boris@kolpackov.net>
+
+	* variable.c (initialize_file_variables): Mark pattern-specific
+	variable as a per-target and copy export status.
+
+2004-09-21  Boris Kolpackov  <boris@kolpackov.net>
+
+	* file.c (snap_deps): Mark .PHONY prerequisites as targets.
+
+	* implicit.c (pattern_search): When considering an implicit rule's
+	prerequisite check that it is actually a target rather then
+	just an entry in the file hashtable.
+
+2004-09-21  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (readstring): Fix some logic errors in backslash handling.
+	(eval): Remove some unnecessary processing in buffer handling.
+	(record_target_var): Assert that parse_variable_definition() succeeded.
+	Reported by: Markus Mauhart <qwe123@chello.at>.
+
+	* misc.c: Removed the sindex() function.  All instances of this
+	function were trivially replaceable by the standard strstr()
+	function, and that function will always have better (or certainly
+	no worse) performance than the very simple-minded algorithm
+	sindex() used.  This can matter with complex makefiles.
+	* make.h: Remove the prototype for sindex().
+	* function.c (subst_expand): Convert sindex() call to strstr().
+	This means we no longer need to track the TLEN value so remove that.
+	(func_findstring): Convert sindex() to strstr().
+	* commands.c (chop_commands): Convert sindex() calls to strstr().
+	Suggested by: Markus Mauhart <qwe123@chello.at>.
+
+	* main.c (find_and_set_default_shell) [WINDOWS32]: Implement the
+	idea behind Savannah Patch #3144 from david.baird@homemail.com.
+	If SHELL is set to CMD.EXE then assume it's batch-mode and
+	non-unixy.  I wrote the code differently from the patch, though,
+	to make it safer.  This also resolves bug #9174.
+
+2004-09-20  Paul D. Smith  <psmith@gnu.org>
+
+	* expand.c (variable_expand_string): Modify to invoke
+	patsubst_expand() instead of subst_expand(); the latter didn't
+	handle suffix patterns correctly.
+	* function.c (subst_expand): Remove the SUFFIX_ONLY parameter; it
+	was used only from variable_expand_string() and is no longer used
+	there.
+	(func_subst): Ditto, on call to subst_expand().
+	(patsubst_expand): Require the percent pointers to point to the
+	character after the %, not to the % itself.
+	* read.c (record_files): New call criteria for patsubst_expand().
+	* variable.h: Remove SUFFIX_ONLY from subst_expand() prototype.
+	This is to fix a bug reported by Markus Mauhart <qwe123@chello.at>.
+
+2004-09-19  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (subst_expand): Fix a check in by_word: look for a
+	previous blank if we're beyond the beginning of the string, not
+	the beginning of the word.
+	Bugs reported by Markus Mauhart <qwe123@chello.at>.
+
+2004-05-16  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_goal_chain): Change the argument specifying
+	whether we're rebuilding makefiles to be a global variable,
+	REBUILDING_MAKEFILES.
+	(complain): Extract the code that complains about no rules to make
+	a target into a separate function.
+	(update_file_1): If we tried to rebuild a file during the makefile
+	rebuild phase and it was dontcare, then no message was printed.
+	If we then try to build the same file during the normal build,
+	print a message this time.
+	(remake_file): Don't complain about un-remake-able files when
+	we're rebuilding makefiles.
+
+2004-05-11  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (construct_command_argv_internal): OS/2 patches from
+	Andreas Buening <andreas.buening@nexgo.de>.
+
+2004-05-10  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_file): Don't walk the double-colon chain unless
+	this is a double-colon rule.  Fix suggested by Boris Kolpackov
+	<boris@kolpackov.net>.
+
+	* makefile.vms (CFLAGS): Remove glob/globfree (see readme.vms docs)
+	* readme.vms: New section describing OpenVMS support and issues.
+	* default.c (default_variables): Add support for IA64.
+	* job.c (tryToSetupYAst) [VMS]: On VMS running make in batch mode
+	without some privilege aborts make with the error
+	%SYSTEM-F-NOPRIV. It happens when setting up a handler for
+	pressing Ctrl+Y and the input device is no terminal. The change
+	catches this error and just continues.
+
+	Patches by Hartmut Becker <Hartmut.Becker@hp.com>
+
+2004-04-25  Paul D. Smith  <psmith@gnu.org>
+
+	* commands.c (set_file_variables): Set $< properly in the face of
+	order-only prerequisites.
+	Patch from Boris Kolpackov <boris@kolpackov.net>
+
+2004-04-21  Bob Byrnes  <byrnes@curl.com>
+
+	* main.c (main): Notice failures to remake makefiles.
+
+2004-03-28  Paul D. Smith  <psmith@gnu.org>
+
+	Patches for Acorn RISC OS by Peter Naulls <peter@chocky.org>
+
+	* job.c: No default shell for RISC OS.
+	(load_too_high): Hard-code the return to 1.
+	(construct_command_argv_internal): No sh_chars or sh_cmds.
+	* getloadavg.c: Don't set LOAD_AVE_TYPE on RISC OS.
+
+2004-03-20  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (do_variable_definition): Don't append from the
+	global set if a previous non-appending target-specific variable
+	definition exists.  Reported by Oliver Schmidt <oschmidt@gmx.net>
+	(with fix).
+
+	* expand.c (reference_variable): Don't give up on variables with
+	no value that have the target-specific append flag set: they might
+	have a value after all.  Reported by Oliver Schmidt
+	<oschmidt@gmx.net> (with fix) and also by Maksim A. Nikulin
+	<nikulin@dx1cmd.inp.nsk.su>.
+
+	* rule.c (count_implicit_rule_limits): Don't delete patterns which
+	refer to absolute pathnames in directories that don't exist: some
+	portion of the makefile could create those directories before we
+	match the pattern.  Fixes bugs #775 and #108.
+
+	Fixes from Jonathan R. Grant  <jg-make@jguk.org>:
+
+	* main.c (main): Free makefile_mtimes if we have any.
+	* README.W32.template: Update documentation for the current status
+	of the MS-Windows port.
+	* NMakefile.template (MAKE): Add "MAKE = nmake".  A conflicting
+	environment variable is sometimes already defined which causes the
+	build to fail.
+	* main.c (debug_signal_handler): Only define this function if
+	SIGUSR1 is available.
+
+	Fixes for OS/2 from Andreas Beuning <andreas.buening@nexgo.de>:
+
+	* configure.in [OS/2]: Relocate setting of HAVE_SA_RESTART for OS/2.
+	* README.OS2.template: Documentation updates.
+	* build.template: Add LIBINTL into LOADLIBES.  Add $CFLAGS to the
+	link line for safety.
+	* maintMakefile (build.sh.in): Remove an extraneous ")".
+	* job.c (child_execute_job): Close saved FDs.
+	* job.c (exec_command) [OS/2]: exec_command(): If the command
+	can't be exec'ed and if the shell is not Unix-sh, then try again
+	with argv = { "cmd", "/c", ... }. Normally, this code is never
+	reached for the cmd shell unless the command really doesn't exist.
+	(construct_command_argv_internal) [OS/2]: The code for cmd
+	handling now uses new_argv = { "cmd", "/c", "original line", NULL}.
+	The CMD builtin commands are case insensitive so use strcasecmp().
+
+2004-03-19  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (do_define): Re-order line counter increment so the count
+	is accurate (we were losing one line per define).  Reported by
+	Dave Yost <Dave@Yost.com>.
+
+2004-03-06  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in (HAVE_ANSI_COMPILER): Define if we have an ANSI/ISO
+	compiler.
+	* make.h: Convert uses of __STDC__ to HAVE_ANSI_COMPILER.
+	* misc.c (message,error,fatal): Ditto.
+	* configh.dos.template: Define HAVE_ANSI_COMPILER.
+	* config.h.W32.template: Ditto.
+	* config.h-vms.template: Ditto.
+	* config.ami.template: Ditto.
+
+2004-03-04  Paul D. Smith  <psmith@gnu.org>
+
+	* README.template: Add a note about broken /bin/sh on SunOS
+	4.1.3_U1 & 4.1.4.  Fix up Savannah links.
+
+	* misc.c (message, error, fatal): Don't use "..." if we're using
+	varargs.  ansi2knr should handle this but it doesn't work: it
+	translates "..." to va_dcl etc. but _AFTER_ the preprocessor is
+	done.  On many systems (SunOS for example) va_dcl is a #define.
+	So, force the use of the non-"..." version on pre-ANSI compilers.
+
+	* maintMakefile (sign-dist): Create some rules to help automate
+	the new GNU ftp upload method.
+
+2004-02-24  Paul D. Smith  <psmith@gnu.org>
+
+	* config.h.W32.template: Add HAVE_STDARG_H
+	* config.h-vms.template: Ditto.
+	* config.ami.template: Ditto.
+
+2004-02-23  Jonathan Grant  <jg-make@jguk.org>
+
+	* README.W32.template: Add a notation about -j with BATCH_MODE_ONLY.
+	* build_w32.bat: Remove extra "+".
+
+2004-02-23  Paul D. Smith  <psmith@gnu.org>
+
+	* make.h: Create an UNUSED macro to mark unused parameters.
+	* (many): Clean up warnings by applying UNUSED, fixing
+	signed/unsigned incompatibilities, etc.
+
+	* acinclude.m4 (AC_STRUCT_ST_MTIM_NSEC): Add quoting to silence
+	autoconf warnings.
+	* filedef.h: Name the command_state enumeration.
+	* file.c (set_command_state): Use the enumeration in the function
+	argument.
+
+	* configure.in: Explicitly set SET_MAKE to empty, to disable
+	MAKE=make even when no make already exists.  Fix bug #3823.
+
+2004-02-22  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile: Perl script to clean up all non-CVS files.  Use
+	it on all the subdirectories for the cvs-clean target.
+
+	* main.c (decode_switches): Require non-empty strings for all our
+	string command-line options.  Fixes Debian bug # 164165.
+
+	* configure.in: Check for stdarg.h and varargs.h.
+	* make.h (USE_VARIADIC): Set this if we can use variadic functions
+	for printing messages.
+	* misc.c: Check USE_VARIADIC instead of (obsolete) HAVE_STDVARARGS.
+	(message): Ditto.
+	(error): Ditto.
+	(fatal): Ditto.
+
+	A number of patches for OS/2 support from Andreas Buening
+	<andreas.buening@nexgo.de>:
+
+	* job.c (child_handler) [OS/2]: Allow this on OS/2 but we have to
+	disable the SIGCHLD handler.
+	(reap_children) [OS/2]: Remove special handling of job_rfd.
+	(set_child_handler_action_flags) [OS/2]: Use this function in OS/2.
+	(new_job) [OS/2]: Disable the SIGCHLD handler on OS/2.
+	* main.c (main) [OS/2]: Special handling for paths in OS/2.
+	* configure.in [OS/2]: Force SA_RESTART for OS/2.
+	* Makefile.am (check-regression): Use $(EXEEXT) for Windows-type
+	systems.
+
+2004-02-21  Paul D. Smith  <psmith@gnu.org>
+
+	* w32/subproc/sub_proc.c (process_easy) [W32]: Christoph Schulz
+	<mail@kristov.de> reports that if process_begin() fails we don't
+	handle the error condition correctly in all cases.
+	* w32/subproc/w32err.c (map_windows32_error_to_string): Make sure
+	to have a newline on the message.
+
+	* job.c (construct_command_argv_internal): Add "test" to UNIX
+	sh_cmds[].  Fixes Savannah bug # 7606.
+
+2004-02-04  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (vms_handle_apos) [VMS]: Fix various string handling
+	situations in VMS DCL.  Fixes Savannah bug #5533.  Fix provided by
+	Hartmut Becker <Hartmut.Becker@hp.com>.
+
+2004-01-21  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (load_too_high): Implement an algorithm to control the
+	"thundering herd" problem when using -l to control job creation
+	via the load average.  The system only recomputes the load once a
+	second but we can start many jobs in a second.  To solve this we
+	keep track of the number of jobs started in the last second and
+	apply a weight to try to guess what a correct load would be.
+	The algorithm was provided by Thomas Riedl <thomas.riedl@siemens.com>.
+	Also fixes bug #4693.
+	(reap_children): Decrease the job count for this second.
+	(start_job_command): Increase the job count for this second.
+
+	* read.c (conditional_line): Expand the text after ifn?def before
+	checking to see if it's a single word.  Fixes bug #7257.
+
+2004-01-09  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (print_file): Recurse to print all targets in
+	double-colon rules.  Fixes bug #4518, reported (with patch) by
+	Andrew Chatham <chatham@google.com>.
+
+2004-01-07  Paul D. Smith  <psmith@gnu.org>
+
+	* acinclude.m4: Remove make_FUNC_SETVBUF_REVERSED.
+	* configure.in: Change make_FUNC_SETVBUF_REVERSED to
+	AC_FUNC_SETVBUF_REVERSED.
+
+	* doc/make.texi (Target-specific): Fix Savannah bug #1772.
+	(MAKE Variable): Fix Savannah bug #4898.
+
+	* job.c (construct_command_argv_internal): Add "!" to the list of
+	shell escape chars.  POSIX sh allows it to appear before a
+	command, to negate the exit code.  Fixes bug #6404.
+
+	* implicit.c (pattern_search): When matching an implicit rule,
+	remember which dependencies have the ignore_mtime flag set.
+	Original fix provided in Savannah patch #2349, by Benoit
+	Poulot-Cazajous <Benoit.Poulot-Cazajous@jaluna.com>.
+
+2003-11-22  Paul D. Smith  <psmith@gnu.org>
+
+	* README.W32.template (Outputs): Clarification on -j with
+	BATCH_MODE_ONLY_SEHLL suggested by Jonathan R. Grant
+	<jg-make@jguk.org>.
+
+2003-11-02  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (func_if): Strip all the trailing whitespace from the
+	condition, then don't expand it.  Fixed bug # 5798.
+
+	* expand.c (recursively_expand_for_file): If we're expanding a
+	variable with no file context, then use the variable's context.
+	Fixes bug # 6195.
+
+2003-10-21  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (log_working_directory): Add newlines to printf()s.
+
+	* README.cvs: Add a note to ignore warnings during autoreconf.
+
+	* maintMakefile (po_repo): Set a new URL for PO file updates.
+	(get-config/config.guess get-config/config.sub): Get these files
+	from the Savannah config project instead of ftp.gnu.org.
+
+2003-10-05  Paul Eggert  <eggert@twinsun.com>
+
+	* main.c (main): Avoid potential subscript error if environ has
+	short strings.
+
+2003-08-22  Paul D. Smith  <psmith@gnu.org>
+
+	* misc.c (xmalloc, xrealloc): Add one to 0 sizes, to cater to
+	systems which don't yet implement the C89 standard :-/.
+
+2003-07-18  Paul D. Smith  <psmith@gnu.org>
+
+	* dir.c (directory_contents_hash_1, directory_contents_hash_1)
+	[WINDOWS32]: Initialize hash.
+
+2003-06-19  Earnie Boyd  <earnie@uses.sf.net>
+
+	* dir.c (read_dirstream): Provide a workaround for broken versions of
+	the MinGW dirent structure.
+
+2003-05-30  Earnie Boyd  <earnie@users.sf.net>
+
+	* w32/include/dirent.h: Add __MINGW32__ filter.
+
+2003-05-30  Earnie Boyd  <earnie@users.sf.net>
+
+	* make.h: Add global declaration of *make_host.
+	* main.c (print_usage): Remove local declaration of *make_host.
+	(print_version): Display "This program built for ..." after Copyright
+	notice.
+
+2003-05-30  Earnie Boyd  <earnie@users.sf.net>
+
+	* doc/make.texi: Change "ifinfo" to "ifnottex" as suggested by the
+	execution of "makeinfo --html make.texi".
+
+2003-04-30  Paul D. Smith  <psmith@gnu.org>
+
+	* build.template: Make some changes to maybe allow this script to
+	work on DOS/Windows/OS2 systems.  Suggested by Andreas Buening.
+
+	* README.OS2.template: New file for OS/2 support.  Original
+	contributed by Andreas Buening.
+	* configure.in: Invoke new pds_AC_DOS_PATHS macro to test for
+	DOS-style paths.
+
+2003-04-19  Paul D. Smith  <psmith@gnu.org>
+
+	Fix bug #1405: allow a target to match multiple pattern-specific
+	variables.
+
+	* rule.c (create_pattern_var, lookup_pattern_var): Move these to
+	variable.c, where they've always belonged.
+	* rule.h: Move the prototypes and struct pattern_var as well.
+	* variable.c (initialize_file_variables): Invoke
+	lookup_pattern_var() in a loop, until no more matches are found.
+	If a match is found, create a new variable set for the target's
+	pattern variables.  Then merge the contents of each matching
+	pattern variable set into the target's pattern variable set.
+	(lookup_pattern_var): Change this function to be usable
+	in a loop.  It takes a starting position: if NULL, start at the
+	beginning; if non-NULL, start with the pattern variable after that
+	position, and return the next matching pattern.
+	(create_pattern_var): Create a unique instance of
+	pattern-specific variables for every definition in the makefile.
+	Don't combine the same pattern together.  This allows us to
+	process the variable handling properly even when the same pattern
+	is used multiple times.
+	(parse_variable_definition): New function: break out the parsing
+	of a variable definition line from try_variable_definition.
+	(try_variable_definition): Call parse_variable_definition to
+	parse.
+	(print_variable_data_base): Print out pattern-specific variables.
+	* variable.h (struct variable): Remember when a variable is
+	conditional.  Also remember its flavor.
+	(struct pattern_var): Instead of keeping a variable set, we just
+	keep a single variable for each pattern.
+	* read.c (record_target_var): Each pattern variable contains only a
+	single variable, not a set, so create it properly.
+	* doc/make.texi (Pattern-specific): Document the new behavior.
+
+2003-04-17  Paul D. Smith  <psmith@gnu.org>
+
+	* dir.c (file_exists_p) [VMS]: Patch provided with Bug #3018 by
+	Jean-Pierre Portier <portierjp2@free.fr>.  I don't understand the
+	file/directory naming rules for VMS so I can't tell whether this
+	is correct or not.
+
+2003-04-09  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in (HAVE_DOS_PATHS): Define this on systems that need
+	DOS-style pathnames: backslash separators and drive specifiers.
+
+2003-03-28  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (snap_deps): If .SECONDARY with no targets is given, set
+	the intermediate flag on all targets.  Fixes bug #2515.
+
+2003-03-24  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in, Makefile.am, glob/Makefile.am, doc/Makefile.am:
+	Upgrade to autoconf 2.57 and automake 1.7.3.
+
+	* job.c: More OS/2 changes from Andreas Buening.
+
+	* file.c (print_file): Fix variable initialization.
+	Fixes bug #2892.
+
+	* remake.c (notice_finished_file):
+
+	* make.h (ENULLLOOP): Set errno = 0 before invoking the command;
+	some calls (like readdir()) return NULL in valid situations
+	without resetting errno.  Fixes bug #2846.
+
+2003-02-25  Paul D. Smith  <psmith@gnu.org>
+
+	Port to OS/2 (__EMX__) by Andreas Buening <andreas.buening@nexgo.de>.
+
+	* job.c (_is_unixy_shell) [OS/2]: New function.
+	Set default shell to /bin/sh.
+	(reap_children): Close the job_rfd pipe here since we don't use a
+	SIGCHLD handler.
+	(set_child_handler_action_flags): define this to empty on OS/2.
+	(start_job_command): Close the jobserver pipe and use
+	child_execute_job() instead of fork/exec.
+	(child_execute_job): Rewrite to handle stdin/stdout FDs and spawn
+	rather than exec'ing, then reconfigure stdin/stdout.
+	(exec_command): Rewrite to use spawn instead of exec.  Return the
+	PID of the child.
+
+	* main.c (main) [OS/2]: Call initialize_main().  Handle argv[0] as
+	in DOS.  Handle the TEMP environment variable as in DOS.  Don't
+	use a SIGCHLD handler on OS/2.  Choose a shell as in DOS.  Don't
+	use -j in DOS mode.  Use child_execute_job() instead of
+	exec_command().
+
+	* function.c (func_shell) [OS/2]: Can't use fork/exec on OS/2: use
+	spawn() instead.
+
+	* job.h [OS/2]: Move CLOSE_ON_EXEC here from job.c.  Add
+	prototypes that return values.
+
+	* remake.c (f_mtime) [OS/2]: Handle FAT timestamp offsets for OS/2.
+
+	* read.c (readline) [OS/2]: Don't handle CRLF specially on OS/2.
+	* default.c (default_suffixes) [OS/2]: Set proper default suffixes
+	for OS/2.
+	* vpath.c (construct_vpath_list) [OS/2]: Handle OS/2 paths like
+	DOS paths.
+
+2003-02-24  Paul D. Smith  <psmith@gnu.org>
+
+	* default.c [VMS]: New default rules for .cxx -> .obj compiles.
+	* job.c (child_execute_job) [VMS]: New code for handling spawn().
+	(child_execute_job) [VMS]: Handle error status properly.
+	Patches provided by Hartmut Becker <Hartmut.Becker@compaq.com>.
+
+	* function.c (func_shell): Use EINTRLOOP() while reading from the
+	subshell pipe (Fixes bug #2502).
+	* job.c (free_child): Use EINTRLOOP() while writing tokens to the
+	jobserver pipe.
+	* main.c (main): Ditto.
+
+2003-01-30  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (eval): eval() was not fully reentrant, because the
+	collapsed buffer was static.  Change it to be an automatic
+	variable so that eval() can be invoked recursively.
+	Fixes bug # 2238.
+	(eval): Apply patch # 1022: fix memory reference error on long
+	target-specific variable lines.
+	Patch provided by Steve Brown <Steve.Brown@macquarie.com>.
+
+	* function.c (check_numeric): Combine the is_numeric() function
+	into this function, since it's only called from one place.
+	Constify this function.  Have it print the incorrect string in the
+	error message.  Fixes bug #2407.
+	(strip_whitespace): Constify.
+	(func_if): Constify.
+	* expand.c (expand_argument): Constify.
+
+2003-01-29  Paul D. Smith  <psmith@gnu.org>
+
+	Fix bug # 2169, also reported by other people on various systems.
+
+	* make.h: Some systems, such as Solaris and PTX, do not fully
+	implement POSIX-compliant SA_RESTART functionality; important
+	system calls like stat() and readdir() can still fail with EINTR
+	even if SA_RESTART has been set on the signal handler.  So,
+	introduce macros EINTRLOOP() and ENULLLOOP() which can loop on
+	EINTR for system calls which return -1 or 0 (NULL), respectively,
+	on error.
+	Also, remove the old atomic_stat()/atomic_readdir() and
+	HAVE_BROKEN_RESTART handling.
+
+	* configure.in: Remove setting of HAVE_BROKEN_RESTART.
+
+	* arscan.c (ar_member_touch): Use EINTRLOOP() to wrap fstat().
+	* remake.c (touch_file): Ditto.
+
+	* commands.c (delete_target): Use EINTRLOOP() to wrap stat().
+	* read.c (construct_include_path): Ditto.
+	* remake.c (name_mtime): Ditto.
+	* vpath.c (selective_vpath_search): Ditto.
+	* dir.c (find_directory): Ditto.
+	(local_stat): Ditto.
+	(find_directory): Use ENULLLOOP() to wrap opendir().
+	(dir_contents_file_exists_p): Use ENULLLOOP() to wrap readdir().
+
+	* misc.c: Remove HAVE_BROKEN_RESTART, atomic_stat(), and
+	atomic_readdir() handling.
+
+2003-01-22  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (func_call): Fix Bug #1744.  If we're inside a
+	recursive invocation of $(call ...), mask any of the outer
+	invocation's arguments that aren't used by this one, so that this
+	invocation doesn't "inherit" them accidentally.
+
+2002-12-05  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (subst_expand): Valery Khamenia reported a
+	pathological performance hit when doing substitutions on very
+	large values with lots of words: turns out we were invoking
+	strlen() a ridiculous number of times.  Instead of having each
+	call to sindex() call strlen() again, keep track of how much of
+	the text we've seen and pass the length to sindex().
+
+2002-11-19  Paul D. Smith  <psmith@gnu.org>
+
+	* README.cvs, configure.in: Upgrade to require autoconf 2.56.
+
+
+2002-11-16  Paul D. Smith  <psmith@gnu.org>
+
+	* NMakefile.template (OBJS): Add hash.c object file.
+	* SMakefile.template (srcs): Ditto.
+	* Makefile.ami (objs): Ditto.
+	* build_w32.bat: Ditto.
+
+	* Makefile.DOS.template: Remove extra dependencies.
+
+2002-10-25  Paul D. Smith  <psmith@gnu.org>
+
+	* expand.c (install_variable_buffer): New function.  Install a new
+	variable_buffer context and return the previous one.
+	(restore_variable_buffer): New function.  Free the current
+	variable_buffer context and put a previously saved one back.
+	* variable.h: Prototypes for {install,restore}_variable_buffer.
+	* function.c (func_eval): Push a new variable_buffer context
+	before we eval, then restore the old one when we're done.
+	Fixes Bug #1517.
+
+	* read.c (install_conditionals): New function.  Install a new
+	conditional context and return the previous one.
+	(restore_conditionals): New function.  Free the current
+	conditional context and put a previously saved one back.
+	(eval): Use the {install,restore}_conditionals for "include"
+	handling.
+	(eval_buffer): Use {install,restore}_conditionals to preserve the
+	present conditional state before we evaluate the buffer.
+	Fixes Bug #1516.
+
+	* doc/make.texi (Quick Reference): Add references to $(eval ...)
+	and $(value ...).
+	(Recursion): Add a variable index entry for CURDIR.
+
+	* README.cvs: Update to appropriate versions.
+	* Makefile.am (nodist_loadavg_SOURCES): automake gurus point out I
+	don't need to copy loadavg.c: automake is smart enough to create
+	it for me.  Still have a bug in automake related to ansi2knr tho.
+
+2002-10-14  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (notice_finished_file): Only touch targets if they have
+	at least one command (as per POSIX).  Resolve Bug #1418.
+
+	* *.c: Convert to using ANSI C-style function definitions.
+	* Makefile.am: Enable the ansi2knr feature of automake.
+	* configure.in: ditto.
+
+2002-10-13  Paul D. Smith  <psmith@gnu.org>
+
+	* commands.c (set_file_variables): Bug #1379: Don't use alloca()
+	for automatic variable values like $^, etc.  In the case of very
+	large lists of prerequisites this causes problems.  Instead reuse
+	a static buffer (resizeable) for each variable.
+
+	* read.c (eval): Fix Bug #1391: allow "export" keyword in
+	target-specific variable definitions.  Check for it and set an
+	"exported" flag.
+	(record_target_var): Set the export field to v_export if the
+	"exported" flag is set.
+	* doc/make.texi (Target-specific): Document the ability to use
+	"export".
+
+	* doc/make.texi: Change the name of the section on automatic
+	variables from "Automatic" to "Automatic Variables".  Added text
+	clarifying the scope of automatic variables.
+
+2002-10-04  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (eval): Allow SysV $$@ variables to use {} braces as well
+	as () braces.
+	(record_files): Ditto.
+
+	* expand.c (variable_expand_string): In $(A:x=y) expansion limit
+	the search for the '=' to only within the enclosing parens.
+
+2002-10-03  Paul D. Smith  <psmith@gnu.org>
+
+	Version 3.80 released.
+
+	* dir.c: Change hash functions to use K&R function definition style.
+	* function.c: Ditto.
+	* read.c: Ditto.
+	* variable.c: Ditto.
+
+	Update to automake 1.7.
+
+	* Makefile.am (AUTOMAKE_OPTIONS): Update to require 1.7.
+	(pdf): Remove this target as automake now provides one.
+
+	* configure.in: Change AM_CONFIG_HEADER to AC_CONFIG_HEADERS.
+
+2002-09-30  Martin P.J. Zinser  <zinser@decus.de>
+
+	* makefile.com: Updates for GNU make 3.80.
+	* makefile.vms: Ditto.
+
+2002-09-23  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (enum make_word_type): Remove w_comment.
+	(get_next_mword): Don't treat comment characters as special; where
+	this function is used we will never see a comment (it's stripped
+	before we get here) and treating comments specially means that
+	targets like "foo\#bar" aren't handled properly.
+
+2002-09-18  Paul D. Smith  <psmith@gnu.org>
+
+	* doc/make.texi (Bugs): Update with some info on Savannah, etc.
+
+	* read.c (eval): Expansion of arguments to export/unexport was
+	ignoring all arguments after the first one.  Change the algorithm
+	to expand the whole line once, then parse the results.
+
+2002-09-17  Paul D. Smith  <psmith@gnu.org>
+
+	Fix Bug #940 (plus another bug I found while looking at this):
+
+	* read.c (record_target_var): enter_file() will add a new entry if
+	it's a double-colon target: we don't want to do that in this
+	situation.  Invoke lookup_file() and only enter_file() if it does
+	not already exist.  If the file we get back is a double-colon then
+	add this variable to the "root" double-colon target.
+
+	* variable.c (initialize_file_variables): If this file is a
+	double-colon target but is not the "root" target, then initialize
+	the root and make the root's variable list the parent of our
+	variable list.
+
+2002-09-13  Paul D. Smith  <psmith@gnu.org>
+
+	* doc/make.texi (MAKE Variable): Add some indexing for "+".
+
+	* hash.c (round_up_2): Get rid of a warning.
+
+2002-09-12  Paul D. Smith  <psmith@gnu.org>
+
+	* Makefile.am (loadavg_SOURCES, loadavg.c): Tiptoe around automake
+	so it doesn't complain about getloadavg.c.
+
+	* commands.c (set_file_variables): Make sure we always alloca() at
+	least 1 character for the value of $? (for '\0').
+
+2002-09-11  Paul D. Smith  <psmith@gnu.org>
+
+	* hash.h (STRING_COMPARE, ISTRING_COMPARE, STRING_N_COMPARE): Fix
+	macro to use RESULT instead of the incorrect _RESULT_.
+
+	* make.h (HAVE_BROKEN_RESTART): Add prototypes for atomic_stat()
+	and atomic_readdir().  We need to #include dirent.h to get this to
+	work.
+	* misc.c (atomic_readdir): Fix typos.
+
+2002-09-10  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (eval): Expand variable lists given to export and
+	unexport, so that "export $(LIST_OF_VARIABLES)" (etc.) works.
+	(conditional_line): Ditto for "ifdef".  Fixes bug #103.
+
+	* doc/make.texi (Variables/Recursion): Document this.
+	(Conditional Syntax): And here.
+
+2002-09-09  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Check for memmove().
+
+2002-09-07  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in (HAVE_BROKEN_RESTART): Define this on PTX systems;
+	Michael Sterrett <msterret@coat.com> reports that while it has
+	SA_RESTART, it does not work properly.
+
+	* misc.c (atomic_stat): If HAVE_BROKEN_RESTART, create a function
+	that invokes stat() and loops to do it again if it returns EINTR.
+	(atomic_readdir): Ditto, with readdir().
+
+	* make.h (stat, readdir): If HAVE_BROKEN_RESTART, alias stat()
+	and readdir() to atomic_stat() and atomic_readdir().
+
+2002-09-04  Paul D. Smith  <psmith@gnu.org>
+
+	* implicit.c (pattern_search): Daniel <barkalow@reputation.com>
+	reports that GNU make sometimes doesn't recognize that targets can
+	be made, when directories can be created as prerequisites.  He
+	reports that changing the order of predicates in the DEP->changed
+	flag test so that lookup_file() is always performed, solves this
+	problem.
+
+2002-08-08  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Require a newer version of gettext.
+
+	* misc.c (perror_with_name): Translate the format string (for
+	right-to-left language support).
+	(pfatal_with_name): Ditto.
+
+	* main.c: Create a static array of strings to store the usage
+	text.  This is done to facilitate translations.
+	(struct command_switch): Remove argdesc and description fields.
+	(switches): Remove values for obsolete fields.
+	(print_usage): Print each element of the usage array.
+
+	* hash.c: Change function definitions to be K&R style.
+
+2002-08-02  Paul D. Smith  <psmith@gnu.org>
+
+	* NEWS: Remove the mention of .TARGETS; we aren't going to publish
+	this one because it's too hard to get right.  We'll look at it for
+	a future release.
+	* main.c (main): Don't create the .TARGETS variable.
+	* variable.c (handle_special_var): Don't handle .TARGETS.
+
+2002-08-01  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (switches): Add a new option, -B (--always-make).  If
+	specified, make will rebuild all targets that it encounters even
+	if they don't appear to be out of date.
+	(always_make_flag): New flag.
+	* make.h: Extern always_make_flag.
+	* remake.c (update_file_1): Check always_make_flag; if it's set we
+	will always rebuild any target we can, even if none of its
+	prerequisites are newer.
+	* NEWS: Mention it.
+
+	* doc/make.texi (Shell Function): Make it clear that make
+	variables marked as "export" are not passed to instances of the
+	shell function.
+
+	Add new introspection variable .VARIABLES and .TARGETS.
+
+	* variable.c (handle_special_var): New function.  If the variable
+	reference passed in is "special" (.VARIABLES or .TARGETS),
+	calculate the new value if necessary.  .VARIABLES is handled here:
+	walk through the hash of defined variables and construct a value
+	which is a list of the names.  .TARGETS is handled by
+	build_target_list().
+	(lookup_variable): Invoke handle_special_var().
+	* file.c (build_target_list): Walk through the hask of known files
+	and construct a list of the names of all the ones marked as
+	targets.
+	* main.c (main): Initialize them to empty (and as simple variables).
+	* doc/make.texi (Special Variables): Document them.
+	* NEWS: Mention them.
+
+	* variable.h (struct variable): Add a new flag "exportable" which
+	is true if the variable name is valid for export.
+	* variable.c (define_variable_in_set): Set "exportable" when a new
+	variable is defined.
+	(target_environment): Use the "exportable" flag	instead of
+	re-checking the name here... an efficiency improvement.
+
+2002-07-31  Paul D. Smith  <psmith@gnu.org>
+
+	* config.h-vms.template: Updates to build on VMS.  Thanks to
+	Brian_Benning@aksteel.com for helping verify the build.
+	* makefile.com: Build the new hash.c file.
+	* hash.h: Use strcpmi(), not stricmp(), in the
+	HAVE_CASE_INSENSITIVE_FS case.
+
+2002-07-30  Paul D. Smith  <psmith@gnu.org>
+
+	* hash.h (ISTRING_COMPARE, return_ISTRING_COMPARE): Add missing
+	backslashes to the HAVE_CASE_INSENSITIVE_FS case.
+	Reported by <Brian_Benning@aksteel.com>.
+
+2002-07-10  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (pop_variable_scope): Remove variable made unused by
+	new hash infrastructure.
+	* read.c (dep_hash_cmp): Rewrite this to handle ignore_mtime
+	comparisons as well as name comparisons.
+	* variable.h: Add a prototype for new hash_init_function_table().
+	* file.c (lookup_file): Remove variables made unused by new hash
+	infrastructure.
+	* dir.c (directory_contents_hash_2): Missing return of hash value.
+	(dir_contents_file_exists_p): Remove variables made unused by new
+	hash infrastructure.
+
+
+	Installed Greg McGary's integration of the hash functions from the
+	GNU id-utils package:
+
+2002-07-10  Greg McGary  <greg@mcgary.org>
+
+	* scripts/functions/filter-out: Add literals to to the
+	pattern space in order to add complexity, and trigger
+	use of an internal hash table.  Fix documentation strings.
+	* scripts/targets/INTERMEDIATE: Reverse order of files
+	passed to expected `rm' command.
+
+2002-07-10  Greg McGary  <greg@mcgary.org>
+
+	* Makefile.am (SRCS): Add hash.c (noinst_HEADERS): Add hash.h
+	* hash.c: New file, taken from id-utils.
+	* hash.h: New file, taken from id-utils.
+
+	* make.h (HASH, HASHI): Remove macros.
+	(find_char_unquote): Change arglist in decl.
+	(hash_init_directories): New function decl.
+	* variable.h (hash.h): New #include.
+	(MAKELEVEL_NAME, MAKELEVEL_LENGTH): New constants.
+	* filedef.h (hash.h): New #include.
+	(struct file) [next]: Remove member.
+	(file_hash_enter): Remove function decl.
+	(init_hash_files): New function decl.
+
+	* ar.c (ar_name): Delay call to strlen until needed.
+	* main.c (initialize_global_hash_tables): New function.
+	(main): Call it.  Use MAKELEVEL_NAME & MAKELEVEL_LENGTH.
+	* misc.c (remove_comments): Pass char constants to find_char_unquote.
+	* remake.c (notice_finished_file): Update last_mtime on `prev' chain.
+
+	* dir.c (hash.h): New #include.
+	(struct directory_contents) [next, files]: Remove members.
+	[ctime]: Add member for VMS.  [dirfiles]: Add hash-table member.
+	(directory_contents_hash_1, directory_contents_hash_2,
+	directory_contents_hash_cmp): New functions.
+	(directories_contents): Change type to `struct hash_table'.
+	(struct directory) [next]: Remove member.
+	(directory_hash_1, directory_hash_2, directory_hash_cmp): New funcs.
+	(directory): Change type to `struct hash_table'.
+	(struct dirfile) [next]: Remove member.
+	[length]: Add member.  [impossible]: widen type to fill alignment gap.
+	(dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp): New functions.
+	(find_directory): Use new hash table package.
+	(dir_contents_file_exists_p): Likewise.
+	(file_impossible): Likewise.
+	(file_impossible_p): Likewise.
+	(print_dir_data_base): Likewise.
+	(open_dirstream): Likewise.
+	(read_dirstream): Likewise.
+	(hash_init_directories): New function.
+
+	* file.c (hash.h): New #include.
+	(file_hash_1, file_hash_2, file_hash_cmp): New functions.
+	(files): Change type to `struct hash_table'.
+	(lookup_file): Use new hash table package.
+	(enter_file): Likewise.
+	(remove_intermediates): Likewise.
+	(snap_deps): Likewise.
+	(print_file_data_base): Likewise.
+
+	* function.c
+	(function_table_entry_hash_1, function_table_entry_hash_2,
+	function_table_entry_hash_cmp): New functions.
+	(lookup_function): Remove `table' argument.
+	Use new hash table package.
+	(struct a_word) [chain, length]: New members.
+	(a_word_hash_1, a_word_hash_2, a_word_hash_cmp): New functions.
+	(struct a_pattern): New struct.
+	(func_filter_filterout): Pass through patterns noting boundaries
+	and '%', if present.  Note a_word length.  Use a hash table if
+	arglists are large enough to justify cost.
+	(function_table_init): Renamed from function_table.
+	(function_table): Declare as `struct hash_table'.
+	(FUNCTION_TABLE_ENTRIES): New constant.
+	(hash_init_function_table): New function.
+
+	* read.c (hash.h): New #include.
+	(read_makefile): Pass char constants to find_char_unquote.
+	(dep_hash_1, dep_hash_2, dep_hash_cmp): New functions.
+	(uniquize_deps): Use hash table to efficiently identify duplicates.
+	(find_char_unquote): Accept two char-constant stop chars, rather
+	than a string constant, avoiding zillions of calls to strchr.
+	Tighten inner search loops to test only for desired delimiters.
+
+	* variable.c (variable_hash_1, variable_hash_2,
+	variable_hash_cmp): New functions.
+	(variable_table): Declare as `struct hash_table'.
+	(global_variable_set): Remove initialization.
+	(init_hash_global_variable_set): New function.
+	(define_variable_in_set): Use new hash table package.
+	(lookup_variable): Likewise.
+	(lookup_variable_in_set): Likewise.
+	(initialize_file_variables): Likewise.
+	(pop_variable_scope): Likewise.
+	(create_new_variable_set): Likewise.
+	(merge_variable_sets): Likewise.
+	(define_automatic_variables): Likewise.
+	(target_environment): Likewise.
+	(print_variable_set): Likewise.
+
+2002-07-10  Paul D. Smith  <psmith@gnu.org>
+
+	Implement the SysV make syntax $$@, $$(@D), and $$(@F) in the
+	prerequisite list.  A real SysV make will expand the entire
+	prerequisites list _twice_: we don't do that as it's a big
+	backward-compatibility problem.  We only replace those specific
+	variables.
+
+	* read.c (record_files): Replace any $@, $(@D), and $(@F) variable
+	references left in the list of prerequisites.  Check for .POSIX as
+	we record targets, so we can disable non-POSIX behavior while
+	reading makefiles as well as running them.
+	(eval): Check the prerequisite list to see if we have anything
+	that looks like a SysV prerequisite variable reference.
+
+2002-07-09  Paul D. Smith  <psmith@gnu.org>
+
+	* doc/make.texi (Prerequisite Types): Add a new section describing
+	order-only prerequisites.
+
+	* read.c (uniquize_deps): If we have the same file as both a
+	normal and order-only prereq, get rid of the order-only prereq,
+	since the normal one supersedes it.
+
+2002-07-08  Paul D. Smith  <psmith@gnu.org>
+
+	* AUTHORS: Added Greg McGary to the AUTHORS file.
+	* NEWS: Blurbed order-only prerequisites.
+	* file.c (print_file): Show order-only deps properly when printing
+	the database.
+
+	* maintMakefile: Add "update" targets for wget'ing the latest
+	versions of various external files.  Taken from Makefile.maint in
+	autoconf, etc.
+
+	* dosbuild.bat: Somehow we got _double_ ^M's.  Remove them.
+	Reported by Eli Zaretskii <eliz@is.elta.co.il>.
+
+2002-07-07  Paul D. Smith  <psmith@gnu.org>
+
+	* po/*.po: Remove.  We'll use wget to retrieve them at release
+	time.
+
+	* variable.c (do_variable_definition) [W32]: On W32 using cmd
+	rather than a shell you get an exception.  Make sure we look up
+	the variable.  Patch provided by Eli Zaretskii <eliz@is.elta.co.il>.
+
+	* remake.c (notice_finished_file): Fix handling of -t flag.
+	Patch provided by Henning Makholm <henning@makholm.net>.
+
+	* implicit.c (pattern_search): Some systems apparently run short
+	of stack space, and using alloca() in this function caused an
+	overrun.  I modified it to use xmalloc() on the two variables
+	which seemed like they might get large.  Fixes Bug #476.
+
+	* main.c (print_version): Update copyright notice to conform with
+	GNU standards.
+	(print_usage): Update help output.
+
+	* function.c (func_eval): Create a new make function, $(eval
+	...).  Expand the arguments, put them into a buffer, then invoke
+	eval_buffer() on the resulting string.
+	(func_quote): Create a new function, $(quote VARNAME).  Inserts
+	the value of the variable VARNAME without expanding it any
+	further.
+
+	* read.c (struct ebuffer): Change the linebuffer structure to an
+	"eval buffer", which can be either a file or a buffer.
+	(eval_makefile): Move the code in the old read_makefile() which
+	located a makefile into here: create a struct ebuffer with that
+	information.  Have it invoke the new function eval() with that
+	ebuffer.
+	(eval_buffer): Create a new function that creates a struct ebuffer
+	that holds a string buffer instead of a file.  Have it invoke
+	eval() with that ebuffer.
+	(eval): New function that contains the guts of the old
+	read_makefile() function: this function parses makefiles.  Obtains
+	data to parse from the provided ebuffer.  Some modifications to
+	make the flow of the function cleaner and clearer.  Still could
+	use some work here...
+	(do_define): Takes a struct ebuffer instead of a FILE*.  Read the
+	contents of the define/endef variable from the ebuffer.
+	(readstring): Read the next line from a string-style ebuffer.
+	(readline): Read the next line from an ebuffer.  If it's a string
+	ebuffer, invoke readstring().  If it's a FILE* ebuffer, read it
+	from the file.
+
+	* dep.h (eval_buffer): Prototype eval_buffer();
+
+	* variable.c (do_variable_definition): Make sure that all
+	non-target-specific variables are registered in the global set.
+	If we're invoked from an $(eval ...) we might be inside a $(call
+	...) or other function which has pushed a variable scope; we still
+	want to define our variables from evaluated makefile code in the
+	global scope.
+
+2002-07-03  Greg McGary  <greg@mcgary.org>
+
+	* dep.h (struct dep) [ignore_mtime]: New member.
+	[changed]: convert to a bitfield.
+	* implicit.c (pattern_search): Zero ignore_mtime.
+	* main.c (main, handle_non_switch_argument): Likewise.
+	* rule.c (convert_suffix_rule): Likewise.
+	* read.c (read_all_makefiles, read_makefile, multi_glob): Likewise.
+	(read_makefile): Parse '|' in prerequisite list.
+	(uniquize_deps): Consider ignore_mtime when comparing deps.
+	* remake.c (update_file_1, check_dep): Don't force remake for
+	dependencies that have d->ignore_mtime.
+	* commands.c (FILE_LIST_SEPARATOR): New constant.
+	(set_file_variables): Don't include a
+	prerequisite in $+, $^ or $? if d->ignore_mtime.
+	Define $|.
+
+2002-06-18  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo: Updates for next revision.  New date/rev/etc.
+	Recreate all Info menus.  Change license on the manual to the GNU
+	Free Documentation License.  A number of typos.
+	(Variables Simplify): Don't use "-" before it's defined.
+	(Automatic Prerequisites): Rewrite the target example to work
+	properly if the compile fails.  Remove incorrect comments about
+	how "set -e" behaves.
+	(Text Functions): Move the "word", "wordlist", "words", and
+	"firstword" functions here, from "File Name Functions".
+	* make-stds.texi: Update from latest GNU version.
+	* fdl.texi: (created) Import the latest GNU version.
+
+2002-06-06  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (do_variable_definition): New function: extract the
+	part of try_variable_definition() that actually sets the value
+	into a separate function.
+	(try_variable_definition): Call do_variable_definition() after
+	parsing the variable definition string.
+	(define_variable_in_set): Make the name argument const.
+
+	* variable.h (enum variable_flavor): Make public.
+	(do_variable_definition): Create prototype.
+
+	* read.c (read_all_makefiles): Create a new built-in variable,
+	MAKEFILE_LIST.
+	(read_makefile): Add each makefile read in to this variable value.
+
+2002-05-18  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* Makefile.DOS.template: Tweak according to changes in the
+	distribution.  Add back the dependencies of *.o files.
+
+	* configh.dos.template: Synchronize with config.h.in.
+
+2002-05-09  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (file_timestamp_now): Use K&R function declaration.
+
+	* getloadavg.c (getloadavg): Merge setlocale() fix from sh-utils
+	getloadavg.c.  Autoconf thinks QNX is SVR4-like, but it isn't, so
+	#undef it.  Remove predefined setup of NLIST_STRUCT.  Decide
+	whether to include nlist.h based on HAVE_NLIST_H.  Change obsolete
+	NLIST_NAME_UNION to new HAVE_STRUCT_NLIST_N_UN_N_NAME.
+	* configure.in (NLIST_STRUCT): Define this if we have nlist.h and
+	nlist.n_name is a pointer rather than an array.
+
+	* acinclude.m4 (make_FUNC_SETVBUF_REVERSED): Grab the latest
+	version of AC_FUNC_SETVBUF_REVERSED from autoconf CVS.
+	* configure.in: Use it instead of the old version.
+
+	* main.c (main): Prefer setvbuf() to setlinebuf().
+
+2002-05-08  Paul D. Smith  <psmith@gnu.org>
+
+	* Makefile.am (make_LDADD): Add GETLOADAVG_LIBS.
+	(loadavg_LDADD): Ditto.
+
+2002-04-29  Paul D. Smith  <psmith@gnu.org>
+
+	* expand.c (recursively_expand_for_file): Rename
+	recursively_expand() to recursively_expand_for_file() and provide
+	an extra argument, struct file.  If the argument is provided, set
+	the variable scope to that of the file before expanding.
+	* variable.h (recursively_expand): Make this a macro that invokes
+	recursively_expand_for_file() with a NULL file pointer.
+	* variable.c (target_environment): Call the renamed function and
+	provide the current file context.
+	Fixes Debian bug #144306.
+
+2002-04-28  Paul D. Smith  <psmith@gnu.org>
+
+	Allow $(call ...) user-defined variables to be self-referencing
+	without throwing an error.  Allows implementation of transitive
+	closures, among other possibly useful things.
+	Requested by: Philip Guenther <guenther@sendmail.com>
+
+	* variable.h (struct variable): Add a new field: exp_count, and
+	new macros to hold its size and maximum value.
+	(warn_undefined): Make this a macro.
+	* variable.c (define_variable_in_set): Initialize it.
+	* expand.c (recursively_expand): If we detect recursive expansion
+	of a variable, check the exp_count field.  If it's greater than 0
+	allow the recursion and decrement the count.
+	(warn_undefined): Remove this (now a macro in variable.h).
+	* function.c (func_call): Before we expand the user-defined
+	function, modify its exp_count field to contain the maximum
+	number of recursive calls we'll allow.  After the call, reset it
+	to 0.
+
+2002-04-21  Paul D. Smith  <psmith@gnu.org>
+
+	Modified to use latest autoconf (2.53), automake (1.6.1), and
+	gettext (0.11.1).  We're using gettext's new "external" support,
+	to avoid including libintl source with GNU make.
+
+	* README.cvs: New file.  Explain how to build GNU make from CVS.
+
+	* configure.in: Modify checking for the system glob library.
+	Use AC_EGREP_CPP instead of AC_TRY_CPP.  Remove the setting of
+	GLOBDIR (we will always put "glob" in SUBDIRS, so automake
+	etc. will manage it correctly).  Set an automake conditional
+	USE_LOCAL_GLOB to decide whether to compile the glob library.
+
+	* getloadavg.c (main): Include make.h in the "TEST" program to
+	avoid warnings.
+
+	* Makefile.am: Remove special rules for loadavg.  Replace them
+	with Automake capabilities for building extra programs.
+
+	* signame.c: This file does nothing if the system provide
+	strsignal().  If not, it implements strsignal().  If the system
+	doesn't define sys_siglist, then we make our own; otherwise we use
+	the system version.
+	* signame.h: Removed.
+
+	* main.c (main): No need to invoke signame_init().  Update copyright.
+
+	* ABOUT-NLS: Removed.
+	* gettext.c: Removed.
+	* gettext.h: Get a simplified copy from the gettext package.
+	* po/*: Created.
+	* i18n/*.po: Moved to po/.
+	* i18n/: Removed.
+
+	* config/*: Created.  Contains package configuration helper files.
+	* config.guess, config.sub: Moved to config directory.
+
+	* configure.in (AC_CONFIG_FILES): Add po/Makefile.in, config/Makefile.
+	Rework to use new-style autoconf features.  Use the "external"
+	mode for gettext.  Make the build.sh config file conditional on
+	whether build.sh.in exists, to avoid autoconf errors.
+	* acinclude.m4: Removed almost all macros as being obsolete.
+	Rewrote remaining macros to use AC_DEFINE.
+	* acconfig.h: Removed.
+
+	* Makefile.am (EXTRA_DIST): Add config/config.rpath.  Use a
+	conditional to handle customs support.  Remove special handling
+	for i18n features.
+
+2002-04-20  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (func_call): Don't mark the argument variables $1,
+	etc. as recursive.  They've already been fully expanded so
+	there's no need to do it again, and doing so strips escaped $'s.
+	Reported by Sebastian Glita <glseba@yahoo.com>.
+
+	* remake.c (notice_finished_file): Walk through double-colon
+	entries via the prev field, not the next field!
+	Reported by Greg McGary <greg@mcgary.org>.
+
+	* main.c (main): If the user specifies -q and asks for a specific
+	target which is a makefile, we got an assert.  In that case it
+	turns out we should continue normally instead.
+
+	* i18n/de.po, i18n/fr.po: Installed an updated translation.
+
+	* i18n/he.po: Installed a new translation.
+
+2002-01-07  Paul D. Smith  <psmith@gnu.org>
+
+	* i18n/es.po, i18n/ru.po: Installed an updated translation.
+
+2001-12-04  Paul D. Smith  <psmith@gnu.org>
+
+	* i18n/ja.po: Installed an updated translation.
+
+2001-09-06  Paul Eggert  <eggert@twinsun.com>
+
+	* configure.in (AC_CHECK_HEADERS): Add sys/resource.h.
+	(AC_CHECK_FUNCS): Add getrlimit, setrlimit.
+
+	* main.c: Include <sys/resource.h> if it, getrlimit, and setrlimit
+	are available.
+	(main): Get rid of any avoidable limit on stack size.
+
+2001-09-04  Paul D. Smith  <psmith@gnu.org>
+
+	* i18n/da.po: Installed an updated translation.
+
+2001-08-03  Paul D. Smith  <psmith@gnu.org>
+
+	* i18n/fr.po: Installed an updated translation.
+	Resolves Debian	bug #106720.
+
+2001-06-13  Paul D. Smith  <psmith@gnu.org>
+
+	* i18n/da.po, configure.in (ALL_LINGUAS): Installed a new
+	translation.
+
+2001-06-11  Paul D. Smith  <psmith@gnu.org>
+
+	* i18n/ko.po: Installed a new translation.
+
+2001-05-06  Paul D. Smith  <psmith@gnu.org>
+
+	Modify the EINTR handling.
+
+	* job.c (new_job): Reorganize the jobserver algorithm.  Reorder
+	the way in which we manage the file descriptor/signal handler race
+	trap to be more efficient.
+
+2001-05-06  Paul Eggert  <eggert@twinsun.com>
+
+	Restart almost all system calls that are interrupted, instead
+	of worrying about EINTR.  The lone exception is the read() for
+	job tokens.
+
+	* configure.in (HAVE_SA_RESTART): New macro.
+	(MAKE_JOBSERVER): Define to 1 only if HAVE_SA_RESTART.
+	* main.c (main): Use SA_RESTART instead of the old,
+	nonstandard SA_INTERRUPT.
+
+	* configure.in (AC_CHECK_FUNCS): Add bsd_signal.
+	* main.c (bsd_signal): New function or macro,
+	if the implementation doesn't supply it.
+	(The bsd_signal function will be in POSIX 1003.1-200x.)
+	(HANDLESIG): Remove.
+	(main, FATAL_SIG): Use bsd_signal instead of signal or HANDLESIG.
+
+	* make.h (EINTR_SET): Remove.
+	(SA_RESTART): New macro.
+
+	* arscan.c (ar_member_touch): Don't worry about EINTR.
+	* function.c (func_shell): Likewise.
+	* job.c (reap_children, free_child, new_job): Likewise.
+	* main.c (main): Likewise.
+	* remake.c (touch_file, name_mtime): Likewise.
+
+	* arscan.c (ar_member_touch): Fix bug uncovered by EINTR removal;
+	if fstat failed with errno!=EINTR, the error was ignored.
+
+	* job.c (set_child_handler_action_flags): New function.
+	(new_job): Use it to temporarily clear the SIGCHLD action flags
+	while reading the token.
+
+2001-05-02  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (start_job_command): Don't add define/endef per-line flags
+	to the top-level flags setting.
+
+2001-04-03  Paul D. Smith  <psmith@gnu.org>
+
+	* arscan.c (VMS_get_member_info,ar_scan) [VMS]: VMS sets the low
+	bit on error, so check for odd return values, not non-0 return
+	values.
+	(VMS_get_member_info): Calculate the timezone differences correctly.
+	Reported by John Fowler <jfowler@nyx.net>.
+
+
+2001-03-14  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (lookup_variable) [VMS]: Null-terminate the variable
+	value before invoking define_variable().
+	Reported by John Fowler <jfowler@nyx.net>.
+
+2001-02-07  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (record_target_var): If we reset the variable due to a
+	command-line variable setting overriding it, turn off the "append"
+	flag.
+
+2001-01-17  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (lookup_variable) [VMS]: When getting values from the
+	environment, allocate enough space for the _value_ plus escapes,
+	not enough space for the name plus escapes :-/.
+	Reported by John Fowler <jfowler@nyx.net>.
+
+	* remake.c (f_mtime): Removed the "***" prefix from the mod time
+	warnings that make generates, so it doesn't look like an error.
+	Reported by Karl Berry <karl@gnu.org>.
+
+
+	Fix for PR/2020:  Rework appended target-specific variables.  I'm
+	fairly confident this algorithm is finally correct.
+
+	* expand.c (allocated_variable_append): Rewrite.  Instead of
+	expanding each appended variable then adding all the expanded
+	strings together, we append all the unexpanded values going up
+	through the variable set contexts, then expand the final result.
+	This behaves just like non-target-specific appended variable
+	values, while the old way didn't in various corner cases.
+	(variable_append): New function: recursively append the unexpanded
+	value of a variable, walking from the outermost variable scope to
+	the innermost.
+	* variable.c (lookup_variable): Remove the code that looked up the
+	variable set list if the found variable was "append".  We don't
+	need this anymore.
+	(lookup_variable_in_set): Make this non-static so we can use it
+	elsewhere.
+	(try_variable_definition): Use lookup_variable_in_set() rather
+	than faking out current_variable_set_list by hand (cleanup).
+	* variable.h: Add a prototype for the now non-static
+	lookup_variable_in_set().
+
+2000-11-17  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (f_mtime) [WINDOWS32]: On various advice, I changed the
+	WINDOWS32 port to assume timestamps can be up to 3 seconds away
+	before throwing a fit.
+
+2000-11-17  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (readline): CRLF calculations had a hole, if you hit the
+	buffer grow scenario just right.  Reworked the algorithm to avoid
+	the need for len or lastlen at all.  Problem description with
+	sample code chages provided by Chris Faylor <cgf@redhat.com>.
+
+2000-10-24  Paul D. Smith  <psmith@gnu.org>
+
+	* gettext.c (SWAP): Declare this with the prototype, otherwise
+	some systems don't work (non-32-bit?  Reported for Cray T3E).
+	Reported by Thorstein Thorsteinsson <thor@signe.teokem.lu.se>.
+
+2000-10-05  Paul D. Smith  <psmith@gnu.org>
+
+	* acinclude.m4 (AM_LC_MESSAGES): Remove undefined macro
+	AM_LC_MESSAGES; it doesn't seem to do anything anyway??
+
+	* i18n/gl.po, configure.in (ALL_LINGUAS): New Galician translation.
+
+2000-09-22  Paul D. Smith  <psmith@gnu.org>
+
+	* gettext.c: Don't #define _GETTEXT_H here; we only include some
+	parts of the real gettext.h here, and we expect to really include
+	the real gettext.h later.  If we keep this #define, it's ignored.
+
+2000-09-21  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (log_working_directory): Rework the text to use complete
+	sentences, to make life simpler for the translators.
+
+2000-08-29  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (remove_intermediates): Print a debug message before we
+	remove intermediate files, so the user (if she uses -d) knows
+	what's going on.
+
+2000-08-21  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (try_variable_definition): Change how we handle
+	target-specific append variable defns: instead of just setting the
+	value, expand it as an append _but_ only within the current
+	target's context.  Otherwise we lose all but the last value if the
+	variable is appended more than once within the current target
+	context.  Fixes PR/1831.
+
+2000-08-16  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (func_shell): Nul-terminate the buffer before
+	printing an exec error message (just in case it's not!).
+	Fixes PR/1860, reported by Joey Hess <joey@valinux.com>.
+
+2000-07-25  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (construct_command_argv_internal): Add "~" to the list of
+	sh_chars[] which disallow optimizing out the shell call.
+
+2000-07-23  Paul Eggert  <eggert@twinsun.com>
+
+	* NEWS, make.texinfo: Document .LOW_RESOLUTION_TIME, which
+	supersedes --disable-nsec-timestamps.
+	* make.texinfo: Consistently use "time stamp" instead of "timestamp".
+	* README: Remove --disable-nsec-timestamps.
+
+	* filedef.h (struct file.low_resolution_time): New member.
+	* file.c (snap_deps): Add support for .LOW_RESOLUTION_TIME.
+	* remake.c (update_file_1):
+	Avoid spurious rebuilds due to low resolution time stamps,
+	generalizing the earlier code that applied only to archive members.
+	(f_mtime): Archive members always have low resolution time stamps.
+
+	* configure.in: Remove --disable-nsec-timestamps, as this has
+	been superseded by .LOW_RESOLUTION_TIME.
+
+2000-07-23  Paul Eggert  <eggert@twinsun.com>
+
+	* configure.in (enable_nsec_timestamps): Renamed from
+	make_cv_nsec_timestamps, since enable/disable options
+	shouldn't be cached.
+
+2000-07-23  Bruno Haible  <haible@clisp.cons.org>
+       and  Paul Eggert  <eggert@twinsun.com>
+
+	* file.c (file_timestamp_now):
+	Use preprocessor-time check for FILE_TIMESTAMP_HI_RES
+	so that clock_gettime is not linked unless needed.
+
+	* filedef.h (FILE_TIMESTAMP_HI_RES):
+	Remove definition; "configure" now does this.
+
+	* configure.in (jm_AC_TYPE_UINTMAX_T): Move up,
+	to before high resolution file timestamp check,
+	since that check now uses uintmax_t.
+	(FILE_TIMESTAMP_HI_RES): Define to nonzero if the code should use
+	high resolution file timestamps.
+	(HAVE_CLOCK_GETTIME): Do not define if !FILE_TIMESTAMP_HI_RES,
+	so that we don't link in clock_gettime unnecessarily.
+
+2000-07-17  Paul D. Smith  <psmith@gnu.org>
+
+	* i18n/ja.po: New version of the translation file.
+
+2000-07-07  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (f_mtime): If NO_FLOAT is defined, don't bother with
+	the offset calculation.
+	(name_mtime): Replace EINTR test with EINTR_SET macro.
+
+2000-07-07  Paul Eggert  <eggert@twinsun.com>
+
+	Fix for PR/1811:
+
+	* remake.c (update_file_1):
+	Avoid spurious rebuilds of archive members due to their
+	timestamp resolution being only one second.
+	(f_mtime): Avoid spurious warnings of timestamps in the future due to
+	the clock's resolution being lower than file timestamps'.
+	When warning about future timestamps, report only the discrepancy,
+	not the absolute value of the timestamp and the current time.
+
+	* file.c (file_timestamp_now): New arg RESOLUTION.
+	* filedef.h (file_timestamp_now): Likewise.
+	(FILE_TIMESTAMP_NS): Now returns int.  All uses changed.
+
+2000-07-05  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (lookup_variable) [VMS]: Remove vestigial references
+	to listp.  Fixes PR/1793.
+
+2000-06-26  Paul Eggert  <eggert@twinsun.com>
+
+	* Makefile.am (MAINTAINERCLEANFILES): New macro, with stamp-pot in it.
+
+	* dir.c (vms_hash): Ensure ctype macro args are nonnegative.
+
+	* remake.c (f_mtime): Remove unused var memtime.
+
+2000-06-25  Martin Buchholz  <martin@xemacs.org>
+
+	* make.texinfo, NEWS, TODO.private: Minor spelling corrections.
+	Ran spell-check	on make.texinfo.
+
+2000-06-23  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Replace EXIT_SUCCESS, EXIT_FAILURE, and
+	EXIT_TROUBLE with MAKE_SUCCESS, MAKE_FAILURE, and MAKE_TROUBLE.
+	* make.h: Define these macros.
+
+	* Version 3.79.1 released.
+
+	* configure.in: Add a new option, --disable-nsec-timestamps, to
+	avoid using sub-second timestamps on systems that support it.  It
+	can lead to problems, e.g. if your makefile relies on "cp -p".
+	* README.template: Document the issue with "cp -p".
+
+	* config.guess, config.sub: Updated.
+
+
+
+
+See ChangeLog.2, available in the CVS repository at:
+
+	http://savannah.gnu.org/cvs/?group=make
+
+for earlier changes.
+
+
+Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/ChangeLog.1
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/ChangeLog.1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/ChangeLog.1	(revision 1780)
@@ -0,0 +1,4999 @@
+Tue Oct 29 20:57:36 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.
+
+	* remake.c (update_file_1): Check for deps still running before
+	giving up if any dep has failed.
+
+Sat Oct 26 16:20:00 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h [uts]: #undef S_ISREG and S_ISDIR if defined.
+
+Fri Oct 25 19:50:39 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.60.17.
+
+Thu Oct 24 16:58:36 1991  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* job.c (start_job): Don't check for empty cmds before tweaking the
+	command_ptr.  Just let construct_command_argv do it.
+
+Tue Oct 22 20:21:03 1991  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* remake.c, arscan.c [POSIX]: <fcntl.h> instead of <sys/file.h>.
+
+	* make.h [POSIX]: Declare vfork as pid_t.
+
+Mon Oct 21 15:37:30 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.60.16.
+
+	* job.c (construct_command_argv, construct_command_argv_internal):
+	Take new 2nd arg RESTP.  If non-NULL, stop parsing at newline, and
+	store addr of the NL in *RESTP.
+	(start_job): Don't chop expanded cmd lines up; use above code to do it.
+	* function.c (expand_function: `shell'): Pass RESTP==NULL.
+
+Sat Oct 19 15:36:34 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.60.15.
+
+Fri Oct 18 15:26:55 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (start_job): If on the same cmds->command_lines elt, look
+	at cmds->lines_recurse[CHILD->command_line - 1] instead of
+	[CHILD->command_line].
+
+	* dir.c [sgi]: <sys/dir.h>, not ndir or anything else.
+
+Thu Oct 17 16:28:55 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* file.c (print_file_data_base): Remove unused var.
+
+	* make.h [NeXT]: No #define ANSI_STRING.
+
+Tue Oct 15 20:08:41 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.60.14.
+
+Fri Oct 11 16:23:52 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* make.h: Use PATH_MAX for getwd defn.
+
+	* make.h: Move getcwd/getwd outside of #ifndef POSIX, and make it
+	#if USG||POSIX.
+
+Thu Oct 10 11:53:31 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.60.13.
+
+	* read.c (read_all_makefiles): When processing MAKEFILES, save the
+	malloc'd ptr to be freed, instead of freeing part-way thru it.
+
+	* remake.c (update_file_1): Don't tweak FILE->also_make.
+	(update_file): Do it here.  After calling update_file_1, set the
+	command_state, update_status, and updated members of each also_make
+	elt to FILE's values.
+
+Tue Oct  8 14:56:04 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* Version 3.60.12.
+
+	* remake.c (notice_finished_file): Set command_state of FILE and
+	its also_make chain to cs_finished here.
+	* commands.c (execute_file_commands), job.c (child_handler),
+	remake.c (remake_file): Don't set it before calling
+	notice_finished_file.
+
+	* file.h (struct file): Changed `also_make' to struct dep *.
+	* job.c (delete_child_targets), file.c (print_file_data_base),
+	remake.c (notice_finished_file), implicit.c (pattern_search):
+	Use dep chain instead of array of file names.
+
+Mon Oct  7 17:04:33 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.60.11.
+
+	* arscan.c: Declare open.
+	* misc.c: Declare {get,set}{re,}[ug]id.
+	* variable.c (target_environment): Declare getenv.
+
+Sat Oct  5 15:13:03 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* make.h [NeXT]: <string.h> instead of <strings.h>.
+
+Fri Oct  4 16:05:41 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* default.c (default_suffixes, defualt_suffix_rules): Add .texi
+	just like .texinfo.
+
+	* Version 3.60.10.
+
+	* job.c: Move vfork decl into make.h.
+
+Fri Sep 27 18:45:30 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* compatMakefile (glob/libglob.a): Pass CC value to submake.
+
+Thu Sep 26 00:08:15 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* load.c (load_average): Made not static.
+
+	* load.c [ultrix && vax]: Define LDAV_TYPE and LDAV_CVT for Ultrix 4.2.
+
+Tue Sep 24 00:17:20 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.60.9.
+
+	* read.c (record_files): Warn about extra cmds even if the target's
+	name begins with a dot.  I think the lusers can handle this.
+
+Mon Sep 23 22:33:26 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h, arscan.c: Don't declare bcmp, bzero, or bcopy if they're
+	#define'd.
+	* make.h: Declare write and open.
+
+	* default.c (default_suffixes, default_suffix_rules,
+	default_variables): Add .C just like .cc.
+	* make.texinfo (Catalogue of Rules): Document .C.
+
+	* make.man (-w): Fix gramo.
+
+Fri Sep 20 17:18:16 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h: No text after #endif.
+
+Sun Sep 15 16:20:46 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* Version 3.60.8.
+
+	* implicit.c (pattern_search): In the second pass, recurse on rule
+	deps that don't have a %.  Why did I make it not do this?
+
+Fri Sep 14 18:29:39 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* read.c (record_files): For extra cmds, use the last ones given.
+	If the target's name doesn't begin with a dot (bletch!!), emit a
+	two-line warning, one line giving the old cmds' location and the
+	other the new cmds' location.
+
+	* misc.c (makefile_error, makefile_fatal): New fns.
+	* make.h: Declare them.
+	* Use them instead of error/fatal for all msgs including a file
+	name and line number.
+
+Thu Sep 13 16:35:54 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* make.h: Declare define_default_variables.
+	Declare ar_parse_name, instead of ar_name_parse (M-t).
+
+Mon Sep 10 18:35:40 1991  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* Version 3.60.7.
+
+	* make.texinfo (Variables: Setting): Say whitespace is removed if
+	"immediately after =", rather than simply "after =".
+
+	* job.c: Don't declare wait #ifdef POSIX.
+
+	* make.h [__GNUC__]: #undef alloca and then #define it.
+
+	* main.c (main): When pruning makefiles which might loop from the
+	read_makefiles chain, look at all `prev' entries of double-colon rules.
+
+Fri Sep  7 00:41:53 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* main.c (main): Only remove makefiles with cmds but no deps from
+	the list of makefiles to be rebuilt if they are :: targets.
+	: targets with cmds and no deps are not dangerous.
+
+Wed Sep  5 17:35:51 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (defines): Add comment that some compilers take
+	ENUM_BITFIELDS but produce bogus code.
+	(LOAD_AVG): Fix examples to \ "s.
+	(LOADLIBES): Add comment that SGI Irix needs -lmld for nlist.
+
+Tue Sep  4 20:26:26 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.60.6.
+
+Fri Aug 30 19:34:04 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* remake.c (update_file_1): When checking the command_state of
+	deps, check through the prev chain.
+	(update_goal_chain): When a target is finished, start checking its
+	prev (if it has one) instead.
+
+Wed Aug  7 17:32:03 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* rule.c (convert_to_pattern): Allow files with deps to define
+	suffix rules (really this time).
+
+Mon Aug  5 17:09:21 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* misc.c (user_access, make_access): Do saved-IDs (USG) flavor
+	#ifdef POSIX.
+
+	* file.c (enter_file): Strip ./s here.
+	* read.c (parse_file_seq): Not here.
+
+Tue Jul 23 23:34:30 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile: Added comment that -lPW alloca is broken on HPUX.
+
+Thu Jul 18 03:10:41 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.60.5.
+
+	* read.c (read_makefile): Ignore lines containing chars that are
+	all isspace, not just all isblank.
+
+	* make.texinfo (Copying): @include gpl.texinfo, rather than copying
+	the text.
+	* gpl.texinfo: New file (symlink to /gd/gnu/doc/gpl.texinfo).
+	* GNUmakefile: Put gpl.texinfo in distribution.
+
+Tue Jul 16 12:50:35 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* make.h: #define _GNU_SOURCE before including headers.
+	Include <ctype.h> and define isblank if <ctype.h> doesn't.
+	* commands.c: Don't include <ctype.h> here.
+	* *.c: Use isblank instead of explicit ' ' || '\t'.
+
+Mon Jul 15 17:43:38 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* function.c (expand_function: `filter'/`filter-out'): Fixed to not
+	loop infinitely.
+
+Fri Jul 12 12:18:12 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* function.c (expand_function: `filter'/`filter-out'): Rewritten to
+	handle filter-out of multiple patterns properly.  Also no longer
+	mallocs and reallocs for temp array; uses alloca and a linked-list
+	instead.
+
+Wed Jul 10 22:34:54 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.60.4.
+
+	* make.texinfo: Moved some @groups that were outside @examples to
+	be inside them.
+
+	* load.c [apollo] (load_average): Define using special syscall for
+	Apollo DOMAIN/OS SR10.n.
+
+Thu Jul  4 12:32:53 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* make.texinfo (Missing): Added Unix excessive implicit rule
+	search; mention that POSIX.2 doesn't require any of the missing
+	features.
+	(Top): Updated printed manual price to $15.
+
+Wed Jul  3 18:17:50 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* file.c (rename_file): Carry over last_mtime when merging files.
+	* remake.c (f_mtime): Tail-recurse after renaming VPATH file, to
+	check for saved date in existing renamed-to file.
+
+	* remote-cstms.c (start_remote_job): Use PATH_VAR.
+
+	* commands.c [POSIX || __GNU_LIBRARY__]: Don't declare getpid.
+
+	* compatMakefile (glob-{clean,realclean}): Run clean/realclean in glob.
+	(clean, realclean): Require those.
+
+	* make.h: Always declare environ.
+	Don't declare old glob functions.
+
+	* GNUmakefile: Make no-lib deps for load.c and remote.c.
+
+Tue Jul  2 18:35:20 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.60.3.
+
+Mon Jul  1 16:58:30 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (multi_glob): Don't pass GLOB_QUOTE flag to glob.
+
+	* make.h [POSIX]: Include <unistd.h>, and don't declare things that
+	should be there.
+
+	* main.c (main) [USG && sgi]: malloc a buffer for broken sgi stdio.
+
+Sat Jun 29 11:22:21 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* function.c (expand_function: `shell'): Use alloca for the error
+	msg buffer, instead of assuming an arbitrary max size.
+
+Fri Jun 28 18:15:08 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c [POSIX] (search_path): Do real 1003.1 goop to get NGROUPS_MAX.
+
+Wed Jun 26 11:04:44 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* default.c (define_default_variables): New fn.
+	(install_default_implicit_rules): Code for above fn moved there.
+	* main.c (main): Do define_default_variables before reading the
+	makefile.
+
+Tue Jun 25 17:30:46 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* main.c (main): Quote ; in MAKEOVERRIDES.
+
+Tue Jun 18 13:56:30 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* compatMakefile: Fixed typo in comment.
+
+Tue Jun 11 00:14:59 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* Version 3.60.2.
+
+Mon Jun 10 14:46:37 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h: Always include <sys/types.h>.
+	[POSIX]: Include <limits.h> and #define MAXPATHLEN to be PATH_MAX.
+
+	* default.c (default_suffix_rules: .texinfo.dvi): Use $(TEXI2DVI).
+	(default_variables): Define TEXI2DVI.
+
+Thu Jun  6 16:49:19 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.60.1.
+
+	* make.h (SIGNAL): Cast handler arg to SIGHANDLER type.
+
+Wed Jun  5 06:00:43 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* read.c (multi_glob): Use POSIX.2 `glob' function.
+	If a glob pattern matches nothing, leave it as is (a la sh, bash).
+	Also, if can't find USER for ~USER, leave it as is (a la bash).
+
+Mon Jun  3 16:36:00 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* compatMakefile: Rewrote comments about -Ds to be easier to use.
+
+	* make.h, arscan.c, remake.c, main.c, dir.c, job.c: Changed tests
+	of _POSIX_SOURCE to POSIX.
+
+	* job.c: Take getdtablesize out of #ifdef __GNU_LIBRARY__.
+	Put separately #ifdef USG.
+
+	* COPYING: Replaced with version 2.
+	* Changed copyright notices to refer to GPL v2.
+
+Thu May 30 00:31:11 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h: Don't declare sigblock for POSIX.
+
+	* main.c (main, log_working_directory) [USG]: Get getcwd failure
+	mode from errno, not passed buffer like BSD getwd.
+
+	* misc.c (child_access): New fn to set access for a child process;
+	like user_access, but you can't change back.
+	* make.h: Declare it.
+	* job.c (exec_command): Use it in place of user_access.
+
+Wed May 29 23:28:48 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* default.c (default_variables) [pyr]: PC = pascal.
+
+Tue May 28 20:24:56 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* variable.c (print_variable): Put a newline before `endef'.
+
+Sat May 25 02:39:52 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.60.
+
+Wed May 22 19:41:37 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.59.5.
+
+Thu May 16 13:59:24 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (main): Do USGr3 setvbuf behavior #ifdef APOLLO.
+	Don't handle SIGCHLD #ifdef USG (Apollo is USG but defines SIGCHLD).
+
+Fri May 10 14:59:33 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* remake.c [sgi]: Don't include <sys/file.h>.
+
+Wed May  8 01:54:08 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* make.h (SIGHANDLER): #define as (void *) #if __STDC__,
+	else (int (*)()).
+	(SIGNAL): Use it to cast return value.
+	* main.c (main): Cast SIG_IGN to SIGHANDLER when comparing.
+	* job.c (block_signals, unblock_signals): Use SIGNAL instead of signal.
+
+	* main.c: Declare mktemp to return char*, not int.
+
+	* job.c (new_job): Don't increment files_remade.
+	* remake.c (notice_finished_file): Do it here.
+
+	* read.c (do_define): Don't clobber DEFINITION[-1] on empty defns.
+	Free storage that is no longer needed.
+
+Wed Apr 24 20:49:48 1991  Roland McGrath  (roland at churchy.gnu.ai.mit.edu)
+
+	* misc.c (message): New fn to print informational msgs with
+	leading "make: " or "make[N]: ".
+	* make.h: Declare it.
+	* remake.c (update_file): Use it instead of printf.
+
+Fri Apr 19 05:52:45 1991  Roland McGrath  (roland at churchy.gnu.ai.mit.edu)
+
+	* main.c (main): When there are no targets, if there were no
+	makefiles, print a different error message, which mentions makefiles.
+
+Tue Apr 16 03:22:45 1991  Roland McGrath  (roland at geech.gnu.ai.mit.edu)
+
+	* remake.c (update_file): Print "nothing to be done" instead of "is
+	up to date" if FILE->cmds == 0.
+
+	* job.c [!WIFEXITED]: Define if not already defined.
+
+Thu Apr 11 18:00:50 1991  Roland McGrath  (roland at wookumz.gnu.ai.mit.edu)
+
+	* arscan.c (ar_name_equal): Fixed truncation comparison.
+
+Tue Apr  2 16:17:35 1991  Roland McGrath  (roland at churchy.gnu.ai.mit.edu)
+
+	* glob.c: Use common version from djm.
+	* dir.c: Snarfed #ifdef mess for <dirent.h> or whatever from glob.c.
+	(dir_file_exists_p): Ignore directory entries with d_ino==0.
+
+Mon Apr  1 20:49:45 1991  Roland McGrath  (roland at albert.gnu.ai.mit.edu)
+
+	* Version 3.59.4.
+
+Fri Mar 29 19:16:18 1991  Roland McGrath  (roland at albert.gnu.ai.mit.edu)
+
+	* job.c (free_child): Free CHILD->environment and its elts.
+
+Sat Mar 23 14:08:09 1991  Roland McGrath  (roland at albert.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Don't ignore lines containing only
+	comments if they start with a tab.  Such lines should be passed to
+	the shell for it to decide about the comments.
+
+	* job.c (free_child): Free CHILD->command_lines and its elts, not
+	CHILD->commands (which is obsolete).
+	* job.h, job.c: Remove obsolete `commands' member of `struct child'.
+
+Sun Mar 17 18:40:53 1991  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* remake.c (update_file): Print a msg for a top-level up-to-date
+	phony target (a different one than for a real file).
+
+	* read.c (conditional_line): Boundary check so we don't check the
+	value of the -1th elt of the stack (which is bogus).
+
+Sat Mar 16 16:58:47 1991  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* read.c (conditional_line): Don't evaluate an if* when we're
+	already ignoring.  Instead, just push a new level, with a value of
+	1, to keep ignoring.
+
+Tue Mar 12 00:16:52 1991  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* Version 3.59.3.
+
+Mon Mar 11 23:56:57 1991  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): Quote backslashes
+	when building the shell -c line.
+
+Fri Mar  8 01:40:18 1991  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* job.c (exec_command): Call user_access rather than setgid(getgid()).
+
+	* misc.c (remove_comments): Renamed from collapse_line; took out
+	collapse_continuations call.
+	* make.h: Change decl.
+	* read.c (read_makefile): Collapse continuations on the line buffer
+	immediately after reading it.  Call remove_comments rather than
+	collapse_line (which is now defunct).
+
+Thu Feb 21 18:06:51 1991  Roland McGrath  (mcgrath at cygint.cygnus.com)
+
+	* misc.c (user_access, make_access): New fns to toggle btwn permissions
+	for user data (files and spawning children), and permissions for make
+	(for taking the load average, mostly).
+	* make.h: Declare them.
+	* job.c (start_job): Call make_access before wait_to_start_job, and
+	user_access after.
+	* main.c (main): Call user_access before doing much.
+
+Mon Feb  3 15:02:03 1991  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* Version 3.59.2.
+
+Tue Jan 29 20:30:50 1991  Roland McGrath  (roland at cygint.cygnus.com)
+
+	* read.c (read_all_makefiles): Use allocated_variable_expand to expand
+	`$(MAKEFILES)', since the results are used across calls to
+	read_makefile, which could clobber them.
+
+Wed Jan 23 00:24:10 1991  Roland McGrath  (roland at cygint.cygnus.com)
+
+	* main.c (main): Call install_default_implicit_rules after reading
+	makefiles, not before.
+	* default.c (install_default_implicit_rules): If a suffix-rule file
+	entry has cmds, don't give it any from default_suffix_rules.
+
+Fri Jan 17 17:39:49 1991  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* arscan.c: Added support for AIX archives.
+
+	* remake.c: Don't include ar.h.
+	* main.c: Removed unused atol decl.
+	* arscan.c (ar_scan): Declare arg FUNCTION to return long int.
+	* ar.c (ar_touch): Don't perror for an invalid archive.
+	* make.h: Declare lseek as long int.
+
+	* job.c [hpux]: Define getdtablesize a la USG.
+
+Sun Jan 12 21:08:34 1991  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* Version 3.59.1.
+
+Fri Jan 10 03:48:08 1991  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* job.c (search_path): Take new arg, place to put full pathname (rather
+	than mallocing it).
+	(exec_command): Pass it, using auto storage.
+
+	* main.c (print_version): Updated copyright years.
+
+Wed Jan  8 19:46:19 1991  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* job.c [_POSIX_SOURCE]: Just #include <sys/wait.h>, and define macro
+	WAIT_NOHANG in terms of waitpid.
+	[!_POSIX_SOURCE && (HAVE_SYS_WAIT || !USG)]: Don't #include <signal.h>
+	(make.h does).
+	Define macro WAIT_NOHANG in terms of wait3.
+	(child_handler): #ifdef on WAIT_NOHANG, not HAVE_SYS_WAIT || !USG.
+	Use WAIT_NOHANG macro instead of wait3.
+
+	* file.h (struct file.command_state): Remove unused elt.
+
+Wed Dec 26 18:10:26 1990  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* commands.c (set_file_variables): If FILE got its commands from
+	.DEFAULT, make $< == $@ (4.3 BSD/POSIX.2d11 compat).
+
+Mon Dec 24 17:36:27 1990  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* default.c (default_variables): Rename 2nd LINK.s defn to LINK.S.
+
+Fri Dec 14 15:05:25 1990  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* vpath.c (selective_vpath_search): Check for makefile-mentioned before
+	checking for actual existence.  The old order loses if the containing
+	directory doesn't exist (but a rule might make it).
+
+	* make.h [__GNUC__]: Don't #define alloca if already #define'd.
+
+	* rule.c (convert_to_pattern): Don't look at the target constructed for
+	the empty rule when making the null-suffix rule.  Construct it over
+	again, since the former may have been freed already.
+
+Thu Dec 13 17:21:03 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* make.h [__GNU_LIBRARY__]: Include <unistd.h> to get random fn decls.
+
+Wed Dec 12 17:12:59 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* make.h, arscan.c, glob.c: Only include <memory.h> #ifdef USG.
+
+	* variable.c (define_variable_in_set): Replace env_overrides check that
+	wasn't really redundant (undoing Sep 28 change).  Add comment saying
+	why this check is necessary.
+
+	* job.c, main.c [DGUX]: Needs siglist like USG.
+
+Mon Dec 11 01:19:29 1990  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* default.c [M_XENIX]: For rules that are different for Xenix, use the
+	generic Unix version #ifdef __GNUC__.
+
+	* main.c [M_XENIX]: Use USGr3-style setvbuf call.
+
+	* read.c (find_percent): Do backslash folding correctly, not leaving
+	extra crud on the end of the string.
+
+Sun Dec 10 21:48:36 1990  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* job.c: Don't declare wait3 if it's #defined.
+
+	* GNUmakefile, compatMakefile, make.texinfo: Change make-info
+	to make.info.
+
+Thu Dec  7 21:20:01 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* make.h [STDC_HEADERS || __GNU_LIBRARY__ || _POSIX_SOURCE]: Use
+	ANSI <string.h> and names for str/mem functions.
+	Use <stdlib.h> to declare misc fns rather than explicit decls.
+	[_POSIX_SOURCE]: Don't declare kill (<signal.h> will).
+	Include <sys/types.h> before <signal.h> because some braindead
+	nonconformant 1003.1 implementation needs it.
+	* misc.c: Don't declare malloc, realloc.  Do it in make.h.
+	* arscan.c, glob.c: Use sequence for string fns from make.h verbatim.
+	* make.h (S_ISDIR, S_ISREG): Declare if necessary.
+	* commands.c (delete_child_targets), job.c (search_path), read.c
+	(construct_include_path): Use S_ISfoo(m) instead of
+	(m & S_IFMT) == S_IFfoo.
+	* dir.c, glob.c [_POSIX_SOURCE]: Use dirent.
+
+Wed Nov 29 22:53:32 1990  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* Version 3.59.
+
+Tue Nov 28 16:00:04 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* arscan.c (ar_name_equal) [APOLLO]: Don't do `.o' hacking.  On Apollos
+	the full file name is elsewhere, and there is no length restriction (or
+	so I'm told).
+
+Thu Nov 23 17:33:11 1990  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* load.c [hp300 && BSD] (LDAV_CVT): Define for this system.
+
+Tue Nov 21 07:58:40 1990  Roland McGrath  (roland at albert.ai.mit.edu)
+
+	* read.c (record_files): Fix trivial bug with deciding to free storage
+	for a file name.
+
+Thu Nov 16 06:21:38 1990  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* compatMakefile ($(bindir)/make): Install it setgid kmem.
+
+Thu Nov  1 16:12:55 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* GNUmakefile (make-*.tar.Z): Use `h' option to tar (dereference
+	symlinks), to grab texinfo.tex from wherever it lives.
+
+Tue Oct 30 16:15:20 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* Version 3.58.13.
+
+Fri Oct 26 14:33:34 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* GNUmakefile: make-*.tar.Z: Include texinfo.tex.
+
+Tue Oct 23 19:34:33 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* main.c (define_makeflags): When there are no flags to write, make
+	sure the array has two leading nulls, since `MAKEFLAGS' is defined from
+	&flags[1].
+
+	* main.c (default_keep_going_flag): New variable (constant one).
+	(command_switches: -k, -S): Use above for default value.
+	(define_makeflags): Only write flag/flag_off switches if they are on,
+	and either there is no default value, or they are not the default.
+
+Mon Oct 22 16:14:44 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* main.c (struct command_switch): New member `no_makefile'.
+	(command_switches: -n, -q, -t): Set no_makefile == 1.
+	(define_makeflags): Take new arg MAKEFILE: if nonzero, don't use
+	options whose `no_makefile' flags are set.
+	(main): Call define_makeflags with MAKEFILE==1 before remaking
+	makefiles, and again with MAKEFILE==0 before remaking goals.
+
+Tue Oct  2 17:16:45 1990  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* Version 3.58.12.
+
+Mon Oct  1 15:43:23 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* arscan.c [HPUX]: Use PORTAR==1 format.
+
+Sat Sep 29 16:38:05 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* make.h, remake.c, arscan.c: Don't declare `open'.
+
+Fri Sep 28 04:46:23 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* variable.c (define_variable_in_set): Remove redundant -e check.
+
+Wed Sep 26 00:28:59 1990  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* job.c (start_job): Set RECURSIVE from the right elt of
+	CHILD->file->cmds->lines_recurse.
+
+	* commands.c (chop_commands): Don't botch the line count for allocating
+	CMDS->lines_recurse.
+
+	* Version 3.58.11.
+
+	* job.c (start_job): Don't always increment CHILD->command_line!  Only
+	do it when CHILD->command_ptr has run out!  (Dumb bug.  Sigh.)
+
+Thu Sep 20 02:18:51 1990  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* GNUmakefile [ARCH]: Give explicit rule for remote.{c,dep} to use
+	variable `REMOTE' for more flags.
+	($(prog)): Link in $(LOADLIBES).
+
+Wed Sep 19 02:30:36 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* commands.h (struct commands): New member `ncommand_lines', the number
+	of elts in `command_lines' et al.
+	* commands.c (chop_commands): Set `ncommand_lines' elt of CMDS, and
+	don't put a nil pointer at the end of `command_lines'.
+	* job.h (struct child): New member `command_lines' to hold
+	variable-expanded command lines.
+	* job.c (new_job): Store expanded command lines in `command_lines'
+	member of new child.  Don't clobber FILE->cmds.
+	(start_job): Use CHILD->command_lines in place of
+	CHILD->file->cmds->command_lines.
+
+	* variable.h, variable.c, job.c, expand.c: Undo yesterday's change,
+	which is no longer necessary since we have cleverly avoided the issue.
+
+	* job.c (start_job): Don't variable-expand each command line.
+	(new_job): Do them all here, storing the expansions in the array.
+
+Tue Sep 18 01:23:13 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* variable.h (struct variable): Remove `expanding' member.
+	* variable.c (define_variable_in_set): Don't initialize it.
+	* expand.c (struct variable_expanding): New type, a linked list
+	containing `struct variable' pointers.
+	(variables_expanding): New variable, the chain of variables currently
+	being expanded.
+	(recursively_expand): Don't test and set `expanding' member.
+	Instead, run through the `variables_expanding' chain looking for a link
+	referring to V to find self-reference.  Add a new link to the chain,
+	describing V, before recursive expansion, and pop it off afterward.
+	* job.c (child_handler): Save `variables_expanding' and clear it before
+	calling start_job, and restore it afterward.  This avoids major lossage
+	when the SIGCHLD comes in the middle of variable expansion.
+
+Mon Sep 17 14:46:26 1990  Roland McGrath  (roland at geech.ai.mit.edu)
+
+	* job.c, commands.c: Don't define sigmask.
+	* make.h: Put it here instead.
+
+	* variable.c (target_environment): If `.NOEXPORT' was specified as a
+	target, only export command-line and environment variables, and
+	file-origin variables that were in the original environment.
+
+	* make.man: Add missing ?roff control for `-I' option description.
+
+Thu Sep 13 14:10:02 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* load.c [UMAX]: Move #include <sys/sysdefs.h> to [not UMAX_43].
+
+Wed Sep 12 15:10:15 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* expand.c (recursively_expand): Don't use `reading_filename' and
+	`reading_lineno_ptr' if they're nil.
+
+Thu Aug 30 17:32:50 1990  Roland McGrath  (roland at geech)
+
+	* Version 3.58.10.
+
+Tue Aug 28 04:06:29 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* job.c [USG] (unknown_children_possible): New variable, set nonzero
+	when it's possible for children not in the `children' chain to die.
+	(block_signals) [USG]: Set it.
+	(unblock_signals) [USG]: Clear it.
+	(child_handler) [USG]: Don't complain about unknown children if
+	`unknown_children_possible' is set.
+
+	* read.c (do_define): Make sure there's enough space for the newline,
+	so we don't write off the end of allocated space.
+
+	* arscan.c (ar_name_equal): Fixed to work when MEM is AR_NAMELEN-1 but
+	NAME is not the same length.
+
+Sat Aug 25 16:17:14 1990  Roland McGrath  (roland at geech)
+
+	* job.c (construct_command_argv_internal): Use a static char array for
+	a constant, since old C has no auto aggregate initializers.
+
+Thu Aug 23 16:11:03 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* job.c (search_path): If PATH is nil or "" use a default path.
+
+Wed Aug 22 01:05:32 1990  Roland McGrath  (roland at churchy.ai.mit.edu)
+
+	* Version 3.58.9.
+
+	* job.c (exec_command): Don't take PATH and SHELL args.  Get them from
+	ENVP.
+	(child_execute_job): Don't take FILE arg, and don't pass path and shell
+	to exec_command.
+	(start_job): Don't pass FILE arg to child_execute_job.
+	* function.c (expand_function: `shell'): Ditto.
+	* main.c (main): Don't pass path and shell to exec_command.
+
+Fri Aug 17 23:17:27 1990  Roland McGrath  (roland at geech)
+
+	* job.c (construct_command_argv_internal): New fn broken out of
+	construct_command_argv.  Takes strings SHELL and IFS instead of doing
+	variable expansion for them.  Recurse to make an argv for SHELL,
+	passing SHELL==0.  When SHELL==0, don't recurse for shell argv; make a
+	simple one using /bin/sh.
+	(construct_command_argv): Do the variable expansions and call above.
+
+Thu Aug 16 19:03:14 1990  Roland McGrath  (roland at geech)
+
+	* read.c (multi_glob): For ~USER/FILE, if USER isn't found, don't
+	change the file name at all.
+
+Tue Aug  7 18:33:28 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* function.c (expand_function: `suffix'/`notdir'): Don't kill the last
+	space if we never wrote one.
+
+	* function.c (expand_function: `suffix'): Retain the dot, like the
+	documentation says.
+
+Mon Aug  6 14:35:06 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.58.8.
+
+	* main.c (decode_switches): For positive_int and floating cases, move
+	SW past the arg (and don't set it to ""), so another switch can follow.
+
+Fri Aug  3 00:43:15 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* job.c (child_execute_job): Use unblock_signals instead of
+	push_signals_blocked_p (0).
+
+	* main.c (fatal_signal_mask): New variable, mask of signals caught with
+	fatal_error_signal.
+	(main): Set it.
+	* job.c ({block,unblock}_children): Renamed to {block,unblock}_signals.
+	Block/unblock both child signal and signals in fatal_signal_mask.
+	(children_blocked_p_{stack,max,depth}, {push,pop}_children_blocked_p):
+	Renamed from children to signals.  Use {block,unblock}_signals instead
+	of {block,unblock}_children.
+	* commands.c (fatal_error_signal), job.c (wait_for_children, new_job,
+	child_execute_job, main, log_working_directory), function.c
+	(expand_function: `shell'), job.h: Rename {push,pop}_children_blocked_p
+	to {push,pop}_signals_blocked_p.
+	* job.c (child_handler): Call {block,unblock}_signals instead of just
+	{block,unblock}_remote_children.  We need to block the fatal signals.
+
+Thu Aug  2 22:41:06 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* main.c, function.c: Fixed typos in comments.
+
+	* file.c (print_file_data_base): Fix computation of avg files/bucket.
+
+Tue Jul 31 22:11:14 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.58.7.
+
+Wed Jul 25 16:32:38 1990  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* arscan.c (ar_name_equal): Fixed to really do it right.
+	(ar_member_pos): Fixed order of args.
+	* ar.c (ar_member_date_1): Ditto.
+
+Fri Jul 20 15:30:26 1990  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* arscan.c (ar_name_equal): Rewritten.  Accounts for a possible
+	trailing slash in MEM.
+
+	* remake.c (f_mtime): Keep track of whether ARNAME is used and free it
+	if not.  Also free MEMNAME.
+	* ar.c (ar_member_date, ar_touch): Ditto.
+
+	* arscan.c (arscan) [HPUX or hpux]: Treat same as USGr3 PORTAR==1.
+
+	* make.h: If NSIG is not defined, but _NSIG is, #define NSIG _NSIG.
+
+	* compatMakefile: Don't use $* in explicit rules.
+
+	* default.c (default_variables: "PREPROCESS.S"): Include $(CPPFLAGS).
+
+	* remake.c (f_mtime): If FILE is an ar ref, get the member modtime.
+
+	* function.c (string_glob): Terminate the string properly when it's
+	empty.
+
+Wed Jul 18 11:26:56 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.58.6.
+
+	* commands.c (set_file_variables): Fixed computation for ^F/?F elt len.
+
+Sat Jul 14 13:41:24 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* job.c (construct_command_argv): Always use
+	allocated_variable_expand_for_file instead of variable_expand_for_file
+	because we might be called from inside a variable expansion (for the
+	`shell' function).
+
+	* function.c (expand_function: `shell'): Free the arglist's storage
+	correctly.  construct_command_argv only allocates ARGV and ARGV[0].
+
+	* job.c (children_blocked_p_idx): Renamed to children_blocked_p_depth.
+	(push_children_blocked_p, pop_children_blocked_p): Use ..._depth
+	instead of ..._idx, and do it right!
+
+Wed Jul 11 15:35:43 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* make.h (SIGNAL): New macro to replace `signal' calls.  Does arg and
+	ret value casts to (void *) #ifdef __STDC__ to avoid conflicts btwn
+	ANSI and BSD `signal' and handler types.
+	* main.c (main), job.c (child_handler): Use it.
+
+Fri Jul  6 00:00:38 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* ar.c (ar_member_date, ar_touch): Pass 2nd arg to f_mtime.
+
+	* read.c (read_makefile): Search the include path for MAKEFILES
+	variable makefiles (TYPE == 1), like it says in the manual.
+
+	* file.h (struct file), main.c (struct command_switch): Remove trailing
+	commas from enums.
+
+	* commands.c (execute_file_commands): Remove unused variables.
+	* commands.h: Declare chop_commands.
+	* make.h: Declare uniquize_deps.
+	* main.c (main): Remove unused variable.
+	(decode_switches): Remove unused label.
+	* remake.c: Include "ar.h" for ar_parse_name decl.
+	* implicit.c (try_implicit_rule): Remove unused variable.
+	* function.c (expand_function: `shell'): Declare fork, pipe.
+	* ar.c: Declare ar_name_equal.
+
+	* GNUmakefile: If using gcc, add warning flags to CFLAGS.
+
+	* remake.c: Remove decl of ar_member_date, since it's done in make.h.
+
+	* remake.c (f_mtime): For ar refs, allow the archive to be found via
+	VPATH search if we're searching, and change the ar ref accordingly.
+
+	* ar.c (ar_parse_name): New global fn to parse archive-member
+	references into the archive and member names.
+	(ar_member_date, ar_touch): Use it.
+	* make.h: Declare it.
+
+	* remake.c (f_mtime): After doing rename_file, do check_renamed instead
+	of assuming rename_file will always set FILE->renamed (which it won't).
+
+	* vpath.c (selective_vpath_search): Only accept prospective files that
+	don't actually exist yet are mentioned in a makefile if the file we are
+	searching for isn't a target.
+
+Wed Jul  4 04:11:55 1990  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* remake.c (update_goal_chain): Do check_renamed after calling
+	file_mtime.
+	(check_dep): Ditto after update_file.
+
+	* file.c (rename_file): Prettied up long message for merging cmds.
+
+	* remake.c (update_file_1): Get each dep file's modtime, and allow for
+	it being renamed, before checking for a circular dep, since a renaming
+	may have introduced one.
+
+Tue Jul  3 18:15:01 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* ar.c (ar_touch): Don't free ARNAME since enter_file holds onto the
+	storage.
+
+	* function.c (string_glob): Don't leave a trailing space.
+
+	* read.c (do_define): Allow leading whitespace before `endef'.
+
+Mon Jul  2 14:10:16 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* implicit.c (pattern_search): No longer take NAME arg.  Instead take
+	ARCHIVE flag.  If ARCHIVE is nonzero, FILE->name is of the form
+	"LIB(MEMBER)"; rule for "(MEMBER)" is searched for, and LASTSLASH is
+	set to nil.  Since NAME was only non-nil when it was the archive member
+	name passed by try_implicit_rule, this change easily allows turning off
+	LASTSLASH checking for archive members without excessive kludgery.
+	(try_implicit_rule): Pass ARCHIVE flag instead of file name.
+
+	* Version 3.58.5.
+
+	* commands./c (set_file_variables): Don't kill last char of $(^D) elts.
+
+Sat Jun 30 00:53:38 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* ar.c (ar_member_date): Don't free ARNAME since enter_file holds onto
+	the storage.
+
+	* arscan.c (ar_scan) [sun386 && PORTAR == 1]: Treat like USGr3.
+
+Wed Jun 27 14:38:49 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* main.c (main): Put a newline on the debugging message when deciding
+	not to remake a makefile to avoid a possible loop.
+	Only decide not to remake makefiles that have commands (as well as
+	being targets and having no deps).
+
+Fri Jun 22 12:35:37 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* default.c (default_variables): Define `LINK.s' and `LINK.S'.
+	(default_suffix_rules): Define .S.o rule.
+
+	* job.c (construct_command_argv): If we decide to go the slow route,
+	free all storage for the chopped args.
+	(start_job): Free the argument list's storage correctly.
+	construct_command_argv only allocates ARGV and ARGV[0].
+
+Tue Jun 19 18:27:43 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.58.4.
+
+Fri Jun 15 21:12:10 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* glob.c: New version from ai-lab which doesn't do [^abc].
+
+Thu Jun  7 00:30:46 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* dir.c: Copied dirent vs direct et al mess from glob.c.
+
+	* glob.c: Replaced with updated version from djm.
+	* glob.c: Check macro DIRENT instead of _POSIX_SOURCE for <dirent.h>.
+	__GNU_LIBRARY__ implies DIRENT and STDC_HEADERS.
+
+Thu May 31 22:19:49 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* vpath.c (vpath_search): Don't stop the loop if a pattern matches but
+	the search fails.  All matching patterns have their paths searched
+	(like it says in the manual).
+
+	* make.texinfo (Rules: Directory Search: Selective Search): Say that
+	multiple `vpath' directives with the same pattern DO accumulate, not
+	supersede earlier ones.
+
+	* vpath.c (print_vpath_data_base): Increment the count of vpaths on
+	each loop iteration, rather than letting it stay zero.
+
+	* Version 3.58.3.
+
+	* job.c (block_children, unblock_children): Made static.
+	(push_children_blocked_p, pop_children_blocked_p): New functions to
+	push and pop whether children are blocked or not.
+	* job.h: Declare push_children_blocked_p, pop_children_blocked_p and
+	not block_children, unblock_children.
+	* commands.c (fatal_error_signal), job.c (wait_for_children, new_job,
+	child_execute_job), main.c (main, log_working_directory): Use sequences
+	of push_children_blocked_p (1) and pop_children_blocked_p () instead of
+	explicitly blocking and unblocking children.
+	* function.c (expand_function: `shell'): Don't unblock children.  The
+	push-pop sequence in wait_for_children makes it unnecessary.
+
+Tue May 29 21:30:00 1990  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* read.c (do_define): Don't include the last newline in the definition.
+
+	* function.c (expand_function: `shell'): Call construct_command_argv
+	before forking and don't fork if it returns nil.  Free the argument
+	list's storage before finishing.
+
+	* job.c (start_job): Free the storage for the child's argument list
+	in the parent side of the fork after the child has been spawned.
+
+	* job.c (start_job): If construct_command_argv returns nil, go to the
+	next command line.
+
+	* job.c (construct_command_argv): Use the shell if the command contains
+	an unterminated quote.
+
+Wed May 23 19:54:10 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.58.2.
+
+	* read.c (read_makefile): Parse "override define" correctly.
+
+Thu May 17 15:25:58 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* arscan.c [USG]: Don't declare memcpy and memcmp.  <memory.h> should
+	do this anyway (and lack of declarations is harmless).
+
+	* remote-customs.c: Renamed to remote-cstms.c for System V.
+	* remote.c [CUSTOMS]: Changed accordingly.
+
+Sun May 13 14:38:39 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* GNUmakefile: Use same cmds for doc tar.Z as for dist tar.Z (so the
+	contents go in make-N.NN).
+
+Thu Apr 26 19:33:25 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.58.1.
+
+Wed Apr 25 20:27:52 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* job.c (init_siglist): Don't do SIGUSR1 and SIGUSR2 if they are the
+	same as SIGIO and SIGURG (true on Cray).
+
+Tue Apr 24 20:26:41 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* arscan.c (ar_scan): Do behavior for PORTAR == 1 and USGr3 also
+	#ifdef APOLLO.
+
+Wed Apr 11 10:00:39 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* job.c (exec_command): Set the effective GID to the real GID.  Somehow
+	this code got lost.
+
+	* implicit.c (pattern_search): Use the right index variable when
+	seeing if we need to expand FILE->also_make.
+
+Sun Mar  4 09:18:58 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.58.0.
+
+	* remake.c (remake_file): Treat non-targets without commands under -t
+	the same as anything else without commands.
+
+Sat Feb 24 17:46:04 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* default.c (default_variables: PREPROCESS.S): Removed $< from defn.
+
+	* main.c (main): Ignore arguments that are the empty string, rather
+	than feeding them to enter_file and barfing therein.
+
+Wed Feb 14 16:28:37 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* main.c (main): Call construct_include_path after doing chdirs.
+
+Thu Feb  8 13:43:44 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.58.
+
+Sat Feb  3 22:06:55 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.57.7.
+
+	* make.texinfo (Implicit: Catalogue of Rules): For RCS, noted that
+	working files are never overwritten by the default rule.
+
+Thu Feb  1 17:27:54 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* rule.c (count_implicit_rule_limits): Redid loop control to not run
+	twice on freed rules.
+
+	* GNUmakefile: Made `.dep' files be architecture-specific too.
+
+	* main.c (main, log_working_directory) [USG]: Block children around
+	calls to `getwd' (actually `getcwd' on USG), because that function
+	sometimes spawns a child running /bin/pwd on USG.
+
+Tue Jan 30 14:02:50 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* function.c (subst_expand): Pay attention to SUFFIX_ONLY, putz.
+
+Wed Jan 24 21:03:29 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* make.man: Fixed repeated word.
+
+	* make.texinfo (Missing): Reworded a buggy sentence.
+
+Mon Jan 22 12:39:22 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* main.c (print_version): Added 1990 to copyright notice.
+
+	* Version 3.57.6.
+
+Sat Jan 20 11:52:01 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* file.c (rename_file): Don't free the storage for the old name, since
+	it might not have been malloc'd.
+
+	* job.c (construct_command_argv): Call
+	allocated_variable_expand_for_file instead of variable_expand_for_file
+	to expand `$(SHELL)'.
+
+	* make.texinfo (Bugs): Change address from roland@wheaties.ai.mit.edu
+	to roland@prep.ai.mit.edu.
+
+Tue Jan 16 19:22:33 1990  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Version 3.57.5.
+
+Sun Jan 14 16:48:01 1990  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* job.c (start_job): Only call wait_to_start_job for the first command
+	line in each sequence.
+
+Thu Jan  4 14:27:20 1990  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* load.c [LDAV_BASED] (wait_to_start_job): Loop while job_slots_used >
+	0, not > 1.
+
+	* job.c (search_path): Don't return a pointer to local storage.
+	Allocate data space for the pathname instead.
+
+	* function.c (expand_function: `shell'): Don't write garbage if the
+	child wrote no output.
+
+Wed Jan  3 15:28:30 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.57.4.
+
+	* file.h (struct file): New member `renamed', a `struct file *' that is
+	the place this file has been renamed to (or nil).
+	(check_renamed): Macro to check for a file having been renamed.
+	Dereferences the renaming and sets the given variable.
+	* file.c (rename_file): Completely rewritten.  Renames in place if
+	possible, or moves FILE to a different hash bucket if there is no
+	existing file with the new name.  If there is an existing file with the
+	new name, FILE is merged into it and FILE->renamed is set to point to
+	it.
+	* variable.c (merge_variable_sets): New fn to merge two variable sets.
+	(merge_variable_set_lists): New fn to merge two variable set lists.
+	* variable.h: Declare merge_variable_set_lists.
+	* remake.c (update_file_1, check_dep): Run `check_renamed' after
+	calling file_mtime, check_dep.
+	(update_file): Same after update_file_1.
+	(update_goal_chain, update_file_1, check_dep): Same after update_file.
+
+	* read.c (uniquize_deps): New fn, broken out of record_files, to remove
+	duplicate deps from a chain.
+	(record_files): Use it.
+	* implicit.c (pattern_search): Use uniquize_deps.
+
+	* file.h (file_mtime_1): New macro, like file_mtime, but take second
+	arg, passed to f_mtime.
+	(file_mtime): Implement as file_mtime_1 (file, 1).
+	(file_mtime_no_search): New macro: file_mtime (file, 0).
+	* remake.c (f_mtime): Take new arg SEARCH.  Only do VPATH and `-lNAME'
+	searching if it is nonzero.
+	* main.c (main): Use file_mtime_no_search for makefiles.
+	* remake.c (update_goal_chain): Use file_mtime_no_search if MAKEFILES.
+
+	* main.c (printed_version): New variable, init'd to zero.
+	(print_version): Set it to nonzero before returning.
+	(die): If -v and !printed_version, call print_version before clean up
+	and death.
+
+	* main.c (log_working_directory): Keep track of whether or not the
+	"Entering" message has been printed, and return without printing the
+	"Leaving" message if not.
+
+	* main.c (decode_switches): Don't complain about missing args before
+	checking for a noarg_value elt in the command_switch structure.
+
+Tue Jan  2 15:41:08 1990  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.texinfo (Commands: Recursion: Options/Recursion): Document
+	special case of -j.
+
+	* make.texinfo, main.c, job.c: Changed copyright notices to include
+	1990.
+
+	* make.texinfo (Top): Fixed introductory paragraph, which said that
+	`make' itself (instead of the manual) has various chapters.
+	(Variables: Advanced: Substitution Refs): When pxref'ing about
+	`patsubst', use node `Text Functions', not `Functions'.
+	Add an xref about `patsubst' after description of $(var:a%b=c%d).
+	(Functions: Syntax of Functions): Explain why mixing delimiters in
+	function/var refs is unwise.  Clarify fn arg evaluation order.
+	(Options): Reworded sentence about `-e'.
+	(Implicit: Implicit Variables): Don't say `RM' is unused.
+	Say the dflt values for the flag vars is empty unless otherwise noted,
+	since some have defaults.
+	(Implicit: Pattern Rules: Pattern Examples): Clarified use of $< and $@
+	in first example.
+	(Implicit: Last Resort): Don't say the .DEFAULT example creates files
+	"silently".  It's automatic, but not silent.
+	(Implicit: Search Algorithm): Fixed confusing ungrammatical sentence
+	for item 5.1.
+	(Archives: Archive Update): Added missing `next' pointer.
+	(Archives: Archive Symbols): Note that GNU `ar' deals with this
+	automatically.
+
+	* job.c (search_path): New fn, to search for an executable file in a
+	search path (broken out of exec_command).
+	(exec_command): Take fourth arg, the shell program to use (if
+	necessary).  Use search_path for the program, and the shell program.
+	Pass args "file args ..." to shell program (with no -c), where FILE is
+	the full pathname of the program (script) to be run.
+	(child_execute_job): Pass shell program to exec_command.
+	* main.c (main): Ditto.
+
+	* main.c (main): Don't write a message if exec_command returns, because
+	it will never return.
+
+Fri Dec 22 16:19:58 1989  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)
+
+	* default.c (default_variables: "LINK.cc"): Use $(C++FLAGS) instead of
+	$(CFLAGS).
+
+Wed Dec 20 09:58:48 1989  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)
+
+	* job.c (new_job): If start_job set the child's `command_state' to
+	`cs_finished', call notice_finished_file.
+
+Sun Dec 17 19:45:41 1989  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)
+
+	* Version 3.57.3.
+
+Wed Dec 13 17:57:12 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* rule.c (convert_to_pattern): Accept files with dependencies as
+	suffix rules.
+
+Thu Nov 30 15:47:13 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.57.2.
+
+	* function.c (expand_function: `shell'): Don't clobber BUFFER and then
+	try to free it.
+
+	* remake.c (update_file_1): Took code to force remake of nonexistent
+	deps out of #if 0, and changed the test to nonexistent non-intermediate
+	deps.  In version 4, I think removing this test completely will
+	implement the new feature that if a: b and b: c and c is newer than a,
+	b need not be remade.
+
+Sun Nov 26 16:12:41 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* compatMakefile (load.o, remote.o): Use $*.c instead of explicit file
+	names so that using VPATH works.
+
+Tue Nov 21 14:57:18 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.57.1.
+
+Fri Nov 10 03:28:40 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* remake.c (check_dep): Set *MUST_MAKE_PTR if FILE does not exist after
+	being updated.  (The exact opposite test was here before; why???)
+	(update_file_1): Set a dep's `changed' member after updating it if it
+	is phony and has commands (because they will then always be executed).
+
+Thu Nov  9 13:47:12 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* load.c [UMAX]: #ifdef UMAX_43 include different headers for the
+	`inq_stats' call.
+	* compatMakefile (LOAD_AVG): Document UMAX_43.
+
+	* Version 3.57.0.
+
+	* commands.c (chop_commands): New function to chop commands into lines.
+	* job.c (new_job): Break that code out, and call chop_commands.
+	* remake.c (remake_file): Call chop_commands before looking at
+	FILE->cmds->any_recurse.
+
+	* make.texinfo (Running: Goals): Don't say that the default target
+	won't be taken from an included makefile.
+
+	* remake.c (update_file_1): #if 0 out setting MUST_MAKE if a dep
+	doesn't exist.
+
+Fri Nov  3 15:53:03 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Version 3.57.
+
+	* variable.c (try_variable_definition): Don't calculate useless value.
+
+	* main.c (define_makeflags): Fixed -j propagation.
+
+	* commands.c (execute_file_commands): Removed unused variable.
+
+Sun Oct 29 11:11:15 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (execute_file_commands): If the commands are empty, call
+	notice_finished_file before returning.
+
+Sat Oct 28 23:06:32 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* remake.c (update_file_1): Don't always update a target that has no
+	deps.  Only do this for double-colon targets.
+
+Wed Oct 25 16:36:16 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* main.c (main) [hpux]: hpux == HPUX.
+	* compatMakefile (defines): Document that HPUX should be defined.
+
+Tue Oct 24 19:19:48 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.56.8.
+
+	* job.c (exec_command): Fixed what mode bits are checked.
+
+	* remake.c (update_file_1): "No cmds and no deps actually changed"
+	loses if ! FILE->is_target.
+
+	* make.texinfo (Variables: Setting): Don't say that spaces after a
+	variable definition are ignored (since they aren't).
+
+Mon Oct 23 14:34:23 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.56.7.
+
+	* remake.c (update_file_1): If, after being updated, any dependency
+	does not exist, remake the target.
+
+	* remake.c (update_file_1): Always update if FILE has commands but no
+	deps.
+
+	* commands.c (execute_file_commands): If we return early because there
+	are no commands, set FILE->updated.
+
+Thu Oct 19 18:47:37 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* arscan.c (ar_scan) [M_XENIX]: Don't run atoi or atol on the
+	`struct ar_hdr' members that are int or long int on Xenix.
+
+Sat Oct 14 10:43:03 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* arscan.c (ar_scan): Cosmetic clean ups.
+	(ar_name_equal): New function to compare names, handling truncated
+	member names and special `.o' truncation.
+	(ar_member_pos): Use ar_name_equal.
+	* ar.c (ar_member_date_1): Use ar_name_equal.
+
+	* Version 3.56.6.
+
+	* file.h (struct file): Made `update_status' a `short int', and moved
+	it before `command_state' so the bitfields can be packed better.
+
+	* remake.c (files_remade): Made global.
+	(notice_finished_file): Don't increment files_remade.
+	* job.c (new_job): Do.
+
+	* job.c (start_job): Don't return a value.  Always set
+	CHILD->file->command_state to either cs_running or cs_finished.
+	(new_job, child_handler): Don't expect start_job to return a value.
+	Instead, look at the file's command_state.
+
+	* commands.c (chop_commands): Merged into job.c (new_job).
+	* commands.h: Don't declare chop_commands.
+
+	* job.c (start_job): Made static.
+	(new_job): New function to create a `struct child' and call start_job.
+	(free_child): New function to free a `struct child'.
+	(child_handler, new_job): Call it.
+	* job.h: Don't declare start_job.  Do declare new_job.
+	* commands.c (execute_file_commands): Call new_job.
+
+	* commands.c (execute_file_commands): Don't set FILE->update_status if
+	start_job fails.
+
+	* function.c (expand_function): Don't use `reading_filename' and
+	`reading_lineno_ptr' if they're nil.
+
+Fri Oct 13 18:16:00 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* read.c (find_semicolon): New function to look for an unquoted ; not
+	preceded by an unquoted # in a string.
+	(read_makefile): Call it before expanding the line.  If it finds a ;,
+	cut the line short there before expanding it.  If not, call it again
+	after expanding.
+
+	* commands.c (execute_file_commands): Don't check FILE->command_state.
+	We won't get called unless it's cs_not_started.
+
+	* read.c (read_makefile): Call collapse_line on the variable-expanded
+	rule line after checking for ; and #.
+
+	* job.c (start_job): When there are no more commands, always return 0.
+	* commands.c (execute_file_commands): Don't put the new child in the
+	`children' chain unless FILE->command_state is cs_running.
+
+	* read.c (read_makefile): Rewrote ;-handling to only do it once (why
+	did I do it twice??) and to check for a # before the ;.
+
+	* job.c (start_job): Set CHILD->file->update_status to 0 when we run
+	out of commands.  Set it to 1 before returning failure.
+	(child_handler): Don't set C->file->update_status to 0 when start_job
+	returns success and commands are not running.
+
+	* read.c (read_makefile): If there is a # before the ; for commands,
+	forget the ; and commands.
+
+Thu Oct 12 15:48:16 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* job.c (child_execute_job): Pass -c to the shell.
+
+Wed Oct 11 18:41:10 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.56.5.
+
+	* main.c (define_makeflags): Cleaned up to keep better track of dashes
+	written, etc.
+
+	* function.c (expand_function: `shell'): When converting newlines to
+	spaces in output, search with `index' calls rather than a simple loop.
+
+	* main.c (main): Make sure stdout is line-buffered.
+
+	* main.c (decode_switches): Always check for missing switch arg.
+
+Mon Oct  9 17:17:23 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.56.4.
+
+Sat Oct  7 00:32:25 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (set_file_variables): #ifdef NO_ARCHIVES, still set $@ and
+	$%.
+
+	* commands.c (set_file_variables): Include a trailing slash in the
+	directory variables (@D, etc.).
+
+	* job.c (child_handler): Call notice_finished_file after changing a
+	child's state to `cs_finished'.
+	* remake.c (update_file_1): Don't call notice_finished_file if
+	FILE->command_state == cs_finished.
+
+Wed Oct  4 16:09:33 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.56.3.
+
+Tue Oct  3 21:09:51 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* read.c (read_all_makefiles): When setting elements of MAKEFILES from
+	the contents of read_makefiles, make sure we're using the right
+	element.
+
+	* dir.c, glob.c [USGr3 || DIRENT]: Don't define d_ino as d_fileno.
+
+	* Version 3.56.2.
+
+	* remake.c (update_file_1): Return zero after calling remake_file if
+	FILE->command_state != cs_finished.  Test update_status thoroughly.
+
+	* commands.c (execute_file_commands): Don't call notice_finished_file.
+
+	* remake.c (remake_file): Return immediately after calling
+	execute_file_commands.
+
+Sat Sep 30 14:57:05 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.56.1 (alpha).
+
+	* file.h (struct file): Made `update_status' not be a bitfield, since
+	some broken compilers don't handle it right.
+
+	* function.c (expand_function: `join'): Don't clobber the pointers and
+	then try to free them.
+
+	* job.c (exec_command): Fixed & vs = precedence problem.
+
+Thu Sep 28 17:29:56 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* remake.c (update_file_1): Fixed typo in debugging output.
+
+	* remake.c (library_file_mtime): Search for /usr/local/lib/libLIB.a
+	after /usr/lib/libLIB.a.
+
+Tue Sep 26 16:07:58 1989  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* read.c (conditional_line): For `ifeq (a, b)', swallow space after the
+	comma.
+
+Sun Sep 24 13:25:32 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* function.c (patsubst_function): If BY_WORD and the match is not a
+	full word, update the text pointer correctly.
+
+	* function.c (expand_function: `word'): Don't lose track of the second
+	arg's expansion and free something else instead.
+
+Fri Sep 22 16:15:29 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.56.
+
+Thu Sep 21 14:28:42 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* main.c (main): Make an array of the mtimes of the makefiles before
+	updating them, and compare their file_mtimes against this later.  Don't
+	re-exec if a makefile was successfully updated but didn't change.  If a
+	makefile failed to be remade and no longer exists, die.  If a makefile
+	failed to be remade, but changed anyway, re-exec.  If a makefile failed
+	to be remade, but is unchanged, continue on.
+
+Wed Sep 20 18:02:07 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.55.6.
+
+	* implicit.c (pattern_search): Maintain an array CHECK_LASTSLASH of the
+	CHECK_LASTSLASH flag values used to match each member of TRYRULES.
+	When making FILE->stem, if CHECKED_LASTSLASH[FOUNDRULE], prepend the
+	part of FILENAME before LASTSLASH.
+
+Tue Sep 19 17:44:08 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* dir.c (dir_file_exists_p): Check for FILENAME being nil before
+	checking for it being "".
+
+	* main.c (define_makeflags): Fixed test for whether a flag/flag_off
+	option was non-default.  Also changed to generate a string that Unix
+	Make will grok (except for FP/int values and new flags).
+
+	* job.c (child_execute_job): Don't use the shell's -c option.
+	Also fixed an off-by-one bug in the ARGV -> shell arg list copying.
+
+Mon Sep 18 15:17:31 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.55.5.
+
+	* read.c (parse_file_seq): Check the beginning of the file name for a
+	`./', not the two chars after the end of the name (Q rather than P).
+
+	* job.c (child_execute_job): Include all of ARGV in the arg list for
+	the shell.
+
+	* main.c (define_makeflags): Don't include floating and positive_int
+	options in !PF.
+
+	* job.c (exec_command): Set the effective gid to the real gid before
+	execing.
+
+	* job.c (child_execute_job): Don't clobber the arg list when execing
+	the shell.
+
+Sun Sep 17 15:27:19 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* main.c (define_makeflags): Moved all the checking inside the switch.
+
+	* load.c [LDAV_BASED] (load_average): When we can't get the load
+	average, return zero instead of running off the end.
+
+	* file.c: Include variables.h.
+	* job.c: Declare dup2 and {block,unblock}_remote_children.
+	* file.h: Declare f_mtime.
+	* job.c: Don't declare construct_command_argv, since job.h does.
+	* function.c, main.c, load.c, remake.c: Include job.h.
+	* load.c [LDAV_BASED] (load_average): Declare nlist.
+	* variable.h: Declare print_file_variables.
+	* job.c [!USG]: Don't declare sigsetmask.
+	[!USG]: Declare getdtablesize.
+	Don't declare load_average.  Do declare wait_to_start_job.
+	Declare vfork, gete[gu]id, execve.
+	* commands.c: Declare remote_kill, getpid.
+	* make.h: Declare kill, exit, sigblock, pipe, close, ctime, open,
+	lseek, read.
+	* make.h [not USG]: Declare sigsetmask.
+	* job.h: Declare wait_for_children and {block,unblock}_children.
+
+	* dir.c (dir_file_exists_p): If FILENAME is nil, read in the whole
+	directory.
+	(find_directory): When we want to read in the whole directory, call
+	dir_file_exists_p with nil instead of "".
+
+	* file.h (struct file), job.h (struct child),
+	  variable.h (struct variable): Use bitfields for flags.
+	* make.h (ENUM_BITFIELD): If GCC or #ifdef ENUM_BITFIELDS, define as
+	:BITS, else empty.
+	* compatMakefile (defines): Document ENUM_BITFIELDS.
+
+Sat Sep 16 12:38:58 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.55.4 (alpha).
+
+	* GNUmakefile (dist): Depend on default and doc.
+
+	* load.c [LDAV_BASED]: Include <nlist.h> rather than <a.out.h>; #ifdef
+	NLIST_NAME_UNION, use n_un.n_name instead of n_name.
+	* compatMakefile (LOAD_AVG): Document NLIST_NAME_UNION.
+
+	* job.c [USG-ish]: Don't redefine WIF{SIGNALED,EXITED} if they're
+	already defined.
+
+Fri Sep 15 13:59:42 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* glob.c, dir.c [USGr3 or DIRENT]: If neither d_ino, nor d_fileno is
+	defined, define d_ino as d_fileno.
+
+Thu Sep 14 18:29:38 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* job.c: Don't declare exec_command static.
+
+	* make.texinfo (Name Index): Changed title to include directives.
+
+	* Version 3.55.3 (alpha).
+
+	* make.texinfo (Running: Options): Document -e.
+
+	* main.c (main): Always give imported environment variables origin
+	`o_env'.
+	* variable.c (define_variable_in_set): Under -e, if ORIGIN, or an
+	existing variable's origin, is `o_env', make it `o_env_override'.
+
+	* load.c: Use the symbol KERNEL_FILE_NAME instead of KERNEL_FILE.
+	* compatMakefile: Changed the comment for `LOAD_AVG' accordinly.
+
+Thu Sep  7 16:46:26 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.55.2 (alpha).
+
+	* variable.c (print_variable_set), rule.c (print_rule_data_base),
+	file.c (print_file_data_base): If NO_FLOAT is defined, don't use
+	floating-point for printing statistics.
+	* compatMakefile (defines): Document NO_FLOAT.
+
+	* make.h (HASH): New macro to add the hashing value of one char to a
+	variable.c.
+	* file.c (lookup_file, enter_file, rename_file): Use it.
+	* dir.c (find_directory, dir_file_exists_p, file_impossible_p): Ditto.
+	* variable.c (define_variable_in_set, lookup_variable): Same here.
+
+	* variable.c, file.c, dir.c: Don't define *_BUCKETS if they are already
+	defined.
+
+	* compatMakefile (defines): Added comment about defining NO_ARCHIVES.
+	(ARCHIVES, ARCHIVES_SRC): New variables for {ar,arscan}.[oc].
+	(objs, srcs): Use $(ARCHIVES) and $(ARCHIVES_SRC).
+	* commands.c (set_file_variables), dir.c (file_exists_p),
+	remake.c (touch_file, name_mtime), implicit.c (try_implicit_rule,
+	pattern_search), make.h: If NO_ARCHIVES is #defined, don't do any
+	archive stuff.
+
+	* commands.c (set_file_variables): Don't kill the last char of
+	directory names in $([@*<%?^]D).
+
+Wed Sep  6 15:23:11 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* default.c (default_terminal_rules {%:: %,v}, {%:: RCS/%,v}): Don't
+	run co if the target exists.
+
+	* glob.c (glob_match): [!xyz], rather than [^xyz], means none of [xyz].
+
+	* glob.c: Misc minor cosmetic changes.
+
+Tue Sep  5 14:49:56 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)
+
+	* load.c [LDAV_BASED] (load_average): Check for == -1, rather than < 0
+	to see if lseek fails.  On some systems, `avenrun' is at an offset >
+	(2**31)-1, and lseek succeeds, returning a negative value.
+
+Mon Sep  4 11:07:58 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)
+
+	* rule.c (new_pattern_rule): Return `int' instead of `void': nonzero if
+	the passed rule was used, zero if not.
+	(install_pattern_rule): Pay attention to the return from
+	new_pattern_rule, and don't set the rule's `terminal' flag or give it
+	commands unless it's used.
+	(create_pattern_rule): Same idea.
+
+	* dir.c (find_directory): Removed unused variable.
+
+	* commands.c (execute_file_commands): Removed unused variable.
+
+	* read.c (record_files): Don't use NAME after freeing it.
+
+Sat Sep  2 00:33:19 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)
+
+	* Version 3.55.1 (alpha).
+
+	* function.c (string_glob): Don't add spaces after file names that
+	aren't added.  (Also means don't add spaces without checking the size
+	of the buffer.)
+
+	* remake.c (update_goal_chain): Don't remove makefiles with cmds and no
+	deps from the chain.
+	* main.c (main): Do it here, before calling update_goal_chain.
+
+	* remake.c (update_goal_chain): When updating fails, change STATUS even
+	if MAKEFILES is set.  Also stop remaking when updating fails if not
+	under -k and MAKEFILES is not set.
+
+	* remake.c (remake_file, update_file_1, notice_finished_file),
+	commands.c (execute_file_commands), make.h, commands.h: The functions
+	remake_file, notice_finished_file, and execute_file_commands no longer
+	return values, and their callers no longer expect values returned.
+
+	* remake.c (notice_finished_file): Don't set FILE's modtime to now if
+	it is a non-target with no commands.
+
+Fri Sep  1 00:04:39 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)
+
+	* read.c (read_all_makefiles): After freeing each element on MAKEFILES,
+	replace it with the name stored in read_makefiles by read_makefile.
+
+	* remake.c (update_file_1): Don't decide not to remake if FILE has no
+	cmds and no deps actually changed if FILE doesn't have any deps.
+
+	* file.c (remove_intermediate): Remove precious files that also have
+	the `dontcare' flag set.
+
+	* remake.c (update_file_1): Don't always remake if FILE has cmds but no
+	deps; only if FILE is double-colon.  (I don't know why this should be
+	done for double-colon targets, but that's what Unix make does.)
+
+	* load.c [LDAV_BASED] (load_average): Write error messages if the
+	various system calls fail.  Keep track of if we've failed before.
+	The first time we fail, write a message saying -l won't be enforced.
+	The first time we succeed after having failed, write a message saying
+	-l will be enforced again.
+
+	* remake.c [USG]: Don't #include <sys/file.h>
+
+	* load.c [generic Unix LDAV_BASED]: #include <fcntl.h> #ifdef USG,
+	else <sys/file.h> instead.
+
+	* job.c [USG && !USGr3 && !HAVE_DUP2]: Remove redundant
+	#include <errno.h> and declaration of `errno'.
+	[...] (dup2): Fixed so it won't always lose.
+
+	* default.c (default_suffix_rules: .texinfo.dvi): Copy, rather than
+	move, the aux and index files, so the TeX run can use them.
+
+	* compatMakefile: Remove redundant comment.
+
+	* load.c [generic Unix LDAV_BASED]: Include <a.out.h> instead of
+	<nlist.h>, since the `struct nlist' declaration in <nlist.h> varies
+	more than the one in <a.out.h>.
+	(load_average): Use the `n_un.n_name' field of the `struct nlist',
+	since the <a.out.h> declaration uses the union.
+
+	* main.c (main): For the temporary files made for stdin makefiles, set
+	the `intermediate' and `dontcare' flags.
+	* file.c (remove_intermediates): Don't print any messages for files
+	whose `dontcare' flag is set.  (The only files that will be
+	intermediate and `dontcare' will be the temporary files made for stdin
+	makefiles.)
+
+	* job.c (exec_command): Made global.
+	* job.h: Declare it.
+	* main.c (main): Use exec_command when re-execing.
+
+	* make.h: Declare environ.
+	* make.c: Don't.
+
+	* job.c (child_execute_job): New function to perform everything done in
+	the child side of a fork (for a job or `shell' function).
+	(start_job): Call it.
+	* job.h: Declare construct_command_argv and child_execute_job.
+	* function.c (expand_function: `shell'): Use child_execute_job.
+
+Thu Aug 31 18:42:51 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)
+
+	* function.c (expand_function: `shell'): Remove a trailing newline
+	instead of turning it into a space.
+
+	* main.c (main): Do init_siglist #ifdef HAVE_SIGLIST.
+
+	* job.c [WTERMSIG || (USG && !HAVE_SYS_WAIT)]: Test each W* macro
+	separately and define all those that aren't defined.
+
+Sat Aug 26 15:13:21 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* ar.c (ar_name): Return zero for `(foo)'.
+
+	* Version 3.55.
+
+	* make.texinfo (Rules: Multiple Targets): Make this node's `next'
+	pointer point to `Static Pattern'.
+	* make.texinfo (Makefiles: MAKEFILES Variable): Make this node's `prev'
+	pointer point to `Makefile Names'.
+
+	* make.1: Renamed to make.man.
+	* compatMakefile: Define `mandir' and `manext'.
+	(install): Depend on $(mandir)/make.$(manext).
+	($(mandir)/make.$(manext)): Depend on make.man and copy it to $@.
+	($(bindir)/make): Use `make' rather than $<; so Unix make can grok it.
+
+Thu Aug 24 03:35:48 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* variable.c (target_environment): Allow variables that start with
+	underscores.
+
+Wed Aug 23 22:50:32 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* variable.c (target_environment): Reject variables that don't start
+	with letters.
+
+Tue Aug 22 04:14:29 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* GNUmakefile (make-$(version).tar.Z): Put make.1 (the Unix manual
+	page) in the tar file.
+
+	* variable.c (target_environment): Don't write variables with origin
+	o_default (i.e., ones from default.c).
+	* make.texinfo (Commands: Recursion: Variables/Recursion): Document
+	that default variables are not put in the environment.
+
+	* remake.c (update_file_1): Remake all targets with commands but no
+	deps.
+
+Sat Aug 19 06:03:16 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* remake.c (update_file_1): In the final loop, set the deps'
+	`changed' members if they are newer than FILE.
+
+	* remake.c (update_goal_chain): Under -d, print a message if we decide
+	not to remake a makefile so as to avoid a possible infinite loop.
+
+Fri Aug 18 20:30:14 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* remake.c (remake_file): Cleaned up.
+
+	* commands.c (execute_file_commands): If the commands are empty, set
+	FILE->update_status to zero before returning.
+
+	* remake.c (notice_finished_file): Set `last_mtime' fields to zero
+	instead of calling name_mtime; file_mtime will do that later if anybody
+	cares.
+
+Thu Aug 17 10:01:11 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* make.texinfo (Rules: Wildcards: Wildcard Examples): Give this node a
+	`prev' pointer.
+
+	* Version 3.54.9 (alpha).
+
+	* make.texinfo: Fixed some @nodes.
+
+	* remake.c (check_dep): Don't set *MUST_MAKE_PTR if FILE doesn't exist
+	after running update_file.
+
+	* remake.c (notice_finished_file): If FILE has no commands, pretend its
+	modtime is now.
+
+	* remake.c (update_file_1): In the loops that call update_file on the
+	deps, compare modtimes before and after (unless deps are still being
+	made) and set the deps' `changed' members.  Do not set the `changed'
+	members in the loop that prints the newer/older debugging messages.
+	* remake.c (update_file_1): If no deps changed and FILE has no
+	commands, decide it doesn't need remaking.
+
+	* remake.c (update_file_1): Print a debugging message if we take
+	commands from default_file.
+
+	* make.texinfo (Rules: Directory Search: Selective Search): Removed
+	note about warning for `vpath' with a constant pathname, since it isn't
+	warned about anymore.
+
+	* remake.c (update_goal_chain): If MAKEFILES, remove makefiles which
+	are targets and have no deps.
+	* make.texinfo (Makefiles: Remaking Makefiles): Document that makefiles
+	will not be remade if they are targets but have no dependencies.
+
+Tue Aug 15 00:00:08 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+
+	* remake.c (notice_finished_file): Increment files_remade for non-phony
+	files if they didn't exist before (even if they still don't).
+
+	* job.c: Include <errno.h> and declare errno.
+
+	* job.c (exec_command): If the execve fails with ENOEXEC (Exec format
+	error), return instead of exiting the child process.
+
+	* job.c (start_job): In the child side, if exec_command fails, try
+	using the shell.
+
+	* job.c (start_job): In the child side, call unblock_children instead
+	of sigsetmask.
+
+	* remake.c (notice_finished_file): Under -n or -q, always increment
+	files_remade for non-phony files.
+
+	* rule.c (intall_pattern_rule): Use find_percent.
+
+	* vpath.c (vpath_search): Pass the `percent' members to
+	pattern_matches.
+
+Mon Aug 14 23:30:24 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+
+	* vpath.c (struct vpath): New member `percent', to hold a pointer into
+	the pattern where the % is.
+	(construct_vpath_list): Call find_percent on the pattern and set the
+	new `percent' member.
+	* read.c (read_makefile): Don't run find_percent on `vpath' directive
+	patterns.
+
+	* function.c (pattern_matches): Take new arg PERCENT, a pointer into
+	PATTERN where the % is.  If PERCENT is nil, copy PATTERN into local
+	space and run find_percent on it.
+	(expand_function: `filter', `filter-out'): Pass new arg to
+	pattern_matches.
+	* read.c (record_files): Pass PATTERN_PERCENT to pattern_matches for
+	static pattern rules.  Save the percent pointer into implicit rule
+	targets, and pass them to create_pattern_rule.
+	* rule.c (convert_to_pattern): Pass new arg to create_pattern_rule.
+	(create_pattern_rule): Take new arg TARGET_PERCENTS, nil or an array of
+	pointers into the corresponding elements of TARGETS, where the %s are.
+
+Sun Aug 13 00:29:19 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* Version 3.54.8.
+
+	* README.templatate, README-doc.template: New files, turned into README
+	and README-doc to go into the two distribution tar files.
+	* GNUmakefile: Added a rule to edit the version number in
+	README.template and README-doc.template, producing README and
+	README-doc.
+
+	* remake.c (update_goal_chain): If -n or -q is in effect for a
+	makefile, and it got updated, don't change STATUS, so we can still
+	return -1 (meaning nothing was done).  This avoids an infinite loop on
+	"make -n Makefile".
+
+Sat Aug 12 23:14:24 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* remake.c (notice_finished_file): Treat -q the same as -n.
+
+	* remake.c (update_goal_chain): Fixed handling of return from
+	update_file.  If -n or -q is in effect, ignore it.
+
+	* job.c (start_job): Don't test for -t.  We should never get called in
+	that case.
+
+Fri Aug 11 04:09:14 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* function.c (expand_function): Removed unused variables.
+	(handle_function): Removed unused variable.
+
+	* main.c (main): Removed unused variable.
+
+Wed Aug  9 09:37:10 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* Version 3.54.7.
+
+	* remake.c (notice_finished_file): If FILE's modtime actually changed,
+	increment files_remade.
+	(remake_file): Don't increment files_remade.
+
+	* remake.c (update_file): Don't print "up to date" messages for
+	phony files.
+
+	* job.c (child_handler): Don't set C->file->update_status to 1 if
+	start_job returns nonzero under -n or -t.
+
+	* expand.c (variable_expand): Count parens in $(foo:a=b) refs.
+
+	* main.c: Removed old declaration of `glob_tilde' (which hasn't existed
+	for a few months).
+
+Tue Aug  8 23:53:43 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* job.c (exec_command): Fixed to not ignore the last path component and
+	to do the right thing with an empty path.
+
+Fri Aug  4 15:58:19 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* remake.c (library_file_mtime): Look for libLIB.a, not /libLIB.a.
+	Do VPATH search on libLIB.a, not /usr/lib/libLIB.a
+
+Thu Aug  3 20:42:00 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* job.c [HAVE_SYS_WAIT or not USG]: If WIFSIGNALED is not defined by
+	<sys/wait.h>, define it as (WTERMSIG != 0).
+
+Tue Aug  1 19:25:34 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* remake.c (remake_file): If FILE has no commands and is a target,
+	don't set its time to now.  The time gets reset by notice_finished_file
+	anyway, and it isn't needed since check_dep checks for nonexistence.
+
+	* Version 3.54.6.
+
+	* read.c (read_makefile): Don't read off the end of the string after an
+	`include'.
+
+	* job.c (exec_command): New function to search the path for a file and
+	execute it.
+	(start_job): Use exec_command rather than execvp.
+
+	* read.c (read_makefile): Expand `include' directive args before
+	parsing them.  Allow trailing whitespace after filename.
+
+	* variable.c (target_environment): Put makelevel + 1, rather than
+	makelevel, in the `MAKELEVEL' envariable.
+
+Sat Jul 29 10:27:04 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* remake.c (notice_finished_file): Don't get the new modtime of phony
+	files.
+
+	* remake.c (remake_file): Run commands instead of touching under -t if
+	FILE->cmds->any_recurse is set.
+
+	* commands.h (struct commands): Add new member `any_recurse', to be set
+	nonzero if any `lines_recurse' element is nonzero.
+	* commands.c (chop_commands): Set the `any_recurse' member.
+
+	* commands.c (execute_file_commands): Split chopping of commands into
+	lines into new function chop_commands.
+	* commands.h: Declare chop_commands.
+
+	* read.c (read_makefile): Test for a line beginning with a tab after
+	checking for conditional lines, but before all other checks.
+
+Fri Jul 28 18:10:29 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* read.c (read_makefile): Match directives against collapsed line
+	and use that for their args.
+
+	* read.c (read_makefile): Warn about extra text after `include'.
+
+Tue Jul 25 14:34:25 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* make.texinfo (Rules: Directory Search: Selective Search): Fixed
+	example to use correct `vpath' syntax.
+
+Mon Jul 24 12:10:58 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* Version 3.54.5.
+
+	* job.c (start_job): In the child side, unblock SIGCHLD.
+
+Fri Jul 21 18:25:59 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* make.h: Don't include <sys/types.h> #ifdef sun.
+
+Mon Jul 17 14:29:10 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* implicit.c (pattern_search): If ar_name (FILENAME), don't check for
+	directory names.
+
+	* job.c (wait_for_children): Changed "waiting for children" message to
+	"waiting for unfinished jobs".
+
+Fri Jul 14 13:17:13 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* load.c (load_average): Use an unsigned offset into kmem.
+
+Thu Jul 13 18:44:49 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* variable.c (pop_variable_scope): Don't free the head of the chain of
+	variables in each bucket twice.
+
+Tue Jul 11 06:45:24 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* GNUmakefile: Include COPYING in the doc tar file.
+
+	* variable.c, read.c, misc.c, job.c, function.c: Replace some identical
+	"for" loops with next_token or end_of_token calls.
+
+Mon Jul 10 16:55:08 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* Version 3.54.4.
+
+	* compatMakefile: Documented new conditionals.
+
+	* job.c: Don't define sys_siglist if HAVE_SIGLIST is defined.
+	Don't define dup2 if HAVE_DUP2 is defined.
+
+	* job.c (child_handler): Interpret the return from start_job correctly.
+
+	* remake.c (update_file_1): Don't write "target not remade because of
+	errors" message under -n or -q.
+
+	* read.c: Declare getpwnam.
+
+	* glob.c: Use <dirent.h> if DIRENT is defined.
+	[USG]: Don't declare memcpy, since <memory.h> does.
+
+Fri Jul  7 20:53:13 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* misc.c (collapse_line): Copy the line over in the right place.
+
+Fri Jul  7 18:33:24 1989  Roland McGrath    (fsf at void.ai.mit.edu)
+
+	* remake.c: Conditionalize inclusion of <sys/file.h> on not
+	USG, since HP-UX defines a `struct file' there.
+
+Fri Jul  7 12:11:30 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* job.c: If WTERMSIG is defined by <sys/wait.h>, define WAIT_T as int,
+	and don't define other macros; this covers HP-UX.
+	If WTERMSIG is not defined, use int or union wait based on USG and
+	HAVE_SYS_WAIT; this covers BSD and SysV.
+
+	* Version 3.54.3 (alpha).
+
+	* job.c [USG and not USGr3]: Include <errno.h> and declare errno.
+
+	* job.c (unblock_children [USG]): Declare child_handler.
+
+	* job.c: Renamed WRETCODE to WEXITSTATUS.
+	[HAVE_SYS_WAIT or not USG]: Undefine WTERMSIG, WCOREDUMP, and
+	WEXITSTATUS before defining them.  The HP-UX <sys/wait.h> defines them.
+
+	* main.c (main): If there are no goals, fatal AFTER printing the data
+	base under -p.
+
+Thu Jul  6 22:43:33 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+
+	* glob.c [USG]: #define rindex as strrchr.
+
+	* job.c [USG]: Include <sys/param.h> and #define getdtablesize() as
+	NOFILE.
+
+Wed Jul  5 09:36:00 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* Version 3.54.2 (alpha).
+
+	* expand.c (variable_expand): When expanding recursive variable
+	references (${${a}}), use the correct delimiters in the constructed
+	variable reference.
+
+Mon Jul  3 18:29:26 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+
+	* compatMakefile: Clear out and redefine the .SUFFIXES list because
+	silly Sun 4 make defines .cps.h.
+
+	* compatMakefile: Fix comment about -DNO_MINUS_C_MINUS_O.
+
+	* remake.c: Include <sys/file.h> for O_* on 4.2.
+
+	* commands.c: Define sigmask if it's not defined.
+
+Fri Jun 30 07:33:08 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)
+
+	* remake.c (remake_file): Don't always increment files_remade.
+
+	* variable.c (push_new_variable_scope): Zero the new variable hash
+	table.
+
+Thu Jun 29 17:14:32 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* expand.c (variable_expand): When terminating the variable expansion
+	buffer, use variable_buffer_output instead of a simply zero store,
+	because the buffer may need to be enlarged.
+
+Wed Jun 28 16:53:47 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* Version 3.54.
+
+	* default.c (default_suffixes): Added `.ln'.
+	(default_suffix_rules): Changed lint rules to use -C.
+
+Thu Jun 22 20:49:35 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* job.c (start_job): Set `environ' to CHILD->environment before execing
+	in the child process!
+
+Tue Jun 20 17:23:13 1989  Roland McGrath  (roland at spiff.ai.mit.edu)
+
+	* compatMakefile: Put job.h and rule.h in `srcs'.
+
+	* Version 3.53.
+
+Mon Jun 19 16:25:18 1989  Roland McGrath  (roland at spiff.ai.mit.edu)
+
+	* job.c (start_job): If there are no more commands, return nonzero
+	under -n or -t.
+
+	* compatMakefile (make): Pass `-f' to mv.
+
+	* GNUmakefile: If `ARCH' or `machine' is defined, make $(ARCH)/*.o and
+	$(ARCH)/make instead of *.o and make.
+
+	* function.c (string_glob): Don't try to use freed storage!
+
+	* read.c (readline): If there is only one byte of space in the buffer,
+	enlarge the buffer before reading more.
+
+	* arscan.c [M_XENIX]: Miscellaneous minor changes for Xenix.
+
+Sun Jun 18 13:07:45 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* GNUmakefile (depend): Split commands into two lines so they won't be
+	so long when variable-expanded.
+
+	* compatMakefile: Documented MINUS_C_MINUS_O meaning.  The line
+	describing it got removed when the USG/wait stuff was documented.
+
+Sat Jun 17 22:56:54 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
+
+	* Version 3.52.
+
+Mon Jun 12 17:45:11 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* remake.c (check_dep): Drop circular dependencies instead of fataling.
+	(update_file_1 already does this.)
+
+	* default.c (default_suffix_rules): For .s -> .o, put the -o flag to
+	the assembler before the source file name.
+
+Sun Jun 11 12:00:52 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.51.
+
+	* make.texinfo (Features): Noted 1003.2 requirement of `+' meaning.
+
+	* file.c (remove_intermediates): If !SIG, write a single "rm" command
+	line, listing all files.
+
+	* read.c (read_makefile): Don't free the storage for the passed
+	filename, since it might not be malloc'd.  When doing an included
+	makefile, free the name's storage.
+	(read_all_makefiles): Use variable_expand to find the value of
+	`MAKEFILES'.  Free the storage for the names of -f makefiles.
+	(read_makefile): Allocate storage for the makefile name in the
+	`struct file' in read_makefiles.
+
+	* make.texinfo (Running: Instead of Execution): Document the effect of
+	+ and $(MAKE)/${MAKE}.
+
+	* make.texinfo (Functions: Foreach Function): Document that if the
+	iteration variable was undefined before the `foreach' call, it will be
+	undefined after the call.
+
+	* commands.c: Split into commands.c, job.h, and job.c.
+
+	* rule.c (try_implicit_rule, pattern_search): Moved to new file
+	implicit.c.
+
+	* rule.c: Split into rule.h, rule.c, and default.c.
+	* default.c (install_default_pattern_rules): Renamed to
+	install_default_implicit_rules.
+	* make.h, main.c (main): Renamed uses.
+
+	* make.c: Renamed to misc.c.
+
+	* make.c (main, log_working_directory, decode_switches,
+	decode_env_switches, define_makeflags, die, print_version,
+	print_data_base): Moved to new file main.c.
+
+	* commands.c (execute_file_commands): Don't collapse backslash-newlines
+	here.  When chopping the commands up into lines, don't chop at
+	backslash-newlines.
+	(start_job): Collapse backslash-newlines after printing the line.
+
+	* commands.c (start_job): Don't collapse backslash-newlines here.
+	(execute_file_commands): Collapse backslash-newlines before chopping
+	the commands up into lines.
+
+	* commands.c (set_file_variables): Initialize the length counters for
+	$^ and $? to zero!
+
+	* commands.c (start_job): Use vfork instead of fork.  Someone else says
+	the child and parent DO have separate file descriptors.
+
+	* variable.c: Split internals into variable.c, function expansion into
+	function.c, and variable expansion into expand.c.
+	* function.c (handle_function): New function to check for a function
+	invocation and expand it.
+	* expand.c (variable_expand): Use handle_function.
+	* variable.c (push_new_variable_scope): New function to push a new
+	empty variable set onto the current setlist.
+	(pop_variable_scope): New function to pop the topmost set from the
+	current setlist and free its storage.
+	* function.c (expand_function: `foreach'): Push a new variable scope
+	for the iteration variable and pop the scope when finished.
+	* variable.h: Declare new functions.
+	* variable.c (initialize_variable_output): New function to return a
+	pointer to the beginning of the output buffer.
+	(save_variable_output): New function to save the variable output state.
+	(restore_variable_output): New function to restore it.
+	* expand.c (variable_expand): Use initialize_variable_output.
+	(allocated_variable_expand): Use {save,restore}_variable_output.
+	* variable.c (current_setlist): Renamed to current_variable_set_list
+	and made global.
+
+Sat Jun 10 00:11:25 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* remake.c (library_file_mtime): Check for libNAME.a in the current
+	directory before doing VPATH search.
+
+	* variable.c (print_variable_set): Don't write "# Variables", and write
+	fewer blank lines.
+	(print_variable_data_base): Precede the variables with "# Variables".
+
+	* make.c (main): Print the data base under -p after doing everything
+	else, just before exitting.  This way it gets info determined in
+	updating the goal targets.
+
+	* variable.c (print_variable_data_base): Split into print_variable,
+	which prints one variable, and print_variable_set, which prints a set.
+	Replaced with a call to print_variable_set for the global set.
+	(print_file_variables): New function to print a given file's local
+	variables.
+
+	* file.c (print_file_data_base): Call print_file_variables to print
+	each file's local variables.
+
+	* commands.c (set_file_variables): Actually define the values for
+	the $^ and $? variables!!!
+
+	* make.texinfo (Implicit: Pattern Rules: Automatic): Document new D and
+	F versions of $^ and $?.
+
+	* commands.c (start_job): In the child fork, use getdtablesize and a
+	loop to close all file descriptors other than 0, 1, and 2.  We need to
+	do this since not only the bad stdin pipe, but also some directories,
+	may be open.
+
+	* commands.c (start_job): Use fork instead of vfork, because a vfork
+	parent and child share file descriptors, and our child needs to diddle
+	with stdin.
+
+	* variable.c (initialize_file_variables): When created a new variable
+	set, zero out the hash table.
+
+	* variable.c (target_environment): Don't use variables whose names are
+	not made up of alphanumerics and underscores.
+
+	* remake.c (update_file_1): Set the `parent' member of each dependency
+	to FILE before updating it.
+
+	* file.h (struct file): Add `parent' member.
+
+	* variable.c (initialize_file_variables): Don't take second arg PARENT.
+	Use FILE->parent instead.  If FILE->parent->variables is nil, recurse
+	to initialize it.
+
+	* variable.h: Declare {allocated_}variable_expand_for_file.
+
+	* variable.c (allocated_variable_expand): Now
+	allocated_variable_expand_for_file, calling variable_expand_for_file,
+	and taking second arg FILE.
+	(allocated_variable_expand): New function, a wrapper around
+	allocated_variable_expand_for_file, passing a nil second arg.
+
+Fri Jun  9 12:11:45 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (start_job): On the child side of the fork, always close
+	the bad stdin file descriptor.
+
+	* commands.c (struct child): New member `environment', to hold the
+	environment for the child.
+	(execute_file_commands): Set the new childs `environment' member to nil
+	before calling start_job.
+	(start_job): Set up CHILD->environment before running the commands if
+	it is nil.
+
+	* make.c (main): Don't call new_environ.  `shell' functions will now be
+	run with the environment make was called with.
+
+	* commands.c (child_handler): Don't check C->command_ptr before calling
+	start_job since we now have to check C->file->cmds->command_lines and
+	it's easier to let start_job handle all that.
+
+	* commands.c (struct child): New member `command_line', to hold an
+	index into file->cmds->command_lines.
+	(execute_file_commands): Set the new child's `command_line' to 0 and
+	its `commands' and `commands_ptr' to nil.
+	(start_job): When CHILD->command_ptr runs out, increment
+	CHILD->command_line and run the corresponding line from
+	CHILD->file->cmds->command_lines.  Run it even under -t, -q, or -n if
+	the CHILD->file->cmds->lines_recurse element for that line is set.
+
+	* commands.c (execute_file_commands): Chop CMDS up into lines, setting
+	its `command_lines' and `lines_recurse' members, if it wasn't already
+	chopped.
+
+	* commands.h (struct commands): New members `command_lines' and
+	`lines_recurse'.  The first is an array of chopped-up lines; the second
+	is an array of flags, each nonzero if the corresponding line is
+	recursive.
+
+	* variable.c (variable_expand_for_file): If FILE is nil, just do a
+	vanilla variable_expand.
+	(expand_function: `shell'): Pass second arg (as nil) to
+	construct_command_argv.
+
+	* commands.c (construct_command_argv): Use variable_expand_for_file on
+	`$(SHELL)' and `$(IFS)' instead of lookup_variable to check those
+	variables.  This handles file-local and recursive values correctly.
+	To support this, take an additional argument FILE.
+
+	* variable.c (initialize_file_variables): New function to initialize
+	FILE's variable set list from PARENT's setlist.  PARENT is the
+	immediate dependent that caused FILE to be remade, or nil if FILE is a
+	goal.  (When user-level per-file variables are implemented, PARENT
+	should be passed as nil when defining per-file variables.)
+
+	* variable.c (variable_expand_for_file): New function to expand a line
+	using the variable set of a given file, and reporting error messages
+	for the file and line number of that file's commands.
+
+	* variable.h: Don't declare lookup_variable_for_file.
+
+	* variable.c (lookup_variable_*): Turned back into lookup_variable.  It
+	now uses current_setlist.
+	(global_setlist): New static `struct variable_set_list', a setlist
+	containing global_variable_set.
+	(current_setlist): New static `struct variable_set_list *', a pointer
+	to the current variable set list.
+	(define_variable): Define in the current top-level set, not the global
+	set.
+
+	* commands.c (set_file_variables): New function to set up the automatic
+	variables for a file in its own variable set.
+	(execute_file_commands): Use set_file_variables.
+
+	* variable.c (new_environ): Replaced with target_environment, taking an
+	argument FILE, and returning an environment for FILE's commands.
+
+	* variable.c, variable.h: Remove all global special variable pointers.
+
+	* variable.c (define_variable_for_file): New function like
+	define_variable, but takes additional arg FILE, and defines the
+	variable in the variable set at the top of FILE's chain.
+	(lookup_variable_for_file): New function like lookup_variable, but
+	takes additional arg FILE, and looks the variable up in all of FILE's
+	variable sets.
+
+	* file.h (struct file): New member `variables', a `struct
+	variable_set_list' containing the list of variable sets used in the
+	expansion of the file's commands.
+
+	* variable.c (variables): Replaced with static `struct variable_set'
+	global_variable_set.
+	(define_variable): Now define_variable_in_set, taking additional
+	argument SET, the `struct variable_set' to define it in.
+	(define_variable): Use define_variable_in_set with global_variable_set.
+	(lookup_variable): Now lookup_variable_in_set, taking additional
+	argument SET, the `struct variable_set' to look it up in.
+	(lookup_variable): Use lookup_variable_in_set with global_variable_set.
+	(lookup_variable_in_setlist): New function to look up a variable in a
+	`struct variable_set_list' using lookup_variable_in_set.
+
+	* variable.h (struct variable_set): New structure, containing a hash
+	table and the number of hash buckets.
+	(struct variable_set_list): New structure, containing a link for a
+	linked-list, and a `struct variable_set'.
+
+	* commands.c (start_job): Under -n, return what the recursive start_job
+	call returns, since it might actually start a child.
+
+	* make.texinfo (Rules: Wildcards): Document ~ and ~USER expansion.
+
+	* commands.c (execute_file_commands): If start_job returns
+	failure, but -t is set, set FILE->update_status to success.
+	(start_job): If -t is set, and the commands are not recursive, return
+	failure (is is done for -q).
+
+	* remake.c (touch_file): New function to touch FILE.
+	(remake_file): Use touch_file.  When touching a file, still do
+	execute_file_commands.
+
+	* remake.c (remake_file): Don't check question_flag (-q), since we
+	can't know here if the commands are recursive.
+
+	* commands.c (start_job): Don't use the `recursive' member of
+	CHILD->file->cmds.  Instead, check for leading +s and $(MAKE) or
+	${MAKE} in the command line here.
+
+	* commands.h (struct commands): Remove `recursive' member.
+
+	* rule.c (install_default_pattern_rules): Remove use of `recursive'
+	member.
+
+	* read.c (record_files): Don't check commands from $(MAKE) and set
+	their `recursive' member.
+
+	* commands.c (fatal_error_signal): Treat SIGQUIT like SIGINT, SIGHUP,
+	and SIGTERM, but don't send it to ourselves because it will cause a
+	core dump.
+
+Thu Jun  8 20:30:04 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.50.
+
+	* variable.c (variable_expand): Use allocated_variable_expand instead
+	of expand_argument in a few places.
+
+	* variable.c (allocated_variable_expand): Do static variable shuffling
+	here instead of using expand_argument.
+	(expand_argument): Use allocated_variable_expand.
+
+	* variable.c (recursively_expand): New function to recursively expand
+	its argument (a `struct variable'), returning the malloc'd value.
+	(variable_expand): Use recursively_expand.
+
+Sun May 28 12:49:27 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.c (main): Fixed buggy fix in deciding to increase space for
+	command-line variable definitions.  (First it never did it, then it
+	always did it; now it does it when necessary.)
+
+Sat May 27 14:01:54 1989  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)
+
+	* make.c (main): Fixed bug in deciding to increase space for
+	command-line variable definitions.
+
+Fri May 26 15:48:01 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* read.c (multi_glob): Use allocated_expand_variable for checking
+	`HOME' variable for ~ expansion, since this may be called from inside a
+	`wildcard' function expansion.
+
+	* variable.h: Declare allocated_expand_variable.
+
+	* variable.c (allocated_expand_variable): New function to do variable
+	expansion in an allocated buffer, rather than the static one.
+
+	* make.c (main): Don't set glob_tilde (it no longer exists).
+
+	* variable.c (string_glob): Use multi_glob and parse_file_seq.
+
+	* read.c (multi_glob): Do ~ expansion here.
+
+	* glob.c (glob_tilde, glob_filename): Removed ~ expansion.
+
+	* variable.c (define_variable, lookup_variable): Use a smarter hashing
+	algorithm (the same one used for files and directories).
+	(VARIABLE_BUCKETS): Increased to 523.
+
+	* file.c (enter_file, lookup_file, rename_file): Use a smarter hashing
+	algorithm, spreading the bits about somewhat.
+
+	* make.c (log_working_directory): Under `-p', precede the directory
+	message with a `#'.
+
+	* make.c (print_version): Under `-p', precede each line with a `#'.
+	(print_data_base): Precede the header line with a `#' and include the
+	date and time on it.
+
+	* vpath.c (print_vpath_data_base): Precede non-directive
+	lines with `#'s.
+
+	* commands.c (print_commands): Precede the non-command line with a `#'.
+
+	* rule.c (print_rule_data_base), file.c (print_file_data_base): Precede
+	non-rule lines with `#'s.
+
+	* dir.c (print_dir_data_base): Precede all lines with `#'s.
+
+	* variable.c (print_variable_data_base): Changed format so that it can
+	be makefile input.  Lines that are not variable definitions are
+	preceded with `#'.  Nonrecursive variable definitions are made with all
+	dollar signs doubled to reproduce the initial value.  Recursive
+	variable definitions containing newlines are done with `define'
+	directives.  Nonrecursive variable definitions containing newlines, and
+	variable names containing :, =, or newlines, will come out garbled.
+
+Wed May 24 00:20:04 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.49.
+
+Tue May 23 19:18:00 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* variable.c (expand_function: `filter'/`filter-out'): Use
+	find_percent instead of pattern_p.
+
+	* variable.c (expand_function: `patsubst'): Pass new args (both nil)
+	to patsubst_expand.
+	(variable_expand): For $(var:pat%=rep%) references, pass new args to
+	patsubst_expand so as to avoid find_percent and thus disallow
+	quoting the %s.
+
+	* read.c (record_files): Pass new args to patsubst_expand.
+
+	* variable.c (patsubst_expand): Take two new args: PATTERN_PERCENT
+	and REPLACE_PERCENT.  Each of these, if non-nil, means that PATTERN
+	(or REPLACE) has already been run through find_percent, and
+	PATTERN_PERCENT (or REPLACE_PERCENT) is the result.
+
+	* make.h: Declare find_percent instead of pattern_p.
+
+	* read.c (pattern_p): Changed to find_percent, returning a pointer
+	to the %, or nil if there is none.
+	(record_files): Take another arg, PATTERN_PERCENT, a pointer to the
+	% in PATTERN.
+	(read_makefile): Pass PATTERN_PERCENT to record_files.
+
+	* make.texinfo (Rules: Static Pattern: Static Usage,
+	Rules: Directory Search: Selective Search,
+	Functions: Text Functions): Documented that `%' can be quoted.
+
+	* variable.c (expand_function: `filter'/`filter-out'): Use pattern_p
+	to allow quoted %s in patterns.
+
+	* variable.c (patsubst_expand): Use pattern_p on PATTERN and REPLACE
+	to allow quoted %s.  Quoting backslashes are removed from REPLACE
+	even if PATTERN contains no unquoted %.
+
+	* read.c (pattern_p): Made global.
+	* make.h: Declare pattern_p.
+
+	* read.c (pattern_p): New function to search for an unquoted % in a
+	string.  Backslashes quote %s and backslashes.  Quoting backslashes
+	are removed from the string by compacting it into itself.  Returns
+	nonzero if an unquoted % was found, zero if not.
+	(record_files): Use pattern_p to check for implicit rules.
+	(read_makefile): Use pattern_p to check for static pattern rules.
+	Also use it to allow quoted %s in `vpath' patterns; warn about
+	`vpath' patterns with no %s.
+
+Mon May 22 16:31:52 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* glob.c (glob_filename): Replace a `1' with the `l' that should
+	have been there.  This incidentally stops it from dumping core.
+
+	* glob.c (glob_filename): If the path is just a directory, with no
+	file name pattern, return the directory alone.
+
+	* glob.c (glob_tilde): New global variable (int), defaults to zero.
+	(glob_filename): If glob_tilde is nonzero, expand ~ or ~USER.
+
+	* variable.c (string_glob): Keep a static allocated buffer for file
+	names taken from the list, instead of allocating and freeing one
+	every time.
+
+Fri May 19 18:06:26 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* make.c (decode_switches): Get floating numbers from the right string.
+
+Sun May 14 13:48:04 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* commands.c (delete_child_targets): When deleting `also_make'
+	files, include the target's name in the message:
+		make: *** [foo] Deleting file `bar'
+
+Sat May 13 17:34:26 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.c (max_load_average, default_load_average): Default to -1.
+
+	* load.c (wait_to_start_job): Return if max_load_average is < 0.0,
+	not equal.
+
+Fri May 12 16:08:05 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* variable.c (variable_buffer_output): Don't try to do pointer
+	arithmetic between objects not in the same array.
+
+Wed May 10 15:55:29 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* rule.c [M_XENIX] (default_suffix_rules, default_variables): Minor
+	changes to allow for strange compiler syntax.
+
+	* rule.c (default_variables): Don't include "> $@" in
+	$(PREPROCESS.S), since it's already in the .S.s rule.
+
+	* file.c (enter_file): Make a new double-colon file the `prev'
+	member of the bottom `prev' file (the one whose `prev' is nil).
+
+	* read.c (do_define): Append newlines after copying the lines into
+	the value buffer, so we end up with a trailing newline.
+
+	* make.c (print_version): If the global variable
+	`remote_description' is not nil or "", append "-%s" (its value) to
+	the version number.
+	* remote-*.c: Define remote_description appropriately.
+
+Sun May  7 15:15:53 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (error_status): Converted to new function child_error,
+	taking new arguments TARGET_NAME and IGNORED, and writing an error
+	message: "*** [target] Error 1" (or signal #, etc.), appending
+	" (ignored)" if IGNORED is nonzero.
+	(child_handler): Use child_error instead of error_status.
+
+	* compatMakefile (all): Don't depend on `doc'.
+
+	* compatMakefile (clean): Don't remove make-info*.
+	(realclean): New rule, depends on `clean', removes tags, TAGS,
+	and all Info and TeX files.
+
+Thu May  4 17:00:46 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* variable.c (print_variable_data_base), file.c
+	(print_file_data_base), rule.c (print_rule_data_base),
+	Use floating-point for averages and percentages.
+
+	* make.c (print_data_base): Print messages before and after the data
+	base information.
+
+	* commands.c (print_commands): Changed output format to separate
+	lines in commands and prefix them with tabs.
+
+	* dir.c (print_dir_data_base): Changed output format slightly.
+
+	* vpath.c (struct vpath, construct_vpath_list,
+	selective_vpath_search): Remove the `exists' member and its uses.
+
+	* vpath.c (print_vpath_data_base): New function to print all
+	selective and general VPATH search paths (for -p).
+
+	* make.c (print_data_base): Call print_vpath_data_base.
+
+	* file.c (print_file_data_base): Changed format to look more like a
+	makefile rule.  Now reports all information in the `struct file'.
+
+	* rule.c (print_rule_data_base): Changed format of display from:
+	  %: (terminal)
+	   depends on: RCS/%,v
+	to:
+	  %: RCS/%,v
+	    is terminal.
+	    references nonexistent subdirectory.
+	Also include number and percent that refer to nonexistent
+	subdirectories.
+
+Thu Apr 27 15:45:40 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* make.c (main): Figure out the level of recursion before writing
+	the `Entering directory' message.
+	* variable.c (define_automatic_variables): Don't figure out the
+	level of recursion from `MAKELEVEL'.  It's now done in main.
+
+	* Version 3.48.
+
+Wed Apr 26 16:39:17 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (child_handler): Set `update_status' to zero when there
+	are no more commands.
+
+	* make.c (log_working_directory): If MAKELEVEL > 0, indicate the
+	recurson in the message (make[1]: ...).
+
+	* commands.c (child_handler): Change status to `cs_finished' when
+	commands fail.
+
+	* commands.c (start_job): Return 0 (success) if there were no more
+	commands for the child.
+	(child_handler): Change the status to `cs_finished' when start_job
+	fails to start the commands.
+
+	* make.c (main): Don't handle SIGEMT if it's not defined.
+	Do handle SIGDANGER if it is defined.
+
+	* commands.c (child_handler): Reorganized inner loop so that it
+	doesn't try to inspect the child before finding it.
+
+Tue Apr 25 16:28:24 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* make.c (end_of_token): Fixed bug wherein backslashes caused
+	immediate return.
+
+	* Version 3.47.
+
+	* make.texinfo (Implicit: Pattern Rules: Automatic): Document
+	setting of `$*' for explicit rules.  Add note clarifying that
+	automatic variables, though referred to in the documentation as
+	`$<', etc. are no different than `$(<)', etc.
+
+Fri Apr 21 18:00:12 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* file.c (enter_file): Don't strip leading `./'s.
+
+	* read.c (parse_file_seq): Strip leading `./'s.
+
+Thu Apr 13 17:26:41 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* make.texinfo (Commands: Parallel, Running: Options): Document that
+	-l with no argument removes a previous load limit.
+
+	* make.c (struct command_switch): New member `default_value'.
+	(default_job_slots): Default value (of 1) for -j.
+	(default_load_average): Default value (of 0, unlimited) for -l.
+	(command_switches): Use default values for -j and -l.
+	Also, -l without an arg now means no load limit.
+	(define_makeflags): Don't write positive_int or floating options
+	whose values are their defaults.
+
+	* make.c (main): Under -w, write a `Leaving directory' message
+	before re-execing.
+
+Tue Apr 11 16:46:29 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.46.
+
+	* Makefile: Provide an easy place for system-specific definitions
+	(-DUSG, etc.) and extra object files (for whatever).
+
+	* make.texinfo: Miscellaneous fixes from RMS.
+
+Mon Apr 10 19:31:34 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* rule.c (pattern_search): Put rules with `subdir' flags set in
+	TRYRULES, since these might be valid with VPATHs.  In the TRYRULES
+	loop, don't do lookup_file or file_exists_p calls for dependencies
+	of rules with `subdir' flags set, but still do vpath_search calls
+	and intermediate-file searches.
+
+Thu Apr  6 16:33:00 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* make.texinfo (Implicit: Pattern Rules: Automatic): Document the
+	new definition of $* for explicit rules.
+
+	* commands.c (execute_file_commands): If FILE->stem is nil, figure
+	out if FILE->name ends in a suffix in the .SUFFIXES list; if so,
+	store the name sans suffix in FILE->stem (and $*).
+
+Wed Apr  5 15:24:48 1989  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* file.c (remove_intermediates): Don't use `file_exists_p' to check
+	for the existence of intermediate files, because the hashed
+	directories will probably be out of date.
+
+	* commands.c (child_handler): Free the good stdin before running the
+	next command line.
+
+	* commands.c [USG] (init_siglist): Don't case SIGEMT if it's not
+	defined.  Do case SIGDANGER (for IBM RT) if it is defined.
+
+	* commands.c: Changed `SYS_WAIT' to `HAVE_SYS_WAIT'.
+	(child_handler): Use `wait3' if HAVE_SYS_WAIT is #defined.
+
+	* file.c (enter_file): If any `./'s are stripped off, allocate a new
+	copy of the shortened name.
+
+	* rule.c (pattern_search): Allocate the right length strings for
+	`also_make' members.
+
+Sat Apr  1 13:28:38 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.45.
+
+	* GNUmakefile: Make a separate tarfile of the DVI and info files.
+
+	* make.c (define_makeflags): If a switch that takes an argument has
+	its default value, put the switch in MAKEFLAGS with no arguments.
+
+	* make.c (command_switches): Pass `-l' in MAKEFLAGS.
+
+Wed Mar 29 17:50:05 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* GNUmakefile: Don't include the DVI and info files in the dist.
+
+	* commands.c (child_handler): Don't call
+	check_changed_{directories,vpaths}.
+
+	* make.h: Don't declare check_changed_{directories,vpaths}.
+
+	* vpath.c (check_changed_vpaths): Removed this function.
+
+	* dir.c (struct directory): Remove `modtime' member.
+	(find_directory): Don't set `modtime' member.
+	(check_changed_directories): Removed this function.
+
+	* remake.c (update_file_1): Set FILE->command_state to cs_finished
+	if it didn't need to be remade.
+
+	* remake.c (update_file): Only write the "up to date" message if the
+	target went from `not_started' state to `finished' state without
+	incrementing the count of files remade.
+
+	* commands.c [USG] (init_siglist): If both SIGCHLD and SIGCLD are
+	defined, don't put them both in the `switch'.
+
+Tue Mar 28 15:37:02 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* file.c (rename_file): Change FILE's name!!!
+
+	* rule.c (create_pattern_rule): Set the `terminal' member of the new
+	rule after calling new_pattern_rule, which zeros it.
+
+	* rule.c (default_variables): Use $(C++) in $(COMPILE.cc)!
+
+Sun Mar 26 15:52:30 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Makefile: Added a `clean' target.
+
+Fri Mar 24 15:08:46 1989  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* Version 3.44.
+
+	* file.c (rename_file): If a `struct file' for the renamed-to name
+	exists, and it is a target or has deps or commands, barf.
+	If not just remove the old one for put in the new one.
+
+	* remake.c (update_file_1, check_dep): Changed it back so that equal
+	modtimes to NOT make dependencies be considered newer.  RCS checks
+	out files with equal modtimes as the RCS files, so this screws it.
+
+	* make.h, glob.c: If __GNUC__ is defined, use __builtin_alloca.
+
+	* Makefile: Use variables `ALLOCA' and `ALLOCASRC' so systems
+	without a good standard alloca can get it from the Emacs
+	distribution (or somewhere).
+
+	* dir.c: Don't include <sys/stat.h>, since make.h does.
+
+	* make.c: Removed debugging version of getwd.
+
+Thu Mar 23 16:16:27 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.43.
+
+	* remake.c (update_file_1): If a dependency loop is found, don't
+	fatal.  Emit an error message and remove the dependency.
+
+	* remake.c (library_file_mtime): Fixed to use the right names.
+	(update_file_1, check_dep): Consider a dependency "newer" than its
+	dependent if they have the same modification time.
+
+Wed Mar 22 19:31:35 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* file.c (remove_intermediates): Don't try to remove nonexistent files.
+
+Mon Mar 20 10:21:22 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.42.
+
+	* rule.c (default_variables): Set F77 to $(FC) and F77FLAGS to
+	$(FFLAGS) so explicit rules expecting these (which are in System V)
+	will work.  However, there is no way to make setting these affect
+	the implicit rules, unless we trash FC and FFLAGS (which BSD uses).
+	[USG]: Set GET to `get' rather than `/usr/sccs/get'.
+
+Sun Mar 19 20:00:27 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* vpath.c (construct_vpath_list): Don't replace VPATH[ELEM] with
+	dir_name (V), because the latter may get freed.
+
+Sat Mar 18 15:01:39 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.41.
+
+	* make.texinfo: Cleaned-up edition 0.1 Beta from RMS and Bob Chassell.
+
+	* file.c (rename_file): If a file with the new name already existed,
+	use the same storage space, after freeing the old file's name, deps,
+	and `also_make' member, preserving the link in the chain.
+	Also write an error message telling the user to report the incident;
+	I don't think this should be able to happen, but I'm not sure.
+
+	* file.c (rename_file): Don't add the hash values of the old and new
+	names together!  Reset HASHVAL before computing the second value.
+
+	* dir.c (check_changed_directories): Zero the new file hash table
+	after allocating it.
+
+	* dir.c (dir_file_exists_p): If FILENAME is "", return 1 if the
+	directory exists.
+
+	* vpath.c (check_changed_vpaths): New function to run through the
+	search paths of all VPATHs, making the `exists' members correspond
+	to reality.
+
+	* commands.c (child_handler): Call check_changed_vpaths.
+
+	* make.h: Declare check_changed_vpaths.
+
+	* vpath.c (struct vpath): New element `exists', an array of char
+	flags; exists[N] is nonzero if searchpath[N] exists.
+	(construct_vpath_list): Set the `exists' member.
+	(selective_vpath_search): Don't search directories whose `exists'
+	elements are zero.
+
+	* read.c (read_makefile): Set the `dontcare' flag of makefiles
+	from the MAKEFILES variable if they were not mentioned anywhere but
+	in the MAKEFILES variable.
+
+	* read.c (read_makefile): Don't write an error message if fopen
+	fails for a makefile from the MAKEFILES variable.
+
+	* dir.c (struct directory): Add `modtime' member to record the
+	modification time of the directory when it was opened.
+	(check_changed_directories): New function to check all known
+	directories; if their modtimes have changed since they were opened,
+	their file tables are cleared and they are reset to be read in.
+
+	* commands.c (child_handler): Call check_changed_directories before
+	returning.
+	make.h: Declare check_changed_directories.
+
+Tue Mar 14 20:07:13 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.40.
+
+	* make.c (print_version): Made the copyright say 1988, 1989.
+
+	* read.c (read_all_makefiles): Don't set *MAKEFILES to the name of
+	the end of the read_makefiles chain, since the latter may be from an
+	included makefile.  (Why did I do this before?)
+
+	* make.c (main): Set argv[0] to "" if it was nil.  Don't put the
+	command-line variable definitions into argv[0], only into the MAKE
+	variable!
+
+Sun Mar  5 20:44:08 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* ar.c (ar_member_date, ar_touch): Remove the trailing ) from the
+	member name.
+
+Fri Mar  3 18:15:15 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (construct_command_argv): Initialize NEW_ARGV to 0.  At
+	`slow' label, if NEW_ARGV is not 0, free it; then allocate 4 strings.
+
+Tue Feb 28 14:29:39 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.39.
+
+	* COPYING, make.texinfo: New GNU General Public License, version 1.
+
+	* *.c, *.h, Makefile: New copyright notices for the new GNU General
+	Public License, version 1.
+
+	* commands.c [USG]: Define WRETCODE correctly (again).
+
+	* variable.c (expand_function: `shell'): Don't capture the standard
+	error output of the shell command.
+
+	* ar.c (ar_touch, ar_member_date): Allocate MEMNAME with the right
+	length.
+
+	* load.c [not UMAX] (load_average): Don't clobber the first nlist
+	member when trying to set the second!
+
+Thu Feb 23 13:13:53 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* commands.c (child_handler): Really ignore errors under -i and for
+	- lines, don't just print a different message.
+
+	* make.c (decode_switches): Fixed handling of arguments (or lack
+	thereof) to switches.
+
+Wed Feb 22 16:25:39 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* commands.c (construct_command_argv): Don't clobber LINE when
+	checking the IFS variable.
+
+Sun Feb 19 11:17:07 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* load.c [UMAX, not NO_LDAV] (load_average): Return 0.0 rather than
+	randomness when calls fail.
+
+	* Version 3.38.
+
+	* commands.c (fatal_error_signal): If handling a user kill signal
+	(TERM, INT, HUP), wait for the children without printing the
+	"Waiting for children" message, since they will die quickly.
+
+	* Version 3.37.
+
+	* remote-stub.c (remote_status): Take another arg, BLOCK.  If this
+	is nonzero block waiting for remote children.  If not, return 0 if
+	we would have to block.
+
+	* commands.c (child_handler) [not USG]: If called as a signal
+	handler, use wait3 and don't block.
+	[USG]: If called as a signal handler, return after handling one child.
+
+Sat Feb 18 13:37:04 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* file.c (snap_deps): Process all double-colon entries of each file,
+	not just the first one.
+
+	* Version 3.36.
+
+	* remote-stub.c: remote.c renamed.
+	remote.c: Just include remote-stub.c
+
+	* commands.c (child_handler): If we were called as a signal handler,
+	return after handling one child.
+
+	* commands.c [not USG]: Include <signal.h> and define `sigmask' if
+	<signal.h> doesn't.
+	(block_children, unblock_children): Use sigmask rather than
+	bitshifting explicitly (and incorrectly).
+
+	* remote.c (remote_kill): New function to send a signal to a
+	remote child.
+
+	* commands.c (fatal_error_signal): If we get a SIGTERM, send one to
+	each living child.  If we get a SIGTERM, SIGINT, or SIGHUP, delete
+	all pending targets before waiting for children.
+	(struct child): Add new member `deleted'.
+	(start_job): Initialize `deleted' member to 0.
+	(delete_child_targets): New function to delete a given child's
+	targets, unless the `deleted' flag in the `struct child' says they
+	have already been deleted.  Sets this flag before returning.
+
+Thu Feb 16 18:32:07 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c [USG]: Define `WRETCODE' correctly (X & 0xff00).
+
+Tue Feb 14 16:05:00 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (construct_command_argv): Don't make the 0th element of
+	the argument list be "sh" when executing /bin/sh, because start_job
+	uses the 0th element as the program name.
+
+Sun Feb 12 17:42:05 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.35.
+
+	* read.c (readline): Put a null in the beginning of the buffer
+	before starting the reading loop.
+
+	* read.c (read_makefile): Made main reading loop while
+	!feof (infile), and removed EOF check after calling readline.
+
+Sun Feb  5 19:52:38 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* remote.c (block_remote_children, unblock_remote_children): New
+	(stub) functions to block and restore asynchronous notification of
+	remote child death.
+
+	* commands.c (block_children): Call block_remote_children.
+	(unblock_children): Call unblock_remote_children.
+	(child_handler): If called as a signal handler, block remote
+	children on entry and unblock them before returning.
+
+	* commands.c (child_handler): For unknown children, if they are
+	remote, give their remote ID; if local, give their PID and make's.
+
+	* commands.c (execute_file_command): Don't put a new child in the
+	chain unless start_job succeeds.  Block children before calling
+	start_job, and unblock them after putting the child in the chain and
+	incrementing `job_slots_used' (if start_job succeeded).
+
+	* commands.c (block_children, unblock_children): Make these globally
+	visible (not `static').
+	commands.h: Declare block_children and unblock_children.
+
+	* variable.c (expand_function: `shell'): Use
+	`shell_function_completed'.  Block children before forking and
+	unblock after `shell_function_pid' is set properly and
+	`shell_functon_completed' is reset to 0.
+
+	* commands.c (child_handler): When the child of the `shell' function
+	completes, set `shell_function_completed' to 1 if it actually ran,
+	or -1 if it didn't (due to fork or exec failure).
+
+	* commands.c (block_children, unblock_children): New functions to
+	block and unblock the child termination signal.
+	(wait_for_children): Use block_children and unblock_children.
+	(execute_file_commands): Block children around the critical section
+	wherein a new child is put on the chain.
+
+	* make.c (main): Change the environment to contain the correct
+	MAKELEVEL before re-execing.
+
+Sat Feb  4 18:28:48 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.34.
+
+Fri Feb  3 16:36:49 1989  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* rule.c (default_variables): Fixed $(LINK.c).
+
+Wed Feb  1 18:05:07 1989  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)
+
+	* Version 3.33.
+
+	* version.c: Removed copyright notice, since this is a one-line file.
+
+	* commands.c (error_status): Made it return BUF, rather than running
+	off the end (this apparently worked on Sun 3s for some reason).
+
+	* ar.c, commands.c, dep.h, load.c, make.c, make.h, read.c, remake.c,
+	rule.c, variable.c, Makefile: Changed copyrght notices to cover 1989.
+
+Mon Jan 30 15:51:28 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.32.
+
+Fri Jan 27 20:09:24 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* remake.c (remake_file): Don't touch phony targets.
+
+	* rule.c (convert_to_pattern): Fixed an incorrect length passed to
+	savestring.
+
+	* variable.c (expand_function: `shell'): Close the read side of the
+	pipe on the parent side of the fork.
+
+	* commands.c (start_job): On the child of the fork, close the
+	BAD_STDIN fd if we're not using it.
+
+	* read.c (record_files): A file beginning with a dot can be a
+	default target if it also contains a slash (as in `../foo').
+
+	* commands.c (wait_for_children): For BSD, block SIGCHLD rather than
+	ignoring it to avoid a race condition when child_handler is returning.
+
+	* commands.c (child_handler): Do blocking waits.
+	(error_status): Return a string describing exit status.  (Split out
+	of child_handler).
+
+	* read.c (multi_glob): Change VECTOR to VEC for Alliant.
+
+Thu Jan  5 00:06:51 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.31.
+
+	* make.texinfo (Features): Noted $(foo:PAT=SUB) from SunOS 4.0.
+
+	* make.texinfo (Options/Recursion): -d and -p go in the environment.
+
+	* load.c: Include "commands.h".
+
+Wed Jan  4 17:49:25 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* make.c (switches): -d and -p can come from the environment and are
+	put into it.
+
+	* read.c (record_files): Fixed the checking for duplicate deps so it
+	doesn't clobber the first one.
+
+	* make.texinfo: Documented default implicit rule changes.
+
+	* rule.c: Revamped default suffix rules.  They now use Sun's style
+	of using variables `COMPILE.c', `LINK.c', etc. for each suffix, and
+	use `TARGET_ARCH' and `TARGET_MACH' variable where appropriate.
+	Also support Modula-2 compilation (suffixes .sym, .def, and .mod).
+	Ratfor Yacc support is gone, since nobody has yacc -r.
+	All EFL support is gone, since nobody uses EFL.
+
+	* ar.c, arscan.c: Don't assume `long int' and `int' are the same.
+
+	* commands.c [USG]: Fixed wait status bit encoding.
+	[USG and not USGr3] (dup2): Define this for SysVr2.
+
+	* make.h, dep.h, make.c [iAPX286]: Make allowances for this
+	brain-damaged compiler.
+
+	* make.texinfo (Variables: Flavors): Fixed a typo.
+
+Tue Jan  3 18:09:31 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* ar.c (ar_member_date, ar_touch): Truncate member names to 15 chars.
+
+	* Version 3.30.
+
+	* commands.c [SYS_WAIT]: If this is defined, use BSD <sys/wait.h>
+	and wait3 even if USG.
+
+	* read.c (record_files): Defining .DEFAULT with no deps or commands
+	clears its commands.
+
+	* rule.c (default_suffixes): Added `.sh'.
+	(default_suffix_rules): Added single-suffix .sh rule, copies source
+	to target and makes target executable.
+	make.texinfo (Catalogue of Rules): Documented .sh rule and its use
+	in conjunction with SCCS.
+
+	* rule.c (set_default_suffixes): Define variable `SUFFIXES' to the
+	default list ("" under -r).
+	make.texinfo (Suffix Rules): Document `SUFFIXES' variable.
+
+	* rule.c (default_variables), make.texinfo (Implicit Variables):
+	Variable AR defaults to `ar', ARFLAGS to `rv', and RM to `rm -f'.
+
+	* rule.c (install_default_pattern_rules): Default variables are made
+	recursive.
+	(default_variables): Added "CPP", defined to "$(CC) -E".
+	(default_suffixes): Added `.S', before `.s'.
+	(default_suffix_rules): New rule for .S to .s, runs CPP.
+	All rules that use CPP now include "$(CPPFLAGS)".
+	make.texinfo (Catalogue of Implicit Rules, Implicit Variables):
+	Documented above changes.
+
+	* commands.c [USG] (sys_siglist): Don't define.
+	[USG] (init_siglist): New function to initialize sys_siglist.
+
+	* make.texinfo (Variables: Reference): Documented `$(foo:PAT=SUB)'
+	references.
+
+	* variable.c (variable_expand): A reference `$(foo:PAT=SUB)' is
+	equivalent to `$(patsubst PAT,SUB,$(foo))'.
+
+	* variable.c (variable_expand): Free the storage for the expansion
+	of a recursive variable when it is nod longer needed.
+
+	* variable.c (variable_expand): When checking for `$($(foo))', use
+	lindex so as not to search for the second `$' outside the parens.
+
+	* make.c (struct stringlist, main, decode_switches): Changed `index'
+	member to `idx'.
+
+Sat Dec 24 16:02:32 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (wait_for_children [USG]): Handle SIGCLD with SIG_DFL,
+	rather than SIG_IGN.  Ignoring SIGCLD reportedly makes wait return -1.
+
+	* arscan.c [USGr3]: Define PORTAR to 1 (as with sun386).
+	(ar_scan [USGr3]): Remove trailing slashes from member names.
+
+Thu Dec 22 17:54:05 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* make.texinfo (Makefiles: Overriding Makefiles): New node
+	documenting use of .DEFAULT to have one makefile defer unmakeable
+	targets to another.
+
+	* make.texinfo (Implicit: Using Implicit, Implicit: Last Resort):
+	Mention empty commands and xref node `Empty Commands'.
+
+Wed Dec 21 20:12:40 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Version 3.29.
+
+	* make.c (struct command_switch, command_switches, et al): New
+	member `noarg_value', if not nil, ptr to value to use if no arg is
+	given to a switch that would otherwise require one.  The -j option
+	can now be given w/o an arg, to mean infinite jobs.
+	* commands.c: If job_slots is zero, infinite jobs.
+
+	* read.c (read_all_makefiles, read_makefile): Make makefiles precious.
+
+	* make.c (decode_switches): For a positive_int or floating option,
+	if we moved to the next argument word, but found no argument for the
+	option, move back to the correct word.
+
+	* make.c (decode_switches): If we got any unknown options, die after
+	processing all arguments.
+
+	* GNUmakefile: Moved `include depend' to the end, so the default
+	goal will be set before then.
+
+	* load.c (wait_to_start_job [Unix, UMAX]): Merged into one version
+	under #ifdef LDAV_BASED.  Only loop while we have jobs running.
+	Sleep for increasing amounts (increase one second per iteration)
+	before checking the load average (after the first check).
+	Get the load average from function load_average.
+	(wait_to_start_job [not LDAV_BASED]): Always return.
+	(load_average [UMAX]): Fetch load average for Encore UMAX.
+	(load_average [not NO_LDAV]): Fetch load average from /dev/kmem.
+	[not NO_LDAV]: Define LDAV_BASED.
+
+Tue Dec 20 18:54:50 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Version 3.28.
+
+	* commands.c (wait_for_children): Take second arg, ERROR.  If
+	nonzero, and there are children, print a message on stderr.
+	(execute_file_commands, fatal_error_signal): Pass second arg.
+	* make.c (die), remake.c (update_goal_chain), variable.c
+	(expand_function: `shell'): Ditto.
+
+Sat Dec 17 01:05:38 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* commands.c (start_job): Call wait_to_start_job before forking.
+
+	* load.c (load_average): Converted to wait_to_start_job.
+
+	* remote.c: New file for remote execution functions.
+	(start_remote_job_p): Return nonzero if the next job should be run
+	remotely.
+	(start_remote_job): Start a remote job and return an ID for it.
+	(remote_status): Get status of dead remote children.
+
+Fri Dec 16 16:51:07 1988  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)
+
+	* commands.c (start_job): If start_remote_job_p () returns nonzero,
+	call start_remote_job to start the job rather than fork and exec.
+	(child_handler):
+
+	* commands.c (execute_file_commands): Moved load average checking to
+	start_job.
+
+	* commands.c (child_handler: USG): Record the pid wait returns.
+
+	* load.c (UMAX): Added some #include's needed for UMAX.
+
+	* read.c (multi_glob), variable.c (string_glob): Ignore a (char **)
+	-1 return from glob_filename.
+
+	* variable.c (variable_expand): Make sure we don't increment past
+	the end of the string we were passed.
+
+	* variable.c (variable_expand): Terminate the expansion.
+
+	* file.c (rename_file): If there is already a file under the new
+	name, set its contents equal to FILE's (ick).
+
+	* variable.c (define_automatic_variables): Pass all the args to
+	define_variable when defining MAKELEVEL!
+
+	* commands.c (execute_file_commands): If max_load_average > 0, and
+	we have children running, don't start up another child until the
+	load average goes below max_load_average.
+
+	* make.c: New variable `max_load_average'.
+	(struct command_switch, decode_switches, decode_env_switches):
+	Handle floating-point (double) args.
+	(command_switches): Added `-l' switch to set `max_load_average'.
+
+	* load.c (load_average): New file and function to return a double
+	that is the current load average (1.00 scale).
+	* GNUmakefile, oldMakefile: Pass flags in $(LOAD_AVG) for load.c.
+
+Thu Dec 15 15:22:08 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Makefile: Renamed to oldMakefile.
+	* GNUmakefile: Make Makefile from oldMakefile and depend.
+
+	* read.c (read_all_makefiles): When putting the default makefiles in
+	the read_makefiles chain so they will be remade, put them in the
+	right order.
+
+	* remake.c (update_goal_chain): If MAKEFILES is nonzero, always make
+	in serial, and return as soon as one goal whose `changed' member is
+	nonzero  is successfully remade.
+
+	* commands.c: Don't include <sys/fcntl.h>.
+
+	* commands.c (construct_command_argv): Added ` to sh_chars.
+
+	* make.h: Don't declare construct_makeflags.
+
+	* make.c (main): Set up MAKEFLAGS and MFLAGS and make an environment
+	both before and after reading the makefiles, so the makefiles can
+	use them and possible change them, and later children will get the
+	right information.
+	(construct_makeflags): Replaced with define_makeflags (static void),
+	which defines the two variables.
+	* variable.c (define_automatic_variables): Don't define MAKEFLAGS
+	and MFLAGS.
+
+Mon Dec 12 14:40:31 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* Version 3.27.
+
+	* commands.c (child_handler): Reset the handler to ourselves when
+	called for USG, since it has no safe signals.
+
+	* commands.c: For USG, use an int rather than a `union wait' for
+	wait calls, and dissect it with bitmasks.
+	(child_handler): No wait3 system call in USG.  Since we can't
+	protect from hanging, always return immediately if we have no
+	children we know about and we're not running a `shell' function.
+	(There is still the danger of hanging waiting for a child that died
+	without our being notified.)
+
+	* remake.c: Include <fcntl.h> instead of <sys/file.h>.  What we need
+	is really in <fcntl.h>, and while BSD <sys/file.h> includes
+	<fcntl.h>, USG doesn't.
+
+	* make.c (main): Figure out the program name before doing anything
+	which might need it (in a call to error or fatal).
+
+	* dir.c, glob.c: Use `struct dirent' and <dirent.h> for USGr3.
+
+	* arscan.c (ar_scan): Added missing & before buf (which is an int)
+	if SARMAG is not defined (SysV).
+
+Fri Dec  9 18:44:13 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)
+
+	* Version 3.26.
+
+	* dir.c (find_directory, dir_file_exists_p): Keep track of how many
+	directories we have open and don't let it be more than
+	MAX_OPEN_DIRECTORIES (currently 10).
+
+	* variable.c (expand_function: `foreach'): Use expand_argument
+	rather than variable_expand so each repetition doesn't clobber the
+	last!!!
+
+Mon Dec  5 15:58:46 1988  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)
+
+	* Version 3.25.
+
+	* Makefile: Define `install' target.
+
+	* GNUmakefile: Don't include GNUmakefile or depend in the
+	distribution file.
+
+Wed Nov 30 15:53:42 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* commands.c (execute_file_commands): Don't clobber a null into
+	random storage if there were no $^ and/or $? words.
+
+	* remake.c (check_dep): Set *MUST_MAKE_PTR nonzero if a dependency
+	doesn't exist.
+
+	* ar.c (ar_member_date, ar_touch): Make sure the modtime of the
+	archive file itself is known before we fetch or change the modtime
+	of one of its members.
+
+	* read.c (read_makefile): Expand variable and function references
+	before parsing rules so variable can contain special characters
+	(colons and semicolons).
+
+Sat Nov 26 11:36:31 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* variable.c (expand_function: `filter', `filter-out'): Fixed so
+	that filter-out works right.
+
+	* variable.c (expand_function: `filter', `filter-out'): Made these
+	functions use each word of their first argument as a pattern.
+
+Fri Nov 25 10:51:47 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.24.
+
+	* read.c (record_files): If a target is listed more than once in a
+	single rule (that defines commands), give a warning message rather
+	than the counter-intuitive message saying commands were already
+	defined (in the same place).
+
+	* make.c (fatal, error): Made them both take 6 args since there is
+	at least one error message that need that many.  Too bad vfprintf is
+	not universal!
+
+	* Version 3.23.
+
+	* read.c (read_makefile): Moved the construction of the `struct
+	commands' into record_files.  Call record_files before recursing for an
+	included makefile so the higher-up will determine the default goal.
+	(record_files): Take arguments COMMANDS, COMMANDS_IDX and
+	COMMANDS_STARTED and construct a `struct commands.
+
+Thu Nov 24 14:36:33 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.22.
+
+	* make.c (main): Made it a fatal error if we can't move back to the
+	directory we started in before re-execing.
+
+	* make.c (main): Get the current directory before doing anything
+	else, so we know it even if we don't need it for the value of
+	`MAKE', since we might want it when re-execing.
+
+Wed Nov 23 13:34:44 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.21.
+
+	* read.c (record_files): Eliminate duplicate deps in a chain.
+
+	* variable.c (expand_function: `sort'): Pass the right number to
+	qsort, not one less.
+
+	* remake.c (remake_file): Always call notice_finished_file if
+	FILE->command_state == cs_finished.
+
+	* commands.c (execute_file_commands): Call notice_finished_file to
+	set FILE's status correctly when start_job fails (because it's out
+	of commands or running under -n).
+
+Fri Nov 18 15:31:12 1988  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)
+
+	* Version 3.20.
+
+	* remake.c (update_file_1): Set the `update_status' of FILE to
+	nonzero and set FILE's `updated' bit if we have decided to give up
+	on remaking FILE because of errors in the dependencies.
+
+	* rule.c (pattern_search): Debugging messages use `dependency' (vs.
+	`dependent') properly.
+
+	* make.texinfo (Conditionals: Conditional Syntax): Function index
+	entries for `ifndef' and `ifneq'.
+
+	* variable.c (define_automatic_variables): Define `MAKELEVEL' to the
+	decimal number of the makelevel, since it may be malformed or blank.
+
+	* remake.c (remake_file): Call notice_finished_file after touching.
+
+Sat Nov 12 19:29:34 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Version 3.19.
+
+	* GNUmakefile (dist): Pass the `-f' flag to compress.
+
+	* vpath.c (build_vpath_lists): Check for VPATHS being nil after
+	constructing the general VPATH list from the `VPATH' variable.
+
+Fri Nov 11 08:02:26 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.c (fatal, error): Made error messages for recursive runs be
+	shorter.
+
+Thu Nov 10 16:51:36 1988  Roland McGrath  (mcgrath at basil.Berkeley.EDU)
+
+	* Version 3.18.
+
+	* read.c (read_makefile): Made it eat leading spaces and formfeeds
+	(but not tabs), like it's documented to.
+
+	* read.c (read_makefile): Let included makefiles determine the
+	default goal, as is done by System V Make.
+
+Tue Nov  1 19:03:08 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* variable.c (new_environ): Don't increment VCNT when a variable is
+	rejected.
+
+Fri Oct 28 16:54:15 1988  Roland McGrath  (mcgrath at basil.Berkeley.EDU)
+
+	* Version 3.17.
+
+	* rule.c (convert_to_pattern): Don't use the same storage for a name
+	in two rules since new_pattern_rule may free this storage when a
+	rule is discarded.
+
+	* rule.c (new_pattern_rule): Undid useless change I made Oct 25.
+
+Thu Oct 27 19:17:53 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Version 3.16.
+
+	* GNUmakefile, Makefile: Fixed a typo in a comment.
+	* Makefile: Removed malloc.o from object file list.
+
+	* variable.c: Removed old debugging #define's for xmalloc and
+	xrealloc so non-ANSI cpp's won't barf.
+
+	* make.c (main): Made local array for temp file name static so
+	compilers that don't do auto aggregate initialization won't barf.
+
+	* read.c: Removed static declaration of copy_dep_chain since it is
+	no longer static.
+
+Tue Oct 25 16:59:30 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)
+
+	* rule.c (new_pattern_rule): If we threw out the new rule because it
+	matched an old one and OVERRIDE was zero, don't put the freed
+	pointer in the chain!
+
+Wed Oct 19 15:07:43 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)
+
+	* Version 3.15.
+
+	* variable.c (expand_function: `sort'): Don't do the sorting and
+	writing out if there were no words in the first place.
+
+	* remake.c (remake_file): Only fail with a "no way to make" message
+	for a dependency (non-target) file.  If we don't know how to remake
+	a target file, pretend it was successfully remade and is very new.
+
+	* remake.c (remake_file): Don't increment `files_remade' for a
+	non-target file we don't know how to remake.
+
+	* read.c (record_files): Don't die with "both : and :: entries" for
+	a file whose `is_target' flag is not set.
+
+Tue Oct 18 17:24:11 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* variable.c (expand_function: `patsubst', `subst'): Free the right
+	things!
+
+	* variable.c (expand_function: `subst'): Don't clobber the
+	pointer to the end of the second arg and then try to use it!!!
+
+Mon Oct 17 16:44:45 1988  Roland McGrath  (mcgrath at catnip.Berkeley.EDU)
+
+	* variable.c (expand_function: `patsubst'): Don't clobber the
+	pointer to the end of the second arg and then try to use it!!!
+
+	* variable.c (expand_function: `word' function): Made it parse its
+	second argument correctly.
+
+	* ar.c (ar_touch): Return 1 rather than -1 for on errors.
+
+Sat Oct 15 15:12:16 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.14.
+
+	* GNUmakefile: Removed explicit rule for make.dvi since the built-in
+	implicit rule now works.
+
+	* rule.c (default_suffix_rules): Fixed .texinfo.dvi rule yet again
+	so that it really works, now that parens are counted.
+
+	* remake.c (update_file_1): Set FILE's `updated' flag after calling
+	remake_file if it failed or finished immediately.
+
+	* remake.c (update_file): Use the `updated' flag rather than the
+	command state to decide if a file was fully considered, and
+	therefore might give an "up to date" message.
+
+	* variable.c (expand_function): Made all functions that take more
+	than one argument count parens of the appropriate flavor in their
+	args and ignore commands nested in parens.
+
+Fri Oct 14 18:35:00 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* read.c (read_all_makefiles): Pass second arg to read_makefile for
+	default makefiles.
+
+Thu Oct 13 16:40:08 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Version 3.13.
+
+	* GNUmakefile: Added an explicit rule for make.dvi since the
+	built-in .texinfo.dvi implicit rule is screwed up.
+
+	* rule.c (default_suffix_rules): Added a comment that the
+	.texinfo.dvi rule does not work because of an ahem, feature of Make
+	that at some point will be fixed--er, enhanced to alleviate this
+	difficulty.
+
+	* rule.c (default_suffix_rules): Fixed Texinfo -> DVI rule (again).
+
+	* make.texinfo (Commands: Execution): Documented new competing for
+	standard input among children.
+
+	* commands.c (struct child): Added `good_stdin' flag to tell if this
+	child has the stdin that doesn't point into nirvana.
+	(good_stdin_used): New variable to tell if any child has the good
+	standard input.
+	(child_handler): Reset `good_stdin_used' if a dead child's
+	`good_stdin' flag is set.
+	(start_job): Give the new child the good standard input if
+	`good_stdin_used' is no set, and set the child's `good_stdin' flag
+	appropriately.
+
+	* rule.c (default_suffix_rules): Changed Texinfo -> DVI rule to work
+	better (I hope).
+
+	* read.c (read_all_makefiles): Stop reading default makefiles after
+	one is found.
+
+	* read.c (read_makefile): Reset `reading_filename' and
+	`reading_lineno_ptr' after recursing for an included makefile.
+
+	* GNUmakefile: New GNU Make-specific makefile that does everything
+	Makefile does plus distribution stuff, and doesn't contain any hacks
+	to try to work with Unix make.
+
+	* Makefile: Removed distribution stuff.
+
+	* make.c (main): Use mktemp to construct the names of temporary
+	files used for standard input makefiles.
+
+	* make.c (main): Don't turn standard input into a broken pipe.
+
+	* commands.c (start_job): Keep two extra file descriptors around: a
+	good standard input, and a bad one that reads from a broken pipe.
+	On the child side of the fork, if there are other children, give
+	this one the broken pipe so they won't compete; if this is the only
+	one, give it the good standard input.
+
+	* make.h: Declare notice_finished_file.
+
+	* commands.c (execute_file_commands): Use noticed_finished_file
+	after waiting for the child when there is only one job slot.
+
+	* remake.c (notice_finished_file): New function to re-check mtime's
+	and such things to be done when commands finish.
+	(update_file_1): Use notice_finished_file.
+
+	* commands.c (child_handler, execute_file_commands): Use new
+	variable `job_slots_used' to record the number of jobs currently
+	running, rather than diddling with `job_slots'.
+	(execute_file_commands): Increment `job_slots_used' before calling
+	start_job and decrement it on failure to avoid race condition.
+	If there is only one job slot, wait for the child to finish and
+	return its status so commands are run in linear order, as if there
+	were no parallelism.
+
+Wed Oct 12 15:59:03 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* remake.c (remake_file): Don't print a "No way to make" message for
+	targets whose `dontcare' flags are set.
+
+	* read.c (read_all_makefiles): Set the `dontcare' flag of the
+	`struct file' each default makefile added to the chain.
+
+	* file.h (struct file): Add `dontcare' member.
+
+	* read.c (read_all_makefiles): When no default makefiles are found,
+	put the names of all those tried in the `read_makefiles' chain so
+	they will be updated if possible, giving their `struct dep's'
+	`changed' members the value of 0 so we won't care if they cannot be
+	found or remade.
+
+	* make.texinfo (Makefiles: Remaking Makefiles): Documented that
+	default makefiles will be remade if not found.
+
+	* read.c (read_all_makefiles): If no default makefiles can be found,
+	go through the list of default names, trying to make one, stopping
+	if one is made.
+
+	* remake.c (remake_file): Set STATUS to 0 after successfully touching.
+
+	* dir.c (file_impossible, file_impossible_p): Don't clobber FILENAME
+	to "" and then try to to a strcmp on it!!!
+
+Mon Oct 10 16:09:18 1988  Roland McGrath  (mcgrath at cinnamon.Berkeley.EDU)
+
+	* make.c (main): Don't do `dir_load (".")'.
+
+	* rule.c (count_implicit_rule_limits), vpath.c
+	(construct_vpath_list): Test the existence of a given directory by
+	`dir_file_exists_p (DIR, ".")' and assume that if this returns zero,
+	it means the directory really does not exist.
+
+	* dir.c (struct dirdata): Replaced with `struct directory' for
+	directories, each containing a chain of `struct dirfiles', one for
+	each file (real or impossible).
+	(dir_load): Removed.
+	(find_directory): New function to find the `struct directory' for a
+	named directory and return it (possibly creating a new one).
+	(dir_file_exists_p): Read the directory on the fly if its stream is
+	still valid (and ever was) if the file we're looking for is not
+	already in the hash tables.
+	(file_impossible, file_impossible_p, dir_name, print_dir_data_base):
+	Use the new directory/file scheme.
+
+	* make.texinfo: Miscellaneous editorial changes and clarifiactions.
+
+	* commands.c (struct child): Remove `environ' member.
+	(child_handler, start_job, execute_file_commands): Remove use of
+	`environ' member and new_environ.
+
+	* make.c (main): Call new_environ after reading makefiles.
+
+	* variable.h: Declare `new_environ' to return void.
+
+	* variable.c (new_environ): Put the environment in `environ' and
+	return void.
+
+Fri Oct  7 15:48:39 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)
+
+	* Version 3.12.
+
+	* Makefile: Don't make the uncompressed tar file.
+
+	* variable.c (expand_function: `shell' function): Made it not expect
+	read to null-terminate the buffer.
+
+	* Makefile: Made it use a temporary symlink to . rather than a
+	temporary directory to make the distribution tar file.
+
+Thu Oct  6 17:52:35 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.11.
+
+	* make.texinfo: Fixed a line that got garbaged somehow.
+
+Mon Oct  3 16:14:39 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* make.c (main): Try to move back to the directory we started in
+	before re-exec ourself.
+
+	* remake.c (update_file_1): A double-colon target with no deps
+	always needs to be remade.
+
+	* remake.c (remake_file): Changed "No way to make" message to say
+	`target' rather than `file'.
+
+Sun Oct  2 12:50:47 1988  Roland McGrath  (mcgrath at catnip.Berkeley.EDU)
+
+	* remake.c (update_file_1): Set FILE->update_status to the return
+	value of remake_file.
+
+	* rule.c (convert_to_pattern): Fixed swapped lengths passed to
+	xmalloc for source/target suffixes.
+
+	* make.texinfo: Documented that MAKEFLAGS and MFLAGS are read in
+	from makefiles.  Updated the `Features' section a bit.
+
+	* make.c (main): Read switches from MAKEFLAGS and MFLAGS variables
+	after reading in makefiles.
+
+	* make.c (main): Put a line "/tmp/foo:;" rather than ".PHONY:
+	/tmp/foo" in front of temp files made for stdin makefiles.
+
+	* remake.c (update_file): Test the state of the right `struct file'
+	for double-colon files.
+
+	* make.c (main): Put a ".PHONY: /tmp/foo" line in front of temp
+	files made for stdin makefiles so they won't be remade when we
+	re-exec.  Kludge-o-matic!!
+
+	* remake.c (update_goal_chain): Judge files as being finished based
+	on their `updated' flag, not their state.
+
+	* read.c (read_makefile): Don't check for FILENAME being "-".
+	(read_all_makefiles): Set each element of MAKEFILES to the name put
+	in READ_MAKEFILES by read_makefile, since read_makefile may free the
+	storage for the name it is passed, and someone might want to look at
+	the elements of MAKEFILES again.
+
+	* make.c (main): For each `-f' flag with arg `-' (standard input),
+	read standard input into a temp file and pass the temp file's name
+	to read_all_makefiles, after making sure it will not be remade.
+
+	* make.c (construct_makeflags): Always put out `-j1'.
+
+Sat Oct  1 00:19:59 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* commands.c (execute_file_commands): If commands are nothing but
+	whitespace, set the state to `cs_finished' before returning 0.
+
+	* make.c (decode_switches): Allocate space for args in stringlists
+	so they can be freed later.
+
+	* make.h: Declare `makelevel'.
+
+	* variable.c (makelevel): Moved to make.c (and made global).
+
+	* make.c (fatal, error): Print the makelevel if it's > 0.
+	(perror_with_name): Use error rather than calling fprintf directly.
+	(pfatal_with_name): Use fatal rather than fprintf and die.
+
+	* variable.c (new_environ): Don't put default variables (origin
+	`o_default') into the environment; they just take up space.
+
+	* read.c (read_makefile): Don't add FILENAME to the chain of read
+	makefiles if it's "-" (standard input).
+
+	* remake.c (update_goal_chain): Set STATUS correctly when nothing
+	happens (as well as in all other situations).
+
+	* make.c (construct_makeflags): Put a `-' before each switch and
+	spaces between them.
+
+	* Version 3.10.
+
+	* commands.c (wait_for_children): Don't check if `children' is nil.
+	This is the case when waiting for the child of a `shell' function.
+
+	* dir.c (dir_load): Don't add a hash-table entry for directory
+	DIRNAME and filename "" if DIRNAME doesn't exist.
+
+	* commands.c (execute_file_commands): Return 0 after start_job
+	returns 1 (failure) under the -n flag.
+
+	* remake.c (remake_file): Set the state to `cs_finished' when not
+	calling execute_file_commands.
+
+	* remake.c (update_goal_chain): Second arg is now MAKEFILES, nonzero
+	meaning to disable -t, -q, and -n for each target unless the target
+	was also given on the command-line.
+
+	* read.c (read_makefile): Enter the `struct file's for the makefiles
+	added to the `read_makefiles' `struct dep' chain.
+
+	* remake.c (update_goal_chain): Made it not enter the files for the
+	goals in the chain.  It will already have been done.
+
+	* rule.c (convert_to_pattern): Null-terminate the names of targets
+	and deps of the pattern rules properly.
+
+Fri Sep 30 18:56:20 1988  Roland McGrath  (mcgrath at nutmeg.Berkeley.EDU)
+
+	* make.c (main): Call install_default_pattern_rules.
+
+	* make.h: Declare copy_dep_chain.
+
+	* read.c (copy_dep_chain): Moved to make.c (and made global).
+
+	* make.c (main): Call update_goal_chain to update goals.
+	Update read makefiles and re-exec self if they change.
+
+	* remake.c (update_file): Make this function static.
+	(update_goal_chain): New function to update a `struct dep' chain of
+	goals, waiting until they are all finished before returning.
+
+	* make.h: Don't declare update_file.  Declare update_goal_chain.
+
+	* make.c (main): Call snap_deps, etc. that were in read_all_makefiles.
+
+	* read.c (find_makefile): Removed this function.
+	(read_all_makefiles): Don't update makefiles, don't diddle with
+	pattern rules, don't call snap_deps, etc.  Return a `struct dep'
+	chain of all makefiles read.
+	(read_makefile): Now takes two args: FILENAME and TYPE, which is 0
+	for a normal makefile, 1 for MAKEFILES variable or 2 for an included
+	makefile.  Add a `struct dep' containing the name of the makefile
+	(as it was found in the search path for type 2s), and TYPE in the
+	`changed' member to the global `read_makefiles' chain.
+
+	* make.h, rule.c (displace_pattern_rules,
+	add_displaced_pattern_rules): Removed these functions.
+
+	* read.c (read_makefile): Variable-expand the name of an `include'd
+	makefile before calling find_makefile on it.
+
+	* file.c (snap_deps): If the `struct file' for a `struct dep'
+	already exists, free the `struct dep's `name' member before setting
+	it to nil (since this info is in the `struct file').
+
+	* read.c (copy_dep_chain): Made it copy each name rather than
+	leaving multiple `struct dep's with the same pointers.
+
+Thu Sep 29 19:08:13 1988  Roland McGrath  (mcgrath at catnip.Berkeley.EDU)
+
+	* make.c (decode_switches): Fixed second decode_env_switches call to
+	use correct length of "MFLAGS" (6, not 5).
+
+	* read.c (read_makefile): Don't stop reading when readline returns
+	zero lines read.  Only stop when the stream reaches EOF.  This makes
+	it recognize the last line of a makefile without a newline.
+
+	* remake.c (remake_file): If we don't know how to make FILE, set its
+	command state to `cs_finished'.
+
+	* remake.c (update_file): Don't write the "up to date" message if
+	update_file_1 returned a nonzero status.
+
+Wed Sep 28 16:30:07 1988  Roland McGrath  (mcgrath at catnip.Berkeley.EDU)
+
+	* commands.c (child_handler): Set the `update_status' member
+	properly for ignored errors.
+
+	* rule.c (convert_to_pattern): Made it not care about if the target
+	suffix comes before the source suffix in the .SUFFIXES list.
+
+	* make.texinfo: Misc editorial changes.
+
+	* commands.c (wait_for_children): Return immediately if `children'
+	is nil (there are no children).
+
+Tue Sep 27 15:33:14 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)
+
+	* Version 3.09.
+
+	* commands.c (struct child): New member `command_ptr' to hold the
+	current position in the commands.  The `commands' member is never
+	changed.
+	(start_job, child_handler, execute_file_commands): Use new method
+	for `commands' and `command_ptr' members.
+
+	* make.c (decode_env_switches): Skip past an invalid letter (instead
+	of looping forever).
+
+	* commands.c (struct child): Add `environ' member to hold the
+	environment for this child.
+	(execute_file_commands): Get a new environment from new_environ and
+	put in the the new `struct child's `environ' member.
+	(child_handler): When freeing a child, free its `commands' member, the
+	elements of its `environ' array and its `environ' member itself.
+	(start_job): Set `environ' to the child's `environ' member before
+	exec'ing the command.
+
+	* variable.h, variable.c (new_environ): Made it return the new
+	environment, not putting it in `environ'.
+
+	* remake.c (update_file): Don't give a "is up to date" message
+	unless no files were remade and the state went from `cs_not_started'
+	to `cs_finished', so repeat calls to finish jobs won't get the message.
+
+Mon Sep 26 16:26:08 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* Version 3.08.
+
+	* make.texinfo (Commands: Execution): Documented that children will
+	be waited for rather than killed.
+
+	* commands.c (fatal_error_signal): Wait for children.
+	(kill_children): Removed this function.
+
+	* make.c (main, die): Wait for children to die, don't kill them.
+
+	* variable.c (expand_function): Use wait_for_children.
+
+	* make.c (main): Use wait_for_children rather than child_handler.
+
+	* commands.c (wait_for_children): New function to block waiting for
+	children, insuring that child_handler is not called recursively.
+	(execute_file_commands, kill_children): Use wait_for_children.
+
+	* commands.c (child_handler): Start up additional commands in a
+	sequence after an ignored error.
+
+	* remake.c (update_file): Don't print "`foo' is up to date" messages
+	when update_file_1 returns while commands are executing.
+
+	* remake.c (update_file_1): Pass the file name to name_mtime, not
+	the bloody `struct file', dammit!!
+
+	* commands.c (child_handler): Print out the "*** ..." error message
+	when not under -i.  (I somehow forgot this.)
+
+	* remake.c (update_file_1): Use name_mtime rather than file_mtime to
+	re-get the mtime of a file whose commands have finished.
+
+	* make.c (command_switches, decode_switches, decode_env_switches):
+	Make all switches that take string args allow them right after the
+	switch letter.
+
+	* commands.c (child_handler): Check for a child being the `shell'
+	function's command returning and set the global variable for
+	expand_function to check.
+
+	* variable.c (expand_function): For the `shell' function, instead of
+	waiting for the child shell ourselves, let child_handler do it and
+	loop around waiting for something to happen.
+
+	* make.c (print_version): Made the copyright year static, not dynamic.
+
+	* make.h, make.c: Remove construct_argv function.
+
+	* make.c (main): Say "no goal target" instead of "no target".
+
+	* make.texinfo (Commands: Parallel): Don't send SIGKILL.
+
+	* commands.c (kill_children): Don't send SIGKILL to children that
+	aren't killed by the first signal.
+
+	* make.c (main), commands.c (kill_children): Decide between SIGCHLD
+	and SIGCLD based on whether or not SIGCHLD is defined, not on USG.
+
+	* Makefile: Link make with $(LOADLIBES).
+
+	* read.c (construct_include_path): Fixed another bad xrealloc call.
+
+	* make.c (decode_switches): Fixed an xrealloc call with no first arg.
+
+Sat Sep 24 01:16:21 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* Version 3.07.
+
+	* remake.c (update_file_1): If deps are running, set state to
+	`cs_deps_running' and return 0.  If deps are done, run commands.
+
+	* commands.c (child_handler): Made it delete non-precious targets
+	killed by fatal signals.
+
+	* make.texinfo: Documented parallelism.
+
+Fri Sep 23 16:52:27 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* remake.c (update_file_1): Don't return if FILE's state is
+	`cs_deps_running'.  In that case, we need to run through and check
+	the states of all our dependencies.
+
+	* commands.c (execute_file_commands): Decrement `job_slots' after
+	starting a new job to run file commands.
+
+	* commands.c (start_job): Made it set the state to `cs_running'.
+
+	* make.c (main): Fixed usage of `g', `lastgoal', and `goals' in the
+	goal-making loop.
+
+	* commands.c (child_handler): When commands finish, set the
+	corresponding file's `update_status' and `updated' flags as
+	appropriate, and reset the modtimes of the file and any `also_make'
+	files it has.
+
+	* remake.c (remake_file): Don't re-set `last_mtime' and set `updated'.
+
+	* commands.c (fatal_error_signal): Don't swallow all the children
+	with a loop around `wait ((union wait *) 0)'!!!
+
+	* make.c (struct command_switch): Added `positive_int' type.
+	(switches): Added -j (job_slots).
+	(construct_makeflags, decode_switches, decode_env_switches):
+	Handle`positive_int'-type switches.
+
+	* glob.c (glob_vector): Rename local variable `vector' to `VeCtOr'.
+	This is said to avoid a conflict with some system's global `vector'
+	variable.
+
+	* variable.c (expand_function): Made the `shell' function use
+	construct_command_argv and do its own child control and piping.
+
+	* make.c (main): Turn standard input into a broken pipe after
+	reading in all makefiles (the last time it will be needed).
+
+	* commands.c (struct child): Remove `pipe_fd' member.  We don't use
+	pipes any more.
+	(start_job): Return 0 for success, 1 or failure (rather than void).
+	Don't use pipes.  Don't turn the child's stdin into a broken pipe.
+	(child_handler): Print "*** Error" messages when necessary.
+	Die on failed commands when -k was not given.
+	(execute_file_commands): Check the return of start_job and remove
+	the child from the chain and return failure if it is nonzero.
+
+	* make.c (die): New function to clean up and exit.
+	(fatal, pfatal_with_name): Use die.
+
+Thu Sep 22 14:27:11 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* commands.c (struct child): Added `commands', `pipe_fd', and
+	`noerror' members to keep track of info about a command thread.
+	(start_job): New function to start a job and update the argument
+	`struct child' to reflect its status.
+	(execute_file_commands): Merged run_file_commands back in.
+	Made it use new start_job function.
+
+	* rule.c (freerule): Don't free the `struct commands' of the
+	discarded rule.  It may be used in more than one place.
+
+	* commands.c (execute_command_line): Made it not try to delete the
+	possibly partly-made file.  The child_handler function will do this.
+	(fatal_error_signal): Ditto + call kill_children.
+
+	* make.h: Declare job_slots.
+
+	* make.c (main): Collect goals in a dep chain and run through this
+	chain waiting for a child, eliminating finished goals, updating all
+	remaining goals, and quitting if they fail and not -k.
+
+	* commands.c (child_handler): If called with SIG < 0, - SIG is the
+	max number of children to bury.
+
+	* commands.c (child_handler): If called with SIG as zero,
+	block waiting for running children.
+	(kill_children): Call child_handler with zero rather than SIGCHLD.
+
+	* remake.c (update_file_1): Use the `command_state' member of FILE
+	and its dependencies to determine what commands are running, what to
+	do, etc.  If commands or dep commands are running when we are
+	called, return success (0).  If commands finished since the last
+	time we were called, return their status.
+
+	* commands.h: Declare kill_children.
+
+	* commands.c: Define `struct child' to keep track of child
+	processes, with the chain in `children'.
+	(child_handler): New function to catch child-termination signals
+	(SIGCHLD, or SIGCLD for USG), store the returned status in the
+	appropriate structure, take the now-obsolete `struct child' out of
+	the chain, and free its storage.
+	(execute_file_commands): Put all of the stuff invloving running the
+	commands into new function run_file_commands.  Execute_file_commands
+	now does process management for the commands, while
+	run_file_commands (which is run in a subprocess) runs the commands.
+	(kill_children): New function to kill all running children by
+	sending them signal SIG.  If there are any children still living
+	after they are all sent SIG, they are all sent SIGKILL.
+
+	* make.c (main): Catch SIGCHLD (SIGCLD for USG) with child_handler.
+
+	* commands.h: Declare child_handler function.
+
+	* commands.c (execute_file_commands): Check the `command_state'
+	member of FILE and return 0 if it is `cs_running' or
+	`cs_deps_running' and return the stored status if it is `cs_finished'.
+
+	* file.h (struct file): Added `command_state' member.
+
+	* commands.c (execute_command_line): Add `$' to the list of
+	characters special to the shell.
+
+Wed Sep 21 15:57:41 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* read.c (read_all_makefiles): Call convert_to_pattern before
+	recomputing the limits after adding the displaced rules.
+
+	* make.c (main): Move calls to snap_deps, convert_to_pattern, and
+	build_vpath_lists to read_all_makefiles.
+
+	* read.c (read_all_makefiles): Install the default pattern rules
+	before checking to remake the makefiles, displace these rules before
+	reading in the makefiles, and then add the displaced rules to the
+	chain after reading in all the makefiles.
+
+	* make.c (main): Don't call install_default_pattern_rules or
+	count_implicit_rule_limits.
+
+	* make.h: Declare displace_pattern_rules and
+	add_displaced_pattern_rules.
+
+	* rule.c (displace_pattern_rules, add_displaced_pattern_rules): New
+	functions to stow the chain and add the stowed chain on the end of
+	the current chain.
+
+	* make.texinfo (Implicit: Search Algorithm): Fixed PREV reference.
+
+	* make.c (main): Call construct_include_path right after decoding
+	the switches.
+
+	* read.c (find_makefile): Use rename_file.
+
+	* file.h: Declare rename_file.
+
+	* file.c (rename_file): New function to rename a `struct file' and
+	put it in the correct hash bucket.
+
+	* read.c (find_makefile): New function to find and update a makefile.
+	 (read_all_makefilese): Use find_makefile.
+	 (read_makefile): Don't do updating.  Removed UPDATEIT arg.
+
+	* remake.c (update_file_1): Took out setting the `updated' member to
+	-1 rather than 1 sometimes.
+
+	* make.c (main): Made it print version info before doing anything else.
+
+	* remake.c (library_file_mtime, f_mtime): Removed use of last two
+	arguments to vpath_search.
+
+	* rule.c (pattern_search): Removed use of last two arguments
+	to vpath_search.
+
+	* vpath.c (vpath_search, selective_vpath_search): Removed unused
+	DIRPREFIX and DPLEN args.
+
+	* read.c (read_makefile): Also turn off -n when updating makefiles.
+
+Tue Sep 20 17:01:10 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)
+
+	* Makefile: Put tags files in the tarfile.
+
+	* read.c (read_makefile): Get the modtime of the makefile via a stat
+	call so that a later file_mtime call won't do VPATH search for it.
+
+	* read.c (read_makefile): Don't turn off -t and -q if the makefile
+	was a command-line target.
+
+	* make.c (main): Enter command-line targets as files and set their
+	`cmd_target' members.
+
+	* file.h (struct file): Added `cmd_target' member.
+
+	* read.c (read_makefile): Temporarily turn off -t and -q while
+	updating makefiles.
+
+	* make.c (main): Don't use arg 0 from other_args (which is now
+	argv[0]; i.e., the program's name).
+
+	* read.c (read_makefile): Only return nonzero if commands were
+	actually run to remake the makefile.
+
+	* remake.c (update_file_1): Set FILE->updated to -1 if no commands
+	were actually run (because no update was done or -t was given).
+
+	* make.c (decode_switches): Fixed bug wherein xrealloc was passed
+	bad args if it tried to expand other_args->list.
+
+	* read.c (read_all_makefiles): Made it not look at the `MAKE'
+	variable, just use argv[0].
+
+Sun Sep 18 17:34:11 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)
+
+	* read.c (rerun_make): New function to re-exec make.
+
+	* make.c (construct_makeflags, construct_argv): New functions to
+	construct the `MAKEFLAGS' variable and to construct an arg list from
+	parsed info.
+
+	* read.c (read_makefile): New arg UPDATEIT, if nonzero, says to
+	update the makefile as a target before reading it in.  When reading
+	included makefiles, pass this as zero.  Now returns nonzero if the
+	makefile was updated, zero if not.
+	(read_all_makefiles): Pass a nonzero UPDATEIT arg to read_makefile
+	for all default and -f makefiles and all makefiles from the
+	`MAKEFILES' variable.  If any of the makefiles has changed, re-exec
+	self to re-read them.
+
+	* remake.c (update_file): Print a "File `foo' up to date'" message
+	under -p.
+
+	* commands.c (execute_file_commands): Allocate one byte for each of
+	$^ and $< rather than zero if they are to be empty.
+
+Fri Sep 16 13:59:59 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Version 3.06.
+
+	* make.c (command_switches): Fixed entry for `-o' switch.
+
+	* make.texinfo: Renamed -c switch to -C.
+
+	* make.c: Renamed -c switch to -C.
+
+	* Miscellaneous de-linting.
+
+	* read.c (record_files): Made it not free the storage for the name
+	if it started with `./' and was therefore not quite the same as in
+	the `struct file'.
+
+	* read.c (record_files): If commands were specified twice, the error
+	message specifies in what files and at what line numbers.
+
+	* make.c (main): If any of the signals we usually fatal on were
+	ignored by the parent (probably a shell), ignore them.
+
+	* make.c (main): Print version info for -v, -p, or -d.
+	(print_data_base): Don't print version info.  It will be done in main.
+
+	* variable.c: Increased number of hash buckets to 257.
+
+	* file.c: Increased number of hash buckets to 1007.
+
+	* rule.c (count_implicit_rule_limits): Moved comptation of
+	`maxsuffix' to convert_to_pattern, since that function uses
+	`maxsuffix', and must be called before count_implicit_rule_limits.
+
+	* rule.c (pattern_search): If an existent (non-intermediate)
+	dependendency was found via a terminal rule, set its
+	`tried_implicit' flag, so it will never have implicit rule search done.
+
+	* glob.c: Bug fix to avoid alloca(0).
+
+	* arscan.c: USG and Sun386i fixes.
+
+Thu Sep 15 19:40:26 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* make.texinfo: Fixed some typos and spelling errors.
+
+Wed Sep  7 14:20:39 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)
+
+	* make.c (decode_switches): Fixed bug wherein a bad option would
+	give a useless error message and loop forever.
+
+Tue Sep  6 14:36:02 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.texinfo: Documented `shell' function.
+
+	* variable.c (expand_function): New function `shell', does
+	backquote-style command expansion of its arg.
+
+	* commands.c (execute_command_line): Second arg OUTBUF, if not nil,
+	gets filled in with a malloc'd buffer containing the piped stdout of
+	the command.
+	(execute_file_commands): Use above (pass nil).
+
+Mon Sep  5 17:03:49 1988  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)
+
+	* Makefile: Added copyright notice.
+	Added a comment about defining `NO_MINUS_C_MINUS_O' if necessary.
+
+	* Version 3.05.
+
+	* rule.c (default_suffix_rules): Don't pass `-o' switches with `-c'
+	switches if `NO_MINUS_C_MINUS_O' is #define'd.
+
+	* make.texinfo: Documented `GNUmakefile'.
+
+	* read.c (read_all_makefiles): Made it try default makefile
+	`GNUmakefile' before others.
+
+	* make.texinfo: Added new-style Texinfo header thingies.
+
+Sat Sep  3 18:09:39 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* Version 3.04.
+
+	* make.texinfo (Chained Rules): Added a @cindex about using
+	.PRECIOUS to preserve intermediate files.
+
+	* remake.c (update_file_1): Made it not just return before executing
+	commands under -p.
+
+	* rule.c (default_pattern_rules, default_variables): Made it use
+	`$(AR)' for `ar r' (to put files in archives).
+
+	* vpath.c (build_vpath_lists): Made it recursively expand the
+	`VPATH' variable (by using variable_expand instead of lookup_variable).
+
+	* read.c (conditional_line): Made it not swallow whitespace after
+	the comma in an `ifeq' using the `(a,b)' syntax.
+
+	* rule.c (count_implicit_rule_limits): Made it not crash if a
+	pattern rule dep begins with `/'.
+
+Sun Aug 28 15:51:12 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)
+
+	* make.texinfo: Clarified that the arg to the `origin' function is a
+	variable *name*, not a reference.
+
+	* make.texinfo: Clarified that both -Idir and -I dir are allowed.
+
+Sat Aug 27 13:49:28 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* remake.c (remake_file): Made touching phonies work right.
+
+Wed Aug 24 20:40:48 1988  Roland McGrath  (mcgrath at nutmeg.Berkeley.EDU)
+
+	* make.texinfo: Removed reference to `RANLIB' variable.
+
+	* Version 3.03.
+
+	* variables.c (expand_function): Added `origin' function.
+	* make.texinfo: Documented same.
+
+	* read.c (record_files): Made double-colon entries work.
+
+Sat Aug 20 21:09:39 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.c (collapse_continuations): Bug fix from RMS.
+
+	* rule.c (install_default_pattern_rules): Made it set the
+	`in_use' flag of the created rules to zero, rather than letting
+	it be random garbage.
+
+	* rule.c (pattern_search): Fixed putting `also make' targets into
+	file strucutres.
+
+	* read.c (record_files): Fixed bug which made double-colon entries
+	make it read off into space.
+
+	* make.c (decode_switches): Made it understand `ignored' switches
+	rather than dumping core.
+
+Sun Aug 14 16:49:00 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* read.c (read_makefile): Made `include' filenames be
+	variable-expanded.
+
+	* read.c (read_makefile): Fixed an error message.
+
+	* read.c (read_makefile): Made it accept ^L's as whitespace.
+	* make.c (next_token, end_of_token): Ditto.
+
+	* vpath.c (vpath_search): Fixed it so that the general VPATH (from
+	the variable) is always checked, even if a selective VPATH (from a
+	directive) matched the filename.
+
+Sat Aug 13 14:20:46 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.c (decode_switches, main): Made the command switches be
+	processed from a table of switches, variables, and types.  No
+	functions are passed argc and argv any more.  They are passed arrays
+	of strings they need to process.
+	* read.c (read_all_makefiles): Made it take an array rather than
+	argc and argv.
+	(construct_include_path): Ditto.
+
+	* make.c (collapse_continuations): Made it work right (I hope).
+
+	* make.texinfo: Minor editorial changes.
+
+	* read.c (read_makefile): Minor speed improvement by freeing and
+	then mallocing something rather than reallocing it to avoid the
+	unnecessary bcopy.
+
+Thu Aug 11 00:10:43 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.texinfo: Fixed some unquoted @'s.
+
+	* make.texinfo: Documented multiple-target pattern rules.
+	Miscellaneous minor editorial changes and corrections.
+
+	* make.texinfo (Implicit: Catalogue of Rules): Removed the list of
+	variables.  That's what the next section is for.
+	(Implicit: Implicit Variables): Made it agree with reality.
+
+Wed Aug 10 00:55:39 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* variable.c (print_variable_data_base): Fixed bug which made -p
+	dump core.  (This was a really idiotic bug.)
+
+	* rule.c (pattern_search): Fixed a bug which made it make the
+	`also_make' member of the file in question nil if the first of
+	the successful rule's targets was the matching one.
+	Made it use only as much storage as necessary in the `also_make'
+	member.
+	(create_pattern): Made it use only as much storage as necessary in
+	the `lens' and `suffixes' members of the created rule.
+
+	* remake.c (library_file_mtime): Made it `static'.
+
+	* file.c: Added a declaration for `errno', which is declared in some
+	<errno.h>'s, but not all.
+
+	* file.h (struct file): Added `also_make' member for multiple-target
+	implicit rules.
+	* rule.c (pattern_search): Made it put the names of files updated by
+	the given file's commands in its `also_make' member.
+	* remake.c (update_file_1): Made it mark the files in a file's
+	`also_make' member as updated when the file is updated.
+
+	* variable.c (try_variable_definition): Fixed a bug which made it
+	define a variable with the name of the whole definition when there
+	was no space before the = or :=.
+
+	* make.texinfo (Features): Made the changes which were made in RCS
+	revision 2.7 but somehow lost since then.  Added -W.
+
+Tue Aug  9 10:04:50 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* variable.h: Added `o_default' to `enum variable_origin'.
+	* variable.c (print_variable_data_base): Made it print the origins of
+	the variables.
+	* rule.c (install_default_pattern_rules): Made it define the default
+	variables with origin `o_default'.
+
+	* make.texinfo: Documented -W.
+
+	* make.c (decode_switches, main): Added the -W flag to give files a
+	time-stamp of now, for a `what if' effect when used with -n.
+
+	* commands.c (print_commands): Made it say `(built-in)' for commands
+	that are built into the default ruleset.
+
+	* read.c (record_file): Made .SUFFIXES get its deps frontwards (again).
+	* rule.c (set_default_suffixes, convert_to_pattern): Made it read
+	.SUFFIXES's deps frontwards, so the converted rules will not be in
+	reverse order.
+
+	* rule.c (new_pattern_rule): Fixed a bug wherein it would keep
+	searching after it had removed a matching rule and ended up diddling
+	with freed storage.
+
+	* rule.c (freerule): Made it take the given rule off the chain.
+	(new_pattern_rule, count_implicit_rule_limits): Use freerule to
+	remove rules from the chain.
+
+	* vpath.c (construct_vpath_list): Made it return after cleaning out
+	all previous searchpaths when given a nil DIRPATH arg, so it won't
+	go into the construction code and dump core dereferencing a nil
+	pointer.
+
+	* variable.c (patsubst_expand): Fixed a bug which made it not match
+	correctly and sometimes dump core.
+
+Mon Aug  8 16:35:48 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* rule.c (default_suffix_rules): Made the .texinfo.dvi rule remove
+	the files used in the comparison to determine whether or not a
+	second TeX run is necessary.
+
+	* make.texinfo: Fixed some overfull TeX hboxes.
+
+	* make.texinfo (Implicit: Catalogue of Rules): Fixed a Texinfo error.
+
+	* rule.c (create_pattern_rule): Fixed bug wherein index was not
+	being passed its second arg.
+
+	* read.c (getline): Merged back into readline.
+
+	* rule.c (default_suffixes, default_suffix_rules,
+	default_variables): Added .texinfo.info rule.
+	* make.texinfo (Implicit: Catalogue of Rules): Documented
+	.texinfo.dvi and .texinfo.info rules.
+
+	* make.texinfo (Top): Changed `last updated' date to be correct (for
+	the last time it was updated, not today).  Changed `for version
+	3.00' since it's not going to be called that.
+
+Sat Aug  6 19:51:10 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* commands.c (print_commands): Added this function to print the
+	contents of a `struct commands' for -p.
+	* rule.c (print_rule_data_base): Use above.
+	* file.c (print_file_data_base): Ditto.
+
+	* rule.c (count_implicit_rule_limits, new_pattern_rule,
+	install_pattern_rule, print_rule_data_base): Made it understand the
+	changed `struct rule' and act accordingly.
+	(freerule): Added this function to free all the storage used by a rule.
+
+	* rule.c (pattern_search): Made it grok multiple targets of pattern
+	rules.  The matching is done properly, but at present, only the
+	matching pattern's target is used to give deps and commands.
+
+Fri Aug  5 18:00:29 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* rule.c (struct rule): Changed name, namelen, and patsuffix members
+	to targets, lens, and suffixes, which are arrays, for multiple targets.
+	(create_pattern_rule): Now takes first arg TARGETS, a nil-terminated
+	array of targets, rather than a single target and patsuffix pointer.
+
+	* read.c (record_files): If it finds an implicit pattern rule, it
+	collects all the targets into an array and passes the whole thing to
+	create_pattern_rule.  If there are non-pattern targets, it is a
+	fatal error.
+
+Tue Aug  2 15:06:38 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.c (readline): Split backslash-newline checking from reading
+	and buffer-expanding.
+	(getline): Created to do the reading and buffer-expanding formerly
+	done in readline.
+
+	* rule.c (pattern_search): Made it reject nonterminal match-anything
+	rules when a specific rule has matched, rather than rejecting
+	terminal match-anything rules in this case.
+
+	* rule.c (convert_to_pattern): Fixed a bug caused when the change to
+	make it only recognize two-suffix rules whose target suffixes
+	precede their dependency suffixes which made it work in the opposite
+	direction (even worse than it started out).
+
+	* rule.c (pattern_search): Made it reject nonterminal match-anything
+	rules as intermediate targets when searching for both real and
+	intermediate dependencies, rather than only when searching for
+	intermediate ones.
+
+Sun Jul 31 00:33:56 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* rule.c (convert_to_pattern): Made it only recognize two-suffix
+	rules whose target suffix comes before the dependency suffix in the
+	.SUFFIXES list.
+
+	* variable.c (define_automatic_variables): Made all automatic
+	variables be defined with origin `o_automatic'.
+
+	* variable.h: Added `o_automatic' to `enum variable_origin'
+
+	* file.c (remove_intermediates): Made it not print an error message
+	if the error was that the file does not exist.
+
+	* rule.c: Removed `recursive' member from `struct rule'.
+
+	* remake.c (library_file_mtime): Made it not use the directory hash
+	functions, as reading in and hashing /usr/lib and /lib is slow and
+	most likely unnecessary.
+
+	* remake.c (remake_file): Changed message from ``No specification
+	for making'' to ``No way to make'' so it will be short enough that
+	most filenames will fit on a line.
+	Made it look at the `recursive' member of the `struct commands',
+	rather than of the `struct file' (which no longer has one).
+
+	* commands.c (execute_file_commands): Made it look at the
+	`recursive' member of the `struct commands', rather than of the
+	`struct file' (which no longer has one).
+
+	* file.h: Removed `recursive' member from `struct file'.
+
+	* commands.h: Added `recursive' member to `struct commands'.
+
+	* dep.h: Removed unused `quotedparen' member from `struct nameseq'
+	and `struct dep'.
+
+	* read.c (dequote): Removed this function.
+	(multi_glob): Removed reference to `quotedparen' member of
+	a `struct nameseq' and calls to dequote.
+
+	* read.c (record_files): Made it set the stem for $* for all static
+	pattern rules, not just those with commands given at that time.
+	Removed check for recursive commands.
+	Made it check for pairs of .SUFFIXES dependencies to reject as
+	default goals as well as single ones (that don't start with dots).
+	(read_makefile): Added checks for recursive commands to set
+	the `recursive' flag in the `struct commands'.
+
+Sat Jul 30 15:47:23 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.c (find_next_token): Made the LENGTHPTR arg optionally nil.
+
+	* make.c: Removed `files_made' variable which is defined static in
+	remake.c and used only there.
+	(main): Cleaned up somewhat.
+	(decode_switches): Cleaned up a bit.  Made an unknown option be a
+	non-fatal error.
+	(decode_env_switches): Made LEN arg unsigned.  Cleaned up.
+	(print_version): Made it say ``see the source'' rather than ``see
+	the source file'', since there is more than one.
+
+	* file.h: Made `num_intermediates' declared unsigned.
+
+	* file.c: Made `num_intermediates' variable unsigned.
+	(remove_intermediates): Removed unused FORMAT arg.
+	(enter_file): Made it handle double-colon files properly, adding the
+	new entry as the old entry's prev pointer.
+
+	* dir.c: Re-indented the `struct dir' definition to be right.
+	(dir_load): Cleaned up slighty.
+	(file_exists_p): Removed comment saying we could use `access', since
+	that is a bad idea (except for setuid programs).  Cleaned up slightly.
+
+	* commands.c: Changed some comments slightly.
+	(execute_file_commands): Cleaned up a bit.  Changed some comments,
+	added others.  Moved freeing of storage for $^ and $? to the same
+	place as for the other automatic variables.
+	(execute_command_line): Made `#' trigger a shell.
+	Added some comments.  Cleaned up a bit.  Put all the special chars
+	that trigger shells into an array easily changeable at the top.
+
+	* ar.c: Added comments explaining each function.
+	(ar_scan_1): Merged into ar_member_date.
+	(ar_member_date): Changed call to ar_scan_1 to the body of that
+	function.
+	(ar_member_date_1): Simplified to a ?: expression rather than an
+	if-else statement.
+	(ar_member_touch): Changed error handling around a bit.
+	None of these errors are fatal now.
+
+	* variable.c (subst_expand): Added a new arg BY_WORD, to do substs
+	only on full words.
+	(patsubst_expand): Fixed bug which made calls whose patterns
+	contained no `%' to not work correctly, by using above.
+	(variable_expand): Pass extra arg to `subst_expand'.
+
+	* variable.c (expand_function): Fixed bug which made `foreach' calls
+	with one-word lists run off into never-never land.
+
+Fri Jul 29 20:12:36 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* variable.c (expand_function): Made a very minor speed improvement
+	by avoiding an unnecessary strlen call.
+
+Wed Jul 27 16:01:47 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* rule.c (default_suffixes): Rearranged the list somewhat; added
+	`.el' and `.elc' to speed things up (especially when building
+	Emacs), for the same reason `.h' is there.
+
+	* read.c (record_files): Changed `lineno' from `long' to
+	`unsigned int'.
+
+Sun Jul 24 02:15:30 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* variable.c (expand_function): Eliminated use of `wstok'
+	because it is non-reentrant and unreliable.
+	Fixed a minor bug which would cause something not to be freed.
+	* make.c (wstok): Removed `wstok' because it is no longer used.
+
+	* variable.c (expand_function): Made `foreach' function put
+	spaces between output texts like it's supposed to.
+
+Sat Jul 23 17:32:55 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* rule.c (default_suffixes, default_suffix_rules): Added rule
+	to make %.dvi from %.texinfo.
+
+	* dir.c (print_dir_data_base): Made it say a bit more.
+
+Fri Jul 22 23:13:16 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* make.c (print_data_base): Split this function up into one
+	for each thing.
+	* variable.c (print_variable_data_base): One of the above.
+	* rule.c (print_rule_data_base): Ditto.
+	* file.c (print_file_data_base): Ditto.
+	* dir.c (print_dir_data_base): Ditto.
+
+	* rule.c (install_pattern_rule): Fixed a bug which caused the
+	terminal and recursive flags to always be zero for rules
+	entered by this function.
+
+	* make.texinfo (Rules: Double-colon): Added a paragraph
+	explaining the purpose of double-colon rules.
+
+	* make.texinfo (Implicit: Catalogue of Rules): Updated to
+	reflect new C++, TeX, Web, and Texinfo rules.  Other slight
+	editorial changes.
+
+	* commands.c (execute_file_commands): Fixed a bug wherein
+	random memory could get written for files with no deps.
+
+Wed Jul 20 19:30:31 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* read.c (readline): Fix bug wherein it would not recognize a
+	backslash-newline if the buffer filled up and was enlarged
+	right before reading the newline.
+
+Tue Jul 19 19:55:02 1988  Roland McGrath  (mcgrath at chilli.Berkeley.EDU)
+
+	* read.c: Added default suffix rules for .cc (using $(C++),
+	which defaults to `g++', and $(C++FLAGS)), .tex, .dvi, .web
+	and .cweb (using $(TEX), $(WEAVE), $(TANGLE), $(CWEAVE) and
+	$(CTANGLE)).
+
+Sat Jul 16 21:24:28 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Made error formats use %u rather than %ld for line numbers,
+	which are now unsigned int's rather than long's.
+
+	* read.c (conditional_line): Fixed some bugs caused by use of
+	unsigned int rather than int in one place.
+
+	* read.c (conditional_line): Put the info about active
+	conditionals in a struct.
+	(read_makefile): Make a new struct of info about conditionals
+	for included makefiles and restore the old one after the
+	included makefile has been read.
+
+	* read.c (read_makefile): Don't try to read a makefile with
+	name "" after giving an error message because an `include'
+	directive gave no filename.
+
+	* read.c (read_makefile): Give an error message for
+	non-whitespace text after the filename in an `include' directive.
+
+	* make.c (error): Take five args, like `fatal'.  It managed to
+	lose with only two.  Is there a better way to do this without vfprintf?
+
+	* read.c (read_makefile): Commands consisting of only
+	whitespace are not the same as no commands.  I thought I'd
+	fixed this bug months ago; it seems to have come back.
+
+	* make.c (collapse_continuations): All whitespace around a
+	backslash-newline combination is turned into a single space.
+
+	* Added COPYING file and copyright notices to all files.
+
+	* make.texinfo (Running: Goals): Fix a typo.
+
+	* read.c (do_define): Take an arg for the origin of the
+	variable being defined.
+	(read_makefile): Grok `override define'.
+
+	* make.texinfo (Variables: Override Directive, Defining):
+	Document the `override define' combination directive.
+
+	* ar.c (ar_member_date): Make a 0 return from `ar_scan' return
+	(time_t) -1 (nonexistent file), rather than (time_t) 0, which,
+	when put in the `struct file', makes `file_mtime' try to get
+	the mtime over and over again.
+
+	* variable.c (pattern_matches): Fix a bug that made patterns
+	not beginning with `%' never match.
+
+Fri Jul 15 21:01:44 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)
+
+	* Took Make out of RCS.
+
+	* Split the monolithic `make.c' into several smaller files.
+
+
+
+
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/ChangeLog.2
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/ChangeLog.2	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/ChangeLog.2	(revision 1780)
@@ -0,0 +1,6655 @@
+2000-06-22  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (start_job_command): Increment commands_started before the
+	special check for ":" (empty command) to avoid spurious "is up to
+	date" messages.  Also move the test for question_flag after we
+	expand arguments, and only stop if the expansion provided an
+	actual command to run, not just whitespace.  This fixes PR/1780.
+
+2000-06-21  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): If we find a semicolon in the target
+	definition, remember where it was.  If the line turns out to be a
+	target-specific variable, add back the semicolon and everything
+	after it.  Fixes PR/1709.
+
+2000-06-19  Paul D. Smith  <psmith@gnu.org>
+
+	* config.h-vms.template: #define uintmax_t for this system.
+	* config.ami.template: Ditto.
+	* config.h.W32.template: Ditto.
+
+	* configure.in: We don't use select(2) anymore, so don't bother
+	checking for it.
+	* acconfig.h: Ditto.
+	* acinclude.m4: Ditto.
+
+	* file.c (all_secondary): New static global; if 1 it means
+	.SECONDARY with no prerequisites was seen in the makefile.
+	(snap_deps): Set it appropriately.
+	(remove_intermediates): Check it.
+	(num_intermediates): Remove this global, it's not used anywhere.
+	(considered): Move this to remake.c and make it static.
+
+	* NEWS: Document the change to .SECONDARY.
+	* make.texinfo (Special Targets): Document the change to .SECONDARY.
+
+	* implicit.c (pattern_search): Remove the increment of
+	num_intermediates; it's not used.
+	* filedef.h: Remove num_intermediates and considered.
+
+	* function.c (handle_function): If the last argument was empty, we
+	were pretending it didn't exist rather than providing an empty
+	value.  Keep looking until we're past the end, not just at the end.
+
+	* implicit.c (pattern_search): Multi-target implicit rules weren't
+	expanding the "also made" targets correctly if the pattern didn't
+	contain a slash but the target did; in that case the directory
+	part wasn't being added back to the stem on the "also made"
+	targets.  Reported by Seth M LaForge <sethml@newtonlabs.com>, with
+	a patch.
+
+2000-06-17  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* Makefile.DOS.template (DESTDIR, bindir, datadir, libdir)
+	(infodir, mandir, includedir): Support installation under a
+	non-default DESTDIR.
+
+	* remake.c (f_mtime): Fix the spelling of __MSDOS__.
+
+	* configh.DOS.template (HAVE_FDOPEN, HAVE_MKSTEMP): Define.
+
+2000-06-14  Paul D. Smith  <psmith@gnu.org>
+
+	* acinclude.m4 (pds_WITH_GETTEXT): rewrite fp_WITH_GETTEXT and
+	rename it to avoid confusion.  This version is very specific: it
+	won't accept any gettext that isn't GNU.  If the user doesn't
+	explicitly ask for the included gettext, we look to see if the
+	system gettext is GNU (testing both the actual libintl library,
+	and the libintl.h header file).  Only if the system gettext is
+	really GNU gettext will we allow it to be used.
+	(pds_CHECK_SYSTEM_GETTEXT): A helper function.
+
+2000-06-13  Paul D. Smith  <psmith@gnu.org>
+
+	* gettext.h: If we have libintl.h, use that instead of any of the
+	contents of gettext.h.  We won't check for libintl.h unless we're
+	using the system gettext.
+
+	* function.c (func_word): Clarify error message.
+
+2000-06-10  Paul Eggert  <eggert@twinsun.com>
+
+	Support nanosecond resolution on hosts with 64-bit time_t and
+	uintmax_t (e.g. 64-bit Sparc Solaris), by splitting
+	FILE_TIMESTAMP into a 30-bit part for nanoseconds, with the
+	rest for seconds, if FILE_TIMESTAMP is at least 64 bits wide.
+
+	* make.h: Always define FILE_TIMESTAMP to be uintmax_t, for
+	simplicity.
+
+	* filedef.h (FILE_TIMESTAMP_HI_RES, FILE_TIMESTAMP_LO_BITS)
+	(UNKNOWN_MTIME, NONEXISTENT_MTIME, OLD_MTIME)
+	(ORDINARY_MTIME_MIN, ORDINARY_MTIME_MAX): New macros.
+	(FILE_TIMESTAMP_STAT_MODTIME): Now takes fname arg.  All uses changed.
+	(FILE_TIMESTAMP_DIV, FILE_TIMESTAMP_MOD)
+	(FILE_TIMESTAMP_FROM_S_AND_NS): Remove.
+	(FILE_TIMESTAMP_S, FILE_TIMESTAMP_NS): Use shifts instead of
+	multiplication and division.  Offset the timestamps by
+	ORDINARY_MTIME_MIN.
+	(file_timestamp_cons): New decl.
+	(NEW_MTIME): Now just the maximal timestamp value, as we no longer use
+	-1 to refer to nonexistent files.
+
+	* file.c (snap_deps, print_file): Use NONEXISTENT_MTIME,
+	UNKNOWN_MTIME, and OLD_MTIME instead of magic constants.
+	* filedef.h (file_mtime_1): Likewise.
+	* main.c (main): Likewise.
+	* remake.c (update_file_1, notice_finished_file, check_dep)
+	(f_mtime, name_mtime, library_search): Likewise.
+	* vpath.c (selective_vpath_search): Likewise.
+
+	* remake.c (f_mtime): Do not assume that (time_t) -1 equals
+	NONEXISTENT_MTIME.  When futzing with time stamps, adjust by
+	multiples of 2**30, not 10**9.  Do not calculate timestamp
+	adjustments on DOS unless they are needed.
+
+	* commands.c (delete_target): Do not assume that
+	FILE_TIMESTAMP_S yields -1 for a nonexistent file, as that is
+	no longer true with the new representation.
+
+	* file.c (file_timestamp_cons): New function, replacing
+	FILE_TIMESTAMP_FROM_S_AND_NS.  All uses changed.
+	(file_timestamp_now): Use FILE_TIMESTAMP_HI_RES instead of 1 <
+	FILE_TIMESTAMPS_PER_S to determine whether we're using hi-res
+	timestamps.
+	(print_file): Print OLD_MTIME values as "very old" instead of
+	as a timestamp.
+
+2000-05-31  Paul Eggert  <eggert@twinsun.com>
+
+	* remake.c (name_mtime): Check for stat failures.  Retry if EINTR.
+
+2000-05-24  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (decode_switches): The "positive_int" switch uses atoi()
+	which succeeds for any input, and doesn't notice if extra,
+	non-digit text is after the number.  This causes make to mis-parse
+	command lines like "make -j 5foo" as "make -j5" (ignoring "foo"
+	completely) instead of "make -j0 5foo" (where "5foo" is a
+	target).  Fix this by checking the value by hand.  We could use
+	strtol() if we were sure of having it; this is the only
+	questionable use of atoi() I found so we'll just stick with that.
+	Fixes PR/1716.
+
+	* i18n/ja.po, i18n/nl.po, i18n/pt_BR.po: New translation files.
+	* configure.in (ALL_LINGUAS): Added pt_BR.
+
+2000-05-22  Paul Eggert  <eggert@twinsun.com>
+
+	* remake.c (f_mtime): Fix bug when handling future odd
+	timestamps in the WINDOWS32 case.  Do not bother initializing
+	static var to zero.  Simplify code that works around WINDOWS32
+	and __MSDOS__ time skew brain damage.
+
+2000-05-22  Paul Eggert  <eggert@twinsun.com>
+
+	* job.c: Don't include time.h, as make.h already does this.
+
+2000-05-22  Paul Eggert  <eggert@twinsun.com>
+
+	* configure.in (AC_CHECK_HEADERS): Add sys/time.h.
+	(AC_HEADER_TIME): Add.
+	(clock_gettime): Prefer -lrt to -lposix4, for Solaris 7.
+	(gettimeofday): Add check for standard version of gettimeofday.
+	This merges changes written by Paul D. Smith.
+
+	* file.c (file_timestamp_now):  Use gettimeofday if available
+	and if clock_gettime does not work.  Don't bother with
+	high-resolution clocks if file timestamps have only one-second
+	resolution.
+
+	* make.h <sys/time.h>: Include, conditionally on the usual
+	TIME_WITH_SYS_TIME and HAVE_SYS_TIME_H macros.  This is needed
+	for gettimeofday.
+
+2000-05-20  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): We weren't keeping makefile names around
+	unless there was a rule defined in them; but now we need to keep
+	them for variables as well.  Forget trying to be fancy: just keep
+	every makefile name we successfully open.
+
+	* remote-cstms.c (start_remote_job_p): Change DB_EXTRA (?) to DB_JOBS.
+
+2000-05-17  Paul Eggert  <eggert@twinsun.com>
+
+	* commands.c (chop_commands): Ensure ctype macro args are nonnegative.
+	* expand.c (variable_expand_string): Likewise.
+	* function.c (subst_expand, lookup_function, msdos_openpipe):
+	Likewise.
+	* job.c (vms_redirect, start_job_command, new_job, child_execute_job,
+	construct_command_argv_internal, construct_command_argv): Likewise.
+	* main.c (decode_env_switches, quote_for_env): Likewise.
+	* misc.c (collapse_continuations, end_of_token, end_of_token_w32,
+	next_token): Likewise.
+	* read.c (read_makefile, do_define, conditional_line,
+	find_char_unquote,get_next_mword): Likewise.
+	* variable.c (try_variable_definition): Likewise.
+	* vpath.c (construct_vpath_list): Likewise.
+	* w32/pathstuff.c (convert_vpath_to_windows32): Likewise.
+
+2000-05-10  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* main.c (main) [__MSDOS__]: Add SIGFPE to signals we block when
+	running child programs, to prevent Make from dying on Windows 9X
+	when the child triggers an FP exception.
+
+2000-05-08  Paul D. Smith  <psmith@gnu.org>
+
+	* dir.c (find_directory) [WINDOWS32]: If we strip a trailing "\"
+	from the directory name, remember to add it back.  The argument
+	might really be inside a longer string (e.g. %Path%) and if you
+	don't restore the "\" it'll be truncated permanently.  Fixes PR/1722.
+	Reported by <steven@surfcast.com>
+
+2000-05-02  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (construct_command_argv_internal) [WINDOWS32]: Added "rd"
+	and "rmdir" to the list of command.com commands.
+	Reported by Elod Horvath <Elod_Horvath@lnotes5.bankofny.com>
+
+2000-04-24  Paul D. Smith  <psmith@gnu.org>
+
+	* i18n/ja.po: New translation file from the Japanese language team.
+
+2000-04-18  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (f_mtime): If ar_member_date() returns -1 (the member
+	doesn't exist), then return (FILE_TIMESTAMP)-1 rather than
+	returning the timestamp calculated from the value -1.  Fixes PR/1696.
+	Reported by Gilles Bourhis <Gilles.Bourhis@univ-rennes1.fr>.
+
+2000-04-17  Paul D. Smith  <psmith@gnu.org>
+
+	* config.h.W32.template: Add LOCALEDIR macro resolving to "".
+	* w32/subproc/sub_proc.c (process_begin): Remove reference to
+	debug_flag; change it to a DB() call.  Fixes PR/1700.
+	Reported by Jim Smith <jwksmith@attglobal.net>
+
+2000-04-17  Bruno Haible  <haible@clisp.cons.org>
+
+	* arscan.c [BeOS]: Add replacement for nonexistent <ar.h> from GNU
+	binutils.
+
+2000-04-11  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (expand_builtin_function): If no arguments were
+	provided, just quit early rather than changing each function to
+	test for this.
+	(function_table[]): Change the min # of arguments to 0 for all
+	those functions for which it makes sense (currently everything
+	that used to take a minimum of 1 argument, except $(call ...)).
+	Fixes PR/1689.
+
+2000-04-09  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* README.DOS: Add instructions to install a binary distro.
+	Mention latest versions of Windows.
+
+2000-04-07  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* main.c (main): Rename TMP_TEMPLATE into DEFAULT_TMPDIR, and use
+	it for the directory of the temporary file.  If P_tmpdir is
+	defined, use it in preference to "/tmp/".  Try $TMPDIR, $TEMP, and
+	$TMP in the environment before defaulting to DEFAULT_TMPDIR.
+	(print_version): Add year 2000 to the Copyright line.
+
+2000-04-04  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.79 released.
+
+	* make.texinfo: Update documentation with new features for 3.79.
+
+	* function.c (func_wordlist): Don't re-order arguments to
+	wordlist.
+
+2000-04-03  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (f_mtime): Archive member timestamps are stored as
+	time_t, without nanoseconds.  But, f_mtime() wants to return
+	nanosecond info on those systems that support it.  So, convert the
+	return value of ar_member_date() into a FILE_TIMESTAMP, using 0 as
+	the nanoseconds.
+
+2000-03-28  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.78.92 released.
+
+	* build.template: Updates for gettext support; some bugs fixed.
+
+2000-03-27  Paul D. Smith  <psmith@gnu.org>
+
+	* config.guess, config.sub: Updated from config CVS archive at
+	:pserver:anoncvs@subversions.gnu.org:/home/cvs as of today.
+
+	* read.c (record_files): Check if expanding a static pattern
+	rule's prerequisite pattern leaves an empty string as the
+	prerequisite, and issue an error if so.  Fixes PR/1670.
+	(read_makefile): Store the starting linenumber for a rule in
+	TGTS_STARTED.
+	(record_waiting_files): Use the TGTS_STARTED value for the file
+	location passed to record_file() instead of the current
+	linenumber, so error messages list the line where the target was
+	defined instead of the line after the end of the rule definition.
+
+	* remake.c (start_updating, finish_updating, is_updating): Fix
+	PR/1671; circular dependencies in double-colon rules are not
+	diagnosed.  These macros set the updating flag in the root
+	double-colon file instead of the current one, if it's part of a
+	double-colon list.  This solution provided by Tim Magill
+	<magill@gate.net>; I just changed the macro names :).
+	(update_file_1): Call them.
+	(check_dep): Call them.
+
+	The change to not automatically evaluate the $(call ...)
+	function's arguments breaks recursive use of call.  Although using
+	$(if ...) and $(foreach ...) in $(call ...) macros is important,
+	the error conditions generated are simply to obscure for me to
+	feel comfortable with.  If a method is devised to get both
+	working, we'll revisit.  For now, remove this change.
+
+	* function.c (function_table): Turn on the expand bit for func_call.
+	(func_call): Don't expand arguments for builtin functions; that
+	will have already been done.
+
+2000-03-26  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (remove_intermediates): Never remove targets explicitly
+	requested on the command-line by checking the cmd_target flag.
+	Fixed PR/1669.
+
+2000-03-23  Paul Eggert  <eggert@twinsun.com>
+
+	* filedef.h (FILE_TIMESTAMP_STAT_MODTIME): Use st_mtime instead of
+	st_mtim.tv_sec; the latter doesn't work on Unixware.
+
+2000-03-18  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (file_hash_enter): If we're trying to change a file into
+	itself, just return.  We used to assert this wasn't true, but
+	someone came up with a weird case involving archives.  After
+	playing with it for a while I decided it was OK to ignore it.
+
+	* default.c: Define COFLAGS to empty to avoid spurious warnings.
+
+	* filedef.h: Change #if ST_MTIM_NSEC to #ifdef; this is a macro
+	containing the name of the nsec field, not true/false.
+	* make.h: Ditto.
+	Reported by Marco Franzen <Marco.Franzen@Thyron.com>.
+
+2000-03-08  Tim Magill  <magill@gate.net>
+
+	* remake.c (update_file): Return the exit status of the pruned
+	file when pruning, not just 0.  Fixes PR/1634.
+
+2000-02-24  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Close a minor potential security hole; if you're
+	reading makefiles from stdin (who does that?) you could run into a
+	race condition with the temp file using mktemp() or tmpnam().  Add
+	a check for mkstemp() and fdopen().
+	* main.c (open_tmpfile): New function to open a temporary file.
+	If we have mkstemp() (and fdopen()), use that.  If not use
+	mktemp() or tmpnam().  If we have fdopen(), use open() to open the
+	file O_CREAT|O_EXCL.  If not, fall back to normal fopen() (insecure).
+	(main): Call it.
+	* job.c (child_execute_job) [VMS]: Call it.
+
+	* variable.c (lookup_variable): If we find a variable which is
+	being expanded, then note it but keep looking through the rest of
+	the set list to see if we can find one that isn't.  If we do,
+	return that.  If we don't, return the original.  Fix for PR/1610.
+
+	While implementing this I realized that it also solves PR/1380 in
+	a much more elegant way.  I don't know what I was smoking before.
+	So, remove the hackage surrounding the original fix for that (see
+	below).  Change this function back to lookup_variable and remove
+	the extra setlist argument.
+	* variable.h (recursively_expand_setlist): Remove the macro,
+	rename the prototype, and remove the extra setlist argument.
+	(lookup_variable): Ditto.
+	* expand.c (recursively_expand): Rename and remove the extra
+	setlist argument.
+	(reference_variable): Use lookup_variable() again.
+	(allocated_variable_append): Remove the extra setlist argument.
+
+2000-02-21  Paul D. Smith  <psmith@gnu.org>
+
+	* README.template: A few updates.
+
+	* i18n/de.po: New version from the German translation team.
+
+2000-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.78.91 released.
+
+2000-02-07  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): Reset *p2 to ':', not *colonp.  If any
+	filenames contained backslashes the resulting output (without
+	backslashes) will be shorter, so setting *colonp doesn't change
+	the right character.  Fix for PR/1586.
+
+	For += target-specific variables we need to remember which
+	variable set we found the variable in, so we can start looking
+	from there in the next iteration (otherwise we might see it again
+	in recursively_expand and fail!).  This is turning into a hack; if
+	it gets any worse we'll have to rethink this entire algorithm...
+	implementing expansion of these references separately from the
+	"normal" expansion, say, instead of using the same codepath.
+	Actually, it's already "worse enough" :-/.
+	Fix for PR/1380.
+
+	* variable.h (recursively_expand_setlist): Rename
+	recursively_expand to add a struct variable_set_list argument, and
+	make a macro for recursively_expand.
+	(lookup_variable_setlist): Rename lookup_variable to add a struct
+	variable_set_list argument, and make a macro for lookup_variable.
+
+	* expand.c (recursively_expand_setlist): Take an extra struct
+	variable_set_list argument and pass it to allocated_variable_append().
+	(reference_variable): Use lookup_variable_setlist() and pass the
+	returned variable_set_list to recursively_expand_setlist.
+	(allocated_variable_append): Take an extra setlist argument and
+	use this as the starting place when searching for the appended
+	expansion.  If it's null, use current_variable_set_list as before.
+
+	* variable.c (lookup_variable_setlist): If the LISTP argument is
+	not nil, set it to the list containing the variable we found.
+
+2000-02-04  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (print_variable): Write out filename/linenumber
+	information for the variable definition if present.
+	(define_variable_in_set): Store filename information if provided.
+	(define_variable, define_variable_for_file): Removed.
+	(try_variable_definition): Use define_variable_loc() to keep
+	variable definition location information.
+	* read.c (read_makefile): Keep variable definition location info.
+	(do_define): Ditto.
+	(record_target_var): Ditto.
+	* variable.h (define_variable_in_set): New fileinfo argument.
+	(define_variable, define_variable_loc, define_variable_for_file):
+	Declare new macros.
+
+	Fix PR/1407:
+
+	* filedef.h (struct file): Rename patvar to pat_variables and make
+	it just a variable_set_list; we need our own copy of the pattern
+	variable's variable set list here to avoid overwriting the global
+	one.
+	* variable.c (initialize_file_variables): Move the instantiation
+	of the pat_variables pointer here.  Only do the search after we're
+	done reading the makefiles so we don't search too early.  If
+	there's a pat_variables value, set up the variables next ptr.
+	* expand.c (variable_expand_for_file): Remove the setup of the
+	pat_variables info; it's done earlier now to ensure the parent's
+	pattern variables are set up correctly as well.
+
+2000-02-03  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (sh_chars_dos) [WINDOWS32]: Add "&" as a shell
+	metacharacter for the W32 DOS shell.
+	Reported by Warren Jones <wjones@tc.fluke.com>.
+
+2000-02-02  Paul D. Smith  <psmith@gnu.org>
+
+	Fixes for the OpenVMS port from Hartmut Becker <becker@rto.dec.com>
+
+	* config.h-vms [VMS]: Define LOCALEDIR to something; needed for
+	the expansion of bindtextdomain() even though it's a no-op.
+	* vmsfunctions.c (strcmpi): Remove duplicate definition of strcmpi().
+	(readdir): Use DB() instead of testing debug_flag.
+	* dir.c (file_impossible) [VMS]: Search "p" not "name".
+	* job.c [VMS]: Switch from debug_flag to the new DB macro.  Add
+	some i18n _() macros (even though VMS doesn't yet support it).
+
+	* function.c (patsubst_expand): Change "len" to not be unsigned to
+	avoid type mismatches.
+
+	* main.c (main): Declare signame_init() if we're going to call it.
+
+2000-01-29  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* Makefile.DOS.template: Track changes in Makefile.in
+	(install-recursive, uninstall-recursive): Add missing targets.
+	(DESTDIR): Define.
+	(install-binPROGRAMS, uninstall-binPROGRAMS): Use $(DESTDIR).
+
+	* default.c (default_variables) [__MSDOS__]: Define CXX to gpp.
+
+2000-01-27  Paul D. Smith  <psmith@gnu.org>
+
+	* gettext.c: Some warning cleanups, and a fix for systems which
+	don't define HAVE_ALLOCA (the workaround code was included
+	twice).
+
+2000-01-26  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.78.90 released.
+
+2000-01-25  Paul D. Smith  <psmith@gnu.org>
+
+	Change gettext support to use the simplified version in libit 0.7.
+
+	* getopt.c, make.h: Use gettext.h instead of libintl.h.
+	* ABOUT-NLS, gettext.h, gettext.c: New files from libit 0.7.
+	Modified to remove some static declarations which aren't defined.
+	* acconfig.h: Use new gettext #defines.
+	* acinclude.m4: Add fp_WITH_GETTEXT; remove AM_GNU_GETTEXT.
+	* configure.in: Call fp_WITH_GETTEXT instead.
+	* Makefile.am: New gettext stuff.  Also force inclusion of glob
+	files for systems which have LIBC glob.
+
+	* i18n/Makefile.am, i18n/.cvsignore: New dir for translation files.
+	* i18n/de.po, i18n/es.po, i18n/fr.po, i18n/ko.po, i18n/nl.po:
+	* i18n/pl.po, i18n/ru.po: Import translations already done for
+	earlier versions of GNU make.  Thanks for that work!!
+
+	* po/Makefile.in.in, po/POTFILES.in: Removed.
+
+2000-01-23  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (decode_debug_flags): If debug_flag is set, enable all
+	debugging levels.
+	(debug_flag): Resurrect this flag variable.
+	(switches): Make -d give the old behavior of turning on all
+	debugging.  Change --debug alone to emit basic debugging and take
+	optional arguments to expand debugging.
+	* NEWS: Document the new debugging options.
+
+	* remake.c (no_rule_error): Remove this function.  This tries to
+	fix a real problem--see the description with the introduction of
+	this function below.  However, the cure is worse than the disease
+	and this approach won't work.
+	(remake_file): Put the code from no_rule_error back here.
+	(update_file_1): Remove call to no_rule_error.
+
+	* filedef.h (struct file): Remove mfile_status field.
+
+2000-01-22  Paul D. Smith  <psmith@gnu.org>
+
+	Integrate GNU gettext support.
+
+	* configure.in: Add AM_GNU_GETTEXT.
+	* Makefile.am: Add options for setting LOCALEDIR, -Iintl, etc.
+	* acinclude.m4: Add gettext autoconf macros.
+	* acconfig.h: Add new gettext #defines.
+	* make.h: Include libintl.h.  Make sure _() and N_() macros are
+	declared.  Make gettext() an empty macro is NLS is disabled.
+	* main.c (struct command_switch switches[]): Can't initialize
+	static data with _() (gettext calls), so use N_() there then use
+	gettext() directly when printing the strings.
+	* remake.c (no_rule_error): The string constants can't be static
+	when initializing _() macros.
+	* file.c (print_file): Reformat a few strings to work better for
+	translation.
+	* po/POTFILES.in, po/Makefile.in.in: New files.  Take
+	Makefile.in.in from the latest GNU tar distribution, as that
+	version works better than the one that comes with gettext.
+	* NEWS: Mention i18n ability.
+
+2000-01-21  Paul D. Smith  <psmith@gnu.org>
+
+	Installed patches for the VMS port.
+	Patches provided by: Hartmut Becker <Hartmut.Becker@compaq.com>
+
+	* readme.vms, arscan.c, config.h-vms, default.c, dir.c, file.c:
+	* implicit.c, job.c, make.h, makefile.com, makefile.vms, rule.c:
+	* variable.c, vmsdir.h, vmsfunctions.c, vmsify.c, glob/glob.c:
+	* glob/glob.h: Installed patches.  See readme.vms for details.
+
+2000-01-14  Andreas Schwab  <schwab@suse.de>
+
+	* dir.c (read_dirstream): Initialize d_type if it exists.
+
+2000-01-11  Paul D. Smith  <psmith@gnu.org>
+
+	Resolve PR/xxxx: don't automatically evaluate the $(call ...)
+	function's arguments.  While we're here, clean up argument passing
+	protocol to always use simple nul-terminated strings, instead of
+	sometimes using offset pointers to mark the end of arguments.
+	This change also fixes PR/1517.
+	Reported by Damien GIBOU <damien.gibou@st.com>.
+
+	* function.c (struct function_table_entry): Remove the negative
+	required_args hack; put in explicit min and max # of arguments.
+	(function_table): Add in the max value.  Turn off the expand bit
+	for func_call.
+	(expand_builtin_function): Test against minimum_args instead of
+	the obsolete required_args.
+	(handle_function): Rewrite this.  We don't try to be fancy and
+	pass one style of arguments to expanded functions and another
+	style to non-expanded functions: pass pointers to nul-terminated
+	strings to all functions.
+	(func_call): Rewrite this.  If we are invoking a builtin function
+	and it's supposed to have its arguments expanded, do that (since
+	it's not done by handle_function for $(call ...) anymore).  For
+	non-builtins, just add the variables as before but mark them as
+	recursive so they'll be expanded later, as needed.
+	(func_if): All arguments are vanilla nul-terminated strings:
+	remove trickery with "argv[1]-1".
+	(func_foreach): Ditto.
+
+	* expand.c (expand_argument): If the second arg is NULL, expand
+	the entire first argument.
+
+	* job.c (new_job): Zero the child struct.  This change was just
+	made to keep some heap checking software happy, not because there
+	was an actual bug (the important memory was being cleared properly).
+
+1999-12-15  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (print_variable): Print the variable with += if the
+	append flag is set.
+
+	* implicit.c (pattern_search): Remove the extra check of the
+	implicit flag added on 8/24/1998.  This causes problems and the
+	reason for the change was better resolved by the change made to
+	check_deps() on 1998-08-26.  This fixes PR/1423.
+
+1999-12-08  Paul D. Smith  <psmith@gnu.org>
+
+	* dir.c (dir_setup_glob): On 64 bit ReliantUNIX (5.44 and above)
+	in LFS mode, stat() is actually a macro for stat64().  Assignment
+	doesn't work in that case.  So, stat is a macro, make a local
+	wrapper function to invoke it.
+	(local_stat): Wrapper function, if needed.
+	Reported by Andrej Borsenkow <Andrej.Borsenkow@mow.siemens.ru>.
+
+1999-12-02  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_file): Move the considered test outside the
+	double-colon loop, _but_ make sure we test the double_colon target
+	not the "current" target.  If we stop early because one
+	double-colon target is running, mark all the rest considered and
+	try to start their prerequisites (so they're marked considered).
+	Fix for PR/1476 suggested by Tim Magill <tim.magill@telops.gte.com>.
+
+1999-11-22  Rob Tulloh  <rob_tulloh@dev.tivoli.com>
+
+	* function.c (windows32_openpipe, func_shell): Correct Windows32
+	problem where $(shell nosuchfile) would incorrectly exit make. The
+	fix is to print the error and let make continue.
+	Reported by David Masterson <David.Masterson@kla-tencor.com>.
+
+	* w32/subproc/misc.c (arr2envblk): Memory leak fix.
+
+1999-11-21  Paul D. Smith  <psmith@gnu.org>
+
+	Rework GNU make debugging to provide different levels of output.
+
+	* NEWS: mention it.
+	* debug.h: New file.  Define various debugging levels and macros.
+	* function.c, implicit.c, job.c, main.c, misc.c, read.c, remake.c
+	* remote-cstms.c, vmsfunctions.c: Replace all code depending on
+	debug_flag with invocations of debugging macros.
+	* make.h: Remove debug_flag and DEBUGPR, add db_level.
+
+1999-11-18  Paul Eggert  <eggert@twinsun.com>
+
+	* acinclude.m4 (AC_SYS_LARGEFILE_FLAGS): Work around a problem
+	with the QNX 4.25 shell, which doesn't propagate exit status of
+	failed commands inside shell assignments.
+
+1999-11-17  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (func_if): Find the end of the arg list by testing
+	the next item for NULL; any other test is not correct.
+	Reported by Graham Reed <grahamr@algorithmics.com> (PR/1429).
+
+	Fix += when used in a target-specific variable context.
+
+	* variable.h: New bitfield APPEND set if we have a +=
+	target-specific variable.
+
+	* variable.c (try_variable_definition): Add an argument to specify
+	if we're trying a target-specific variable.  If we are and it's an
+	append style, don't append it, record it as normal recursive, but
+	set the APPEND flag so it'll be expanded later.
+	* main.c (handle_non_switch_argument): Use new
+	try_variable_definition() signature.
+	* read.c (read_makefile,record_target_var): Ditto.
+
+	* expand.c (allocated_variable_append): New function: like
+	allocated_variable_expand(), but we expand the same variable name
+	in the context of the ``next'' variable set, then we append this
+	expanded value.
+	(recursively_expand): Invoke it, if the APPEND bit is set.
+
+1999-11-10  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (snap_deps): If the .NOTPARALLEL target is defined, turn
+	off parallel builds for this make only (still allow submakes to be
+	run in parallel).
+	* main.c: New variable, ``not_parallel''.
+	* make.h: Add an extern for it.
+	* job.c (new_job): Test NOT_PARALLEL as well as JOB_SLOTS.
+	* NEWS: Add info on .NOTPARALLEL.
+	* make.texinfo (Special Targets): Document it.
+
+	* configure.in (GLOBDIR): Set to "glob" if we need to build the
+	glob library.
+	* Makefile.am (SUBDIRS): Use the GLOBDIR variable instead of
+	"glob" so we don't try to build glob if we don't need to (if we
+	have GLIBC glob).  Reported by Lars Hecking <lhecking@nmrc.ucc.ie>.
+
+	* main.c (main): Don't put "***" in the clock skew warning
+	message.  Reported by karl@gnu.org.
+
+	* make.h: Remove unneeded signal setup.
+
+	* signame.c: Remove extraneous #includes; some versions of Ultrix
+	don't protect against multiple inclusions and it causes compile
+	errors.  Reported by Simon Burge <simonb@thistledown.com.au>.
+
+1999-10-15  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (quote_for_env): Rename from quote_as_word().
+
+	* make.h, *.c: Prefer strchr() and strrchr() in the code
+	rather than index() and rindex().  Define strchr/strrchr in terms
+	of index/rindex if the former aren't supported.
+
+	* default.c (CHECKOUT,v): Replace the fancy, complicated
+	patsubst/filter expression with a simple $(if ...) expression.
+
+	* main.c (print_usage): Add the bug reporting mailing address to
+	the --help output, as per the GNU coding standards.
+	Reported by Paul Eggert <eggert@twinsun.com>.
+
+	* README.customs: Installed information on running Customs-ized
+	GNU make and setuid root, collected by Ted Stern <stern@tera.com>.
+
+	* read.c (read_all_makefiles): PR/1394: Mark the end of the next
+	token in the MAKEFILES value string _before_ we dup it.
+
+1999-10-13  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in (make_cv_sys_gnu_glob): We used to add the -Iglob
+	flag to CPPFLAGS, but that loses if the user specifies his own
+	CPPFLAGS; this one gets added _after_ his and if he happens to
+	have an old or broken glob.h--boom.  Instead, put it in GLOBINC
+	and SUBST it.
+
+	* Makefile.am (INCLUDES): Add @GLOBINC@ to the INCLUDES macro;
+	these things get on the compile line well before the user's
+	CPPFLAGS.
+
+1999-10-12  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (notice_finished_file): If we get here and -n is set,
+	see if all the command lines are marked recursive.  If so, then we
+	ran every command there is, so check the mtime on this file just
+	like we would normally.  If not, we assume the command we didn't
+	run would updates the target and set mtime of the target to "very new".
+
+	* job.c (start_job_command): Update lines_flags in the file's cmds
+	structure with any per-line tokens we found (`@', `-', `+').
+
+1999-10-08  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (initialize_file_variables): Always recurse to
+	initialize the parent's file variables: the parent might not have
+	any rules to run so it might not have been initialized before
+	this--we need this to set up the chain properly for
+	target-specific variables.
+
+1999-09-29  Paul Eggert  <eggert@twinsun.com>
+
+	* main.c (quote_as_word): Always quote for decode_env_switches
+        instead of for the shell, so that arguments with strange
+        characters are are passed to submakes correctly.  Remove
+        double_dollars arg; we always double dollars now.  All callers
+        changed.
+        (decode_env_switches): Don't run off the end of an environment
+        variable whose contents ends in a unescaped backslash.
+
+1999-09-23  Paul D. Smith  <psmith@gnu.org>
+
+	* commands.c, function.c, job.c, read.c: Cast arguments to
+	ctype.h functions/macros to _unsigned_ char for portability.
+
+	* remake.c, function.c: Compiler warning fixes: the second
+	argument to find_next_token() should be an _unsigned_ int*.
+	Reported by Han-Wen Nienhuys <hanwen@cs.uu.nl>.
+
+1999-09-23  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.78.1 released.
+
+	* make.texinfo: Update version/date stamp.
+
+	* main.c (main): Argh.  For some reason we were closing _all_ the
+	jobserver pipes before we re-exec'd due to changed makefiles.
+	This means that any re-exec got a "jobserver unavailable" error :-/.
+	I can't believe we didn't notice this before.
+
+1999-09-22  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.78 released.
+
+	* main.c (main): Only fail on multiple --jobserver-fds options if
+	they aren't all the same.  Some makefiles use things like
+	$(MAKE) $(MFLAGS) which will cause multiple, identical copies of
+	--jobserver-fds to show up.
+
+1999-09-16  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (define_makeflags): Zero out FLAGSTRING to avoid
+	uninitialized memory reads when checking *p != '-' in the loop.
+
+1999-09-15  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.77.97 released.
+
+	* configure.in (MAKE_HOST): AC_SUBST this so it will go into the
+	makefile.
+	* Makefile.am (check-local): Print a success banner if the check
+	succeeds.
+	(check-regression): A bit of fine-tuning.
+
+1999-09-15  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* README.DOS.template: Document requirements for the test suite.
+	* Makefile.DOS.template: Updates to allow the test suite to run
+	from "make check".
+
+	* main.c (main): Handle it if argv[0] isn't an absolute path.
+
+1999-09-13  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.77.96 released.
+
+	* Makefile.am (loadavg): Use CPPFLAGS, etc. to make sure we get
+	all the right #defines to compile.
+	(check-regression): Look for the regression test suite in the make
+	package itself.  If we're building remotely, use symlinks to make
+	a local copy.
+	(dist-hook): Put the test suite into the tar file.
+
+	* configure.in: Look for perl for the test suite.
+
+1999-09-10  Paul Eggert  <eggert@twinsun.com>
+
+        * acinclude.m4 (AC_SYS_LARGEFILE_FLAGS): If on HP-UX 10.20 or
+        later, and using GCC, define __STDC_EXT__; this works around a
+        bug in GCC 2.95.1.
+
+1999-09-08  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (print_version): Ugh.  GLIBC's configure tries to check
+	make version strings and is too aggressive with their matching
+	expressions.  I've struck a deal with them to leave the version
+	output as-is for 3.78, and they'll change their configure checks
+	so that I can change this back in the future.
+
+1999-09-07  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* job.c (construct_command_argv_internal) [__MSDOS__]: Add "echo"
+	and "unset" to the list of builtin shell commands.
+
+	* configh.DOS.template (MAKE_HOST): Define to "i386-pc-msdosdjgpp"
+	which is the canonical name of the DJGPP host.
+
+1999-09-05  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.77.95 released.
+
+	* make.texinfo (Make Errors): Document some new jobserver error
+	messages.
+
+1999-09-04  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* make.texinfo (Make Errors): Document the hint about 8 spaces
+	instead of a TAB.
+	(Call Function, Quick Reference): Use @code{$(1)}, not @var.
+
+	* main.c (main) [__MSDOS__]: Say "on this platform" instead of "on
+	MS-DOS", since the MSDOS version could run on Windows.
+
+1999-09-03  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (notice_finished_file): Always set mtime_before_update
+	if it's not been set, not just if we ran some rules.  Otherwise we
+	may have a situation where a target's prerequisite was rebuilt but
+	not changed, so this target's rules weren't run, then
+	update_goal_chain() sees mtime_before_update != last_mtime and
+	thinks that the top-level target changed when it really didn't.
+	This can cause an infinite loop when remaking makefiles.
+	(update_goal_chain): If we get back to the top and we don't know
+	what the goal's last_mtime was, find it now.  We need to know so
+	we can compare it to mtime_before_update later (this is only
+	crucial when remaking makefiles--should we only do it then?)
+
+1999-09-02  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): If "override" appears as the first
+	prerequisite, look further to ensure this is really a
+	target-specific variable definition, and not just some
+	prerequisite named "override".
+
+1999-09-01  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (IS_PATHSEP) [WINDOWS32]: Allow backslash separators
+	for W32 platforms.
+	* read.c (record_files) [WINDOWS32]: Allow backslash separators
+	for W32 platforms.
+	* implicit.c (pattern_search) [WINDOWS32]: Allow backslash
+	separators for W32 platforms.
+
+	* configure.in (MAKE_HOST): Define it to be the canonical build
+	host info, now that we need AC_CANONICAL_HOST anyway (for large
+	file support).
+	* version.c (make_host): Define a variable to MAKE_HOST so we're
+	sure to get it from the local config.h.
+	* main.c (print_version): Use it in the version information.
+	* config.ami.template: Add MAKE_HOST.
+	* configh.dos.template: Ditto.
+	* config.h.W32.template: Ditto.
+	* config.h-vms.template: Ditto.
+
+	* main.c (main): Close the jobserver file descriptors if we need
+	to re-exec ourselves.
+	Also print more reasonable error if users force -jN for submakes.
+	This may be common for a while until people use the jobserver
+	feature.  If it happens, we ignore the existing jobserver stuff
+	and use whatever they specified on the commandline.
+	(define_makeflags): Fixed a long-standing bug: if a long name
+	only option comes immediately after a single letter option with no
+	argument, then the option string is constructed incorrectly.  For
+	example, with -w and --jobserver-fds you get "-w-jobserver-fds..."
+	instead of "-w --jobserver-fds..."; add in an extra " -".
+
+	* make.texinfo (Phony Targets): Add another example of using
+	.PHONY with subdirectories/recursive make.
+
+1999-08-30  Paul D. Smith  <psmith@gnu.org>
+
+	* README.W32.template: Renamed from README.W32 so it's
+	autogenerated during the dist.  A few minor modifications.
+
+	* configure.in: Check for kstat_open before AC_FUNC_GETLOADAVG
+	since the latter needs to know whether the former exists to give
+	an accurate result.
+
+1999-08-26  Rob Tulloh  <rob_tulloh@dev.tivoli.com>
+
+	* NMakefile [WINDOWS32]: Now more robust. If you change a file
+	under w32/subproc, the make.exe will be relinked. Also added some
+	tests to make sure erase commands won't fail when executed in a
+	pristine build environment.
+
+	* w32/subproc/sub_proc.c [WINDOWS32]: Added support for
+	HAVE_CYGWIN_SHELL. If you are using the Cygwin B20.1 release, it
+	is now possible to have have native support for this shell without
+	having to rely on klutzy BATCH_MODE_ONLY_SHELL.
+
+	* config.h.W32 [WINDOWS32]: Added HAVE_CYGWIN_SHELL macro which
+	users can define if they want to build make to use this shell.
+
+	* README.W32 [WINDOWS32]: Added informaton about
+	HAVE_CYGWIN_SHELL. Cleaned up text a bit to make it more current.
+
+1999-08-26  Paul Eggert  <eggert@twinsun.com>
+
+	Support large files in AIX, HP-UX, and IRIX.
+
+	* acinclude.m4 (AC_LFS): Remove.  Superseded by AC_SYS_LARGEFILE.
+	(AC_SYS_LARGEFILE_FLAGS, AC_SYS_LARGEFILE_SPACE_APPEND,
+	AC_SYS_LARGEFILE_MACRO_VALUE, AC_SYS_LARGEFILE): New macros.
+	(jm_AC_TYPE_UINTMAX_T): Check for busted compilers that can't
+	shift or divide unsigned long long.
+	(AM_PROG_CC_STDC): New macro; a temporary workaround of a bug in
+	automake 1.4.
+
+	* configure.in (AC_CANONICAL_HOST): Add; required by new
+	AC_SYS_LARGEFILE.
+	(AC_SYS_LARGEFILE): Renamed from AC_LFS.
+	(AM_PROG_CC_STDC): Add.
+
+	* config.guess, config.sub: New files, needed for AC_CANONICAL_HOST.
+
+1999-08-25  Paul Eggert  <eggert@twinsun.com>
+
+	* make.h (CHAR_MAX): New macro.
+	* main.c (struct command_switch): c is now int,
+	so that it can store values greater than CHAR_MAX.
+	(switches): Replace small numbers N with CHAR_MAX+N-1,
+	to avoid problems with non-ASCII character sets.
+	(short_option): New macro.
+	(init_switches, print_usage, define_makeflags): Use it instead of
+	isalnum.
+
+1999-08-25  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.77.94 released.
+
+	* main.c (main) [__MSDOS__]: If the user uses -j, warn that it's
+	not supported and reset it.
+
+	* make.h (ISDIGIT): Obtained this from the textutils distribution.
+	* main.c (decode_switches): Use it.
+	* function.c (is_numeric): Use it.
+
+	* main.c (struct command_switch): Store the switch char in an
+	unsigned char to shut up GCC about using it with ctype.h macros.
+	Besides, it _is_ always unsigned.
+
+1999-08-24  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo: Change "dependency" to "prerequisite" and
+	"dependencies" to "prerequisites".  Various other cleanups related
+	to the terminology change.
+	* file.c: Change debugging and error messages to use
+	"prerequisite" instead of "dependency".
+	* implicit.c: Ditto.
+	* remake.c: Ditto.
+	* NEWS: Document it.
+
+1999-08-23  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_file): Move the considered check into the
+	double-colon rule loop, so we consider double-colon rules
+	individually (otherwise after the first is pruned, the rest won't
+	get run).
+
+	* README.template: Minor changes.
+
+	Remove the debugging features of the jobserver, so it no longer
+	writes distinct tokens to the pipe.  Thus, we don't need to store
+	the token we get.  A side effect of this is to remove a potential
+	"unavailable token" situation: make-1 invokes make-2 with its
+	special token and make-3 with a normal token; make-2 completes.
+	Now we're waiting for make-3 but using 2 tokens; our special token
+	is idle.  In the new version we don't have special tokens per se,
+	we merely decide if we already have a child or not.  If we don't,
+	we don't need a token.  If we do, we have to get one to run the
+	next child.  Similar for putting tokens back: if we're cleaning up
+	the last child, we don't put a token back.  Otherwise, we do.
+
+	* main.c: Add a new, internal flag --jobserver-fds instead of
+	overloading the meaning of -j.  Remove job_slots_str and add the
+	stringlist jobserver_fds.
+	(struct command_switch): We don't need the int_string type.
+	(switches[]): Add a new option for --jobserver-fds and remove
+	conditions around -j.  Make the description for the former 0 so it
+	doesn't print during "make --help".
+	(main): Rework jobserver parsing.  If we got --jobserver-fds
+	make sure it's valid.  We only get one and job_slots must be 0.
+	If we're the toplevel make (-jN without --jobserver-fds) create
+	the pipe and write generic tokens.
+	Create the stringlist struct for the submakes.
+	Clean up the stringlist where necessary.
+	(init_switches): Remove int_string handling.
+	(print_usage): Don't print internal flags (description ptr is 0).
+	(decode_switches): Remove int_string handling.
+	(define_makeflags): Remove int_string handling.
+
+	* job.c: Remove my_job_token flag and all references to the
+	child->job_token field.
+	(free_job_token): Remove this and merge it into free_child().
+	(reap_children): Rework the "reaped a child" logic slightly.
+	Don't call defunct free_job_token anymore.  Always call
+	free_child, even if we're dying.
+	(free_child): If we're not freeing the only child, put a token
+	back in the pipe.  Then, if we're dying, don't bother to free.
+	(new_job): If we are using the jobserver, loop checking to see if
+	a) there are no children or b) we get a token from the pipe.
+
+	* job.h (struct child): Remove the job_token field.
+
+1999-08-20  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (try_variable_definition): Allocate for variable
+	expansion in f_append with a simple variable: if we're looking at
+	target-specific variables we don't want to trash the buffer.
+	Noticed by Reiner Beninga <Reiner.Beninga@mchp.siemens.de>.
+
+1999-08-16  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* main.c (main) [__MSDOS__]: Mirror any backslashes in argv[0], to
+	avoid problems in shell commands that use backslashes as escape
+	characters.
+
+1999-08-16  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.77.93 released.
+
+1999-08-13  Paul D. Smith  <psmith@gnu.org
+
+	* function.c (func_if): New function $(if ...) based on the
+	original by Han-Wen but reworked quite a bit.
+	(function_table): Add it.
+	* NEWS: Introduce it.
+	* make.texinfo (If Function): Document it.
+
+	* job.c (free_job_token): Check for EINTR when writing tokens to
+	the jobserver pipe.
+
+1999-08-12  Paul D. Smith  <psmith@gnu.org>
+
+	Another jobserver algorithm change.  We conveniently forgot that
+	the blocking bit is shared by all users of the pipe, it's not a
+	per-process setting.  Since we have many make processes all
+	sharing the pipe we can't use the blocking bit as a signal handler
+	flag.  Instead, we'll dup the pipe's read FD and have the SIGCHLD
+	handler close the dup'd FD.  This will cause the read() to fail
+	with EBADF the next time we invoke it, so we know we need to reap
+	children.  We then re-dup and reap.
+
+	* main.c (main): Define the job_rfd variable to hold the dup'd FD.
+	Actually dup the read side of the pipe.  Don't bother setting the
+	blocking bit on the file descriptor.
+	* make.h: Declare the job_rfd variable.
+	* job.c (child_handler): If the dup'd jobserver pipe is open,
+	close it and assign -1 to job_rfd to notify the main program that
+	we got a SIGCHLD.
+	(start_job_command): Close the dup'd FD before exec'ing children.
+	Since we open and close this thing so often it doesn't seem
+	worth it to use the close-on-exec bit.
+	(new_job): Remove code for testing/setting the blocking bit.
+	Instead of EAGAIN, test for EBADF.  If the dup'd FD has been
+	closed, re-dup it before we reap children.
+
+	* function.c (func_shell): Be a little more accurate about the
+	length of the error string to allocate.
+
+	* expand.c (variable_expand_for_file): If there's no filenm info
+	(say, from a builtin command) then reset reading_file to 0.
+
+1999-08-09  Paul D. Smith  <psmith@gnu.org>
+
+	* maintMakefile: Use g in sed (s///g) to replace >1 variable per
+	line.
+
+	* Makefile.DOS.template [__MSDOS__]: Fix mostlyclean-aminfo to
+	remove the right files.
+
+1999-08-01  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* function.c (msdos_openpipe) [__MSDOS__]: *Really* return a FILE
+	ptr.
+
+1999-08-01  Paul D. Smith  <psmith@gnu.org>
+
+	New jobserver algorithm to avoid a possible hole where we could
+	miss SIGCHLDs and get into a deadlock.  The original algorithm was
+	suggested by Roland McGrath with a nice refinement by Paul Eggert.
+	Many thanks as well to Tim Magill and Howard Chu, who also
+	provided many viable ideas and critiques.  We all had a fun week
+	dreaming up interesting ways to use and abuse UNIX syscalls :).
+
+	Previously we could miss a SIGCHLD if it happened after we reaped
+	the children but before we re-entered the blocking read.  If this
+	happened to all makes and/or all children, make would never wake
+	up.
+
+	We avoid this by having the SIGCHLD handler reset the blocking bit
+	on the jobserver pipe read FD (normally read does block in this
+	algorithm).  Now if the handler is called between the time we reap
+	and the time we read(), and there are no tokens available, the
+	read will merely return with EAGAIN instead of blocking.
+
+	* main.c (main): Set the blocking bit explicitly here.
+	* job.c (child_handler): If we have a jobserver pipe, set the
+	non-blocking bit for it.
+	(start_waiting_job): Move the token stuff back to new_job; if we
+	do it here then we're not controlling the number of remote jobs
+	started!
+	(new_job): Move the check for job slots to _after_ we've created a
+	child structure.  If the read returns without getting a token, set
+	the blocking bit then try to reap_children.
+
+	* make.h (EINTR_SET): Define to test errno if EINTR is available,
+	or 0 otherwise.  Just some code cleanup.
+	* arscan.c (ar_member_touch): Use it.
+	* function.c (func_shell): Use it.
+	* job.c (reap_children): Use it.
+	* remake.c (touch_file): Use it.
+
+1999-07-28  Paul D. Smith  <psmith@gnu.org>
+
+	* make.h: Define _() and N_() macros as passthrough to initiate
+	NLS support.
+	* <all>: Add _()/N_() around translatable strings.
+
+1999-07-27  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c: Make sure make.h comes before other headers.
+
+1999-07-26  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo (Quick Reference): Update with the new features.
+
+1999-07-25  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* remake.c [__MSDOS__]: Don't include variables.h, it's already
+	included.
+
+	* function.c (msdos_openpipe) [__MSDOS__]: Return FILE ptr.
+	(func_shell) [__MSDOS__]: Fix the argument list.
+
+	* Makefile.DOS.template: Update from Makefile.in.
+
+	* README.DOS.template: Configure command fixed.
+
+	* configh.dos.template: Update to provide definitions for
+	uintmax_t, fd_set_size_t, and HAVE_SELECT.
+
+1999-07-24  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.77.91 released.
+
+	* configure.in: Changes to the boostrapping code: if build.sh.in
+	doesn't exist configure spits an error and generates an empty
+	build.sh file which causes make to be confused.
+	* maintMakefile: Don't build README early.
+
+1999-07-23  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (my_job_token): This variable controls whether we've
+	handed our personal token to a subprocess or not.  Note we could
+	probably infer this from the value of job_slots_used, but it's
+	clearer to just keep it separately.  Job_slots_used isn't really
+	relevant when running the job server.
+	(free_job_token): New function: free a job token.  If we don't
+	have one, no-op.  If we have the personal token, reclaim it.  If
+	we have another token, write it back to the pipe.
+	(reap_children): Call free_job_token.
+	(free_child): Call free_job_token.
+	(start_job_command): Remove duplicate test for '+' in the command.
+	If we don't appear to be running a recursive make, close the
+	jobserver filedescriptors.
+	(start_waiting_job): If our personal token is available, use that
+	instead of going to the server pipe.
+	(*): Add the token value to many debugging statements, and print
+	the child target name in addition to the ptr hex value.
+	Change the default "no token" value from '\0' to '-' so it looks
+	better in the output.
+
+	* main.c (main): Install the child_handler with sigaction()
+	instead of signal() if we have it.  On SysV systems, signal() uses
+	SysV semantics which are a pain.  But sigaction() always does what
+	we want.
+	(main): If we got job server FDs from the environment, test them
+	to see if they're open.  If not, the parent make closed them
+	because it didn't think we were a submake.  Print a warning and
+	suggestion to use "+" on the submake invocation, and hard-set to
+	-j1 for this instance of make.
+	(main): Change the algorithm for assigning slots to be more
+	robust.  Previously make checked to see if it thought a subprocess
+	was a submake and if so, didn't give it a token.  Since make's
+	don't consume tokens we could spawn many of makes fighting for a
+	small number of tokens.  Plus this is unreliable because submakes
+	might not be recognized by the parent (see above) then all the
+	tokens could be used up by unrecognized makes, and no one could
+	run.  Now every make consumes a token from its parent.  However,
+	the make can also use this token to spawn a child.  If the make
+	wants more than one, it goes to the jobserver pipe.  Thus there
+	will never be more than N makes running for -jN, and N*2 processes
+	(N makes and their N children).  Every make can always run at
+	least one job, and we'll never deadlock.  (Note the closing of the
+	pipe for non-submakes also solves this, but this is still a better
+	algorithm.)  So!  Only put N-1 tokens into the pipe, since the
+	topmost make keeps one for itself.
+
+	* configure.in: Find sigaction.  Disable job server support unless
+	the system provides it, in addition to either waitpid() or
+	wait3().
+
+1999-07-22  Rob Tulloh  <rob_tulloh@dev.tivoli.com>
+
+	* arscan.c (ar_member_touch) [WINDOWS32]: The ar_date field is a
+	string on Windows, not a timestamp.
+
+1999-07-21  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.77.90 released.
+
+	* Makefile.am (AUTOMAKE_OPTIONS): Require automake 1.4.
+
+	* function.c: Rearrange so we don't need to predeclare the
+	function_table array; K&R C compilers don't like that.
+
+	* acinclude.m4 (AC_FUNC_SELECT): Ouch; this requires an ANSI C
+	compiler!  Change to work with K&R compilers as well.
+
+	* configure.in (AC_OUTPUT): Put build.sh back.  I don't know how I
+	thought it would work this way :-/.  We'll have to think of
+	something else.
+	* Makefile.am: Remove rule to create build.sh.
+
+	* default.c (default_suffix_rules): Rearrange the default command
+	lines to conform to POSIX rules (put the filename argument $<
+	_after_ the OUTPUT_OPTION, not before it).
+
+	* various: Changed !strncmp() calls to strneq() macros.
+
+	* misc.c (sindex): Make slightly more efficient.
+
+	* dir.c (file_impossible): Change savestring(X,strlen(X)) to xstrdup().
+	* implicit.c (pattern_search): Ditto.
+	* main.c (enter_command_line_file): Ditto.
+	(main): Ditto.
+	* misc.c (copy_dep_chain): Ditto.
+	* read.c (read_makefile): Ditto.
+	(parse_file_seq): Ditto.
+	(tilde_expand): Ditto.
+	(multi_glob): Ditto.
+	* rule.c (install_pattern_rule): Ditto.
+	* variable.c (define_variable_in_set): Ditto.
+	(define_automatic_variables): Ditto.
+	* vpath.c (construct_vpath_list): Ditto.
+
+	* misc.c (xrealloc): Some reallocs are non-standard: work around
+	them in xrealloc by calling malloc if PTR is NULL.
+	* main.c (main): Call xrealloc() directly instead of testing for
+	NULL.
+
+	* function.c (func_sort): Don't try to free NULL; some older,
+	non-standard versions of free() don't like it.
+
+	* configure.in (--enable-dmalloc): Install some support for using
+	dmalloc (http://www.dmalloc.com/) with make.  Use --enable-dmalloc
+	with configure to enable it.
+
+	* function.c (function_table_entry): Whoops!  The function.c
+	rewrite breaks backward compatibility: all text to a function is
+	broken into arguments, and extras are ignored.  So $(sort a,b,c)
+	returns "a"!  Etc.  Ouch.  Fix it by making a positive value in
+	the REQUIRED_ARGS field mean exactly that many arguments to the
+	function; any "extras" are considered part of the last argument as
+	before.  A negative value means at least that many, but may be
+	more: in this case all text is broken on commas.
+	(handle_function): Stop when we've seen REQUIRED_ARGS args, if >0.
+	(expand_builtin_function): Compare number of args to the absolute
+	value of REQUIRED_ARGS.
+
+1999-07-20  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (start_job_command): Ensure that the state of the target
+	is cs_running.  It might not be if we skipped all the lines due to
+	-n (for example).
+
+	* commands.c (execute_file_commands): If we discover that the
+	command script is empty and succeed early, set cs_running so the
+	modtime of the target is still rechecked.
+
+	* rule.c (freerule): Free the dependency list for the rule.
+
+	* implicit.c (pattern_search): When turning an intermediate file
+	into a real target, keep the also_make list.
+	Free the dep->name if we didn't use it during enter_file().
+
+1999-07-16  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): Don't allocate the commands buffer until
+	we're sure we found a makefile and won't return early (mem leak).
+
+	* job.c (start_job_command): Broken #ifdef test: look for F_SETFD,
+	not FD_SETFD.  Close-on-exec isn't getting set on the bad_stdin
+	file descriptor and it's leaking :-/.
+	* getloadavg.c (getloadavg): Ditto.
+
+1999-07-15  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): Fix some potential memory stomps parsing
+	`define' directives where no variable name is given.
+
+	* function.c (func_call): Rename from func_apply.  Various code
+	cleanup and tightening.
+	(function_table): Add "call" as a valid builtin function.
+
+	* make.texinfo (Call Function): Document it.
+
+	* NEWS: Announce it.
+
+1999-07-09  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* variable.c (try_variable_definition) [__MSDOS__, WINDOWS32]:
+	Treat "override SHELL=" the same as just "SHELL=".
+
+1999-07-09  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (start_waiting_job): Don't get a second job token if we
+	already have one; if we're waiting on the load to go down
+	start_waiting_job() might get called twice on the same file.
+
+	* filedef.h (struct file): Add new field, mtime_before_update.
+	When notice_finished_file runs it assigns the cached last_mtime to
+	this field.
+	* remake.c (update_goal_chain): Notice that a file wasn't updated
+	by asking if it changed (g->changed) and comparing the current
+	cached time (last_mtime) with the previous one, stored in
+	mtime_before_update.  The previous check ("did last_mtime changed
+	during the run of update_file?") fails for parallel builds because
+	last_mtime is set during reap_children, before update_file is run.
+	This causes update_goal_chain to always return -1 (nothing
+	rebuilt) when running parallel (-jN).  This is OK during "normal"
+	builds since our caller (main) treats these cases identically in
+	that case, but if when rebuilding makefiles the difference is very
+	important, as it controls whether we re-exec or not.
+	* file.c (file_hash_enter): Copy the mtime_before_update field.
+	(snap_deps): Initialize mtime_before_update to -1.
+	* main.c (main): Initialize mtime_before_update on old (-o) and
+	new (-W) files.
+
+1999-07-08  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (switches): Define a new switch -R (or
+	--no-builtin-variables).  This option disables the defining of all
+	the GNU make builtin variables.
+	(main): If -R was given, force -r as well.
+	* default.c (define_default_variables): Test the new flag.
+	* make.h: Declare global flag.
+	* make.texinfo (Options Summary): Document the new option.
+	(Implicit Variables): Ditto.
+
+1999-07-06  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo (Options Summary): Correct examples in
+	--print-data-base option summary (problem reported by David Morse
+	<morse@nichimen.com>).
+
+	* arscan.c: Add support for archives in Windows (VC++).  Frank
+	Libbrecht <frankl@abzx.belgium.hp.com> provided info on how to do
+	this.
+	* NMakefile.template (CFLAGS_any): Remove NO_ARCHIVES from the
+	compile line.
+	* build_w32.bat: Ditto.
+
+	* remake.c (no_rule_error): Fix -include/sinclude so it doesn't
+	give errors if you try to -include the same file twice.
+	(updating_makefiles): New variable: we need to know this info in
+	no_rule_error() so we know whether to print an error or not.
+	(update_file_1): Unconditionally call no_rule_error(), don't try
+	to play games with the dontcare flag.
+
+1999-06-14  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo (Remaking Makefiles): Add a description of how to
+	prevent implicit rule searches for makefiles.
+
+	* make.1: Remove statement that make continues processing when -v
+	is given.
+
+1999-06-14  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): Cast -1 arguments to
+	variable_expand_string() to long.  Alexandre Sauve
+	<Alexandre.SAUVE@ifp.fr> reports that without casts, this breaks
+	on a NEC SUPER-UX SX-4 system (and it's wrong without a cast
+	anyway).  Of course, (a) I'd really love to start using function
+	prototypes, and (b) there's a whole slew of issues related to int
+	vs. long and signed vs. unsigned in the length handling of
+	variable buffers, etc.  Gross.  Needs a complete mucking-out.
+	* expand.c (variable_expand): Ditto.
+
+	* acinclude.m4 (AC_FUNC_SELECT): Slight enhancement for AIX 3.2 by
+	Lars Hecking <lhecking@nmrc.ucc.ie>.
+
+	* read.c (get_next_mword): Allow colons to be escaped in target
+	names: fix for regression failure.
+
+1999-04-26  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Reset read_makefiles to empty after processing so
+	we get the right error message.
+
+1999-04-25  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo: Updates to @dircategory and @direntry suggested by
+	Karl Berry <karl@cs.umb.edu>.
+
+1999-04-23  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* job.c (start_job_command) [__MSDOS__]: Call unblock_sigs before
+	turning off dos_command_running, so child's signals produce the
+	right effect.
+
+	* commands.c (fatal_error_signal) [__MSDOS__]: Use EXIT_FAILURE
+	instead of 1.
+
+1999-04-18  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* configh.dos.template: Update to recognize that version 2.02 of
+	DJGPP contains sys_siglist stuff.
+
+1999-04-14  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo (Options/Recursion): Document the job server.
+	(Parallel): Tweaks.
+
+1999-04-13  Paul D. Smith  <psmith@gnu.org>
+
+	Implement a new "job server" feature; the implementation was
+	suggested by Howard Chu <hyc@highlandsun.com>.
+
+	* configure.in (job-server): New disable option for job server
+	support--it's enabled by default.  If it works well this will go
+	away.
+
+	* NEWS: Summarize the new feature.
+
+	* acconfig.h: New definition MAKE_JOBSERVER if job server support
+	is enabled.
+	* config.h-vms.template: Undef MAKE_JOBSERVER for this port.
+	* config.h.W32.template: Ditto.
+	* config.ami.template: Ditto.
+
+	* main.c (struct command_switch): Add a new type: int_string.
+	(switches[]) Use int_string for -j if MAKE_JOBSERVER.
+	(init_switches): Initialize the new int_string switch type.
+	(print_usage): New function, extracted from decode_switches().
+	(decode_switches): Call it.  Decode the new int_string switch type.
+	(define_makeflags): Add new int_string switch data to MAKEFLAGS.
+	(job_fds[]) Array to contain the pipe file descriptors.
+	(main): Parse the job_slots_str option results.  If necessary,
+	create the pipe and seed it with tokens.  Set the non-blocking bit
+	for the read fd.  Enable the signal handler for SIGCHLD even if we
+	have a non-hanging wait; it's needed to interrupt the select() in
+	job.c:start_waiting_job().
+
+	* make.h: Declare job_fds[].
+
+	* job.h (struct child): Add job_token field to store the token for
+	this job (if any).
+
+	* job.c (reap_children): When a child is fully reaped, release the
+	token back into the pipe.
+	(free_child): If the child to be freed still has a token, put it
+	back.
+	(new_job): Initialize the job_token member.
+	(start_waiting_job): For local jobs, if we're using the pipe, get
+	a token before we check the load, etc.  We do this by performing a
+	non-blocking read in a loop.  If the read fails, no token is
+	available.  Do a select on the fd to wait for a token.  We need to
+	re-enable the signal handler for SIGCHLD even if we have a
+	non-hanging waitpid() or wait3(), so that the signal will
+	interrupt the select() and we can wake up to reap children.
+	(child_handler): Re-enable the signal handler.  The count is still
+	kept although it's not needed or used unless you don't have
+	waitpid() or wait3().
+
+1999-04-10  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Reset the considered bit on all the makefiles if
+	something failed to update; we need to examine them again if they
+	appear as normal targets in order to get the proper error message.
+
+1999-04-09  Paul D. Smith  <psmith@gnu.org>
+
+	Performance enhancement from Tim Magill <tim.magill@telops.gte.com>.
+
+	* remake.c (update_file): If you have large numbers of
+	dependencies and you run in parallel, make can spend considerable
+	time each pass through the graph looking at branches it has
+	already seen.  Since we only reap_children() when starting a pass,
+	not in the middle, if a branch has been seen already in that pass
+	nothing interesting can happen until the next pass.  So, we toggle
+	a bit saying whether we've seen this target in this pass or not.
+	(update_goal_chain): Initially set the global considered toggle to
+	1, since all targets initialize their boolean to 0.  At the end of
+	each pass, toggle the global considered variable.
+	* filedef.h (struct file): Per-file considered toggle bit.
+	* file.c: New global toggle variable considered.
+
+1999-04-05  Paul D. Smith  <psmith@gnu.org>
+
+	* arscan.c (ar_scan): Added support for ARFZMAG (compressed
+	archives?) for Digital UNIX C++.  Information provided by
+	Patrick	E. Krogel <pekrogel@mtu.edu>.
+	(ar_member_touch): Ditto.
+
+1999-04-03  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (f_mtime): If: a) we found a file and b) we didn't
+	create it and c) it's not marked as an implicit target and d) it
+	is marked as an intermediate target, then it was so marked due to
+	an .INTERMEDIATE special target, but it already existed in the
+	directory.  In this case, unset the intermediate flag so we won't
+	delete it when make is done.  It feels like it would be cleaner to
+	put this check in update_file_1() but I worry it'll get missed...
+
+1999-04-01  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (construct_command_argv_internal): Use bcopy() to copy
+	overlapping strings, rather than strcpy().  ISO C says the latter
+	is undefined.  Found this in a bug report from 1996!  Ouch!
+
+1999-03-31  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (readline): Ignore carriage returns at the end of the
+	line, to allow Windows-y CRLF line terminators.
+
+1999-03-30  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Don't put build.sh here, since build.sh.in doesn't
+	exist initially.  This cause autoreconf and automake to fail when
+	run on a clean CVS checkout.  Instead, we create build.sh in the
+	Makefile (see below).
+
+	* Makefile.am: Remove BUILT_SOURCES; this is no longer relevant.
+	Put those files directly into EXTRA_DIST so they're distributed.
+	Create a local build rule to create build.sh.
+	Create a local maintainer-clean rule to delete all the funky
+	maintainers files.
+
+	* maintMakefile: Makefile.in depends on README, since automake
+	fails if it doesn't exist.  Also don't remove glob/Makefile.in
+	here, as it causes problems.
+
+1999-03-26  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Substitute GLOBLIB if we need the link the
+	glob/libglob.a library.
+	* Makefile.am (make_LDADD): Use the subst variable GLOBLIB so we
+	don't link the local libglob.a at all if we don't need it.
+	* build.template: Don't compile glob/*.o unless we want globlib.
+	* maintMakefile (build.sh.in): Substitute the glob/*.o files
+	separately.
+
+1999-03-25  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo: Various typos and additions, pointed out by James
+	G. Sack <jsack@dornfeld.com>.
+
+1999-03-22  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo (Functions): Add a new section documenting the new
+	$(error ...) and $(warning ...) functions.  Also updated copyright
+	dates.
+	* NEWS: Updated for the new functions.
+	* function.c (func_error): Implement the new $(error ...) and
+	$(warning ...) functions.
+	(function_table): Insert new functions into the table.
+	(func_firstword): Don't call find_next_token() with argv[0]
+	itself, since that function modifies the pointer.
+	* function.c: Cleanups and slight changes to the new method of
+	calling functions.
+
+1999-03-20  Han-Wen Nienhuys  <hanwen@cs.uu.nl>
+
+	* function.c: Rewrite to use one C function per make function,
+	instead of a huge switch statement.  Also allows some cleanup of
+	multi-architecture issues, and a cleaner API which makes things
+	like func_apply() simple.
+
+	* function.c (func_apply): Initial implementation.  Expand either
+	a builtin function or a make variable in the context of some
+	arguments, provided as $1, $2, ... $N.
+
+1999-03-19  Eli Zaretskii  <eliz@is.elta.co.il>
+1999-03-19  Rob Tulloh  <rob_tulloh@dev.tivoli.com>
+
+	* job.c (construct_command_argv_internal): Don't treat _all_
+	backslashes as escapes, only those which really escape a special
+	character.  This allows most normal "\" directory separators to be
+	treated normally.
+
+1999-03-05  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Check for a system strdup().
+	* misc.c (xstrdup): Created.  Suggestion by Han-Wen Nienhuys
+	<hanwen@cs.uu.nl>.
+	* make.h: Prototype xstrdup().
+	* remake.c (library_search): Use it.
+	* main.c (main): Use it.
+	(find_and_set_default_shell): Use it.
+	* job.c (construct_command_argv_internal): Use it.
+	* dir.c (find_directory): Use it.
+
+	* Makefile.am, configure.in: Use AC_SUBST_FILE to insert the
+	maintMakefile instead of "include", to avoid automake 1.4
+	incompatibility.
+
+1999-03-04  Paul D. Smith  <psmith@gnu.org>
+
+	* amiga.c, amiga.h, ar.c, arscan.c, commands.c, commands.h,
+	* default.c, dep.h, dir.c, expand.c, file.c, filedef.h, function.c,
+	* implicit.c, job.c, job.h, main.c, make.h, misc.c, read.c, remake.c
+	* remote-cstms.c, remote-stub.c, rule.h, variable.c, variable.h,
+	* vpath.c, Makefile.ami, NMakefile.template, build.template,
+	* makefile.vms: Updated FSF address in the copyright notice.
+
+	* variable.c (try_variable_definition): If we see a conditional
+	variable and we decide to set it, re-type it as recursive so it
+	will be expanded properly later.
+
+1999-02-22  Paul D. Smith  <psmith@gnu.org>
+
+	* NEWS: Mention new .LIBPATTERNS feature.
+
+	* make.texinfo (Libraries/Search): Describe the use and
+	ramifications of the new .LIBPATTERNS variable.
+
+	* remake.c (library_search): Instead of searching only for the
+	hardcoded expansion "libX.a" for a library reference "-lX", we
+	obtain a list of patterns from the .LIBPATTERNS variable and
+	search those in order.
+
+	* default.c: Added a new default variable .LIBPATTERNS.  The
+	default for UNIX is "lib%.so lib%.a".  Amiga and DOS values are
+	also provided.
+
+	* read.c: Remove bogus HAVE_GLOB_H references; always include
+	vanilla glob.h.
+
+1999-02-21  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (expand_function): Set value to 0 to avoid freeing it.
+	* variable.c (pop_variable_scope): Free the value of the variable.
+	(try_variable_definition): For simple variables, use
+	allocated_variable_expand() to avoid stomping on the variable
+	buffer when we still need it for other things.
+
+	* arscan.c: Modified to support AIX 4.3 big archives.  The changes
+	are based on information provided by Phil Adams
+	<padams@austin.ibm.com>.
+
+1999-02-19  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Check to see if the GNU glob library is already
+	installed on the system.  If so, _don't_ add -I./glob to the
+	compile line.  Using the system glob code with the local headers
+	is very bad mojo!
+	Rewrite SCCS macros to use more autoconf facilities.
+
+	* Makefile.am: Move -Iglob out of INCLUDES; it'll get added to
+	CPPFLAGS by configure now.
+	Automake 1.4 introduced its own "include" feature which conflicts
+	with the maintMakefile stuff.  A hack that seems to work is add a
+	space before the include :-/.
+
+	* build.template: Move -Iglob out of the compile line; it'll get
+	added to CPPFLAGS by configure now.
+
+1999-02-16  Glenn D. Wolf  <Glenn_Wolf@email.sps.mot.com>
+
+	* arscan.c (ar_scan) [VMS]: Initialized VMS_member_date before
+	calling lbr$get_index since if the archive is empty,
+	VMS_get_member_info won't get called at all, and any leftover date
+	will be used.  This bug shows up if any member of any archive is
+	made, followed by a dependency check on a different, empty
+	archive.
+
+1998-12-13  Martin Zinser  <zinser@decus.decus.de>
+
+	* config.h-vms [VMS]: Set _POSIX_C_SOURCE.  Redefine the getopt
+	functions so we don't use the broken VMS versions.
+	* makefile.com [VMS]: Allow debugging.
+	* dir.c (dir_setup_glob) [VMS]: Don't extern stat() on VMS.
+
+1998-11-30  Paul D. Smith  <psmith@gnu.org>
+
+	* signame.c (init_sig): Check the sizes of signals being set up to
+	avoid array overwrites (if the system headers have problems).
+
+1998-11-17  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (record_files): Clean up some indentation.
+
+1998-11-08  Han-Wen Nienhuys  <hanwen@cs.uu.nl>
+
+	* rule.c (print_rule_data_base): Fix arguments to fatal() call.
+
+1998-10-13  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (start_job_command): If the command list resolves to no
+	chars at all (e.g.: "foo:;$(empty)") then command_ptr is NULL;
+	quit early.
+
+1998-10-12  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>
+
+	* rule.c (print_rule_data_base): Ignore num_pattern_rules if it is
+	zero.
+
+1998-10-09  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): Allow non-empty lines to expand to the
+	empty string after variable, etc., expansion, and be ignored.
+
+1998-09-21  Paul D. Smith  <psmith@gnu.org>
+
+	* job.c (construct_command_argv_internal): Only add COMMAND.COM
+	"@echo off" line for non-UNIXy shells.
+
+1998-09-09  Paul D. Smith  <psmith@gnu.org>
+
+	* w32/subproc/sub_proc.c: Add in missing HAVE_MKS_SHELL tests.
+
+1998-09-04  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): If we hit the "missing separator" error,
+	check for the common case of 8 spaces instead of a TAB and give an
+	extra comment to help people out.
+
+1998-08-29  Paul Eggert  <eggert@twinsun.com>
+
+	* configure.in (AC_STRUCT_ST_MTIM_NSEC):
+	Renamed from AC_STRUCT_ST_MTIM.
+
+	* acinclude.m4 (AC_STRUCT_ST_MTIM_NSEC):  Likewise.
+	Port to UnixWare 2.1.2 and pedantic Solaris 2.6.
+
+	* acconfig.h (ST_MTIM_NSEC):
+	Renamed from HAVE_ST_MTIM, with a new meaning.
+
+	* filedef.h (FILE_TIMESTAMP_FROM_S_AND_NS):
+	Use new ST_MTIM_NSEC macro.
+
+1998-08-26  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (check_dep): For any intermediate file, not just
+	secondary ones, try implicit and default rules if no explicit
+	rules are given.  I'm not sure why this was restricted to
+	secondary rules in the first place.
+
+1998-08-24  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo (Special Targets): Update documentation for
+	.INTERMEDIATE: if used with no dependencies, then it does nothing;
+	old docs said it marked all targets as intermediate, which it
+	didn't... and which would be silly :).
+
+	* implicit.c (pattern_search): If we find a dependency in our
+	internal tables, make sure it's not marked intermediate before
+	accepting it as a found_file[].
+
+1998-08-20  Paul D. Smith  <psmith@gnu.org>
+
+	* ar.c (ar_glob): Use existing alpha_compare() with qsort.
+	(ar_glob_alphacompare): Remove it.
+
+	Modify Paul Eggert's patch so we don't abandon older systems:
+
+	* configure.in: Warn the user if neither waitpid() nor wait3() is
+	available.
+
+	* job.c (WAIT_NOHANG): Don't syntax error on ancient hosts.
+	(child_handler, dead_children): Define these if WAIT_NOHANG is not
+	available.
+	(reap_children): Only track the dead_children count if no
+	WAIT_NOHANG.  Otherwise, it's a boolean.
+
+	* main.c (main): Add back signal handler if no WAIT_NOHANG is
+	available; only use default signal handler if it is.
+
+1998-08-20  Paul Eggert  <eggert@twinsun.com>
+
+	Install a more robust signal handling mechanism for systems which
+	support it.
+
+	* job.c (WAIT_NOHANG): Define to a syntax error if our host
+	is truly ancient; this should never happen.
+	(child_handler, dead_children): Remove.
+	(reap_children): Don't try to keep separate track of how many
+	dead children we have, as this is too bug-prone.
+	Just ask the OS instead.
+	(vmsHandleChildTerm): Fix typo in error message; don't mention
+	child_handler.
+
+	* main.c (main): Make sure we're not ignoring SIGCHLD/SIGCLD;
+	do this early, before we could possibly create a subprocess.
+	Just use the default behavior; don't have our own handler.
+
+1998-08-18  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* read.c (read_makefile) [__MSDOS__, WINDOWS32]: Add code to
+	recognize library archive members when dealing with drive spec
+	mess.  Discovery and initial fix by George Racz <gracz@mincom.com>.
+
+1998-08-18  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Check for stdlib.h explicitly (some hosts have it
+	but don't have STDC_HEADERS).
+	* make.h: Use HAVE_STDLIB_H.  Clean up some #defines.
+	* config.ami: Re-compute based on new config.h.in contents.
+	* config.h-vms: Ditto.
+	* config.h.W32: Ditto.
+	* configh.dos: Ditto.
+
+	* dir.c (find_directory) [WINDOWS32]: Windows stat() fails if
+	directory names end with `\' so strip it.
+
+1998-08-17  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo: Added copyright year to the printed copy.  Removed
+	the price from the manual.  Change the top-level reference to
+	running make to be "Invoking make" instead of "make Invocation",
+	to comply with GNU doc standards.
+
+	* make.h (__format__, __printf__): Added support for these in
+	__attribute__ macro.
+	(message, error, fatal): Use ... prototype form under __STDC__.
+	Add __format__ attributes for printf-style functions.
+
+	* configure.in (AC_FUNC_VPRINTF): Check for vprintf()/_doprnt().
+
+	* misc.c (message, error, fatal): Add preprocessor stuff to enable
+	creation of variable-argument functions with appropriate
+	prototypes, that works with ANSI, pre-ANSI, varargs.h, stdarg.h,
+	v*printf(), _doprnt(), or none of the above.  Culled from GNU
+	fileutils and slightly modified.
+	(makefile_error, makefile_error): Removed (merged into error() and
+	fatal(), respectively).
+	* amiga.c: Use them.
+	* ar.c: Use them.
+	* arscan.c: Use them.
+	* commands.c: Use them.
+	* expand.c: Use them.
+	* file.c: Use them.
+	* function.c: Use them.
+	* job.c: Use them.
+	* main.c: Use them.
+	* misc.c: Use them.
+	* read.c: Use them.
+	* remake.c: Use them.
+	* remote-cstms.c: Use them.
+	* rule.c: Use them.
+	* variable.c: Use them.
+
+	* make.h (struct floc): New structure to store file location
+	information.
+	* commands.h (struct commands): Use it.
+	* variable.c (try_variable_definition): Use it.
+	* commands.c: Use it.
+	* default.c: Use it.
+	* file.c: Use it.
+	* function.c: Use it.
+	* misc.c: Use it.
+	* read.c: Use it.
+	* rule.c: Use it.
+
+1998-08-16  Paul Eggert  <eggert@twinsun.com>
+
+	* filedef.h (FILE_TIMESTAMP_PRINT_LEN_BOUND): Add 10, for nanoseconds.
+
+1998-08-16  Paul Eggert  <eggert@twinsun.com>
+
+	* filedef.h (FLOOR_LOG2_SECONDS_PER_YEAR): New macro.
+	(FILE_TIMESTAMP_PRINT_LEN_BOUND): Tighten bound, and try to
+	make it easier to understand.
+
+1998-08-14  Paul D. Smith  <psmith@gnu.org>
+
+	* read.c (read_makefile): We've already unquoted any colon chars
+	by the time we're done reading the targets, so arrange for
+	parse_file_seq() on the target list to not do so again.
+
+1998-08-05  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Added glob/configure.in data.  We'll have the glob
+	code include the regular make config.h, rather than creating its
+	own.
+
+	* getloadavg.c (main): Change return type to int.
+
+1998-08-01  Paul Eggert  <eggert@twinsun.com>
+
+	* job.c (reap_children): Ignore unknown children.
+
+1998-07-31  Paul D. Smith  <psmith@gnu.org>
+
+	* make.h, filedef.h, dep.h, rule.h, commands.h, remake.c:
+	Add prototypes for functions.  Some prototypes needed to be moved
+	in order to get #include order reasonable.
+
+1998-07-30  Paul D. Smith  <psmith@gnu.org>
+
+	* make.h: Added MIN/MAX.
+	* filedef.h: Use them; remove FILE_TIMESTAMP_MIN.
+
+1998-07-30  Paul Eggert  <eggert@twinsun.com>
+
+        Add support for sub-second timestamp resolution on hosts that
+        support it (just Solaris 2.6, so far).
+
+	* acconfig.h (HAVE_ST_MTIM, uintmax_t): New undefs.
+	* acinclude.m4 (jm_AC_HEADER_INTTYPES_H, AC_STRUCT_ST_MTIM,
+        jm_AC_TYPE_UINTMAX_T): New defuns.
+	* commands.c (delete_target): Convert file timestamp to
+        seconds before comparing to archive timestamp.  Extract mod
+        time from struct stat using FILE_TIMESTAMP_STAT_MODTIME.
+	* configure.in (C_STRUCT_ST_MTIM, jm_AC_TYPE_UINTMAX_T): Add.
+        (AC_CHECK_LIB, AC_CHECK_FUNCS): Add clock_gettime.
+	* file.c (snap_deps): Use FILE_TIMESTAMP, not time_t.
+        (file_timestamp_now, file_timestamp_sprintf): New functions.
+        (print_file): Print file timestamps as FILE_TIMESTAMP, not
+        time_t.
+	* filedef.h: Include <inttypes.h> if available and if HAVE_ST_MTIM.
+        (FILE_TIMESTAMP, FILE_TIMESTAMP_STAT_MODTIME, FILE_TIMESTAMP_MIN,
+        FILE_TIMESTAMPS_PER_S, FILE_TIMESTAMP_FROM_S_AND_NS,
+        FILE_TIMESTAMP_DIV, FILE_TIMESTAMP_MOD, FILE_TIMESTAMP_S,
+        FILE_TIMESTAMP_NS, FILE_TIMESTAMP_PRINT_LEN_BOUND): New macros.
+        (file_timestamp_now, file_timestamp_sprintf): New decls.
+        (struct file.last_mtime, f_mtime, file_mtime_1, NEW_MTIME):
+        time_t -> FILE_TIMESTAMP.
+	* implicit.c (pattern_search): Likewise.
+	* vpath.c (vpath_search, selective_vpath_search): Likewise.
+	* main.c (main): Likewise.
+	* remake.c (check_dep, name_mtime, library_search, f_mtime): Likewise.
+        (f_mtime): Use file_timestamp_now instead of `time'.
+        Print file timestamp with file_timestamp_sprintf.
+	* vpath.c (selective_vpath_search): Extract file time stamp from
+        struct stat with FILE_TIMESTAMP_STAT_MODTIME.
+
+1998-07-28  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.77 released.
+
+	* dosbuild.bat: Change to DOS CRLF line terminators.
+
+	* make-stds.texi: Update from latest version.
+
+	* make.texinfo (Options Summary): Clarify that the -r option
+	affects only rules, not builtin variables.
+
+1998-07-27  Paul D. Smith  <psmith@gnu.org>
+
+	* make.h: Make __attribute__ resolve to empty for non-GCC _and_
+	for GCC pre-2.5.x.
+
+	* misc.c (log_access): Print UID/GID's as unsigned long int for
+	maximum portability.
+
+	* job.c (reap_children): Print PIDs as long int for maximum
+	portability.
+
+1998-07-24  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* Makefile.DOS (*_INSTALL, *_UNINSTALL): Replace `true' with `:'.
+
+1998-07-25  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.76.94 released.
+
+1998-07-23  Paul D. Smith  <psmith@gnu.org>
+
+	* config.h.W32.template: Make sure all the #defines of macros here
+	have a value (e.g., use ``#define HAVE_STRING_H 1'' instead of
+	just ``#define HAVE_STRING_H''.  Keeps the preprocessor happy in
+	some contexts.
+
+	* make.h: Remove __attribute__((format...)) stuff; using it with
+	un-prototyped functions causes older GCC's to fail.
+
+	* Version 3.76.93 released.
+
+1998-07-22  Paul D. Smith  <psmith@gnu.org>
+
+	* file.c (print_file_data_base): Fix average calculation.
+
+1998-07-20  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (die): Postpone the chdir() until after
+	remove_intermediates() so that intermediate targets with relative
+	pathnames are removed properly.
+
+1998-07-17  Paul D. Smith  <psmith@gnu.org>
+
+	* filedef.h (struct file): New flag: did we print an error or not?
+
+	* remake.c (no_rule_error): New function to print error messages,
+	extraced from remake_file().
+
+	* remake.c (remake_file): Invoke the new error print function.
+	(update_file_1): Invoke the error print function if we see that we
+	already tried this target and it failed, but that an error wasn't
+	printed for it.  This can happen if a file is included with
+	-include or sinclude and couldn't be built, then later is also
+	the dependency of another target.  Without this change, make just
+	silently stops :-/.
+
+1998-07-16  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo: Removed "beta" version designator.
+	Updated ISBN for the next printing.
+
+1998-07-13  Paul Eggert  <eggert@twinsun.com>
+
+	* acinclude.m4: New AC_LFS macro to determine if special compiler
+	flags are needed to allow access to large files (e.g., Solaris 2.6).
+	* configure.in: Invoke it.
+
+1998-07-08  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* Makefile.DOS: track changes in Makefile.in.
+
+1998-07-07  Paul D. Smith  <psmith@gnu.org>
+
+	* remote-cstms.c (start_remote_job): Move gethostbyaddr() to the
+	top so host is initialized early enough.
+
+	* acinclude.m4: New file.  Need some special autoconf macros to
+	check for network libraries (-lsocket, -lnsl, etc.) when
+	configuring Customs.
+
+	* configure.in (make_try_customs): Invoke new network libs macro.
+
+1998-07-06  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.76.92 released.
+
+	* README.customs: Added to the distribution.
+
+	* configure.in (make_try_customs): Rewrite to require an installed
+	Customs library, rather than looking at the build directory.
+
+	* Makefile.am (man_MANS): Install make.1.
+	* make.1: Renamed from make.man.
+
+	* make.texinfo (Bugs): New mailing list address for GNU make bug
+	reports.
+
+1998-07-02  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.76.91 released.
+
+	* default.c: Added default rule for new-style RCS master file
+	storage; ``% :: RCS/%''.
+	Added default rules for DOS-style C++ files with suffix ".cpp".
+	They use the new LINK.cpp and COMPILE.cpp macros, which are set by
+	default to be equal to LINK.cc and COMPILE.cc.
+
+1998-06-19  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* job.c (start_job_command): Reset execute_by_shell after an empty
+        command was skipped.
+
+1998-06-09  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Keep track of the temporary filename created when
+	reading a makefile from stdin (-f-) and attempt to remove it
+	as soon as we know we're not going to re-exec.  If we are, add it
+	to the exec'd make's cmd line with "-o" so the exec'd make doesn't
+	try to rebuild it.  We still have a hole: if make re-execs then
+	the temporary file will never be removed.  To fix this we'd need
+	a brand new option that meant "really delete this".
+	* AUTHORS, getopt.c, getopt1.c, getopt.h, main.c (print_version):
+	Updated mailing addresses.
+
+1998-06-08  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Andreas Luik <luik@isa.de> points out that the
+	check for makefile :: rules with commands but no dependencies
+	causing a loop terminates incorrectly.
+
+	* maintMakefile: Make a template for README.DOS to update version
+	numbers.
+
+1998-05-30  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* remake.c (update_file_1): Don't free the memory for the
+	dependency structure when dropping a circular dependency.
+
+1998-05-30  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* dir.c (file_exists_p, file_impossible_p, file_impossible)
+	[__MSDOS__, WINDOWS32]: Retain trailing slash in "d:/", and make
+	dirname of "d:foo" be "d:".
+
+1998-05-26  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* read.c (read_makefile): Avoid running past EOS when scanning
+	file name after `include'.
+
+1998-05-26  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* make.texinfo (Flavors): Correct description of conditional
+	assignment, which is not equivalent to ifndef.
+	(Setting): Likewise.
+
+1998-05-24  Paul D. Smith  <psmith@gnu.org>
+
+	* arscan.c (ar_name_equal): strncmp() might be implemented as a
+	macro, so don't put preprocessor conditions inside the arguments
+	list.
+
+1998-05-23  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* read.c (read_makefile) [__MSDOS__, WINDOWS32]: Skip colons in
+	drive specs when parsing targets, target-specific variables and
+	static pattern rules.  A colon can only be part of drive spec if
+	it is after the first letter in a token.
+
+1998-05-22  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* remake.c (f_mtime) [__MSDOS__]: Allow up to 3 sec of skew before
+	yelling bloody murder.
+
+	* dosbuild.bat: Use -DINCLUDEDIR= and -DLIBDIR= where appropriate.
+
+	* read.c (parse_file_seq): Combine the special file-handling code
+	for WINDOWS32 and __MSDOS__ into a single snippet.
+	(get_next_mword) [__MSDOS__, WINDOWS32]: Allow a word to include a
+	colon as part of a drive spec.
+
+	* job.c (batch_mode_shell) [__MSDOS__]: Declare.
+
+1998-05-20  Paul D. Smith  <psmith@gnu.org>
+
+	* Version 3.76.90 released.
+
+1998-05-19  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo (Make Errors): Added a new appendix describing
+	common errors make might generate and how to resolve them (or at
+	least more information on what they mean).
+
+	* maintMakefile (NMAKEFILES): Use the new automake 1.3 feature
+	to create a dependency file to construct Makefile.DOS, SMakefile,
+	and NMakefile.
+	(.dep_segment): Generate the dependency fragment file.
+
+1998-05-14  Paul D. Smith  <psmith@gnu.org>
+
+	* make.man: Minor changes.
+
+1998-05-13  Paul D. Smith  <psmith@gnu.org>
+
+	* function.c (pattern_matches,expand_function): Change variables
+	and types named "word" to something else, to avoid compilation
+	problems on Cray C90 Unicos.
+	* variable.h: Modify the function prototype.
+
+1998-05-11  Rob Tulloh  <rob_tulloh@tivoli.com>
+
+	* job.c (construct_command_argv_internal) [WINDOWS32]: Turn off
+	echo when using a batch file, and make sure the command ends in a
+	newline.
+
+1998-05-03  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in (make_try_customs): Add some customs flags if the
+	user configures custom support.
+
+	* job.c, remote-cstms.c: Merge in changes for custom library.
+
+	* remote-stub.c: Add option to stub start_remote_job_p().
+
+1998-05-01  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (f_mtime): Install VPATH+ handling for archives; use
+	the hname field instead of the name field, and rehash when
+	appropriate.
+
+1998-04-30  Paul D. Smith  <psmith@gnu.org>
+
+	* rule.c (print_rule_data_base): Print out any pattern-specific
+	variable values into the rules database.
+
+	* variable.c (print_variable_set): Make this variable extern, to
+	be called by print_rule_data_base() for pattern-specific variables.
+
+	* make.texinfo (Pattern-specific): Document pattern-specific
+	variables.
+
+1998-04-29  Paul D. Smith  <psmith@gnu.org>
+
+	* expand.c (variable_expand_for_file): Make static; its only
+	called internally.  Look up this target in the list of
+	pattern-specific variables and insert the variable set into the
+	queue to be searched.
+
+	* filedef.h (struct file): Add a new field to hold the
+	previously-found pattern-specific variable reference.  Add a new
+	flag to remember whether we already searched for this file.
+
+	* rule.h (struct pattern_var): New structure for storing
+	pattern-specific variable values.  Define new function prototypes.
+
+	* rule.c: New variables pattern_vars and last_pattern_var for
+	storage and handling of pattern-specific variable values.
+	(create_pattern_var): Create a new pattern-specific variable value
+	structure.
+	(lookup_pattern_var): Try to match a target to one of the
+	pattern-specific variable values.
+
+1998-04-22  Paul D. Smith  <psmith@gnu.org>
+
+	* make.texinfo (Target-specific): Document target-specific
+	variables.
+
+1998-04-21  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (define_variable_in_set): Made globally visible.
+	(lookup_variable_in_set): New function: like lookup_variable but
+	look only in a specific variable set.
+	(target_environment): Use lookup_variable_in_set() to get the
+	correct export rules for a target-specific variable.
+	(create_new_variable_set): Create a new variable set, and just
+	return it without installing it anywhere.
+	(push_new_variable_scope): Reimplement in terms of
+	create_new_variable_set.
+
+	* read.c (record_target_var): Like record_files, but instead of
+	files create a target-specific variable value for each of the
+	listed targets.  Invoked from read_makefile() when the target line
+	turns out to be a target-specific variable assignment.
+
+1998-04-19  Paul D. Smith <psmith@gnu.org>
+
+	* read.c (read_makefile): Rewrite the entire target parsing
+	section to implement target-specific variables.  In particular, we
+	cannot expand the entire line as soon as it's read in, since we
+	may want to evaluate parts of it with different variable contexts
+	active.  Instead, start expanding from the beginning until we find
+	the `:' (or `::'), then determine what kind of line this is and
+	continue appropriately.
+
+	* read.c (get_next_mword): New function to parse a makefile line
+	by "words", considering an entire variable or function as one
+	word.  Return the type read in, along with its starting position
+	and length.
+	(enum make_word_type): The types of words that are recognized by
+	get_next_mword().
+
+	* variable.h (struct variable): Add a flag to specify a per-target
+	variable.
+
+	* expand.c: Make variable_buffer global.  We need this during the
+	new parsing of the makefile.
+	(variable_expand_string): New function.  Like variable_expand(),
+	but start at a specific point in the buffer, not the beginning.
+	(variable_expand): Rewrite to simply call variable_expand_string().
+
+1998-04-13  Paul D. Smith  <psmith@gnu.org>
+
+	* remake.c (update_goal_chain): Allow the rebuilding makefiles
+	step to use parallel jobs.  Not sure why this was disabled:
+	hopefully we won't find out :-/.
+
+1998-04-11  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Set the CURDIR makefile variable.
+	* make.texinfo (Recursion): Document it.
+
+1998-03-17  Paul D. Smith  <psmith@gnu.org>
+
+	* misc.c (makefile_fatal): If FILE is nil, invoke plain fatal().
+	* variable.c (try_variable_definition): Use new feature.
+
+1998-03-10  Paul D. Smith  <psmith@gnu.org>
+
+	* main.c (main): Don't pass included, rebuilt makefiles to
+	re-exec'd makes with -o.  Reopens a possible loop, but it caused
+	too many problems.
+
+1998-03-02  Paul D. Smith  <psmith@gnu.org>
+
+	* variable.c (try_variable_definition): Implement ?=.
+	* make.texinfo (Setting): Document it.
+
+1998-02-28  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* job.c (start_job_command): Reset execute_by_shell after an empty
+        command, like ":", has been seen.
+
+Tue Oct 07 15:00:00 1997  Phil Brooks <phillip_brooks@hp.com>
+
+	* make.h [WINDOWS32]: make case sensitivity configurable
+	* dir.c [WINDOWS32]: make case sensitivity configurable
+	* README.W32: Document case sensitivity
+	* config.ami: Share case warping code with Windows
+
+Mon Oct  6 18:48:45 CDT 1997 Rob Tulloh <rob_tulloh@dev.tivoli.com>
+
+	* w32/subproc/sub_proc.c: Added support for MKS toolkit shell
+	(turn on HAVE_MKS_SHELL).
+	* read.c [WINDOWS32]: Fixed a problem with multiple target rules
+ 	reported by Gilbert Catipon (gcatipon@tibco.com).  If multiple
+ 	path tokens in a rule did not have drive letters, make would
+ 	incorrectly concatenate the 2 tokens together.
+	* main.c/variable.c [WINDOWS32]: changed SHELL detection code to
+ 	follow what MSDOS did. In addition to watching for SHELL variable
+ 	updates, make's main will attempt to default the value of SHELL
+ 	before and after makefiles are parsed.
+	* job.c/job.h [WINDOWS32]: The latest changes made to enable use
+ 	of the GNUWIN32 shell from make could cause make to fail due to a
+ 	concurrency condition between parent and child processes.  Make
+ 	now creates a batch file per job instead of trying to reuse the
+ 	same singleton batch file.
+	* job.c/job.h/function.c/config.h.W32 [WINDOWS32]: Renamed macro
+ 	from HAVE_CYGNUS_GNUWIN32_TOOLS to BATCH_MODE_ONLY_SHELL. Reworked
+ 	logic to reduce complexity. WINDOWS32 now uses the unixy_shell
+ 	variable to detect Bourne-shell compatible environments. There is
+ 	also a batch_mode_shell variable that determines whether not
+ 	command lines should be executed via script files. A WINDOWS32
+ 	system with no sh.exe installed would have unixy_shell set to
+ 	FALSE and batch_mode_shell set to TRUE. If you have a unixy shell
+ 	that does not behave well when invoking things via 'sh -c xxx',
+ 	you may want to turn on BATCH_MODE_ONLY_SHELL and see if things
+ 	improve.
+	* NMakefile: Added /D DEBUG to debug build flags so that unhandled
+ 	exceptions could be debugged.
+
+Mon Oct  6 00:04:25 1997  Rob Tulloh <rob_tulloh@dev.tivoli.com>
+
+	* main.c [WINDOWS32]: The function define_variable() does not
+ 	handle NULL. Test before calling it to set Path.
+	* main.c [WINDOWS32]: Search Path again after makefiles have been
+	parsed to detect sh.exe.
+	* job.c [WINDOWS32]: Added support for Cygnus GNU WIN32 tools.
+	To use, turn on HAVE_CYGNUS_GNUWIN32_TOOLS in config.h.W32.
+	* config.h.W32: Added HAVE_CYGNUS_GNUWIN32_TOOLS macro.
+
+Sun Oct  5 22:43:59 1997  John W. Eaton <jwe@bevo.che.wisc.edu>
+
+	* glob/glob.c (glob_in_dir) [VMS]: Globbing shouldn't be
+	case-sensitive.
+	* job.c (child_execute_job) [VMS]: Use a VMS .com file if the
+	command contains a newline (e.g. from a define/enddef block).
+	* vmsify.c (vmsify): Return relative pathnames wherever possible.
+	* vmsify.c (vmsify): An input string like "../.." returns "[--]".
+
+Wed Oct  1 15:45:09 1997  Rob Tulloh <rob_tulloh@tivoli.com>
+
+	* NMakefile: Changed nmake to $(MAKE).
+	* subproc.bat: Take the make command name from the command
+	line. If no command name was given, default to nmake.
+	* job.c [MSDOS, WINDOWS32]: Fix memory stomp: temporary file names
+	are now always created in heap memory.
+	* w32/subproc/sub_proc.c: New implementation of make_command_line()
+	which is more compatible with different Bourne shell implementations.
+	Deleted the now obsolete fix_command_line() function.
+	* main.c [WINDOWS32]: Any arbitrary spelling of Path can be
+	detected. Make will ensure that the special spelling `Path' is
+	inserted into the environment when the path variable is propagated
+	within itself and to make's children.
+	* main.c [WINDOWS32]: Detection of sh.exe was occurring too
+	soon. The 2nd check for the existence of sh.exe must come after
+	the call to read_all_makefiles().
+
+Fri Sep 26 01:14:18 1997  <zinser@axp602.gsi.de>
+
+	* makefile.com [VMS]: Fixed definition of sys.
+	* readme.vms: Comments on what's changed lately.
+
+Fri Sep 26 01:14:18 1997  John W. Eaton <jwe@bevo.che.wisc.edu>
+
+	* read.c (read_all_makefiles): Allow make to find files named
+	"MAKEFILE" with no extension on VMS.
+	* file.c (lookup_file): Lowercase filenames on VMS.
+
+1997-09-29  Paul D. Smith  <psmith@baynetworks.com>
+
+	* read.c (read_makefile): Reworked target detection again; the old
+	version had an obscure quirk.
+
+Fri Sep 19 09:20:49 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* Version 3.76.1 released.
+
+	* Makefile.am: Add loadavg files to clean rules.
+
+	* configure.in (AC_OUTPUT): Remove stamp-config; no longer needed.
+	* Makefile.ami (distclean): Ditto.
+	* SMakefile (distclean): Ditto.
+
+	* main.c (main): Arg count should be int, not char!  Major braino.
+
+Tue Sep 16 10:18:22 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* Version 3.76 released.
+
+Tue Sep  2 10:07:39 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* function.c (expand_function): When processing $(shell...)
+  	translate a CRLF (\r\n) sequence as well as a newline (\n) to a
+ 	space.  Also remove an ending \r\n sequence.
+	* make.texinfo (Shell Function): Document it.
+
+Fri Aug 29 12:59:06 1997  Rob Tulloh  <rob_tulloh@tivoli.com>
+
+	* w32/pathstuff.c (convert_Path_to_windows32): Fix problem where
+ 	paths which contain single character entries like `.' are not
+ 	handled correctly.
+
+	* README.W32: Document path handling issues on Windows systems.
+
+Fri Aug 29 02:01:27 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* Version 3.75.93.
+
+Thu Aug 28 19:39:06 1997  Rob Tulloh  <rob_tulloh@tivoli.com>
+
+	* job.c (exec_command) [WINDOWS32]: If exec_command() is invoked
+ 	from main() to re-exec make, the call to execvp() would
+ 	incorrectly return control to parent shell before the exec'ed
+ 	command could run to completion. I believe this is a feature of
+ 	the way that execvp() is implemented on top of WINDOWS32 APIs. To
+ 	alleviate the problem, use the supplied process launch function in
+ 	the sub_proc library and suspend the parent process until the
+ 	child process has run.  When the child exits, exit the parent make
+ 	with the exit code of the child make.
+
+Thu Aug 28 17:04:47 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* Makefile.DOS.template (distdir): Fix a line that got wrapped in
+	email.
+
+	* Makefile.am (loadavg): Give the necessary cmdline options when
+	linking loadavg.
+
+	* configure.in: Check for pstat_getdynamic for getloadvg on HP.
+
+	* job.c (start_job_command) [VMS, _AMIGA]: Don't perform empty
+	command optimization on these systems; it doesn't make sense.
+
+Wed Aug 27 17:09:32 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* Version 3.75.92
+
+Tue Aug 26 11:59:15 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* main.c (print_version): Add '97 to copyright years.
+
+	* read.c (do_define): Check the length of the array before looking
+	at a particular offset.
+
+	* job.c (construct_command_argv_internal): Examine the last byte
+	of the previous arg, not the byte after that.
+
+Sat Aug 23 1997  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* Makefile.DOS.template: New file (converted to Makefile.DOS in
+	the distribution).
+
+	* configure.bat: Rewrite to use Makefile.DOS instead of editing
+        Makefile.in.  Add support for building from outside of the source
+        directory.  Fail if the environment block is too small.
+
+	* configh.dos: Use <sys/config.h>.
+
+	* README.DOS: Update instructions.
+
+Fri Aug 22 1997  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* job.c (start_job_command) [__MSDOS__]: Don't test for "/bin/sh"
+        literally, use value of unixy_shell instead.
+
+	* filedef.h (NEW_MTIME): Use 1 less than maximum possible value if
+        time_t is unsigned.
+
+Sat Aug 16 00:56:15 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* vmsify.c (vmsify, case 11): After translating `..' elements, set
+        nstate to N_OPEN if there are still more elements to process.
+        (vmsify, case 2): After translating `foo/bar' up to the slash,
+        set nstate to N_OPEN, not N_DOT.
+
+Fri Aug  8 15:18:09 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* dir.c (vmsstat_dir): Leave name unmodified on exit.
+	* make.h (PATH_SEPARATOR_CHAR): Set to comma for VMS.
+	* vpath.c: Fix comments to refer to path separator, not colon.
+        (selective_vpath_search): Avoid Unixy slash handling for VMS.
+
+Thu Aug  7 22:24:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* ar.c [VMS]: Don't declare ar_member_touch.
+	Delete VMS version of ar_member_date.
+	Enable non-VMS versions of ar_member_date and ar_member_date_1 for
+	VMS too.
+	* arscan.c (VMS_get_member_info): New function.
+	(ar_scan): Provide version for VMS systems.
+	(ar_name_equal): Simply compare name and mem on VMS systems.
+	Don't define ar_member_pos or ar_member_touch on VMS systems.
+
+	* config.h-vms (pid_t, uid_t): Don't define.
+
+	* remake.c: Delete declaration of vms_stat.
+	(name_mtime): Don't call vms_stat.
+	(f_mtime) [VMS]: Funky time value manipulation no longer necessary.
+
+	* file.c (print_file): [VMS] Use ctime, not cvt_time.
+
+	* make.h [VMS]: Don't define POSIX.
+
+	* makefile.com (filelist): Include ar and arscan.
+	Also include them in the link commands.
+	Don't define NO_ARCHIVES in cc command.
+
+	* makefile.vms (ARCHIVES, ARCHIVES_SRC): Uncomment.
+	(defines): Delete NO_ARCHIVES from list.
+
+	* remake.c (f_mtime): Only check to see if intermediate file is
+	out of date if it also exists (i.e., mtime != (time_t) -1).
+
+	* vmsdir.h (u_long, u_short): Skip typedefs if using DEC C.
+
+Fri Jun 20 23:02:07 1997  Rob Tulloh  <rob_tulloh@tivoli.com>
+
+	* w32/subproc/sub_proc.c: Get W32 sub_proc to handle shebang
+	(#!/bin/sh) in script files correctly.
+	Fixed a couple of memory leaks.
+	Fixed search order in find_file() (w32/subproc/sub_proc.c) so that
+	files with extensions are preferred over files without extensions.
+	Added search for files with .cmd extension too.
+	* w32/subproc/misc.c (arr2envblk): Fixed memory leak.
+
+Mon Aug 18 09:41:08 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* Version 3.75.91
+
+Fri Aug 15 13:50:54 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* read.c (do_define): Remember to count the newline after the endef.
+
+Thu Aug 14 23:14:37 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* many: Rewrote builds to use Automake 1.2.
+
+	* AUTHORS: New file.
+	* maintMakefile: Contains maintainer-only make snippets.
+	* GNUmakefile: This now only runs the initial auto* tools.
+	* COPYING,texinfo.tex,mkinstalldirs,install-sh: Removed (obtained
+	automatically by automake).
+	* compatMakefile: Removed (not needed anymore).
+	* README,build.sh.in: Removed (built from templates).
+	* config.h.in,Makefile.in: Removed (built by tools).
+
+Wed Aug 13 02:22:08 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* make.texinfo: Updates for DOS/Windows information (Eli Zaretskii)
+	* README,README.DOS: Ditto.
+
+	* remake.c (update_file_1,f_mtime): Fix GPATH handling.
+	* vpath.c (gpath_search): Ditto.
+
+	* file.c (rename_file): New function: rehash, but also rename to
+	the hashname.
+	* filedef.h: Declare it.
+
+	* variable.c (merge_variable_set_lists): Remove free() of variable
+	set; since various files can share variable sets we don't want to
+	free them here.
+
+Tue Aug 12 10:51:54 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* configure.in: Require autoconf 2.12
+
+	* make.texinfo: Replace all "cd subdir; $(MAKE)" examples with a
+	more stylistically correct "cd subdir && $(MAKE)".
+
+	* main.c: Global variable `clock_skew_detected' defined.
+	(main): Print final warning if it's set.
+	* make.h: Declare it.
+	* remake.c (f_mtime): Test and set it.
+
+	* job.c (start_job_command): Add special optimizations for
+ 	"do-nothing" rules, containing just the shell no-op ":".  This is
+ 	useful for timestamp files and can make a real difference if you
+ 	have a lot of them (requested by Fergus Henderson <fjh@cs.mu.oz.au>).
+
+	* configure.in,Makefile.in: Rewrote to use the new autoconf
+	program_transform_name macro.
+
+	* function.c (function_strip): Strip newlines as well as spaces
+	and TABs.
+
+Fri Jun  6 23:41:04 1997  Rob Tulloh <rob_tulloh@tivoli.com>
+
+	* remake.c (f_mtime): Datestamps on FAT-based files are rounded to
+	even seconds when stored, so if the date check fails on WINDOWS32
+	 systems, see if this "off-by-one" error is the problem.
+
+	* General: If your TZ environment variable is not set correctly
+	then all your timestamps will be off by hours.  So, set it!
+
+Mon Apr  7 02:06:22 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* Version 3.75.1
+
+	* compatMakefile (objs): Define & use the $(GLOB) variable so
+	that it's removed correctly from build.sh.in when it's built.
+
+	* configure.in: On Solaris we can use the kstat_*() functions to
+	get load averages without needing special permissions.  Add a
+	check for -lkstat to see if we have it.
+
+	* getloadavg.c (getloadavg): Use HAVE_LIBKSTAT instead of SUN5 as
+	the test to enable kstat_open(), etc. processing.
+
+Fri Apr  4 20:21:18 1997  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* <lots>: Fixes to work in the DJGPP DOS environment.
+
+Mon Mar 31 02:42:52 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* function.c (expand_function): Added new function $(wordlist).
+
+	* make.texinfo (Filename Functions): Document $(wordlist) function.
+
+	* vpath.c (build_vpath_lists): Construct the GPATH variable
+	information in the same manner we used to construct VPATH.
+	(gpath_search): New function to search GPATH.
+
+	* make.h: Declare the new function.
+
+	* remake.c (update_file_1): Call it, and keep VPATH if it's found.
+
+	* make.texinfo (Search Algorithm): Document GPATH variable.
+
+Sun Mar 30 20:57:16 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* main.c (handle_non_switch_argument): Defined the MAKECMDGOALS
+	variable to contain the user options passed in on the cmd line.
+
+	* make.texinfo (Goals): Document MAKECMDGOALS variable.
+
+	* remake.c (f_mtime): Print a warning if we detect a clock skew
+	error, rather than failing.
+
+	* main.c (main): If we rebuild any makefiles and need to re-exec,
+	add "-o<mkfile>" options for each makefile rebuilt to avoid
+	infinite looping.
+
+Fri Mar 28 15:26:05 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* job.c (construct_command_argv_internal): Track whether the last
+	arg in the cmd string was empty or not (Roland).
+	(construct_command_argv_internal): If the shell line is empty,
+	don't do anything (Roland).
+
+	* glob/glob.h,glob/glob.c,glob/fnmatch.c,glob/fnmatch.h: Install
+	the latest changes from the GLIBC version of glob (Ulrich Drepper).
+
+	* getloadavg.c,make-stds.texi: New version (Roland).
+
+	* (ALL): Changed WIN32 to W32 or WINDOWS32 (RMS).
+
+Mon Mar 24 15:33:34 1997  Rob Tulloh  <rob_tulloh@tivoli.com>
+
+	* README.W32: Describe preliminary FAT support.
+
+	* build_w32.bat: Use a variable for the final exe name.
+
+	* dir.c (find_directory): W32: Find the filesystem type.
+	(dir_contents_file_exists_p): W32: for FAT filesystems, always
+	rehash since FAT doesn't change directory mtime on change.
+
+	* main.c (handle_runtime_exceptions): W32: Add an
+ 	UnhandledExceptionFilter so that when make bombs due to ^C or a
+ 	bug, it won't cause a GUI requestor to pop up unless debug is
+ 	turned on.
+	(main): Call it.
+
+Mon Mar 24 00:57:34 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* configure.in, config.h.in, config.ami, config.h-vms, config.h.w32:
+ 	Check for memmove() function.
+
+	* make.h (bcopy): If memmove() available, define bcopy() to use it.
+	Otherwise just use bcopy().  Don't use memcpy(); it's not guaranteed
+	to handle overlapping moves.
+
+	* read.c (read_makefile): Fix some uninitialized memory reads
+	(reported by Purify).
+
+	* job.c (construct_command_argv_internal): Use bcopy() not
+	strcpy(); strcpy() isn't guaranteed to handle overlapping moves.
+
+	* Makefile.in: Change install-info option ``--infodir'' to
+	``--info-dir'' for use with new texinfo.
+
+	* function.c (expand_function): $(basename) and $(suffix) should
+	only search for suffixes as far back as the last directory (e.g.,
+	only the final filename in the path).
+
+Sun Mar 23 00:13:05 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* make.texinfo: Add @dircategory/@direntry information.
+	(Top): Remove previous reference to (dir) (from RMS).
+	(Static Usage): Add "all:" rule to example.
+	(Automatic Dependencies): fix .d file creation example.
+
+	* Install VPATH+ patch:
+
+	* filedef.h (struct file): Add in hname field to store the hashed
+        filename, and a flag to remember if we're using the vpath filename
+	or not.  Renamed a few functions for more clarity.
+
+	* file.c (lookup_file,enter_file,file_hash_enter): Store filenames
+	in the hash table based on their "hash name".  We can change this
+	while keeping the original target in "name".
+	(rehash_file): Renamed from "rename_file" to be more accurate.
+	Changes the hash name, but not the target name.
+
+	* remake.c (update_file_1): Modify -d output for more detailed
+ 	VPATH info.  If we don't need to rebuild, use the VPATH name.
+	(f_mtime): Don't search for vpath if we're ignoring it.  Call
+ 	renamed function rehash_file.  Call name_mtime instead of
+ 	file_mtime, to avoid infinite recursion since the file wasn't
+ 	actually renamed.
+
+	* implicit.c (pattern_search): if we find an implicit file in
+	VPATH, save the original name not the VPATH name.
+
+	* make.texinfo (Directory Search): Add a section on the new VPATH
+	functionality.
+
+Sun Dec  1 18:36:04 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* dir.c (file_exists_p, file_impossible, file_impossible_p): If
+	dirname is empty replace it by the name of the root directory.
+	Note that this doesn't work (yet) for W32, Amiga, or VMS.
+
+Tue Oct 08 13:57:03 1996  Rob Tulloh  <tulloh@tivoli.com>
+
+	* main.c (main): W32 bug fix for PATH vars.
+
+Tue Sep 17 1996  Paul Eggert  <eggert@twinsun.com>
+
+	* filedef.h (NEW_MTIME): Don't assume that time_t is a signed
+ 	32-bit quantity.
+
+	* make.h: (CHAR_BIT, INTEGER_TYPE_SIGNED, INTEGER_TYPE_MAXIMUM,
+ 	INTEGER_TYPE_MINIMUM): New macros.
+
+Tue Aug 27 01:06:34 1996  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* Version 3.75 released.
+
+	* main.c (print_version): Print out bug-reporting address.
+
+Mon Aug 26 19:55:47 1996  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* main.c (print_data_base): Don't declare ctime; headers do it for us
+ 	already.
+
+Sun Jul 28 15:37:09 1996  Rob Tulloh (tulloh@tivoli.com)
+
+	* w32/pathstuff.c: Turned convert_vpath_to_w32() into a
+	real function. This was done so that VPATH could contain
+	white space separated pathnames. Please note that directory
+	paths (in VPATH/vpath context) containing white space are not
+	supported (just as they are not under Unix). See README.W32
+	for suggestions.
+
+	* w32/include/pathstuff.h: Added prototype for the new
+	function convert_vpath_to_w32. Deleted macro for same.
+
+	* README.W32: Added some notes about why I chose not to try
+	and support pathnames which contain white space and some
+	workaround suggestions.
+
+Thu Jul 25 19:53:31 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* GNUmakefile (mkdep-nolib): Use -MM option unconditionally.
+
+	* Version 3.74.7.
+
+	* main.c (define_makeflags): Back up P to point at null terminator
+	when killing final space and dash before setting MFLAGS.
+
+	From Robert Hoehne <robert.hoehne@Mathematik.TU-Chemnitz.DE>:
+	* dir.c [__MSDOS__ && DJGPP > 1]: Include <libc/dosio.h> and defin
+	`__opendir_flags' initialized to 0.
+	(dosify) [__MSDOS__ && DJGPP > 1]: Return name unchanged if _USE_LFN.
+	(find_directory) [__MSDOS__ && DJGPP > 1]: If _USE_LGN, set
+	__opendir_flags to __OPENDIR_PRESERVE_CASE.
+
+	* vmsfunctions.c (vms_stat): `sys$dassgn (DevChan);' added by kkaempf.
+
+	* GNUmakefile (w32files): Add NMakefile.
+
+	* NMakefile (LDFLAGS_debug): Value fixed by tulloh.
+
+Sat Jul 20 12:32:10 1996  Klaus Kämpf (kkaempf@progis.de)
+
+	* remake.c (f_mtime) [VMS]: Add missing `if' conditional for future
+	modtime check.
+	* config.h-vms, makefile.vms, readme.vms, vmsify.c: Update address.
+
+Sat Jul 20 05:29:43 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* configure.in: Require autoconf 2.10 or later.
+
+Fri Jul 19 16:57:27 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* Version 3.74.6.
+
+	* GNUmakefile (w32files): New variable.
+	(distfiles): Add it.
+	* w32: Updated by Rob Tulloh.
+
+	* makefile.vms (LOADLIBES): Fix typo.
+
+Sun Jul 14 12:59:27 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* job.c (construct_command_argv_internal): Fix up #else, #endifs.
+
+	* configh.dos: Define HAVE_DIRENT_H instead of DIRENT.
+
+	* remake.c (f_mtime): Don't compare MTIME to NOW if MTIME == -1.
+
+	* Version 3.74.5.
+
+	* main.c (main): Exit with status 2 when update_goal_chain returns 2.
+
+Sat Jun 22 14:56:05 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* configure.in: Don't check for _sys_siglist.
+	* make.h [HAVE__SYS_SIGLIST]: Don't test this; just punt if there is
+	no strsignal or sys_siglist.
+
+	* read.c (conditional_line): Strip ws in `ifeq (a , b)' so it is the
+	same as `ifeq (a, b)'.
+
+	* job.c (reap_children): Don't call die if handling_fatal_signal.
+
+	* file.c (file_hash_enter): Allow renaming :: to : when latter is
+	non-target, or : to :: when former is non-target.
+
+	* job.c (start_job_command): Call block_sigs.
+	(block_sigs): New function, broken out of start_job_command.
+	(reap_children): Block fatal signals around removing dead child from
+	chain and adjusting job_slots_used.
+	* job.h: Declare block_sigs.
+
+	* remote-stub.c (remote_setup, remote_cleanup): New (empty) functions.
+	* main.c (main): Call remote_setup.
+	(die): Call remote_cleanup.
+
+	* job.c (reap_children): Quiescent value of shell_function_pid is
+	zero, not -1.
+
+	* main.c (print_version): Add 96 to copyright years.
+
+Sat Jun 15 20:30:01 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* read.c (find_char_unquote): Avoid calling strlen on every call
+	just to throw away the value most of the time.
+
+Sun Jun  2 12:24:01 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* main.c (decode_env_switches): Prepend '-' to ARGV[1] if it contains
+	no '=', regardless of ARGC.
+	(define_makeflags): Elide leading '-' from MAKEFLAGS value if first
+	word is short option, regardless of WORDS.
+
+Wed May 22 17:24:51 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* makefile.vms: Set LOADLIBES.
+	* makefile.com (link_using_library): Fix typo.
+
+Wed May 15 17:37:26 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* dir.c (print_dir_data_base): Use %ld dev and ino and cast them to
+	long.
+
+Wed May 15 10:14:14 CDT 1996  Rob Tulloh  <tulloh@tivoli.com>
+
+	* dir.c: W32 does not support inode. For now, fully qualified
+	pathname along with st_mtime will be keys for files.
+	Fixed problem where vpath can be confused when files
+	are added to a directory after the directory has already been
+	read in. The code now attempts to reread the directory if it
+	discovers that the datestamp on the directory has changed since
+	it was cached by make. This problem only seems to occur on W32
+	right now so it is lumped under port #ifdef WINDOWS32.
+
+	* function.c: W32: call subproc library (CreateProcess()) instead of
+	fork/exec.
+
+	* job.c: W32: Added the code to do fork/exec/waitpid style processing
+	on W32 systems via calls to subproc library.
+
+	* main.c: W32: Several things added here. First, there is code
+	for dealing with PATH and SHELL defaults. Make tries to figure
+	out if the user has %PATH% set in the environment and sets it to
+	%Path% if it is not set already. Make also looks to see if sh.exe
+	is anywhere to be found. Code path through job.c will change
+	based on existence of a working Bourne shell. The checking for
+	default shell is done twice: once before makefiles are read in
+	and again after. Fall back to MSDOS style execution mode if no sh.exe
+	is found. Also added some debug support that allows user to pause make
+	with -D switch and attach a debugger. This is especially useful for
+	debugging recursive calls to make where problems appear only in the
+	sub-make.
+
+	* make.h: W32: A few macros and header files for W32 support.
+
+	* misc.c: W32: Added a function end_of_token_w32() to assist
+	in parsing code in read.c.
+
+	* read.c: W32: Fixes similar to MSDOS which allow colon to
+	appear in filenames. Use of colon in filenames would otherwise
+	confuse make.
+
+	* remake.c: W32: Added include of io.h to eliminate compiler
+	warnings. Added some code to default LIBDIR if it is not set
+	on W32.
+
+	* variable.c: W32: Added support for detecting Path/PATH
+	and converting them to semicolon separated lists for make's
+	internal use. New function sync_Path_environment()
+	which is called in job.c and function.c before creating a new
+	process. Caller must set Path in environment since we don't
+	have fork() to do this for us.
+
+	* vpath.c: W32: Added detection for filenames containing
+	forward or backward slashes.
+
+	* NMakefile: W32: Visual C compatible makefile for use with nmake.
+	Use this to build GNU make the first time on Windows NT or Windows 95.
+
+	* README.W32: W32: Contains some helpful notes.
+
+	* build_w32.bat: W32: If you don't like nmake, use this the first
+	time you build GNU make on Windows NT or Windows 95.
+
+	* config.h.W32: W32 version of config.h
+
+	* subproc.bat: W32: A bat file used to build the
+	subproc library from the top-level NMakefile. Needed because
+	WIndows 95 (nmake) doesn't allow you to cd in a make rule.
+
+	* w32/include/dirent.h
+	* w32/compat/dirent.c: W32: opendir, readdir, closedir, etc.
+
+	* w32/include/pathstuff.h: W32: used by files needed functions
+	defined in pathstuff.c (prototypes).
+
+	* w32/include/sub_proc.h: W32: prototypes for subproc.lib functions.
+
+	* w32/include/w32err.h: W32: prototypes for w32err.c.
+
+	* w32/pathstuff.c: W32: File and Path/Path conversion functions.
+
+	* w32/subproc/build.bat: W32: build script for subproc library
+	if you don't wish to use nmake.
+
+	* w32/subproc/NMakefile: W32: Visual C compatible makefile for use
+	with nmake. Used to build subproc library.
+
+	* w32/subproc/misc.c: W32: subproc library support code
+	* w32/subproc/proc.h: W32: subproc library support code
+	* w32/subproc/sub_proc.c: W32: subproc library source code
+	* w32/subproc/w32err.c: W32: subproc library support code
+
+Mon May 13 14:37:42 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* Version 3.74.4.
+
+	* GNUmakefile (vmsfiles): Fix typo.
+
+	* GNUmakefile (amigafiles): Add amiga.h.
+
+Sun May 12 19:19:43 1996  Aaron Digulla   <digulla@fh-konstanz.de>
+
+	* dir.c: New function: amigafy() to fold filenames
+	Changes HASH() to HASHI() to fold filenames on Amiga.
+	Stringcompares use strieq() instead of streq()
+	The current directory on Amiga is "" instead of "."
+	* file.c: Likewise.
+
+	* amiga.c: New function wildcard_expansion(). Allows to use
+	Amiga wildcards with $(wildcard )
+
+	* amiga.h: New file. Prototypes for amiga.c
+
+	* function.c: Use special function wildcard_expansion() for
+	$(wildcard ) to allow Amiga wildcards
+	The current directory on Amiga is "" instead of "."
+
+	* job.c: No Pipes on Amiga, too
+	(load_too_high) Neither on Amiga
+	ENV variable on Amiga are in a special directory and are not
+	passed as third argument to main().
+
+	* job.h: No envp on Amiga
+
+	* make.h: Added HASHI(). This is the same as HASH() but converts
+	it's second parameter to lowercase on Amiga to fold filenames.
+
+	* main.c: (main), variable.c Changed handling of ENV-vars. Make
+	stores now the names of the variables only and reads their contents
+	when they are accessed to reflect that these variables are really
+	global (ie. they CAN change WHILE make runs !) This handling is
+	made in lookup_variable()
+
+	* Makefile.ami: renamed file.h to filedep.h
+	Updated dependencies
+
+	* read.c: "find_semicolon" is declared as static but never defined.
+	No difference between Makefile and makefile on Amiga; added
+	SMakefile to *default_makefiles[].
+	(read_makefile) SAS/C want's two_colon and pattern_percent be set
+	before use.
+	The current directory on Amiga is "" instead of "."
+	Strange #endif moved.
+
+	* README.Amiga: updated feature list
+
+	* SMakefile: Updated dependencies
+
+	* variable.c: Handling of ENV variable happens inside lookup_variable()
+
+Sat May 11 17:58:32 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* variable.c (try_variable_definition): Count parens in lhs variable
+	refs to avoid seeing =/:=/+= inside a ref.
+
+Thu May  9 13:54:49 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* commands.c (fatal_error_signal) [SIGQUIT]: Make SIGQUIT check
+	conditional.
+
+	* main.c (main): Use unsigned for fread return.
+
+	* read.c (parse_file_seq): Use `int' for char arg to avoid widening
+	conflict issues.
+	* dep.h: Fix prototype.
+
+	* function.c (expand_function) [_AMIGA]: Fix some typos.
+	(patsubst_expand): Make len vars unsigned.
+
+	* GNUmakefile (globfiles): Add AmigaDOS support files.
+	(distfiles): Add $(amigafiles).
+	(amigafiles): New variable.
+
+Thu Nov  7 10:18:16 1995  Aaron Digulla   <digulla@fh-konstanz.de>
+
+	* Added Amiga support in commands.c, dir.c, function.c,
+	job.c, main.c, make.h, read.c, remake.c
+	* commands.c: Amiga has neither SIGHUP nor SIGQUIT
+	* dir.c: Amiga has filenames with Upper- and Lowercase,
+	but "FileName" is the same as "filename". Added strieq()
+	which is use to compare filenames. This is like streq()
+	on all other systems. Also there is no such thing as
+	"." under AmigaDOS.
+	* function.c: On Amiga, the environment is not passed as envp,
+	there are no pipes and Amiga can't fork. Use my own function
+	to create a new child.
+	* job.c: default_shell is "" (The system automatically chooses
+	a shell for me). Have to use the same workaround as MSDOS for
+	running batch commands. Added HAVE_SYS_PARAM_H. NOFILE isn't
+	known on Amiga. Cloned code to run children from MSDOS. Own
+	version of sh_chars[] and sh_cmds[]. No dup2() or dup() on Amiga.
+	* main.c: Force stack to 20000 bytes. Read environment from ENV:
+	device. On Amiga, exec_command() does return, so I exit()
+	afterwards.
+	* make.h: Added strieq() to compare filenames.
+	* read.c: Amiga needs special extension to have passwd. Only
+	one include-dir. "Makefile" and "makefile" are the same.
+	Added "SMakefile".  Added special code to handle device names (xxx:)
+	and "./" in rules.
+	* remake.c: Only one lib-dir. Amiga link-libs are named "%s.lib"
+	instead of "lib%s.a".
+	* main.c, rule.c, variable.c: Avoid floats at all costs.
+	* vpath.c: Get rid of as many alloca()s as possible.
+
+Thu May  9 13:20:43 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* read.c (read_makefile): Grok `sinclude' as alias for `-include'.
+
+Wed Mar 20 09:52:27 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>
+
+	* GNUmakefile (vmsfiles): New variable.
+	(distfiles): Include $(vmsfiles).
+
+Tue Mar 19 20:21:34 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>
+
+	Merged VMS port from Klaus Kaempf <kkaempf@didymus.rmi.de>.
+	* make.h (PARAMS): New macro.
+	* config.h-vms: New file.
+	* makefile.com: New file.
+	* makefile.vms: New file.
+	* readme.vms: New file.
+	* vmsdir.h: New file.
+	* vmsfunctions.c: New file.
+	* vmsify.c: New file.
+	* file.h: Renamed to filedef.h to avoid conflict with VMS system hdr.
+	* ar.c: Added prototypes and changes for VMS.
+	* commands.c: Likewise.
+	* commands.h: Likewise.
+	* default.c: Likewise.
+	* dep.h: Likewise.
+	* dir.c: Likewise.
+	* expand.c: Likewise.
+	* file.c: Likewise.
+	* function.c: Likewise.
+	* implicit.c: Likewise.
+	* job.c: Likewise.
+	* job.h: Likewise.
+	* main.c: Likewise.
+	* make.h: Likewise.
+	* misc.c: Likewise.
+	* read.c: Likewise.
+	* remake.c: Likewise.
+	* remote-stub.c: Likewise.
+	* rule.c: Likewise.
+	* rule.h: Likewise.
+	* variable.c: Likewise.
+	* variable.h: Likewise.
+	* vpath.c: Likewise.
+	* compatMakefile (srcs): Rename file.h to filedef.h.
+
+Sat Aug 19 23:11:00 1995  Richard Stallman  <rms@mole.gnu.ai.mit.edu>
+
+	* remake.c (check_dep): For a secondary file, try implicit and
+	default rules if appropriate.
+
+Wed Aug  2 04:29:42 1995  Richard Stallman  <rms@mole.gnu.ai.mit.edu>
+
+	* remake.c (check_dep): If an intermediate file exists,
+	do consider its actual date.
+
+Sun Jul 30 00:49:53 1995  Richard Stallman  <rms@mole.gnu.ai.mit.edu>
+
+	* file.h (struct file): New field `secondary'.
+	* file.c (snap_deps): Check for .INTERMEDIATE and .SECONDARY.
+	(remove_intermediates): Don't delete .SECONDARY files.
+
+Sat Mar  2 16:26:52 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>
+
+	* compatMakefile (srcs): Add getopt.h; prepend $(srcdir)/ to getopt*.
+
+Fri Mar  1 12:04:47 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>
+
+	* Version 3.74.3.
+
+	* remake.c (f_mtime): Move future modtime check before FILE is
+	clobbered by :: loop.
+
+	* dir.c: Use canonical code from autoconf manual for dirent include.
+	[_D_NAMLEN]: Redefine NAMLEN using this.
+	(dir_contents_file_exists_p): Use NAMLEN macro.
+	(read_dirstream) [_DIRENT_HAVE_D_NAMLEN]: Only set d_namlen #if this.
+
+	* compatMakefile (objs): Add missing backslash.
+
+Wed Feb 28 03:56:20 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>
+
+	* default.c (default_terminal_rules): Remove + prefix from RCS cmds.
+	(default_variables): Put + prefix in $(CHECKOUT,v) value instead.
+
+	* remake.c (f_mtime): Check for future timestamps; give error and mark
+	file as "failed to update".
+
+Fri Jan 12 18:09:36 1996  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* job.c: Don't declare unblock_sigs; job.h already does.
+
+Sat Jan  6 16:24:44 1996  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* acconfig.h (HAVE_SYSCONF_OPEN_MAX): #undef removed.
+
+	* job.c (NGROUPS_MAX): Don't try to define this macro.
+
+Fri Dec 22 18:44:44 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* compatMakefile (GETOPT, GETOPT_SRC, GLOB): Variables removed.
+	(objs, srcs): Include their values here instead of references.
+
+Thu Dec 14 06:21:29 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.74.2.
+
+	* job.c (reap_children): Call unblock_sigs after start_job_command.
+
+Thu Dec 14 07:22:03 1995  Roland McGrath  <roland@duality.gnu.ai.mit.edu>
+
+	* dir.c (dir_setup_glob): Don't use lstat; glob never calls it anyway.
+	Avoid & before function names to silence bogus sunos4 compiler.
+
+	* configure.in: Remove check for `sysconf (_SC_OPEN_MAX)'.
+
+Tue Dec 12 00:48:42 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.74.1.
+
+	* dir.c (read_dirstream): Fix braino: fill in the buffer when not
+	reallocating it!
+
+Mon Dec 11 22:26:15 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* misc.c (collapse_continuations): Fix skipping of trailing \s so
+	it can never dereference before the beginning of the array.
+
+	* read.c (find_semicolon): Function removed.
+	(read_makefile): Don't use find_semicolon or remove_comments for
+	rule lines.  Use find_char_unquote directly and handle quoted comments
+	properly.
+
+	* default.c: Remove all [M_XENIX] code.
+
+	* dir.c [HAVE_D_NAMLEN]: Define this for __GNU_LIBRARY__ > 1.
+	(D_NAMLEN): Macro removed.
+	(FAKE_DIR_ENTRY): New macro.
+	(dir_contents_file_exists_p): Test HAVE_D_NAMLEN instead of using
+	D_NAMLEN.
+	(read_dirstream): Return a struct dirent * for new glob interface.
+	(init_dir): Function removed.
+	(dir_setup_glob): New function.
+	* main.c (main): Don't call init_dir.
+	* read.c (multi_glob): Call dir_setup_glob on our glob_t and use
+	GLOB_ALTDIRFUNC flag.
+
+	* misc.c (safe_stat): Function removed.
+	* read.c, commands.c, remake.c, vpath.c: Use plain stat instead of
+	safe_stat.
+
+Sat Nov 25 20:35:18 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* job.c [HAVE_UNION_WAIT]: Include sys/wait.h.
+
+	* main.c (log_working_directory): Made global.
+	Print entering msg only once.
+	* make.h (log_working_directory): Declare it.
+	* misc.c (message): Take new arg PREFIX.  Print "make: " only if
+	nonzero.  Call log_working_directory.
+	* remake.c: Pass new arg in `message' calls.
+	* job.c (start_job_command): Pass new arg to `message'; fix
+	inverted test in that call.
+
+Tue Nov 21 19:01:12 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* job.c (start_job_command): Use `message' to print the command,
+	and call it with null if the command is silent.
+	* remake.c (touch_file): Use message instead of printf.
+
+Tue Oct 10 14:59:30 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (enter_command_line_file): Barf if NAME is "".
+
+Sat Sep  9 06:33:20 1995  Roland McGrath  <roland@whiz-bang.gnu.ai.mit.edu>
+
+	* commands.c (delete_target): Ignore unlink failure if it is ENOENT.
+
+Thu Aug 17 15:08:57 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* configure.in: Don't check for getdtablesize.
+	* job.c (getdtablesize): Remove decls and macros.
+
+Thu Aug 10 19:10:03 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (define_makeflags): Omit command line variable
+ 	definitions from MFLAGS value.
+
+	* arscan.c (ar_scan) [AIAMAG]: Check for zero MEMBER_OFFSET,
+ 	indicating a valid, but empty, archive.
+
+Mon Aug  7 15:40:03 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* dir.c (file_impossible_p): Correctly reset FILENAME to name
+ 	within directory before hash search.
+
+	* job.c (child_error): Do nothing if IGNORED under -s.
+
+	* job.c (exec_command): Correctly use ARGV[0] for script name when
+ 	running shell directly.
+
+Tue Aug  1 14:39:14 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* job.c (child_execute_job): Close STDIN_FD and STDOUT_FD after
+ 	dup'ing from them.  Don't try to close all excess descriptors;
+ 	getdtablesize might return a huge value.  Any open descriptors in
+ 	the parent should have FD_CLOEXEC set.
+	(start_job_command): Set FD_CLOEXEC flag on BAD_STDIN descriptor.
+
+Tue Jun 20 03:47:15 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* read.c (read_all_makefiles): Properly append default makefiles
+ 	to the end of the `read_makefiles' chain.
+
+Fri May 19 16:36:32 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.74 released.
+
+Wed May 10 17:43:34 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.73.3.
+
+Tue May  9 17:15:23 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* compatMakefile ($(infodir)/make.info): Make sure $$dir is set in
+ 	install-info cmd.
+
+Wed May  3 15:56:06 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* file.c (print_file): Grok update_status of 1 for -q.
+
+Thu Apr 27 12:39:35 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.73.2.
+
+Wed Apr 26 17:15:57 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* file.c (remove_intermediates): Fix inverted test to bail under
+ 	-n for signal case.  Bail under -q or -t.
+	Skip files with update_status==-1.
+
+	* job.c (job_next_command): Skip empty lines.
+	(new_job): Don't test the return of job_next_command.
+	Just let start_waiting_job handle the case of empty commands.
+
+Wed Apr 19 03:25:54 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* function.c [__MSDOS__]: Include <fcntl.h>.  From DJ Delorie.
+
+	* Version 3.73.1.
+
+Sat Apr  8 14:53:24 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* remake.c (notice_finished_file): Set FILE->update_status to zero
+ 	if it's -1.
+
+Wed Apr  5 00:20:24 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.73 released.
+
+Tue Mar 28 13:25:46 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (main): Fixed braino in assert.
+
+	* Version 3.72.13.
+
+Mon Mar 27 05:29:12 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c: Avoid string in assert expression.  Some systems are broken.
+
+Fri Mar 24 00:32:32 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (main): Handle 1 and 2 returns from update_goal_chain
+ 	makefile run properly.
+
+	* Version 3.72.12.
+
+	* main.c (handle_non_switch_argument): New function, broken out of
+ 	decode_switches.
+	(decode_switches): Set optind to 0 to reinitialize getopt, not to 1.
+	When getopt_long returns EOF, break the loop and handle remaining args
+ 	with a simple second loop.
+
+	* remake.c (remake_file): Set update_status to 2 instead of 1 for
+ 	no rule to make.  Mention parent (dependent) in error message.
+	(update_file_1): Handle FILE->update_status == 2 in -d printout.
+	* job.c (start_job_command, reap_children): Set update_status to 2
+ 	instead of 1 for failed commands.
+
+Tue Mar 21 16:23:38 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* job.c (search_path): Function removed (was already #if 0'd out).
+	* configure.in: Remove AC_TYPE_GETGROUPS; nothing needs it any more.
+
+Fri Mar 17 15:57:40 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* configure.bat: Write @CPPFLAGS@ translation.
+
+Mon Mar 13 00:45:59 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* read.c (parse_file_seq): Rearranged `l(a b)' -> `l(a) l(b)' loop
+ 	to not skip the elt immediately preceding `l(...'.
+
+Fri Mar 10 13:56:49 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.72.11.
+
+	* read.c (find_char_unquote): Make second arg a string of stop
+ 	chars instead of a single stop char.  Stop when any char in the
+ 	string is hit.  All callers changed.
+	(find_semicolon): Pass stop chars "#;" to one find_char_unquote call,
+	instead of using two calls.  If the match is not a ; but a #,
+ 	return zero.
+	* misc.c: Changed find_char_unquote callers here too.
+
+	* Version 3.72.10.
+
+	* read.c (read_makefile, parse_file_seq): Fix typo __MS_DOS__ ->
+ 	__MSDOS__.
+
+	* GNUmakefile (globfiles): Add glob/configure.bat.
+	(distfiles): Add configh.dos, configure.bat.
+
+Wed Mar  8 13:10:57 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	Fixes for MS-DOS from DJ Delorie.
+	* read.c (read_makefile, parse_file_seq) [__MS_DOS__]: Don't see :
+ 	as separator in "C:\...".
+	* configh.dos (STDC_HEADERS): Define only if undefined.
+	(HAVE_SYS_PARAM_H): Don't define this.
+	(HAVE_STRERROR): Define this.
+	* job.c (construct_command_argv_internal) [__MSDOS__]: Fix typos.
+
+	* Version 3.72.9.
+
+	* main.c (decode_switches): Reset optind to 1 instead of 0.
+
+Tue Mar  7 17:31:06 1995  Roland McGrath  <roland@geech.gnu.ai.mit.edu>
+
+	* main.c (decode_switches): If non-option arg is "-", ignore it.
+
+Mon Mar  6 23:57:38 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.72.8.
+
+Wed Feb 22 21:26:36 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.72.7.
+
+Tue Feb 21 22:10:43 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (main): Pass missing arg to tmpnam.
+
+	* configure.in: Check for strsignal.
+	* job.c (child_error): Use strsignal.
+	* main.c (main): Don't call signame_init #ifdef HAVE_STRSIGNAL.
+
+	* misc.c (strerror): Fix swapped args in sprintf.
+
+Mon Feb 13 11:50:08 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* configure.in (CFLAGS, LDFLAGS): Don't set these variables.
+
+Fri Feb 10 18:44:12 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (print_version): Add 95 to copyright years.
+
+	* Version 3.72.6.
+
+	* job.c (start_job_command): Remember to call notice_finished_file
+ 	under -n when not recursing.  To do this, consolidate that code
+ 	under the empty command case and goto there for the -n case.
+
+Tue Feb  7 13:36:03 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* make.h [! STDC_HEADERS]: Don't declare qsort.  Sun headers
+ 	declare it int.
+
+Mon Feb  6 17:37:01 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* read.c (read_makefile): For bogus line starting with tab, ignore
+ 	it if blank after removing comments.
+
+	* main.c: Cast results of `alloca' to `char *'.
+	* expand.c: Likewise.
+
+Sun Feb  5 18:35:46 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.72.5.
+
+	* configure.in: Check for mktemp.
+	* main.c (main) [! HAVE_MKTEMP]: Use tmpnam instead of mktemp.
+
+	* configure.in (make_cv_sysconf_open_max): New check for `sysconf
+ 	(_SC_OPEN_MAX)'.
+	* acconfig.h: Added #undef HAVE_SYSCONF_OPEN_MAX.
+	* job.c [HAVE_SYSCONF_OPEN_MAX] (getdtablesize): Define as macro
+ 	using sysconf.
+
+Fri Jan 27 04:42:09 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* remake.c (update_file_1): When !MUST_MAKE, don't set
+ 	FILE->update_status to zero before calling notice_finished_file.
+	(notice_finished_file): Touch only when FILE->update_status is zero.
+	(remake_file): Set FILE->update_status to zero after not calling
+	execute_file_command and deciding to touch instead.
+
+Thu Jan 26 01:29:32 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (debug_signal_handler): New function; toggles debug_flag.
+	(main): Handle SIGUSR1 with that.
+
+Mon Jan 16 15:46:56 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* compatMakefile (realclean): Remove Info files.
+
+Sun Jan 15 08:23:09 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.72.4.
+
+	* job.c (start_job_command): Save and restore environ around vfork
+        call.
+	(search_path): Function #if 0'd out.
+	(exec_command): Use execvp instead of search_path.
+
+	* expand.c (variable_expand): Rewrote computed variable name and
+	substitution reference handling to be simpler.  First expand the
+	entire text between the parens if it contains any $s, then examine
+	the result of that for subtitution references and do no further
+	expansion while parsing them.
+
+	* job.c (construct_command_argv_internal): Handle " quoting too,
+	when no backslash, $ or ` characters appear inside the quotes.
+
+	* configure.in (union wait check): If WEXITSTATUS and WTERMSIG are
+        defined, just use int.
+
+Tue Jan 10 06:27:27 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* default.c (default_variables) [__hpux]: Remove special
+	definition of ARFLAGS.  Existence of the `f' flag is not
+	consistent across HPUX versions; and one might be using GNU ar
+	anyway.
+
+	* compatMakefile (clean): Don't remove Info files.
+
+	* compatMakefile (check): Remove gratuitous target declaration.
+
+Sat Jan  7 11:38:23 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* compatMakefile (ETAGS, CTAGS): Don't use -t.
+
+	* arscan.c (ar_name_equal) [cray]: Subtract 1 like [__hpux].
+
+	* main.c (decode_switches): For --help, print usage to stdout.
+
+Mon Dec  5 12:42:18 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.72.3.
+
+	* remake.c (update_file_1): Do set_command_state (FILE,
+	cs_not_started) only if old state was deps_running.
+
+Mon Nov 28 14:24:03 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* job.c (start_waiting_job): Use set_command_state.
+
+	* build.template (CPPFLAGS): New variable.
+	(prefix, exec_prefix): Set from @...@.
+	(compilation loop): Pass $CPPFLAGS to compiler.
+
+	* GNUmakefile (build.sh.in): Make it executable.
+
+	* GNUmakefile (globfiles): Add configure.in, configure.
+
+	* Version 3.72.2.
+
+	* configure.in (AC_OUTPUT): Don't write glob/Makefile.
+
+	* configure.in (AC_CHECK_SYMBOL): Use AC_DEFINE_UNQUOTED.
+
+	* configure.in: Don't check for ranlib.
+
+Tue Nov 22 22:42:40 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* remake.c (notice_finished_file): Only mark also_make's as
+	updated if really ran cmds.
+
+Tue Nov 15 06:32:46 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* configure.in: Put dnls before random whitespace.
+
+Sun Nov 13 05:02:25 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* compatMakefile (CPPFLAGS): New variable, set from @CPPFLAGS@.
+	(RANLIB): Variable removed.
+	(prefix, exec_prefix): Set these from @...@.
+	(.c.o): Use $(CPPFLAGS).
+	(glob/libglob.a): Don't pass down variables to sub-make.
+	glob/Makefile should be configured properly by configure.
+	(distclean): Remove config.log and config.cache (autoconf stuff).
+
+Mon Nov  7 13:58:06 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* acconfig.h: Add #undef HAVE_UNION_WAIT.
+	* configure.in: Converted to Autoconf v2.
+	* dir.c: Test HAVE_DIRENT_H, HAVE_SYS_DIR_H, HAVE_NDIR_H instead
+	of DIRENT, SYSDIR, NDIR.
+	* build.sh.in (prefix, exec_prefix): Set these from @...@.
+	(CPPFLAGS): New variable, set from @CPPFLAGS@.
+	(compiling loop): Pass $CPPFLAGS before $CFLAGS.
+	* install.sh: File renamed to install-sh.
+
+	* main.c (define_makeflags): When no flags, set WORDS to zero.
+
+Sun Nov  6 18:34:01 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.72.1.
+
+	* main.c (define_makeflags): Terminate properly when FLAGSTRING is
+        empty.
+
+Fri Nov  4 16:02:51 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.72.
+
+Tue Nov  1 01:18:10 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.71.5.
+
+	* job.c (start_job_command): When ARGV is nil, only set
+	update_state and call notice_finished_file if job_next_command
+	returns zero.
+
+	* job.c (start_job_command): Call notice_finished_file for empty
+        command line.
+
+Thu Oct 27 02:02:45 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* file.c (snap_deps): Set COMMANDS_SILENT for .SILENT, not
+        COMMANDS_NOERROR.
+
+Wed Oct 26 02:14:10 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.71.4.
+
+Tue Oct 25 22:49:24 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* file.c (snap_deps): Set command_flags bits in all :: entries.
+
+Mon Oct 24 18:47:50 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* make.h (posix_pedantic): Declare it.
+	* main.c (main): Move checks .IGNORE, .SILENT, .POSIX to
+        snap_deps.
+	* file.c (snap_deps): Check .IGNORE, .SILENT, .POSIX here instead
+	of in main.  If .IGNORE has deps, OR COMMANDS_NOERROR into their
+	command_flags and don't set -i.  Likewise .SILENT.
+	* job.c (start_job_command): In FLAGS initialization, OR in
+	CHILD->file->command_flags.
+	* file.h (struct file): New member `command_flags'.
+
+Sun Oct 16 01:01:51 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (switches): Bump flag values for --no-print-directory and
+	--warn-undefined-variables, so neither is 1 (which indicates a
+	nonoption argument).
+
+Sat Oct 15 23:39:48 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (main): Add missing code in .IGNORE test.
+
+Mon Oct 10 04:09:03 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* variable.c (define_automatic_variables): Define +D and +F.
+
+Sat Oct  1 04:07:48 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (main): Define hidden automatic variable with command
+	vars, and MAKEOVERRIDES to a reference to that.
+	(define_makeflags): If posix_pedantic, write a reference to that
+	instead.
+
+Thu Sep 29 00:14:26 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* main.c (posix_pedantic): New variable.
+	(main): Set posix_pedantic if .POSIX is a target.
+	Fix .IGNORE and .SILENT checks to require is_target.
+
+	* commands.c (set_file_variables): Define new automatic variable
+	$+, like $^ but before calling uniquize_deps.
+
+	* job.c (reap_children): Call delete_child_targets for non-signal
+	error if .DELETE_ON_ERROR is a target.
+
+Tue Sep 27 01:57:14 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.71.3.
+
+Mon Sep 26 18:16:55 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* job.c (reap_children): Don't change C->file->command_state when
+	dying.  Test it only after calling start_job_command for a new
+	command line.  When no more cmds, just set C->file->update_status.
+	(start_job_command): When the last line is empty or under -n, set
+	C->file->update_status.
+	(start_waiting_job): Grok cs_not_started after start_job_command
+	as success.
+	(new_job): Set C->file->update_status when there are no cmds.
+	(job_next_command): When out of lines, don't set
+	CHILD->file->update_status or CHILD->file->command_state.
+
+	* main.c (quote_as_word): Renamed from shell_quote.  Take new arg;
+	if nonzero, also double $s.
+	(main): Define MAKEOVERRIDES from command_variables here.
+	(define_makeflags): Don't use command_variables here; instead write a
+	reference $(MAKEOVERRIDES) in MAKEFLAGS.  Make vars recursive.
+
+	* dir.c [__MSDOS__]: Fixed typo.
+
+	* vpath.c (selective_vpath_search): Reset EXISTS when stat fails.
+
+Sat Sep 10 03:01:35 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* remake.c: Include <assert.h> and use assert instead of printfs
+        and abort.
+
+	* main.c (decode_switches): Loop until optind hits ARGC, not just
+	until getopt_long returns EOF.  Initialize C to zero before loop;
+	in loop if C is EOF, set optarg from ARGV[optind++], else call
+	getopt_long.
+	(decode_env_switches): Use variable_expand instead of
+	allocated_variable_expand.  Allocate a fresh buffer to copy split
+	words into; scan characters by hand to break words and
+	debackslashify.
+	(shell_quote): New function.
+	(define_makeflags): Allocate doubled space for switch args, and command
+	variable names and values; use shell_quote to quote those things.
+
+Fri Sep  9 01:37:47 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* Version 3.71.2.
+
+	* acconfig.h: Add HAVE_SYS_SIGLIST and HAVE__SYS_SIGLIST.
+
+	* main.c (decode_switches): The non-option return from getopt is
+	1, not 0.
+	(command_variables): New type and variable.
+	(decode_switches, decode_env_switches): After making a variable
+	definition, record the struct variable pointer in the
+	command_variables chain.
+	(define_makeflags): If ALL, write variable definitions for
+	command_variables.
+
+	* main.c (other_args): Variable removed.
+	(goals, lastgoal): New static variables (moved from auto in main).
+	(main): Don't process OTHER_ARGS at all.
+	Don't set variable MAKEOVERRIDES at all; define MAKE to just
+        $(MAKE_COMMAND).
+	(init_switches): Prepend a - {return in order} instead of a +
+	{require order}.
+	(decode_switches): Don't set OTHER_ARGS at all.
+	Grok '\0' return from getopt_long as non-option argument; try
+	variable definition and (if !ENV) enter goal targets here.
+	(decode_env_switches): Use allocated_variable_expand to store value.
+	Use find_next_token to simplify word-splitting loop.  Don't
+	prepend a dash to uninterpreted value.  Instead, if split into
+	only one word, try variable definition and failing that prepend a
+	dash to the word and pass it to decode_switches as a single arg.
+
+Wed Sep  7 03:02:46 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	* remake.c (notice_finished_file): Only recheck modtimes if
+	FILE->command_state was cs_running on entry (meaning the commands
+	actually just ran).
+	(update_file_1): Whenever we set FILE->update_status, call
+	notice_finished_file instead of just set_command_state.
+	* job.c (start_job_command): Whenever we set
+	CHILD->file->update_status, call notice_finished_file instead of
+	just set_command_state.
+
+Tue Sep  6 19:13:54 1994  Roland McGrath  <roland@geech.gnu.ai.mit.edu>
+
+	* default.c: Add missing ".
+
+	* job.c: Changed all assignments of command_state members to calls
+	to set_command_state.
+	* remake.c: Likewise.
+	* file.c (set_command_state): New function.
+	* file.h: Declare set_command_state.
+
+	* main.c (init_switches): Put a + first in options.
+
+Mon Jul 25 18:07:46 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+	Merge MSDOS/GO32 port from DJ Delorie <dj@ctron.com>.
+	* vpath.c: Changed all uses of ':' to PATH_SEPARATOR_CHAR.
+	* main.c (directory_before_chdir): New variable, moved out of main
+        (was local).
+	(main) [__MSDOS__]: Look for \ or : to delimit last component of
+	PROGRAM.  Don't frob ARGV[0] before setting MAKE_COMMAND variable.
+	(die): Change back to `directory_before_chdir' before dying.
+	* make.h (PATH_SEPARATOR_CHAR): New macro; differing defns for
+        [__MSDOS__] and not.
+	* job.c [__MSDOS__]: Include <process.h>.
+	[__MSDOS__] (dos_pid, dos_status, dos_bname, dos_bename,
+	dos_batch_file): New variables.
+	(reap_children) [__MSDOS__]: Don't call wait; just examine those vars.
+	(unblock_sigs) [__MSDOS__]: Do nothing.
+	(start_job_command) [__MSDOS__]: Use spawnvpe instead of vfork & exec.
+	(load_too_high) [__MSDOS__]: Always return true.
+	(search_path) [__MSDOS__]: Check for : or / in FILE to punt.
+	Use PATH_SEPARATOR_CHAR instead of ':'.
+	(construct_command_argv_internal) [__MSDOS__]: Wholly different
+	values for sh_chars and sh_cmds.  Wholly new code to handle shell
+	scripts.
+	* function.c (expand_function: `shell') [__MSDOS__]: Wholly new
+        implementation.
+	* dir.c [__MSDOS__] (dosify): New function.
+	(dir_contents_file_exists_p) [__MSDOS__]: Call it on FILENAME and
+	process the result instead of FILENAME itself.
+	(file_impossible_p) [__MSDOS__]: Likewise.
+	* default.c [__MSDOS__]: Define GCC_IS_NATIVE.
+	(default_suffix_rules) [__MSDOS__]: Use `y_tab.c' instead of `y.tab.c'.
+	(default_variables) [GCC_IS_NATIVE]: Set CC and CXX to `gcc', YACC to
+	`bison -y', and LEX to `flex'.
+	* configure.bat, configh.dos: New files.
+	* commands.c (fatal_error_signal) [__MSDOS__]: Just remove
+	intermediates and exit.
+
+	* commands.c (set_file_variables): Add parens in length
+	computation in .SUFFIXES dep loop to quiet compiler warning.  From
+	Jim Meyering.
+
+	* read.c (read_makefile): Free FILENAME if we allocated it.  From
+        Jim Meyering.
+
+Mon Jul  4 17:47:08 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* misc.c (safe_stat): New function, EINTR-safe wrapper around stat.
+	* vpath.c (selective_vpath_search): Use safe_stat in place of stat.
+	* read.c (construct_include_path): Use safe_stat in place of stat.
+	* job.c (search_path): Use safe_stat in place of stat.
+	* dir.c (find_directory): Use safe_stat in place of stat.
+	* commands.c (delete_target): Use safe_stat in place of stat.
+	* arscan.c (ar_member_touch) [EINTR]: Do EINTR looping around fstat.
+	* remake.c (name_mtime): Use safe_stat in place of stat.
+	(touch_file) [EINTR]: Do EINTR looping around fstat.
+
+Fri Jun 24 05:40:24 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Check for a shell command first, and
+	then strip leading tabs before further checking if it's not a
+	shell command line.
+
+	* make.h [__arm]: Undefine POSIX.
+	[!__GNU_LIBRARY__ && !POSIX && !_POSIX_VERSION]: Don't declare system
+	functions that return int.
+
+	* job.c (construct_command_argv_internal): After swallowing a
+	backslash-newline combination, if INSTRING is set goto string_char
+	(new label) for normal INSTRING handling code.
+
+Sat Jun  4 01:11:20 1994  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* configure.in: Don't check for sys_siglist and _sys_siglist with
+	AC_HAVE_FUNCS.  Instead use two AC_COMPILE_CHECKs.
+
+Mon May 23 18:20:38 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.71.1 released.
+
+	* make.h [!__GNU_LIBRARY__ && !POSIX]: Also test #ifndef
+	_POSIX_VERSION for these declarations.
+
+	* misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Remove bogus #ifndefs
+	around #undefs of HAVE_SETREUID and HAVE_SETREGID.
+
+Sat May 21 16:26:38 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.71 released.
+
+	* misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Don't test [HAVE_SETUID]
+	and [HAVE_SETGID].  Every system has those, and configure doesn't
+	check for them.
+
+	* make.h [_POSIX_VERSION]: Don't #define POSIX #ifdef ultrix.
+
+	* compatMakefile (loadavg): Depend on and use loadavg.c instead of
+	getloadavg.c.
+	(loadavg.c): Link or copy it from getloadavg.c.
+	(distclean): Remove loadavg.c.
+
+Mon May 16 22:59:04 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.70.4.
+
+	* misc.c [GETLOADAVG_PRIVILEGED] [! POSIX]: Undefine HAVE_SETEUID
+	and HAVE_SETEGID.
+
+	* default.c (default_terminal_rules): In SCCS rules, put
+	$(SCCS_OUTPUT_OPTION) before $<.  On some systems -G is grokked
+	only before the file name.
+	* configure.in (SCCS_GET_MINUS_G check): Put -G flag before file name.
+
+Tue May 10 16:27:38 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): Swallow
+	backslash-newline combinations inside '' strings too.
+
+Thu May  5 04:15:10 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (do_define): Call collapse_continuations on each line
+	before all else.
+
+Mon Apr 25 19:32:02 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): Notice newline inside
+	'' string when RESTP is non-null.
+
+Fri Apr 22 17:33:30 1994  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.70.3.
+
+	* remake.c (update_goal_chain): Reset FILE to G->file after the
+	double-colon loop so it is never null for following code.
+
+	* read.c (read_makefile): Fix `override define' parsing to skip
+	whitespace after `define' properly.
+
+	* compatMakefile (srcdir): Define as @srcdir@; don't reference
+	$(VPATH).
+	(glob/Makefile): New target.
+
+Thu Apr 21 16:16:55 1994  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.70.2.
+
+	* misc.c (remove_comments): Use find_char_unquote.
+	* make.h (find_char_unquote): Declare it.
+	* read.c (find_char_unquote): New function, generalized from
+	find_percent.
+	(find_percent, find_semicolon, parse_file_seq): Use that.
+
+Wed Apr 20 18:42:39 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* implicit.c (pattern_search): Always allocate new storage for
+	FILE->stem.  It is not safe to store STEM's address because it
+	might be auto storage.
+
+	* configure.in: Check for seteuid and setegid.
+	* misc.c [HAVE_SETEUID]: Declare seteuid.
+	[HAVE_SETEGID]: Declare setegid.
+	(make_access, user_access) [HAVE_SETEUID]: Use seteuid.
+	[HAVE_SETEGID]: Use setegid.
+
+	* remake.c (update_goal_chain): Set STATUS to FILE->update_status,
+	to preserve whether it's 2 for error or 1 for -q trigger.  When
+	STATUS gets nonzero and -q is set, always stop immediately.
+	* main.c (main, decode_switches): Die with 2 for errors.
+	(main): Accept 2 return from update_goal_chain and die with that.
+	* misc.c (fatal, makefile_fatal): Die with 2; 1 is reserved for -q
+	answer.
+	* job.c (reap_children): Die with 2 for error.
+	(start_job_command): Set update_status to 2 for error.  Set it to
+	1 when we would run a command and question_flag is set.
+
+	* read.c (read_makefile): Don't mark makefiles as precious.  Just
+	like other targets, they can be left inconsistent and in need of
+	remaking by aborted commands.
+
+	* read.c (read_makefile): Write no error msg for -include file.
+
+Tue Apr  5 05:22:19 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* commands.c (fatal_error_signal): Don't unblock signals.
+
+	* file.h (struct file): Change member `double_colon' from flag to
+	`struct file *'.
+	* read.c (record_files): Set double_colon pointer instead of flag.
+	* main.c (main): When disqualifying makefiles for updating, use
+	double_colon pointer to find all entries for a file.
+	* file.c (enter_file): If there is already a double-colon entry
+	for the file, set NEW->double_colon to that pointer.
+	(file_hash_enter): Use FILE->double_colon to find all entries to
+	set name.
+	* remake.c (update_goal_chain): Do inner loop on double-colon entries.
+	(update_file): Use FILE->double_colon pointer to find all entries.
+	(f_mtime): Likewise.
+	(notice_finished_file): Propagate mtime change to all entries.
+
+	* variable.c (try_variable_definition): Return after abort.
+
+Fri Apr  1 18:44:15 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Remove unused variable.
+	(parse_file_seq): When removing an elt that is just `)', properly
+	fix up the previous elt's next pointer.
+
+Mon Mar 28 18:31:49 1994  Roland McGrath  (roland@mole.gnu.ai.mit.edu)
+
+	* configure.in: Do AC_SET_MAKE.
+	* GNUmakefile (Makefile.in): Edit MAKE assignment into @SET_MAKE@.
+
+Fri Mar  4 00:02:32 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* function.c (subst_expand): If BY_WORD or SUFFIX_ONLY is set and
+	the search string is the empty string, find a match at the end of
+	each word (using end_of_token in place of sindex).
+
+	* misc.c (end_of_token): Don't treat backslashes specially; you
+	can no longer escape blanks with backslashes in export, unexport,
+	and vpath.  This was never documented anyway.
+
+Thu Mar  3 23:53:46 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Variable name for `define' is not just
+	first token; use whole rest of line and strip trailing blanks.
+
+Wed Feb 16 16:03:45 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.70.1.
+
+	* read.c (read_makefile): Add -d msg stating args.
+
+	* read.c (read_makefile): Use isspace to skip over leading
+	whitespace, and explicitly avoid skipping over tabs.  Don't want
+	to skip just spaces though; formfeeds et al should be skipped.
+
+	* default.c (default_variables) [__hpux]: Add f in ARFLAGS.
+
+	* arscan.c (ar_name_equal) [__hpux]: Subtract 2 instead of 1 from
+	sizeof ar_name for max length to compare.
+
+	* misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Undefine HAVE_SETREUID
+	#ifdef HAVE_SETUID; likewise HAVE_SETREGID and HAVE_SETGID.
+
+	* main.c (main): Call user_access after setting `program', in case
+	it needs to use it in an error message.
+
+	* read.c (read_makefile): Ignore an empty line starting with a tab.
+
+Thu Feb 10 21:45:31 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in (AC_SYS_SIGLIST_DECLARED): Use this instead of
+	AC_COMPILE_CHECK that is now its contents.
+
+Fri Feb  4 16:28:54 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h: #undef strerror after #include <string.h>.
+	[! ANSI_STRING]: Declare strerror.
+
+Thu Feb  3 02:21:22 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* misc.c (strerror): #undef any macro before function definition.
+
+Mon Jan 31 19:07:23 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* variable.c (try_variable_definition): Calculate BEG before loop
+	to strip blanks by decrementing END.  Don't decr END to before BEG.
+
+	* read.c (read_makefile): Skip over leading space characters, but
+	not tabs, after removing continuations and comments (it used to
+	use isspace).
+
+Tue Jan 25 16:45:05 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* variable.c (define_automatic_variables): In $(@D) et al, use
+	patsubst to remove trailing slash.
+
+	* commands.c (delete_target): New function, broken out of
+	delete_child_targets.  Check for archive members and give special msg.
+	(delete_child_targets): Use delete_target.
+
+Mon Jan 17 17:03:22 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* default.c (default_suffix_rules): Use $(TEXI2DVI_FLAGS) in
+	texi2dvi rules.	Use $(MAKEINFO_FLAGS) in makeinfo rules.
+
+Tue Jan 11 19:29:55 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* GNUmakefile (tarfiles): Omit make-doc.
+	(make-$(version).tar): Include make.info*.
+
+Fri Jan  7 16:27:00 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (configure, config.h.in): Comment out rules.
+
+Thu Jan  6 18:08:08 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (binprefix, manprefix): New variables.
+	(instname): Variable removed.
+	(install): Use $({bin,man}prefix)make in place of $(instname).
+	File targets likewised renamed.
+
+Mon Jan  3 17:50:25 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.70 released.
+
+Thu Dec 23 14:46:54 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.69.3.
+
+	* read.c (parse_file_seq): Inside multi-word archive ref
+	translation loop, check NEW1==0 at end and break out of the loop.
+
+	* GNUmakefile (make-$(version).tar): Distribute install.sh.
+	* install.sh: New file.
+
+	* configure.in (SCCS_GET_MINUS_G check): Put redirection for admin
+	cmds outside subshell parens, to avoid "command not found" msgs
+	from the shell.
+
+Wed Dec 22 17:00:43 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in (SCCS_GET_MINUS_G check): Put -G flag last in get cmd.
+	Redirect output & error from get to /dev/null.
+	Fix reversed sense of test.
+
+Fri Dec 17 15:31:36 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in (SCCS_GET_MINUS_G check): Use parens instead of
+	braces inside if condition command; some shells lose.
+
+Thu Dec 16 15:10:23 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.69.2.
+
+	* arscan.c [M_UNIX]: Move #undef M_XENIX for PORTAR stuff.
+	(PORTAR) [M_XENIX]: Define to 0 instead of 1.
+
+	* main.c (define_makeflags): Only export MAKEFLAGS if !ALL.
+
+Wed Dec 15 17:47:48 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (main): Cast result of pointer arith to unsigned int
+	before passing to define_variable for envars.  Matters when
+	sizeof(unsigned)!=sizeof(ptrdiff_t).
+
+Tue Dec 14 14:21:16 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in: Add new check for SCCS_GET_MINUS_G.
+	* config.h.in: Add #undef SCCS_GET_MINUS_G.
+	* default.c (default_terminal_rules): Use `$(SCCS_OUTPUT_OPTION)' in
+	place of `-G $@' in SCCS commands.
+	(default_variables) [SCCS_GET_MINUS_G]: Define SCCS_OUTPUT_OPTION
+	to "-G$@".
+
+	* configure.in (AC_OUTPUT): Put touch stamp-config in second arg
+	(so it goes in config.status), rather than afterward.
+
+	* ar.c (ar_member_date): Don't call enter_file on the archive file
+	if it doesn't exist (by file_exists_p).
+
+	* compatMakefile ($(infodir)/make.info): Replace `$$d/foo.info'
+	with `$$dir/make.info' in install-info invocation (oops).
+
+	* vpath.c (construct_vpath_list): Only set LASTPATH set PATH when
+	we do not unlink and free PATH.
+
+	* file.c (print_file_data_base): Fix inverted calculation for
+	average files per hash bucket.
+
+	* read.c (readline): When we see a NUL, give only a warning and
+	synthesize a newline to terminate the building line (used to
+	fatal).  Move fgets call into the loop condition, and after the
+	loop test ferror (used to test !feof in the loop).
+
+Fri Dec  3 16:40:31 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in: Check for strerror in AC_HAVE_FUNCS.
+
+Thu Dec  2 15:37:50 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	Differentiate different flavors of missing makefile error msgs,
+	removing gratuitous `fopen: ' and giving caller for included makefiles.
+	* misc.c [! HAVE_STRERROR]: Define our own strerror here.
+	(perror_with_name, pfatal_with_name): Use strerror instead of
+	replicating its functionality.
+	* read.c (read_makefile): Return int instead of void.
+	(read_all_makefiles, read_makefile): Change callers to notice zero
+	return and give error msg.
+
+Thu Nov 11 11:47:36 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.69.1.
+
+	* default.c: Put `-G $@' before $< in SCCS cmds.
+
+Wed Nov 10 06:06:14 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): After trying a variable defn, notice if
+	the line begins with a tab, and diagnose an error.
+
+Sun Nov  7 08:07:37 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.69.
+
+Wed Nov  3 06:54:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.10.
+
+	* implicit.c (try_implicit_rule): Look for a normal rule before an
+	archive rule.
+
+Fri Oct 29 16:45:28 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* function.c (expand_function: `sort'): Double NWORDS when it
+	overflows, instead of adding five.
+
+	* compatMakefile (clean): Remove loadavg.
+
+Wed Oct 27 17:58:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.9.
+
+	* file.h (NEW_MTIME): Define new macro.
+	* main.c (main): Set time of NEW_FILES to NEW_MTIME, not to
+	current time returned from system.  Removed variable NOW.
+	* remake.c (notice_finished_file): Use NEW_MTIME in place of
+	current time here too.
+
+Tue Oct 26 19:45:35 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.8.
+
+	* remake.c (update_file_1): Don't clear MUST_MAKE when FILE has no
+	cmds and !DEPS_CHANGED unless also !NOEXIST.
+
+Mon Oct 25 15:25:21 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (parse_file_seq): When converting multi-word archive
+	refs, ignore a word beginning with a '('.
+
+Fri Oct 22 02:53:38 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in: Check for sys/timeb.h.
+	* make.h [HAVE_SYS_TIMEB_H]: Test this before including it.
+
+Thu Oct 21 16:48:17 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.7.
+
+	* rule.c (convert_suffix_rule): New local TARGPERCENT.  Set it to
+	TARGNAME+1 for "(%.o)", to TARGNAME for "%.?".  Use it in place of
+	TARGNAME to initialize PERCENTS[0].
+
+Mon Oct 18 06:49:35 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in: Use AC_HAVE_HEADERS(unistd.h) instead of AC_UNISTD_H.
+	Remove AC_USG; it is no longer used.
+
+	* file.c (print_file): New function, broken out of
+	print_file_data_base.
+	(print_file_data_base): Call it.
+	* rule.c (print_rule): New function, broken out of
+	print_rule_data_base.
+	(print_rule_data_base): Call it.
+
+Thu Oct 14 14:54:03 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* default.c (install_default_suffix_rules): New function, broken
+	out of install_default_implicit_rules.
+	(install_default_implicit_rules): Move suffix rule code there.
+	* make.h: Declare install_default_suffix_rules.
+	* main.c (main): Call install_default_suffix_rules before reading
+	makefiles.  Move convert_to_pattern call before
+	install_default_implicit_rules.
+
+	* job.h (struct child): Make `pid' member type `pid_t' instead of
+	`int'.
+
+	* compatMakefile (RANLIB): New variable, set by configure.
+	(glob/libglob.a): Pass RANLIB value down to submake.
+
+	Fixes for SCO 3.2 "devsys 4.2" from pss@tfn.com (Peter Salvitti).
+	* make.h: Include <sys/timeb.h> before <time.h> for SCO lossage.
+	* job.c [! getdtablesize] [! HAVE_GETDTABLESIZE]: If NOFILE is not
+	defined but NOFILES_MAX is, define it to be that.
+
+Mon Oct 11 19:47:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* GNUmakefile (make-$(version).tar): Depend on acconfig.h, so it
+	is distributed.
+
+Sun Oct  3 15:15:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* default.c (default_terminal_rules): Add `-G $@' to SCCS get cmds.
+
+Tue Sep 28 14:18:20 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): Add ^ to SH_CHARS; it
+	is another symbol for | in some shells.
+	* main.c (main): Add it to CMD_DEFS quoting list as well.
+
+Mon Sep 20 18:05:24 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): Remove '=' from
+	SH_CHARS.  Only punt on '=' if it is unquoted in a word before the
+	first word without an unquoted '='.
+
+	* main.c (define_makeflags): Set v_export for MAKEFLAGS.
+
+Fri Sep 17 00:37:18 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* remake.c (update_file_1): Use .DEFAULT cmds for phony targets.
+
+	* make.h [_AIX && _POSIX_SOURCE]: Define POSIX.
+
+	* commands.c (delete_child_targets): Don't delete phony files.
+
+	* job.c (start_job_command): Set COMMANDS_RECURSE in FLAGS if we
+	see a `+' at the beginning of the command line.
+
+Thu Sep  9 17:57:14 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.6.
+
+Wed Sep  8 20:14:21 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (define_makeflags): Define MAKEFLAGS with o_file, not o_env.
+
+Mon Aug 30 12:31:58 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* expand.c (variable_expand): Fatal on an unterminated reference.
+
+Thu Aug 19 16:27:53 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.5.
+
+	* variable.c (define_automatic_variables): Define new o_default
+	variable `MAKE_VERSION' from version_string and remote_description.
+
+	* make.h (version_string, remote_description): Declare these here.
+	* main.c: Don't declare version_string.
+	(print_version): Don't declare remote_description.
+
+Wed Aug 18 15:01:24 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Free space pointed to by CONDITIONALS
+	before restoring the old pointer.
+
+Mon Aug 16 17:33:36 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile ($(objs)): Depend on config.h.
+
+	* GNUmakefile (build.sh.in): Depend on compatMakefile.
+
+	* configure.in: Touch stamp-config after AC_OUTPUT.
+
+Fri Aug 13 16:04:22 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.4.
+
+Thu Aug 12 17:18:57 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h: Include <config.h> instead of "config.h".
+
+Wed Aug 11 02:35:25 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (main): Make all variables interned from ENVP be v_export.
+	* variable.c (try_variable_definition): In v_default case, don't
+	check for an o_file variable that `getenv' finds.
+
+	* job.c (reap_children): New local variable ANY_LOCAL; set it
+	while setting ANY_REMOTE.  If !ANY_LOCAL, don't wait for local kids.
+
+	* main.c (main): Don't call decode_env_switches on MFLAGS.  DOC THIS.
+
+	* function.c (expand_function): #if 0 out freeing of ENVP since it
+	is environ.
+
+Mon Aug  9 17:37:20 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.3.
+
+	* remote-stub.c (remote_status): Set errno to ECHILD before return.
+	* job.c (reap_children): Scan the chain for remote children and
+	never call remote_status if there are none.
+
+	* function.c (expand_function: `shell'): #if 0 out calling
+	target_environment; just set ENVP to environ instead.
+
+	* job.c (reap_children): Check for negative return from
+	remote_status and fatal for it.
+	When blocking local child wait returns 0, then try a blocking call
+	to remote_status.
+
+Tue Aug  3 00:19:00 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (clean): Delete make.info* and make.dvi here.
+	(distclean): Not here.
+
+	* dep.h (RM_*): Use #defines instead of enum to avoid lossage from
+	compilers that don't like enum values used as ints.
+
+Mon Aug  2 16:46:34 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (loadavg): Add $(LOADLIBES).
+
+Sun Aug  1 16:01:15 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.2.
+
+	* compatMakefile (loadavg, check-loadavg): New targets.
+	(check): Depend on check-loadavg.
+
+	* compatMakefile (glob/libglob.a): Depend on config.h.
+
+	* misc.c (log_access): Write to stderr instead of stdout.
+
+Fri Jul 30 00:07:02 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.1.
+
+Thu Jul 29 23:26:40 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in (SYS_SIGLIST_DECLARED): In test program include
+	<unistd.h> #ifdef HAVE_UNISTD_H.
+
+	* compatMakefile (.PHONY): Put after `all' et al.
+
+	* configure.in: Add AC_IRIX_SUN.
+
+Wed Jul 28 17:41:12 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.68.
+
+Mon Jul 26 14:36:49 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.8.
+
+Sun Jul 25 22:09:08 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.7.
+
+	* compatMakefile ($(infodir)/make.info): Don't use $(instname).
+	Run install-info script if present.
+
+Fri Jul 23 16:03:50 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h [STAT_MACROS_BROKEN]: Test this instead of [uts].
+
+	* configure.in: Add AC_STAT_MACROS_BROKEN.
+
+Wed Jul 14 18:48:11 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.6.
+
+	* read.c (read_makefile): Recognize directive `-include', like
+	`include' but sets RM_DONTCARE flag.
+
+	* variable.c (target_environment): If FILE is nil, use
+	current_variable_set_list in place of FILE->variables.
+	* function.c (expand_function: `shell'): Get an environment for
+	the child from target_environment instead of using environ.
+
+	* dep.h: Declare read_all_makefiles here.
+	(RM_*): Define new enum constants.
+	* read.c (read_makefile): Second arg is FLAGS instead of TYPE.
+	Treat it as a bit mask containing RM_*.
+	(read_all_makefiles): For default makefiles, set D->changed to
+	RM_DONTCARE instead of 1.
+	* main.c: Don't declare read_all_makefiles here.
+	(main): Check `changed' member of read_makefiles elts for RM_*
+	flags instead of specific integer values.
+
+Mon Jul 12 22:42:17 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h [sequent && i386]: #undef POSIX.  From trost@cse.ogi.edu.
+
+Thu Jul  8 19:51:23 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* vpath.c (construct_vpath_list): If ELEM is zero 0, free PATTERN
+	as well as VPATH.
+	(build_vpath_lists): Empty `vpaths' around construct_vpath_list
+	call for $(VPATH).  Expand $(strip $(VPATH)), not just $(VPATH).
+
+	* rule.c (convert_suffix_rule): Use alloca instead of xmalloc for
+	PERCENTS, whose storage is not consumed by create_pattern_rule.
+
+	* make.h [__mips && _SYSTYPE_SVR3]: #undef POSIX.
+
+Wed Jun 30 18:11:40 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.5.
+
+	* rule.c (max_pattern_targets): New variable.
+	(count_implicit_rule_limits): Compute its value.
+	* rule.h: Declare it.
+	* implicit.c (pattern_search): Make TRYRULES max_target_patterns
+	times bigger.  Move adding new TRYRULES elt inside the inner
+	targets loop, so each matching target gets its own elt in MATCHES
+	and CHECKED_LASTSLASH.
+
+	* file.c (remove_intermediates): If SIG!=0 say `intermediate file'
+	instead of just `file' in error msg.
+
+Fri Jun 25 14:55:15 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv): Turn off
+	--warn-undefined-variables around expansion of SHELL and IFS.
+	* read.c (tilde_expand): Likewise for HOME.
+	(read_all_makefiles): Likewise for MAKEFILES.
+	* vpath.c (build_vpath_lists): Likewise for VPATH.
+
+	* main.c (warn_undefined_variables_flag): New flag variable.
+	(switches): Add --warn-undefined-variables.
+	* make.h (warn_undefined_variables_flag): Declare it.
+	* expand.c (warn_undefined): New function.
+	(reference_variable): Call it if the variable is undefined.
+	(variable_expand): In substitution ref, call warn_undefined if the
+	variable is undefined.
+
+	* default.c (default_pattern_rules): Add `%.c: %.w %.ch' and
+	`%.tex: %.w %.ch' rules.
+	(default_suffix_rules: .w.c, .w.tex): Pass three args: $< - $@.
+	(default_suffixes): Add `.ch'.
+
+Mon Jun 21 17:55:39 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* default.c (default_suffixes): Replace `.cweb' with `.w'.
+	(default_suffix_rules): Rename `.cweb.c' and `.cweb.tex' to `.w.c'
+	and `.w.tex'.
+
+Fri Jun 11 14:42:09 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile ($(bindir)/$(instname)): Add missing backslash.
+
+Thu Jun 10 18:14:08 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.4.
+
+	* read.c (multi_glob): Don't free OLD and OLD->name in the
+	FOUND!=0 fork.  Use new block-local variable F instead of
+	clobbering OLD.
+
+	* ar.c (glob_pattern_p): New function, snarfed from glob/glob.c.
+	(ar_glob): Call it; return nil immediately if MEMBER_PATTERN
+	contains no metacharacters.
+
+Wed Jun  9 16:25:35 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* ar.c (ar_glob{_match,_alphacompare}): New function.
+
+	* dep.h [! NO_ARCHIVES]: Declare it.
+	* read.c (multi_glob) [! NO_ARCHIVES]: Use it on archive member elts.
+
+	* read.c (read_makefile): Pass flag (1) to parse_file_seq, not to
+	multi_glob (which doesn't take a 3rd arg).
+	* rule.c (install_pattern_rule): Likewise.
+	* default.c (set_default_suffixes): Here too.
+	* function.c (string_glob): Don't pass gratuitous arg to multi_glob.
+
+	* read.c (parse_file_seq) [! NO_ARCHIVES]: Add post-processing
+	loop to translate archive refs "lib(a b)" into "lib(a) lib(b)".
+
+Mon Jun  7 19:26:51 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (installdirs): Actually pass directory names.
+	($(bindir)/$(instname)): Test chgrp&&chmod exit status with `if';
+	if it fails, echo a warning msg, but don't make the rule fail.
+
+	* read.c (tilde_expand): New function, broken out of tilde_expand.
+	(multi_glob): Call it.
+	(construct_include_path): Expand ~ in directory names.
+	* dep.h: Declare tilde_expand.
+	* main.c (enter_command_line_file): Expand ~ at the start of NAME.
+	(main): Expand ~ in -C args.
+	* read.c (read_makefile): Expand ~ in FILENAME unless TYPE==2.
+
+Fri Jun  4 13:34:47 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (decode_env_switches): Use xmalloc instead of alloca for ARGS.
+
+	* main.c (main): Put result of alloca in temporary variable with
+	simple assignment, to make SGI compiler happy.
+
+Thu Jun  3 20:15:46 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.3.
+
+	* main.c (main): Before re-execing, remove intermediate files, and
+	print the data base under -p.  Sexier debugging message.
+
+	* implicit.c (pattern_search): Allocate an extra copy of the name
+	of a winning intermediate file when putting it in FOUND_FILES.
+
+Wed Jun  2 16:38:08 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Pass flag (1) to parse_file_seq, not to
+	multi_glob (which doesn't take a 3rd arg).
+
+	* dir.c (dir_contents_file_exists_p): When reading dirents, ignore
+	chars within D_NAMLEN that are NULs.
+
+	* main.c (decode_switches): Don't savestring ARGV[0] to put it
+	into `other_args'.
+	For string switch, don't savestring `optarg'.
+	(main): Don't free elts of makefiles->list that are "-".
+	Use alloca'd rather than savestring'd storage for elts of
+	makefiles->list that are temporary file names.
+	* read.c (read_all_makefiles): Don't free *MAKEFILES.
+	* file.c (enter_file): Don't strip `./'s.
+	* main.c (enter_command_line_file): New function.
+	(main): Use it in place of enter_file for command-line goals from
+	other_files, and for old_files and new_files.
+
+Mon May 31 18:41:40 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.2.
+
+	* compatMakefile (.SUFFIXES): Add .info.
+	($(infodir)/$(instname).info): Find make.info* in cwd if there,
+	else in $srcdir.  Use basename to remove dir name from installed name.
+
+Thu May 27 17:35:02 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* implicit.c (pattern_search): When interning FOUND_FILES, try
+	lookup_file first; if found, free the storage for our copy of the name.
+
+Wed May 26 14:31:20 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.1.
+
+	* main.c (decode_switches): In usage msg, write `--switch=ARG' or
+	`--switch[=OPTARG]' rather than `--switch ARG' or `--switch [ARG]'.
+
+Mon May 24 16:17:31 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* rule.c (convert_suffix_rule): New function.
+	(convert_to_pattern): Use it instead of doing all the work here
+	several times.
+	For target suffix `.a', generate both the archive magic rule and
+	the normal rule.
+
+	* compatMakefile (distclean): Remove stamp-config.
+
+Sat May 22 16:15:18 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.67.
+
+	* file.c (remove_intermediates): Don't write extra space after `rm'.
+
+	* main.c (struct command_switch.type): Remove `usage_and_exit'.
+	(print_usage_flag): New variable.
+	(switches: --help): Make type `flag', to set print_usage_flag.
+	(init_switches): Remove `usage_and_exit' case.
+	(decode_switches): Likewise.
+	(decode_switches): Print usage if print_usage_flag is set.
+	When printing usage, die with status of BAD.
+	(main): Die with 0 if print_version_flag.
+
+Fri May 21 16:09:28 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.66.
+
+Wed May 19 21:30:44 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (installdirs): New target.
+	(install): Depend on it.
+
+Sun May 16 20:15:07 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.65.2.
+
+Fri May 14 16:40:09 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* vpath.c (construct_vpath_list): In removal loop for DIRPATH==0,
+	set LASTPATH to PATH, not NEXT.
+
+	* dir.c (read_dirstream): Break out of loop after incrementing
+	DS->buckets such that it reaches DIRFILE_BUCKETS; avoid trying to
+	dereference DS->contents->files[DIRFILE_BUCKETS].
+
+	* read.c (read_makefile): Clear no_targets after reading a
+	targetful rule line.
+
+	* main.c (main): If print_version_flag is set, exit after printing
+	the version.
+	(switches): Change --version docstring to say it exits.
+
+	* make.h [butterfly]: #undef POSIX.
+
+Wed May 12 15:20:21 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.65.1.
+
+	* arscan.c (ar_scan) [! AIAMAG]: Don't declare LONG_NAME.
+	[AIAMAG]: Pass TRUNCATE flag arg to (*FUNCTION), always zero.
+
+	* function.c (handle_function): Use fatal instead of
+	makefile_fatal when reading_filename is nil.
+
+	* configure.in: Add AC_GETGROUPS_T.
+	* job.c (search_path): Use GETGROUPS_T in place of gid_t.
+
+Sun May  9 15:41:25 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.65.
+
+Fri May  7 18:34:56 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* function.c (handle_function): Fatal for unmatched paren.
+
+Thu May  6 16:13:41 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.64.3.
+
+	* commands.c (handling_fatal_signal): New variable.
+	(fatal_error_signal): Set it.
+	* job.c (reap_children): Avoid nonreentrant operations if that is set.
+	* make.h: Declare handling_fatal_signal.
+
+	* expand.c (reference_variable): New function, snippet of code
+	broken out of simple-reference case of variable_expand.
+	(variable_expand): Use it for simple refs.
+	(variable_expand): When checking for a computed variable name,
+	notice a colon that comes before the final CLOSEPAREN.  Expand
+	only up to the colon, and then replace the pending text with a
+	copy containing the expanded name and fall through to subst ref
+	handling.
+	(variable_expand): Don't bother expanding the name if a colon
+	appears before the first $.
+	(expand_argument): Use alloca instead of savestring.
+	(variable_expand): For subst ref, expand both sides of = before
+	passing to [pat]subst_expand.  Use find_percent instead of lindex
+	to check the lhs for a %.
+
+Wed May  5 14:45:52 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.64.2.
+
+Mon May  3 17:00:32 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* arscan.c (ar_name_equal) [AIAMAG]: Abort if TRUNCATED is nonzero.
+
+	* read.c (read_makefile): Pass extra arg of 1 to parse_file_seq,
+	not to multi_glob.
+
+Thu Apr 29 19:47:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.64.1.
+
+	* arscan.c (ar_scan): New local flag var LONG_NAME.  Set it when
+	we read the member name in any of the fashions that allow it to be
+	arbitrarily long.  Pass its negation to FUNCTION.
+	(describe_member): Take TRUNCATED from ar_scan and print it.
+	(ar_name_equal): Take new arg TRUNCATED; if nonzero, compare only
+	the first sizeof (struct ar_hdr.ar_name) chars.
+	(ar_member_pos): Take TRUNCATED from ar_scan, pass to ar_name_equal.
+	* ar.c (ar_member_date_1): Likewise.
+
+Wed Apr 28 21:18:22 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (reap_children): Before calling start_job_command to start
+	the next command line, reset C->remote by calling start_remote_job_p.
+
+Mon Apr 26 15:56:15 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* arscan.c (ar_scan): New local var NAMEMAP.
+	In loop, rename NAME to NAMEBUF; new var NAME is a pointer; new
+	flag IS_NAMEMAP.  When extracting the member name, always put a
+	null at its end first.  If the name is "//" or "/ARFILENAMES", set
+	IS_NAMEMAP.  If we have already read in NAMEMAP, and NAME looks
+	like " /N", get full name from NAMEMAP+N.
+	Else if NAME looks like "#1/N", read N chars from the
+	elt data to be the full name.  At end of loop, if IS_NAMEMAP, read
+	the elt's data into alloca'd NAMEMAP.
+	(ar_name_equal): #if 0 truncating code.
+
+	* make.h: Don't declare vfork at all.  It returns int anyway,
+	unless <unistd.h> declared it; and we conflicted with some systems.
+
+	* main.c (define_makeflags): If FLAGSTRING[1] is '-', define
+	MAKEFLAGS to all of FLAGSTRING, not &FLAGSTRING[1].  Don't want to
+	define it to something like "-no-print-directory".
+	Use %g format instead of %f for floating-valued things.
+
+Thu Apr 22 18:40:58 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* GNUmakefile (Makefile.in): Use a substitution ref on nolib-deps
+	to change remote-%.dep to remote-stub.dep.
+
+Wed Apr 21 15:17:54 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.64.
+
+Fri Apr 16 14:22:22 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (install): Remove - prefix from chgrp+chmod.
+
+	* Version 3.63.8.
+
+Thu Apr 15 18:24:07 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* acconfig.h: New file; contains "#undef SCCS_GET" for autoheader.
+	* configure.in: If /usr/sccs/get exists, define SCCS_GET to that,
+	else to "get".
+	* default.c (default_variables): Set GET to macro SCCS_GET.
+
+	* read.c (parse_file_seq): Take extra arg STRIP; strip `./' only
+	if nonzero.  I hope this is the last time this argument is added
+	or removed.
+	(read_makefile): Pass it 1 when parsing include file names.
+	Pass it 1 when parsing target file names.
+	Pass it 1 when parsing static pattern target pattern names.
+	* rule.c (install_pattern_rule): Pass it 1 when parsing rule deps.
+	* default.c (set_default_suffixes): Pass it 1 when parsing
+	default_suffixes.
+	* function.c (string_glob): Pass it 0 here.
+
+Wed Apr 14 11:32:05 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* misc.c (log_access): New function.
+	({init,user,make,child}_access): Call it.
+	(child_access): Abort if !access_inited.
+
+	* main.c (switches: --no-print-directory): Use 1 instead of -1 for
+	single-letter option.
+	(init_switches, decode_switches, define_makeflags): An option with
+	no single-letter version is no longer indicated by a value of -1;
+	instead a value that is !isalnum.
+	(init_switches): Don't put such switches into the string, only
+	into the long_option table.
+
+	* make.h [!NSIG] [!_NSIG]: #define NSIG 32.
+
+	* job.c [HAVE_WAITPID]: Remove #undef HAVE_UNION_WAIT.  AIX's
+	bsdcc defined WIF* to use union wait.
+
+	* main.c (struct command_switch): Change member `c' to type int.
+	(switches): Make const.
+	(decode_switches): Use `const struct command_switch *'.
+	(define_makeflags): Likewise.
+
+	* default.c (default_suffix_rules): Add `-o $@' to makeinfo rules.
+
+Mon Apr 12 12:30:04 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.63.7.
+
+	* configure.in (AC_HAVE_HEADERS): Check for string.h and memory.h.
+	Removed AC_MEMORY_H.
+	* make.h [USG, NeXT]: Don't test these.
+	[HAVE_STRING_H]: Test this to include string.h and define ANSI_STRING.
+	[HAVE_MEMORY_H]: Test this instead of NEED_MEMORY_H.
+	[! ANSI_STRING]: Put decls of bcopy et al here.
+	[sparc]: Don't test this for alloca.h; HAVE_ALLOCA_H is sufficient.
+	[HAVE_SIGSETMASK]: Test this rather than USG.
+	[__GNU_LIBRARY__ || POSIX]: Don't #include <unistd.h> again.
+	* main.c (main): Handle SIGCHLD if defined, and SIGCLD if defined.
+	It doesn't hurt to do both if they are both defined, and testing
+	USG is useless.
+	* dir.c: Rationalize directory header conditionals.
+	* arscan.c [HAVE_FCNTL_H]: Test this rather than USG || POSIX.
+
+	* default.c (default_suffixes): Add `.txinfo'.
+	(default_suffix_rules): Add `.txinfo.info' and `.txinfo.dvi' rules.
+
+	* variable.c (try_variable_definition): Replace RECURSIVE flag
+	with enum FLAVOR, which can be simple, recursive, or append.
+	Recognize += as append flavor.  Set new variable VALUE in a switch
+	on FLAVOR.  For append flavor, prepend the variable's old value.
+	If the variable was previously defined recursive, set FLAVOR to
+	recursive; if it was defined simple, expand the new value before
+	appending it to the old value.  Pass RECURSIVE flag to
+	define_variable iff FLAVOR == recursive.
+
+	* variable.c (try_variable_definition): Use alloca and bcopy for
+	NAME, instead of savestring.  Might as well use stack storage
+	since we free it immediately anyway.
+
+Thu Apr  8 18:04:43 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (start_waiting_jobs): Move decl of JOB outside of loop.
+
+	* main.c (define_makeflags): Rename `struct flag' member `switch'
+	to `cs', which is not a reserved word.
+
+Wed Apr  7 15:30:51 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (new_job): Call start_waiting_jobs first thing.
+	(start_waiting_job): Changed return type from void to int.
+	Return 0 when putting the child on the waiting_jobs chain.
+	(start_waiting_jobs): Don't check load and job_slots here.
+	Always take a job off the chain and call start_waiting_job on it;
+	give up and return when start_waiting_job returns zero.
+
+	* main.c (define_makeflags: struct flag): Change member `char c' to
+	`struct command_switch *switch'.
+	(ADD_FLAG): Set that to CS instead of CS->c.
+	If CS->c is -1, increment FLAGSLEN for the long name.
+	When writing out FLAGS, handle FLAGS->switch->c == -1 and write
+	the long name instead.
+
+	* compatMakefile (stamp-config): New target of old config.h rule.
+	Touch stamp-config after running config.status.
+	(config.h): Just depend on stamp-config, and have empty commands.
+
+Mon Apr  5 20:14:02 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c [HAVE_WAITPID]: #undef HAVE_UNION_WAIT.
+
+	* configure.in (AC_HAVE_FUNCS): Check for psignal.
+
+Fri Apr  2 17:15:46 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (long_option_aliases): Remove "new"; it is already an
+	unambiguous prefix of "new-file".
+
+Sun Mar 28 16:57:17 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.63.6.
+
+Wed Mar 24 14:26:19 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* vpath.c (selective_vpath_search): When adding the
+	name-within-directory at the end of NAME, and we don't add a
+	slash, don't copy FILENAME in one char too far into NAME.
+
+	* variable.c (define_automatic_variables): Find default_shell's
+	length with strlen, not numerology.
+
+Wed Mar 17 20:02:27 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (define_makeflags): Add the elts of a string option in
+	reverse order, so they come out right when reversed again.
+
+Fri Mar 12 15:38:45 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* compatMakefile (make.info): Use `-o make.info'.
+
+Thu Mar 11 14:13:00 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* compatMakefile (REMOTE): Set to @REMOTE@; change comments to
+	reflect new use.
+	(objs): Replace remote.o with remote-$(REMOTE).o.
+	(srcs): Replace remote.c with remote-$(REMOTE).c.
+	(remote.o): Rule removed.
+
+	* configure.in (REMOTE): Subst this in Makefile et al; default "stub".
+	Use AC_WITH to grok --with-customs arg to set REMOTE=cstms.
+	* GNUmakefile (build.sh.in): Filter out remote-% from objs list.
+	* build.template (REMOTE): New var; set to @REMOTE@.
+	(objs): Add remote-${REMOTE}.o.
+
+Wed Mar 10 15:12:24 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.63.5.
+
+	* implicit.c (pattern_search): Fix "dependent"->"dependency" in
+	"Rejecting impossible" -d msg.
+
+	* file.c (file_hash_enter): New local vars {OLD,NEW}BUCKET.  Store
+	mod'd values there; never mod {OLD,NEW}HASH.
+
+Mon Mar  8 13:32:48 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* remake.c [eta10]: Include <fcntl.h> instead of <sys/file.h>.
+
+	* compatMakefile (VPATH): Set this to @srcdir@.
+	(srcdir): Set this to $(VPATH).
+
+	* main.c (main): New local var DIRECTORY_BEFORE_CHDIR.  Save in it
+	a copy of CURRENT_DIRECTORY after the first getcwd.  Use it
+	instead of CURRENT_DIRECTORY when chdir'ing back before re-execing.
+
+	* remake.c (notice_finished_file): Pass missing SEARCH arg to f_mtime.
+
+	* read.c (read_makefile): Remove extraneous arg to parse_file_seq.
+
+Mon Feb 22 14:19:38 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile ($(infodir)/$(instname).info): Use , instead of /
+	as the sed delimiter char.
+
+Sun Feb 21 14:11:04 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.63.4.
+
+	* rule.h (struct rule): Removed `subdir' member.
+	* rule.c (new_pattern_rule): No need to clear it.
+	(count_implicit_rule_limits): Set the `changed' flag in each dep
+	that refers to a nonexistent directory.  No longer set rule-global
+	`subdir' flag with that information.
+	(print_rule_data_base): Don't record info on `subdir' flags.
+
+	* implicit.c (pattern_search): Check the DEP->changed flag rather
+	than the (now gone) RULE->subdir flag.  Also test CHECK_LASTSLASH;
+	if it is set, the file might exist even though the DEP->changed
+	flag is set.
+
+	* rule.c (count_implicit_rule_limits): Pass "", not ".", as file
+	name arg to dir_file_exists_p to check for existence of directory.
+
+	* implicit.c (pattern_search): Inside dep-finding loop, set
+	CHECK_LASTSLASH from the value recorded in CHECKED_LASTSLASH[I],
+	rather than computing it anew.
+
+	* commands.c (set_file_variables): Must alloca space for PERCENT
+	and copy it, to avoid leaving the trailing `)' in the value.
+
+	* misc.c (remove_comments): Fixed backslash-checking loop
+	condition to allow it to look at the first char on the line.
+	P2 >= LINE, not P2 > LINE.
+
+	* compatMakefile ($(bindir)/$(instname)): Before moving $@.new to
+	$@, rm $@.old and mv $@ to $@.old.
+
+	* variable.c (try_variable_definition): Take new args FILENAME and
+	LINENO.  Fatal if the variable name is empty.
+	* read.c (read_makefile): Change callers.
+	* main.c (main): Likewise.
+
+	* compatMakefile (group): Define to @KMEM_GROUP@, autoconf magic
+	that configure will replace with the group owning /dev/kmem.
+
+Mon Feb  8 14:26:43 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* vpath.c (vpath_search): Take second arg MTIME_PTR, pass thru to
+	selective_vpath_search.
+	(selective_vpath_search): Take second arg MTIME_PTR.
+	If the dir cache thinks a file exists, stat it to make sure, and
+	put the modtime in *MTIME_PTR.
+	* remake.c (library_search): Take second arg MTIME_PTR.
+	When we find a match, record its mtime there.
+	Pass MTIME_PTR through to vpath_search to do same.
+	(f_mtime): Pass &MTIME as new 2nd arg to {vpath,library}_search;
+	store it in FILE->last_mtime if set nonzero.
+	* implicit.c (pattern_search): Pass nil 2nd arg to vpath_search.
+
+	* compatMakefile (remote.o): Prepend `$(srcdir)/' to `remote-*.c',
+	so globbing looks somewhere it will find things.
+
+	* compatMakefile ($(infodir)/$(instname).info): Install `make.info*'
+	not `$(srcdir)/make.info*'; no need to use basename.
+
+Fri Feb  5 12:52:43 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.63.3.
+
+	* compatMakefile (install): Add missing ;\s.
+
+	Make -, @, and + prefixes on a pre-expanded command line affect
+	all lines in the expansion, not just the first.
+	* commands.h (struct commands): Replace `lines_recurse' member
+	with `lines_flags'.
+	(COMMANDS_{RECURSE,SILENT,NOERROR}): New macros, bits to set in
+	that flag byte.
+	* commands.c (chop_commands): Set `lines_flags' instead of
+	`lines_recurse'.  Record not only + but also @ and - prefixes.
+	* remake.c (notice_finished_file): Check the COMMANDS_RECURSE bit
+	in FILE->cmds->lines_flags, rather than FILE->cmds->lines_recurse.
+	* job.c (start_job_command): Replaced RECURSIVE and NOPRINT local
+	var with FLAGS; initialize it to the appropriate `lines_flags' byte.
+	Set CHILD->noerror if the COMMANDS_NOERROR bit is set in FLAGS.
+	Set the COMMANDS_SILENT bit in FLAGS for a @ prefix.
+
+	* remake.c (update_goal_chain): Set G->file to its prev after
+	checking for G being finished, since that check needs to examine
+	G->file.
+
+	* configure.in (union wait check) [HAVE_WAITPID]: Try using
+	waitpid with a `union wait' STATUS arg.  If waitpid and union wait
+	don't work together, we should not use union wait.
+
+	* Version 3.63.2.
+
+	* remake.c (update_goal_chain): When G->file->updated, move
+	G->file to its prev.  We aren't finished until G->file is nil.
+
+Thu Feb  4 12:53:04 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (starting_directory): New global variable.
+	(main): Set it to cwd after doing -Cs.
+	(log_working_directory): Use it, rather than computing each time.
+	* make.h: Declare it.
+
+	* compatMakefile (SHELL): Define to /bin/sh for losing Unix makes.
+
+	* main.c (decode_env_switches): Allocate (1 + LEN + 1) words for
+	ARGV, rather than LEN words plus one byte.
+
+Wed Feb  3 18:13:52 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* compatMakefile ($(bindir)/$(instname)): Put - before
+	install_setgid command line, so its failure won't be an error.
+	(infodir): New variable.
+	(install): Depend on $(infodir)/$(instname).info.
+	($(infodir)/$(instname).info): New target.
+
+	* read.c (read_makefile): If FILENAMES is nil when we see a line
+	starting with a tab, don't treat it as a command.  Just fall
+	through, rather than giving an error.
+
+	* read.c (read_makefile): If the NO_TARGETS flag is set when we see a
+	command line, don't clear it before continuing.  We want
+	subsequent command lines to be ignored as well.
+
+	* job.c (new_job): Before expanding each command line, collapse
+	backslash-newline combinations that are inside var or fn references.
+
+Mon Feb  1 16:00:13 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* compatMakefile (exec_prefix): Default to $(prefix), not /usr/local.
+
+	* compatMakefile (make.info): Pass -I$(srcdir) to makeinfo.
+
+	* job.c [POSIX] (unblock_sigs): Made global.
+	[!POSIX] (unblock_sigs): Move defns to job.h.
+	* job.h [POSIX] (unblock_sigs): Declare.
+
+Sun Jan 31 19:11:05 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): In vpath parsing, after finding the
+	pattern token, take entire rest of line as the search path, not
+	just the next token.
+
+	* compatMakefile (remote.o): Depend on remote-*.c.
+
+Thu Jan 28 16:40:29 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* commands.c (set_file_variables): Don't define any F or D versions.
+	* variable.c (define_automatic_variables): Define them here as
+	recursively-expanded variables that use the dir and notdir funcs.
+
+	* variable.c (target_environment): In v_default case, don't export
+	o_default or o_automatic variables.
+
+	* configure.in (union wait check): Remove ` and ' inside C code;
+	they confuse the shell script.
+
+Mon Jan 25 13:10:42 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.63.1.
+
+	* vpath.c (construct_vpath_list): When skipping further processing
+	of an elt that is ".", don't also skip the code that pushes P past
+	the next separator.
+
+	* compatMakefile (distclean): Don't remove make-*.
+
+	* configure.in (HAVE_UNION_WAIT): Try to use WEXITSTATUS if it's
+	defined.  If one cannot use WEXITSTATUS with a `union wait'
+	argument, we don't want to believe the system has `union wait' at all.
+
+	* remake.c (update_file): Do nothing to print "up to date" msgs.
+	(update_goal_chain): Do it here instead.
+	Use the `changed' flag of each goal's `struct dep' to keep track
+	of whether files_remade (now commands_started) changed around a
+	call to update_file for that goal.
+	When a goal is finished, and its file's update_status is zero (i.e.,
+	success or nothing done), test the `changed' flag and give an "up
+	to date" msg iff it is clear.
+	* make.h (files_remade): Renamed to commands_started.
+	* remake.c: Changed defn.
+	(update_goal_chain): Changed uses.
+	* job.c (start_job_command): Increment commands_started here.
+	(reap_children): Not here.
+
+	* remake.c (update_goal_chain): Don't do anything with files'
+	`prev' members.  update_file now completely handles this.
+
+	* variable.c (target_environment): Don't expand recursive
+	variables if they came from the environment.
+
+	* main.c (define_makeflags): For flags with omitted optional args,
+	store {"", 0} with ADD_FLAG.  When constructing FLAGSTRING, a flag
+	so stored cannot have more flags appended to the same word.
+
+Fri Jan 22 14:46:16 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* variable.c (print_variable_set): In vars/bucket calculation,
+	don't spuriously multiply by 100.
+
+	* Version 3.63.
+
+	* job.c [!HAVE_UNION_WAIT] (WTERMSIG, WCOREDUMP, WEXITSTATUS):
+	Don't define if already defined.
+
+	* remake.c (update_file): Don't keep track of the command_state before
+	calling update_file_1.  Remove local variable COMMANDS_FINISHED,
+	and don't test it to decide to print the "is up to date" msg.
+	Testing for files_remade having changed should always be sufficient.
+	The old method lost when we are called in the goal chain run on a
+	makefile, because the makefile's command_state is already
+	`cs_finished' from the makefile chain run.
+
+	* misc.c [HAVE_SETRE[GU]ID]: Test these to decl setre[gu]id.
+
+	* configure.in: Rewrote wait checking.
+	Use AC_HAVE_HEADERS to check for <sys/wait.h>.
+	Use AC_HAVE_FUNCS to check for waitpid and wait3.
+	Use a compile check to test just for `union wait'.
+	* job.c: Rewrote conditionals accordingly.
+	[HAVE_WAITPID]: Test this only to define WAIT_NOHANG.
+	[HAVE_WAIT3]: Likewise.
+	[HAVE_UNION_WAIT]: Test this to define WAIT_T and W*.
+
+	* configure.in: Set CFLAGS and LDFLAGS before all checks.
+
+	* dir.c: Add static forward decls of {open,read}_dirstream.
+
+Thu Jan 21 17:18:00 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.31.
+
+	* job.c [NGROUPS_MAX && NGROUPS_MAX==0]: #undef NGROUPS_MAX.
+
+	* compatMakefile (CFLAGS, LDFLAGS): Set to @CFLAGS@/@LDFLAGS@.
+	* build.template (CFLAGS, LDFLAGS): Same here.
+	* configure.in: AC_SUBST(CFLAGS) and LDFLAGS.
+	Set them to -g if not defined in the environment.
+
+	* remake.c (library_search): Use LIBNAME consistently, setting it
+	only once, to be the passed name sans `-l'.
+	Pass new var FILE to be modified by vpath_search.
+
+Mon Jan 18 14:53:54 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.30.
+
+	* job.c (start_waiting_jobs): Return when job_slots_used is equal to
+	job_slots.
+
+	* configure.in: Add AC_CONST for the sake of getopt.
+
+	* read.c (read_makefile): Continue after parsing `override'
+	directive, rather than falling through to lossage.
+	Check for EOL or blank after "override define".
+
+	* compatMakefile (.c.o, remote.o): Put $(CFLAGS) after other switches.
+
+Fri Jan 15 12:52:52 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.29.
+
+	* main.c (define_makeflags): After writing everything into
+	FLAGSTRING, only back up two chars if [-1] is a dash, meaning we
+	just wrote " -".  Always terminate the string at *P.
+
+	* remake.c (library_search): When constructing names in std dirs,
+	use &(*LIB)[2] for the stem, not LIBNAME (which points at the
+	buffer we are writing into!).
+
+Thu Jan 14 13:50:06 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Set IN_IGNORED_DEFINE for "override
+	define" when IGNORING is true.
+
+	* compatMakefile (distclean): Remove config.status and build.sh.
+
+Wed Jan 13 16:01:12 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.28.
+
+	* misc.c (xmalloc, xrealloc): Cast result of malloc/realloc to
+	(char *).
+
+	* arscan.c (ar_scan) [AIAMAG]: Cast read arg to (char *).
+
+	* variable.c (define_automatic_variables): Override SHELL value for
+	origin o_env_override as well as o_env.
+
+	* GNUmakefile (build.sh.in): Don't replace %globobjs%.  Instead,
+	add the names of the glob objects (w/subdir) to %objs%.
+	* build.template (globobjs): Removed.
+	Take basename of $objs before linking.
+
+Tue Jan 12 12:31:06 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.27.
+
+	* configure.in (AC_OUTPUT): Also edit build.sh.
+	* build.template: New file.
+	* GNUmakefile (build.sh.in): New rule to create it from build.template.
+	(make-$(version).tar.Z): Depend on build.sh.in.
+
+	* main.c (die): Call print_data_base if -p.
+	(main): Don't call it here.
+
+	* compatMakefile (defines): Add @DEFS@.  configure should turn this
+	into -DHAVE_CONFIG_H.
+
+Mon Jan 11 14:39:23 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.26.
+
+	* misc.c (init_access): Surround with #ifdef GETLOADAVG_PRIVILEGED.
+	({make,user,child}_access) [! GETLOADAVG_PRIVILEGED]: Make no-op.
+	* compatMakefile (install_setgid): New var, set by configure.
+	(install): Install setgid $(group) only if $(install_setgid) is true.
+
+Fri Jan  8 15:31:55 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (load_too_high): If getloadavg fails with errno==0, give a
+	message saying that load limits are not supported.
+
+	* vpath.c (construct_vpath_list): Rewrote path deletion code to
+	not try to use PATH's next link after freeing PATH.
+
+	* main.c (define_makeflags): Rewritten; now handles string-valued
+	option, and has no arbitrary limits.
+	(switches): Set `toenv' flag for -I and -v.
+
+	* main.c (decode_env_switches): Cast return value of alloca to char *.
+
+	* misc.c (child_access) [HAVE_SETREUID, HAVE_SETREGID]: Use
+	setre[gu]id in place of set[gu]id.
+
+Wed Jan  6 15:06:12 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (main): Define MAKEOVERRIDES, MAKE, and MAKE_COMMAND with
+	origin o_default.
+
+	* make.h [POSIX]: Don't test this to use ANSI_STRING.
+	Testing STDC_HEADERS should be sufficient.
+
+	* job.h: Declare start_waiting_jobs.
+
+	* read.c (read_makefile): Add missing parens in if stmt that find
+	conditional directives.
+
+	* main.c (main): Declare init_dir.
+	* implicit.c (pattern_search): Always use two % specs in a
+	DEBUGP2, and always pass two non-nil args.
+	Cast field width args to int.
+	Add missing parens in !RULE->subdir if stmt.
+	* function.c (expand_function, patsubst_expand): Add parens around
+	assignments inside `while' stmts.
+	* commands.c (print_commands): Cast field width args to int.
+
+	* read.c (do_define): Cast return value of alloca to (char *).
+
+	* main.c (init_switches): New function, broken out of decode_switches.
+	(decode_switches): Take new arg ENV.  If set, ignore non-option
+	args; print no error msgs; ignore options with clear `env' flags.
+	(decode_env_switches): Rewritten to chop envar value into words
+	and pass them to decode_switches.
+	(switches): Set `env' flag for -I and -v.
+
+	* dir.c (init_dir): Cast free to __glob_closedir_hook's type.
+
+Tue Jan  5 14:52:15 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.25.
+
+	* job.c [HAVE_SYS_WAIT || !USG]: Don't #include <sys/time.h> and
+	<sys/resource.h>.  <sys/time.h> interacts badly with <time.h>, and
+	we don't need these anyway.
+
+	* configure.in (AC_HAVE_FUNCS): Check for setre[gu]id.
+	* misc.c ({user,make}_access): Test #ifndef HAVE_SETRE[GU]ID, not
+	#ifdef POSIX || USG.  SunOS 4.1 is supposedly POSIX.1 compliant,
+	but its set[gu]id functions aren't; its setre[gu]id functions work.
+
+	* misc.c ({user,make,child}_access): Give name of caller in error msgs.
+
+	* job.c (load_too_high): Say "cannot enforce load limit" in error msg.
+
+	* configure.in: Call AC_PROG_CC.
+	* compatMakefile (CC): Define to @CC@ (autoconf magic).
+
+	* compatMakefile: Add .NOEXPORT magic target.
+
+Mon Jan  4 17:00:03 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (print_version): Updated copyright to include 93.
+
+Thu Dec 31 12:26:15 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* make.h [_AIX]: Don't declare alloca.
+
+Tue Dec 29 13:45:13 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.24.
+
+	* compatMakefile (objs): Add signame.o.
+	(srcs): Add signame.[ch].
+
+	* compatMakefile (srcs): Add config.h.in.
+	(remote.o): Add -I. before -I$(srcdir).
+
+Mon Dec 28 15:51:26 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.23.
+
+	* read.c (readline): Fatal when LEN==0, indicating a line starting
+	with a NUL.
+	(readline): Take new arg LINENO, for use in error msg.
+	(read_makefile, do_define): Pass it.
+
+	* compatMakefile (glob/libglob.a): Pass -DHAVE_CONFIG_H in CPPFLAGS.
+	(.c.o): Add -I. before -I$(srcdir).
+
+Wed Dec 23 12:12:04 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Accept and ignore a rule with no targets.
+
+	* compatMakefile (ALLOCA_SRC): New variable.
+	(srcs): Include its value.
+
+	* read.c (struct conditional): Renamed member `max_ignoring' to
+	`allocated'; added new member `seen_else'.
+	(conditional_line): Initialize seen_else flag when starting an `if...';
+	set it when we see an `else'; fatal if set when we see `else'.
+	(read_makefile): Fatal "missing `endif'" if there are any pending
+	conditionals, not just if we are still ignoring.
+
+Tue Dec 22 15:36:28 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (manext): Set to 1, not l.
+	($(mandir)/$(instname).$(manext)): Use $(srcdir) for make.man in cmds.
+
+	* file.c (file_hash_enter): Don't call uniquize_deps here.
+	* read.c (record_files): Likewise.
+	* implicit.c (pattern_search): Likewise.
+	* commands.c (set_file_variables): Call it only here.
+
+	* default.c (default_variables) [__convex__]: FC=fc.
+
+	* variable.c (target_environment): Expand the values of recursively
+	expanded variables when putting them into the environment.
+	* expand.c (recursively_expand): Made global.
+	* make.h (recursively_expand): Declare it.
+
+	* remake.c (check_dep): Set FILE->command_state to cs_deps_running
+	when a dep's command_state is cs_running or cs_deps_running.
+
+	* read.c (read_makefile): Changed error msg for spurious cmds to
+	not say "first target".
+
+Sun Dec 20 17:56:09 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* configure.in: Do AC_CONFIG_HEADER right after AC_INIT.
+	* make.h (HAVE_CONFIG_H): #include "config.h", then #define this.
+	* compatMakefile (config.h, configure, config.h.in): New rules.
+	(defines): Removed @DEFS@.
+
+Thu Dec 17 16:11:40 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (realclean): Just depend on distclean; no cmds.
+	(distclean): Do what realclean did before; also remove Makefile and
+	config.h; don't remove configure.
+	(info, dvi): New targets; depend on make.{info,dvi}.
+	(doc): Removed target.
+	(MAKEINFO, TEXI2DVI): New vars.
+	(make.info, make.dvi): Use them instead of explicit cmds.
+
+Wed Dec 16 16:25:24 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* configure.in: Added fcntl.h to AC_HAVE_HEADERS.  getloadavg cares.
+
+Wed Dec  9 15:21:01 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (long_option_aliases): Add --new-file alias for -W.
+
+	* default.c (default_variables): Change all C++ to CXX and C++FLAGS
+	to CXXFLAGS.
+
+	* read.c (do_define): Expand the variable name before using it.
+
+	* main.c (main): Define variable "MAKE_COMMAND" to argv[0];
+	define "MAKE=$(MAKE_COMMAND) $(MAKEOVERRIDES)" always.
+
+	* remake.c (library_search): Search for libNAME.a in cwd; look in
+	vpath before looking in standard dirs, not after.
+	Changed order of std dirs to: /lib, /usr/lib, ${prefix}/lib.
+
+Mon Nov 23 14:57:34 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* default.c (default_pattern_rules, default_terminal_rules): Added
+	brackets around initializers.
+
+	* variable.c (try_variable_definition): Don't check for LINE[0]=='\t'.
+	(try_variable_definition): Expand the name before defining the var.
+
+	* job.c (init_siglist): Removed function.
+	Removed decl of `sys_siglist'.
+	* make.h [! HAVE_SYS_SIGLIST]: #include "signame.h".
+	[HAVE_SYS_SIGLIST && !SYS_SIGLIST_DECLARED]: Declare sys_siglist
+	only under these conditions.
+	* main.c (main): Don't declare init_siglist.
+	(main) [! HAVE_SYS_SIGLIST]: Call signame_init instead of init_siglist.
+
+Wed Nov 18 14:52:51 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (record_files): Don't try to append to FIRSTDEPS if it's
+	nil; instead just set it to MOREDEPS.
+
+Mon Nov 16 17:49:17 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* vpath.c (construct_vpath_list): Initialize P to DIRPATH before
+	loop that sets MAXELEM.
+
+Fri Nov 13 18:23:18 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.22.
+
+Thu Nov 12 15:45:31 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (start_job_command): Under -n, increment files_remade after
+	processing (i.e., printing) all command lines.
+
+Tue Nov 10 15:33:53 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* read.c (record_files): Append new deps if this rule has no
+	commands; prepend them to existing deps if this rule has no commands.
+
+	* dir.c (open_dirstream): Return nil if DIR->contents->files is nil.
+
+	* read.c (parse_file_seq): Removed last arg STRIP.  Always strip `./'s.
+	(read_makefile): Changed callers.
+	* function.c (string_glob): Likewise.
+	* rule.c (install_pattern_rule): Likewise.
+
+Mon Nov  9 17:50:16 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* remake.c (files_remade): Made global.
+	(notice_finished_file): Don't increment files_remade here; this
+	function gets called in many situations where no remaking was in
+	fact done.
+	* job.c (reap_children): Do it here instead, when we know that
+	actual commands have been run for the file.
+	* make.h (files_remade): Declare it.
+
+Thu Nov  5 18:26:10 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* vpath.c (construct_vpath_list): Allow blanks as well as colons to
+	separate elts in the search path.
+
+	* read.c (read_makefile): Don't fatal on extra tokens in `vpath'.
+	The search path can contain spaces now.
+
+Tue Nov  3 20:44:32 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* compatMakefile (check): New target; no-op.
+
+	* file.c (file_hash_enter): Mod OLDHASH by FILE_BUCKETS after
+	testing for OLDHASH==0 but before using the value.
+	(rename_file): Don't mod OLDHASH by FILE_BUCKETS before passing it
+	to file_hash_enter.
+
+	* file.c (rename_file): Notice when OLDFILE->cmds came from
+	default.c, and don't try to print ->filename in that case.
+
+Sun Oct 25 01:48:23 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* remake.c (update_file): Don't process F->also_make here.
+	(notice_finished_file): Don't process FILE->also_make if no attempt
+	to update FILE was actually made.
+	Fixed to call f_mtime directly to refresh their modtimes.
+
+Sat Oct 24 22:08:59 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (find_percent): Don't increment P again after skipping
+	an escaped %.
+
+	* expand.c (variable_expand): In call to patsubst_expand, don't
+	find `%'s ourselves; let that function do it.
+
+	* read.c (read_makefile: record_waiting_files): Don't call
+	record_files if FILENAMES is nil.
+	(read_makefile): All alternatives in the parsing, except for rule
+	lines, fall through to the end of the loop.  At the end of the
+	loop, do record_waiting_files so we notice later spurious cmds.
+
+Fri Oct 23 15:57:37 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* variable.c (define_automatic_variables): Free old value of SHELL
+	before replacing it.
+
+Thu Oct 15 18:57:56 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* compatMakefile (.c.o): Add -I$(srcdir)/glob to flags.
+
+	* dir.c (open_dirstream): Cast return value to __ptr_t.
+
+	* default.c (default_variables: "GET") [_IBMR2]: Use USG defn.
+
+	* make.h (MAXPATHLEN): Moved out of #ifndef POSIX.
+	(GET_PATH_MAX): Moved from #ifdef POSIX to #ifdef PATH_MAX #else.
+	Define as (get_path_max ()).
+	[! PATH_MAX] (NEED_GET_PATH_MAX): Define.
+	[! PATH_MAX] (get_path_max): Declare fn.
+	* misc.c [NEED_GET_PATH_MAX] (get_path_max): New function.
+
+Mon Oct 12 13:34:45 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.21.
+
+	* job.c (sys_siglist): Only declare #ifndef SYS_SIGLIST_DECLARED.
+	* make.h [! HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define
+	SYS_SIGLIST_DECLARED.
+
+	* dir.c (file_impossible): When initializing DIR->contents, set
+	DIR->contents->dirstream to nil.
+
+	* compatMakefile (GLOB): Define new variable.
+	(objs): Use it, rather than glob/libglob.a explicitly.
+
+	* read.c (parse_file_seq): When stripping "./", handle cases like
+	".///foo" and "./////".
+	* file.c (lookup_file, enter_file): Likewise.
+
+Sun Oct 11 17:00:35 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* dir.c (struct dirstream, {open,read}_dirstream): New
+	data type and functions to read a directory sequentially.
+	(init_dir): New function to hook it into glob.
+	* main.c (main): Call init_dir.
+
+	* compatMakefile (objs): Added glob/libglob.a.
+	* configure.in: Remove code to test for glob.
+
+Fri Oct  9 12:08:30 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (record_files): Generalized test for NAME pointing
+	somewhere into F->name.
+
+	* variable.c (define_variable_in_set): Free old value when replacing.
+
+	* read.c (do_define): Free the linebuffer before returning.
+	(record_files): When clearing .SUFFIXES deps, free their data.
+	(multi_glob): Free OLD and its data when replacing it with results
+	of glob run.
+
+	* commands.c (set_file_variables): Use alloca in place of xmalloc
+	for temp space for $^, $?, et al.
+
+	* dir.c (struct directory): New member `contents' replaces `files'
+	and `dirstream'.
+	(struct directory_contents): New type.
+	(directories_contents): New hash table.
+	(dir_struct_file_exists_p): Take a struct directory_contents.
+	(dir_file_exists_p): Pass it the `contents' member of the dir found.
+	(dir_struct_file_exists_p): Renamed to dir_contents_file_exists_p;
+	made static.  Return 0 if DIR is nil (meaning it couldn't be stat'd).
+	(dir_file_exists_p, find_directory): Change all callers.
+	(file_impossible): Use DIR->contents, initializing it if nil.
+	(print_dir_data_base): Use DIR->contents, and print out device and
+	inode numbers with each directory.
+
+	* Changes for performance win from John Gilmore <gnu@cygnus.com>:
+	* dir.c (DIRECTORY_BUCKETS): Increase to 199.
+	(DIRFILE_BUCKETS): Decrease to 107.
+	(find_directory): Allocate and zero a multiple of
+	sizeof (struct dirfile *), not of sizeof (struct dirfile).
+	(dir_struct_file_exists_p): New function, nearly all code from
+	dir_file_exists_p.
+	(dir_file_exists_p): Just call find_directory+dir_struct_file_exists_p.
+	* vpath.c (selective_vpath_search): Remove redundant
+	dir_file_exists_p call.
+
+	* configure.in: Comment out glob check; always use our code.
+
+Fri Oct  2 19:41:20 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* make.h [! HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define
+	HAVE_SYS_SIGLIST; after doing #define sys_siglist _sys_siglist, we
+	do have it.
+
+Wed Sep 30 19:21:01 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (main): Don't do -w automatically if -s.
+
+Tue Sep 29 21:07:55 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (printed_version): Move variable inside print_version.
+	(print_version): Return immediately if printed_version is set.
+	(die): Don't test printed_version here.
+	(decode_switches): Under -v, do print_version before giving usage.
+	(DESCRIPTION_COLUMN): New macro.
+	(decode_switches): Use it when printing the usage message.
+	Leave at least two spaces between options and their descriptions.
+
+Fri Sep 25 13:12:42 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.20.
+
+Wed Sep 16 16:15:22 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Save errno value from trying to open
+	FILENAME, and restore it before erring; otherwise we get the errno
+	value from the last elt of the search path.
+
+Tue Sep 15 15:12:47 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (long_option_aliases): Add --stop for -S.
+
+	* read.c (word1eq): Do strncmp before dereferencing someplace that
+	may be out in space.
+
+Wed Sep  9 15:50:41 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* remake.c (notice_finished_file): If all the command lines were
+	recursive, don't do the touching.
+
+	* job.c (start_job_command): Don't check for + here.
+	* commands.c (chop_commands): Do it here instead.
+
+	* default.c (default_terminal_rules): Prepend + to cmds for RCS.
+
+Wed Sep  2 17:53:08 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* compatMakefile (objs): Include $(ALLOCA).
+
+	* make.h [CRAY]: Move #define signal bsdsignal to before #includes.
+
+Thu Aug 27 17:45:43 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* read.c (default_include_directories): Add INCLUDEDIR first.
+	* compatMakefile (includedir): Define.
+	(defines): Add -D for INCLUDEDIR="$(includedir)".
+
+	* read.c (read_makefile): Grok multiple files in `include';
+	globbing too.
+
+	* remake.c (library_search): New function.
+	(library_file_mtime): Remove function.
+	(f_mtime): Use library_search instead of library_file_mtime.
+	* compatMakefile (libdir): Define.
+	(defines): Add -D for LIBDIR="$(libdir)".
+	* make.texinfo (Libraries/Search): Document change.
+
+	* file.c (rename_file): Fix file_hash_enter call with missing arg.
+
+Wed Aug 26 17:10:46 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.19.
+
+	* main.c (main): Set command_state to cs_finished for temp files
+	made for stdin makefiles.
+
+	* main.c (decode_switches): Don't tell getopt to return non-option
+	args in order.
+	Ignore an argument of `-'.
+
+Thu Aug 20 13:36:04 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* job.c (start_job_command): If (touch_flag && !RECURSIVE), ignore
+	the command line and go to the next.
+	(notice_finished_file): Under -t, touch FILE.
+	* remake.c (remake_file): Don't touch it here.
+
+Wed Aug 19 16:06:09 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* function.c (pattern_matches): Use temporary for strlen (WORD)
+	instead of two function calls.
+
+	* compatMakefile (LOAD_AVG): Remove variable and comments.
+
+Tue Aug 18 14:58:58 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* make.texinfo (Running): Node renamed to `make Invocation'.
+
+Fri Aug 14 12:27:10 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* arscan.c (ar_name_equal): Don't compare [MAX-3..MAX] if
+	NAMELEN != MEMLEN.
+
+Thu Aug 13 17:50:09 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.18.
+
+	* main.c: Don't #include <time.h>; make.h already does.
+
+Mon Aug 10 17:03:01 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* implicit.c (pattern_search): Fixed copying of suffix when building
+	also_make elts.
+
+	* function.c (expand_function: `shell'): Make sure BUFFER is
+	null-terminated before replacing newlines.
+
+	* compatMakefile (mandir): Use man$(manext), not always manl.
+
+Sun Aug  2 01:42:50 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* rule.c (new_pattern_rule): Not static.
+	* rule.h: Declare it.
+
+	* file.c (file_hash_enter): New function, most code from rename_file.
+	(rename_file): Call it.
+	* file.h (file_hash_enter): Declare it.
+
+	* dep.h: Doc fix.
+
+Thu Jul 30 15:40:48 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (decode_switches): Handle usage_and_exit when building
+	long options vector.
+
+	* default.c (default_terminal_rules): Make RCS rules use $(CHECKOUT,v).
+	(default_variables): Define CHECKOUT,v (hairy).
+
+	* make.h [!HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define
+	sys_siglist to _sys_siglist.
+
+Sun Jul 26 16:56:32 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* NEWS: Add header and tail copyright info like Emacs NEWS.
+
+	* make.h [ANSI_STRING]: Don't #define index, rindex, bcmp, bzero,
+	bcopy if already #define'd.
+	[STDC_HEADERS] (qsort, abort, exit): Declare here.
+	[! __GNU_LIBRARY__ && !POSIX]: Not here.
+
+	* make.h [_AIX]: #pragma alloca first thing.
+
+	* job.c (start_waiting_job): Set the command_state to cs_running
+	when we queue a job on waiting_jobs.
+
+Fri Jul 24 02:16:28 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* variable.c (define_automatic_variables): Use "" instead of nil
+	for empty value.
+
+Thu Jul 23 22:31:18 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.17.
+
+	* main.c (struct command_switch.type): Add alternative usage_and_exit.
+	(command_switches): Add -h/--help.
+
+Thu Jul 16 14:27:50 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* GNUmakefile (make-$(version).tar.Z): Include NEWS, not CHANGES.
+	* README.template: Mention NEWS.
+	* CHANGES: Renamed to NEWS.
+
+	* main.c [! STDC_HEADERS] [sun]: Don't declare exit.
+
+Tue Jul 14 18:48:41 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (main): Set -o files' command_states to cs_finished.
+
+	* rule.c (count_implicit_rule_limits): Decrement num_pattern_rules
+	when tossing a rule.
+
+	* main.c (main): Use alloca only in simple local var assignment,
+	for braindead SGI compiler.
+
+	* rule.c (print_rule_data_base): Barf if num_pattern_rules is
+	inconsistent with the number computed when listing them.
+
+Mon Jul 13 17:51:53 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* commands.c (set_file_variables): For $? and $^ elts that are archive
+	member refs, use member name only.
+
+Fri Jul 10 00:05:04 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* variable.h (struct variable.export): Add new alternative v_ifset.
+	* variable.c (target_environment): Check for it.
+	(define_automatic_variables): Set it for MAKEFILES.
+
+Thu Jul  9 21:24:28 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (objs): Remove getloadavg.o; $(extras) gets it.
+	(remote.o): Use $(srcdir)/remote.c, not $remote.c<.
+	(distclean, mostlyclean): New targets.
+
+Tue Jul  7 19:12:49 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.16.
+
+	* compatMakefile (config.status): Remove rule.
+
+	* job.c (start_waiting_job): Free C after using C->file, not before.
+
+Sat Jul  4 20:51:49 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* commands.c, job.c, main.c, make.h, remote-cstms.c: Use #ifdef
+	HAVE_* instead of #ifndef *_MISSING.
+	* configure.in: Use AC_HAVE_FUNCS instead of AC_MISSING_FUNCS (gone).
+
+Thu Jul  2 18:47:52 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* main.c (main): makelevel>0 or -C implies -w.
+
+Tue Jun 30 20:50:17 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* file.c, job.c, function.c: Don't #include <errno.h>.
+	make.h: Do it here instead.
+	* arscan.c (ar_member_touch): Don't declare errno.
+
+Thu Jun 25 17:06:55 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* GNUmakefile (make-$(version).tar.Z): Depend on INSTALL, configure.in.
+
+	* remake.c (update_file): If commands or deps are running after
+	update_file_1 returns, break out of the :: rule (->prev) loop and
+	just return.
+
+	* job.c	(job_next_command): New function; code from start_job.
+	(start_job_command): Renamed from start_job.  Call job_next_command
+	and recurse for empty command lines and -n.
+	(start_waiting_job): Call start_job_command, not start_job.
+	(new_job): Call job_next_command to prime the child structure, and
+	then call start_waiting_job.
+	(reap_children): Use job_next_command and start_job_command.
+	(start_waiting_job): Call start_remote_job_p here, and store its
+	result in C->remote.  If zero, check the load average and
+	maybe put C on waiting_jobs.
+	(start_job_command): Test CHILD->remote rather than calling
+	start_remote_job_p.  Don't do load avg checking at all here.
+
+	* main.c (main): Don't handle SIGILL, SIGIOT, SIGEMT, SIGBUS,
+	SIGSEGV, SIGFPE or SIGTRAP.
+
+	* compatMakefile (glob/libglob.a): Don't pass srcdir to sub-make.
+	configure will set it in glob/Makefile.
+
+Wed Jun 24 19:40:34 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* dir.c [DIRENT] (direct): Don't define to dirent.
+	[! DIRENT] (direct): Define to dirent.
+	(dir_file_exists_p): Use struct dirent instead of struct direct.
+
+	* make.h (getcwd): No space between macro and ( for args!
+
+	* job.c (start_job): Don't put the job on waiting_jobs if
+	job_slots_used==0.
+
+	* make.texinfo (Missing): Shortened title.
+
+Tue Jun 23 18:42:21 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* file.c (remove_intermediates): Print "rm" commands under -n.
+
+Mon Jun 22 16:20:02 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.15.
+
+Fri Jun 19 16:20:26 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* arscan.c [M_UNIX]: #undef M_XENIX.
+
+Wed Jun 17 17:59:28 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* default.c (default_terminal_rules): Put @ prefix on RCS cmds.
+
+Tue Jun 16 19:24:17 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile (getloadavg.o): Removed special rule.
+	(CFLAGS): Don't include $(defines).
+	(.c.o): Define suffix rule.
+	(glob/libglob.a): Pass CPPFLAGS=$(defines) to submake.
+	(GETOPT_SRC, srcs, tagsrcs): Prefix files with $(srcdir)/.
+
+	* arscan.c (ar_name_equal): Moved local vars inside #if'd block.
+
+	* make.h (max): Removed.
+	* expand.c (variable_buffer_output): Don't use it.
+
+	* compatMakefile (INSTALL): Define.
+	(Makefile): New rule to make from Makefile.in.
+	(srcdir): Define.
+	(VPATH): Define.
+	(getloadavg.o, remote.o): Use autoconf $foo< hack.
+
+	* commands.c (fatal_error_signal): Removed return.
+
+Mon Jun 15 17:42:51 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.14.
+
+	* make.texinfo (Summary): New node.
+	(Special Targets): Mention .EXPORT_ALL_VARIABLES here.
+
+	* variable.c (max): Moved to make.h.
+
+	* compatMakefile (objs, srcs): Added ar & arscan.
+
+	* job.c (start_waiting_job): New function, 2nd half of new_job.
+	(new_job): Call it.
+	(start_waiting_jobs): New function.
+	* remake.c (update_goal_chain): Call start_waiting_jobs at the top
+	of the main loop.
+	* compatMakefile (objs, srcs): Removed load, added getloadavg.
+
+Fri Jun 12 19:33:16 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* job.c (load_too_high): New function.  Uses getloadavg.
+	(waiting_jobs): New variable.
+	(start_job): Don't call wait_to_start_job.  Instead, if
+	load_too_high returns nonzero, add the child to the
+	`waiting_jobs' chain and return without starting the job.
+
+Thu Jun 11 00:05:28 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* expand.c (variable_buffer_output): Made global again.
+	* variable.h: And declare it.
+
+	* arscan.c (PORTAR): Define for all systems if PORT5AR is not defined.
+	(AR_NAMELEN, AR_TRAILING_SLASH): Removed.
+	(ar_scan): Don't use it.  Don't #ifdef AR_TRAILING_SLASH; just look
+	for a slash in the archive at run time.
+	(ar_name_equal): Rewrote .o hacking to not use AR_NAMELEN, and to
+	cope with trailing-slash and non-trailing-slash archives.
+
+	* main.c (main) [! SETVBUF_REVERSED]: Test this instead of USGr3 et al.
+	[SETVBUF_REVERSED]: Always allocate a buffer ourselves.
+
+	* load.c (load_average) [sgi]: Use sysmp call.
+
+	* compatMakefile (INSTALL_DATA, INSTALL_PROGRAM): Define.
+	($(bindir)/$(instname), $(mandir)/make.$(manext)): Use them.
+
+	* make.h [HAVE_VFORK_H]: #include <vfork.h>.
+	(vfork, VFORK_NAME): Don't define.
+	* job.c (start_job): Use "vfork" in place of VFORK_NAME.
+
+	* make.h [HAVE_LIMITS_H, HAVE_SYS_PARAM_H]: If #define'd, #include
+	the each file.  Rearranged PATH_MAX hacking.
+	* job.c: Rearranged NGROUPS_MAX hacking.
+
+	* remake.c (fstat, time): Don't declare.
+
+	* compatMakefile (defines): Value is @DEFS@.
+	(LOADLIBES): Value is @LIBS@.
+	(extras): Value is @LIBOBJS@.
+	(ARCHIVES, ARCHIVES_SRC, ALLOCASRC): Removed.
+	* arscan.c, ar.c: Surround body with #ifndef NO_ARCHIVES.
+
+	* misc.c [! HAVE_UNISTD_H]: Test instead of !POSIX to decl get*id.
+
+	* make.h [GETCWD_MISSING]: Test instead of !USG && !POSIX et al.
+	(getcwd): Just declare if present.  If not, declare as a macro
+	using getwd, and declare getwd.
+	[PATH_MAX] (GET_PATH_MAX): #define to PATH_MAX.
+	* main.c (main,	log_working_directory): Use getcwd instead of getwd.
+
+	* main.c (main) [SETLINEBUF_MISSING]: Test this instead of USG.
+
+	* make.h (SIGHANDLER, SIGNAL): Removed.
+	(RETSIGTYPE): Define if not #define'd.
+	* main.c (main): Use signal in place of SIGNAL.
+
+	* main.c [SYS_SIGLIST_MISSING]: Test instead of USG.
+
+	* job.c (search_path) [GETGROUPS_MISSING]: Test instead of USG.
+	[HAVE_UNISTD_H]: Test instead of POSIX to not decl getgroups.
+
+	* main.c [! HAVE_UNISTD_H]: Test instead of !POSIX to decl chdir.
+	[! STDC_HEADERS]: Test instead of !POSIX to decl exit & atof.
+
+	* job.c (child_handler), commands.c (fatal_error_signal): Return
+	RETSIGTYPE instead of int.
+	* main.c (main): Declare fatal_error_signal and child_handler here
+	to return RETSIGTYPE; removed top-level decl of former.
+
+	* commands.c (fatal_error_signal), job.c (unblock_sigs, start_job),
+	main.c [SIGSETMASK_MISSING]: Test this instead of USG.
+
+Wed Jun 10 22:06:13 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* job.c [HAVE_WAITPID]: Test this instead of USG.
+	[! HAVE_UNISTD_H]: Test this instead of !POSIX to declare misc fns.
+	(GID_T): Don't #define.
+	(search_path): Use gid_t instead of GID_T.
+	[GETDTABLESIZE_MISSING, SYS_SIGLIST_MISSING, DUP2_MISSING]: Test
+	these individually instead of USG for all.
+	* make.h (ctime): Don't declare.  #include time.h instead.
+	[HAVE_UNISTD_H]: #include <unistd.h> and #define POSIX #ifdef
+	_POSIX_VERSION.
+	* dir.c [__GNU_LIBRARY__] (D_NAMLEN): Define to use d_namlen member.
+	* make.h [NEED_MEMORY_H]: Only include memory.h #ifdef this.
+
+	* arscan.c: Removed #ifdef mess about string.h et al.
+	Just #include make.h instead.
+	* make.h (fstat, atol): Declare.
+
+	* commands.c (fatal_error_signal): Don't use sigmask to check for
+	propagated signals; use ||s instead.
+	(PROPAGATED_SIGNAL_MASK): Removed.
+	(fatal_error_signal) [POSIX]: Use sigprocmask in place of sigsetmask.
+
+	* variable.c (variable_buffer, variable_buffer_length,
+	initialize_variable_output, variable_output): Moved to expand.c;
+	made all static.
+	(struct output_state, save_variable_output,
+	restore_variable_output): Removed.
+	* expand.c (initialize_variable_output): Put a NUL at the beginning
+	of the new buffer after allocating it.
+	(allocated_variable_expand_for_file): Don't use
+	{save,restore}_variable_output.  Do it by hand instead, keeping
+	state on the stack instead of malloc'ing it.
+	(allocated_variable_expand): Removed.
+	* variable.h (allocated_variable_expand): Define here as macro.
+	(variable_buffer_output, initialize_variable_output,
+	save_variable_output, restore_variable_output): Removed decls.
+
+	* read.c (conditional_line): For an if cmd, if any elt of the
+	conditionals stack is ignoring, just push a new level that ignores
+	and return 1; don't evaluate the condition.
+
+Thu Jun  4 21:01:20 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (main): Put #ifdef's around frobbing SIGSYS and SIGBUS.
+
+	* job.c (getdtablesize): Don't declare or #define if already #define'd.
+
+Wed Jun  3 23:42:36 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* file.c (snap_deps): If `.EXPORT_ALL_VARIABLES' is a target, set
+	export_all_variables.
+	* make.texinfo (Variables/Recursion): Document .EXPORT_ALL_VARIABLES.
+
+Tue Jun  2 21:08:35 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.13.
+
+	* commands.c (set_file_variables): Calculate length for ^D and ?D
+	individually, making sure to give them at least enough space for "./".
+
+	* make.h [CRAY]: #define signal to bsdsignal.
+
+	* default.c (default_variables) [CRAY]: Define PC, SEGLDR,
+	CF77PPFLAGS, CF77PP, CFT, CF, and FC.
+
+	* arscan.c (AR_HDR_SIZE): Define to sizeof (struct ar_hdr), if it
+	wasn't defined by <ar.h>.
+
+Thu May 28 00:56:53 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.12.
+
+Tue May 26 01:26:30 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* rule.c (new_pattern_rule): Initialize LASTRULE to nil, not
+	pattern_rules.
+
+Mon May 25 19:02:15 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (decode_switches): Initialize all the long_option elt members.
+
+Thu May 21 16:34:24 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* make.texinfo (Text Functions): Correct filter-out description.
+
+Tue May 19 20:50:01 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* compatMakefile (realclean): Don't remove backup files.
+
+	* main.c (decode_switches): Allocate ARGC+1 elts in `other_args'.
+
+Sun May 17 16:38:48 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* Version 3.62.11.
+
+Thu May 14 16:42:33 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* job.c (reap_children): Don't die if wait returns EINTR.
+
+Wed May 13 18:28:25 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* job.c (reap_children): Always run the next command for a
+	successful target.  If we are going to die, we don't want to leave
+	the target partially made.
+
+Tue May 12 00:39:19 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): After loop, if we only
+	have one word, check it for being a shell command.
+
+	* main.c (decode_switches): Allocate ARGC slots in other_args to
+	begin with, so we never need to worry about growing it.
+	If we get a non-option arg and POSIXLY_CORRECT is in the
+	environment, break out of the loop.  After the loop, add all remaining
+	args to other_args list.
+
+	* main.c (decode_switches): For positive_int and floating switches
+	when optarg is nil, use next arg if it looks right (start with a
+	digit, or maybe decimal point for floating).
+
+	* variable.c (define_automatic_variables): Always set SHELL to
+	default if it comes from the environment.  Set its export bit.
+	* make.texinfo (Environment): Document change.
+
+Mon May 11 00:32:46 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* Version 3.62.10.
+
+	* compatMakefile (tags, TAGS): Use vars for cmds.
+	(ETAGS, CTAGS): Define.
+
+	* main.c (decode_switches): If a switches elt has a nil long_name,
+	make the long option name elt be "".
+	Fixed loop to not ignore all the options.
+
+	* make.texinfo (Option Summary): Added long options.
+
+	* main.c (switches): Changed -m's description to "-b".
+	(decode_switches): When printing the usage message, don't print
+	switches whose descriptions start with -.
+	When constructing the list of names for switch -C, search the
+	switches vector for switches whose descriptions are "-C".
+
+	* main.c (switches): Call -S --no-keep-going, not --dont-keep-going.
+	Call -I --include-dir, not --include-path.
+	(long_option_aliases): Added --new == -W, --assume-new == -W,
+	--assume-old == -o, --max-load == -l, --dry-run == -n, --recon == -n,
+	--makefile == -f.
+
+	* main.c (switches): Removed bogus "silent" elt.
+	(long_option_aliases): Define new var.
+	(decode_switches): Add long_option_aliases onto the end of the long
+	options vector created for getopt_long.
+	Look through long_option_aliases for extra names to list
+	in usage message.
+
+Sat May  9 00:21:05 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (log_working_directory): Fixed to properly not print the
+	leaving message when we haven't printed the entering message.
+
+Fri May  8 21:55:35 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* main.c (struct command_switch): Added elts `long_name',
+	`description', and `argdesc'.
+	(switches): Added initializers for new members.
+	(decode_switches): Rewritten to use getopt_long.
+	* compatMakefile (GETOPT, GETOPT_SRC): Define.
+	(objs, srcs): Include them.
+
+	* job.c (child_died): Renamed to dead_children; made static.
+	(child_handler): Increment dead_children instead of setting child_died.
+	(reap_children): Decrement dead_children instead of clearing
+	child_died.  The point of all this is to avoid printing "waiting
+	for unfinished jobs" when we don't actually need to block.
+	This happened when multiple SIGCHLDs before reap_children was called.
+
+	* job.c (reap_children): If ERR is set, so we don't call start_job
+	on the child being reaped, instead set its command_state to
+	cs_finished.
+	(reap_children, child_handler, new_job): I added several
+	debugging printf's while fixing this.  I left them in if (debug_flag)
+	because they may be useful for debugging this stuff again.
+
+Wed May  6 22:02:37 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): v_export is not 1.
+
+Mon May  4 17:27:37 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.9.
+
+	* variable.c (export_all_variables): New variable.
+	(target_environment): Export variables whose `export' member is
+	v_default if export_all_variables is set and their names are benign.
+	* variable.h: Declare export_all_variables.
+	* read.c (read_makefile): If export or unexport is given with no
+	args, set or clear export_all_variables, respectively.
+
+	* variable.c (target_environment): Exclude MAKELEVEL in the loop,
+	so it isn't duplicated when we add it at the end.
+
+Sun May  3 17:44:48 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.8.
+
+	* variable.h (struct variable): Added new member `export'.
+	* variable.c (define_variable_in_set): Initialize it to v_default.
+	(target_environment): Don't check for .NOEXPORT.
+	Export variables whose `export' member is v_default and that would
+	have been exported under .NOEXPORT, and variables whose `export'
+	member is v_export.
+	(try_variable_definition): Return the variable defined.
+	* variable.h (try_variable_definition): Changed decl.
+	* read.c (read_makefile): Recognize `export' and `unexport' directives.
+
+Fri May  1 11:39:38 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* main.c (main) [POSIX]: Reversed args to sigaddset.
+
+Thu Apr 30 17:33:32 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* job.c [POSIX || !USG] (unblock_sigs): New fn.
+	(start_job): Block signals before forking.
+	(new_job): Unblock signals after putting the new child on the chain.
+	* main.c (main) [POSIX]: Use sigset_t fatal_signal_set instead of
+	int fatal_signal_mask.
+
+	* load.c [sgi] (LDAV_CVT): Define.
+
+Wed Apr 29 17:15:59 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* Version 3.62.7.
+
+	* load.c (load_average) [sgi]: Clear the high bit of the address
+	from the symbol table before looking it up in kmem.
+
+	* misc.c (fatal, makefile_fatal): Put *** in fatal error messages.
+	(remake_file): No longer needed in message here.
+
+	* main.c (die): Call reap_children with BLOCK==1.
+
+Tue Apr 28 20:44:35 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* rule.c (freerule): Don't set LASTRULE->next if LASTRULE is nil.
+
+Sun Apr 26 15:09:51 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* rule.c (count_implicit_rule_limits): Initialize LASTRULE to nil,
+	not to head of chain.  Extract next ptr before we might do
+	freerule, and use that for next iteration.
+	(freerule): Still do next ptr frobbing if LASTRULE is nil.
+
+Tue Apr 21 03:16:29 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* job.c (child_error): Removed extra %s from error msg format.
+
+	* Version 3.62.6.
+
+	* job.c (reap_children): Don't start later commands in a sequence
+	if ERR is nonzero.
+
+	* job.c (new_job): Always call reap_children with BLOCK==0 first thing.
+
+	* job.c (reap_children): New function; work that used to be done in
+	child_handler.
+	(child_died): New global var.
+	(child_handler): Now just sets child_died.
+	(wait_for_children): Removed.
+	(unknown_children_possible, block_signals, unblock_signals,
+	push_signals_blocked_p, pop_signals_blocked_p): Removed.
+	(child_execute_job): Removed call to unblock_signals.
+	(new_job): Removed calls to push_signals_blocked_p and
+	pop_signals_blocked_p.
+	* job.h: Declare reap_children, not wait_for_children.
+	* commands.c (fatal_error_signal), job.c (new_job),
+	load.c [LDAV_BASED] (wait_to_start_job), main.c (die),
+	remake.c (update_goal_chain), function.c (expand_function: `shell'):
+	Changed wait_for_children calls to reap_children.
+	Some needed to be loops to wait for all children to die.
+	* commands.c (fatal_error_signal), main.c (main,
+	log_working_directory), function.c (expand_function): Removed calls
+	to push_signals_blocked_p and pop_signals_blocked_p.
+	* job.h: Removed decls.
+
+	* job.h: Added copyright notice.
+
+Wed Apr 15 02:02:40 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (child_error): No *** for ignored error.
+
+Tue Apr 14 18:31:21 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* implicit.c (DEBUGP2): Use do ... while (0) instead of if ... else to
+	avoid compiler warnings.
+
+	* read.c (parse_file_seq): Don't remove ./ when it is followed by a
+	blank.
+
+Mon Apr 13 21:56:15 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h (DEBUGPR): Use do ... while (0) instead of if ... else to
+	avoid compiler warnings.
+
+	* remake.c (notice_finished_file): Run file_mtime on the also_make
+	files, so vpath_search can happen.
+
+	* GNUmakefile (tests): Use perl test suite from csa@sw.stratus.com.
+	(alpha-files): Include test suite tar file.
+
+Fri Apr  3 00:50:13 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* Version 3.62.5.
+
+Wed Apr  1 05:31:18 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* remake.c (update_file, update_file_1): Do check_renamed on elts
+	of dep chains when traversing them.  Something unrelated might have
+	renamed one of the files the dep chain points to.
+
+	* file.c (rename_file): If FILE has been renamed, follow its
+	`renamed' ptr, so we get to the final real FILE.  Using the renamed
+	ones loses because they are not in the hash table, so the removal
+	code loops infinitely.
+
+	* read.c (read_all_makefiles): Clobber null terminator into
+	MAKEFILES expansion, so string passed to read_makefile is properly
+	terminated.
+
+Mon Mar 30 20:18:02 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* commands.c (set_file_variables): $* for archive member with
+	explicit cmds is stem of member, not of whole `lib(member)'.
+
+Thu Mar 26 15:24:38 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* Version 3.62.4.
+
+Tue Mar 24 05:20:51 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* rule.c (new_pattern_rule): Rules are identical only if all their
+	targets match (regardless of order).
+
+Wed Mar 11 13:49:54 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)
+
+	* remake.c (remake_file): Changed error "no way to make" to "no
+	rule to make".  Fiat Hugh.
+
+	* make.texinfo (Last Resort): Describe %:: rules and new .DEFAULT
+	behavior.
+
+	* remake.c (update_file_1): Only use .DEFAULT cmds if FILE is not a
+	target.
+
+Tue Mar 10 18:13:13 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* remote-stub.c, remote-cstms.c (start_remote_job): Take new arg,
+	environment to pass to child.
+	* job.c (start_job): Pass it.
+
+Mon Mar  9 19:00:11 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* file.c (enter_file): Also strip ./s here, to get command-line
+	target names.
+
+	* remote-cstms.c: Add comment telling people to leave me alone.
+
+	* compatMakefile (manpage install): Remove target before copying.
+
+Tue Mar  3 18:43:21 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.texinfo (Missing): Renamed to "Incompatibilities and ...".
+	Added paragraph describing $? incompatibility with Unix and POSIX.2.
+
+Sun Mar  1 15:50:54 1992  Roland McGrath  (roland@nutrimat.gnu.ai.mit.edu)
+
+	* function.c (expand_function: `shell'): Don't declare fork or pipe.
+	Use vfork instead of fork.
+
+Tue Feb 25 22:05:32 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* make.texinfo (Chained Rules): Clarify .PRECIOUS to save
+	intermediate files.
+
+	* load.c [sun] (LDAV_CVT): Define to divide by FSCALE.
+
+Sun Feb 16 02:05:16 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* Version 3.62.3.
+
+Sat Feb 15 17:12:20 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* compatMakefile (makeinfo): Use emacs batch-texinfo-format fn.
+
+Fri Feb 14 00:11:55 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Correctly handle define & endef in ifdefs.
+
+	* read.c (record_files): Pass arg for %s in error msg.
+
+	* main.c (main) [__IBMR2, POSIX]: Use correct (a la USGr3) setvbuf
+	call.
+
+Wed Feb 12 12:07:39 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* make.texinfo (Libraries/Search): Say it does /usr/local/lib too.
+
+Sun Feb  9 23:06:24 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* read.c (read_makefile): Check for extraneous `endef' when ignoring.
+
+Thu Feb  6 16:15:48 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* Version 3.62.2.
+
+Tue Feb  4 20:04:46 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): Correctly ignore
+	whitespace after backslash-NL.
+
+Fri Jan 31 18:30:05 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* compatMakefile: Ignore errors from chgrp and chmod when installing.
+
+Wed Jan 29 18:13:30 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* main.c (main): When setting MAKELEVEL in the env to re-exec,
+	allocate space so as not to clobber past the end of the old string.
+
+	* make.h [HAVE_ALLOCA_H]: Include <alloca.h>
+	* compatMakefile (defines): Document HAVE_ALLOCA_H.
+
+Mon Jan 20 13:40:05 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* make.h [VFORK_MISSING]: Use fork instead.
+	* compatMakefile (defines): Document same.
+
+	* job.c (construct_command_argv_internal): Don't create an empty
+	arg if backslash-NL is at beginning of word.
+
+Sun Jan 19 16:26:53 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* main.c [DGUX]: Call setvbuf as for USGr3.
+
+	* job.c (construct_command_argv_internal): Notice correctly that
+	backslash-NL is the end of the arg (because it is replaced with a
+	space).
+
+Thu Jan 16 18:42:38 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): If SHELL is nil, set it
+	to default_shell before proceeding.
+
+	* make.h [sgi]: No alloca.h, after all.
+
+Wed Jan 15 12:30:04 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* read.c (multi_glob): Cons up the chain of the results of glob
+	from back to front, so it comes out in forward order.
+
+	* job.c (construct_command_argv_internal): Don't eat char following
+	backslash-NL.
+
+Mon Jan 13 19:16:56 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* Version 3.62.1.
+
+	* default.c (default_variables) [ultrix]: GET=get, like USG.
+
+	* job.c (construct_command_argv_internal): Remove tabs following
+	backslash-NL combos in the input line, so they don't show up when
+	that line is printed.
+
+	* read.c (read_makefile): Don't collapse_continuations the line on
+	input; do it on the copy we do remove_comments on.
+	For rule lines, collapse_continuations the line after chopping
+	";cmds" off the end, so we don't eat conts in the cmds.
+	Give error for ";cmds" with no rule.
+	* job.c (construct_command_argv_internal): Eat backslash-NL combos
+	when constructing the line to recurse on for slow, too.
+
+Sat Jan 11 02:20:27 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)
+
+	* file.c (enter_file): Don't strip leading `./'s.
+	* read.c (parse_file_seq): Take new arg STRIP; if nonzero, do it here.
+	* default.c (set_default_suffixes), function.c (string_glob),
+	read.c (read_makefile), rule.c (install_pattern_rule): Change callers.
+
+	* default.c (default_variables) [_IBMR2]: FC=xlf
+
+	* job.c (construct_command_argv_internal): Turn backslash-NL and
+	following whitespace into a single space, rather than just eating
+	the backslash.
+
+	* make.texinfo (Copying): @include gpl.texinfo, rather than
+	duplicating its contents.
+
+Fri Nov  8 20:06:03 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): Make sure not to bother
+	processing an empty line.
+
+	* Version 3.62.0.
+
+	* job.c (construct_command_argv_internal): Always recurse for slow;
+	simple case didn't handle finding newlines.
+
+Tue Nov  5 18:51:10 1991  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)
+
+	* job.c (construct_command_argv_internal): Set RESTP properly when
+	slow; don't \ify past a newline.
+
+Fri Nov  1 19:34:28 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)
+
+	* make.h [sgi]: #include <alloca.h>.
+
+
+
+
+See ChangeLog.1, available in the CVS repository at:
+
+	http://savannah.gnu.org/cvs/?group=make
+
+for earlier changes.
+
+
+Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/INSTALL
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/INSTALL	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/INSTALL	(revision 1780)
@@ -0,0 +1,231 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+   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, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   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 you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+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.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+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.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `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 `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+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 other than `/usr/local' by giving `configure' the
+option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PREFIX', the package will
+use PREFIX 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=DIR' 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'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+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.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
Index: /tags/kBuild-0.1.4/src/kmk/Makefile.DOS.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/Makefile.DOS.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/Makefile.DOS.template	(revision 1780)
@@ -0,0 +1,544 @@
+# -*-Makefile-*- template for DJGPP
+# Makefile.in generated automatically by automake 1.2 from Makefile.am
+#
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+# 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+SHELL = /bin/sh
+
+srcdir = .
+VPATH = $(srcdir)
+# $DJDIR is defined automatically by DJGPP to point
+# to the root of the DJGPP installation tree.
+prefix = /dev/env/DJDIR
+exec_prefix = ${prefix}
+
+bindir = /bin
+datadir = /share
+libdir = /lib
+infodir = /info
+mandir = /man
+includedir = /include
+oldincludedir = c:/djgpp/include
+
+DESTDIR = /dev/env/DJDIR
+
+pkgdatadir = $(datadir)/make
+pkglibdir = $(libdir)/make
+pkgincludedir = $(includedir)/make
+localedir = $(datadir)/locale
+
+INSTALL = ${exec_prefix}/bin/ginstall -c
+INSTALL_PROGRAM = ${exec_prefix}/bin/ginstall -c
+INSTALL_DATA = ${exec_prefix}/bin/ginstall -c -m 644
+INSTALL_SCRIPT = ${exec_prefix}/bin/ginstall -c
+transform = s,x,x,
+
+# This will fail even if they don't have a Unix-like shell (stock DOS
+# shell doesn't know about `false').  The only difference is that they
+# get "Error -1" instead of "Error 1".
+EXIT_FAIL = false
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+EXEEXT = .exe
+OBJEXT = o
+
+AR = ar
+AWK = gawk
+CC = gcc
+CPP = gcc -E
+LIBOBJS =
+MAKEINFO = ${exec_prefix}/bin/makeinfo
+PACKAGE = make
+PERL = perl
+RANLIB = ranlib
+REMOTE = stub
+VERSION = %VERSION%
+
+AUTOMAKE_OPTIONS = 1.2
+
+bin_PROGRAMS =	%PROGRAMS%$(EXEEXT)
+
+make_SOURCES =	%SOURCES%
+# This should include the glob/ prefix
+libglob_a_SOURCES =	%GLOB_SOURCES%
+make_LDADD =	  glob/libglob.a
+
+info_TEXINFOS =	make.texinfo
+man_MANS =	make.1
+
+INCLUDES =	-I$(srcdir)/glob -DLIBDIR=\"c:/djgpp/lib\" -DINCLUDEDIR=\"c:/djgpp/include\" -DLOCALEDIR=\"$(localedir)\"
+
+BUILT_SOURCES =	README build.sh-in
+
+EXTRA_DIST = 	$(BUILT_SOURCES) $(man_MANS) README.customs remote-cstms.c  make-stds.texi texinfo.tex SCOPTIONS SMakefile  Makefile.ami README.Amiga config.ami amiga.c amiga.h  NMakefile README.DOS configh.dos configure.bat makefile.com  README.W32 build_w32.bat config.h-W32 subproc.bat make.lnk  config.h-vms makefile.vms readme.vms vmsdir.h vmsfunctions.c  vmsify.c
+
+SUBDIRS =	glob
+mkinstalldirs = ${exec_prefix}/bin/gmkdir -p
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =  build.sh
+PROGRAMS =  $(bin_PROGRAMS)
+
+MAKE_HOST = i386-pc-msdosdjgpp
+
+
+DEFS =  -I. -I$(srcdir) -I.
+CPPFLAGS = -DHAVE_CONFIG_H
+LDFLAGS =
+LIBS =
+make_OBJECTS =  %OBJECTS%
+make_DEPENDENCIES =    glob/libglob.a
+make_LDFLAGS =
+libglob_a_LIBADD =
+libglob_a_OBJECTS =  %GLOB_OBJECTS%
+noinst_LIBRARIES =	glob/libglob.a
+CFLAGS = -O2 -g
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+TEXI2DVI = texi2dvi
+TEXINFO_TEX = $(srcdir)/config/texinfo.tex
+INFO_DEPS = make.info
+DVIS = make.dvi
+TEXINFOS = make.texinfo
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON =  README ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL Makefile.am  Makefile.in NEWS acconfig.h aclocal.m4 alloca.c build.sh-in config.h-in  configure configure.in getloadavg.c
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP = --best
+SOURCES = $(make_SOURCES)
+OBJECTS = $(make_OBJECTS)
+HEADERS = $(wildcard $(srcdir)/*.h)
+
+default: all
+
+.SUFFIXES:
+.SUFFIXES: .c .dvi .info .o .obj .ps .texinfo .tex
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+	-rm -f config.h
+
+maintainer-clean-hdr:
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do    if test -f $$p; then      echo "  $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p | sed '$(transform)'`";       $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p | sed '$(transform)'`;    else :; fi;  done
+
+uninstall-binPROGRAMS:
+	$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do    rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`.exe;  done
+
+.c.o:
+	$(COMPILE) -c $<
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT) *$(EXEEXT) make.new core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c *_tab.c
+
+maintainer-clean-compile:
+
+make$(EXEEXT): $(make_OBJECTS) $(make_DEPENDENCIES)
+	@command.com /c if exist make del make
+	@command.com /c if exist make.exe del make.exe
+	$(LINK) $(make_LDFLAGS) $(make_OBJECTS) $(make_LDADD) $(LIBS)
+
+make.info: make.texinfo
+make.dvi: make.texinfo
+
+
+DVIPS = dvips
+
+.texinfo.info:
+	@command.com /c if exist make.info* del make.info*
+	@command.com /c if exist make.i* del make.i*
+	$(MAKEINFO) -I$(srcdir) $< -o ./$@
+
+.texinfo:
+	@command.com /c if exist make.info* del make.info*
+	@command.com /c if exist make.i* del make.i*
+	$(MAKEINFO) -I$(srcdir) $< -o ./$@
+
+.texinfo.dvi:
+	TEXINPUTS="$(srcdir);$$TEXINPUTS"    MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+
+.dvi.ps:
+	$(DVIPS) $< -o $@
+
+install-info-am: $(INFO_DEPS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(infodir)
+	@for file in $(INFO_DEPS) make.i; do    d=$(srcdir);    for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9] $$file[0-9] $$file[0-9][0-9]`; do      if test -f $$d/$$ifile; then        echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; else : ; fi;    done;  done
+	@$(POST_INSTALL)
+	@if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then    for file in $(INFO_DEPS); do      echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";     install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;   done;  else : ; fi
+
+uninstall-info:
+	$(PRE_UNINSTALL)
+	@if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then    ii=yes;  else ii=; fi;  for file in $(INFO_DEPS); do    test -z $ii || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file;  done
+	$(NORMAL_UNINSTALL)
+	for file in $(INFO_DEPS) make.i; do    (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9] $$file[0-9] $$file[0-9][0-9]);  done
+
+dist-info: $(INFO_DEPS)
+	for base in $(INFO_DEPS); do    d=$(srcdir);    for file in `cd $$d && eval echo $$base*`; do      test -f $(distdir)/$$file      || ln $$d/$$file $(distdir)/$$file 2> /dev/null      || cp -p $$d/$$file $(distdir)/$$file;    done;  done
+
+mostlyclean-aminfo:
+	-rm -f make.aux make.cp make.cps make.dvi make.fn make.fns make.ky \
+	  make.kys make.ps make.log make.pg make.toc make.tp make.tps \
+	  make.vr make.vrs make.op make.tr make.cv make.cn
+
+clean-aminfo:
+
+distclean-aminfo:
+
+maintainer-clean-aminfo:
+	for i in $(INFO_DEPS) make.i; do rm -f `eval echo $$i*`; done
+
+install-man1:
+	$(mkinstalldirs) $(DESTDIR)$(man1dir)
+	@list='$(man1_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.1*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+	  $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+	done
+
+uninstall-man1:
+	@list='$(man1_MANS)'; \
+	l2='$(man_MANS)'; for i in $$l2; do \
+	  case "$$i" in \
+	    *.1*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+	  rm -f $(DESTDIR)$(man1dir)/$$inst; \
+	done
+install-man: $(MANS)
+	@$(NORMAL_INSTALL)
+	$(MAKE) install-man1
+uninstall-man:
+	@$(NORMAL_UNINSTALL)
+	$(MAKE) uninstall-man1
+
+# Assume that the only thing to do in glob is to build libglob.a,
+# but do a sanity check: if $SUBDIRS will ever have more than
+# a single directory, yell bloody murder.
+all-recursive:
+ifeq ($(words $(SUBDIRS)), 1)
+	@command.com /c if not exist glob\\nul md glob
+	@echo Making all in $(SUBDIRS)
+	$(MAKE) -C $(SUBDIRS) -f ../Makefile INCLUDES='-I$(srcdir) -I$(srcdir)/glob' DEFS='-I.. -I$(srcdir)' VPATH=$(srcdir)/glob libglob.a
+else
+	@echo FATAL: There is more than one directory in "($(SUBDIRS))"
+	@$(EXIT_FAIL)
+endif
+
+$(SUBDIRS):
+	command.com /c md $@
+
+libglob.a: $(libglob_a_OBJECTS)
+	command.com /c if exist libglob.a del libglob.a
+	$(AR) cru libglob.a $(libglob_a_OBJECTS) $(libglob_a_LIBADD)
+	$(RANLIB) libglob.a
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive check-recursive:
+ifeq ($(words $(SUBDIRS)), 1)
+	@echo Making $(shell echo $@ | sed s/-recursive//) in $(SUBDIRS)
+	$(MAKE) -C $(SUBDIRS) -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am
+else
+	@echo FATAL: There is more than one directory in "($(SUBDIRS))"
+	@$(EXIT_FAIL)
+endif
+
+tags-in-glob: $(libglob_a_SOURCES)
+	etags $(addprefix $(srcdir)/,$^) -o ./glob/TAGS
+
+tags-recursive:
+ifeq ($(words $(SUBDIRS)), 1)
+	$(MAKE) tags-in-glob
+else
+	@echo FATAL: There is more than one directory in "($(SUBDIRS))"
+	@$(EXIT_FAIL)
+endif
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES)
+	mkid $(srcdir)/$(SOURCES) $(srcdir)/$(libglob_a_SOURCES) ./config.h $(HEADERS)
+
+TAGS: tags-recursive $(HEADERS) $(srcdir)/$(SOURCES) config.h $(TAGS_DEPENDENCIES)
+	etags -i ./glob/TAGS $(ETAGS_ARGS) $(srcdir)/$(SOURCES) ./config.h $(HEADERS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	rm -rf $(distdir)
+	GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz
+	mkdir $(distdir)/=build
+	mkdir $(distdir)/=inst
+	dc_install_base=`cd $(distdir)/=inst && pwd`;  cd $(distdir)/=build    && ../configure --srcdir=.. --prefix=$$dc_install_base    && $(MAKE)    && $(MAKE) dvi    && $(MAKE) check    && $(MAKE) install    && $(MAKE) installcheck    && $(MAKE) dist
+	rm -rf $(distdir)
+	@echo "========================";  echo "$(distdir).tar.gz is ready for distribution";  echo "========================"
+dist: distdir
+	-chmod -R a+r $(distdir)
+	GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
+	rm -rf $(distdir)
+dist-all: distdir
+	-chmod -R a+r $(distdir)
+	GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
+	rm -rf $(distdir)
+distdir: $(DISTFILES)
+	rm -rf $(distdir)
+	mkdir $(distdir)
+	-chmod 777 $(distdir)
+	@for file in $(DISTFILES); do d=$(srcdir); test -f $(distdir)/$$file || ln $$d/$$file $(distdir)/$$file 2> /dev/null || cp -p $$d/$$file $(distdir)/$$file; done; for subdir in $(SUBDIRS); do test -d $(distdir)/$$subdir || mkdir $(distdir)/$$subdir || exit 1; chmod 777 $(distdir)/$$subdir; (cd $$subdir && $(MAKE) top_distdir=../$(top_distdir)/$$subdir distdir=../$(distdir)/$$subdir distdir) || exit 1; done
+	$(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info
+	$(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+
+info: $(INFO_DEPS) info-recursive
+dvi: $(DVIS) dvi-recursive
+check: all-am check-recursive check-local
+	@:
+installcheck: installcheck-recursive
+all-recursive-am: config.h
+	$(MAKE) all-recursive
+
+all-am: Makefile $(INFO_DEPS) $(PROGRAMS) config.h
+
+install-exec-am: install-binPROGRAMS
+
+install-data-am: install-info-am
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info
+
+install-exec: install-exec-recursive install-exec-am
+	@$(NORMAL_INSTALL)
+
+install-data: install-data-recursive install-data-am
+	@$(NORMAL_INSTALL)
+
+install-recursive uninstall-recursive:
+	@:
+
+install: install-recursive install-exec-am install-data-am
+	@:
+
+uninstall: uninstall-recursive uninstall-am
+
+all: all-recursive-am all-am
+
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs: installdirs-recursive
+	$(mkinstalldirs)  $(bindir) $(infodir)
+
+
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f Makefile $(DISTCLEANFILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean-am:  mostlyclean-hdr mostlyclean-binPROGRAMS  mostlyclean-compile mostlyclean-aminfo mostlyclean-tags  mostlyclean-generic
+
+clean-am:  clean-hdr clean-binPROGRAMS clean-compile clean-aminfo  clean-tags clean-generic mostlyclean-am
+
+distclean-am:  distclean-hdr distclean-binPROGRAMS distclean-compile  distclean-aminfo distclean-tags distclean-generic  clean-am
+
+maintainer-clean-am:  maintainer-clean-hdr maintainer-clean-binPROGRAMS  maintainer-clean-compile maintainer-clean-aminfo  maintainer-clean-tags maintainer-clean-generic  distclean-am
+
+mostlyclean:  mostlyclean-recursive mostlyclean-am
+
+clean: clean-noinstLIBRARIES clean-recursive clean-am
+
+distclean:  distclean-recursive distclean-am
+	rm -f config.status
+
+maintainer-clean:  maintainer-clean-recursive maintainer-clean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+	rm -f config.status
+
+.PHONY: default mostlyclean-hdr distclean-hdr clean-hdr \
+maintainer-clean-hdr mostlyclean-binPROGRAMS distclean-binPROGRAMS \
+clean-binPROGRAMS maintainer-clean-binPROGRAMS uninstall-binPROGRAMS \
+install-binPROGRAMS mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile install-info-am uninstall-info \
+mostlyclean-aminfo distclean-aminfo clean-aminfo \
+maintainer-clean-aminfo install-data-recursive uninstall-data-recursive \
+install-exec-recursive uninstall-exec-recursive installdirs-recursive \
+uninstalldirs-recursive all-recursive check-recursive check-am \
+installcheck-recursive info-recursive dvi-recursive \
+mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi check-local installcheck \
+all-recursive-am all-am install-exec-am install-data-am uninstall-am \
+install-exec install-data install uninstall all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# --------------- Local DIST Section
+
+# Install the w32 subdirectory
+#
+dist-hook:
+	(cd $(srcdir); \
+	 w32=`find w32 -follow \( -name CVS -prune \) -o -type f -print`; \
+	 tar chf - $$w32) \
+	| (cd $(distdir); tar xfBp -)
+
+# --------------- Local CHECK Section
+
+# Note: check-loadavg is NOT a prerequisite of check-local, since
+# there's no uptime utility, and the test it does doesn't make sense
+# on MSDOS anyway.
+check-local: check-shell check-regression
+	@banner=" Regression PASSED: GNU Make $(VERSION) ($(MAKE_HOST)) built with $(CC) "; \
+	dashes=`echo "$$banner" | sed s/./=/g`; \
+	echo; \
+	echo "$$dashes"; \
+	echo "$$banner"; \
+	echo "$$dashes"; \
+	echo
+
+.PHONY: check-loadavg check-shell check-regression
+
+# > check-shell
+#
+# check-shell is designed to fail if they don't have a Unixy shell
+# installed.  The test suite requires such a shell.
+check-shell:
+	@echo If Make says Error -1, you do not have Unix-style shell installed
+	@foo=bar.exe :
+
+# > check-loadavg
+#
+loadavg: loadavg.c config.h
+	@rm -f loadavg
+	$(LINK) -DTEST $(make_LDFLAGS) loadavg.c $(LIBS)
+# We copy getloadavg.c into a different file rather than compiling it
+# directly because some compilers clobber getloadavg.o in the process.
+loadavg.c: getloadavg.c
+	ln $(srcdir)/getloadavg.c loadavg.c || \
+	cp $(srcdir)/getloadavg.c loadavg.c
+check-loadavg: loadavg
+	@echo The system uptime program believes the load average to be:
+	-uptime
+	@echo The GNU load average checking code believes:
+	-./loadavg
+
+# > check-regression
+#
+# Look for the make test suite, and run it if found.  Look in MAKE_TEST if
+# specified, or else in the srcdir or the distdir, their parents, and _their_
+# parents.
+#
+check-regression:
+	@if test -f "$(srcdir)/tests/run_make_tests"; then \
+	  if $(PERL) -v >/dev/null 2>&1; then \
+	    case `cd $(srcdir); pwd` in `pwd`) : ;; \
+	      *) test -d tests || mkdir tests; \
+		 for f in run_make_tests run_make_tests.pl test_driver.pl scripts; do \
+		   rm -rf tests/$$f; cp -pr $(srcdir)/tests/$$f tests; \
+		 done ;; \
+	    esac; \
+	    echo "cd tests && $(PERL) ./run_make_tests.pl -make ../make.exe $(MAKETESTFLAGS)"; \
+	    cd tests && $(PERL) ./run_make_tests.pl -make ../make.exe $(MAKETESTFLAGS); \
+	  else \
+	    echo "Can't find a working Perl ($(PERL)); the test suite requires Perl."; \
+	  fi; \
+	 else \
+	  echo "Can't find the GNU Make test suite ($(srcdir)/tests)."; \
+	 fi
+
+# --------------- Maintainer's Section
+
+# Note this requires GNU make.  Not to worry, since it will only be included
+# in the Makefile if we're in the maintainer's environment.
+#include $(srcdir)/maintMakefile
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+# --------------- DEPENDENCIES
Index: /tags/kBuild-0.1.4/src/kmk/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/Makefile.am	(revision 1780)
@@ -0,0 +1,286 @@
+# This is a -*-Makefile-*-, or close enough
+#
+# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+AUTOMAKE_OPTIONS = 1.8 dist-bzip2 check-news
+ACLOCAL_AMFLAGS	=  -I config
+
+MAKE_HOST =	@MAKE_HOST@
+
+# Only process if target is MS-Windows
+if WINDOWSENV
+  MAYBE_W32 =	w32
+  W32INC =	-I $(top_srcdir)/w32/include
+  W32LIB =	-Lw32 -lw32
+endif
+
+# we can safely drop doc and po when bootstrapping kmk.
+# SUBDIRS =	glob config po doc $(MAYBE_W32)
+SUBDIRS =	glob config $(MAYBE_W32)
+
+bin_PROGRAMS =	kmk kmk_redirect
+
+if USE_CUSTOMS
+  remote =	remote-cstms.c
+else
+  remote =	remote-stub.c
+endif
+
+
+kmk_SOURCES =	ar.c arscan.c commands.c default.c dir.c expand.c file.c \
+		function.c getopt.c getopt1.c implicit.c job.c main.c \
+		misc.c read.c remake.c $(remote) rule.c signame.c \
+		strcache.c variable.c version.c vpath.c hash.c \
+		\
+		expreval.c \
+		kbuild.c \
+		electric.c \
+		../lib/md5.c \
+		../lib/kDep.c \
+		\
+		kmkbuiltin.c \
+		kmkbuiltin/append.c \
+		kmkbuiltin/cat.c \
+		kmkbuiltin/chmod.c \
+		kmkbuiltin/cmp.c \
+		kmkbuiltin/cmp_util.c \
+		kmkbuiltin/cp.c \
+		kmkbuiltin/cp_utils.c \
+		kmkbuiltin/echo.c \
+		kmkbuiltin/expr.c \
+		kmkbuiltin/install.c \
+		kmkbuiltin/kDepIDB.c \
+		kmkbuiltin/ln.c \
+		kmkbuiltin/md5sum.c \
+		kmkbuiltin/mkdir.c \
+		kmkbuiltin/mv.c \
+		kmkbuiltin/printf.c \
+		kmkbuiltin/rm.c \
+		kmkbuiltin/rmdir.c \
+		kmkbuiltin/test.c \
+		kmkbuiltin/err.c \
+		kmkbuiltin/setmode.c \
+		kmkbuiltin/strmode.c \
+		kmkbuiltin/strlcpy.c \
+		kmkbuiltin/osdep.c \
+		kmkbuiltin/kbuild_protection.c \
+		kmkbuiltin/kbuild_version.c
+
+kmk_redirect_SOURCES = kmkbuiltin/redirect.c
+
+EXTRA_kmk_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c
+
+noinst_HEADERS = commands.h dep.h filedef.h job.h make.h rule.h variable.h \
+		debug.h getopt.h gettext.h hash.h
+
+#kmk_LDADD =	@LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@
+kmk_LDADD =	@LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@
+# Only process if target is MS-Windows
+if WINDOWSENV
+    kmk_LDADD += $(W32LIB)
+endif
+
+man_MANS =	make.1
+
+# org - DEFS =		-DLOCALEDIR=\"$(localedir)\" -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\" @DEFS@
+DEFS = \
+	-DNO_ARCHIVES \
+	-DEXPERIMENTAL \
+	-DCONFIG_WITH_TOUPPER_TOLOWER \
+	-DCONFIG_WITH_DEFINED \
+	-DCONFIG_WITH_EXPLICIT_MULTITARGET \
+	-DCONFIG_WITH_PREPEND_ASSIGNMENT \
+	-DCONFIG_WITH_LOCAL_VARIABLES \
+	-DCONFIG_WITH_2ND_TARGET_EXPANSION \
+	\
+	-DKMK \
+	-DKMK_HELPERS \
+	-DVARIABLE_HASH \
+	-DCONFIG_NO_DEFAULT_SUFFIXES \
+	-DCONFIG_NO_DEFAULT_PATTERN_RULES	\
+	-DCONFIG_NO_DEFAULT_TERMINAL_RULES \
+	-DCONFIG_NO_DEFAULT_SUFFIX_RULES \
+	-DCONFIG_NO_DEFAULT_VARIABLES \
+	-DCONFIG_WITH_EXTENDED_NOTPARALLEL \
+	-DCONFIG_WITH_INCLUDEDEP \
+	-DCONFIG_WITH_VALUE_LENGTH \
+	-DCONFIG_WITH_RSORT \
+	-DCONFIG_WITH_ABSPATHEX \
+	-DCONFIG_WITH_COMPARE \
+	-DCONFIG_WITH_STACK \
+	-DCONFIG_WITH_MATH \
+	-DCONFIG_WITH_XARGS \
+	-DCONFIG_WITH_NANOTS \
+	-DCONFIG_WITH_SET_CONDITIONALS \
+	-DCONFIG_WITH_IF_CONDITIONALS \
+	-DCONFIG_WITH_DATE \
+	-DCONFIG_WITH_FILE_SIZE \
+	-DCONFIG_WITH_WHICH \
+	-DCONFIG_WITH_EVALPLUS \
+	-DCONFIG_WITH_MAKE_STATS \
+	-DCONFIG_WITH_COMMANDS_FUNC \
+	-DCONFIG_PRETTY_COMMAND_PRINTING \
+	\
+	-DKBUILD_HOST=\"$(BUILD_TARGET)\" \
+	-DKBUILD_HOST_ARCH=\"$(BUILD_TARGET_ARCH)\" \
+	-DKBUILD_HOST_CPU=\"$(BUILD_TARGET_CPU)\" \
+	\
+	-DKBUILD_SVN_REV=1 \
+	-DKBUILD_VERSION_MAJOR=0 \
+	-DKBUILD_VERSION_MINOR=1 \
+	-DKBUILD_VERSION_PATCH=4 \
+	\
+	-DCONFIG_WITH_KMK_BUILTIN \
+    @DEFS@
+
+AM_CPPFLAGS =	$(GLOBINC) -I$(srcdir)/../lib
+# Only process if target is MS-Windows
+if WINDOWSENV
+    AM_CPPFLAGS +=	$(W32INC)
+endif
+
+
+# Extra stuff to include in the distribution.
+
+EXTRA_DIST =	README build.sh.in $(man_MANS) \
+		README.customs README.OS2 \
+		SCOPTIONS SMakefile \
+		README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h \
+		README.DOS Makefile.DOS configure.bat dosbuild.bat configh.dos\
+		README.W32 NMakefile config.h.W32 build_w32.bat subproc.bat \
+		make_msvc_net2003.sln make_msvc_net2003.vcproj \
+		readme.vms makefile.vms makefile.com config.h-vms \
+		vmsdir.h vmsfunctions.c vmsify.c
+
+# This is built during configure, but behind configure's back
+
+DISTCLEANFILES = build.sh
+
+# Forward targets
+
+html:
+	cd doc && $(MAKE) $(AM_MAKEFLAGS) $@
+
+.PHONY: html
+
+# --------------- Internationalization Section
+
+localedir =	$(datadir)/locale
+
+# --------------- Local INSTALL Section
+
+# If necessary, change the gid of the app and turn on the setgid flag.
+#
+
+# Whether or not make needs to be installed setgid.
+# The value should be either `true' or `false'.
+# On many systems, the getloadavg function (used to implement the `-l'
+# switch) will not work unless make is installed setgid kmem.
+#
+inst_setgid = @NEED_SETGID@
+
+# Install make setgid to this group so it can get the load average.
+#
+inst_group = @KMEM_GROUP@
+
+install-exec-local:
+	@if $(inst_setgid); then \
+	   app=$(DESTDIR)$(bindir)/`echo $(bin_PROGRAMS)|sed '$(transform)'`; \
+	   if chgrp $(inst_group) $$app && chmod g+s $$app; then \
+	     echo "chgrp $(inst_group) $$app && chmod g+s $$app"; \
+	   else \
+	     echo "$$app needs to be owned by group $(inst_group) and setgid;"; \
+	     echo "otherwise the \`-l' option will probably not work."; \
+	     echo "You may need special privileges to complete the installation"; \
+	     echo "of $$app."; \
+	   fi; \
+	 else true; fi
+
+# --------------- Local DIST Section
+
+# Install the w32 and tests subdirectories
+#
+dist-hook:
+	(cd $(srcdir); \
+	 sub=`find w32 tests -follow \( -name CVS -prune -o -name .cvsignore -o -name work -prune \) -o \( -name \*.orig -o -name \*.rej -o -name \*~ -prune \) -o -type f -print`; \
+	 tar chf - $$sub) \
+	| (cd $(distdir); tar xfBp -)
+
+
+# --------------- Local CHECK Section
+
+check-local: check-regression check-loadavg
+	@banner=" Regression PASSED: GNU Make $(VERSION) ($(MAKE_HOST)) built with $(CC) "; \
+	dashes=`echo "$$banner" | sed s/./=/g`; \
+	echo; \
+	echo "$$dashes"; \
+	echo "$$banner"; \
+	echo "$$dashes"; \
+	echo
+
+.PHONY: check-loadavg check-regression
+
+check-loadavg: loadavg$(EXEEXT)
+	@echo The system uptime program believes the load average to be:
+	-uptime
+	@echo The GNU load average checking code thinks:
+	-./loadavg$(EXEEXT)
+
+# The loadavg function is invoked during "make check" to test getloadavg.
+check_PROGRAMS = loadavg
+nodist_loadavg_SOURCES = getloadavg.c
+loadavg_CPPFLAGS = -DTEST
+loadavg_LDADD = @GETLOADAVG_LIBS@
+
+# > check-regression
+#
+# Look for the make test suite, and run it if found and we can find perl.
+# If we're building outside the tree, we use symlinks to make a local copy of
+# the test suite.  Unfortunately the test suite itself isn't localizable yet.
+#
+MAKETESTFLAGS =
+
+check-regression:
+	@if test -f "$(srcdir)/tests/run_make_tests"; then \
+	  if $(PERL) -v >/dev/null 2>&1; then \
+	    case `cd $(srcdir); pwd` in `pwd`) : ;; \
+	      *) test -d tests || mkdir tests; \
+		 rm -f srctests; \
+		 if ln -s "$(srcdir)/tests" srctests; then \
+		   for f in run_make_tests run_make_tests.pl test_driver.pl scripts; do \
+		     rm -f tests/$$f; ln -s ../srctests/$$f tests; \
+		   done; fi ;; \
+	    esac; \
+	    echo "cd tests && $(PERL) ./run_make_tests.pl -make ../make$(EXEEXT) $(MAKETESTFLAGS)"; \
+	    cd tests && $(PERL) ./run_make_tests.pl -make ../make$(EXEEXT) $(MAKETESTFLAGS); \
+	  else \
+	    echo "Can't find a working Perl ($(PERL)); the test suite requires Perl."; \
+	  fi; \
+	 else \
+	  echo "Can't find the GNU Make test suite ($(srcdir)/tests)."; \
+	 fi
+
+
+# --------------- Maintainer's Section
+
+# Tell automake that I haven't forgotten about this file and it will be
+# created before we build a distribution (see maintMakefile in the CVS
+# distribution).
+
+README:
+
+@MAINT_MAKEFILE@
Index: /tags/kBuild-0.1.4/src/kmk/Makefile.ami
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/Makefile.ami	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/Makefile.ami	(revision 1780)
@@ -0,0 +1,306 @@
+# -*-Makefile-*- for GNU make on Amiga
+#
+# NOTE: If you have no `make' program at all to process this makefile, run
+# `build.sh' instead.
+#
+# Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#
+#	Makefile for GNU Make
+#
+
+CC = sc
+RM = delete
+
+CFLAGS =
+CPPFLAGS =
+LDFLAGS =
+
+# Define these for your system as follows:
+#	-DNO_ARCHIVES		To disable `ar' archive support.
+#	-DNO_FLOAT		To avoid using floating-point numbers.
+#	-DENUM_BITFIELDS	If the compiler isn't GCC but groks enum foo:2.
+#				Some compilers apparently accept this
+#				without complaint but produce losing code,
+#				so beware.
+# NeXT 1.0a uses an old version of GCC, which required -D__inline=inline.
+# See also `config.h'.
+defines =
+
+# Which flavor of remote job execution support to use.
+# The code is found in `remote-$(REMOTE).c'.
+REMOTE = stub
+
+# If you are using the GNU C library, or have the GNU getopt functions in
+# your C library, you can comment these out.
+GETOPT = getopt.o getopt1.o
+GETOPT_SRC = $(srcdir)getopt.c $(srcdir)getopt1.c $(srcdir)getopt.h
+
+# If you are using the GNU C library, or have the GNU glob functions in
+# your C library, you can comment this out.  GNU make uses special hooks
+# into the glob functions to be more efficient (by using make's directory
+# cache for globbing), so you must use the GNU functions even if your
+# system's C library has the 1003.2 glob functions already.  Also, the glob
+# functions in the AIX and HPUX C libraries are said to be buggy.
+GLOB = glob/glob.lib
+
+# If your system doesn't have alloca, or the one provided is bad, define this.
+ALLOCA = alloca.o
+ALLOCA_SRC = $(srcdir)alloca.c
+
+# If your system needs extra libraries loaded in, define them here.
+# System V probably need -lPW for alloca.  HP-UX 7.0's alloca in
+# libPW.a is broken on HP9000s300 and HP9000s400 machines.  Use
+# alloca.c instead on those machines.
+LOADLIBES =
+
+# Any extra object files your system needs.
+extras = amiga.o
+
+# Common prefix for machine-independent installed files.
+prefix =
+# Common prefix for machine-dependent installed files.
+exec_prefix =
+
+# Directory to install `make' in.
+bindir = sc:c
+# Directory to find libraries in for `-lXXX'.
+libdir = lib:
+# Directory to search by default for included makefiles.
+includedir = include:
+# Directory to install the Info files in.
+infodir = doc:
+# Directory to install the man page in.
+mandir = t:
+# Number to put on the man page filename.
+manext = 1
+# Prefix to put on installed `make' binary file name.
+binprefix =
+# Prefix to put on installed `make' man page file name.
+manprefix = $(binprefix)
+
+# Whether or not make needs to be installed setgid.
+# The value should be either `true' or `false'.
+# On many systems, the getloadavg function (used to implement the `-l'
+# switch) will not work unless make is installed setgid kmem.
+install_setgid = false
+# Install make setgid to this group so it can read /dev/kmem.
+group = sys
+
+# Program to install `make'.
+INSTALL_PROGRAM = copy
+# Program to install the man page.
+INSTALL_DATA = copy
+# Generic install program.
+INSTALL = copy
+
+# Program to format Texinfo source into Info files.
+MAKEINFO = makeinfo
+# Program to format Texinfo source into DVI files.
+TEXI2DVI = texi2dvi
+
+# Programs to make tags files.
+ETAGS = etags -w
+CTAGS = ctags -w
+
+objs = commands.o job.o dir.o file.o misc.o main.o read.o remake.o	\
+       rule.o implicit.o default.o variable.o expand.o function.o	\
+       vpath.o version.o ar.o arscan.o signame.o strcache.o hash.o      \
+       remote-$(REMOTE).o $(GETOPT) $(ALLOCA) $(extras)
+srcs = $(srcdir)commands.c $(srcdir)job.c $(srcdir)dir.c             \
+       $(srcdir)file.c $(srcdir)getloadavg.c $(srcdir)misc.c         \
+       $(srcdir)main.c $(srcdir)read.c $(srcdir)remake.c             \
+       $(srcdir)rule.c $(srcdir)implicit.c $(srcdir)default.c        \
+       $(srcdir)variable.c $(srcdir)expand.c $(srcdir)function.c     \
+       $(srcdir)vpath.c $(srcdir)version.c $(srcdir)hash.c           \
+       $(srcdir)remote-$(REMOTE).c                                     \
+       $(srcdir)ar.c $(srcdir)arscan.c $(srcdir)strcache.c              \
+       $(srcdir)signame.c $(srcdir)signame.h $(GETOPT_SRC)            \
+       $(srcdir)commands.h $(srcdir)dep.h $(srcdir)filedep.h            \
+       $(srcdir)job.h $(srcdir)make.h $(srcdir)rule.h                \
+       $(srcdir)variable.h $(ALLOCA_SRC) $(srcdir)config.h.in
+
+
+.SUFFIXES:
+.SUFFIXES: .o .c .h .ps .dvi .info .texinfo
+
+all: make
+info: make.info
+dvi: make.dvi
+# Some makes apparently use .PHONY as the default goal if it is before `all'.
+.PHONY: all check info dvi
+
+make.info: make.texinfo
+	$(MAKEINFO) -I$(srcdir) $(srcdir)make.texinfo -o make.info
+
+make.dvi: make.texinfo
+	$(TEXI2DVI) $(srcdir)make.texinfo
+
+make.ps: make.dvi
+	dvi2ps make.dvi > make.ps
+
+make: $(objs) $(GLOB)
+	$(CC) Link $(LDFLAGS) $(objs) Lib $(GLOB) $(LOADLIBES) To make.new
+	-delete make
+	rename make.new make
+
+TMPFILE = t:Make$$
+
+$(GLOB):
+	cd glob @@\
+	$(MAKE) -$(MAKEFLAGS) -f Makefile
+
+# -I. is needed to find config.h in the build directory.
+OUTPUT_OPTION =
+.c.o:
+	$(CC) $(defines) IDir "" IDir glob \
+	      $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION)
+
+# For some losing Unix makes.
+SHELL = /bin/sh
+#@SET_MAKE@
+
+glob/libglob.a: FORCE config.h
+	cd glob; $(MAKE) libglob.a
+FORCE:
+
+tagsrcs = $(srcs) $(srcdir)remote-*.c
+
+.PHONY: install installdirs
+install: installdirs \
+	 $(bindir)$(binprefix)make $(infodir)make.info \
+	 $(mandir)$(manprefix)make.$(manext)
+
+installdirs:
+	$(SHELL) ${srcdir}/mkinstalldirs $(bindir) $(infodir) $(mandir)
+
+$(bindir)$(binprefix)make: make
+	$(INSTALL_PROGRAM) make $@.new
+	@if $(install_setgid); then \
+	   if chgrp $(group) $@.new && chmod g+s $@.new; then \
+	     echo "chgrp $(group) $@.new && chmod g+s $@.new"; \
+	   else \
+	     echo "$@ needs to be owned by group $(group) and setgid;"; \
+	     echo "otherwise the \`-l' option will probably not work."; \
+	     echo "You may need special privileges to install $@."; \
+	   fi; \
+	 else true; fi
+# Some systems can't deal with renaming onto a running binary.
+	-$(RM) $@.old
+	-mv $@ $@.old
+	mv $@.new $@
+
+$(infodir)make.info: make.info
+	if [ -r ./make.info ]; then dir=.; else dir=$(srcdir); fi; \
+	for file in $${dir}/make.info*; do \
+	  name="`basename $$file`"; \
+	  $(INSTALL_DATA) $$file \
+	    `echo $@ | sed "s,make.info\$$,$$name,"`; \
+	done
+# Run install-info only if it exists.
+# Use `if' instead of just prepending `-' to the
+# line so we notice real errors from install-info.
+# We use `$(SHELL) -c' because some shells do not
+# fail gracefully when there is an unknown command.
+	if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
+	  if [ -r ./make.info ]; then dir=.; else dir=$(srcdir); fi; \
+	  install-info --infodir=$(infodir) $$dir/make.info; \
+	else true; fi
+
+$(mandir)$(manprefix)make.$(manext): make.man
+	$(INSTALL_DATA) $(srcdir)make.man $@
+
+
+loadavg: loadavg.c config.h
+	$(CC) $(defines) -DTEST -I. -I$(srcdir) $(CFLAGS) $(LDFLAGS) \
+	      loadavg.c $(LOADLIBES) -o $@
+# We copy getloadavg.c into a different file rather than compiling it
+# directly because some compilers clobber getloadavg.o in the process.
+loadavg.c: getloadavg.c
+	ln $(srcdir)getloadavg.c loadavg.c || \
+	cp $(srcdir)getloadavg.c loadavg.c
+check-loadavg: loadavg
+	@echo The system uptime program believes the load average to be:
+	-uptime
+	@echo The GNU load average checking code believes:
+	./loadavg
+check: check-loadavg
+
+
+.PHONY: clean realclean distclean mostlyclean
+clean: glob-clean
+	-$(RM) make loadavg "#?.o" core make.dvi
+
+distclean: clean glob-realclean
+	-$(RM) Makefile config.h config.status build.sh
+	-$(RM) config.log config.cache
+	-$(RM) TAGS tags
+	-$(RM) make.?? make.??s make.log make.toc make.*aux
+	-$(RM) loadavg.c
+
+realclean: distclean
+	-$(RM) make.info*
+mostlyclean: clean
+
+.PHONY: glob-clean glob-realclean
+glob-clean glob-realclean:
+	cd glob @@\
+	$(MAKE) $@
+
+# This tells versions [3.59,3.63) of GNU make not to export all variables.
+.NOEXPORT:
+
+# The automatically generated dependencies below may omit config.h
+# because it is included with ``#include <config.h>'' rather than
+# ``#include "config.h"''.  So we add the explicit dependency to make sure.
+$(objs): config.h
+
+# Automatically generated dependencies will be put at the end of the file.
+
+# Automatically generated dependencies.
+commands.o: commands.c make.h dep.h filedef.h variable.h job.h \
+ commands.h
+job.o: job.c make.h job.h filedef.h commands.h variable.h
+dir.o: dir.c make.h
+file.o: file.c make.h dep.h filedef.h job.h commands.h variable.h
+misc.o: misc.c make.h dep.h
+main.o: main.c make.h dep.h filedef.h variable.h job.h commands.h \
+ getopt.h
+read.o: read.c make.h dep.h filedef.h job.h commands.h variable.h \
+ glob/glob.h
+remake.o: remake.c make.h filedef.h job.h commands.h dep.h
+rule.o: rule.c make.h dep.h filedef.h job.h commands.h variable.h \
+ rule.h
+implicit.o: implicit.c make.h rule.h dep.h filedef.h
+default.o: default.c make.h rule.h dep.h filedef.h job.h commands.h \
+ variable.h
+variable.o: variable.c make.h dep.h filedef.h job.h commands.h \
+ variable.h
+expand.o: expand.c make.h filedef.h job.h commands.h variable.h
+function.o: function.c make.h filedef.h variable.h dep.h job.h \
+ commands.h amiga.h
+vpath.o: vpath.c make.h filedef.h variable.h
+strcache.o: strcache.c make.h hash.h
+version.o: version.c
+ar.o: ar.c make.h filedef.h dep.h
+arscan.o: arscan.c make.h
+signame.o: signame.c signame.h
+remote-stub.o: remote-stub.c make.h filedef.h job.h commands.h
+getopt.o: getopt.c
+getopt1.o : getopt1.c getopt.h
+getloadavg.o: getloadavg.c
+amiga.o: amiga.c make.h variable.h amiga.h
Index: /tags/kBuild-0.1.4/src/kmk/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/Makefile.kmk	(revision 1780)
@@ -0,0 +1,515 @@
+# $Id$
+## @file
+# Sub-makefile for kmk / GNU Make.
+#
+
+#
+# Copyright (c) 2004-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../..
+include $(KBUILD_PATH)/subheader.kmk
+
+
+#
+# Template for kmk and the kmk_* binaries in this makefile.
+#
+TEMPLATE_BIN-KMK = Template for src/gmake binaries
+TEMPLATE_BIN-KMK_EXTENDS = BIN
+TEMPLATE_BIN-KMK_DEFS = \
+	HAVE_CONFIG_H \
+	$(TEMPLATE_BIN_DEFS) \
+	KBUILD_SVN_REV=$(KBUILD_SVN_REV)
+TEMPLATE_BIN-KMK_DEPS = $(PATH_kmk)/config.h
+TEMPLATE_BIN-KMK_CLEAN = $(TEMPLATE_BIN-KMK_DEPS)
+TEMPLATE_BIN-KMK_DEPS.solaris = \
+	$(PATH_kmk)/fts.h \
+	$(PATH_kmk)/paths.h
+TEMPLATE_BIN-KMK_CLEAN.solaris = $(TEMPLATE_BIN-KMK_DEPS.solaris)
+TEMPLATE_BIN-KMK_DEPS.win     = \
+	$(PATH_kmk)/fts.h \
+	$(PATH_kmk)/sysexits.h \
+	$(PATH_kmk)/unistd.h \
+	$(PATH_kmk)/paths.h \
+	$(PATH_kmk)/grp.h \
+	$(PATH_kmk)/pwd.h \
+	$(PATH_kmk)/inttypes.h
+TEMPLATE_BIN-KMK_CFLAGS.win.amd64 = $(TEMPLATE_BIN_CFLAGS.win.amd64) -wd4244 -wd4267
+TEMPLATE_BIN-KMK_CLEAN.win = $(TEMPLATE_BIN-KMK_DEPS.win)
+TEMPLATE_BIN-KMK_INCS = $(PATH_kmk) . $(TEMPLATE_BIN_INCS)
+TEMPLATE_BIN-KMK_INCS.darwin = glob
+TEMPLATE_BIN-KMK_INCS.dragonfly = glob
+TEMPLATE_BIN-KMK_INCS.freebsd = glob
+TEMPLATE_BIN-KMK_INCS.solaris = glob
+TEMPLATE_BIN-KMK_LIBS = $(TEMPLATE_BIN_LIBS) $(TARGET_kmkmissing) $(LIB_KUTIL)
+ifdef ELECTRIC_HEAP # for electric heap (see electric.c) - windows only.
+ifeq ($(KBUILD_TARGET),win)
+ TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN_CFLAGS) /FI$(kmk_PATH)/electric.h -DELECTRIC_HEAP=1
+else
+ TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN_CFLAGS) -include $(kmk_PATH)/electric.h -DELECTRIC_HEAP=1
+endif
+endif
+
+
+#
+# A library containing the missing features needed by kmk and the
+# kmk_* binaries. Saves a bit of work later on.
+#
+LIBRARIES += kmkmissing
+kmkmissing_TEMPLATE = BIN-KMK
+kmkmissing_DEFS = KMK
+kmkmissing_NOINST = 1
+kmkmissing_SOURCES = \
+	kmkbuiltin/err.c \
+	kmkbuiltin/setmode.c \
+	kmkbuiltin/strmode.c \
+	kmkbuiltin/kbuild_version.c \
+	kmkbuiltin/kbuild_protection.c \
+	getopt.c \
+	getopt1.c \
+	electric.c
+
+kmkmissing_SOURCES.darwin = \
+	kmkbuiltin/darwin.c \
+	glob/glob.c \
+	glob/fnmatch.c
+
+kmkmissing_SOURCES.dragonfly = \
+	glob/glob.c \
+	glob/fnmatch.c
+
+kmkmissing_SOURCES.freebsd = \
+	glob/glob.c \
+	glob/fnmatch.c
+
+kmkmissing_SOURCES.linux += \
+	kmkbuiltin/strlcpy.c
+
+kmkmissing_SOURCES.solaris = \
+	kmkbuiltin/strlcpy.c \
+	kmkbuiltin/solfakes.c \
+	kmkbuiltin/fts.c \
+	glob/glob.c \
+	glob/fnmatch.c
+
+kmkmissing_SOURCES.win += \
+	kmkbuiltin/strlcpy.c \
+	kmkbuiltin/mscfakes.c \
+	kmkbuiltin/fts.c \
+	glob/glob.c \
+	glob/fnmatch.c \
+	getloadavg.c \
+	w32/subproc/misc.c \
+	w32/subproc/sub_proc.c \
+	w32/subproc/w32err.c \
+	w32/compat/dirent.c \
+	w32/pathstuff.c
+
+#
+# kmk
+#
+PROGRAMS += kmk
+
+kmk_TEMPLATE = BIN-KMK
+
+kmk_DEFS = \
+	NO_ARCHIVES \
+	EXPERIMENTAL \
+	CONFIG_WITH_TOUPPER_TOLOWER \
+	CONFIG_WITH_DEFINED \
+	CONFIG_WITH_EXPLICIT_MULTITARGET \
+	CONFIG_WITH_PREPEND_ASSIGNMENT \
+	CONFIG_WITH_LOCAL_VARIABLES \
+	CONFIG_WITH_2ND_TARGET_EXPANSION \
+	\
+	KMK \
+	KMK_HELPERS \
+	VARIABLE_HASH \
+	CONFIG_NO_DEFAULT_SUFFIXES \
+	CONFIG_NO_DEFAULT_PATTERN_RULES	\
+	CONFIG_NO_DEFAULT_TERMINAL_RULES \
+	CONFIG_NO_DEFAULT_SUFFIX_RULES \
+	CONFIG_NO_DEFAULT_VARIABLES \
+	CONFIG_WITH_EXTENDED_NOTPARALLEL \
+	CONFIG_WITH_INCLUDEDEP \
+	CONFIG_WITH_VALUE_LENGTH \
+	CONFIG_WITH_RSORT \
+	CONFIG_WITH_ABSPATHEX \
+	CONFIG_WITH_COMPARE \
+	CONFIG_WITH_STACK \
+	CONFIG_WITH_MATH \
+	CONFIG_WITH_XARGS \
+	CONFIG_WITH_NANOTS \
+	CONFIG_WITH_SET_CONDITIONALS \
+	CONFIG_WITH_IF_CONDITIONALS \
+	CONFIG_WITH_DATE \
+	CONFIG_WITH_FILE_SIZE \
+	CONFIG_WITH_WHICH \
+	CONFIG_WITH_EVALPLUS \
+	CONFIG_WITH_MAKE_STATS \
+	CONFIG_WITH_COMMANDS_FUNC \
+	CONFIG_PRETTY_COMMAND_PRINTING \
+	\
+	KBUILD_HOST=\"$(KBUILD_TARGET)\" \
+	KBUILD_HOST_ARCH=\"$(KBUILD_TARGET_ARCH)\" \
+	KBUILD_HOST_CPU=\"$(KBUILD_TARGET_CPU)\"
+kmk_DEFS.x86 = CONFIG_WITH_OPTIMIZATION_HACKS
+kmk_DEFS.amd64 = CONFIG_WITH_OPTIMIZATION_HACKS
+kmk_DEFS.win = CONFIG_NEW_WIN32_CTRL_EVENT
+
+kmk_SOURCES = \
+	main.c \
+	read.c \
+	expreval.c \
+	hash.c \
+	strcache.c \
+	variable.c \
+	ar.c \
+	arscan.c \
+	commands.c \
+	default.c \
+	dir.c \
+	expand.c \
+	file.c \
+	function.c \
+	implicit.c \
+	job.c \
+	misc.c \
+	remake.c \
+	rule.c \
+	signame.c \
+	version.c \
+	vpath.c \
+	remote-stub.c \
+	kbuild.c
+
+#
+# kmkbuiltin commands
+#
+kmk_DEFS += CONFIG_WITH_KMK_BUILTIN
+kmk_LIBS += $(LIB_KUTIL) $(LIB_KDEP)
+kmk_SOURCES += \
+	kmkbuiltin.c \
+	kmkbuiltin/append.c \
+	kmkbuiltin/cat.c \
+	kmkbuiltin/chmod.c \
+	kmkbuiltin/cmp.c \
+	kmkbuiltin/cmp_util.c \
+	kmkbuiltin/cp.c \
+	kmkbuiltin/cp_utils.c \
+	kmkbuiltin/echo.c \
+	kmkbuiltin/expr.c \
+	kmkbuiltin/install.c \
+	kmkbuiltin/kDepIDB.c \
+	kmkbuiltin/md5sum.c \
+	kmkbuiltin/mkdir.c \
+	kmkbuiltin/mv.c \
+	kmkbuiltin/ln.c \
+	kmkbuiltin/printf.c \
+	kmkbuiltin/rm.c \
+	kmkbuiltin/rmdir.c \
+	kmkbuiltin/test.c \
+
+## @todo kmkbuiltin/redirect.c
+
+## Some profiling
+#kmk_SOURCES += kbuildprf.c
+#kmk_DEFS += open=prf_open read=prf_read lseek=prf_lseek close=prf_close
+##kmk_DEFS += KMK_PRF=1
+##kmkmissing_DEFS += KMK_PRF=1
+
+#
+# Standalone kmkbuiltin commands.
+#
+PROGRAMS += \
+	kmk_append \
+	kmk_cat \
+	kmk_chmod \
+	kmk_cp \
+	kmk_cmp \
+	kmk_echo \
+	kmk_expr \
+	kmk_md5sum \
+	kmk_mkdir \
+	kmk_mv \
+	kmk_install \
+	kmk_ln \
+	kmk_printf \
+	kmk_redirect \
+	kmk_rm \
+	kmk_rmdir \
+	kmk_test \
+	kDepIDB \
+
+kmk_append_TEMPLATE = BIN-KMK
+kmk_append_DEFS = kmk_builtin_append=main
+kmk_append_INCS = .
+kmk_append_SOURCES = \
+	kmkbuiltin/append.c
+
+kmk_cat_TEMPLATE = BIN-KMK
+kmk_cat_DEFS = kmk_builtin_cat=main
+kmk_cat_SOURCES = \
+	kmkbuiltin/cat.c
+
+kmk_chmod_TEMPLATE = BIN-KMK
+kmk_chmod_DEFS = kmk_builtin_chmod=main
+kmk_chmod_SOURCES = \
+	kmkbuiltin/chmod.c
+
+kmk_cmp_TEMPLATE = BIN-KMK
+kmk_cmp_DEFS = kmk_builtin_cmp=main
+kmk_cmp_SOURCES = \
+	kmkbuiltin/cmp.c \
+	kmkbuiltin/cmp_util.c
+
+kmk_cp_TEMPLATE = BIN-KMK
+kmk_cp_DEFS = kmk_builtin_cp=main
+kmk_cp_SOURCES = \
+	kmkbuiltin/cp.c \
+	kmkbuiltin/cp_utils.c \
+	kmkbuiltin/cmp_util.c
+
+kmk_echo_TEMPLATE = BIN-KMK
+kmk_echo_DEFS = kmk_builtin_echo=main
+kmk_echo_SOURCES = \
+	kmkbuiltin/echo.c
+
+kmk_expr_TEMPLATE = BIN-KMK
+kmk_expr_DEFS = kmk_builtin_expr=main
+kmk_expr_SOURCES = \
+	kmkbuiltin/expr.c
+
+kmk_install_TEMPLATE = BIN-KMK
+kmk_install_DEFS = kmk_builtin_install=main
+kmk_install_SOURCES = \
+	kmkbuiltin/install.c
+
+kmk_ln_TEMPLATE = BIN-KMK
+kmk_ln_DEFS = kmk_builtin_ln=main
+kmk_ln_SOURCES = \
+	kmkbuiltin/ln.c
+
+kmk_mkdir_TEMPLATE = BIN-KMK
+kmk_mkdir_DEFS = kmk_builtin_mkdir=main
+kmk_mkdir_SOURCES = \
+	kmkbuiltin/mkdir.c
+
+kmk_md5sum_TEMPLATE = BIN-KMK
+kmk_md5sum_DEFS = kmk_builtin_md5sum=main
+kmk_md5sum_SOURCES = \
+	kmkbuiltin/md5sum.c
+kmk_md5sum_LIBS = $(LIB_KUTIL)
+
+kmk_mv_TEMPLATE = BIN-KMK
+kmk_mv_DEFS = kmk_builtin_mv=main
+kmk_mv_SOURCES = \
+	kmkbuiltin/mv.c
+
+kmk_printf_TEMPLATE = BIN-KMK
+kmk_printf_DEFS = kmk_builtin_printf=main
+kmk_printf_SOURCES = \
+	kmkbuiltin/printf.c
+
+kmk_rm_TEMPLATE = BIN-KMK
+kmk_rm_DEFS = kmk_builtin_rm=main
+kmk_rm_SOURCES = \
+	kmkbuiltin/rm.c
+
+kmk_redirect_TEMPLATE = BIN-KMK
+kmk_redirect_DEFS = kmk_builtin_redirect=main
+kmk_redirect_SOURCES = \
+	kmkbuiltin/redirect.c
+
+kmk_rmdir_TEMPLATE = BIN-KMK
+kmk_rmdir_DEFS = kmk_builtin_rmdir=main
+kmk_rmdir_SOURCES = \
+	kmkbuiltin/rmdir.c
+
+kmk_test_TEMPLATE = BIN-KMK
+kmk_test_DEFS = kmk_builtin_test=main
+kmk_test_SOURCES = \
+	kmkbuiltin/test.c
+
+kDepIDB_TEMPLATE = BIN-KMK
+kDepIDB_DEFS = kmk_builtin_kDepIDB=main
+kDepIDB_INCS = .
+kDepIDB_LIBS = $(LIB_KDEP)
+kDepIDB_SOURCES = \
+	kmkbuiltin/kDepIDB.c
+
+
+#
+# kmk_gmake - almost plain GNU Make.
+#
+PROGRAMS += kmk_gmake
+
+kmk_gmake_TEMPLATE = BIN-KMK
+kmk_gmake_DEFS = \
+	HAVE_CONFIG_H \
+	NO_ARCHIVES \
+	CONFIG_WITH_TOUPPER_TOLOWER \
+	EXPERIMENTAL
+
+kmk_gmake_SOURCES = \
+	main.c \
+	read.c \
+	hash.c \
+	strcache.c \
+	variable.c \
+	ar.c \
+	arscan.c \
+	commands.c \
+	default.c \
+	dir.c \
+	expand.c \
+	file.c \
+	function.c \
+	implicit.c \
+	job.c \
+	misc.c \
+	remake.c \
+	rule.c \
+	signame.c \
+	version.c \
+	vpath.c \
+	remote-stub.c
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
+
+#
+# Use checked in config.h instead of running ./Configure for it.
+#
+kmk_config.h.$(KBUILD_TARGET) := $(kmk_PATH)/config.h.$(KBUILD_TARGET)
+$(PATH_kmk)/config.h: $(kmk_config.h.$(KBUILD_TARGET))
+	$(MKDIR) -p $(dir $@)
+	$(CP) $^ $@
+
+#
+# Some missing headers.
+#
+$(PATH_kmk)/fts.h: $(kmk_PATH)/kmkbuiltin/ftsfake.h | $(call DIRDEP,$(PATH_kmk))
+	$(CP) $^ $@
+
+$(PATH_kmk)/unistd.h: | $(call DIRDEP,$(PATH_kmk))
+	$(ECHO_EXT) > $@
+
+$(PATH_kmk)/sysexits.h: | $(call DIRDEP,$(PATH_kmk))
+	$(ECHO_EXT) > $@
+
+$(PATH_kmk)/inttypes.h: | $(call DIRDEP,$(PATH_kmk))
+	$(ECHO_EXT) > $@
+
+$(PATH_kmk)/paths.h: | $(call DIRDEP,$(PATH_kmk))
+	$(ECHO_EXT) > $@
+
+$(PATH_kmk)/pwd.h: | $(call DIRDEP,$(PATH_kmk))
+	$(ECHO_EXT) > $@
+
+$(PATH_kmk)/grp.h: | $(call DIRDEP,$(PATH_kmk))
+	$(ECHO_EXT) > $@
+
+
+#
+# Some tests.
+#
+parallel: parallel_1 parallel_2 parallel_3 parallel_4 parallel_5
+parallel_1 parallel_2 parallel_3 parallel_4 parallel_5:
+	echo $@_start ; sleep 1; echo $@_done
+
+test:
+	echo "1"
+	echo "2"
+	echo "3"
+	echo "4"
+
+
+#
+# Shell execution tests.
+#
+test_shell: test_shell_quoting test_shell_double_quoting test_shell_newline
+
+# shell double and single quoting check (was busted on windows in 3.81).
+test_shell_quoting:
+	$(ECHO_EXT) "double quoted sTrInG"
+	$(ECHO_EXT) "double quoted sTrInG" | $(SED_EXT) -e "s/sTrInG/string/g"
+	$(ECHO_EXT) 'single quoted sTrInG' | $(SED_EXT) -e 's/sTrInG/string/g'
+	$(ECHO) "This string should not be printed with double quotes."
+	$(ECHO) 'This string should not be printed with single quotes.'
+	( echo "  #define PWD \"`pwd`\""; )
+
+test_shell_double_quoting:
+	$(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \
+		"s/foo/$@/" -e \
+		"s/foo/works/" \
+		-e "s/foo/\!/"
+
+test_shell_double_quoting2:
+	$(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \
+		"s/foo/$@/" -e \
+		"s/foo/works/" \
+		-e\
+		"s/foo/\!/"
+
+# when using batch mode shell, the newline got escaped twice and spoiling everything.
+test_shell_newline:
+	$(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \
+		's/foo/$@/' -e \
+		's/foo/works/' \
+		-e 's/foo/\!/'
+
+
+test_stack:
+	$(MAKE) -f $(kmk_PATH)/testcase-stack.kmk
+
+test_math:
+	$(MAKE) -f $(kmk_PATH)/testcase-math.kmk
+
+test_if1of:
+	$(MAKE) -f $(kmk_PATH)/testcase-if1of.kmk
+
+test_local:
+	$(MAKE) -f $(kmk_PATH)/testcase-local.kmk
+
+test_includedep:
+	$(MAKE) -f $(kmk_PATH)/testcase-includedep.kmk
+
+test_2ndtargetexp:
+	$(MAKE) -f $(kmk_PATH)/testcase-2ndtargetexp.kmk
+
+test_30_continued_on_failure_worker:
+	this_executable_does_not_exist.exe
+	echo "We shouldn't see this..."
+
+test_30_continued_on_failure:
+	$(MAKE) -f $(MAKEFILE) test_30_continued_on_failure_worker; \
+	RC=$$?; \
+	if test $${RC} -ne 2; then \
+		echo "$@: FAILED - exit code $${RC} instead of 2."; \
+		exit 1; \
+	else \
+		echo "$@: SUCCESS"; \
+	fi
+
+
+test_all:	test_math test_stack test_shell test_if1of test_local test_includedep test_2ndtargetexp test_30_continued_on_failure
+
Index: /tags/kBuild-0.1.4/src/kmk/Makefile.os2
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/Makefile.os2	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/Makefile.os2	(revision 1780)
@@ -0,0 +1,47 @@
+# $Id$
+
+OBJDIR = objdir/OS2.libc
+#OBJDIR = .
+SRC =	ar.c arscan.c commands.c default.c dir.c expand.c file.c \
+		function.c implicit.c job.c main.c \
+		misc.c read.c remake.c rule.c signame.c \
+		variable.c version.c vpath.c hash.c \
+        getopt.c getopt1.c remote-stub.c
+OBJS = $(addprefix $(OBJDIR)/, $(SRC:.c=.obj))
+CFLAGS = -Zomf -g -Wall -I$(OBJDIR) -I.  -DCONFIG_NO_DEFAULT_SUFFIXES \
+    -DCONFIG_NO_DEFAULT_PATTERN_RULES -DCONFIG_NO_DEFAULT_TERMINAL_RULES \
+    -DCONFIG_NO_DEFAULT_SUFFIX_RULES -DCONFIG_NO_DEFAULT_VARIABLES
+ifndef DEBUG
+CFLAGS += -O3
+endif
+#-DMAKE_DLLSHELL
+
+all: $(OBJDIR) $(OBJDIR)/make-new.exe
+
+clean:
+	rm -f $(OBJS) $(OBJDIR)/make-new.exe $(OBJDIR)/config.h
+
+$(OBJDIR)/make-new.exe: $(OBJDIR)/config.h $(OBJS)
+	gcc -g $(CFLAGS) -Zhigh-mem -Zstack 1024 -o $@ $(OBJS)
+
+$(OBJDIR)/%.obj : %.c
+	gcc -c $(CFLAGS) -o $@ -DHAVE_CONFIG_H  $<
+
+$(OBJDIR)/config.h: config.h.os2
+	cp $< $@
+
+$(OBJDIR):
+	mkdir.exe -p $@
+
+test:
+	echo "1"
+	echo "2"
+	echo "3"
+	echo "4"
+
+parallel: parallel_1 parallel_2 parallel_3 parallel_4 parallel_5
+
+parallel_1 parallel_2 parallel_3 parallel_4 parallel_5:
+	echo $@_start ; sleep 1; echo $@_done
+
+
Index: /tags/kBuild-0.1.4/src/kmk/NEWS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/NEWS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/NEWS	(revision 1780)
@@ -0,0 +1,1067 @@
+GNU make NEWS                                               -*-indented-text-*-
+  History of user-visible changes.
+  1 April 2006
+
+See the end of this file for copyrights and conditions.
+
+All changes mentioned here are more fully described in the GNU make
+manual, which is contained in this distribution as the file doc/make.texi.
+See the README file and the GNU make manual for instructions for
+reporting bugs.
+
+
+Version 3.81.90
+
+* Compiling GNU make now requires a conforming ISO C 1989 compiler and
+  standard runtime library.
+
+
+
+Version 3.81
+
+* GNU make is ported to OS/2.
+
+* GNU make is ported to MinGW.  The MinGW build is only supported by
+  the build_w32.bat batch file; see the file README.W32 for more
+  details.
+
+* WARNING: Future backward-incompatibility!
+  Up to and including this release, the '$?' variable does not contain
+  any prerequisite that does not exist, even though that prerequisite
+  might have caused the target to rebuild.  Starting with the _next_
+  release of GNU make, '$?' will contain all prerequisites that caused
+  the target to be considered out of date.  See this Savannah bug:
+  http://savannah.gnu.org/bugs/index.php?func=detailitem&item_id=16051
+
+* WARNING: Backward-incompatibility!
+  GNU make now implements a generic "second expansion" feature on the
+  prerequisites of both explicit and implicit (pattern) rules.  In order
+  to enable this feature, the special target '.SECONDEXPANSION' must be
+  defined before the first target which takes advantage of it.  If this
+  feature is enabled then after all rules have been parsed the
+  prerequisites are expanded again, this time with all the automatic
+  variables in scope.  This means that in addition to using standard
+  SysV $$@ in prerequisites lists, you can also use complex functions
+  such as $$(notdir $$@) etc.  This behavior applies to implicit rules,
+  as well, where the second expansion occurs when the rule is matched.
+  However, this means that when '.SECONDEXPANSION' is enabled you must
+  double-quote any "$" in your filenames; instead of "foo: boo$$bar" you
+  now must write "foo: foo$$$$bar".  Note that the SysV $$@ etc. feature,
+  which used to be available by default, is now ONLY available when the
+  .SECONDEXPANSION target is defined.  If your makefiles take advantage
+  of this SysV feature you will need to update them.
+
+* WARNING: Backward-incompatibility!
+  In order to comply with POSIX, the way in which GNU make processes
+  backslash-newline sequences in command strings has changed.  If your
+  makefiles use backslash-newline sequences inside of single-quoted
+  strings in command scripts you will be impacted by this change.  See
+  the GNU make manual subsection "Splitting Command Lines" (node
+  "Splitting Lines"), in section "Command Syntax", chapter "Writing the
+  Commands in Rules", for details.
+
+* WARNING: Backward-incompatibility!
+  Some previous versions of GNU make had a bug where "#" in a function
+  invocation such as $(shell ...) was treated as a make comment.  A
+  workaround was to escape these with backslashes.  This bug has been
+  fixed: if your makefile uses "\#" in a function invocation the
+  backslash is now preserved, so you'll need to remove it.
+
+* New command-line option: -L (--check-symlink-times).  On systems that
+  support symbolic links, if this option is given then GNU make will
+  use the most recent modification time of any symbolic links that are
+  used to resolve target files.  The default behavior remains as it
+  always has: use the modification time of the actual target file only.
+
+* The "else" conditional line can now be followed by any other valid
+  conditional on the same line: this does not increase the depth of the
+  conditional nesting, so only one "endif" is required to close the
+  conditional.
+
+* All pattern-specific variables that match a given target are now used
+  (previously only the first match was used).
+
+* Target-specific variables can be marked as exportable using the
+  "export" keyword.
+
+* In a recursive $(call ...) context, any extra arguments from the outer
+  call are now masked in the context of the inner call.
+
+* Implemented a solution for the "thundering herd" problem with "-j -l".
+  This version of GNU make uses an algorithm suggested by Thomas Riedl
+  <thomas.riedl@siemens.com> to track the number of jobs started in the
+  last second and artificially adjust GNU make's view of the system's
+  load average accordingly.
+
+* New special variables available in this release:
+   - .INCLUDE_DIRS: Expands to a list of directories that make searches
+     for included makefiles.
+   - .FEATURES: Contains a list of special features available in this
+     version of GNU make.
+   - .DEFAULT_GOAL: Set the name of the default goal make will
+     use if no goals are provided on the command line.
+   - MAKE_RESTARTS: If set, then this is the number of times this
+     instance of make has been restarted (see "How Makefiles Are Remade"
+     in the manual).
+   - New automatic variable: $| (added in 3.80, actually): contains all
+     the order-only prerequisites defined for the target.
+
+* New functions available in this release:
+   - $(lastword ...) returns the last word in the list.  This gives
+     identical results as $(word $(words ...) ...), but is much faster.
+   - $(abspath ...) returns the absolute path (all "." and ".."
+     directories resolved, and any duplicate "/" characters removed) for
+     each path provided.
+   - $(realpath ...) returns the canonical pathname for each path
+     provided.  The canonical pathname is the absolute pathname, with
+     all symbolic links resolved as well.
+   - $(info ...) prints its arguments to stdout.  No makefile name or
+     line number info, etc. is printed.
+   - $(flavor ...) returns the flavor of a variable.
+   - $(or ...) provides a short-circuiting OR conditional: each argument
+     is expanded.  The first true (non-empty) argument is returned; no
+     further arguments are expanded.  Expands to empty if there are no
+     true arguments.
+   - $(and ...) provides a short-circuiting AND conditional: each
+     argument is expanded.  The first false (empty) argument is
+     returned; no further arguments are expanded.  Expands to the last
+     argument if all arguments are true.
+
+* Changes made for POSIX compatibility:
+   - Only touch targets (under -t) if they have at least one command.
+   - Setting the SHELL make variable does NOT change the value of the
+     SHELL environment variable given to programs invoked by make.  As
+     an enhancement to POSIX, if you export the make variable SHELL then
+     it will be set in the environment, just as before.
+
+* On MS Windows systems, explicitly setting SHELL to a pathname ending
+  in "cmd" or "cmd.exe" (case-insensitive) will force GNU make to use
+  the DOS command interpreter in batch mode even if a UNIX-like shell
+  could be found on the system.
+
+* On VMS there is now support for case-sensitive filesystems such as ODS5.
+  See the readme.vms file for information.
+
+* Parallel builds (-jN) no longer require a working Bourne shell on
+  Windows platforms.  They work even with the stock Windows shells, such
+  as cmd.exe and command.com.
+
+* Updated to autoconf 2.59, automake 1.9.5, and gettext 0.14.1.  Users
+  should not be impacted.
+
+* New translations for Swedish, Chinese (simplified), Ukrainian,
+  Belarusian, Finnish, Kinyarwandan, and Irish.  Many updated
+  translations.
+
+A complete list of bugs fixed in this version is available here:
+
+  http://savannah.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=103
+
+
+
+Version 3.80
+
+* A new feature exists: order-only prerequisites.  These prerequisites
+  affect the order in which targets are built, but they do not impact
+  the rebuild/no-rebuild decision of their dependents.  That is to say,
+  they allow you to require target B be built before target A, without
+  requiring that target A will always be rebuilt if target B is updated.
+  Patch for this feature provided by Greg McGary <greg@mcgary.org>.
+
+* For compatibility with SysV make, GNU make now supports the peculiar
+  syntax $$@, $$(@D), and $$(@F) in the prerequisites list of a rule.
+  This syntax is only valid within explicit and static pattern rules: it
+  cannot be used in implicit (suffix or pattern) rules.  Edouard G. Parmelan
+  <egp@free.fr> provided a patch implementing this feature; however, I
+  decided to implement it in a different way.
+
+* The argument to the "ifdef" conditional is now expanded before it's
+  tested, so it can be a constructed variable name.
+
+  Similarly, the arguments to "export" (when not used in a variable
+  definition context) and "unexport" are also now expanded.
+
+* A new function is defined: $(value ...).  The argument to this
+  function is the _name_ of a variable.  The result of the function is
+  the value of the variable, without having been expanded.
+
+* A new function is defined: $(eval ...).  The arguments to this
+  function should expand to makefile commands, which will then be
+  evaluated as if they had appeared in the makefile.  In combination
+  with define/endef multiline variable definitions this is an extremely
+  powerful capability.  The $(value ...) function is also sometimes
+  useful here.
+
+* A new built-in variable is defined, $(MAKEFILE_LIST).  It contains a
+  list of each makefile GNU make has read, or started to read, in the
+  order in which they were encountered.  So, the last filename in the
+  list when a makefile is just being read (before any includes) is the
+  name of the current makefile.
+
+* A new built-in variable is defined: $(.VARIABLES).  When it is
+  expanded it returns a complete list of variable names defined by all
+  makefiles at that moment.
+
+* A new command-line option is defined, -B or --always-make.  If
+  specified GNU make will consider all targets out-of-date even if they
+  would otherwise not be.
+
+* The arguments to $(call ...) functions were being stored in $1, $2,
+  etc. as recursive variables, even though they are fully expanded
+  before assignment.  This means that escaped dollar signs ($$ etc.)
+  were not behaving properly.  Now the arguments are stored as simple
+  variables.  This may mean that if you added extra escaping to your
+  $(call ...) function arguments you will need to undo it now.
+
+* The variable invoked by $(call ...) can now be recursive: unlike other
+  variables it can reference itself and this will not produce an error
+  when it is used as the first argument to $(call ...) (but only then).
+
+* New pseudo-target .LOW_RESOLUTION_TIME, superseding the configure
+  option --disable-nsec-timestamps.  You might need this if your build
+  process depends on tools like "cp -p" preserving time stamps, since
+  "cp -p" (right now) doesn't preserve the subsecond portion of a time
+  stamp.
+
+* Updated translations for French, Galician, German, Japanese, Korean,
+  and Russian.  New translations for Croatian, Danish, Hebrew, and
+  Turkish.
+
+* Updated internationalization support to Gettext 0.11.5.
+  GNU make now uses Gettext's "external" feature, and does not include
+  any internationalization code itself.  Configure will search your
+  system for an existing implementation of GNU Gettext (only GNU Gettext
+  is acceptable) and use it if it exists.  If not, NLS will be disabled.
+  See ABOUT-NLS for more information.
+
+* Updated to autoconf 2.54 and automake 1.7.  Users should not be impacted.
+
+A complete list of bugs fixed in this version is available here:
+
+  http://savannah.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=102
+
+
+
+Version 3.79.1
+
+* .SECONDARY with no prerequisites now prevents any target from being
+  removed because make thinks it's an intermediate file, not just those
+  listed in the makefile.
+
+* New configure option --disable-nsec-timestamps, but this was
+  superseded in later versions by the .LOW_RESOLUTION_TIME pseudo-target.
+
+
+Version 3.79
+
+* GNU make optionally supports internationalization and locales via the
+  GNU gettext (or local gettext if suitable) package.  See the ABOUT-NLS
+  file for more information on configuring GNU make for NLS.
+
+* Previously, GNU make quoted variables such as MAKEFLAGS and
+  MAKEOVERRIDES for proper parsing by the shell.  This allowed them to
+  be used within make build scripts.  However, using them there is not
+  proper behavior: they are meant to be passed to subshells via the
+  environment.  Unfortunately the values were not quoted properly to be
+  passed through the environment.  This meant that make didn't properly
+  pass some types of command line values to submakes.
+
+  With this version we change that behavior: now these variables are
+  quoted properly for passing through the environment, which is the
+  correct way to do it.  If you previously used these variables
+  explicitly within a make rule you may need to re-examine your use for
+  correctness given this change.
+
+* A new pseudo-target .NOTPARALLEL is available.  If defined, the
+  current makefile is run serially regardless of the value of -j.
+  However, submakes are still eligible for parallel execution.
+
+* The --debug option has changed: it now allows optional flags
+  controlling the amount and type of debugging output.  By default only
+  a minimal amount information is generated, displaying the names of
+  "normal" targets (not makefiles) that were deemed out of date and in
+  need of being rebuilt.
+
+  Note that the -d option behaves as before: it takes no arguments and
+  all debugging information is generated.
+
+* The `-p' (print database) output now includes filename and linenumber
+  information for variable definitions, to aid debugging.
+
+* The wordlist function no longer reverses its arguments if the "start"
+  value is greater than the "end" value.  If that's true, nothing is
+  returned.
+
+* Hartmut Becker provided many updates for the VMS port of GNU make.
+  See the readme.vms file for more details.
+
+
+Version 3.78
+
+* Two new functions, $(error ...) and $(warning ...) are available.  The
+  former will cause make to fail and exit immediately upon expansion of
+  the function, with the text provided as the error message.  The latter
+  causes the text provided to be printed as a warning message, but make
+  proceeds normally.
+
+* A new function $(call ...) is available.  This allows users to create
+  their own parameterized macros and invoke them later.  Original
+  implementation of this function was provided by Han-Wen Nienhuys
+  <hanwen@cs.uu.nl>.
+
+* A new function $(if ...) is available.  It provides if-then-else
+  capabilities in a builtin function.  Original implementation of this
+  function was provided by Han-Wen Nienhuys <hanwen@cs.uu.nl>.
+
+* Make defines a new variable, .LIBPATTERNS.  This variable controls how
+  library dependency expansion (dependencies like ``-lfoo'') is performed.
+
+* Make accepts CRLF sequences as well as traditional LF, for
+  compatibility with makefiles created on other operating systems.
+
+* Make accepts a new option: -R, or --no-builtin-variables.  This option
+  disables the definition of the rule-specific builtin variables (CC,
+  LD, AR, etc.).  Specifying this option forces -r (--no-builtin-rules)
+  as well.
+
+* A "job server" feature, suggested by Howard Chu <hyc@highlandsun.com>.
+
+  On systems that support POSIX pipe(2) semantics, GNU make can now pass
+  -jN options to submakes rather than forcing them all to use -j1.  The
+  top make and all its sub-make processes use a pipe to communicate with
+  each other to ensure that no more than N jobs are started across all
+  makes.  To get the old behavior of -j back, you can configure make
+  with the --disable-job-server option.
+
+* The confusing term "dependency" has been replaced by the more accurate
+  and standard term "prerequisite", both in the manual and in all GNU make
+  output.
+
+* GNU make supports the "big archive" library format introduced in AIX 4.3.
+
+* GNU make supports large files on AIX, HP-UX, and IRIX.  These changes
+  were provided by Paul Eggert <eggert@twinsun.com>.  (Large file
+  support for Solaris and Linux was introduced in 3.77, but the
+  configuration had issues: these have also been resolved).
+
+* The Windows 95/98/NT (W32) version of GNU make now has native support
+  for the Cygnus Cygwin release B20.1 shell (bash).
+
+* The GNU make regression test suite, long available separately "under
+  the table", has been integrated into the release.  You can invoke it
+  by running "make check" in the distribution.  Note that it requires
+  Perl (either Perl 4 or Perl 5) to run.
+
+
+Version 3.77
+
+* Implement BSD make's "?=" variable assignment operator.  The variable
+  is assigned the specified value only if that variable is not already
+  defined.
+
+* Make defines a new variable, "CURDIR", to contain the current working
+  directory (after the -C option, if any, has been processed).
+  Modifying this variable has no effect on the operation of make.
+
+* Make defines a new default RCS rule, for new-style master file
+  storage: ``% :: RCS/%'' (note no ``,v'' suffix).
+
+  Make defines new default rules for DOS-style C++ file naming
+  conventions, with ``.cpp'' suffixes.  All the same rules as for
+  ``.cc'' and ``.C'' suffixes are provided, along with LINK.cpp and
+  COMPILE.cpp macros (which default to the same value as LINK.cc and
+  COMPILE.cc).  Note CPPFLAGS is still C preprocessor flags!  You should
+  use CXXFLAGS to change C++ compiler flags.
+
+* A new feature, "target-specific variable values", has been added.
+  This is a large change so please see the appropriate sections of the
+  manual for full details.  Briefly, syntax like this:
+
+    TARGET: VARIABLE = VALUE
+
+  defines VARIABLE as VALUE within the context of TARGET.  This is
+  similar to SunOS make's "TARGET := VARIABLE = VALUE" feature.  Note
+  that the assignment may be of any type, not just recursive, and that
+  the override keyword is available.
+
+  COMPATIBILITY: This new syntax means that if you have any rules where
+  the first or second dependency has an equal sign (=) in its name,
+  you'll have to escape them with a backslash: "foo : bar\=baz".
+  Further, if you have any dependencies which already contain "\=",
+  you'll have to escape both of them: "foo : bar\\\=baz".
+
+* A new appendix listing the most common error and warning messages
+  generated by GNU make, with some explanation, has been added to the
+  GNU make User's Manual.
+
+* Updates to the GNU make Customs library support (see README.customs).
+
+* Updates to the Windows 95/NT port from Rob Tulloh (see README.W32),
+  and to the DOS port from Eli Zaretski (see README.DOS).
+
+
+Version 3.76.1
+
+* Small (but serious) bug fix.  Quick rollout to get into the GNU source CD.
+
+
+Version 3.76
+
+* GNU make now uses automake to control Makefile.in generation.  This
+  should make it more consistent with the GNU standards.
+
+* VPATH functionality has been changed to incorporate the VPATH+ patch,
+  previously maintained by Paul Smith <psmith@baynetworks.com>.  See the
+  manual.
+
+* Make defines a new variable, `MAKECMDGOALS', to contain the goals that
+  were specified on the command line, if any.  Modifying this variable
+  has no effect on the operation of make.
+
+* A new function, `$(wordlist S,E,TEXT)', is available: it returns a
+  list of words from number S to number E (inclusive) of TEXT.
+
+* Instead of an error, detection of future modification times gives a
+  warning and continues.  The warning is repeated just before GNU make
+  exits, so it is less likely to be lost.
+
+* Fix the $(basename) and $(suffix) functions so they only operate on
+  the last filename, not the entire string:
+
+      Command              Old Result             New Result
+      -------              ----------             ----------
+    $(basename a.b)        a                      a
+    $(basename a.b/c)      a                      a.b/c
+    $(suffix a.b)          b                      b
+    $(suffix a.b/c)        b/c                    <empty>
+
+* The $(strip) function now removes newlines as well as TABs and spaces.
+
+* The $(shell) function now changes CRLF (\r\n) pairs to a space as well
+  as newlines (\n).
+
+* Updates to the Windows 95/NT port from Rob Tulloh (see README.W32).
+
+* Eli Zaretskii has updated the port to 32-bit protected mode on MSDOS
+  and MS-Windows, building with the DJGPP v2 port of GNU C/C++ compiler
+  and utilities.  See README.DOS for details, and direct all questions
+  concerning this port to Eli Zaretskii <eliz@is.elta.co.il> or DJ
+  Delorie <dj@delorie.com>.
+
+* John W. Eaton has updated the VMS port to support libraries and VPATH.
+
+
+Version 3.75
+
+* The directory messages printed by `-w' and implicitly in sub-makes,
+  are now omitted if Make runs no commands and has no other messages to print.
+
+* Make now detects files that for whatever reason have modification times
+  in the future and gives an error.  Files with such impossible timestamps
+  can result from unsynchronized clocks, or archived distributions
+  containing bogus timestamps; they confuse Make's dependency engine
+  thoroughly.
+
+* The new directive `sinclude' is now recognized as another name for
+  `-include', for compatibility with some other Makes.
+
+* Aaron Digulla has contributed a port to AmigaDOS.  See README.Amiga for
+  details, and direct all Amiga-related questions to <digulla@fh-konstanz.de>.
+
+* Rob Tulloh of Tivoli Systems has contributed a port to Windows NT or 95.
+  See README.W32 for details, and direct all Windows-related questions to
+  <rob_tulloh@tivoli.com>.
+
+
+Version 3.73
+
+* Converted to use Autoconf version 2, so `configure' has some new options.
+  See INSTALL for details.
+
+* You can now send a SIGUSR1 signal to Make to toggle printing of debugging
+  output enabled by -d, at any time during the run.
+
+
+Version 3.72
+
+* DJ Delorie has ported Make to MS-DOS using the GO32 extender.
+  He is maintaining the DOS port, not the GNU Make maintainer;
+  please direct bugs and questions for DOS to <djgpp@sun.soe.clarkson.edu>.
+  MS-DOS binaries are available for FTP from ftp.simtel.net in
+  /pub/simtelnet/gnu/djgpp/.
+
+* The `MAKEFLAGS' variable (in the environment or in a makefile) can now
+  contain variable definitions itself; these are treated just like
+  command-line variable definitions.  Make will automatically insert any
+  variable definitions from the environment value of `MAKEFLAGS' or from
+  the command line, into the `MAKEFLAGS' value exported to children.  The
+  `MAKEOVERRIDES' variable previously included in the value of `$(MAKE)'
+  for sub-makes is now included in `MAKEFLAGS' instead.  As before, you can
+  reset `MAKEOVERRIDES' in your makefile to avoid putting all the variables
+  in the environment when its size is limited.
+
+* If `.DELETE_ON_ERROR' appears as a target, Make will delete the target of
+  a rule if it has changed when its commands exit with a nonzero status,
+  just as when the commands get a signal.
+
+* The automatic variable `$+' is new.  It lists all the dependencies like
+  `$^', but preserves duplicates listed in the makefile.  This is useful
+  for linking rules, where library files sometimes need to be listed twice
+  in the link order.
+
+* You can now specify the `.IGNORE' and `.SILENT' special targets with
+  dependencies to limit their effects to those files.  If a file appears as
+  a dependency of `.IGNORE', then errors will be ignored while running the
+  commands to update that file.  Likewise if a file appears as a dependency
+  of `.SILENT', then the commands to update that file will not be printed
+  before they are run.  (This change was made to conform to POSIX.2.)
+
+
+Version 3.71
+
+* The automatic variables `$(@D)', `$(%D)', `$(*D)', `$(<D)', `$(?D)', and
+  `$(^D)' now omit the trailing slash from the directory name.  (This change
+  was made to comply with POSIX.2.)
+
+* The source distribution now includes the Info files for the Make manual.
+  There is no longer a separate distribution containing Info and DVI files.
+
+* You can now set the variables `binprefix' and/or `manprefix' in
+  Makefile.in (or on the command line when installing) to install GNU make
+  under a name other than `make' (i.e., ``make binprefix=g install''
+  installs GNU make as `gmake').
+
+* The built-in Texinfo rules use the new variables `TEXI2DVI_FLAGS' for
+  flags to the `texi2dvi' script, and `MAKEINFO_FLAGS' for flags to the
+  Makeinfo program.
+
+* The exit status of Make when it runs into errors is now 2 instead of 1.
+  The exit status is 1 only when using -q and some target is not up to date.
+  (This change was made to comply with POSIX.2.)
+
+
+Version 3.70
+
+* It is no longer a fatal error to have a NUL character in a makefile.
+  You should never put a NUL in a makefile because it can have strange
+  results, but otherwise empty lines full of NULs (such as produced by
+  the `xmkmf' program) will always work fine.
+
+* The error messages for nonexistent included makefiles now refer to the
+  makefile name and line number where the `include' appeared, so Emacs's
+  C-x ` command takes you there (in case it's a typo you need to fix).
+
+
+Version 3.69
+
+* Implicit rule search for archive member references is now done in the
+  opposite order from previous versions: the whole target name `LIB(MEM)'
+  first, and just the member name and parentheses `(MEM)' second.
+
+* Make now gives an error for an unterminated variable or function reference.
+  For example, `$(foo' with no matching `)' or `${bar' with no matching `}'.
+
+* The new default variable `MAKE_VERSION' gives the version number of
+  Make, and a string describing the remote job support compiled in (if any).
+  Thus the value (in this release) is something like `3.69' or `3.69-Customs'.
+
+* Commands in an invocation of the `shell' function are no longer run with
+  a modified environment like target commands are.  As in versions before
+  3.68, they now run with the environment that `make' started with.  We
+  have reversed the change made in version 3.68 because it turned out to
+  cause a paradoxical situation in cases like:
+
+	export variable = $(shell echo value)
+
+  When Make attempted to put this variable in the environment for a target
+  command, it would try expand the value by running the shell command
+  `echo value'.  In version 3.68, because it constructed an environment
+  for that shell command in the same way, Make would begin to go into an
+  infinite loop and then get a fatal error when it detected the loop.
+
+* The commands given for `.DEFAULT' are now used for phony targets with no
+  commands.
+
+
+Version 3.68
+
+* You can list several archive member names inside parenthesis:
+  `lib(mem1 mem2 mem3)' is equivalent to `lib(mem1) lib(mem2) lib(mem3)'.
+
+* You can use wildcards inside archive member references.  For example,
+  `lib(*.o)' expands to all existing members of `lib' whose names end in
+  `.o' (e.g. `lib(a.o) lib(b.o)'); `*.a(*.o)' expands to all such members
+  of all existing files whose names end in `.a' (e.g. `foo.a(a.o)
+  foo.a(b.o) bar.a(c.o) bar.a(d.o)'.
+
+* A suffix rule `.X.a' now produces two pattern rules:
+	(%.o): %.X	# Previous versions produced only this.
+	%.a: %.X	# Now produces this as well, just like other suffixes.
+
+* The new flag `--warn-undefined-variables' says to issue a warning message
+  whenever Make expands a reference to an undefined variable.
+
+* The new `-include' directive is just like `include' except that there is
+  no error (not even a warning) for a nonexistent makefile.
+
+* Commands in an invocation of the `shell' function are now run with a
+  modified environment like target commands are, so you can use `export' et
+  al to set up variables for them.  They used to run with the environment
+  that `make' started with.
+
+
+Version 3.66
+
+* `make --version' (or `make -v') now exits immediately after printing
+  the version number.
+
+
+Version 3.65
+
+* Make now supports long-named members in `ar' archive files.
+
+
+Version 3.64
+
+* Make now supports the `+=' syntax for a variable definition which appends
+  to the variable's previous value.  See the section `Appending More Text
+  to Variables' in the manual for full details.
+
+* The new option `--no-print-directory' inhibits the `-w' or
+  `--print-directory' feature.  Make turns on `--print-directory'
+  automatically if you use `-C' or `--directory', and in sub-makes; some
+  users have found this behavior undesirable.
+
+* The built-in implicit rules now support the alternative extension
+  `.txinfo' for Texinfo files, just like `.texinfo' and `.texi'.
+
+
+Version 3.63
+
+* Make now uses a standard GNU `configure' script.  See the new file
+  INSTALL for the new (and much simpler) installation procedure.
+
+* There is now a shell script to build Make the first time, if you have no
+  other `make' program.  `build.sh' is created by `configure'; see README.
+
+* GNU Make now completely conforms to the POSIX.2 specification for `make'.
+
+* Elements of the `$^' and `$?' automatic variables that are archive
+  member references now list only the member name, as in Unix and POSIX.2.
+
+* You should no longer ever need to specify the `-w' switch, which prints
+  the current directory before and after Make runs.  The `-C' switch to
+  change directory, and recursive use of Make, now set `-w' automatically.
+
+* Multiple double-colon rules for the same target will no longer have their
+  commands run simultaneously under -j, as this could result in the two
+  commands trying to change the file at the same time and interfering with
+  one another.
+
+* The `SHELL' variable is now never taken from the environment.
+  Each makefile that wants a shell other than the default (/bin/sh) must
+  set SHELL itself.  SHELL is always exported to child processes.
+  This change was made for compatibility with POSIX.2.
+
+* Make now accepts long options.  There is now an informative usage message
+  that tells you what all the options are and what they do.  Try `make --help'.
+
+* There are two new directives: `export' and `unexport'.  All variables are
+  no longer automatically put into the environments of the commands that
+  Make runs.  Instead, only variables specified on the command line or in
+  the environment are exported by default.  To export others, use:
+	export VARIABLE
+  or you can define variables with:
+	export VARIABLE = VALUE
+  or:
+	export VARIABLE := VALUE
+  You can use just:
+	export
+  or:
+	.EXPORT_ALL_VARIABLES:
+  to get the old behavior.  See the node `Variables/Recursion' in the manual
+  for a full description.
+
+* The commands from the `.DEFAULT' special target are only applied to
+  targets which have no rules at all, not all targets with no commands.
+  This change was made for compatibility with Unix make.
+
+* All fatal error messages now contain `***', so they are easy to find in
+  compilation logs.
+
+* Dependency file names like `-lNAME' are now replaced with the actual file
+  name found, as with files found by normal directory search (VPATH).
+  The library file `libNAME.a' may now be found in the current directory,
+  which is checked before VPATH; the standard set of directories (/lib,
+  /usr/lib, /usr/local/lib) is now checked last.
+  See the node `Libraries/Search' in the manual for full details.
+
+* A single `include' directive can now specify more than one makefile to
+  include, like this:
+	include file1 file2
+  You can also use shell file name patterns in an `include' directive:
+	include *.mk
+
+* The default directories to search for included makefiles, and for
+  libraries specified with `-lNAME', are now set by configuration.
+
+* You can now use blanks as well as colons to separate the directories in a
+  search path for the `vpath' directive or the `VPATH' variable.
+
+* You can now use variables and functions in the left hand side of a
+  variable assignment, as in "$(foo)bar = value".
+
+* The `MAKE' variable is always defined as `$(MAKE_COMMAND) $(MAKEOVERRIDES)'.
+  The `MAKE_COMMAND' variable is now defined to the name with which make
+  was invoked.
+
+* The built-in rules for C++ compilation now use the variables `$(CXX)' and
+  `$(CXXFLAGS)' instead of `$(C++)' and `$(C++FLAGS)'.  The old names had
+  problems with shells that cannot have `+' in environment variable names.
+
+* The value of a recursively expanded variable is now expanded when putting
+  it into the environment for child processes.  This change was made for
+  compatibility with Unix make.
+
+* A rule with no targets before the `:' is now accepted and ignored.
+  This change was made for compatibility with SunOS 4 make.
+  We do not recommend that you write your makefiles to take advantage of this.
+
+* The `-I' switch can now be used in MAKEFLAGS, and are put there
+  automatically just like other switches.
+
+
+Version 3.61
+
+* Built-in rules for C++ source files with the `.C' suffix.
+  We still recommend that you use `.cc' instead.
+
+* If commands are given too many times for a single target,
+  the last set given is used, and a warning message is printed.
+
+* Error messages about makefiles are in standard GNU error format,
+  so C-x ` in Emacs works on them.
+
+* Dependencies of pattern rules which contain no % need not actually exist
+  if they can be created (just like dependencies which do have a %).
+
+
+Version 3.60
+
+* A message is always printed when Make decides there is nothing to be done.
+  It used to be that no message was printed for top-level phony targets
+  (because "`phony' is up to date" isn't quite right).  Now a different
+  message "Nothing to be done for `phony'" is printed in that case.
+
+* Archives on AIX now supposedly work.
+
+* When the commands specified for .DEFAULT are used to update a target,
+  the $< automatic variable is given the same value as $@ for that target.
+  This is how Unix make behaves, and this behavior is mandated by POSIX.2.
+
+
+Version 3.59
+
+* The -n, -q, and -t options are not put in the `MAKEFLAGS' and `MFLAG'
+  variables while remaking makefiles, so recursive makes done while remaking
+  makefiles will behave properly.
+
+* If the special target `.NOEXPORT' is specified in a makefile,
+  only variables that came from the environment and variables
+  defined on the command line are exported.
+
+
+Version 3.58
+
+* Suffix rules may have dependencies (which are ignored).
+
+
+Version 3.57
+
+* Dependencies of the form `-lLIB' are searched for as /usr/local/lib/libLIB.a
+  as well as libLIB.a in /usr/lib, /lib, the current directory, and VPATH.
+
+
+Version 3.55
+
+* There is now a Unix man page for GNU Make.  It is certainly not a replacement
+for the Texinfo manual, but it documents the basic functionality and the
+switches.  For full documentation, you should still read the Texinfo manual.
+Thanks to Dennis Morse of Stanford University for contributing the initial
+version of this.
+
+* Variables which are defined by default (e.g., `CC') will no longer be put
+into the environment for child processes.  (If these variables are reset by the
+environment, makefiles, or the command line, they will still go into the
+environment.)
+
+* Makefiles which have commands but no dependencies (and thus are always
+  considered out of date and in need of remaking), will not be remade (if they
+  were being remade only because they were makefiles).  This means that GNU
+  Make will no longer go into an infinite loop when fed the makefiles that
+  `imake' (necessary to build X Windows) produces.
+
+* There is no longer a warning for using the `vpath' directive with an explicit
+pathname (instead of a `%' pattern).
+
+
+Version 3.51
+
+* When removing intermediate files, only one `rm' command line is printed,
+listing all file names.
+
+* There are now automatic variables `$(^D)', `$(^F)', `$(?D)', and `$(?F)'.
+These are the directory-only and file-only versions of `$^' and `$?'.
+
+* Library dependencies given as `-lNAME' will use "libNAME.a" in the current
+directory if it exists.
+
+* The automatic variable `$($/)' is no longer defined.
+
+* Leading `+' characters on a command line make that line be executed even
+under -n, -t, or -q (as if the line contained `$(MAKE)').
+
+* For command lines containing `$(MAKE)', `${MAKE}', or leading `+' characters,
+only those lines are executed, not their entire rules.
+(This is how Unix make behaves for lines containing `$(MAKE)' or `${MAKE}'.)
+
+
+Version 3.50
+
+* Filenames in rules will now have ~ and ~USER expanded.
+
+* The `-p' output has been changed so it can be used as a makefile.
+(All information that isn't specified by makefiles is prefaced with comment
+characters.)
+
+
+Version 3.49
+
+* The % character can be quoted with backslash in implicit pattern rules,
+static pattern rules, `vpath' directives, and `patsubst', `filter', and
+`filter-out' functions.  A warning is issued if a `vpath' directive's
+pattern contains no %.
+
+* The `wildcard' variable expansion function now expands ~ and ~USER.
+
+* Messages indicating failed commands now contain the target name:
+	make: *** [target] Error 1
+
+* The `-p' output format has been changed somewhat to look more like
+makefile rules and to give all information that Make has about files.
+
+
+Version 3.48
+
+
+Version 3.47
+
+* The `-l' switch with no argument removes any previous load-average limit.
+
+* When the `-w' switch is in effect, and Make has updated makefiles,
+it will write a `Leaving directory' messagfe before re-executing itself.
+This makes the `directory change tracking' changes to Emacs's compilation
+commands work properly.
+
+
+Version 3.46
+
+* The automatic variable `$*' is now defined for explicit rules,
+as it is in Unix make.
+
+
+Version 3.45
+
+* The `-j' switch is now put in the MAKEFLAGS and MFLAGS variables when
+specified without an argument (indicating infinite jobs).
+The `-l' switch is not always put in the MAKEFLAGS and MFLAGS variables.
+
+* Make no longer checks hashed directories after running commands.
+The behavior implemented in 3.41 caused too much slowdown.
+
+
+Version 3.44
+
+* A dependency is NOT considered newer than its dependent if
+they have the same modification time.  The behavior implemented
+in 3.43 conflicts with RCS.
+
+
+Version 3.43
+
+* Dependency loops are no longer fatal errors.
+
+* A dependency is considered newer than its dependent if
+they have the same modification time.
+
+
+Version 3.42
+
+* The variables F77 and F77FLAGS are now set by default to $(FC) and
+$(FFLAGS).  Makefiles designed for System V make may use these variables in
+explicit rules and expect them to be set.  Unfortunately, there is no way to
+make setting these affect the Fortran implicit rules unless FC and FFLAGS
+are not used (and these are used by BSD make).
+
+
+Version 3.41
+
+* Make now checks to see if its hashed directories are changed by commands.
+Other makes that hash directories (Sun, 4.3 BSD) don't do this.
+
+
+Version 3.39
+
+* The `shell' function no longer captures standard error output.
+
+
+Version 3.32
+
+* A file beginning with a dot can be the default target if it also contains
+a slash (e.g., `../bin/foo').  (Unix make allows this as well.)
+
+
+Version 3.31
+
+* Archive member names are truncated to 15 characters.
+
+* Yet more USG stuff.
+
+* Minimal support for Microport System V (a 16-bit machine and a
+brain-damaged compiler).  This has even lower priority than other USG
+support, so if it gets beyond trivial, I will take it out completely.
+
+* Revamped default implicit rules (not much visible change).
+
+* The -d and -p options can come from the environment.
+
+
+Version 3.30
+
+* Improved support for USG and HPUX (hopefully).
+
+* A variable reference like `$(foo:a=b)', if `a' contains a `%', is
+equivalent to `$(patsubst a,b,$(foo))'.
+
+* Defining .DEFAULT with no deps or commands clears its commands.
+
+* New default implicit rules for .S (cpp, then as), and .sh (copy and make
+executable).  All default implicit rules that use cpp (even indirectly), use
+$(CPPFLAGS).
+
+
+Version 3.29
+
+* Giving the -j option with no arguments gives you infinite jobs.
+
+
+Version 3.28
+
+* New option: "-l LOAD" says not to start any new jobs while others are
+running if the load average is not below LOAD (a floating-point number).
+
+* There is support in place for implementations of remote command execution
+in Make.  See the file remote.c.
+
+
+Version 3.26
+
+* No more than 10 directories will be kept open at once.
+(This number can be changed by redefining MAX_OPEN_DIRECTORIES in dir.c.)
+
+
+Version 3.25
+
+* Archive files will have their modification times recorded before doing
+anything that might change their modification times by updating an archive
+member.
+
+
+Version 3.20
+
+* The `MAKELEVEL' variable is defined for use by makefiles.
+
+
+Version 3.19
+
+* The recursion level indications in error messages are much shorter than
+they were in version 3.14.
+
+
+Version 3.18
+
+* Leading spaces before directives are ignored (as documented).
+
+* Included makefiles can determine the default goal target.
+(System V Make does it this way, so we are being compatible).
+
+
+Version 3.14.
+
+* Variables that are defaults built into Make will not be put in the
+environment for children.  This just saves some environment space and,
+except under -e, will be transparent to sub-makes.
+
+* Error messages from sub-makes will indicate the level of recursion.
+
+* Hopefully some speed-up for large directories due to a change in the
+directory hashing scheme.
+
+* One child will always get a standard input that is usable.
+
+* Default makefiles that don't exist will be remade and read in.
+
+
+Version 3.13.
+
+* Count parentheses inside expansion function calls so you can
+have nested calls: `$(sort $(foreach x,a b,$(x)))'.
+
+
+Version 3.12.
+
+* Several bug fixes, including USG and Sun386i support.
+
+* `shell' function to expand shell commands a la `
+
+* If the `-d' flag is given, version information will be printed.
+
+* The `-c' option has been renamed to `-C' for compatibility with tar.
+
+* The `-p' option no longer inhibits other normal operation.
+
+* Makefiles will be updated and re-read if necessary.
+
+* Can now run several commands at once (parallelism), -j option.
+
+* Error messages will contain the level of Make recursion, if any.
+
+* The `MAKEFLAGS' and `MFLAGS' variables will be scanned for options after
+makefiles are read.
+
+* A double-colon rule with no dependencies will always have its commands run.
+(This is how both the BSD and System V versions of Make do it.)
+
+
+Version 3.05
+
+(Changes from versions 1 through 3.05 were never recorded.  Sorry.)
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/NMakefile.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/NMakefile.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/NMakefile.template	(revision 1780)
@@ -0,0 +1,122 @@
+# -*-Makefile-*- to build GNU make with nmake
+#
+# NOTE: If you have no 'make' program at all to process this makefile,
+# run 'build_w32.bat' instead.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+# 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+LINK = link
+CC = cl
+MAKE = nmake
+
+OUTDIR=.
+MAKEFILE=NMakefile
+SUBPROC_MAKEFILE=NMakefile
+
+CFLAGS_any = /nologo /MT /W4 /GX /Zi /YX /I . /I glob /I w32/include /D WIN32 /D WINDOWS32 /D _CONSOLE /D HAVE_CONFIG_H
+CFLAGS_debug = $(CFLAGS_any) /Od /D DEBUG /D _DEBUG /FR.\WinDebug/ /Fp.\WinDebug/make.pch /Fo.\WinDebug/ /Fd.\WinDebug/make.pdb
+CFLAGS_release = $(CFLAGS_any) /O2 /D NDEBUG /FR.\WinRel/ /Fp.\WinRel/make.pch /Fo.\WinRel/
+
+LDFLAGS_debug = w32\subproc\WinDebug\subproc.lib /NOLOGO /SUBSYSTEM:console\
+	/INCREMENTAL:no /PDB:WinDebug/make.pdb /MACHINE:I386 \
+	/OUT:WinDebug/make.exe /DEBUG
+LDFLAGS_release = w32\subproc\WinRel\subproc.lib /NOLOGO /SUBSYSTEM:console\
+	/INCREMENTAL:no /MACHINE:I386 /OUT:WinRel/make.exe
+
+all: config.h subproc Release Debug
+
+#
+# Make sure we build the subproc library first. It has it's own
+# makefile. To be portable to Windows 95, we put the instructions
+# on how to build the library into a batch file. On NT, we could
+# simply have done foo && bar && dog, but this doesn't port.
+#
+subproc: w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib
+
+w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib: w32/subproc/misc.c w32/subproc/sub_proc.c w32/subproc/w32err.c
+	subproc.bat $(SUBPROC_MAKEFILE) $(MAKE)
+	if exist WinDebug\make.exe erase WinDebug\make.exe
+	if exist WinRel\make.exe erase WinRel\make.exe
+
+config.h: config.h.W32
+	copy $? $@
+
+Release:
+	$(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_release)" CFLAGS="$(CFLAGS_release)" OUTDIR=WinRel WinRel/make.exe
+Debug:
+	$(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_debug)" CFLAGS="$(CFLAGS_debug)" OUTDIR=WinDebug WinDebug/make.exe
+
+clean:
+	if exist WinDebug\nul rmdir /s /q WinDebug
+	if exist WinRel\nul rmdir /s /q WinRel
+	if exist w32\subproc\WinDebug\nul rmdir /s /q w32\subproc\WinDebug
+	if exist w32\subproc\WinRel\nul rmdir /s /q w32\subproc\WinRel
+	if exist config.h erase config.h
+	erase *.pdb
+
+$(OUTDIR):
+	if not exist .\$@\nul mkdir .\$@
+
+LIBS = kernel32.lib user32.lib advapi32.lib
+
+OBJS = \
+	$(OUTDIR)/ar.obj \
+	$(OUTDIR)/arscan.obj \
+	$(OUTDIR)/commands.obj \
+	$(OUTDIR)/default.obj \
+	$(OUTDIR)/dir.obj \
+	$(OUTDIR)/expand.obj \
+	$(OUTDIR)/file.obj \
+	$(OUTDIR)/function.obj \
+	$(OUTDIR)/getloadavg.obj \
+	$(OUTDIR)/getopt.obj \
+	$(OUTDIR)/getopt1.obj \
+	$(OUTDIR)/hash.obj \
+	$(OUTDIR)/implicit.obj \
+	$(OUTDIR)/job.obj \
+	$(OUTDIR)/main.obj \
+	$(OUTDIR)/misc.obj \
+	$(OUTDIR)/read.obj \
+	$(OUTDIR)/remake.obj \
+	$(OUTDIR)/remote-stub.obj \
+	$(OUTDIR)/rule.obj \
+	$(OUTDIR)/signame.obj \
+	$(OUTDIR)/strcache.obj \
+	$(OUTDIR)/variable.obj \
+	$(OUTDIR)/version.obj \
+	$(OUTDIR)/vpath.obj \
+	$(OUTDIR)/glob.obj \
+	$(OUTDIR)/fnmatch.obj \
+	$(OUTDIR)/dirent.obj \
+	$(OUTDIR)/pathstuff.obj
+
+$(OUTDIR)/make.exe: $(OUTDIR) $(OBJS)
+	$(LINK) @<<
+		$(LDFLAGS) $(LIBS) $(OBJS)
+<<
+
+.c{$(OUTDIR)}.obj:
+	$(CC) $(CFLAGS) /c $<
+
+$(OUTDIR)/glob.obj : glob/glob.c
+	$(CC) $(CFLAGS) /c $?
+$(OUTDIR)/fnmatch.obj : glob/fnmatch.c
+	$(CC) $(CFLAGS) /c $?
+$(OUTDIR)/dirent.obj : w32/compat/dirent.c
+	$(CC) $(CFLAGS) /c $?
+$(OUTDIR)/pathstuff.obj : w32/pathstuff.c
+	$(CC) $(CFLAGS) /c $?
Index: /tags/kBuild-0.1.4/src/kmk/README.Amiga
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/README.Amiga	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/README.Amiga	(revision 1780)
@@ -0,0 +1,79 @@
+Short: Port of GNU make with SAS/C (no ixemul.library required)
+Author: GNU, Amiga port by Aaron "Optimizer" Digulla
+Uploader: Aaron "Optimizer" Digulla (digulla@fh-konstanz.de)
+Type: dev/c
+
+This is a pure Amiga port of GNU make. It needs no extra libraries or
+anything. It has the following features (in addition to any features of
+GNU make):
+
+- Runs Amiga-Commands with SystemTags() (Execute)
+- Can run multi-line statements
+- Allows to use Device-Names in targets:
+
+	c:make : make.o
+
+    is ok. To distinguish between device-names and target : or ::, MAKE
+    looks for spaces. If there are any around :, it's taken as a target
+    delimiter, if there are none, it's taken as the name of a device. Note
+    that "make:make.o" tries to create "make.o" on the device "make:".
+- Replaces @@ by a newline in any command line:
+
+	if exists make @@\
+	    delete make.bak quiet @@\
+	    rename make make.bak @@\
+	endif @@\
+	$(CC) Link Make.o To make
+
+    works. Note that the @@ must stand alone (ie. "make@@\" is illegal).
+    Also be carefull that there is a space after the "\" (ie, at the
+    beginning of the next line).
+- Can be made resident to save space and time
+- Amiga specific wildcards can be used in $(wildcard ...)
+
+BUGS:
+- The line
+
+    dummy.h : src/*.c
+
+tries to make dummy.h from "src/*.c" (ie. no wildcard-expansion takes
+place). You have to use "$(wildcard src/*.c)" instead.
+
+COMPILING FROM SCRATCH
+----------------------
+
+To recompile, you need SAS/C 6.51. make itself is not neccessary, there
+is an smakefile.
+
+1. Copy config.ami to config.h
+2. If you use make to compie, copy Makefile.ami to Makefile and
+    glob/Makefile.ami to glob/Makefile. Copy make into the current
+    directory.
+
+3. Run smake/make
+
+INSTALLATION
+
+Copy make somewhere in your search path (eg. sc:c or sc:bin).
+If you plan to use recursive makes, install make resident:
+
+    Resident make Add
+
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/README.DOS.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/README.DOS.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/README.DOS.template	(revision 1780)
@@ -0,0 +1,342 @@
+Port of GNU Make to 32-bit protected mode on MSDOS and MS-Windows.
+
+Builds with DJGPP v2 port of GNU C/C++ compiler and utilities.
+
+
+New (since 3.74) DOS-specific features:
+
+   1. Supports long filenames when run from DOS box on Windows 9x.
+
+   2. Supports both stock DOS COMMAND.COM and Unix-style shells
+      (details in ``Notes'' below).
+
+   3. Supports DOS drive letters in dependencies and pattern rules.
+
+   4. Better support for DOS-style backslashes in pathnames (but see
+      ``Notes'' below).
+
+   5. The $(shell) built-in can run arbitrary complex commands,
+      including pipes and redirection, even when COMMAND.COM is your
+      shell.
+
+   6. Can be built without floating-point code (see below).
+
+   7. Supports signals in child programs and restores the original
+      directory if the child was interrupted.
+
+   8. Can be built without (a previous version of) Make.
+
+   9. The build process requires only standard tools.  (Optional
+      targets like "install:" and "clean:" still need additional
+      programs, though, see below.)
+
+  10. Beginning with v3.78, the test suite works in the DJGPP
+      environment (requires Perl and auxiliary tools; see below).
+
+
+To install a binary distribution:
+
+   Simply unzip the makNNNb.zip file (where NNN is the version number)
+   preserving the directory structure (-d switch if you use PKUNZIP).
+   If you are installing Make on Windows 9X or Windows 2000, use an
+   unzip program that supports long filenames in zip files.  After
+   unzipping, make sure the directory with make.exe is on your PATH,
+   and that's all you need to use Make.
+
+
+To build from sources:
+
+   1. Unzip the archive, preserving the directory structure (-d switch
+      if you use PKUNZIP).  If you build Make on Windows 9X or Windows
+      2000, use an unzip program that supports long filenames in zip
+      files.
+
+      If you are unpacking an official GNU source distribution, use
+      either DJTAR (which is part of the DJGPP development
+      environment), or the DJGPP port of GNU Tar.
+
+   2. Invoke the `configure.bat' batch file.
+
+      If you are building Make in-place, i.e. in the same directory
+      where its sources are kept, just type "configure.bat" and press
+      [Enter].  Otherwise, you need to supply the path to the source
+      directory as an argument to the batch file, like this:
+
+	c:\djgpp\gnu\make-%VERSION%\configure.bat c:/djgpp/gnu/make-%VERSION%
+
+      Note the forward slashes in the source path argument: you MUST
+      use them here.
+
+   3. If configure.bat doesn't find a working Make, it will suggest to
+      use the `dosbuild.bat' batch file to build Make.  Either do as it
+      suggests or install another Make program (a pre-compiled binary
+      should be available from the usual DJGPP sites) and rerun
+      configure.bat.
+
+   4. If you will need to run Make on machines without an FPU, you
+      might consider building a version of Make which doesn't issue
+      floating-point instructions (they don't help much on MSDOS
+      anyway).  To this end, edit the Makefile created by
+      configure.bat and add -DNO_FLOAT to the value of CPPFLAGS.
+
+   5. Invoke Make.
+
+      If you are building from outside of the source directory, you
+      need to tell Make where the sources are, like this:
+
+	        make srcdir=c:/djgpp/gnu/make-%VERSION%
+
+      (configure.bat will tell you this when it finishes).  You MUST
+      use a full, not relative, name of the source directory here, or
+      else Make might fail.
+
+   6. After Make finishes, if you have a Unix-style shell installed,
+      you can use the `install' target to install the package.  You
+      will also need GNU Fileutils and GNU Sed for this (they should
+      be available from the DJGPP sites).
+
+      By default, GNU make will install into your DJGPP installation
+      area.  If you wish to use a different directory, override the
+      DESTDIR variable when invoking "make install", like this:
+
+		make install DESTDIR=c:/other/dir
+
+      This causes the make executable to be placed in c:/other/dir/bin,
+      the man pages in c:/other/dir/man, etc.
+
+      Without a Unix-style shell, you will have to install programs
+      and the docs manually.  Copy make.exe to a directory on your
+      PATH, make.i* info files to your Info directory, and update the
+      file `dir' in your Info directory by adding the following item
+      to the main menu:
+
+	* Make: (make.info).           The GNU make utility.
+
+      If you have the `install-info' program (from the GNU Texinfo
+      package), it will do that for you if you invoke it like this:
+
+	install-info --info-dir=c:/djgpp/info c:/djgpp/info/make.info
+
+      (If your Info directory is other than C:\DJGPP\INFO, change this
+      command accordingly.)
+
+   7. The `clean' targets also require Unix-style shell, and GNU Sed
+      and `rm' programs (the latter from Fileutils).
+
+   8. To run the test suite, type "make check".  This requires a Unix
+      shell (I used the DJGPP port of Bash 2.03), Perl, Sed, Fileutils
+      and Sh-utils.
+
+
+Notes:
+-----
+
+   1. The shell issue.
+
+      This is probably the most significant improvement, first
+      introduced in the port of GNU Make 3.75.
+
+      The original behavior of GNU Make is to invoke commands
+      directly, as long as they don't include characters special to
+      the shell or internal shell commands, because that is faster.
+      When shell features like redirection or filename wildcards are
+      involved, Make calls the shell.
+
+      This port supports both DOS shells (the stock COMMAND.COM and its
+      4DOS/NDOS replacements), and Unix-style shells (tested with the
+      venerable Stewartson's `ms_sh' 2.3 and the DJGPP port of `bash' by
+      Daisuke Aoyama <jack@st.rim.or.jp>).
+
+      When the $SHELL variable points to a Unix-style shell, Make
+      works just like you'd expect on Unix, calling the shell for any
+      command that involves characters special to the shell or
+      internal shell commands.  The only difference is that, since
+      there is no standard way to pass command lines longer than the
+      infamous DOS 126-character limit, this port of Make writes the
+      command line to a temporary disk file and then invokes the shell
+      on that file.
+
+      If $SHELL points to a DOS-style shell, however, Make will not
+      call it automatically, as it does with Unix shells.  Stock
+      COMMAND.COM is too dumb and would unnecessarily limit the
+      functionality of Make.  For example, you would not be able to
+      use long command lines in commands that use redirection or
+      pipes.  Therefore, when presented with a DOS shell, this port of
+      Make will emulate most of the shell functionality, like
+      redirection and pipes, and shall only call the shell when a
+      batch file or a command internal to the shell is invoked.  (Even
+      when a command is an internal shell command, Make will first
+      search the $PATH for it, so that if a Makefile calls `mkdir',
+      you can install, say, a port of GNU `mkdir' and have it called
+      in that case.)
+
+      The key to all this is the extended functionality of `spawn' and
+      `system' functions from the DJGPP library; this port just calls
+      `system' where it would invoke the shell on Unix.  The most
+      important aspect of these functions is that they use a special
+      mechanism to pass long (up to 16KB) command lines to DJGPP
+      programs.  In addition, `system' emulates some internal
+      commands, like `cd' (so that you can now use forward slashes
+      with it, and can also change the drive if the directory is on
+      another drive).  Another aspect worth mentioning is that you can
+      call Unix shell scripts directly, provided that the shell whose
+      name is mentioned on the first line of the script is installed
+      anywhere along the $PATH.  It is impossible to tell here
+      everything about these functions; refer to the DJGPP library
+      reference for more details.
+
+      The $(shell) built-in is implemented in this port by calling
+      `popen'.  Since `popen' calls `system', the above considerations
+      are valid for $(shell) as well.  In particular, you can put
+      arbitrary complex commands, including pipes and redirection,
+      inside $(shell), which is in many cases a valid substitute for
+      the Unix-style command substitution (`command`) feature.
+
+
+   2. "SHELL=/bin/sh" -- or is it?
+
+      Many Unix Makefiles include a line which sets the SHELL, for
+      those versions of Make which don't have this as the default.
+      Since many DOS systems don't have `sh' installed (in fact, most
+      of them don't even have a `/bin' directory), this port takes
+      such directives with a grain of salt.  It will only honor such a
+      directive if the basename of the shell name (like `sh' in the
+      above example) can indeed be found in the directory that is
+      mentioned in the SHELL= line (`/bin' in the above example), or
+      in the current working directory, or anywhere on the $PATH (in
+      that order).  If the basename doesn't include a filename
+      extension, Make will look for any known extension that indicates
+      an executable file (.exe, .com, .bat, .btm, .sh, and even .sed
+      and .pl).  If any such file is found, then $SHELL will be
+      defined to the exact pathname of that file, and that shell will
+      hence be used for the rest of processing.  But if the named
+      shell is *not* found, the line which sets it will be effectively
+      ignored, leaving the value of $SHELL as it was before.  Since a
+      lot of decisions that this port makes depend on the gender of
+      the shell, I feel it doesn't make any sense to tailor Make's
+      behavior to a shell which is nowhere to be found.
+
+      Note that the above special handling of "SHELL=" only happens
+      for Makefiles; if you set $SHELL in the environment or on the
+      Make command line, you are expected to give the complete
+      pathname of the shell, including the filename extension.
+
+      The default value of $SHELL is computed as on Unix (see the Make
+      manual for details), except that if $SHELL is not defined in the
+      environment, $COMSPEC is used.  Also, if an environment variable
+      named $MAKESHELL is defined, it takes precedence over both
+      $COMSPEC and $SHELL.  Note that, unlike Unix, $SHELL in the
+      environment *is* used to set the shell (since on MSDOS, it's
+      unlikely that the interactive shell will not be suitable for
+      Makefile processing).
+
+      The bottom line is that you can now write Makefiles where some
+      of the targets require a real (i.e. Unix-like) shell, which will
+      nevertheless work when such shell is not available (provided, of
+      course, that the commands which should always work, don't
+      require such a shell).  More important, you can convert Unix
+      Makefiles to MSDOS and leave the line which sets the shell
+      intact, so that people who do have Unixy shell could use it for
+      targets which aren't converted to DOS (like `install' and
+      `uninstall', for example).
+
+
+   3. Default directories.
+
+      GNU Make knows about standard directories where it searches for
+      library and include files mentioned in the Makefile.  Since
+      MSDOS machines don't have standard places for these, this port
+      will search ${DJDIR}/lib and ${DJDIR}/include respectively.
+      $DJDIR is defined automatically by the DJGPP startup code as the
+      root of the DJGPP installation tree (unless you've tampered with
+      the DJGPP.ENV file).  This should provide reasonable default
+      values, unless you moved parts of DJGPP to other directories.
+
+
+   4. Letter-case in filenames.
+
+      If you run Make on Windows 9x, you should be aware of the
+      letter-case issue.  Make is internally case-sensitive, but all
+      file operations are case-insensitive on Windows 9x, so
+      e.g. files `FAQ', `faq' and `Faq' all refer to the same file, as
+      far as Windows is concerned.  The underlying DJGPP C library
+      functions honor the letter-case of the filenames they get from
+      the OS, except that by default, they down-case 8+3 DOS filenames
+      which are stored in upper case in the directory and would break
+      many Makefiles otherwise.  (The details of which filenames are
+      converted to lower case are explained in the DJGPP libc docs,
+      under the `_preserve_fncase' and `_lfn_gen_short_fname'
+      functions, but as a thumb rule, any filename that is stored in
+      upper case in the directory, is a valid DOS 8+3 filename and
+      doesn't include characters invalid on MSDOS FAT filesystems,
+      will be automatically down-cased.)  User reports that I have
+      indicate that this default behavior is generally what you'd
+      expect; however, your input is most welcome.
+
+      In any case, if you hit a situation where you must force Make to
+      get the 8+3 DOS filenames in upper case, set FNCASE=y in the
+      environment or in the Makefile.
+
+
+   5. DOS-style pathnames.
+
+      There are a lot of places throughout the program sources which
+      make implicit assumptions about the pathname syntax.  In
+      particular, the directories are assumed to be separated by `/',
+      and any pathname which doesn't begin with a `/' is assumed to be
+      relative to the current directory.  This port attempts to
+      support DOS-style pathnames which might include the drive letter
+      and use backslashes instead of forward slashes.  However, this
+      support is not complete; I feel that pursuing this support too
+      far might break some more important features, particularly if
+      you use a Unix-style shell (where a backslash is a quote
+      character).  I only consider support of backslashes desirable
+      because some Makefiles invoke non-DJGPP programs which don't
+      understand forward slashes.  A notable example of such programs
+      is the standard programs which come with MSDOS.  Otherwise, you
+      are advised to stay away from backslashes whenever possible.  In
+      particular, filename globbing won't work on pathnames with
+      backslashes, because the GNU `glob' library doesn't support them
+      (backslash is special in filename wildcards, and I didn't want
+      to break that).
+
+      One feature which *does* work with backslashes is the filename-
+      related built-in functions such as $(dir), $(notdir), etc.
+      Drive letters in pathnames are also fully supported.
+
+
+
+Bug reports:
+-----------
+
+   Bugs that are clearly related to the MSDOS/DJGPP port should be
+   reported first on the comp.os.msdos.djgpp news group (if you cannot
+   post to Usenet groups, write to the DJGPP mailing list,
+   <djgpp@delorie.com>, which is an email gateway into the above news
+   group).  For other bugs, please follow the procedure explained in
+   the "Bugs" chapter of the Info docs.  If you don't have an Info
+   reader, look up that chapter in the `make.i1' file with any text
+   browser/editor.
+
+
+   Enjoy,
+			Eli Zaretskii <eliz@is.elta.co.il>
+
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/README.OS2.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/README.OS2.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/README.OS2.template	(revision 1780)
@@ -0,0 +1,177 @@
+Port of GNU make to OS/2.
+
+Features of GNU make that do not work under OS/2:
+  - remote job execution
+  - dynamic load balancing
+
+
+Special features of the OS/2 version:
+
+Due to the fact that some people might want to use sh syntax in
+Makefiles while others might want to use OS/2's native shell cmd.exe,
+GNU make supports both shell types. The following list defines the order
+that is used to determine the shell:
+
+ 1. The shell specified by the environment variable MAKESHELL.
+ 2. The shell specified by the SHELL variable within a Makefile. Like
+    Unix, SHELL is NOT taken from the environment.
+ 3. The shell specified by the COMSPEC environment variable.
+ 4. The shell specified by the OS2_SHELL environment variable.
+ 5. If none of the above is defined /bin/sh is used as default.  This
+    happens e.g. in the make testsuite.
+
+Note: - Points 3 and 4 can be turned off at compile time by adding
+        -DNO_CMD_DEFAULT to the CPPFLAGS.
+      - DOS support is not tested for EMX and therefore might not work.
+      - The UNIXROOT environment variable is supported to find /bin/sh
+        if it is not on the current drive.
+
+
+COMPILATION OF GNU MAKE FOR OS/2:
+
+I. ***** SPECIAL OPTIONS *****
+
+ - At compile time you can turn off that cmd is used as default shell
+   (but only /bin/sh). Simply set CPPFLAGS="-DNO_CMD_DEFAULT" and make
+   will not use cmd unless you cause it to do so by setting MAKESHELL to
+   cmd or by specifying SHELL=cmd in your Makefile.
+
+ - At compile time you can set CPPFLAGS="-DNO_CHDIR2" to turn off that
+   GNU make prints drive letters. This is necessary if you want to run
+   the testsuite.
+
+
+II. ***** REQUIREMENTS FOR THE COMPILATION *****
+
+A standard Unix like build environment:
+
+ - sh compatible shell (ksh, bash, ash, but tested only with pdksh 5.2.14
+   release 2)
+   If you use pdksh it is recommended to update to 5.2.14 release 2. Older
+   versions may not work! You can get this version at
+   http://www.math.ohio-state.edu/~ilya/software/os2/pdksh-5.2.14-bin-2.zip
+ - GNU file utilities (make sure that install.exe from the file utilities
+   is in front of your PATH before X:\OS2\INSTALL\INSTALL.EXE. I recommend
+   also to change the filename to ginstall.exe instead of install.exe
+   to avoid confusion with X:\OS2\INSTALL\INSTALL.EXE)
+ - GNU shell utilities
+ - GNU text utilities
+ - gawk
+ - grep
+ - sed
+ - GNU make 3.79.1 (special OS/2 patched version) or higher
+ - perl 5.005 or higher
+ - GNU texinfo (you can use 3.1 (gnuinfo.zip), but I recommend 4.0)
+
+If you want to recreate the configuration files (developers only!)
+you need also: GNU m4 1.4, autoconf 2.59, automake 1.9.6 (or compatible)
+
+
+III. ***** COMPILATION AND INSTALLATION *****
+
+ a) ** Developers only - Everyone else should skip this section **
+    To recreate the configuration files use:
+
+      export EMXSHELL=ksh
+      aclocal -I config
+      automake
+      autoconf
+      autoheader
+
+
+b) Installation into x:/usr
+
+   Note: Although it is possible to compile make using "./configure",
+         "make", "make install" this is not recommended.  In particular,
+         you must ALWAYS use LDFLAGS="-Zstack 0x6000" because the default
+         stack size is far to small and make will not work properly!
+
+Recommended environment variables and installation options:
+
+    export ac_executable_extensions=".exe"
+    export CPPFLAGS="-D__ST_MT_ERRNO__"
+    export CFLAGS="-O2 -Zomf -Zmt"
+    export LDFLAGS="-Zcrtdll -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x6000"
+    export RANLIB="echo"
+    ./configure --prefix=x:/usr --infodir=x:/usr/share/info --mandir=x:/usr/share/man --without-included-gettext
+    make AR=emxomfar
+    make install
+
+Note: If you use gcc 2.9.x I recommend to set also LIBS="-lgcc"
+
+Note: You can add -DNO_CMD_DEFAULT and -DNO_CHDIR2 to CPPFLAGS.
+      See section I. for details.
+
+
+IV. ***** NLS support *****
+
+GNU make has NLS (National Language Support), with the following
+caveats:
+
+ a) It will only work with GNU gettext, and
+ b) GNU gettext support is not included in the GNU make package.
+
+Therefore, if you wish to enable the internationalization features of
+GNU make you must install GNU gettext on your system before configuring
+GNU make.
+
+You can choose the languages to be installed. To install support for
+English, German and French only enter:
+
+  export LINGUAS="en de fr"
+
+If you don't specify LINGUAS all languages are installed.
+
+If you don't want NLS support (English only) use the option
+--disable-nls for the configure script.  Note if GNU gettext is not
+installed then NLS will not be enabled regardless of this flag.
+
+
+V. ***** Running the make test suite *****
+
+To run the included make test suite you have to set
+
+  CPPFLAGS="-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2"
+
+before you compile make. This is due to some restrictions of the
+testsuite itself. -DNO_CMD_DEFAULT causes make to use /bin/sh as default
+shell in every case. Normally you could simply set MAKESHELL="/bin/sh"
+to do this but the testsuite ignores the environment. -DNO_CHDIR2 causes
+make not to use drive letters for directory names (i.e. _chdir2() and
+_getcwd2() are NOT used).  The testsuite interpretes the whole output of
+make, especially statements like make[1]: Entering directory
+`C:/somewhere/make-3.79.1/tests' where the testsuite does not expect the
+drive letter. This would be interpreted as an error even if there is
+none.
+
+To run the testsuite do the following:
+
+  export CPPFLAGS="-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2"
+  export CFLAGS="-Zomf -O2 -Zmt"
+  export LDFLAGS="-Zcrtdll -s -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x6000"
+  export RANLIB="echo"
+  ./configure --prefix=x:/usr --disable-nls
+  make AR=emxomfar
+  make check
+
+All tests should work fine with the exception of one of the "INCLUDE_DIRS"
+tests which will fail if your /usr/include directory is on a drive different
+from the make source tree.
+
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/README.W32.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/README.W32.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/README.W32.template	(revision 1780)
@@ -0,0 +1,289 @@
+This version of GNU make has been tested on Microsoft Windows 2000/XP/2003.
+It has also been used on Windows 95/98/NT, and on OS/2.
+
+It builds natively with MSVC 2.x, 4.x, 5.x, 6.x, and 2003 as well as
+.NET 7.x and .NET 2003.
+
+It builds with the MinGW port of GCC 3.x (tested with GCC 3.4.2).
+
+The Windows 32-bit port of GNU make is maintained jointly by various
+people.  It was originally made by Rob Tulloh.
+
+
+Do this first, regardless of the build method you choose:
+---------------------------------------------------------
+
+ 1. At the Windows command prompt run:
+
+      if not exist NMakefile copy NMakefile.template NMakefile
+      if not exist config.h copy config.h.W32 config.h
+
+    Then edit config.h to your liking (especially the few shell-related
+    defines near the end, or HAVE_CASE_INSENSITIVE_FS which corresponds
+    to './configure --enable-case-insensitive-file-system').
+
+
+Using make_msvc_net2003.vcproj
+------------------------------
+
+ 2. Open make_msvc_net2003.vcproj in MSVS71 or MSVC71 or any compatible IDE,
+    then build this project as usual.
+
+
+Building with (MinGW-)GCC using build_w32.bat
+---------------------------------------------
+
+ 2. Open a W32 command prompt for your installed (MinGW-)GCC, setup a
+    correct PATH and other environment variables for it, then execute ...
+
+	build_w32.bat gcc
+
+    This produces gnumake.exe in the current directory.
+
+
+Building with (MSVC++-)cl using build_w32.bat or NMakefile
+----------------------------------------------------------
+
+ 2. Open a W32 command prompt for your installed (MSVC++-)cl, setup a
+    correct PATH and other environment variables for it (usually via
+    executing vcvars32.bat or vsvars32.bat from the cl-installation,
+    e.g. "%VS71COMNTOOLS%vsvars32.bat"; or using a corresponding start
+    menue entry from the cl-installation), then execute EITHER ...
+
+	build_w32.bat
+
+    (this produces WinDebug/gnumake.exe and WinRel/gnumake.exe)
+
+    ... OR ...
+
+	nmake /f NMakefile
+
+    (this produces WinDebug/make.exe and WinRel/make.exe).
+
+
+-------------------
+-- Notes/Caveats --
+-------------------
+
+GNU make on Windows 32-bit platforms:
+
+	This version of make is ported natively to Windows32 platforms
+	(Windows NT 3.51, Windows NT 4.0, Windows 95, and Windows 98). It
+	does not rely on any 3rd party software or add-on packages for
+	building. The only thing needed is a version of Visual C++,
+	which is the predominant compiler used on Windows32 platforms.
+
+	Do not confuse this port of GNU make with other Windows32 projects
+	which provide a GNU make binary. These are separate projects
+	and are not connected to this port effort.
+
+GNU make and sh.exe:
+
+	This port prefers you have a working sh.exe somewhere on your
+	system. If you don't have sh.exe, the port falls back to
+	MSDOS mode for launching programs (via a batch file).
+	The MSDOS mode style execution has not been tested that
+	carefully though (The author uses GNU bash as sh.exe).
+
+	There are very few true ports of Bourne shell for NT right now.
+	There is a version of GNU bash available from Cygnus "Cygwin"
+	porting effort (http://www.cygwin.com/).
+	Other possibilities are the MKS version of sh.exe, or building
+        your own with a package like NutCracker (DataFocus) or Portage
+        (Consensys).  Also MinGW includes sh (http://mingw.org/).
+
+GNU make and brain-dead shells (BATCH_MODE_ONLY_SHELL):
+
+	Some versions of Bourne shell do not behave well when invoked
+	as 'sh -c' from CreateProcess().  The main problem is they seem
+	to have a hard time handling quoted strings correctly. This can
+	be circumvented by writing commands to be executed to a batch
+	file and then executing the command by calling 'sh file'.
+
+	To work around this difficulty, this version of make supports
+	a batch mode.  When BATCH_MODE_ONLY_SHELL is defined at compile
+	time, make forces all command lines to be executed via script
+	files instead of by command line.  In this mode you must have a
+	working sh.exe in order to use parallel builds (-j).
+
+	A native Windows32 system with no Bourne shell will also run
+	in batch mode.  All command lines will be put into batch files
+	and executed via $(COMSPEC) (%COMSPEC%).  Note that parallel
+        builds (-j) require a working Bourne shell; they will not work
+        with COM.
+
+GNU make and Cygnus GNU Windows32 tools:
+
+	Good news! Make now has native support for Cygwin sh. To enable,
+	define the HAVE_CYGWIN_SHELL in config.h and rebuild make
+	from scratch. This version of make tested with B20.1 of Cygwin.
+	Do not define BATCH_MODE_ONLY_SHELL if you use HAVE_CYGWIN_SHELL.
+
+GNU make and the MKS shell:
+
+	There is now semi-official support for the MKS shell. To turn this
+	support on, define HAVE_MKS_SHELL in the config.h.W32 before you
+	build make.  Do not define BATCH_MODE_ONLY_SHELL if you turn
+	on HAVE_MKS_SHELL.
+
+GNU make handling of drive letters in pathnames (PATH, vpath, VPATH):
+
+	There is a caveat that should be noted with respect to handling
+	single character pathnames on Windows systems.	When colon is
+	used in PATH variables, make tries to be smart about knowing when
+	you are using colon as a separator versus colon as a drive
+	letter.	 Unfortunately, something as simple as the string 'x:/'
+	could be interpreted 2 ways: (x and /) or (x:/).
+
+	Make chooses to interpret a letter plus colon (e.g. x:/) as a
+	drive letter pathname.	If it is necessary to use single
+	character directories in paths (VPATH, vpath, Path, PATH), the
+	user must do one of two things:
+
+	 a. Use semicolon as the separator to disambiguate colon. For
+	    example use 'x;/' if you want to say 'x' and '/' are
+	    separate components.
+
+	 b. Qualify the directory name so that there is more than
+	    one character in the path(s) used. For example, none
+	    of these settings are ambiguous:
+
+	      ./x:./y
+	      /some/path/x:/some/path/y
+	      x:/some/path/x:x:/some/path/y
+
+	Please note that you are free to mix colon and semi-colon in the
+	specification of paths.	 Make is able to figure out the intended
+	result and convert the paths internally to the format needed
+	when interacting with the operating system, providing the path
+	is not within quotes, e.g. "x:/test/test.c".
+
+	You are encouraged to use colon as the separator character.
+	This should ease the pain of deciding how to handle various path
+	problems which exist between platforms.	 If colon is used on
+	both Unix and Windows systems, then no ifdef'ing will be
+	necessary in the makefile source.
+
+GNU make test suite:
+
+	I verified all functionality with a slightly modified version
+	of make-test-%VERSION% (modifications to get test suite to run
+	on Windows NT). All tests pass in an environment that includes
+	sh.exe.  Tests were performed on both Windows NT and Windows 95.
+
+Building GNU make on Windows NT and Windows 95/98 with Microsoft Visual C:
+
+	I did not provide a Visual C project file with this port as
+	the project file would not be considered freely distributable
+	(or so I think). It is easy enough to create one, though, if
+	you know how to use Visual C.
+
+	I build the program statically to avoid problems locating DLL's
+	on machines that may not have MSVC runtime installed. If you
+	prefer, you can change make to build with shared libraries by
+	changing /MT to /MD in the NMakefile (or in build_w32.bat).
+
+	The program has not been built for non-Intel architectures (yet).
+
+	I have not tried to build with any other compilers than MSVC. I
+	have heard that this is possible though so don't be afraid to
+	notify me of your successes!
+
+Pathnames and white space:
+
+	Unlike Unix, Windows 95/NT systems encourage pathnames which
+	contain white space (e.g. C:\Program Files\). These sorts of
+	pathnames are legal under Unix too, but are never encouraged.
+	There is at least one place in make (VPATH/vpath handling) where
+	paths containing white space will simply not work. There may be
+	others too. I chose to not try and port make in such a way so
+	that these sorts of paths could be handled. I offer these
+	suggestions as workarounds:
+
+		1. Use 8.3 notation. i.e. "x:/long~1/", which is actually
+		   "x:\longpathtest".  Type "dir /x" to view these filenames
+		   within the cmd.exe shell.
+		2. Rename the directory so it does not contain white space.
+
+	If you are unhappy with this choice, this is free software
+	and you are free to take a crack at making this work. The code
+	in w32/pathstuff.c and vpath.c would be the places to start.
+
+Pathnames and Case insensitivity:
+
+	Unlike Unix, Windows 95/NT systems are case insensitive but case
+	preserving.  For example if you tell the file system to create a
+	file named "Target", it will preserve the case.  Subsequent access to
+	the file with other case permutations will succeed (i.e. opening a
+	file named "target" or "TARGET" will open the file "Target").
+
+	By default, GNU make retains its case sensitivity when comparing
+	target names and existing files or directories.  It can be
+	configured, however, into a case preserving and case insensitive
+	mode by adding a define for HAVE_CASE_INSENSITIVE_FS to
+	config.h.W32.
+
+	For example, the following makefile will create a file named
+	Target in the directory subdir which will subsequently be used
+	to satisfy the dependency of SUBDIR/DepTarget on SubDir/TARGET.
+	Without HAVE_CASE_INSENSITIVE_FS configured, the dependency link
+	will not be made:
+
+	subdir/Target:
+		touch $@
+
+	SUBDIR/DepTarget: SubDir/TARGET
+		cp $^ $@
+
+	Reliance on this behavior also eliminates the ability of GNU make
+	to use case in comparison of matching rules.  For example, it is
+	not possible to set up a C++ rule using %.C that is different
+	than a C rule using %.c.  GNU make will consider these to be the
+	same rule and will issue a warning.
+
+SAMBA/NTFS/VFAT:
+
+	I have not had any success building the debug version of this
+	package using SAMBA as my file server. The reason seems to be
+	related to the way VC++ 4.0 changes the case name of the pdb
+	filename it is passed on the command line. It seems to change
+	the name always to to lower case. I contend that the VC++
+	compiler should not change the casename of files that are passed
+	as arguments on the command line. I don't think this was a
+	problem in MSVC 2.x, but I know it is a problem in MSVC 4.x.
+
+	The package builds fine on VFAT and NTFS filesystems.
+
+	Most all of the development I have done to date has been using
+	NTFS and long file names. I have not done any considerable work
+	under VFAT. VFAT users may wish to be aware that this port of
+	make does respect case sensitivity.
+
+FAT:
+
+	Version 3.76 added support for FAT filesystems. Make works
+	around some difficulties with stat'ing of files and caching of
+	filenames and directories internally.
+
+Bug reports:
+
+	Please submit bugs via the normal bug reporting mechanism which
+	is described in the GNU make manual and the base README.
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/README.customs
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/README.customs	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/README.customs	(revision 1780)
@@ -0,0 +1,114 @@
+                                                            -*-indented-text-*-
+
+GNU make can utilize the Customs library, distributed with Pmake, to
+provide builds distributed across multiple hosts.
+
+In order to utilize this capability, you must first download and build
+the Customs library.  It is contained in the Pmake distribution, which
+can be obtained at:
+
+  ftp://ftp.icsi.berkeley.edu/pub/ai/stolcke/software/
+
+This integration was tested (superficially) with Pmake 2.1.33.
+
+
+BUILDING CUSTOMS
+----------------
+
+First, build pmake and Customs.  You need to build pmake first, because
+Customs require pmake to build.  Unfortunately, this is not trivial;
+please see the pmake and Customs documentation for details.  The best
+place to look for instructions is in the pmake-2.1.33/INSTALL file.
+
+Note that the 2.1.33 Pmake distribution comes with a set of patches to
+GNU make, distributed in the pmake-2.1.33/etc/gnumake/ directory.  These
+patches are based on GNU make 3.75 (there are patches for earlier
+versions of GNU make, also).  The parts of this patchfile which relate
+directly to Customs support have already been incorporated into this
+version of GNU make, so you should _NOT_ apply the patch file.
+
+However, there are a few non-Customs specific (as far as I could tell)
+changes here which are not incorporated (for example, the modification
+to try expanding -lfoo to libfoo.so).  If you rely on these changes
+you'll need to re-apply them by hand.
+
+Install the Customs library and header files according to the
+documentation.  You should also install the man pages (contrary to
+comments in the documentation, they weren't installed automatically for
+me; I had to cd to the ``pmake-2.1.33/doc'' directory and run ``pmake
+install'' there directly).
+
+
+BUILDING GNU MAKE
+-----------------
+
+Once you've installed Customs, you can build GNU make to use it.  When
+configuring GNU make, merely use the ``--with-customs=DIR'' option.
+Provide the directory containing the ``lib'' and ``include/customs''
+subdirectories as DIR.  For example, if you installed the customs
+library in /usr/local/lib and the headers in /usr/local/include/customs,
+then you'd pass ``--with-customs=/usr/local'' as an option to configure.
+
+Run make (or use build.sh) normally to build GNU make as described in
+the INSTALL file.
+
+See the documentation for Customs for information on starting and
+configuring Customs.
+
+
+INVOKING CUSTOMS-IZED GNU MAKE
+-----------------------------
+
+One thing you should be aware of is that the default build environment
+for Customs requires root permissions.  Practically, this means that GNU
+make must be installed setuid root to use Customs.
+
+If you don't want to do this, you can build Customs such that root
+permissions are not necessary.  Andreas Stolcke <stolcke@speech.sri.com>
+writes:
+
+ > pmake, gnumake or any other customs client program is not required to
+ > be suid root if customs was compiled WITHOUT the USE_RESERVED_PORTS
+ > option in customs/config.h.  Make sure the "customs" service in
+ > /etc/services is defined accordingly (port 8231 instead of 1001).
+
+ > Not using USE_RESERVED_PORTS means that a user with programming
+ > skills could impersonate another user by writing a fake customs
+ > client that pretends to be someone other than himself.  See the
+ > discussion in etc/SECURITY.
+
+
+PROBLEMS
+--------
+
+SunOS 4.1.x:
+  The customs/sprite.h header file #includes the <malloc.h> header
+  files; this conflicts with GNU make's configuration so you'll get a
+  compile error if you use GCC (or any other ANSI-capable C compiler).
+
+  I commented out the #include in sprite.h:107:
+
+    #if defined(sun) || defined(ultrix) || defined(hpux) || defined(sgi)
+    /* #include <malloc.h> */
+    #else
+
+  YMMV.
+
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/README.cvs
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/README.cvs	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/README.cvs	(revision 1780)
@@ -0,0 +1,215 @@
+                                                                     -*-text-*-
+
+-------------------------------------------------------------------------------
+Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+-------------------------------------------------------------------------------
+
+Obtaining CVS Code
+------------------
+
+This seems redundant, since if you're reading this you most likely have
+already performed this step; however, for completeness, you can obtain
+the GNU make source code via anonymous CVS from the FSF's Savannah
+project <http://savannah.gnu.org/projects/make/>:
+
+  $ cvs -d:pserver:anoncvs@cvs.savannah.gnu.org:/sources/make co make
+
+You might want to use the "-z3" option to get compression, and you most
+certainly will want the -P option to avoid unneeded directories
+cluttering up your source.  Personally I add these (as well as -dP for
+update) to my ~/.cvsrc file.
+
+
+If you have an older version of CVS, you might have to login first.
+There is no password; just hit the ENTER key if you are asked for one.
+
+
+Building From CVS
+-----------------
+
+To build GNU make from CVS, you will need Autoconf, Automake, and
+Gettext, and any tools that those utilities require (GNU m4, Perl,
+etc.).  See the configure.in file to find the minimum versions of each
+of these tools.  You will also need a copy of wget.
+
+When building from CVS you must build in the source directory: "VPATH
+builds" from remote directories are not supported.  Once you've created
+a distribution, of course, you can unpack it and do a VPATH build from
+there.
+
+After checking out the code, you will need to perform these steps to get
+to the point where you can run "make".
+
+
+ 1) $ autoreconf -i
+
+    This rebuilds all the things that need rebuilding, installing
+    missing files as symbolic links.
+
+    You may get warnings here about missing files like README, etc.
+    Ignore them, they are harmless.
+
+
+ 2) $ ./configure
+
+    Generate a Makefile
+
+
+ 3) $ make update
+
+    Use wget to retrieve various other files that GNU make relies on,
+    but does not keep in its own source tree.
+
+    NB: You may need GNU make to correctly perform this step; if you use
+    a platform-local make you may get problems with missing files in doc/.
+
+
+At this point you have successfully brought your CVS copy of the GNU
+make source directory up to the point where it can be treated
+more-or-less like the official package you would get from ftp.gnu.org.
+That is, you can just run:
+
+  $ make && make check && make install
+
+to build and install GNU make.
+
+
+Windows builds from CVS
+-----------------------
+
+If you have a UNIX emulation like CYGWIN you can opt to run the general
+build procedure above; it will work.  Be sure to read
+README.W32.template for information on options you might want to use
+when running ./configure.
+
+If you can't or don't want to do that, then rename the file
+README.W32.template to README.W32 and follow those instructions.
+
+
+Creating a Package
+------------------
+
+Once you have performed the above steps (including the configuration and
+build) you can create a GNU make package.  This is very simple, just
+run:
+
+  $ make dist-gzip
+
+and, if you like:
+
+  $ make dist-bzip2
+
+Even better, you should run this:
+
+  $ make distcheck
+
+Which will build both .gz and .bz2 package files, then unpack them into
+a temporary location, try to build them, and repack them, verifying that
+everything works, you get the same results, _and_ no extraneous files
+are left over after the "distclean" rule--whew!!  Now, _that_ is why
+converting to Automake is worth the trouble!  A big "huzzah!" to Tom
+T. and the AutoToolers!
+
+
+Steps to Release
+----------------
+
+Here are the things that need to be done (in more or less this order)
+before making an official release:
+
+  * Update the configure.in file with the new release number.
+  * Update the NEWS file with the release number and date.
+  * Create the new release in the Savannah "Bugs" Administration for
+    both the "Component Version" and "Fixed Release" fields.
+  * Create the new release in the Savannah "Patches" Administration for
+    the "Fixed Release" field.
+  * Update the Savannah bug list URL in the NEWS file to use the correct
+    "Fixed Release" ID number.
+  * Run "make distcheck" to be sure it all works.
+  * Commit everything.
+  * cvs tag <RTAG> where RTAG is constructed by replacing each "." in
+    the version with "-" and prefixing it with "make-".
+
+
+Publishing a Package
+--------------------
+
+In order to publish a package on the FSF FTP site, either the release
+site ftp://ftp.gnu.org, or the prerelease site ftp://alpha.gnu.org, you
+first need to have my GPG private key and my passphrase to unlock it.
+And, you can't have them!  So there!  But, just so I remember here's
+what you do:
+
+  Make sure the "Steps to Release" are complete and committed and tagged.
+
+  cvs -d :pserver:anonymous@cvs.savannah.gnu.org:/sources/make \
+     export -r<RTAG> -d make-release make
+
+  cd make-release
+
+  <run the commands above to build the release>
+
+  make upload-alpha             # for alpha.gnu.org (pre-releases)
+       -OR-
+  make upload-ftp               # for ftp.gnu.org (official releases)
+
+It will ask for the GPG passphrase _THREE_ times.  Sigh.
+
+
+For both final releases and pre-releases, send an email with the URL of
+the package to the GNU translation robot to allow the translators to
+work on it:
+
+     <translation@iro.umontreal.ca>
+
+
+Where to Announce
+-----------------
+
+Create the announcement in a text file, then sign it with GPG.
+
+  gpg --clearsign <announcement.txt>
+
+Upload to gnu.org, then login and send from my account there.
+
+Email to: make-alpha@gnu.org, bug-make@gnu.org, help-make@gnu.org, make-w32@gnu.org.
+Email to: info-gnu@gnu.org
+
+Add a news item to the Savannah project site.
+
+Add an update to freshmeat.net.
+
+
+Appendix A - For The Brave
+--------------------------
+
+For those of you who trust me implicitly, or are just brave (or
+foolhardy), here is a canned sequence of commands to build a GNU make
+distribution package from a virgin CVS source checkout (assuming all the
+prerequisites are available of course).
+
+This list is eminently suitable for a quick swipe o' the mouse and a
+swift click o' mouse-2 into an xterm.  Go for it!
+
+autoreconf -i
+./configure
+make update
+make
+make check
+
+Or, all-in-one:
+
+autoreconf -i && ./configure && make update && make && make check
Index: /tags/kBuild-0.1.4/src/kmk/README.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/README.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/README.template	(revision 1780)
@@ -0,0 +1,190 @@
+This directory contains the %VERSION% release of GNU Make.
+
+See the file NEWS for the user-visible changes from previous releases.
+In addition, there have been bugs fixed.
+
+Please check the system-specific notes below for any caveats related to
+your operating system.
+
+For general building and installation instructions, see the file INSTALL.
+
+If you need to build GNU Make and have no other `make' program to use,
+you can use the shell script `build.sh' instead.  To do this, first run
+`configure' as described in INSTALL.  Then, instead of typing `make' to
+build the program, type `sh build.sh'.  This should compile the program
+in the current directory.  Then you will have a Make program that you can
+use for `./make install', or whatever else.
+
+Some systems' Make programs are broken and cannot process the Makefile for
+GNU Make.  If you get errors from your system's Make when building GNU
+Make, try using `build.sh' instead.
+
+
+GNU Make is free software.  See the file COPYING for copying conditions.
+
+
+Downloading
+-----------
+
+GNU Make can be obtained in many different ways.  See a description here:
+
+  http://www.gnu.org/software/software.html
+
+
+Documentation
+-------------
+
+GNU make is fully documented in the GNU Make manual, which is contained
+in this distribution as the file make.texinfo.  You can also find
+on-line and preformatted (PostScript and DVI) versions at the FSF's web
+site.  There is information there about ordering hardcopy documentation.
+
+  http://www.gnu.org/
+  http://www.gnu.org/doc/doc.html
+  http://www.gnu.org/manual/manual.html
+
+
+Development
+-----------
+
+GNU Make development is hosted by Savannah, the FSF's online development
+management tool.  Savannah is here:
+
+  http://savannah.gnu.org
+
+And the GNU Make development page is here:
+
+  http://savannah.gnu.org/projects/make/
+
+You can find most information concerning the development of GNU Make at
+this site.
+
+
+Bug Reporting
+-------------
+
+You can send GNU make bug reports to <bug-make@gnu.org>.  Please see the
+section of the GNU make manual entitled `Problems and Bugs' for
+information on submitting useful and complete bug reports.
+
+You can also use the online bug tracking system in the Savannah GNU Make
+project to submit new problem reports or search for existing ones:
+
+  http://savannah.gnu.org/bugs/?group=make
+
+If you need help using GNU make, try these forums:
+
+  help-make@gnu.org
+  help-utils@gnu.org
+  news:gnu.utils.help
+  news:gnu.utils.bug
+
+  http://savannah.gnu.org/support/?group=make
+
+You may also find interesting patches to GNU Make available here:
+
+  http://savannah.gnu.org/patch/?group=make
+
+Note these patches are provided by our users as a service and we make no
+statements regarding their correctness.  Please contact the authors
+directly if you have a problem or suggestion for a patch available on
+this page.
+
+
+CVS Access
+----------
+
+The GNU make source repository is available via anonymous CVS from the
+GNU Subversions CVS server; look here for details:
+
+  http://savannah.gnu.org/cvs/?group=make
+
+Please note: you won't be able to build GNU make from CVS without
+installing appropriate maintainer's tools, such as GNU m4, automake,
+autoconf, Perl, GNU make, and GCC.  See the README.cvs file for hints on
+how to build GNU make once these tools are available.  We make no
+guarantees about the contents or quality of the latest code in the CVS
+repository: it is not unheard of for code that is known to be broken to
+be checked in.  Use at your own risk.
+
+
+System-specific Notes
+---------------------
+
+It has been reported that the XLC 1.2 compiler on AIX 3.2 is buggy such
+that if you compile make with `cc -O' on AIX 3.2, it will not work
+correctly.  It is said that using `cc' without `-O' does work.
+
+The standard /bin/sh on SunOS 4.1.3_U1 and 4.1.4 is broken and cannot be
+used to configure GNU make.  Please install a different shell such as
+bash or pdksh in order to run "configure".  See this message for more
+information:
+  http://mail.gnu.org/archive/html/bug-autoconf/2003-10/msg00190.html
+
+One area that is often a problem in configuration and porting is the code
+to check the system's current load average.  To make it easier to test and
+debug this code, you can do `make check-loadavg' to see if it works
+properly on your system.  (You must run `configure' beforehand, but you
+need not build Make itself to run this test.)
+
+Another potential source of porting problems is the support for large
+files (LFS) in configure for those operating systems that provide it.
+Please report any bugs that you find in this area.  If you run into
+difficulties, then as a workaround you should be able to disable LFS by
+adding the `--disable-largefile' option to the `configure' script.
+
+On systems that support micro- and nano-second timestamp values and
+where stat(2) provides this information, GNU make will use it when
+comparing timestamps to get the most accurate possible result.  However,
+note that many current implementations of tools that *set* timestamps do
+not preserve micro- or nano-second granularity.  This means that "cp -p"
+and other similar tools (tar, etc.) may not exactly duplicate timestamps
+with micro- and nano-second granularity on some systems.  If your build
+system contains rules that depend on proper behavior of tools like "cp
+-p", you should consider using the .LOW_RESOLUTION_TIME pseudo-target to
+force make to treat them properly.  See the manual for details.
+
+
+Ports
+-----
+
+  - See README.customs for details on integrating GNU make with the
+    Customs distributed build environment from the Pmake distribution.
+
+  - See readme.vms for details about GNU Make on OpenVMS.
+
+  - See README.Amiga for details about GNU Make on AmigaDOS.
+
+  - See README.W32 for details about GNU Make on Windows NT, 95, or 98.
+
+  - See README.DOS for compilation instructions on MS-DOS and MS-Windows
+    using DJGPP tools.
+
+    A precompiled binary of the MSDOS port of GNU Make is available as part
+    of DJGPP; see the WWW page http://www.delorie.com/djgpp/ for more
+    information.
+
+Please note there are two _separate_ ports of GNU make for Microsoft
+systems: a native Windows tool built with (for example) MSVC or Cygwin,
+and a DOS-based tool built with DJGPP.  Please be sure you are looking
+at the right README!
+
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/SCOPTIONS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/SCOPTIONS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/SCOPTIONS	(revision 1780)
@@ -0,0 +1,13 @@
+ERRORREXX
+OPTIMIZE
+NOVERSION
+OPTIMIZERTIME
+OPTIMIZERALIAS
+DEFINE INCLUDEDIR="include:"
+DEFINE LIBDIR="lib:"
+DEFINE NO_ALLOCA
+DEFINE NO_FLOAT
+DEFINE NO_ARCHIVES
+IGNORE=161
+IGNORE=100
+STARTUP=cres
Index: /tags/kBuild-0.1.4/src/kmk/SMakefile.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/SMakefile.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/SMakefile.template	(revision 1780)
@@ -0,0 +1,213 @@
+# -*-Makefile-*- for building GNU make with smake
+#
+# NOTE: If you have no 'make' program at all to process this makefile,
+# run 'build.sh' instead.
+#
+# Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#
+#	Makefile for GNU Make
+#
+
+# Ultrix 2.2 make doesn't expand the value of VPATH.
+VPATH = /make-%VERSION%/
+# This must repeat the value, because configure will remove `VPATH = .'.
+srcdir = /make-%VERSION%/
+
+CC = sc
+RM = delete
+MAKE = smake
+
+CFLAGS =
+CPPFLAGS =
+LDFLAGS =
+
+# Define these for your system as follows:
+#	-DNO_ARCHIVES		To disable `ar' archive support.
+#	-DNO_FLOAT		To avoid using floating-point numbers.
+#	-DENUM_BITFIELDS	If the compiler isn't GCC but groks enum foo:2.
+#				Some compilers apparently accept this
+#				without complaint but produce losing code,
+#				so beware.
+# NeXT 1.0a uses an old version of GCC, which required -D__inline=inline.
+# See also `config.h'.
+defines =
+
+# Which flavor of remote job execution support to use.
+# The code is found in `remote-$(REMOTE).c'.
+REMOTE = stub
+
+# If you are using the GNU C library, or have the GNU getopt functions in
+# your C library, you can comment these out.
+GETOPT = getopt.o getopt1.o
+GETOPT_SRC = $(srcdir)getopt.c $(srcdir)getopt1.c $(srcdir)getopt.h
+
+# If you are using the GNU C library, or have the GNU glob functions in
+# your C library, you can comment this out.  GNU make uses special hooks
+# into the glob functions to be more efficient (by using make's directory
+# cache for globbing), so you must use the GNU functions even if your
+# system's C library has the 1003.2 glob functions already.  Also, the glob
+# functions in the AIX and HPUX C libraries are said to be buggy.
+GLOB = Lib glob/glob.lib
+
+# If your system doesn't have alloca, or the one provided is bad, define this.
+ALLOCA = alloca.o
+ALLOCA_SRC = $(srcdir)alloca.c
+
+# If your system needs extra libraries loaded in, define them here.
+# System V probably need -lPW for alloca.  HP-UX 7.0's alloca in
+# libPW.a is broken on HP9000s300 and HP9000s400 machines.  Use
+# alloca.c instead on those machines.
+LOADLIBES =
+
+# Any extra object files your system needs.
+extras = amiga.o
+
+# Common prefix for machine-independent installed files.
+prefix =
+# Common prefix for machine-dependent installed files.
+exec_prefix =
+
+# Directory to install `make' in.
+bindir = sc:c
+# Directory to find libraries in for `-lXXX'.
+libdir = lib:
+# Directory to search by default for included makefiles.
+includedir = include:
+# Directory to install the Info files in.
+infodir = doc:
+# Directory to install the man page in.
+mandir = t:
+# Number to put on the man page filename.
+manext = 1
+# Prefix to put on installed `make' binary file name.
+binprefix =
+# Prefix to put on installed `make' man page file name.
+manprefix = $(binprefix)
+
+# Whether or not make needs to be installed setgid.
+# The value should be either `true' or `false'.
+# On many systems, the getloadavg function (used to implement the `-l'
+# switch) will not work unless make is installed setgid kmem.
+install_setgid = false
+# Install make setgid to this group so it can read /dev/kmem.
+group = sys
+
+# Program to install `make'.
+INSTALL_PROGRAM = copy
+# Program to install the man page.
+INSTALL_DATA = copy
+# Generic install program.
+INSTALL = copy
+
+# Program to format Texinfo source into Info files.
+MAKEINFO = makeinfo
+# Program to format Texinfo source into DVI files.
+TEXI2DVI = texi2dvi
+
+# Programs to make tags files.
+ETAGS = etags -w
+CTAGS = ctags -w
+
+objs = commands.o job.o dir.o file.o misc.o main.o read.o remake.o	\
+       rule.o implicit.o default.o variable.o expand.o function.o	\
+       vpath.o version.o ar.o arscan.o signame.o strcache.o hash.o      \
+       remote-$(REMOTE).o $(GLOB) $(GETOPT) $(ALLOCA) $(extras)
+srcs = $(srcdir)commands.c $(srcdir)job.c $(srcdir)dir.c             \
+       $(srcdir)file.c $(srcdir)getloadavg.c $(srcdir)misc.c         \
+       $(srcdir)main.c $(srcdir)read.c $(srcdir)remake.c             \
+       $(srcdir)rule.c $(srcdir)implicit.c $(srcdir)default.c        \
+       $(srcdir)variable.c $(srcdir)expand.c $(srcdir)function.c     \
+       $(srcdir)vpath.c $(srcdir)version.c $(srcdir)hash.c           \
+       $(srcdir)remote-$(REMOTE).c                                     \
+       $(srcdir)ar.c $(srcdir)arscan.c $(srcdir)strcache.c              \
+       $(srcdir)signame.c $(srcdir)signame.h $(GETOPT_SRC)            \
+       $(srcdir)commands.h $(srcdir)dep.h $(srcdir)file.h            \
+       $(srcdir)job.h $(srcdir)make.h $(srcdir)rule.h                \
+       $(srcdir)variable.h $(ALLOCA_SRC) $(srcdir)config.h.in
+
+
+.SUFFIXES:
+.SUFFIXES: .o .c .h .ps .dvi .info .texinfo
+
+all: make
+info: make.info
+dvi: make.dvi
+# Some makes apparently use .PHONY as the default goal if it is before `all'.
+.PHONY: all check info dvi
+
+make.info: make.texinfo
+	$(MAKEINFO) -I$(srcdir) $(srcdir)make.texinfo -o make.info
+
+make.dvi: make.texinfo
+	$(TEXI2DVI) $(srcdir)make.texinfo
+
+make.ps: make.dvi
+	dvi2ps make.dvi > make.ps
+
+make: $(objs) glob/glob.lib
+	$(CC) Link $(LDFLAGS) $(objs) $(LOADLIBES) To make.new
+	-delete quiet make
+	rename make.new make
+
+# -I. is needed to find config.h in the build directory.
+.c.o:
+	$(CC) $(defines) IDir "" IDir $(srcdir)glob \
+	      $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION)
+
+glob/glob.lib:
+	execute <<
+	    cd glob
+	    smake
+<
+
+tagsrcs = $(srcs) $(srcdir)remote-*.c
+TAGS: $(tagsrcs)
+	$(ETAGS) $(tagsrcs)
+tags: $(tagsrcs)
+	$(CTAGS) $(tagsrcs)
+
+.PHONY: install installdirs
+install:
+	copy make sc:c
+
+loadavg: loadavg.c config.h
+	$(CC) $(defines) -DTEST -I. -I$(srcdir) $(CFLAGS) $(LDFLAGS) \
+	      loadavg.c $(LOADLIBES) -o $@
+
+clean: glob-clean
+	-$(RM) -f make loadavg *.o core make.dvi
+
+distclean: clean glob-realclean
+	-$(RM) -f Makefile config.h config.status build.sh
+	-$(RM) -f config.log config.cache
+	-$(RM) -f TAGS tags
+	-$(RM) -f make.?? make.??s make.log make.toc make.*aux
+	-$(RM) -f loadavg.c
+
+realclean: distclean
+	-$(RM) -f make.info*
+
+mostlyclean: clean
+
+.PHONY: glob-clean glob-realclean
+
+glob-clean glob-realclean:
+	execute <<
+	cd glob
+	smake $@
+<
Index: /tags/kBuild-0.1.4/src/kmk/TODO.private
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/TODO.private	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/TODO.private	(revision 1780)
@@ -0,0 +1,146 @@
+                                                            -*-Indented-Text-*-
+GNU Make TODO List
+------------------
+
+This list comes both from the authors and from users of GNU make.
+
+They are listed in no particular order!
+
+Also, I don't gaurantee that all of them will be ultimately deemed "good
+ideas" and implemented.  These are just the ones that, at first blush,
+seem to have some merit (and that I can remember).
+
+However, if you see something here you really, really want, speak up.
+All other things being equal, I will tend to implement things that seem
+to maximize user satisfaction.
+
+If you want to implement some of them yourself, barring the ones I've
+marked below, have at it!  Please contact me first to let me know you're
+working on it, and give me some info about the design--and, critically,
+information about any user-visible syntax change, etc.
+
+
+The Top Item
+------------
+
+If you know perl (or want to learn DejaGNU or similar), the number one
+priority on my list of things I don't have time to do right now is
+fixing up the GNU make test suite.  Most importantly it needs to be made
+"parallelizable", so more than one regression can run at the same time
+(essentially, make the "work" directory local).  Also, the CWD during
+the test should be in the work directory or, better, a test-specific
+temporary directory so each test gets a new directory; right now
+sometimes tests leak files into the main directory which causes
+subsequent tests to fail (some tests may need to be tweaked).  Beyond
+that, any cleanup done to make writing, reading, or handling tests
+simpler would be great!  Please feel free to make whatever changes you
+like to the current tests, given some high-level goals, and that you'll
+port the current tests to whatever you do :).
+
+
+The Rest of the List
+--------------------
+
+ 1) Option to check more than timestamps to determine if targets have
+    changed.  This is also a very big one.  It's _close_ to my plate :),
+    and I have very definite ideas about how I would like it done.
+    Please pick something else unless you must have this feature.  If
+    you try it, please work _extremely_ closely with me on it.
+
+ 1a) Possibly a special case of this is the .KEEP_STATE feature of Sun's
+     make.  Some great folks at W U. in Canada did an implementation of
+     this for a class project.  Their approach is reasonable and
+     workable, but doesn't really fit into my ideas for #2.  Maybe
+     that's OK.  I have paperwork for their work so if you want to do
+     this one talk to me to get what they've already done.
+
+     [K R Praveen <praveen@cair.res.in>]
+
+ 2) Currently you can use "%.foo %.bar : %.baz" to mean that one
+    invocation of the rule builds both targets.  GNU make needs a way to
+    do that for explicit rules, too.  I heard a rumor that some versions
+    of make all you to say "a.foo + a.bar : a.baz" to do this (i.e., a
+    "+" means one invocation builds both).  Don't know if this is the
+    best syntax or not... what if you say "a.foo + a.bar a.bam : a.baz";
+    what does that mean?
+
+ 3) Multi-token pattern rule matching (allow %1/%2.c : %1/obj/%2.o,
+    etc., or something like that).  I have an implementation of this
+    already, it just needs some refinement... maybe.  Additionally I
+    think it only works for static pattern rules; it might need to be
+    fixed up to work with normal pattern rules, too.
+
+ 4) Provide a .TARGETS variable, containing the names of the targets
+    defined in the makefile.
+
+    Actually, I now think a $(targets ...) function, at least, might be
+    better than a MAKETARGETS variable.  The argument would be types of
+    targets to list: "phony" is the most useful one.  I suppose
+    "default" might also be useful.  Maybe some others; check the
+    bitfields to see what might be handy.
+
+ 5) Some sort of operating-system independent way of handling paths
+    would be outstanding, so makefiles can be written for UNIX, VMS,
+    DOS, MS-Windows, Amiga, etc. with a minimum of specialization.
+
+    Or, perhaps related/instead of, some sort of meta-quoting syntax so
+    make can deal with filenames containing spaces, colons, etc.  I
+    dunno, maybe something like $[...]?  This may well not be worth
+    doing until #1 is done.
+
+ 6) Right now the .PRECIOUS, .INTERMEDIATE, and .SECONDARY
+    pseudo-targets have different capabilities.  For example, .PRECIOUS
+    can take a "%", the others can't.  Etc.  These should all work the
+    same, insofar as that makes sense.
+
+ 7) Improved debugging/logging/etc. capabilities.  Part of this is done:
+    I introduced a number of debugging enhancements.  Tim Magill is (I
+    think) looking into options to control output more selectively.
+    One thing I want to do in debugging is add a flag to allow debugging
+    of variables as they're expanded (!).  This would be incredibly
+    verbose, but could be invaluable when nothing else seems to work and
+    you just can't figure it out.  The way variables are expanded now
+    means this isn't 100% trivial, but it probably won't be hard.
+
+ 8) Integration of Guile as an embedded scripting language.  This means:
+    allowing Guile functions to be declared in makefiles somehow, then
+    providing a syntax for invoking them.  At least one formulation of
+    that would have the function resolve to a string which would be
+    substituted in the makefile, kind of like $(shell ...) does now, but
+    using the embedded interpreter so there's no process forked of
+    course.  Obviously this is an optional add-on feature.
+
+    It could be more advanced than that, even, who knows?  Maybe make
+    could provide Guile functions that allow Guile scripts more direct
+    access to internal make structures, somehow.  This kind of thing
+    needs a lot of thought.
+
+    Also there's always the flip side: in some very fundamental ways
+    make isn't the best choice right now for a complex build tool.  It's
+    great for simple-to-medium tasks, but there are already other tools
+    available for the really tough situations.  Ask yourself,
+    realistically, how much work is worthwhile to add to make, given the
+    fundamentals you can't really overcome without significantly
+    affecting backward compatibility--and then why not use another tool
+    in the first place?
+
+    Something to think about.
+
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free
+Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/acinclude.m4
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/acinclude.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/acinclude.m4	(revision 1780)
@@ -0,0 +1,132 @@
+dnl acinclude.m4 -- Extra macros needed for GNU make.
+dnl
+dnl Automake will incorporate this into its generated aclocal.m4.
+dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+dnl Free Software Foundation, Inc.
+dnl This file is part of GNU Make.
+dnl
+dnl GNU Make is free software; you can redistribute it and/or modify it
+dnl under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Make is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Make; see the file COPYING.  If not, write to the
+dnl Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+dnl MA 02110-1301 USA.
+
+
+dnl ---------------------------------------------------------------------------
+dnl Got this from the lynx 2.8 distribution.
+dnl by T.E.Dickey <dickey@clark.net>
+dnl and Jim Spath <jspath@mail.bcpl.lib.md.us>
+dnl and Philippe De Muyter <phdm@macqel.be>
+dnl
+dnl Created: 1997/1/28
+dnl Updated: 1997/12/23
+dnl ---------------------------------------------------------------------------
+dnl After checking for functions in the default $LIBS, make a further check
+dnl for the functions that are netlib-related (these aren't always in the
+dnl libc, etc., and have to be handled specially because there are conflicting
+dnl and broken implementations.
+dnl Common library requirements (in order):
+dnl	-lresolv -lsocket -lnsl
+dnl	-lnsl -lsocket
+dnl	-lsocket
+dnl	-lbsd
+AC_DEFUN([CF_NETLIBS],[
+cf_test_netlibs=no
+AC_MSG_CHECKING(for network libraries)
+AC_CACHE_VAL(cf_cv_netlibs,[
+AC_MSG_RESULT(working...)
+cf_cv_netlibs=""
+cf_test_netlibs=yes
+AC_CHECK_FUNCS(gethostname,,[
+	CF_RECHECK_FUNC(gethostname,nsl,cf_cv_netlibs,[
+		CF_RECHECK_FUNC(gethostname,socket,cf_cv_netlibs)])])
+#
+# FIXME:  sequent needs this library (i.e., -lsocket -linet -lnsl), but
+# I don't know the entrypoints - 97/7/22 TD
+AC_CHECK_LIB(inet,main,cf_cv_netlibs="-linet $cf_cv_netlibs")
+#
+if test "$ac_cv_func_lsocket" != no ; then
+AC_CHECK_FUNCS(socket,,[
+	CF_RECHECK_FUNC(socket,socket,cf_cv_netlibs,[
+		CF_RECHECK_FUNC(socket,bsd,cf_cv_netlibs)])])
+fi
+#
+AC_CHECK_FUNCS(gethostbyname,,[
+	CF_RECHECK_FUNC(gethostbyname,nsl,cf_cv_netlibs)])
+])
+LIBS="$LIBS $cf_cv_netlibs"
+test $cf_test_netlibs = no && echo "$cf_cv_netlibs" >&AC_FD_MSG
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Re-check on a function to see if we can pick it up by adding a library.
+dnl	$1 = function to check
+dnl	$2 = library to check in
+dnl	$3 = environment to update (e.g., $LIBS)
+dnl	$4 = what to do if this fails
+dnl
+dnl This uses 'unset' if the shell happens to support it, but leaves the
+dnl configuration variable set to 'unknown' if not.  This is a little better
+dnl than the normal autoconf test, which gives misleading results if a test
+dnl for the function is made (e.g., with AC_CHECK_FUNC) after this macro is
+dnl used (autoconf does not distinguish between a null token and one that is
+dnl set to 'no').
+AC_DEFUN([CF_RECHECK_FUNC],[
+AC_CHECK_LIB($2,$1,[
+	CF_UPPER(cf_tr_func,$1)
+	AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func,1,[Define if you have function $1])
+	ac_cv_func_$1=yes
+	$3="-l$2 [$]$3"],[
+	ac_cv_func_$1=unknown
+	unset ac_cv_func_$1 2>/dev/null
+	$4],
+	[[$]$3])
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Make an uppercase version of a variable
+dnl $1=uppercase($2)
+AC_DEFUN([CF_UPPER],
+[
+changequote(,)dnl
+$1=`echo $2 | tr '[a-z]' '[A-Z]'`
+changequote([,])dnl
+])dnl
+
+
+dnl ---------------------------------------------------------------------------
+dnl From Paul Eggert <eggert@twinsun.com>
+
+AC_DEFUN([AC_STRUCT_ST_MTIM_NSEC],
+ [AC_CACHE_CHECK([for nanoseconds field of struct stat.st_mtim],
+   ac_cv_struct_st_mtim_nsec,
+   [ac_save_CPPFLAGS="$CPPFLAGS"
+    ac_cv_struct_st_mtim_nsec=no
+    # tv_nsec -- the usual case
+    # _tv_nsec -- Solaris 2.6, if
+    #	(defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1
+    #	 && !defined __EXTENSIONS__)
+    # st__tim.tv_nsec -- UnixWare 2.1.2
+    for ac_val in tv_nsec _tv_nsec st__tim.tv_nsec; do
+      CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val"
+      AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/stat.h>
+	], [struct stat s; s.st_mtim.ST_MTIM_NSEC;],
+        [ac_cv_struct_st_mtim_nsec=$ac_val; break])
+    done
+    CPPFLAGS="$ac_save_CPPFLAGS"
+   ])
+
+  if test $ac_cv_struct_st_mtim_nsec != no; then
+    AC_DEFINE_UNQUOTED([ST_MTIM_NSEC], [$ac_cv_struct_st_mtim_nsec],
+	[Define if struct stat contains a nanoseconds field])
+  fi
+ ]
+)
Index: /tags/kBuild-0.1.4/src/kmk/alloca.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/alloca.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/alloca.c	(revision 1780)
@@ -0,0 +1,503 @@
+/* alloca.c -- allocate automatically reclaimed memory
+   (Mostly) portable public-domain implementation -- D A Gwyn
+
+   This implementation of the PWB library alloca function,
+   which is used to allocate space off the run-time stack so
+   that it is automatically reclaimed upon procedure exit,
+   was inspired by discussions with J. Q. Johnson of Cornell.
+   J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+   There are some preprocessor constants that can
+   be defined when compiling for your specific system, for
+   improved efficiency; however, the defaults should be okay.
+
+   The general concept of this implementation is to keep
+   track of all alloca-allocated blocks, and reclaim any
+   that are found to be deeper in the stack than the current
+   invocation.  This heuristic does not reclaim storage as
+   soon as it becomes invalid, but it will do so eventually.
+
+   As a special case, alloca(0) reclaims storage without
+   allocating any.  It is a good idea to use alloca(0) in
+   your main control loop, etc. to force garbage collection.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef emacs
+#include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed.  */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+   there must be some other way alloca is supposed to work.  */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+   provide an "address metric" ADDRESS_FUNCTION macro.  */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#ifndef NULL
+#define	NULL	0
+#endif
+
+/* Different portions of Emacs need to call different versions of
+   malloc.  The Emacs executable needs alloca to call xmalloc, because
+   ordinary malloc isn't protected from input signals.  On the other
+   hand, the utilities in lib-src need alloca to call malloc; some of
+   them are very simple, and don't have an xmalloc routine.
+
+   Non-Emacs programs expect this to call use xmalloc.
+
+   Callers below should use malloc.  */
+
+#ifndef emacs
+#define malloc xmalloc
+#endif
+extern pointer malloc ();
+
+/* Define STACK_DIRECTION if you know the direction of stack
+   growth for your system; otherwise it will be automatically
+   deduced at run-time.
+
+   STACK_DIRECTION > 0 => grows toward higher addresses
+   STACK_DIRECTION < 0 => grows toward lower addresses
+   STACK_DIRECTION = 0 => direction of growth unknown  */
+
+#ifndef STACK_DIRECTION
+#define	STACK_DIRECTION	0	/* Direction unknown.  */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define	STACK_DIR	STACK_DIRECTION	/* Known at compile-time.  */
+
+#else /* STACK_DIRECTION == 0; need run-time code.  */
+
+static int stack_dir;		/* 1 or -1 once known.  */
+#define	STACK_DIR	stack_dir
+
+static void
+find_stack_direction (void)
+{
+  static char *addr = NULL;	/* Address of first `dummy', once known.  */
+  auto char dummy;		/* To get stack address.  */
+
+  if (addr == NULL)
+    {				/* Initial entry.  */
+      addr = ADDRESS_FUNCTION (dummy);
+
+      find_stack_direction ();	/* Recurse once.  */
+    }
+  else
+    {
+      /* Second entry.  */
+      if (ADDRESS_FUNCTION (dummy) > addr)
+	stack_dir = 1;		/* Stack grew upward.  */
+      else
+	stack_dir = -1;		/* Stack grew downward.  */
+    }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+   (a) chain together all alloca'ed blocks;
+   (b) keep track of stack depth.
+
+   It is very important that sizeof(header) agree with malloc
+   alignment chunk size.  The following default should work okay.  */
+
+#ifndef	ALIGN_SIZE
+#define	ALIGN_SIZE	sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];	/* To force sizeof(header).  */
+  struct
+    {
+      union hdr *next;		/* For chaining headers.  */
+      char *deep;		/* For stack depth measure.  */
+    } h;
+} header;
+
+static header *last_alloca_header = NULL;	/* -> last alloca header.  */
+
+/* Return a pointer to at least SIZE bytes of storage,
+   which will be automatically reclaimed upon exit from
+   the procedure that called alloca.  Originally, this space
+   was supposed to be taken from the current stack frame of the
+   caller, but that method cannot be made to work for some
+   implementations of C, for example under Gould's UTX/32.  */
+
+pointer
+alloca (unsigned size)
+{
+  auto char probe;		/* Probes stack depth: */
+  register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)		/* Unknown growth direction.  */
+    find_stack_direction ();
+#endif
+
+  /* Reclaim garbage, defined as all alloca'd storage that
+     was allocated from deeper in the stack than currently.  */
+
+  {
+    register header *hp;	/* Traverses linked list.  */
+
+#ifdef emacs
+    BLOCK_INPUT;
+#endif
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if ((STACK_DIR > 0 && hp->h.deep > depth)
+	  || (STACK_DIR < 0 && hp->h.deep < depth))
+	{
+	  register header *np = hp->h.next;
+
+	  free ((pointer) hp);	/* Collect garbage.  */
+
+	  hp = np;		/* -> next header.  */
+	}
+      else
+	break;			/* Rest are not deeper.  */
+
+    last_alloca_header = hp;	/* -> last valid storage.  */
+
+#ifdef emacs
+    UNBLOCK_INPUT;
+#endif
+  }
+
+  if (size == 0)
+    return NULL;		/* No allocation required.  */
+
+  /* Allocate combined header + user data storage.  */
+
+  {
+    register pointer new = malloc (sizeof (header) + size);
+    /* Address of header.  */
+
+    if (new == 0)
+      abort();
+
+    ((header *) new)->h.next = last_alloca_header;
+    ((header *) new)->h.deep = depth;
+
+    last_alloca_header = (header *) new;
+
+    /* User storage begins just after header.  */
+
+    return (pointer) ((char *) new + sizeof (header));
+  }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+  {
+    long shgrow:32;		/* Number of times stack has grown.  */
+    long shaseg:32;		/* Size of increments to stack.  */
+    long shhwm:32;		/* High water mark of stack.  */
+    long shsize:32;		/* Current size of stack (all segments).  */
+  };
+
+/* The stack segment linkage control information occurs at
+   the high-address end of a stack segment.  (The stack
+   grows from low addresses to high addresses.)  The initial
+   part of the stack segment linkage control information is
+   0200 (octal) words.  This provides for register storage
+   for the routine which overflows the stack.  */
+
+struct stack_segment_linkage
+  {
+    long ss[0200];		/* 0200 overflow words.  */
+    long sssize:32;		/* Number of words in this segment.  */
+    long ssbase:32;		/* Offset to stack base.  */
+    long:32;
+    long sspseg:32;		/* Offset to linkage control of previous
+				   segment of stack.  */
+    long:32;
+    long sstcpt:32;		/* Pointer to task common address block.  */
+    long sscsnm;		/* Private control structure number for
+				   microtasking.  */
+    long ssusr1;		/* Reserved for user.  */
+    long ssusr2;		/* Reserved for user.  */
+    long sstpid;		/* Process ID for pid based multi-tasking.  */
+    long ssgvup;		/* Pointer to multitasking thread giveup.  */
+    long sscray[7];		/* Reserved for Cray Research.  */
+    long ssa0;
+    long ssa1;
+    long ssa2;
+    long ssa3;
+    long ssa4;
+    long ssa5;
+    long ssa6;
+    long ssa7;
+    long sss0;
+    long sss1;
+    long sss2;
+    long sss3;
+    long sss4;
+    long sss5;
+    long sss6;
+    long sss7;
+  };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+   returned by the STKSTAT library routine.  */
+struct stk_stat
+  {
+    long now;			/* Current total stack size.  */
+    long maxc;			/* Amount of contiguous space which would
+				   be required to satisfy the maximum
+				   stack demand to date.  */
+    long high_water;		/* Stack high-water mark.  */
+    long overflows;		/* Number of stack overflow ($STKOFEN) calls.  */
+    long hits;			/* Number of internal buffer hits.  */
+    long extends;		/* Number of block extensions.  */
+    long stko_mallocs;		/* Block allocations by $STKOFEN.  */
+    long underflows;		/* Number of stack underflow calls ($STKRETN).  */
+    long stko_free;		/* Number of deallocations by $STKRETN.  */
+    long stkm_free;		/* Number of deallocations by $STKMRET.  */
+    long segments;		/* Current number of stack segments.  */
+    long maxs;			/* Maximum number of stack segments so far.  */
+    long pad_size;		/* Stack pad size.  */
+    long current_address;	/* Current stack segment address.  */
+    long current_size;		/* Current stack segment size.  This
+				   number is actually corrupted by STKSTAT to
+				   include the fifteen word trailer area.  */
+    long initial_address;	/* Address of initial segment.  */
+    long initial_size;		/* Size of initial segment.  */
+  };
+
+/* The following structure describes the data structure which trails
+   any stack segment.  I think that the description in 'asdef' is
+   out of date.  I only describe the parts that I am sure about.  */
+
+struct stk_trailer
+  {
+    long this_address;		/* Address of this block.  */
+    long this_size;		/* Size of this block (does not include
+				   this trailer).  */
+    long unknown2;
+    long unknown3;
+    long link;			/* Address of trailer block of previous
+				   segment.  */
+    long unknown5;
+    long unknown6;
+    long unknown7;
+    long unknown8;
+    long unknown9;
+    long unknown10;
+    long unknown11;
+    long unknown12;
+    long unknown13;
+    long unknown14;
+  };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+   I doubt that "lint" will like this much.  */
+
+static long
+i00afunc (long *address)
+{
+  struct stk_stat status;
+  struct stk_trailer *trailer;
+  long *block, size;
+  long result = 0;
+
+  /* We want to iterate through all of the segments.  The first
+     step is to get the stack status structure.  We could do this
+     more quickly and more directly, perhaps, by referencing the
+     $LM00 common block, but I know that this works.  */
+
+  STKSTAT (&status);
+
+  /* Set up the iteration.  */
+
+  trailer = (struct stk_trailer *) (status.current_address
+				    + status.current_size
+				    - 15);
+
+  /* There must be at least one stack segment.  Therefore it is
+     a fatal error if "trailer" is null.  */
+
+  if (trailer == 0)
+    abort ();
+
+  /* Discard segments that do not contain our argument address.  */
+
+  while (trailer != 0)
+    {
+      block = (long *) trailer->this_address;
+      size = trailer->this_size;
+      if (block == 0 || size == 0)
+	abort ();
+      trailer = (struct stk_trailer *) trailer->link;
+      if ((block <= address) && (address < (block + size)))
+	break;
+    }
+
+  /* Set the result to the offset in this segment and add the sizes
+     of all predecessor segments.  */
+
+  result = address - block;
+
+  if (trailer == 0)
+    {
+      return result;
+    }
+
+  do
+    {
+      if (trailer->this_size <= 0)
+	abort ();
+      result += trailer->this_size;
+      trailer = (struct stk_trailer *) trailer->link;
+    }
+  while (trailer != 0);
+
+  /* We are done.  Note that if you present a bogus address (one
+     not in any segment), you will get a different number back, formed
+     from subtracting the address of the first block.  This is probably
+     not what you want.  */
+
+  return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+   Determine the number of the cell within the stack,
+   given the address of the cell.  The purpose of this
+   routine is to linearize, in some sense, stack addresses
+   for alloca.  */
+
+static long
+i00afunc (long address)
+{
+  long stkl = 0;
+
+  long size, pseg, this_segment, stack;
+  long result = 0;
+
+  struct stack_segment_linkage *ssptr;
+
+  /* Register B67 contains the address of the end of the
+     current stack segment.  If you (as a subprogram) store
+     your registers on the stack and find that you are past
+     the contents of B67, you have overflowed the segment.
+
+     B67 also points to the stack segment linkage control
+     area, which is what we are really interested in.  */
+
+  stkl = CRAY_STACKSEG_END ();
+  ssptr = (struct stack_segment_linkage *) stkl;
+
+  /* If one subtracts 'size' from the end of the segment,
+     one has the address of the first word of the segment.
+
+     If this is not the first segment, 'pseg' will be
+     nonzero.  */
+
+  pseg = ssptr->sspseg;
+  size = ssptr->sssize;
+
+  this_segment = stkl - size;
+
+  /* It is possible that calling this routine itself caused
+     a stack overflow.  Discard stack segments which do not
+     contain the target address.  */
+
+  while (!(this_segment <= address && address <= stkl))
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+      if (pseg == 0)
+	break;
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      this_segment = stkl - size;
+    }
+
+  result = address - this_segment;
+
+  /* If you subtract pseg from the current end of the stack,
+     you get the address of the previous stack segment's end.
+     This seems a little convoluted to me, but I'll bet you save
+     a cycle somewhere.  */
+
+  while (pseg != 0)
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      result += size;
+    }
+  return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY */
+
+#endif /* no alloca */
+#endif /* not GCC version 2 */
Index: /tags/kBuild-0.1.4/src/kmk/amiga.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/amiga.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/amiga.c	(revision 1780)
@@ -0,0 +1,119 @@
+/* Running commands on Amiga
+Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "variable.h"
+#include "amiga.h"
+#include <assert.h>
+#include <exec/memory.h>
+#include <dos/dostags.h>
+#include <proto/exec.h>
+#include <proto/dos.h>
+
+static const char Amiga_version[] = "$VER: Make 3.74.3 (12.05.96) \n"
+		    "Amiga Port by A. Digulla (digulla@home.lake.de)";
+
+int
+MyExecute (char **argv)
+{
+    char * buffer, * ptr;
+    char ** aptr;
+    int len = 0;
+    int status;
+
+    for (aptr=argv; *aptr; aptr++)
+    {
+	len += strlen (*aptr) + 4;
+    }
+
+    buffer = AllocMem (len, MEMF_ANY);
+
+    if (!buffer)
+      fatal (NILF, "MyExecute: Cannot allocate space for calling a command");
+
+    ptr = buffer;
+
+    for (aptr=argv; *aptr; aptr++)
+    {
+	if (((*aptr)[0] == ';' && !(*aptr)[1]))
+	{
+	    *ptr ++ = '"';
+	    strcpy (ptr, *aptr);
+	    ptr += strlen (ptr);
+	    *ptr ++ = '"';
+	}
+	else if ((*aptr)[0] == '@' && (*aptr)[1] == '@' && !(*aptr)[2])
+	{
+	    *ptr ++ = '\n';
+	    continue;
+	}
+	else
+	{
+	    strcpy (ptr, *aptr);
+	    ptr += strlen (ptr);
+	}
+	*ptr ++ = ' ';
+	*ptr = 0;
+    }
+
+    ptr[-1] = '\n';
+
+    status = SystemTags (buffer,
+	SYS_UserShell, TRUE,
+	TAG_END);
+
+    FreeMem (buffer, len);
+
+    if (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
+	status = 20;
+
+    /* Warnings don't count */
+    if (status == 5)
+	status = 0;
+
+    return status;
+}
+
+char *
+wildcard_expansion (char *wc, char *o)
+{
+#   define PATH_SIZE	1024
+    struct AnchorPath * apath;
+
+    if ( (apath = AllocMem (sizeof (struct AnchorPath) + PATH_SIZE,
+	    MEMF_CLEAR))
+	)
+    {
+	apath->ap_Strlen = PATH_SIZE;
+
+	if (MatchFirst (wc, apath) == 0)
+	{
+	    do
+	    {
+		o = variable_buffer_output (o, apath->ap_Buf,
+			strlen (apath->ap_Buf));
+		o = variable_buffer_output (o, " ",1);
+	    } while (MatchNext (apath) == 0);
+	}
+
+	MatchEnd (apath);
+	FreeMem (apath, sizeof (struct AnchorPath) + PATH_SIZE);
+    }
+
+    return o;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/amiga.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/amiga.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/amiga.h	(revision 1780)
@@ -0,0 +1,19 @@
+/* Definitions for amiga specific things
+Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+int MyExecute (char ** argv);
+char * wildcard_expansion (char * wc, char * o);
Index: /tags/kBuild-0.1.4/src/kmk/ar.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/ar.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/ar.c	(revision 1780)
@@ -0,0 +1,293 @@
+/* Interface to `ar' archives for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#ifndef	NO_ARCHIVES
+
+#include "filedef.h"
+#include "dep.h"
+#include <fnmatch.h>
+
+/* Return nonzero if NAME is an archive-member reference, zero if not.
+   An archive-member reference is a name like `lib(member)'.
+   If a name like `lib((entry))' is used, a fatal error is signaled at
+   the attempt to use this unsupported feature.  */
+
+int
+ar_name (const char *name)
+{
+  const char *p = strchr (name, '(');
+  const char *end;
+
+  if (p == 0 || p == name)
+    return 0;
+
+  end = p + strlen (p) - 1;
+  if (*end != ')')
+    return 0;
+
+  if (p[1] == '(' && end[-1] == ')')
+    fatal (NILF, _("attempt to use unsupported feature: `%s'"), name);
+
+  return 1;
+}
+
+
+/* Parse the archive-member reference NAME into the archive and member names.
+   Creates one allocated string containing both names, pointed to by ARNAME_P.
+   MEMNAME_P points to the member.  */
+
+void
+ar_parse_name (const char *name, char **arname_p, char **memname_p)
+{
+  char *p;
+
+  *arname_p = xstrdup (name);
+  p = strchr (*arname_p, '(');
+  *(p++) = '\0';
+  p[strlen(p) - 1] = '\0';
+  *memname_p = p;
+}
+
+
+
+/* This function is called by `ar_scan' to find which member to look at.  */
+
+/* ARGSUSED */
+static long int
+ar_member_date_1 (int desc UNUSED, const char *mem, int truncated,
+		  long int hdrpos UNUSED, long int datapos UNUSED,
+                  long int size UNUSED, long int date,
+                  int uid UNUSED, int gid UNUSED, int mode UNUSED,
+		  const void *name)
+{
+  return ar_name_equal (name, mem, truncated) ? date : 0;
+}
+
+/* Return the modtime of NAME.  */
+
+time_t
+ar_member_date (const char *name)
+{
+  char *arname;
+  char *memname;
+  long int val;
+
+  ar_parse_name (name, &arname, &memname);
+
+  /* Make sure we know the modtime of the archive itself because we are
+     likely to be called just before commands to remake a member are run,
+     and they will change the archive itself.
+
+     But we must be careful not to enter_file the archive itself if it does
+     not exist, because pattern_search assumes that files found in the data
+     base exist or can be made.  */
+  {
+    struct file *arfile;
+    arfile = lookup_file (arname);
+    if (arfile == 0 && file_exists_p (arname))
+      arfile = enter_file (strcache_add (arname));
+
+    if (arfile != 0)
+      (void) f_mtime (arfile, 0);
+  }
+
+  val = ar_scan (arname, ar_member_date_1, memname);
+
+  free (arname);
+
+  return (val <= 0 ? (time_t) -1 : (time_t) val);
+}
+
+
+/* Set the archive-member NAME's modtime to now.  */
+
+#ifdef VMS
+int
+ar_touch (const char *name)
+{
+  error (NILF, _("touch archive member is not available on VMS"));
+  return -1;
+}
+#else
+int
+ar_touch (const char *name)
+{
+  char *arname, *memname;
+  int val;
+
+  ar_parse_name (name, &arname, &memname);
+
+  /* Make sure we know the modtime of the archive itself before we
+     touch the member, since this will change the archive modtime.  */
+  {
+    struct file *arfile;
+    arfile = enter_file (strcache_add (arname));
+    f_mtime (arfile, 0);
+  }
+
+  val = 1;
+  switch (ar_member_touch (arname, memname))
+    {
+    case -1:
+      error (NILF, _("touch: Archive `%s' does not exist"), arname);
+      break;
+    case -2:
+      error (NILF, _("touch: `%s' is not a valid archive"), arname);
+      break;
+    case -3:
+      perror_with_name ("touch: ", arname);
+      break;
+    case 1:
+      error (NILF,
+             _("touch: Member `%s' does not exist in `%s'"), memname, arname);
+      break;
+    case 0:
+      val = 0;
+      break;
+    default:
+      error (NILF,
+             _("touch: Bad return code from ar_member_touch on `%s'"), name);
+    }
+
+  free (arname);
+
+  return val;
+}
+#endif /* !VMS */
+
+
+/* State of an `ar_glob' run, passed to `ar_glob_match'.  */
+
+struct ar_glob_state
+  {
+    const char *arname;
+    const char *pattern;
+    unsigned int size;
+    struct nameseq *chain;
+    unsigned int n;
+  };
+
+/* This function is called by `ar_scan' to match one archive
+   element against the pattern in STATE.  */
+
+static long int
+ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED,
+	       long int hdrpos UNUSED, long int datapos UNUSED,
+               long int size UNUSED, long int date UNUSED, int uid UNUSED,
+               int gid UNUSED, int mode UNUSED, const void *arg)
+{
+  struct ar_glob_state *state = (struct ar_glob_state *)arg;
+
+  if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0)
+    {
+      /* We have a match.  Add it to the chain.  */
+      struct nameseq *new = xmalloc (state->size);
+      new->name = strcache_add (concat (state->arname, mem, ")"));
+      new->next = state->chain;
+      state->chain = new;
+      ++state->n;
+    }
+
+  return 0L;
+}
+
+/* Return nonzero if PATTERN contains any metacharacters.
+   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
+static int
+glob_pattern_p (const char *pattern, int quote)
+{
+  const char *p;
+  int open = 0;
+
+  for (p = pattern; *p != '\0'; ++p)
+    switch (*p)
+      {
+      case '?':
+      case '*':
+	return 1;
+
+      case '\\':
+	if (quote)
+	  ++p;
+	break;
+
+      case '[':
+	open = 1;
+	break;
+
+      case ']':
+	if (open)
+	  return 1;
+	break;
+      }
+
+  return 0;
+}
+
+/* Glob for MEMBER_PATTERN in archive ARNAME.
+   Return a malloc'd chain of matching elements (or nil if none).  */
+
+struct nameseq *
+ar_glob (const char *arname, const char *member_pattern, unsigned int size)
+{
+  struct ar_glob_state state;
+  struct nameseq *n;
+  const char **names;
+  char *name;
+  unsigned int i;
+
+  if (! glob_pattern_p (member_pattern, 1))
+    return 0;
+
+  /* Scan the archive for matches.
+     ar_glob_match will accumulate them in STATE.chain.  */
+  i = strlen (arname);
+  name = alloca (i + 2);
+  memcpy (name, arname, i);
+  name[i] = '(';
+  name[i + 1] = '\0';
+  state.arname = name;
+  state.pattern = member_pattern;
+  state.size = size;
+  state.chain = 0;
+  state.n = 0;
+  ar_scan (arname, ar_glob_match, &state);
+
+  if (state.chain == 0)
+    return 0;
+
+  /* Now put the names into a vector for sorting.  */
+  names = alloca (state.n * sizeof (const char *));
+  i = 0;
+  for (n = state.chain; n != 0; n = n->next)
+    names[i++] = n->name;
+
+  /* Sort them alphabetically.  */
+  qsort (names, i, sizeof (*names), alpha_compare);
+
+  /* Put them back into the chain in the sorted order.  */
+  i = 0;
+  for (n = state.chain; n != 0; n = n->next)
+    n->name = names[i++];
+
+  return state.chain;
+}
+
+#endif	/* Not NO_ARCHIVES.  */
Index: /tags/kBuild-0.1.4/src/kmk/arscan.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/arscan.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/arscan.c	(revision 1780)
@@ -0,0 +1,846 @@
+/* Library function for scanning an archive file.
+Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#include <sys/file.h>
+#endif
+
+#ifndef	NO_ARCHIVES
+
+#ifdef VMS
+#include <lbrdef.h>
+#include <mhddef.h>
+#include <credef.h>
+#include <descrip.h>
+#include <ctype.h>
+#if __DECC
+#include <unixlib.h>
+#include <lbr$routines.h>
+#endif
+
+static void *VMS_lib_idx;
+
+static char *VMS_saved_memname;
+
+static time_t VMS_member_date;
+
+static long int (*VMS_function) ();
+
+static int
+VMS_get_member_info (struct dsc$descriptor_s *module, unsigned long *rfa)
+{
+  int status, i;
+  long int fnval;
+
+  time_t val;
+
+  static struct dsc$descriptor_s bufdesc =
+    { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
+
+  struct mhddef *mhd;
+  char filename[128];
+
+  bufdesc.dsc$a_pointer = filename;
+  bufdesc.dsc$w_length = sizeof (filename);
+
+  status = lbr$set_module (&VMS_lib_idx, rfa, &bufdesc,
+			   &bufdesc.dsc$w_length, 0);
+  if (! (status & 1))
+    {
+      error (NILF, _("lbr$set_module failed to extract module info, status = %d"),
+	     status);
+
+      lbr$close (&VMS_lib_idx);
+
+      return 0;
+    }
+
+  mhd = (struct mhddef *) filename;
+
+#ifdef __DECC
+  /* John Fowler <jfowler@nyx.net> writes this is needed in his environment,
+   * but that decc$fix_time() isn't documented to work this way.  Let me
+   * know if this causes problems in other VMS environments.
+   */
+  val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600;
+#endif
+
+  for (i = 0; i < module->dsc$w_length; i++)
+    filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]);
+
+  filename[i] = '\0';
+
+  VMS_member_date = (time_t) -1;
+
+  fnval =
+    (*VMS_function) (-1, filename, 0, 0, 0, 0, val, 0, 0, 0,
+		     VMS_saved_memname);
+
+  if (fnval)
+    {
+      VMS_member_date = fnval;
+      return 0;
+    }
+  else
+    return 1;
+}
+
+/* Takes three arguments ARCHIVE, FUNCTION and ARG.
+
+   Open the archive named ARCHIVE, find its members one by one,
+   and for each one call FUNCTION with the following arguments:
+     archive file descriptor for reading the data,
+     member name,
+     member name might be truncated flag,
+     member header position in file,
+     member data position in file,
+     member data size,
+     member date,
+     member uid,
+     member gid,
+     member protection mode,
+     ARG.
+
+   NOTE: on VMS systems, only name, date, and arg are meaningful!
+
+   The descriptor is poised to read the data of the member
+   when FUNCTION is called.  It does not matter how much
+   data FUNCTION reads.
+
+   If FUNCTION returns nonzero, we immediately return
+   what FUNCTION returned.
+
+   Returns -1 if archive does not exist,
+   Returns -2 if archive has invalid format.
+   Returns 0 if have scanned successfully.  */
+
+long int
+ar_scan (const char *archive, ar_member_func_t function, const void *arg)
+{
+  char *p;
+
+  static struct dsc$descriptor_s libdesc =
+    { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
+
+  unsigned long func = LBR$C_READ;
+  unsigned long type = LBR$C_TYP_UNK;
+  unsigned long index = 1;
+
+  int status;
+
+  status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0);
+
+  if (! (status & 1))
+    {
+      error (NILF, _("lbr$ini_control failed with status = %d"),status);
+      return -2;
+    }
+
+  libdesc.dsc$a_pointer = archive;
+  libdesc.dsc$w_length = strlen (archive);
+
+  status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0);
+
+  if (! (status & 1))
+    {
+      error (NILF, _("unable to open library `%s' to lookup member `%s'"),
+	     archive, (char *)arg);
+      return -1;
+    }
+
+  VMS_saved_memname = (char *)arg;
+
+  /* For comparison, delete .obj from arg name.  */
+
+  p = strrchr (VMS_saved_memname, '.');
+  if (p)
+    *p = '\0';
+
+  VMS_function = function;
+
+  VMS_member_date = (time_t) -1;
+  lbr$get_index (&VMS_lib_idx, &index, VMS_get_member_info, 0);
+
+  /* Undo the damage.  */
+  if (p)
+    *p = '.';
+
+  lbr$close (&VMS_lib_idx);
+
+  return VMS_member_date > 0 ? VMS_member_date : 0;
+}
+
+#else /* !VMS */
+
+/* SCO Unix's compiler defines both of these.  */
+#ifdef	M_UNIX
+#undef	M_XENIX
+#endif
+
+/* On the sun386i and in System V rel 3, ar.h defines two different archive
+   formats depending upon whether you have defined PORTAR (normal) or PORT5AR
+   (System V Release 1).  There is no default, one or the other must be defined
+   to have a nonzero value.  */
+
+#if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
+#undef	PORTAR
+#ifdef M_XENIX
+/* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
+   PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
+   right one.  */
+#define PORTAR 0
+#else
+#define PORTAR 1
+#endif
+#endif
+
+/* On AIX, define these symbols to be sure to get both archive formats.
+   AIX 4.3 introduced the "big" archive format to support 64-bit object
+   files, so on AIX 4.3 systems we need to support both the "normal" and
+   "big" archive formats.  An archive's format is indicated in the
+   "fl_magic" field of the "FL_HDR" structure.  For a normal archive,
+   this field will be the string defined by the AIAMAG symbol.  For a
+   "big" archive, it will be the string defined by the AIAMAGBIG symbol
+   (at least on AIX it works this way).
+
+   Note: we'll define these symbols regardless of which AIX version
+   we're compiling on, but this is okay since we'll use the new symbols
+   only if they're present.  */
+#ifdef _AIX
+# define __AR_SMALL__
+# define __AR_BIG__
+#endif
+
+#ifndef WINDOWS32
+# ifndef __BEOS__
+#  include <ar.h>
+# else
+   /* BeOS 5 doesn't have <ar.h> but has archives in the same format
+    * as many other Unices.  This was taken from GNU binutils for BeOS.
+    */
+#  define ARMAG	"!<arch>\n"	/* String that begins an archive file.  */
+#  define SARMAG 8		/* Size of that string.  */
+#  define ARFMAG "`\n"		/* String in ar_fmag at end of each header.  */
+struct ar_hdr
+  {
+    char ar_name[16];		/* Member file name, sometimes / terminated. */
+    char ar_date[12];		/* File date, decimal seconds since Epoch.  */
+    char ar_uid[6], ar_gid[6];	/* User and group IDs, in ASCII decimal.  */
+    char ar_mode[8];		/* File mode, in ASCII octal.  */
+    char ar_size[10];		/* File size, in ASCII decimal.  */
+    char ar_fmag[2];		/* Always contains ARFMAG.  */
+  };
+# endif
+#else
+/* These should allow us to read Windows (VC++) libraries (according to Frank
+ * Libbrecht <frankl@abzx.belgium.hp.com>)
+ */
+# include <windows.h>
+# include <windef.h>
+# include <io.h>
+# define ARMAG      IMAGE_ARCHIVE_START
+# define SARMAG     IMAGE_ARCHIVE_START_SIZE
+# define ar_hdr     _IMAGE_ARCHIVE_MEMBER_HEADER
+# define ar_name    Name
+# define ar_mode    Mode
+# define ar_size    Size
+# define ar_date    Date
+# define ar_uid     UserID
+# define ar_gid     GroupID
+#endif
+
+/* Cray's <ar.h> apparently defines this.  */
+#ifndef	AR_HDR_SIZE
+# define   AR_HDR_SIZE	(sizeof (struct ar_hdr))
+#endif
+
+
+/* Takes three arguments ARCHIVE, FUNCTION and ARG.
+
+   Open the archive named ARCHIVE, find its members one by one,
+   and for each one call FUNCTION with the following arguments:
+     archive file descriptor for reading the data,
+     member name,
+     member name might be truncated flag,
+     member header position in file,
+     member data position in file,
+     member data size,
+     member date,
+     member uid,
+     member gid,
+     member protection mode,
+     ARG.
+
+   The descriptor is poised to read the data of the member
+   when FUNCTION is called.  It does not matter how much
+   data FUNCTION reads.
+
+   If FUNCTION returns nonzero, we immediately return
+   what FUNCTION returned.
+
+   Returns -1 if archive does not exist,
+   Returns -2 if archive has invalid format.
+   Returns 0 if have scanned successfully.  */
+
+long int
+ar_scan (const char *archive, ar_member_func_t function, const void *arg)
+{
+#ifdef AIAMAG
+  FL_HDR fl_header;
+#ifdef AIAMAGBIG
+  int big_archive = 0;
+  FL_HDR_BIG fl_header_big;
+#endif
+#else
+  int long_name = 0;
+#endif
+  char *namemap = 0;
+  int desc = open (archive, O_RDONLY, 0);
+  if (desc < 0)
+    return -1;
+#ifdef SARMAG
+  {
+    char buf[SARMAG];
+    register int nread = read (desc, buf, SARMAG);
+    if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG))
+      {
+	(void) close (desc);
+	return -2;
+      }
+  }
+#else
+#ifdef AIAMAG
+  {
+    register int nread = read (desc, &fl_header, FL_HSZ);
+
+    if (nread != FL_HSZ)
+      {
+	(void) close (desc);
+	return -2;
+      }
+#ifdef AIAMAGBIG
+    /* If this is a "big" archive, then set the flag and
+       re-read the header into the "big" structure. */
+    if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
+      {
+	big_archive = 1;
+
+	/* seek back to beginning of archive */
+	if (lseek (desc, 0, 0) < 0)
+	  {
+	    (void) close (desc);
+	    return -2;
+	  }
+
+	/* re-read the header into the "big" structure */
+	nread = read (desc, &fl_header_big, FL_HSZ_BIG);
+	if (nread != FL_HSZ_BIG)
+	  {
+	    (void) close (desc);
+	    return -2;
+	  }
+      }
+    else
+#endif
+       /* Check to make sure this is a "normal" archive. */
+      if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
+	{
+          (void) close (desc);
+          return -2;
+	}
+  }
+#else
+  {
+#ifndef M_XENIX
+    int buf;
+#else
+    unsigned short int buf;
+#endif
+    register int nread = read(desc, &buf, sizeof (buf));
+    if (nread != sizeof (buf) || buf != ARMAG)
+      {
+	(void) close (desc);
+	return -2;
+      }
+  }
+#endif
+#endif
+
+  /* Now find the members one by one.  */
+  {
+#ifdef SARMAG
+    register long int member_offset = SARMAG;
+#else
+#ifdef AIAMAG
+    long int member_offset;
+    long int last_member_offset;
+
+#ifdef AIAMAGBIG
+    if ( big_archive )
+      {
+	sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
+	sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
+      }
+    else
+#endif
+      {
+	sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
+	sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
+      }
+
+    if (member_offset == 0)
+      {
+	/* Empty archive.  */
+	close (desc);
+	return 0;
+      }
+#else
+#ifndef	M_XENIX
+    register long int member_offset = sizeof (int);
+#else	/* Xenix.  */
+    register long int member_offset = sizeof (unsigned short int);
+#endif	/* Not Xenix.  */
+#endif
+#endif
+
+    while (1)
+      {
+	register int nread;
+	struct ar_hdr member_header;
+#ifdef AIAMAGBIG
+	struct ar_hdr_big member_header_big;
+#endif
+#ifdef AIAMAG
+	char name[256];
+	int name_len;
+	long int dateval;
+	int uidval, gidval;
+	long int data_offset;
+#else
+	char namebuf[sizeof member_header.ar_name + 1];
+	char *name;
+	int is_namemap;		/* Nonzero if this entry maps long names.  */
+#endif
+	long int eltsize;
+	int eltmode;
+	long int fnval;
+
+	if (lseek (desc, member_offset, 0) < 0)
+	  {
+	    (void) close (desc);
+	    return -2;
+	  }
+
+#ifdef AIAMAG
+#define       AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
+
+#ifdef AIAMAGBIG
+	if (big_archive)
+	  {
+	    nread = read (desc, &member_header_big,
+			  AR_MEMHDR_SZ(member_header_big) );
+
+	    if (nread != AR_MEMHDR_SZ(member_header_big))
+	      {
+		(void) close (desc);
+		return -2;
+	      }
+
+	    sscanf (member_header_big.ar_namlen, "%4d", &name_len);
+	    nread = read (desc, name, name_len);
+
+	    if (nread != name_len)
+	      {
+		(void) close (desc);
+		return -2;
+	      }
+
+	    name[name_len] = 0;
+
+	    sscanf (member_header_big.ar_date, "%12ld", &dateval);
+	    sscanf (member_header_big.ar_uid, "%12d", &uidval);
+	    sscanf (member_header_big.ar_gid, "%12d", &gidval);
+	    sscanf (member_header_big.ar_mode, "%12o", &eltmode);
+	    sscanf (member_header_big.ar_size, "%20ld", &eltsize);
+
+	    data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
+			   + name_len + 2);
+	  }
+	else
+#endif
+	  {
+	    nread = read (desc, &member_header,
+			  AR_MEMHDR_SZ(member_header) );
+
+	    if (nread != AR_MEMHDR_SZ(member_header))
+	      {
+		(void) close (desc);
+		return -2;
+	      }
+
+	    sscanf (member_header.ar_namlen, "%4d", &name_len);
+	    nread = read (desc, name, name_len);
+
+	    if (nread != name_len)
+	      {
+		(void) close (desc);
+		return -2;
+	      }
+
+	    name[name_len] = 0;
+
+	    sscanf (member_header.ar_date, "%12ld", &dateval);
+	    sscanf (member_header.ar_uid, "%12d", &uidval);
+	    sscanf (member_header.ar_gid, "%12d", &gidval);
+	    sscanf (member_header.ar_mode, "%12o", &eltmode);
+	    sscanf (member_header.ar_size, "%12ld", &eltsize);
+
+	    data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
+			   + name_len + 2);
+	  }
+	data_offset += data_offset % 2;
+
+	fnval =
+	  (*function) (desc, name, 0,
+		       member_offset, data_offset, eltsize,
+		       dateval, uidval, gidval,
+		       eltmode, arg);
+
+#else	/* Not AIAMAG.  */
+	nread = read (desc, &member_header, AR_HDR_SIZE);
+	if (nread == 0)
+	  /* No data left means end of file; that is OK.  */
+	  break;
+
+	if (nread != AR_HDR_SIZE
+#if defined(ARFMAG) || defined(ARFZMAG)
+	    || (
+# ifdef ARFMAG
+                memcmp (member_header.ar_fmag, ARFMAG, 2)
+# else
+                1
+# endif
+                &&
+# ifdef ARFZMAG
+                memcmp (member_header.ar_fmag, ARFZMAG, 2)
+# else
+                1
+# endif
+               )
+#endif
+	    )
+	  {
+	    (void) close (desc);
+	    return -2;
+	  }
+
+	name = namebuf;
+	memcpy (name, member_header.ar_name, sizeof member_header.ar_name);
+	{
+	  register char *p = name + sizeof member_header.ar_name;
+	  do
+	    *p = '\0';
+	  while (p > name && *--p == ' ');
+
+#ifndef AIAMAG
+	  /* If the member name is "//" or "ARFILENAMES/" this may be
+	     a list of file name mappings.  The maximum file name
+ 	     length supported by the standard archive format is 14
+ 	     characters.  This member will actually always be the
+ 	     first or second entry in the archive, but we don't check
+ 	     that.  */
+ 	  is_namemap = (!strcmp (name, "//")
+			|| !strcmp (name, "ARFILENAMES/"));
+#endif	/* Not AIAMAG. */
+	  /* On some systems, there is a slash after each member name.  */
+	  if (*p == '/')
+	    *p = '\0';
+
+#ifndef AIAMAG
+ 	  /* If the member name starts with a space or a slash, this
+ 	     is an index into the file name mappings (used by GNU ar).
+ 	     Otherwise if the member name looks like #1/NUMBER the
+ 	     real member name appears in the element data (used by
+ 	     4.4BSD).  */
+ 	  if (! is_namemap
+ 	      && (name[0] == ' ' || name[0] == '/')
+ 	      && namemap != 0)
+	    {
+	      name = namemap + atoi (name + 1);
+	      long_name = 1;
+	    }
+ 	  else if (name[0] == '#'
+ 		   && name[1] == '1'
+ 		   && name[2] == '/')
+ 	    {
+ 	      int namesize = atoi (name + 3);
+
+ 	      name = alloca (namesize + 1);
+ 	      nread = read (desc, name, namesize);
+ 	      if (nread != namesize)
+ 		{
+ 		  close (desc);
+ 		  return -2;
+ 		}
+ 	      name[namesize] = '\0';
+
+	      long_name = 1;
+ 	    }
+#endif /* Not AIAMAG. */
+	}
+
+#ifndef	M_XENIX
+	sscanf (member_header.ar_mode, "%o", &eltmode);
+	eltsize = atol (member_header.ar_size);
+#else	/* Xenix.  */
+	eltmode = (unsigned short int) member_header.ar_mode;
+	eltsize = member_header.ar_size;
+#endif	/* Not Xenix.  */
+
+	fnval =
+	  (*function) (desc, name, ! long_name, member_offset,
+		       member_offset + AR_HDR_SIZE, eltsize,
+#ifndef	M_XENIX
+		       atol (member_header.ar_date),
+		       atoi (member_header.ar_uid),
+		       atoi (member_header.ar_gid),
+#else	/* Xenix.  */
+		       member_header.ar_date,
+		       member_header.ar_uid,
+		       member_header.ar_gid,
+#endif	/* Not Xenix.  */
+		       eltmode, arg);
+
+#endif  /* AIAMAG.  */
+
+	if (fnval)
+	  {
+	    (void) close (desc);
+	    return fnval;
+	  }
+
+#ifdef AIAMAG
+	if (member_offset == last_member_offset)
+	  /* End of the chain.  */
+	  break;
+
+#ifdef AIAMAGBIG
+	if (big_archive)
+          sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
+	else
+#endif
+	  sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
+
+	if (lseek (desc, member_offset, 0) != member_offset)
+	  {
+	    (void) close (desc);
+	    return -2;
+	  }
+#else
+
+ 	/* If this member maps archive names, we must read it in.  The
+ 	   name map will always precede any members whose names must
+ 	   be mapped.  */
+	if (is_namemap)
+ 	  {
+ 	    char *clear;
+ 	    char *limit;
+
+ 	    namemap = alloca (eltsize);
+ 	    nread = read (desc, namemap, eltsize);
+ 	    if (nread != eltsize)
+ 	      {
+ 		(void) close (desc);
+ 		return -2;
+ 	      }
+
+ 	    /* The names are separated by newlines.  Some formats have
+ 	       a trailing slash.  Null terminate the strings for
+ 	       convenience.  */
+ 	    limit = namemap + eltsize;
+ 	    for (clear = namemap; clear < limit; clear++)
+ 	      {
+ 		if (*clear == '\n')
+ 		  {
+ 		    *clear = '\0';
+ 		    if (clear[-1] == '/')
+ 		      clear[-1] = '\0';
+ 		  }
+ 	      }
+
+	    is_namemap = 0;
+ 	  }
+
+	member_offset += AR_HDR_SIZE + eltsize;
+	if (member_offset % 2 != 0)
+	  member_offset++;
+#endif
+      }
+  }
+
+  close (desc);
+  return 0;
+}
+#endif /* !VMS */
+
+
+/* Return nonzero iff NAME matches MEM.
+   If TRUNCATED is nonzero, MEM may be truncated to
+   sizeof (struct ar_hdr.ar_name) - 1.  */
+
+int
+ar_name_equal (const char *name, const char *mem, int truncated)
+{
+  const char *p;
+
+  p = strrchr (name, '/');
+  if (p != 0)
+    name = p + 1;
+
+#ifndef VMS
+  if (truncated)
+    {
+#ifdef AIAMAG
+      /* TRUNCATED should never be set on this system.  */
+      abort ();
+#else
+      struct ar_hdr hdr;
+#if !defined (__hpux) && !defined (cray)
+      return strneq (name, mem, sizeof(hdr.ar_name) - 1);
+#else
+      return strneq (name, mem, sizeof(hdr.ar_name) - 2);
+#endif /* !__hpux && !cray */
+#endif /* !AIAMAG */
+    }
+#endif /* !VMS */
+
+  return !strcmp (name, mem);
+}
+
+
+#ifndef VMS
+/* ARGSUSED */
+static long int
+ar_member_pos (int desc UNUSED, const char *mem, int truncated,
+	       long int hdrpos, long int datapos UNUSED, long int size UNUSED,
+               long int date UNUSED, int uid UNUSED, int gid UNUSED,
+               int mode UNUSED, const void *name)
+{
+  if (!ar_name_equal (name, mem, truncated))
+    return 0;
+  return hdrpos;
+}
+
+/* Set date of member MEMNAME in archive ARNAME to current time.
+   Returns 0 if successful,
+   -1 if file ARNAME does not exist,
+   -2 if not a valid archive,
+   -3 if other random system call error (including file read-only),
+   1 if valid but member MEMNAME does not exist.  */
+
+int
+ar_member_touch (const char *arname, const char *memname)
+{
+  long int pos = ar_scan (arname, ar_member_pos, memname);
+  int fd;
+  struct ar_hdr ar_hdr;
+  int i;
+  unsigned int ui;
+  struct stat statbuf;
+
+  if (pos < 0)
+    return (int) pos;
+  if (!pos)
+    return 1;
+
+  fd = open (arname, O_RDWR, 0666);
+  if (fd < 0)
+    return -3;
+  /* Read in this member's header */
+  if (lseek (fd, pos, 0) < 0)
+    goto lose;
+  if (AR_HDR_SIZE != read (fd, &ar_hdr, AR_HDR_SIZE))
+    goto lose;
+  /* Write back the header, thus touching the archive file.  */
+  if (lseek (fd, pos, 0) < 0)
+    goto lose;
+  if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE))
+    goto lose;
+  /* The file's mtime is the time we we want.  */
+  EINTRLOOP (i, fstat (fd, &statbuf));
+  if (i < 0)
+    goto lose;
+#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
+  /* Advance member's time to that time */
+  for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
+    ar_hdr.ar_date[ui] = ' ';
+  sprintf (ar_hdr.ar_date, "%ld", (long int) statbuf.st_mtime);
+#ifdef AIAMAG
+  ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' ';
+#endif
+#else
+  ar_hdr.ar_date = statbuf.st_mtime;
+#endif
+  /* Write back this member's header */
+  if (lseek (fd, pos, 0) < 0)
+    goto lose;
+  if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE))
+    goto lose;
+  close (fd);
+  return 0;
+
+ lose:
+  i = errno;
+  close (fd);
+  errno = i;
+  return -3;
+}
+#endif
+
+
+#ifdef TEST
+
+long int
+describe_member (int desc, const char *name, int truncated,
+		 long int hdrpos, long int datapos, long int size,
+                 long int date, int uid, int gid, int mode, const void *arg)
+{
+  extern char *ctime ();
+
+  printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"),
+	  name, truncated ? _(" (name might be truncated)") : "",
+	  size, hdrpos, datapos);
+  printf (_("  Date %s"), ctime (&date));
+  printf (_("  uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
+
+  return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+  ar_scan (argv[1], describe_member, NULL);
+  return 0;
+}
+
+#endif	/* TEST.  */
+#endif	/* NO_ARCHIVES.  */
Index: /tags/kBuild-0.1.4/src/kmk/build.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/build.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/build.template	(revision 1780)
@@ -0,0 +1,81 @@
+#!/bin/sh
+# Shell script to build GNU Make in the absence of any `make' program.
+# @configure_input@
+
+# Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# See Makefile.in for comments describing these variables.
+
+srcdir='@srcdir@'
+CC='@CC@'
+CFLAGS='@CFLAGS@'
+CPPFLAGS='@CPPFLAGS@'
+LDFLAGS='@LDFLAGS@'
+ALLOCA='@ALLOCA@'
+LOADLIBES='@LIBS@ @LIBINTL@'
+eval extras=\'@LIBOBJS@\'
+REMOTE='@REMOTE@'
+GLOBLIB='@GLOBLIB@'
+PATH_SEPARATOR='@PATH_SEPARATOR@'
+OBJEXT='@OBJEXT@'
+EXEEXT='@EXEEXT@'
+
+# Common prefix for machine-independent installed files.
+prefix='@prefix@'
+# Common prefix for machine-dependent installed files.
+exec_prefix=`eval echo @exec_prefix@`
+# Directory to find libraries in for `-lXXX'.
+libdir=${exec_prefix}/lib
+# Directory to search by default for included makefiles.
+includedir=${prefix}/include
+
+localedir=${prefix}/share/locale
+aliaspath=${localedir}${PATH_SEPARATOR}.
+
+defines="-DALIASPATH=\"${aliaspath}\" -DLOCALEDIR=\"${localedir}\" -DLIBDIR=\"${libdir}\" -DINCLUDEDIR=\"${includedir}\""' @DEFS@'
+
+# Exit as soon as any command fails.
+set -e
+
+# These are all the objects we need to link together.
+objs="%objs% remote-${REMOTE}.${OBJEXT} ${extras} ${ALLOCA}"
+
+if [ x"$GLOBLIB" != x ]; then
+  objs="$objs %globobjs%"
+  globinc=-I${srcdir}/glob
+fi
+
+# Compile the source files into those objects.
+for file in `echo ${objs} | sed 's/\.'${OBJEXT}'/.c/g'`; do
+  echo compiling ${file}...
+  $CC $defines $CPPFLAGS $CFLAGS \
+      -c -I. -I${srcdir} ${globinc} ${srcdir}/$file
+done
+
+# The object files were actually all put in the current directory.
+# Remove the source directory names from the list.
+srcobjs="$objs"
+objs=
+for obj in $srcobjs; do
+  objs="$objs `basename $obj`"
+done
+
+# Link all the objects together.
+echo linking make...
+$CC $CFLAGS $LDFLAGS $objs $LOADLIBES -o makenew${EXEEXT}
+echo done
+mv -f makenew${EXEEXT} make${EXEEXT}
Index: /tags/kBuild-0.1.4/src/kmk/build_w32.bat
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/build_w32.bat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/build_w32.bat	(revision 1780)
@@ -0,0 +1,197 @@
+@echo off
+rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+rem 2006 Free Software Foundation, Inc.
+rem This file is part of GNU Make.
+
+rem GNU Make is free software; you can redistribute it and/or modify it under the
+rem terms of the GNU General Public License as published by the Free Software
+rem Foundation; either version 2, or (at your option) any later version.
+
+rem GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+rem WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+rem A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+rem You should have received a copy of the GNU General Public License along with
+rem GNU Make; see the file COPYING.  If not, write to the Free Software
+rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+if not exist config.h copy config.h.W32 config.h
+cd w32\subproc
+echo "Creating the subproc library"
+%ComSpec% /c build.bat %1
+cd ..\..
+
+if exist link.dbg del link.dbg
+if exist link.rel del link.rel
+echo "Creating GNU Make for Windows 9X/NT/2K/XP"
+if "%1" == "gcc" GoTo GCCBuild
+set make=gnumake
+echo on
+if not exist .\WinDebug\nul mkdir .\WinDebug
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D TIVOLI /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c variable.c
+echo WinDebug\variable.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c rule.c
+echo WinDebug\rule.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remote-stub.c
+echo WinDebug\remote-stub.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c commands.c
+echo WinDebug\commands.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c file.c
+echo WinDebug\file.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getloadavg.c
+echo WinDebug\getloadavg.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c default.c
+echo WinDebug\default.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c signame.c
+echo WinDebug\signame.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c expand.c
+echo WinDebug\expand.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c dir.c
+echo WinDebug\dir.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c main.c
+echo WinDebug\main.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt1.c
+echo WinDebug\getopt1.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c job.c
+echo WinDebug\job.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c read.c
+echo WinDebug\read.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c version.c
+echo WinDebug\version.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt.c
+echo WinDebug\getopt.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c arscan.c
+echo WinDebug\arscan.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c hash.c
+echo WinDebug\hash.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c strcache.c
+echo WinDebug\strcache.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remake.c
+echo WinDebug\remake.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c misc.c
+echo WinDebug\misc.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c ar.c
+echo WinDebug\ar.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c function.c
+echo WinDebug\function.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c vpath.c
+echo WinDebug\vpath.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c implicit.c
+echo WinDebug\implicit.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c  .\w32\compat\dirent.c
+echo WinDebug\dirent.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c  .\glob\glob.c
+echo WinDebug\glob.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c  .\glob\fnmatch.c
+echo WinDebug\fnmatch.obj >>link.dbg
+cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c  .\w32\pathstuff.c
+echo WinDebug\pathstuff.obj >>link.dbg
+echo off
+echo "Linking WinDebug/%make%.exe"
+rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj  .\WinDebug/rule.obj  .\WinDebug/remote-stub.obj  .\WinDebug/commands.obj  .\WinDebug/file.obj  .\WinDebug/getloadavg.obj  .\WinDebug/default.obj  .\WinDebug/signame.obj  .\WinDebug/expand.obj  .\WinDebug/dir.obj  .\WinDebug/main.obj  .\WinDebug/getopt1.obj  .\WinDebug/job.obj  .\WinDebug/read.obj  .\WinDebug/version.obj  .\WinDebug/getopt.obj  .\WinDebug/arscan.obj  .\WinDebug/remake.obj  .\WinDebug/hash.obj  .\WinDebug/strcache.obj  .\WinDebug/misc.obj  .\WinDebug/ar.obj  .\WinDebug/function.obj  .\WinDebug/vpath.obj  .\WinDebug/implicit.obj  .\WinDebug/dirent.obj  .\WinDebug/glob.obj  .\WinDebug/fnmatch.obj  .\WinDebug/pathstuff.obj
+echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib >>link.dbg
+link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe @link.dbg
+if not exist .\WinDebug/%make%.exe echo "WinDebug build failed"
+if exist .\WinDebug/%make%.exe echo "WinDebug build succeeded!"
+if not exist .\WinRel\nul mkdir .\WinRel
+echo on
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /D TIVOLI /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c variable.c
+echo WinRel\variable.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c rule.c
+echo WinRel\rule.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remote-stub.c
+echo WinRel\remote-stub.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c commands.c
+echo WinRel\commands.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c file.c
+echo WinRel\file.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getloadavg.c
+echo WinRel\getloadavg.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c default.c
+echo WinRel\default.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c signame.c
+echo WinRel\signame.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c expand.c
+echo WinRel\expand.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c dir.c
+echo WinRel\dir.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c main.c
+echo WinRel\main.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt1.c
+echo WinRel\getopt1.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c job.c
+echo WinRel\job.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c read.c
+echo WinRel\read.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c version.c
+echo WinRel\version.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt.c
+echo WinRel\getopt.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c arscan.c
+echo WinRel\arscan.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remake.c
+echo WinRel\remake.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c hash.c
+echo WinRel\hash.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c strcache.c
+echo WinRel\strcache.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c misc.c
+echo WinRel\misc.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c ar.c
+echo WinRel\ar.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c function.c
+echo WinRel\function.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c vpath.c
+echo WinRel\vpath.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c implicit.c
+echo WinRel\implicit.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c  .\w32\compat\dirent.c
+echo WinRel\dirent.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c  .\glob\glob.c
+echo WinRel\glob.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c  .\glob\fnmatch.c
+echo WinRel\fnmatch.obj >>link.rel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c  .\w32\pathstuff.c
+echo WinRel\pathstuff.obj >>link.rel
+echo off
+echo "Linking WinRel/%make%.exe"
+rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj  .\WinRel/rule.obj  .\WinRel/remote-stub.obj  .\WinRel/commands.obj  .\WinRel/file.obj  .\WinRel/getloadavg.obj  .\WinRel/default.obj  .\WinRel/signame.obj  .\WinRel/expand.obj  .\WinRel/dir.obj  .\WinRel/main.obj  .\WinRel/getopt1.obj  .\WinRel/job.obj  .\WinRel/read.obj  .\WinRel/version.obj  .\WinRel/getopt.obj  .\WinRel/arscan.obj  .\WinRel/remake.obj  .\WinRel/misc.obj  .\WinRel/hash.obj  .\WinRel/strcache.obj  .\WinRel/ar.obj  .\WinRel/function.obj  .\WinRel/vpath.obj  .\WinRel/implicit.obj  .\WinRel/dirent.obj  .\WinRel/glob.obj  .\WinRel/fnmatch.obj  .\WinRel/pathstuff.obj
+echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib >>link.rel
+link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe @link.rel
+if not exist .\WinRel/%make%.exe echo "WinRel build failed"
+if exist .\WinRel/%make%.exe echo "WinRel build succeeded!"
+set make=
+GoTo BuildEnd
+:GCCBuild
+echo on
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c variable.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c rule.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remote-stub.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c commands.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c file.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getloadavg.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c default.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c signame.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c expand.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c dir.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c main.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt1.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c job.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c read.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c version.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c arscan.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remake.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c hash.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c strcache.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c misc.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ar.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c function.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c vpath.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c implicit.c
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/glob.c -o glob.o
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/fnmatch.c -o fnmatch.o
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/pathstuff.c -o pathstuff.o
+gcc -mthreads -gstabs+ -ggdb3 -o gnumake.exe variable.o rule.o remote-stub.o commands.o file.o getloadavg.o default.o signame.o expand.o dir.o main.o getopt1.o job.o read.o version.o getopt.o arscan.o remake.o misc.o hash.o strcache.o ar.o function.o vpath.o implicit.o glob.o fnmatch.o pathstuff.o w32_misc.o sub_proc.o w32err.o -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
+:BuildEnd
+echo on
Index: /tags/kBuild-0.1.4/src/kmk/commands.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/commands.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/commands.c	(revision 1780)
@@ -0,0 +1,657 @@
+/* Command processing for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "dep.h"
+#include "filedef.h"
+#include "variable.h"
+#include "job.h"
+#include "commands.h"
+#ifdef WINDOWS32
+#include <windows.h>
+#include "w32err.h"
+#endif
+
+#if VMS
+# define FILE_LIST_SEPARATOR ','
+#else
+# define FILE_LIST_SEPARATOR ' '
+#endif
+
+int remote_kill (int id, int sig);
+
+#ifndef	HAVE_UNISTD_H
+int getpid ();
+#endif
+
+
+/* Set FILE's automatic variables up.  */
+
+void
+set_file_variables (struct file *file)
+{
+  const struct dep *d;
+  const char *at, *percent, *star, *less;
+
+#ifndef	NO_ARCHIVES
+  /* If the target is an archive member `lib(member)',
+     then $@ is `lib' and $% is `member'.  */
+
+  if (ar_name (file->name))
+    {
+      unsigned int len;
+      const char *cp;
+      char *p;
+
+      cp = strchr (file->name, '(');
+      p = alloca (cp - file->name + 1);
+      memcpy (p, file->name, cp - file->name);
+      p[cp - file->name] = '\0';
+      at = p;
+      len = strlen (cp + 1);
+      p = alloca (len);
+      memcpy (p, cp + 1, len - 1);
+      p[len - 1] = '\0';
+      percent = p;
+    }
+  else
+#endif	/* NO_ARCHIVES.  */
+    {
+      at = file->name;
+      percent = "";
+    }
+
+  /* $* is the stem from an implicit or static pattern rule.  */
+  if (file->stem == 0)
+    {
+      /* In Unix make, $* is set to the target name with
+	 any suffix in the .SUFFIXES list stripped off for
+	 explicit rules.  We store this in the `stem' member.  */
+      const char *name;
+      unsigned int len;
+
+#ifndef	NO_ARCHIVES
+      if (ar_name (file->name))
+	{
+	  name = strchr (file->name, '(') + 1;
+	  len = strlen (name) - 1;
+	}
+      else
+#endif
+	{
+	  name = file->name;
+	  len = strlen (name);
+	}
+
+      for (d = enter_file (strcache_add (".SUFFIXES"))->deps; d ; d = d->next)
+	{
+	  unsigned int slen = strlen (dep_name (d));
+	  if (len > slen && strneq (dep_name (d), name + (len - slen), slen))
+	    {
+	      file->stem = strcache_add_len (name, len - slen);
+	      break;
+	    }
+	}
+      if (d == 0)
+	file->stem = "";
+    }
+  star = file->stem;
+
+  /* $< is the first not order-only dependency.  */
+  less = "";
+  for (d = file->deps; d != 0; d = d->next)
+    if (!d->ignore_mtime)
+      {
+        less = dep_name (d);
+        break;
+      }
+
+  if (file->cmds == default_file->cmds)
+    /* This file got its commands from .DEFAULT.
+       In this case $< is the same as $@.  */
+    less = at;
+
+#define	DEFINE_VARIABLE(name, len, value) \
+  (void) define_variable_for_file (name,len,value,o_automatic,0,file)
+
+  /* Define the variables.  */
+
+  DEFINE_VARIABLE ("<", 1, less);
+  DEFINE_VARIABLE ("*", 1, star);
+  DEFINE_VARIABLE ("@", 1, at);
+  DEFINE_VARIABLE ("%", 1, percent);
+
+  /* Compute the values for $^, $+, $?, and $|.  */
+
+  {
+    static char *plus_value=0, *bar_value=0, *qmark_value=0;
+    static unsigned int plus_max=0, bar_max=0, qmark_max=0;
+
+    unsigned int qmark_len, plus_len, bar_len;
+    char *cp;
+    char *caret_value;
+    char *qp;
+    char *bp;
+    unsigned int len;
+
+    /* Compute first the value for $+, which is supposed to contain
+       duplicate dependencies as they were listed in the makefile.  */
+
+    plus_len = 0;
+    for (d = file->deps; d != 0; d = d->next)
+      if (! d->ignore_mtime)
+	plus_len += strlen (dep_name (d)) + 1;
+    if (plus_len == 0)
+      plus_len++;
+
+    if (plus_len > plus_max)
+      plus_value = xrealloc (plus_value, plus_max = plus_len);
+    cp = plus_value;
+
+    qmark_len = plus_len + 1;	/* Will be this or less.  */
+    for (d = file->deps; d != 0; d = d->next)
+      if (! d->ignore_mtime)
+        {
+          const char *c = dep_name (d);
+
+#ifndef	NO_ARCHIVES
+          if (ar_name (c))
+            {
+              c = strchr (c, '(') + 1;
+              len = strlen (c) - 1;
+            }
+          else
+#endif
+            len = strlen (c);
+
+          memcpy (cp, c, len);
+          cp += len;
+          *cp++ = FILE_LIST_SEPARATOR;
+          if (! d->changed)
+            qmark_len -= len + 1;	/* Don't space in $? for this one.  */
+        }
+
+    /* Kill the last space and define the variable.  */
+
+    cp[cp > plus_value ? -1 : 0] = '\0';
+    DEFINE_VARIABLE ("+", 1, plus_value);
+
+    /* Make sure that no dependencies are repeated.  This does not
+       really matter for the purpose of updating targets, but it
+       might make some names be listed twice for $^ and $?.  */
+
+    uniquize_deps (file->deps);
+
+    bar_len = 0;
+    for (d = file->deps; d != 0; d = d->next)
+      if (d->ignore_mtime)
+	bar_len += strlen (dep_name (d)) + 1;
+    if (bar_len == 0)
+      bar_len++;
+
+    /* Compute the values for $^, $?, and $|.  */
+
+    cp = caret_value = plus_value; /* Reuse the buffer; it's big enough.  */
+
+    if (qmark_len > qmark_max)
+      qmark_value = xrealloc (qmark_value, qmark_max = qmark_len);
+    qp = qmark_value;
+
+    if (bar_len > bar_max)
+      bar_value = xrealloc (bar_value, bar_max = bar_len);
+    bp = bar_value;
+
+    for (d = file->deps; d != 0; d = d->next)
+      {
+	const char *c = dep_name (d);
+
+#ifndef	NO_ARCHIVES
+	if (ar_name (c))
+	  {
+	    c = strchr (c, '(') + 1;
+	    len = strlen (c) - 1;
+	  }
+	else
+#endif
+	  len = strlen (c);
+
+        if (d->ignore_mtime)
+          {
+	    memcpy (bp, c, len);
+	    bp += len;
+	    *bp++ = FILE_LIST_SEPARATOR;
+	  }
+	else
+	  {
+            memcpy (cp, c, len);
+            cp += len;
+            *cp++ = FILE_LIST_SEPARATOR;
+            if (d->changed)
+              {
+                memcpy (qp, c, len);
+                qp += len;
+                *qp++ = FILE_LIST_SEPARATOR;
+              }
+          }
+      }
+
+    /* Kill the last spaces and define the variables.  */
+
+    cp[cp > caret_value ? -1 : 0] = '\0';
+    DEFINE_VARIABLE ("^", 1, caret_value);
+
+    qp[qp > qmark_value ? -1 : 0] = '\0';
+    DEFINE_VARIABLE ("?", 1, qmark_value);
+
+    bp[bp > bar_value ? -1 : 0] = '\0';
+    DEFINE_VARIABLE ("|", 1, bar_value);
+  }
+
+#undef	DEFINE_VARIABLE
+}
+
+
+/* Chop CMDS up into individual command lines if necessary.
+   Also set the `lines_flags' and `any_recurse' members.  */
+
+void
+chop_commands (struct commands *cmds)
+{
+  const char *p;
+  unsigned int nlines, idx;
+  char **lines;
+
+  /* If we don't have any commands,
+     or we already parsed them, never mind.  */
+
+  if (!cmds || cmds->command_lines != 0)
+    return;
+
+  /* Chop CMDS->commands up into lines in CMDS->command_lines.
+	 Also set the corresponding CMDS->lines_flags elements,
+	 and the CMDS->any_recurse flag.  */
+
+  nlines = 5;
+  lines = xmalloc (5 * sizeof (char *));
+  idx = 0;
+  p = cmds->commands;
+  while (*p != '\0')
+    {
+      const char *end = p;
+    find_end:;
+      end = strchr (end, '\n');
+      if (end == 0)
+        end = p + strlen (p);
+      else if (end > p && end[-1] == '\\')
+        {
+          int backslash = 1;
+          const char *b;
+          for (b = end - 2; b >= p && *b == '\\'; --b)
+            backslash = !backslash;
+          if (backslash)
+            {
+              ++end;
+              goto find_end;
+            }
+        }
+
+      if (idx == nlines)
+        {
+          nlines += 2;
+          lines = xrealloc (lines, nlines * sizeof (char *));
+        }
+      lines[idx++] = savestring (p, end - p);
+      p = end;
+      if (*p != '\0')
+        ++p;
+    }
+
+  if (idx != nlines)
+    {
+      nlines = idx;
+      lines = xrealloc (lines, nlines * sizeof (char *));
+    }
+
+  cmds->ncommand_lines = nlines;
+  cmds->command_lines = lines;
+
+  cmds->any_recurse = 0;
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+  cmds->lines_flags = xmalloc (nlines * sizeof (cmds->lines_flags[0]));
+#else
+  cmds->lines_flags = xmalloc (nlines);
+#endif 
+  for (idx = 0; idx < nlines; ++idx)
+    {
+      int flags = 0;
+
+      for (p = lines[idx];
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+           isblank ((unsigned char)*p) || *p == '-' || *p == '@' || *p == '+' || *p == '%';
+#else
+           isblank ((unsigned char)*p) || *p == '-' || *p == '@' || *p == '+';
+#endif
+           ++p)
+        switch (*p)
+          {
+          case '+':
+            flags |= COMMANDS_RECURSE;
+            break;
+          case '@':
+            flags |= COMMANDS_SILENT;
+            break;
+          case '-':
+            flags |= COMMANDS_NOERROR;
+            break;
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+          case '%':
+            flags |= COMMAND_GETTER_SKIP_IT;
+            break;
+#endif
+          }
+
+      /* If no explicit '+' was given, look for MAKE variable references.  */
+      if (!(flags & COMMANDS_RECURSE)
+#ifndef KMK
+          && (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0))
+#else
+          && (strstr (p, "$(KMK)") != 0 || strstr (p, "${KMK}") != 0 ||
+              strstr (p, "${MAKE}") != 0 || strstr (p, "${MAKE}") != 0))
+#endif
+        flags |= COMMANDS_RECURSE;
+
+#ifdef CONFIG_WITH_KMK_BUILTIN
+      /* check if kmk builtin command */
+      if (!strncmp(p, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
+        flags |= COMMANDS_KMK_BUILTIN;
+#endif
+
+      cmds->lines_flags[idx] = flags;
+      cmds->any_recurse |= flags & COMMANDS_RECURSE;
+    }
+}
+
+
+/* Execute the commands to remake FILE.  If they are currently executing,
+   return or have already finished executing, just return.  Otherwise,
+   fork off a child process to run the first command line in the sequence.  */
+
+void
+execute_file_commands (struct file *file)
+{
+  const char *p;
+
+  /* Don't go through all the preparations if
+     the commands are nothing but whitespace.  */
+
+  for (p = file->cmds->commands; *p != '\0'; ++p)
+    if (!isspace ((unsigned char)*p) && *p != '-' && *p != '@')
+      break;
+  if (*p == '\0')
+    {
+      /* If there are no commands, assume everything worked.  */
+#ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL
+      file->command_flags |= COMMANDS_NO_COMMANDS;
+#endif
+      set_command_state (file, cs_running);
+      file->update_status = 0;
+      notice_finished_file (file);
+      return;
+    }
+
+  /* First set the automatic variables according to this file.  */
+
+  initialize_file_variables (file, 0);
+
+  set_file_variables (file);
+
+  /* Start the commands running.  */
+  new_job (file);
+}
+
+
+/* This is set while we are inside fatal_error_signal,
+   so things can avoid nonreentrant operations.  */
+
+int handling_fatal_signal = 0;
+
+/* Handle fatal signals.  */
+
+RETSIGTYPE
+fatal_error_signal (int sig)
+{
+#ifdef __MSDOS__
+  extern int dos_status, dos_command_running;
+
+  if (dos_command_running)
+    {
+      /* That was the child who got the signal, not us.  */
+      dos_status |= (sig << 8);
+      return;
+    }
+  remove_intermediates (1);
+  exit (EXIT_FAILURE);
+#else /* not __MSDOS__ */
+#ifdef _AMIGA
+  remove_intermediates (1);
+  if (sig == SIGINT)
+     fputs (_("*** Break.\n"), stderr);
+
+  exit (10);
+#else /* not Amiga */
+#if defined(WINDOWS32) && !defined(CONFIG_NEW_WIN32_CTRL_EVENT)
+  extern HANDLE main_thread;
+
+  /* Windows creates a sperate thread for handling Ctrl+C, so we need
+     to suspend the main thread, or else we will have race conditions
+     when both threads call reap_children.  */
+  if (main_thread)
+    {
+      DWORD susp_count = SuspendThread (main_thread);
+
+      if (susp_count != 0)
+	fprintf (stderr, "SuspendThread: suspend count = %ld\n", susp_count);
+      else if (susp_count == (DWORD)-1)
+	{
+	  DWORD ierr = GetLastError ();
+
+	  fprintf (stderr, "SuspendThread: error %ld: %s\n",
+		   ierr, map_windows32_error_to_string (ierr));
+	}
+    }
+#endif
+  handling_fatal_signal = 1;
+
+  /* Set the handling for this signal to the default.
+     It is blocked now while we run this handler.  */
+  signal (sig, SIG_DFL);
+
+  /* A termination signal won't be sent to the entire
+     process group, but it means we want to kill the children.  */
+
+  if (sig == SIGTERM)
+    {
+      struct child *c;
+      for (c = children; c != 0; c = c->next)
+	if (!c->remote)
+	  (void) kill (c->pid, SIGTERM);
+    }
+
+  /* If we got a signal that means the user
+     wanted to kill make, remove pending targets.  */
+
+  if (sig == SIGTERM || sig == SIGINT
+#ifdef SIGHUP
+    || sig == SIGHUP
+#endif
+#ifdef SIGQUIT
+    || sig == SIGQUIT
+#endif
+    )
+    {
+      struct child *c;
+
+      /* Remote children won't automatically get signals sent
+	 to the process group, so we must send them.  */
+      for (c = children; c != 0; c = c->next)
+	if (c->remote)
+	  (void) remote_kill (c->pid, sig);
+
+      for (c = children; c != 0; c = c->next)
+	delete_child_targets (c);
+
+      /* Clean up the children.  We don't just use the call below because
+	 we don't want to print the "Waiting for children" message.  */
+      while (job_slots_used > 0)
+	reap_children (1, 0);
+    }
+  else
+    /* Wait for our children to die.  */
+    while (job_slots_used > 0)
+      reap_children (1, 1);
+
+  /* Delete any non-precious intermediate files that were made.  */
+
+  remove_intermediates (1);
+#ifdef SIGQUIT
+  if (sig == SIGQUIT)
+    /* We don't want to send ourselves SIGQUIT, because it will
+       cause a core dump.  Just exit instead.  */
+    exit (EXIT_FAILURE);
+#endif
+
+#ifdef WINDOWS32
+#ifndef CONFIG_NEW_WIN32_CTRL_EVENT
+  if (main_thread)
+    CloseHandle (main_thread);
+#endif /* !CONFIG_NEW_WIN32_CTRL_EVENT */
+  /* Cannot call W32_kill with a pid (it needs a handle).  The exit
+     status of 130 emulates what happens in Bash.  */
+  exit (130);
+#else
+  /* Signal the same code; this time it will really be fatal.  The signal
+     will be unblocked when we return and arrive then to kill us.  */
+  if (kill (getpid (), sig) < 0)
+    pfatal_with_name ("kill");
+#endif /* not WINDOWS32 */
+#endif /* not Amiga */
+#endif /* not __MSDOS__  */
+}
+
+
+/* Delete FILE unless it's precious or not actually a file (phony),
+   and it has changed on disk since we last stat'd it.  */
+
+static void
+delete_target (struct file *file, const char *on_behalf_of)
+{
+  struct stat st;
+  int e;
+
+  if (file->precious || file->phony)
+    return;
+
+#ifndef NO_ARCHIVES
+  if (ar_name (file->name))
+    {
+      time_t file_date = (file->last_mtime == NONEXISTENT_MTIME
+			  ? (time_t) -1
+			  : (time_t) FILE_TIMESTAMP_S (file->last_mtime));
+      if (ar_member_date (file->name) != file_date)
+	{
+	  if (on_behalf_of)
+	    error (NILF, _("*** [%s] Archive member `%s' may be bogus; not deleted"),
+		   on_behalf_of, file->name);
+	  else
+	    error (NILF, _("*** Archive member `%s' may be bogus; not deleted"),
+		   file->name);
+	}
+      return;
+    }
+#endif
+
+  EINTRLOOP (e, stat (file->name, &st));
+  if (e == 0
+      && S_ISREG (st.st_mode)
+      && FILE_TIMESTAMP_STAT_MODTIME (file->name, st) != file->last_mtime)
+    {
+      if (on_behalf_of)
+	error (NILF, _("*** [%s] Deleting file `%s'"), on_behalf_of, file->name);
+      else
+	error (NILF, _("*** Deleting file `%s'"), file->name);
+      if (unlink (file->name) < 0
+	  && errno != ENOENT)	/* It disappeared; so what.  */
+	perror_with_name ("unlink: ", file->name);
+    }
+}
+
+
+/* Delete all non-precious targets of CHILD unless they were already deleted.
+   Set the flag in CHILD to say they've been deleted.  */
+
+void
+delete_child_targets (struct child *child)
+{
+  struct dep *d;
+
+  if (child->deleted)
+    return;
+
+  /* Delete the target file if it changed.  */
+  delete_target (child->file, NULL);
+
+  /* Also remove any non-precious targets listed in the `also_make' member.  */
+  for (d = child->file->also_make; d != 0; d = d->next)
+    delete_target (d->file, child->file->name);
+
+  child->deleted = 1;
+}
+
+
+/* Print out the commands in CMDS.  */
+
+void
+print_commands (const struct commands *cmds)
+{
+  const char *s;
+
+  fputs (_("#  commands to execute"), stdout);
+
+  if (cmds->fileinfo.filenm == 0)
+    puts (_(" (built-in):"));
+  else
+    printf (_(" (from `%s', line %lu):\n"),
+            cmds->fileinfo.filenm, cmds->fileinfo.lineno);
+
+  s = cmds->commands;
+  while (*s != '\0')
+    {
+      const char *end;
+
+      while (isspace ((unsigned char)*s))
+	++s;
+
+      end = strchr (s, '\n');
+      if (end == 0)
+	end = s + strlen (s);
+
+      printf ("\t%.*s\n", (int) (end - s), s);
+
+      s = end;
+    }
+}
Index: /tags/kBuild-0.1.4/src/kmk/commands.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/commands.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/commands.h	(revision 1780)
@@ -0,0 +1,56 @@
+/* Definition of data structures describing shell commands for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* Structure that gives the commands to make a file
+   and information about where these commands came from.  */
+
+struct commands
+  {
+    struct floc fileinfo;	/* Where commands were defined.  */
+    char *commands;		/* Commands text.  */
+    unsigned int ncommand_lines;/* Number of command lines.  */
+    char **command_lines;	/* Commands chopped up into lines.  */
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+    short *lines_flags;		/* One set of flag bits for each line.  */
+#else
+    char *lines_flags;		/* One set of flag bits for each line.  */
+#endif
+    int any_recurse;		/* Nonzero if any `lines_recurse' elt has */
+				/* the COMMANDS_RECURSE bit set.  */
+  };
+
+/* Bits in `lines_flags'.  */
+#define	COMMANDS_RECURSE	1 /* Recurses: + or $(MAKE).  */
+#define	COMMANDS_SILENT		2 /* Silent: @.  */
+#define	COMMANDS_NOERROR	4 /* No errors: -.  */
+#ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL
+# define COMMANDS_NOTPARALLEL   32  /* kmk: The commands must be executed alone. */
+# define COMMANDS_NO_COMMANDS   64  /* kmk: No commands. */
+#endif 
+#ifdef CONFIG_WITH_KMK_BUILTIN
+# define COMMANDS_KMK_BUILTIN   128 /* kmk: kmk builtin command. */
+#endif
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+# define COMMAND_GETTER_SKIP_IT 256 /* $(commands target) skips this: % */
+#endif
+
+void execute_file_commands (struct file *file);
+void print_commands (const struct commands *cmds);
+void delete_child_targets (struct child *child);
+void chop_commands (struct commands *cmds);
+void set_file_variables (struct file *file);
Index: /tags/kBuild-0.1.4/src/kmk/config.ami.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.ami.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.ami.template	(revision 1780)
@@ -0,0 +1,344 @@
+/* config.h -- hand-massaged for Amiga                                  -*-C-*-
+Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.	*/
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if using alloca.c.  */
+#define C_ALLOCA
+
+/* Define if the closedir function returns void instead of int.  */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define for DGUX with <sys/dg_sys_info.h>.  */
+/* #undef DGUX */
+
+/* Define if the `getloadavg' function needs to be run setuid or setgid.  */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to `unsigned long' or `unsigned long long'
+   if <inttypes.h> doesn't define.  */
+#define uintmax_t unsigned long
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#define gid_t int
+
+/* Define if you have alloca, as a function or macro.  */
+/* #undef HAVE_ALLOCA */
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+/* #undef HAVE_DOPRNT */
+
+/* Define if your system has a working fnmatch function.  */
+/* #undef HAVE_FNMATCH */
+
+/* Define if your system has its own `getloadavg' function.  */
+/* #undef HAVE_GETLOADAVG */
+
+/* Define if you have the getmntent function.  */
+/* #undef HAVE_GETMNTENT */
+
+/* Define if the `long double' type works.  */
+/* #undef HAVE_LONG_DOUBLE */
+
+/* Define if you support file names longer than 14 characters.	*/
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if you have a working `mmap' system call.  */
+/* #undef HAVE_MMAP */
+
+/* Define if system calls automatically restart after interruption
+   by a signal.  */
+/* #undef HAVE_RESTARTABLE_SYSCALLS */
+
+/* Define if your struct stat has st_blksize.  */
+/* #undef HAVE_ST_BLKSIZE */
+
+/* Define if your struct stat has st_blocks.  */
+/* #undef HAVE_ST_BLOCKS */
+
+/* Define if you have the strcoll function and it is properly defined.	*/
+#define HAVE_STRCOLL 1
+
+/* Define if your struct stat has st_rdev.  */
+#define HAVE_ST_RDEV 1
+
+/* Define if you have the strftime function.  */
+#define HAVE_STRFTIME 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.	*/
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define if your struct tm has tm_zone.  */
+/* #undef HAVE_TM_ZONE */
+
+/* Define if you don't have tm_zone but do have the external array
+   tzname.  */
+#define HAVE_TZNAME 1
+
+/* Define if you have <unistd.h>.  */
+#define HAVE_UNISTD_H 1
+
+/* Define if utime(file, NULL) sets file's timestamp to the present.  */
+/* #undef HAVE_UTIME_NULL */
+
+/* Define if you have <vfork.h>.  */
+/* #undef HAVE_VFORK_H */
+
+/* Define if you have the vprintf function.  */
+#define HAVE_VPRINTF 1
+
+/* Define if you have the wait3 system call.  */
+/* #undef HAVE_WAIT3 */
+
+/* Define if on MINIX.	*/
+/* #undef _MINIX */
+
+/* Define if your struct nlist has an n_un member.  */
+/* #undef NLIST_NAME_UNION */
+
+/* Define if you have <nlist.h>.  */
+/* #undef NLIST_STRUCT */
+
+/* Define if your C compiler doesn't accept -c and -o together.  */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#define pid_t int
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work.  */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define if the setvbuf function takes the buffering type as its second
+   argument and the buffer pointer as the third, as on System V
+   before release 3.  */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#define STACK_DIRECTION -1
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly.  */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define if you have the ANSI C header files.	*/
+#define STDC_HEADERS
+
+/* Define on System V Release 4.  */
+/* #undef SVR4 */
+
+/* Define if `sys_siglist' is declared by <signal.h>.  */
+/* #undef SYS_SIGLIST_DECLARED */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#define uid_t int
+
+/* Define for Encore UMAX.  */
+/* #undef UMAX */
+
+/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
+   instead of <sys/cpustats.h>.  */
+/* #undef UMAX4_3 */
+
+/* Define vfork as fork if vfork does not work.  */
+/* #undef vfork */
+
+/* Name of this package (needed by automake) */
+#define PACKAGE "%PACKAGE%"
+
+/* Version of this package (needed by automake) */
+#define VERSION "%VERSION%"
+
+/* Define to the name of the SCCS `get' command.  */
+#define SCCS_GET "get"
+
+/* Define this if the SCCS `get' command understands the `-G<file>' option.  */
+/* #undef SCCS_GET_MINUS_G */
+
+/* Define this to enable job server support in GNU make.  */
+/* #undef MAKE_JOBSERVER */
+
+/* Define to be the nanoseconds member of struct stat's st_mtim,
+   if it exists.  */
+/* #undef ST_MTIM_NSEC */
+
+/* Define this if the C library defines the variable `sys_siglist'.  */
+/* #undef HAVE_SYS_SIGLIST */
+
+/* Define this if the C library defines the variable `_sys_siglist'.  */
+/* #undef HAVE__SYS_SIGLIST */
+
+/* Define this if you have the `union wait' type in <sys/wait.h>.  */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define if you have the dup2 function.  */
+/* #undef HAVE_DUP2 */
+
+/* Define if you have the getcwd function.  */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getgroups function.  */
+/* #undef HAVE_GETGROUPS */
+
+/* Define if you have the gethostbyname function.  */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define if you have the gethostname function.  */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define if you have the memmove function.  */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the mktemp function.  */
+#define HAVE_MKTEMP 1
+
+/* Define if you have the psignal function.  */
+/* #undef HAVE_PSIGNAL */
+
+/* Define if you have the pstat_getdynamic function.  */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define if you have the setegid function.  */
+/* #undef HAVE_SETEGID */
+
+/* Define if you have the seteuid function.  */
+/* #undef HAVE_SETEUID */
+
+/* Define if you have the setlinebuf function.	*/
+/* #undef HAVE_SETLINEBUF */
+
+/* Define if you have the setregid function.  */
+/* #undef HAVE_SETREGID */
+
+/* Define if you have the setreuid function.  */
+/* #undef HAVE_SETREUID */
+
+/* Define if you have the sigsetmask function.	*/
+/* #undef HAVE_SIGSETMASK */
+
+/* Define if you have the socket function.  */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the strcasecmp function.  */
+/* #undef HAVE_STRCASECMP */
+
+/* Define to 1 if you have the strcmpi function.  */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the stricmp function.  */
+/* #undef HAVE_STRICMP */
+
+/* Define if you have the strerror function.  */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strsignal function.  */
+/* #undef HAVE_STRSIGNAL */
+
+/* Define if you have the wait3 function.  */
+/* #undef HAVE_WAIT3 */
+
+/* Define if you have the waitpid function.  */
+/* #undef HAVE_WAITPID */
+
+/* Define if you have the <dirent.h> header file.  */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <fcntl.h> header file.  */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file.  */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <mach/mach.h> header file.  */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define if you have the <memory.h> header file.  */
+/* #undef HAVE_MEMORY_H */
+
+/* Define if you have the <ndir.h> header file.  */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stdlib.h> header file.  */
+/* #undef HAVE_STDLIB_H */
+
+/* Define if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/dir.h> header file.  */
+#define HAVE_SYS_DIR_H 1
+
+/* Define if you have the <sys/ndir.h> header file.  */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file.  */
+/* #undef HAVE_SYS_PARAM_H */
+
+/* Define if you have the <sys/timeb.h> header file.  */
+/* #undef HAVE_SYS_TIMEB_H */
+
+/* Define if you have the <sys/wait.h> header file.  */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define if you have the <unistd.h> header file.  */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the dgc library (-ldgc).  */
+/* #undef HAVE_LIBDGC */
+
+/* Define if you have the kstat library (-lkstat).  */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define if you have the sun library (-lsun).  */
+/* #undef HAVE_LIBSUN */
+
+/* Define for Case Insensitve behavior */
+#define HAVE_CASE_INSENSITIVE_FS
+
+/* Build host information. */
+#define MAKE_HOST "Amiga"
Index: /tags/kBuild-0.1.4/src/kmk/config.h-vms.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.h-vms.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.h-vms.template	(revision 1780)
@@ -0,0 +1,426 @@
+/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@rmi.de>      -*-C-*-
+
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define to 1 if NLS is requested.  */
+/* #undef ENABLE_NLS */
+
+/* Define as 1 if you have dcgettext.  */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext.  */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if your locale.h file contains LC_MESSAGES.  */
+/* #undef HAVE_LC_MESSAGES */
+
+/* Define to the installation directory for locales.  */
+#define LOCALEDIR ""
+
+/* Define as 1 if you have the stpcpy function.  */
+/* #undef HAVE_STPCPY */
+
+/* Define to 1 if the closedir function returns void instead of int.  */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define for DGUX with <sys/dg_sys_info.h>.  */
+/* #undef DGUX */
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.  */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to `unsigned long' or `unsigned long long'
+   if <inttypes.h> doesn't define.  */
+#define uintmax_t unsigned long
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+/* #undef gid_t */
+
+/* Define to 1 if you have alloca, as a function or macro.  */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).  */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if you don't have vprintf but do have _doprnt.  */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if your system has a working fnmatch function.  */
+/* #undef HAVE_FNMATCH */
+
+/* Define to 1 if your system has its own `getloadavg' function.  */
+/* #undef HAVE_GETLOADAVG */
+
+/* Define to 1 if you have the getmntent function.  */
+/* #undef HAVE_GETMNTENT */
+
+/* Define to 1 if the `long double' type works.  */
+/* #undef HAVE_LONG_DOUBLE */
+
+/* Define to 1 if you support file names longer than 14 characters.  */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define to 1 if you have a working `mmap' system call.  */
+/* #undef HAVE_MMAP */
+
+/* Define to 1 if system calls automatically restart after interruption
+   by a signal.  */
+/* #undef HAVE_RESTARTABLE_SYSCALLS */
+
+/* Define to 1 if your struct stat has st_blksize.  */
+/* #undef HAVE_ST_BLKSIZE */
+
+/* Define to 1 if your struct stat has st_blocks.  */
+/* #undef HAVE_ST_BLOCKS */
+
+/* Define to 1 if you have the strcoll function and it is properly defined.  */
+/* #undef HAVE_STRCOLL */
+
+/* Define to 1 if your struct stat has st_rdev.  */
+/* #undef HAVE_ST_RDEV */
+
+/* Define to 1 if you have the strftime function.  */
+/* #undef HAVE_STRFTIME */
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible.  */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define to 1 if your struct tm has tm_zone.  */
+/* #undef HAVE_TM_ZONE */
+
+/* Define to 1 if you don't have tm_zone but do have the external array
+   tzname.  */
+/* #undef HAVE_TZNAME */
+
+/* Define to 1 if you have <unistd.h>.  */
+#ifdef __DECC
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define to 1 if utime(file, NULL) sets file's timestamp to the present.  */
+/* #undef HAVE_UTIME_NULL */
+
+/* Define to 1 if you have <vfork.h>.  */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the vprintf function.  */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the wait3 system call.  */
+/* #undef HAVE_WAIT3 */
+
+/* Define to 1 if on MINIX.  */
+/* #undef _MINIX */
+
+/* Define to 1 if your struct nlist has an n_un member.  */
+/* #undef NLIST_NAME_UNION */
+
+/* Define to 1 if you have <nlist.h>.  */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together.  */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+/* I assume types.h is available for all 5.0 cc/cxx compilers */
+#if __DECC_VER < 50090000
+#define pid_t int
+#endif
+
+/* Define to 1 if the system does not provide POSIX.1 features except
+   with this defined.  */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for stat and other things to work.  */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define to 1 if the setvbuf function takes the buffering type as its second
+   argument and the buffer pointer as the third, as on System V
+   before release 3.  */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly.  */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files.  */
+/* #undef STDC_HEADERS */
+
+/* Define on System V Release 4.  */
+/* #undef SVR4 */
+
+/* Define to 1 if `sys_siglist' is declared by <signal.h>.  */
+/* #undef SYS_SIGLIST_DECLARED */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#if __DECC_VER < 50090000
+#define uid_t int
+#endif
+
+/* Define for Encore UMAX.  */
+/* #undef UMAX */
+
+/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
+   instead of <sys/cpustats.h>.  */
+/* #undef UMAX4_3 */
+
+/* Define vfork as fork if vfork does not work.  */
+/* #undef vfork */
+
+/* Name of this package (needed by automake) */
+#define PACKAGE "%PACKAGE%"
+
+/* Version of this package (needed by automake) */
+#define VERSION "%VERSION%"
+
+/* Define to the name of the SCCS `get' command.  */
+/* #undef SCCS_GET */
+
+/* Define this if the SCCS `get' command understands the `-G<file>' option.  */
+/* #undef SCCS_GET_MINUS_G */
+
+/* Define this to enable job server support in GNU make.  */
+/* #undef MAKE_JOBSERVER */
+
+/* Define to be the nanoseconds member of struct stat's st_mtim,
+   if it exists.  */
+/* #undef ST_MTIM_NSEC */
+
+/* Define to 1 if the C library defines the variable `sys_siglist'.  */
+/* #undefine HAVE_SYS_SIGLIST */
+
+/* Define to 1 if the C library defines the variable `_sys_siglist'.  */
+/* #undef HAVE__SYS_SIGLIST */
+
+/* Define to 1 if you have the `union wait' type in <sys/wait.h>.  */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the dup2 function.  */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the getcwd function.  */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the getgroups function.  */
+/* #undef HAVE_GETGROUPS */
+
+/* Define to 1 if you have the gethostbyname function.  */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the gethostname function.  */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the getloadavg function.  */
+/* #undef HAVE_GETLOADAVG */
+
+/* Define to 1 if you have the memmove function.  */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the mktemp function.  */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the psignal function.  */
+/* #undef HAVE_PSIGNAL */
+
+/* Define to 1 if you have the pstat_getdynamic function.  */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the setegid function.  */
+/* #undef HAVE_SETEGID */
+
+/* Define to 1 if you have the seteuid function.  */
+/* #undef HAVE_SETEUID */
+
+/* Define to 1 if you have the setlinebuf function.  */
+/* #undef HAVE_SETLINEBUF */
+
+/* Define to 1 if you have the setregid function.  */
+/* #undefine HAVE_SETREGID */
+
+/* Define to 1 if you have the setreuid function.  */
+/* #define HAVE_SETREUID */
+
+/* Define to 1 if you have the sigsetmask function.  */
+#define HAVE_SIGSETMASK 1
+
+/* Define to 1 if you have the socket function.  */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the strcasecmp function.  */
+/* #undef HAVE_STRCASECMP */
+
+/* Define to 1 if you have the strcmpi function.  */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the stricmp function.  */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the strerror function.  */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the strsignal function.  */
+/* #undef HAVE_STRSIGNAL */
+
+/* Define to 1 if you have the wait3 function.  */
+/* #undef HAVE_WAIT3 */
+
+/* Define to 1 if you have the waitpid function.  */
+/* #undef HAVE_WAITPID */
+
+/* Define to 1 if you have the <dirent.h> header file.  */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file.  */
+#ifdef __DECC
+#define HAVE_FCNTL_H 1
+#endif
+
+/* Define to 1 if you have the <limits.h> header file.  */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <mach/mach.h> header file.  */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the <memory.h> header file.  */
+/* #undef HAVE_MEMORY_H */
+
+/* Define to 1 if you have the <ndir.h> header file.  */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file.  */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file.  */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file.  */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file.  */
+/* #undef HAVE_SYS_PARAM_H */
+
+/* Define to 1 if you have the <sys/timeb.h> header file.  */
+#ifndef __GNUC__
+#define HAVE_SYS_TIMEB_H 1
+#endif
+
+/* Define to 1 if you have the <sys/wait.h> header file.  */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define to 1 if you have the dgc library (-ldgc).  */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the kstat library (-lkstat).  */
+/* #undef HAVE_LIBKSTAT *
+
+/* Define to 1 if you have the sun library (-lsun).  */
+/* #undef HAVE_LIBSUN */
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 0
+
+/* Define for case insensitve filenames */
+#define HAVE_CASE_INSENSITIVE_FS 1
+
+/* VMS specific, define it if you want to use case sensitive targets */
+/* #undef WANT_CASE_SENSITIVE_TARGETS */
+
+/* VMS specific, V7.0 has opendir() and friends, so it's undefined */
+/* If you want to use non-VMS code for opendir() etc. on V7.0 and greater
+   define the first or both macros AND change the compile command to get the
+   non-VMS versions linked: (prefix=(all,except=(opendir,...  */
+/* #undef HAVE_VMSDIR_H */
+/* #undef _DIRENT_HAVE_D_NAMLEN */
+
+/* On older systems without 7.0 backport of CRTL the first one is defined */
+#ifdef __CRTL_VER
+# if __CRTL_VER < 70000000
+#  define HAVE_VMSDIR_H 1
+# endif
+#else
+# if __VMS_VER < 70000000
+#  define HAVE_VMSDIR_H 1
+# endif
+#endif
+
+#if defined(HAVE_VMSDIR_H) && defined(HAVE_DIRENT_H)
+#undef HAVE_DIRENT_H
+#endif
+
+#define HAVE_STDLIB_H 1
+#define INCLUDEDIR "sys$sysroot:[syslib]"
+#define LIBDIR "sys$sysroot:[syslib]"
+
+/* Don't use RTL functions of OpenVMS */
+#ifdef __DECC
+#include <stdio.h>
+#include <unistd.h>
+#define getopt   gnu_getopt
+#define optarg   gnu_optarg
+#define optopt   gnu_optopt
+#define optind   gnu_optind
+#define opterr   gnu_opterr
+#define globfree gnu_globfree
+#define glob     gnu_glob
+#endif
+
+/* Define if using alloca.c.  */
+/* #undef C_ALLOCA */
+/* maybe this should be placed into make.h */
+#if	defined(__VAX) && defined(__DECC)
+#define alloca(n)	__ALLOCA(n)
+#endif
+
+/* Build host information. */
+#define MAKE_HOST "VMS"
Index: /tags/kBuild-0.1.4/src/kmk/config.h.W32.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.h.W32.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.h.W32.template	(revision 1780)
@@ -0,0 +1,502 @@
+/* config.h.W32 -- hand-massaged config.h file for Windows builds       -*-C-*-
+
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* Suppress some Visual C++ warnings.
+   Maybe after the code cleanup for ISO C we can remove some/all of these.  */
+#if _MSC_VER > 1000
+# pragma warning(disable:4100) /* unreferenced formal parameter */
+# pragma warning(disable:4102) /* unreferenced label */
+# pragma warning(disable:4127) /* conditional expression is constant */
+# pragma warning(disable:4131) /* uses old-style declarator */
+# pragma warning(disable:4702) /* unreachable code */
+#endif
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/*#define C_GETLOADAVG 1*/
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 0
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.
+   */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the `bsd_signal' function. */
+/* #undef HAVE_BSD_SIGNAL */
+
+/* Use case insensitive file names */
+/* #undef HAVE_CASE_INSENSITIVE_FS */
+
+/* Define if you have the clock_gettime function. */
+/* #undef HAVE_CLOCK_GETTIME */
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <direct.h> header file, and it defines getcwd()
+   and chdir().
+   */
+#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__INTERIX)
+# define HAVE_DIRECT_H 1
+#endif
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Use platform specific coding */
+#define HAVE_DOS_PATHS 1
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopen' function. */
+/*#define HAVE_FDOPEN 1*/
+
+/* Define to 1 if you have the `fork' function. */
+/* #undef HAVE_FORK */
+
+/* Define to 1 if you have the `getcwd' function.  */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgroups' function. */
+/* #undef HAVE_GETGROUPS */
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gethostname' function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+/* #undef HAVE_GETLOADAVG */
+
+/* Define to 1 if you have the `getrlimit' function. */
+/* #undef HAVE_GETRLIMIT */
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define if you have a standard gettimeofday function */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define if you have the iconv() function. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/*#define HAVE_INTTYPES_H 1*/
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+/*#define HAVE_LOCALE_H 1*/
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+/* #undef HAVE_MKSTEMP */
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the `pipe' function. */
+/* #undef HAVE_PIPE */
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `realpath' function. */
+/* #undef HAVE_REALPATH */
+
+/* Define if <signal.h> defines the SA_RESTART constant. */
+/* #undef HAVE_SA_RESTART */
+
+/* Define to 1 if you have the `setegid' function. */
+/* #undef HAVE_SETEGID */
+
+/* Define to 1 if you have the `seteuid' function. */
+/* #undef HAVE_SETEUID */
+
+/* Define to 1 if you have the `setlinebuf' function. */
+/* #undef HAVE_SETLINEBUF */
+
+/* Define to 1 if you have the `setlocale' function. */
+/*#define HAVE_SETLOCALE 1*/
+
+/* Define to 1 if you have the `setregid' function. */
+/* #undef HAVE_SETREGID */
+
+/* Define to 1 if you have the `setreuid' function. */
+/* #undef HAVE_SETREUID */
+
+/* Define to 1 if you have the `setrlimit' function. */
+/* #undef HAVE_SETRLIMIT */
+
+/* Define to 1 if you have the `setvbuf' function. */
+/*#define HAVE_SETVBUF 1 */
+
+/* Define to 1 if you have the `sigaction' function. */
+/* #undef HAVE_SIGACTION */
+
+/* Define to 1 if you have the `sigsetmask' function. */
+/* #undef HAVE_SIGSETMASK */
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/*#define HAVE_STDINT_H 1*/
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+/* #undef HAVE_STRCASECMP */
+
+/* Define to 1 if you have the `strcmpi' function. */
+#define HAVE_STRCMPI 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+   */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1 /* bird */
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+/* #define HAVE_STRINGS_H 1 */
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strsignal' function. */
+/* #undef HAVE_STRSIGNAL */
+
+/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+/* #define HAVE_SYS_PARAM_H 1 */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+/* #undef HAVE_SYS_RESOURCE_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+/* #define HAVE_SYS_STAT_H 1 */
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+/*#define HAVE_SYS_TIMEB_H 1*/
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/*#define HAVE_SYS_TIME_H 1*/
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+/*#define HAVE_SYS_TYPES_H 1*/
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define this if you have the \`union wait' type in <sys/wait.h>. */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #define HAVE_UNISTD_H 1*/
+
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
+
+/* Define to 1 if you have the `vfork' function. */
+/* #undef HAVE_VFORK */
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+
+/* Define to 1 if you have the `wait3' function. */
+/* #undef HAVE_WAIT3 */
+
+/* Define to 1 if you have the `waitpid' function. */
+/* #undef HAVE_WAITPID */
+
+/* Define to 1 if `fork' works. */
+/* #undef HAVE_WORKING_FORK */
+
+/* Define to 1 if `vfork' works. */
+/* #undef HAVE_WORKING_VFORK */
+
+/* Build host information. */
+#define MAKE_HOST "Windows32"
+
+/* Define this to enable job server support in GNU make. */
+/* #undef MAKE_JOBSERVER */
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+   on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Define if struct nlist.n_name is a pointer rather than an array. */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of this package (needed by automake) */
+#define PACKAGE "%PACKAGE%"
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the name of the SCCS 'get' command. */
+#define SCCS_GET "echo no sccs get"
+
+/* Define this if the SCCS 'get' command understands the '-G<file>' option. */
+/* #undef SCCS_GET_MINUS_G */
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+   second argument and the buffer pointer as the third, as on System V before
+   release 3. */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if struct stat contains a nanoseconds field */
+/* #undef ST_MTIM_NSEC */
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+   <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Version number of package */
+#define VERSION "%VERSION%"
+
+/* Define if using the dmalloc debugging malloc package */
+/* #undef WITH_DMALLOC */
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#define _POSIX_SOURCE 1
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+/*#define __PROTOTYPES 1*/
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#define gid_t int
+
+/* Define to `int' if <sys/types.h> does not define. */
+#define pid_t int
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#define uid_t int
+
+/* Define uintmax_t if not defined in <stdint.h> or <inttypes.h>. */
+#define uintmax_t unsigned long
+
+/* Define as `fork' if `vfork' does not work. */
+/*#define vfork fork*/
+
+/* Define to `unsigned long' or `unsigned long long'
+   if <inttypes.h> doesn't define.  */
+#define uintmax_t unsigned long
+
+/* Define if you support file names longer than 14 characters.  */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if your struct stat has st_rdev.  */
+#undef HAVE_ST_RDEV
+#define HAVE_ST_RDEV 1
+
+/* Define if you have the strftime function.  */
+#undef HAVE_STRFTIME
+#define HAVE_STRFTIME 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define if your struct tm has tm_zone.  */
+/* #undef HAVE_TM_ZONE */
+
+/* Define if you don't have tm_zone but do have the external array
+   tzname.  */
+#undef HAVE_TZNAME
+#define HAVE_TZNAME 1
+
+/* Define if utime(file, NULL) sets file's timestamp to the present.  */
+#undef HAVE_UTIME_NULL
+#define HAVE_UTIME_NULL 1
+
+/* Define to the installation directory for locales.  */
+#define LOCALEDIR ""
+
+/*
+ * Refer to README.W32 for info on the following settings
+ */
+
+
+/*
+ * If you have a shell that does not grok 'sh -c quoted-command-line'
+ * correctly, you need this setting. Please see below for specific
+ * shell support.
+ */
+/*#define BATCH_MODE_ONLY_SHELL 1 */
+
+/*
+ * Define if you have the Cygnus "Cygwin" GNU Windows32 tool set.
+ * Do NOT define BATCH_MODE_ONLY_SHELL if you define HAVE_CYGWIN_SHELL
+ */
+/*#define HAVE_CYGWIN_SHELL 1 */
+
+/*
+ * Define if you have the MKS tool set or shell. Do NOT define
+ * BATCH_MODE_ONLY_SHELL if you define HAVE_MKS_SHELL
+ */
+/*#define HAVE_MKS_SHELL 1 */
+
+/*
+ * Enforce the mutual exclusivity restriction.
+ */
+#ifdef HAVE_MKS_SHELL
+#undef BATCH_MODE_ONLY_SHELL
+#endif
+
+#ifdef HAVE_CYGWIN_SHELL
+#undef BATCH_MODE_ONLY_SHELL
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/config.h.darwin
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.h.darwin	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.h.darwin	(revision 1780)
@@ -0,0 +1,426 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/* #undef C_GETLOADAVG */
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 0
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.
+   */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the `bsd_signal' function. */
+#define HAVE_BSD_SIGNAL 1
+
+/* Use case insensitive file names */
+/* #undef HAVE_CASE_INSENSITIVE_FS */
+
+/* Define to 1 if you have the clock_gettime function. */
+/* #undef HAVE_CLOCK_GETTIME */
+
+/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL_SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL__SYS_SIGLIST 0
+
+/* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL___SYS_SIGLIST 0
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Use platform specific coding */
+/* #undef HAVE_DOS_PATHS */
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopen' function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgroups' function. */
+#define HAVE_GETGROUPS 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gethostname' function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+#define HAVE_GETLOADAVG 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have a standard gettimeofday function */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if <signal.h> defines the SA_RESTART constant. */
+#define HAVE_SA_RESTART 1
+
+/* Define to 1 if you have the `setegid' function. */
+#define HAVE_SETEGID 1
+
+/* Define to 1 if you have the `seteuid' function. */
+#define HAVE_SETEUID 1
+
+/* Define to 1 if you have the `setlinebuf' function. */
+#define HAVE_SETLINEBUF 1
+
+/* Define to 1 if you have the `setlocale' function. */
+/* #undef HAVE_SETLOCALE */
+
+/* Define to 1 if you have the `setregid' function. */
+#define HAVE_SETREGID 1
+
+/* Define to 1 if you have the `setreuid' function. */
+#define HAVE_SETREUID 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the `setvbuf' function. */
+#define HAVE_SETVBUF 1
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the `sigsetmask' function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+   */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the \`union wait' type in <sys/wait.h>. */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the `wait3' function. */
+#define HAVE_WAIT3 1
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Build host information. */
+#define MAKE_HOST "i686-apple-darwin8.8.1"
+
+/* Define to 1 to enable job server support in GNU make. */
+#define MAKE_JOBSERVER 1
+
+/* Define to 1 to enable symbolic link timestamp checking. */
+#define MAKE_SYMLINKS 1
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+   on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Define to 1 if struct nlist.n_name is a pointer rather than an array. */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "make"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-make@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU make"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU make 3.81.90"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "make"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.81.90"
+
+/* Define to the character that separates directories in PATH. */
+#define PATH_SEPARATOR_CHAR ':'
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the name of the SCCS 'get' command. */
+#define SCCS_GET "get"
+
+/* Define to 1 if the SCCS 'get' command understands the '-G<file>' option. */
+/* #undef SCCS_GET_MINUS_G */
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+   second argument and the buffer pointer as the third, as on System V before
+   release 3. */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if struct stat contains a nanoseconds field */
+/* #undef ST_MTIM_NSEC */
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+   <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Version number of package */
+#define VERSION "3.81.90"
+
+/* Use platform specific coding */
+/* #undef WINDOWS32 */
+
+/* Define if using the dmalloc debugging malloc package */
+/* #undef WITH_DMALLOC */
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#define __PROTOTYPES 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define uintmax_t if not defined in <stdint.h> or <inttypes.h>. */
+/* #undef uintmax_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
Index: /tags/kBuild-0.1.4/src/kmk/config.h.freebsd
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.h.freebsd	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.h.freebsd	(revision 1780)
@@ -0,0 +1,430 @@
+/* config.h.  Generated by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/* #undef C_GETLOADAVG */
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 0
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.
+   */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the `bsd_signal' function. */
+/* #undef HAVE_BSD_SIGNAL */
+
+/* Use case insensitive file names */
+/* #undef HAVE_CASE_INSENSITIVE_FS */
+
+/* Define to 1 if you have the clock_gettime function. */
+/* #undef HAVE_CLOCK_GETTIME */
+
+/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL_SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL__SYS_SIGLIST 0
+
+/* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL___SYS_SIGLIST 0
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Use platform specific coding */
+/* #undef HAVE_DOS_PATHS */
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopen' function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgroups' function. */
+#define HAVE_GETGROUPS 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gethostname' function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+#define HAVE_GETLOADAVG 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have a standard gettimeofday function */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if <signal.h> defines the SA_RESTART constant. */
+#define HAVE_SA_RESTART 1
+
+/* Define to 1 if you have the `setegid' function. */
+#define HAVE_SETEGID 1
+
+/* Define to 1 if you have the `seteuid' function. */
+#define HAVE_SETEUID 1
+
+/* Define to 1 if you have the `setlinebuf' function. */
+#define HAVE_SETLINEBUF 1
+
+/* Define to 1 if you have the `setlocale' function. */
+/* #undef HAVE_SETLOCALE */
+
+/* Define to 1 if you have the `setregid' function. */
+#define HAVE_SETREGID 1
+
+/* Define to 1 if you have the `setreuid' function. */
+#define HAVE_SETREUID 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the `setvbuf' function. */
+#define HAVE_SETVBUF 1
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the `sigsetmask' function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+   */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the \`union wait' type in <sys/wait.h>. */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the `wait3' function. */
+#define HAVE_WAIT3 1
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Build host information. */
+#if defined(__X86__) || defined(__i386__) || defined(__I386__)
+#define MAKE_HOST "i386-unknown-freebsd6.2"
+#else
+#define MAKE_HOST "amd64-unknown-freebsd6.2"
+#endif
+
+/* Define to 1 to enable job server support in GNU make. */
+#define MAKE_JOBSERVER 1
+
+/* Define to 1 to enable symbolic link timestamp checking. */
+#define MAKE_SYMLINKS 1
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+   on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Define to 1 if struct nlist.n_name is a pointer rather than an array. */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "make"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-make@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU make"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU make 3.81.90"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "make"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.81.90"
+
+/* Define to the character that separates directories in PATH. */
+#define PATH_SEPARATOR_CHAR ':'
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the name of the SCCS 'get' command. */
+#define SCCS_GET "get"
+
+/* Define to 1 if the SCCS 'get' command understands the '-G<file>' option. */
+/* #undef SCCS_GET_MINUS_G */
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+   second argument and the buffer pointer as the third, as on System V before
+   release 3. */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if struct stat contains a nanoseconds field */
+/* #undef ST_MTIM_NSEC */
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+   <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Version number of package */
+#define VERSION "3.81.90"
+
+/* Use platform specific coding */
+/* #undef WINDOWS32 */
+
+/* Define if using the dmalloc debugging malloc package */
+/* #undef WITH_DMALLOC */
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#define __PROTOTYPES 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define uintmax_t if not defined in <stdint.h> or <inttypes.h>. */
+/* #undef uintmax_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
Index: /tags/kBuild-0.1.4/src/kmk/config.h.linux
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.h.linux	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.h.linux	(revision 1780)
@@ -0,0 +1,426 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/* #undef C_GETLOADAVG */
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 1
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.
+   */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the `bsd_signal' function. */
+#define HAVE_BSD_SIGNAL 1
+
+/* Use case insensitive file names */
+/* #undef HAVE_CASE_INSENSITIVE_FS */
+
+/* Define to 1 if you have the clock_gettime function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL_SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL__SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL___SYS_SIGLIST 0
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Use platform specific coding */
+/* #undef HAVE_DOS_PATHS */
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopen' function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgroups' function. */
+#define HAVE_GETGROUPS 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gethostname' function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+#define HAVE_GETLOADAVG 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have a standard gettimeofday function */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if <signal.h> defines the SA_RESTART constant. */
+#define HAVE_SA_RESTART 1
+
+/* Define to 1 if you have the `setegid' function. */
+#define HAVE_SETEGID 1
+
+/* Define to 1 if you have the `seteuid' function. */
+#define HAVE_SETEUID 1
+
+/* Define to 1 if you have the `setlinebuf' function. */
+#define HAVE_SETLINEBUF 1
+
+/* Define to 1 if you have the `setlocale' function. */
+/* #undef HAVE_SETLOCALE */
+
+/* Define to 1 if you have the `setregid' function. */
+#define HAVE_SETREGID 1
+
+/* Define to 1 if you have the `setreuid' function. */
+#define HAVE_SETREUID 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the `setvbuf' function. */
+#define HAVE_SETVBUF 1
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the `sigsetmask' function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+   */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the \`union wait' type in <sys/wait.h>. */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the `wait3' function. */
+#define HAVE_WAIT3 1
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Build host information. */
+#define MAKE_HOST "i686-pc-linux-gnu"
+
+/* Define to 1 to enable job server support in GNU make. */
+#define MAKE_JOBSERVER 1
+
+/* Define to 1 to enable symbolic link timestamp checking. */
+#define MAKE_SYMLINKS 1
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+   on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Define to 1 if struct nlist.n_name is a pointer rather than an array. */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "make"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-make@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU make"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU make 3.81.90"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "make"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.81.90"
+
+/* Define to the character that separates directories in PATH. */
+#define PATH_SEPARATOR_CHAR ':'
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the name of the SCCS 'get' command. */
+#define SCCS_GET "get"
+
+/* Define to 1 if the SCCS 'get' command understands the '-G<file>' option. */
+/* #undef SCCS_GET_MINUS_G */
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+   second argument and the buffer pointer as the third, as on System V before
+   release 3. */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if struct stat contains a nanoseconds field */
+#define ST_MTIM_NSEC tv_nsec
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+   <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Version number of package */
+#define VERSION "3.81.90"
+
+/* Use platform specific coding */
+/* #undef WINDOWS32 */
+
+/* Define if using the dmalloc debugging malloc package */
+/* #undef WITH_DMALLOC */
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#define __PROTOTYPES 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define uintmax_t if not defined in <stdint.h> or <inttypes.h>. */
+/* #undef uintmax_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
Index: /tags/kBuild-0.1.4/src/kmk/config.h.os2
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.h.os2	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.h.os2	(revision 1780)
@@ -0,0 +1,461 @@
+/* config.h.  Generated by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/* #undef C_GETLOADAVG */
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#define ENABLE_NLS 1
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 0
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.
+   */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the `bsd_signal' function. */
+#define HAVE_BSD_SIGNAL 1
+
+/* Use case insensitive file names */
+/* #undef HAVE_CASE_INSENSITIVE_FS */
+
+/* Define if you have the clock_gettime function. */
+/* #undef HAVE_CLOCK_GETTIME */
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#define HAVE_DCGETTEXT 1
+
+/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL_SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL__SYS_SIGLIST 0
+
+/* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL___SYS_SIGLIST 0
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Use platform specific coding */
+#define HAVE_DOS_PATHS 1
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopen' function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgroups' function. */
+#define HAVE_GETGROUPS 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gethostname' function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+#define HAVE_GETLOADAVG 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#define HAVE_GETTEXT 1
+
+/* Define if you have a standard gettimeofday function */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the iconv() function. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define if <signal.h> defines the SA_RESTART constant. */
+#define HAVE_SA_RESTART 1
+
+/* Define to 1 if you have the `setegid' function. */
+#define HAVE_SETEGID 1
+
+/* Define to 1 if you have the `seteuid' function. */
+#define HAVE_SETEUID 1
+
+/* Define to 1 if you have the `setlinebuf' function. */
+#define HAVE_SETLINEBUF 1
+
+/* Define to 1 if you have the `setlocale' function. */
+/* #undef HAVE_SETLOCALE */
+
+/* Define to 1 if you have the `setregid' function. */
+#define HAVE_SETREGID 1
+
+/* Define to 1 if you have the `setreuid' function. */
+#define HAVE_SETREUID 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the `setvbuf' function. */
+#define HAVE_SETVBUF 1
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the `sigsetmask' function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+/* #undef HAVE_STRCASECMP */
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+   */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define this if you have the \`union wait' type in <sys/wait.h>. */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
+
+/* Define to 1 if you have the `vfork' function. */
+/* #undef HAVE_VFORK */
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the `wait3' function. */
+#define HAVE_WAIT3 1
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+/* #undef HAVE_WORKING_VFORK */
+
+/* Build host information. */
+#define MAKE_HOST "i386-pc-os2-emx"
+
+/* Define this to enable job server support in GNU make. */
+#define MAKE_JOBSERVER 1
+
+/* Define this to enable symbolic link timestamp checking. */
+#define MAKE_SYMLINKS 1
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+   on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Define if struct nlist.n_name is a pointer rather than an array. */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "make"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-make@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU make"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU make 3.81"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "make"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.81"
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the name of the SCCS 'get' command. */
+#define SCCS_GET "get"
+
+/* Define this if the SCCS 'get' command understands the '-G<file>' option. */
+/* #undef SCCS_GET_MINUS_G */
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+   second argument and the buffer pointer as the third, as on System V before
+   release 3. */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if struct stat contains a nanoseconds field */
+/* #undef ST_MTIM_NSEC */
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+   <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Version number of package */
+#define VERSION "3.81"
+
+/* Use platform specific coding */
+/* #undef WINDOWS32 */
+
+/* Define if using the dmalloc debugging malloc package */
+/* #undef WITH_DMALLOC */
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#define __PROTOTYPES 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define uintmax_t if not defined in <stdint.h> or <inttypes.h>. */
+/* #undef uintmax_t */
+
+/* Define as `fork' if `vfork' does not work. */
+#define vfork fork
+
+/*
+ * Modifications:
+ */
+
+/* Define to the installation directory for locales.  */
+#define LOCALEDIR ""
+
+/*
+ * If you have a shell that does not grok 'sh -c quoted-command-line'
+ * correctly, you need this setting. Please see below for specific
+ * shell support.
+ */
+#define BATCH_MODE_ONLY_SHELL 1
+
+#define _DIRENT_HAVE_D_NAMLEN 1
+#define _DIRENT_HAVE_D_TYPE   1
+
+#define INCLUDEDIR "."
+#define LIBDIR "."
+
Index: /tags/kBuild-0.1.4/src/kmk/config.h.solaris
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.h.solaris	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.h.solaris	(revision 1780)
@@ -0,0 +1,426 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/* #undef C_GETLOADAVG */
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 1
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.
+   */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the `bsd_signal' function. */
+#define HAVE_BSD_SIGNAL 1
+
+/* Use case insensitive file names */
+/* #undef HAVE_CASE_INSENSITIVE_FS */
+
+/* Define to 1 if you have the clock_gettime function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL_SYS_SIGLIST 0
+
+/* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL__SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL___SYS_SIGLIST 0
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#define HAVE_DOPRNT 1
+
+/* Use platform specific coding */
+/* #undef HAVE_DOS_PATHS */
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopen' function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgroups' function. */
+#define HAVE_GETGROUPS 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gethostname' function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+#define HAVE_GETLOADAVG 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have a standard gettimeofday function */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+#define HAVE_LIBKSTAT 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if <signal.h> defines the SA_RESTART constant. */
+#define HAVE_SA_RESTART 1
+
+/* Define to 1 if you have the `setegid' function. */
+#define HAVE_SETEGID 1
+
+/* Define to 1 if you have the `seteuid' function. */
+#define HAVE_SETEUID 1
+
+/* Define to 1 if you have the `setlinebuf' function. */
+#define HAVE_SETLINEBUF 1
+
+/* Define to 1 if you have the `setlocale' function. */
+/* #undef HAVE_SETLOCALE */
+
+/* Define to 1 if you have the `setregid' function. */
+#define HAVE_SETREGID 1
+
+/* Define to 1 if you have the `setreuid' function. */
+#define HAVE_SETREUID 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the `setvbuf' function. */
+#define HAVE_SETVBUF 1
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the `sigsetmask' function. */
+/* #undef HAVE_SIGSETMASK */
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+   */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the \`union wait' type in <sys/wait.h>. */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the `wait3' function. */
+#define HAVE_WAIT3 1
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Build host information. */
+#define MAKE_HOST "i386-pc-solaris2.11"
+
+/* Define to 1 to enable job server support in GNU make. */
+#define MAKE_JOBSERVER 1
+
+/* Define to 1 to enable symbolic link timestamp checking. */
+#define MAKE_SYMLINKS 1
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+   on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Define to 1 if struct nlist.n_name is a pointer rather than an array. */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "make"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-make@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU make"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU make 3.81.90"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "make"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.81.90"
+
+/* Define to the character that separates directories in PATH. */
+#define PATH_SEPARATOR_CHAR ':'
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the name of the SCCS 'get' command. */
+#define SCCS_GET "get"
+
+/* Define to 1 if the SCCS 'get' command understands the '-G<file>' option. */
+#define SCCS_GET_MINUS_G 1
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+   second argument and the buffer pointer as the third, as on System V before
+   release 3. */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if struct stat contains a nanoseconds field */
+#define ST_MTIM_NSEC tv_nsec
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+   <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Version number of package */
+#define VERSION "3.81.90"
+
+/* Use platform specific coding */
+/* #undef WINDOWS32 */
+
+/* Define if using the dmalloc debugging malloc package */
+/* #undef WITH_DMALLOC */
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#define __PROTOTYPES 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define uintmax_t if not defined in <stdint.h> or <inttypes.h>. */
+/* #undef uintmax_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
Index: /tags/kBuild-0.1.4/src/kmk/config.h.win
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config.h.win	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config.h.win	(revision 1780)
@@ -0,0 +1,526 @@
+/* config.h.W32 -- hand-massaged config.h file for Windows builds       -*-C-*-
+
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* Suppress some Visual C++ warnings.
+   Maybe after the code cleanup for ISO C we can remove some/all of these.  */
+#if _MSC_VER > 1000
+# pragma warning(disable:4100) /* unreferenced formal parameter */
+# pragma warning(disable:4102) /* unreferenced label */
+# pragma warning(disable:4127) /* conditional expression is constant */
+# pragma warning(disable:4131) /* uses old-style declarator */
+# pragma warning(disable:4702) /* unreachable code */
+#endif
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/*#define C_GETLOADAVG 1*/
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 0
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.
+   */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the `bsd_signal' function. */
+/* #undef HAVE_BSD_SIGNAL */
+
+/* Use case insensitive file names */
+/* #undef HAVE_CASE_INSENSITIVE_FS */
+
+/* Define if you have the clock_gettime function. */
+/* #undef HAVE_CLOCK_GETTIME */
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <direct.h> header file, and it defines getcwd()
+   and chdir().
+   */
+#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__INTERIX)
+# define HAVE_DIRECT_H 1
+#endif
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Use platform specific coding */
+#define HAVE_DOS_PATHS 1
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopen' function. */
+/*#define HAVE_FDOPEN 1*/
+
+/* Define to 1 if you have the `fork' function. */
+/* #undef HAVE_FORK */
+
+/* Define to 1 if you have the `getcwd' function.  */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgroups' function. */
+/* #undef HAVE_GETGROUPS */
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gethostname' function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+/* #undef HAVE_GETLOADAVG */
+
+/* Define to 1 if you have the `getrlimit' function. */
+/* #undef HAVE_GETRLIMIT */
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define if you have a standard gettimeofday function */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define if you have the iconv() function. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/*#define HAVE_INTTYPES_H 1*/
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+/*#define HAVE_LOCALE_H 1*/
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+/* #undef HAVE_MKSTEMP */
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the `pipe' function. */
+/* #undef HAVE_PIPE */
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `realpath' function. */
+/* #undef HAVE_REALPATH */
+
+/* Define if <signal.h> defines the SA_RESTART constant. */
+/* #undef HAVE_SA_RESTART */
+
+/* Define to 1 if you have the `setegid' function. */
+/* #undef HAVE_SETEGID */
+
+/* Define to 1 if you have the `seteuid' function. */
+/* #undef HAVE_SETEUID */
+
+/* Define to 1 if you have the `setlinebuf' function. */
+/* #undef HAVE_SETLINEBUF */
+
+/* Define to 1 if you have the `setlocale' function. */
+/*#define HAVE_SETLOCALE 1*/
+
+/* Define to 1 if you have the `setregid' function. */
+/* #undef HAVE_SETREGID */
+
+/* Define to 1 if you have the `setreuid' function. */
+/* #undef HAVE_SETREUID */
+
+/* Define to 1 if you have the `setrlimit' function. */
+/* #undef HAVE_SETRLIMIT */
+
+/* Define to 1 if you have the `setvbuf' function. */
+/*#define HAVE_SETVBUF 1 */
+
+/* Define to 1 if you have the `sigaction' function. */
+/* #undef HAVE_SIGACTION */
+
+/* Define to 1 if you have the `sigsetmask' function. */
+/* #undef HAVE_SIGSETMASK */
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/*#define HAVE_STDINT_H 1*/
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+/* #undef HAVE_STRCASECMP */
+
+/* Define to 1 if you have the `strcmpi' function. */
+#define HAVE_STRCMPI 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+   */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1 /* bird */
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+/* #define HAVE_STRINGS_H 1 */
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strsignal' function. */
+/* #undef HAVE_STRSIGNAL */
+
+/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+/* #define HAVE_SYS_PARAM_H 1 */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+/* #undef HAVE_SYS_RESOURCE_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+/* #define HAVE_SYS_STAT_H 1 */
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+/*#define HAVE_SYS_TIMEB_H 1*/
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/*#define HAVE_SYS_TIME_H 1*/
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+/*#define HAVE_SYS_TYPES_H 1*/
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define this if you have the \`union wait' type in <sys/wait.h>. */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #define HAVE_UNISTD_H 1*/
+
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
+
+/* Define to 1 if you have the `vfork' function. */
+/* #undef HAVE_VFORK */
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+
+/* Define to 1 if you have the `wait3' function. */
+/* #undef HAVE_WAIT3 */
+
+/* Define to 1 if you have the `waitpid' function. */
+/* #undef HAVE_WAITPID */
+
+/* Define to 1 if `fork' works. */
+/* #undef HAVE_WORKING_FORK */
+
+/* Define to 1 if `vfork' works. */
+/* #undef HAVE_WORKING_VFORK */
+
+/* Build host information. */
+#define MAKE_HOST "Windows32"
+
+/* Define this to enable job server support in GNU make. */
+/* #undef MAKE_JOBSERVER */
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+   on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Define if struct nlist.n_name is a pointer rather than an array. */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of this package (needed by automake) */
+#define PACKAGE "make"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-make@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU make"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU make 3.81.90"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "make"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.81.90"
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the name of the SCCS 'get' command. */
+#define SCCS_GET "echo no sccs get"
+
+/* Define this if the SCCS 'get' command understands the '-G<file>' option. */
+/* #undef SCCS_GET_MINUS_G */
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+   second argument and the buffer pointer as the third, as on System V before
+   release 3. */
+/* #undef SETVBUF_REVERSED */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if struct stat contains a nanoseconds field */
+/* #undef ST_MTIM_NSEC */
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+   <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Version number of package */
+#define VERSION "3.81.90"
+
+/* Define if using the dmalloc debugging malloc package */
+/* #undef WITH_DMALLOC */
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#define _POSIX_SOURCE 1
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+/*#define __PROTOTYPES 1*/
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#define gid_t int
+
+/* Define to `int' if <sys/types.h> does not define. */
+#define pid_t int
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#define uid_t int
+
+/* Define uintmax_t if not defined in <stdint.h> or <inttypes.h>. */
+#define uintmax_t unsigned long
+
+/* Define as `fork' if `vfork' does not work. */
+/*#define vfork fork*/
+
+/* Define to `unsigned long' or `unsigned long long'
+   if <inttypes.h> doesn't define.  */
+#define uintmax_t unsigned long
+
+/* Define if you support file names longer than 14 characters.  */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if your struct stat has st_rdev.  */
+#undef HAVE_ST_RDEV
+#define HAVE_ST_RDEV 1
+
+/* Define if you have the strftime function.  */
+#undef HAVE_STRFTIME
+#define HAVE_STRFTIME 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define if your struct tm has tm_zone.  */
+/* #undef HAVE_TM_ZONE */
+
+/* Define if you don't have tm_zone but do have the external array
+   tzname.  */
+#undef HAVE_TZNAME
+#define HAVE_TZNAME 1
+
+/* Define if utime(file, NULL) sets file's timestamp to the present.  */
+#undef HAVE_UTIME_NULL
+#define HAVE_UTIME_NULL 1
+
+/* Define to the installation directory for locales.  */
+#define LOCALEDIR ""
+
+/*
+ * Refer to README.W32 for info on the following settings
+ */
+
+
+/*
+ * If you have a shell that does not grok 'sh -c quoted-command-line'
+ * correctly, you need this setting. Please see below for specific
+ * shell support.
+ */
+/*#define BATCH_MODE_ONLY_SHELL 1 */
+
+/*
+ * Define if you have the Cygnus "Cygwin" GNU Windows32 tool set.
+ * Do NOT define BATCH_MODE_ONLY_SHELL if you define HAVE_CYGWIN_SHELL
+ */
+/*#define HAVE_CYGWIN_SHELL 1 */
+
+/*
+ * Define if you have the MKS tool set or shell. Do NOT define
+ * BATCH_MODE_ONLY_SHELL if you define HAVE_MKS_SHELL
+ */
+/*#define HAVE_MKS_SHELL 1 */
+
+/*
+ * Enforce the mutual exclusivity restriction.
+ */
+#ifdef HAVE_MKS_SHELL
+#undef BATCH_MODE_ONLY_SHELL
+#endif
+
+#ifdef HAVE_CYGWIN_SHELL
+#undef BATCH_MODE_ONLY_SHELL
+#endif
+
+/* bird hacks */
+#include <sys/stat.h>
+extern int my_stat(const char *, struct stat *);
+#define stat(_path, _st) my_stat(_path, _st)
+
+/* cygwin sucks to much in one end or the other. */
+#define BATCH_MODE_ONLY_SHELL
+
Index: /tags/kBuild-0.1.4/src/kmk/config/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config/ChangeLog	(revision 1780)
@@ -0,0 +1,45 @@
+2006-03-09  Paul Smith  <psmith@gnu.org>
+
+	* dospaths.m4: Add MSYS to the list of targets allowing DOS-style
+	pathnames.  Reported by David Ergo <david.ergo@alterface.com>.
+
+2005-07-01  Paul D. Smith  <psmith@gnu.org>
+
+	* Makefile.am (EXTRA_DIST): Added more M4 files to EXTRA_DIST, so
+	users can re-run aclocal.
+
+2003-04-30  Paul D. Smith  <psmith@gnu.org>
+
+	* dospaths.m4: New macro to test for DOS-style pathnames, based on
+	coreutils 5.0 "dos.m4" by Jim Meyering.
+
+2002-04-21  gettextize  <bug-gnu-gettext@gnu.org>
+
+	* codeset.m4: New file, from gettext-0.11.1.
+	* gettext.m4: New file, from gettext-0.11.1.
+	* glibc21.m4: New file, from gettext-0.11.1.
+	* iconv.m4: New file, from gettext-0.11.1.
+	* isc-posix.m4: New file, from gettext-0.11.1.
+	* lcmessage.m4: New file, from gettext-0.11.1.
+	* lib-ld.m4: New file, from gettext-0.11.1.
+	* lib-link.m4: New file, from gettext-0.11.1.
+	* lib-prefix.m4: New file, from gettext-0.11.1.
+	* progtest.m4: New file, from gettext-0.11.1.
+	* Makefile.am: New file.
+
+
+
+Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/config/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config/Makefile.am	(revision 1780)
@@ -0,0 +1,22 @@
+# -*-Makefile-*-, or close enough
+# Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+EXTRA_DIST =	codeset.m4 gettext.m4 glibc21.m4 iconv.m4 isc-posix.m4 nls.m4 \
+		intdiv0.m4 inttypes-pri.m4 inttypes.m4 inttypes_h.m4 \
+		isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 \
+		progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 longlong.m4 \
+		dospaths.m4 po.m4 signed.m4 longdouble.m4 wchar_t.m4 \
+		wint_t.m4 intmax.m4 printf-posix.m4 xsize.m4 size_max.m4
Index: /tags/kBuild-0.1.4/src/kmk/config/dospaths.m4
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/config/dospaths.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/config/dospaths.m4	(revision 1780)
@@ -0,0 +1,37 @@
+# Test if the system uses DOS-style pathnames (drive specs and backslashes)
+# By Paul Smith <psmith@gnu.org>.  Based on dos.m4 by Jim Meyering.
+
+# Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+AC_DEFUN([pds_AC_DOS_PATHS],
+  [
+    AC_CACHE_CHECK([whether system uses MSDOS-style paths], [ac_cv_dos_paths],
+      [
+        AC_COMPILE_IFELSE([
+#if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __EMX__ && !defined __MSYS__ && !defined __CYGWIN__
+neither MSDOS nor Windows nor OS2
+#endif
+],
+        [ac_cv_dos_paths=yes],
+        [ac_cv_dos_paths=no])
+      ])
+
+    if test x"$ac_cv_dos_paths" = xyes; then
+      AC_DEFINE_UNQUOTED([HAVE_DOS_PATHS], 1,
+                         [Define if the system uses DOS-style pathnames.])
+    fi
+  ])
Index: /tags/kBuild-0.1.4/src/kmk/configh.dos.template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/configh.dos.template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/configh.dos.template	(revision 1780)
@@ -0,0 +1,120 @@
+/* configh.dos -- hand-massaged config.h file for MS-DOS builds         -*-C-*-
+
+Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* Many things are defined already by a system header.  */
+#include <sys/config.h>
+
+#if __DJGPP__ > 2 || __DJGPP_MINOR__ > 1
+
+/* Define to 1 if `sys_siglist' is declared by <signal.h>.  */
+# define SYS_SIGLIST_DECLARED 1
+
+/* Define to 1 if the C library defines the variable `_sys_siglist'.  */
+# define HAVE_SYS_SIGLIST 1
+
+#else
+
+/* Define NSIG.  */
+# define NSIG SIGMAX
+
+#endif
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 0
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have the fdopen function.  */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `getgroups' function. */
+#define HAVE_GETGROUPS 1
+
+/* Define to 1 if you have the <memory.h> header file.  */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the mkstemp function.  */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the `setlinebuf' function. */
+#define HAVE_SETLINEBUF 1
+
+/* Define to 1 if you have the `setvbuf' function. */
+#define HAVE_SETVBUF 1
+
+#define SCCS_GET "get"
+
+/* Define to `unsigned long' or `unsigned long long'
+   if <inttypes.h> doesn't define.  */
+#define uintmax_t unsigned long long
+
+/* Define the type of the first arg to select().  */
+#define fd_set_size_t int
+
+/* Define to 1 if you have the select function.  */
+#define HAVE_SELECT 1
+
+/* Define to 1 if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the vprintf library function.  */
+#undef HAVE_VPRINTF
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the stricmp function.  */
+#define HAVE_STRICMP 1
+
+/* Name of the package */
+#define PACKAGE "%PACKAGE%"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-%PACKAGE%@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU %PACKAGE%"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU %PACKAGE% %VERSION%"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "%PACKAGE%"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "%VERSION%"
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define to 1 if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
+#define SYS_SIGLIST_DECLARED 1
+
+/* Version number of package */
+#define VERSION "%VERSION%"
+
+/* Build host information. */
+#define MAKE_HOST "i386-pc-msdosdjgpp"
+
+/* Grok DOS paths (drive specs and backslash path element separators) */
+#define HAVE_DOS_PATHS
Index: /tags/kBuild-0.1.4/src/kmk/configure.bat
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/configure.bat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/configure.bat	(revision 1780)
@@ -0,0 +1,62 @@
+@echo off
+rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+rem 2004, 2005, 2006 Free Software Foundation, Inc.
+rem This file is part of GNU Make.
+
+rem GNU Make is free software; you can redistribute it and/or modify it under
+rem the terms of the GNU General Public License as published by the Free
+rem Software Foundation; either version 2, or (at your option) any later
+rem version.
+
+rem GNU Make is distributed in the hope that it will be useful, but WITHOUT
+rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+rem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+rem more details.
+
+rem You should have received a copy of the GNU General Public License along
+rem with GNU Make; see the file COPYING.  If not, write to the Free Software
+rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+echo Configuring MAKE for DJGPP
+
+rem The SmallEnv trick protects against too small environment block,
+rem in which case the values will be truncated and the whole thing
+rem goes awry.  COMMAND.COM will say "Out of environment space", but
+rem many people don't care, so we force them to care by refusing to go.
+
+rem Where is the srcdir?
+set XSRC=.
+if not "%XSRC%"=="." goto SmallEnv
+if "%1%"=="" goto SrcDone
+set XSRC=%1
+if not "%XSRC%"=="%1" goto SmallEnv
+
+:SrcDone
+
+update %XSRC%/configh.dos ./config.h
+
+rem Do they have Make?
+redir -o junk.$$$ -eo make -n -f NUL
+rem REDIR will return 1 if it cannot run Make.
+rem If it can run Make, it will usually return 2,
+rem but 0 is also OK with us.
+if errorlevel 2 goto MakeOk
+if not errorlevel 1 goto MakeOk
+if exist junk.$$$ del junk.$$$
+echo No Make program found--use DOSBUILD.BAT to build Make.
+goto End
+
+rem They do have Make.	Generate the Makefile.
+
+:MakeOk
+del junk.$$$
+update %XSRC%/Makefile.DOS ./Makefile
+echo Done.
+if not "%XSRC%"=="." echo Invoke Make thus: "make srcdir=%XSRC%"
+goto End
+
+:SmallEnv
+echo Your environment is too small.  Please enlarge it and run me again.
+
+:End
+set XRSC=
Index: /tags/kBuild-0.1.4/src/kmk/configure.in
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/configure.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/configure.in	(revision 1780)
@@ -0,0 +1,471 @@
+# Process this file with autoconf to produce a configure script.
+#
+# Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+AC_INIT([GNU make],[3.81.90],[bug-make@gnu.org])
+
+AC_PREREQ(2.59)
+AC_REVISION([[$Id: configure.in,v 1.147 2007/05/09 02:01:53 psmith Exp $]])
+
+# Autoconf setup
+AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_SRCDIR(vpath.c)
+AC_CONFIG_HEADERS(config.h)
+
+# Automake setup
+AM_INIT_AUTOMAKE([1.9])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+AC_PROG_CPP
+AC_CHECK_PROG(AR, ar, ar, ar)
+# Perl is needed for the test suite (only)
+AC_CHECK_PROG(PERL, perl, perl, perl)
+
+# Specialized system macros
+AC_CANONICAL_HOST
+AC_AIX
+AC_ISC_POSIX
+AC_MINIX
+
+# kmk does not need gettext (yet)
+## Enable gettext, in "external" mode.
+#
+#AM_GNU_GETTEXT_VERSION(0.14.1)
+#AM_GNU_GETTEXT([external])
+
+# This test must come as early as possible after the compiler configuration
+# tests, because the choice of the file model can (in principle) affect
+# whether functions and headers are available, whether they work, etc.
+AC_SYS_LARGEFILE
+
+# Checks for libraries.
+AC_SEARCH_LIBS(getpwnam, [sun])
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_DIRENT
+AC_HEADER_STAT
+AC_HEADER_TIME
+AC_CHECK_HEADERS(stdlib.h locale.h unistd.h limits.h fcntl.h string.h \
+		 memory.h sys/param.h sys/resource.h sys/time.h sys/timeb.h)
+
+# Set a flag if we have an ANSI C compiler
+if test "$ac_cv_prog_cc_stdc" != no; then
+  AC_DEFINE(HAVE_ANSI_COMPILER, 1,
+	      [Define to 1 if your compiler conforms to the ANSI C standard.])
+fi
+
+
+# Determine what kind of variadic function calls we support
+AC_CHECK_HEADERS(stdarg.h varargs.h, break)
+
+AM_PROG_CC_C_O
+AC_C_CONST
+AC_TYPE_SIGNAL
+AC_TYPE_UID_T
+AC_TYPE_PID_T
+
+# Find some definition for uintmax_t
+
+AC_CHECK_TYPE(uintmax_t,,[
+  uintmax_t="unsigned long"
+  AC_CHECK_TYPE(unsigned long long,[uintmax_t="unsigned long long"])
+  AC_DEFINE_UNQUOTED(uintmax_t,$uintmax_t,
+    [Define uintmax_t if not defined in <stdint.h> or <inttypes.h>.])])
+
+# Find out whether our struct stat returns nanosecond resolution timestamps.
+
+AC_STRUCT_ST_MTIM_NSEC
+AC_MSG_CHECKING([whether to use high resolution file timestamps])
+AC_CACHE_VAL(make_cv_file_timestamp_hi_res, [
+  make_cv_file_timestamp_hi_res=no
+  if test "$ac_cv_struct_st_mtim_nsec" != no; then
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#	if HAVE_INTTYPES_H
+#	 include <inttypes.h>
+#	endif]],
+	              [[char a[0x7fffffff < (uintmax_t)-1 >> 30 ? 1 : -1];]])],
+      [make_cv_file_timestamp_hi_res=yes],
+      [])
+  fi])
+AC_MSG_RESULT($make_cv_file_timestamp_hi_res)
+if test "$make_cv_file_timestamp_hi_res" = yes; then
+  val=1
+else
+  val=0
+fi
+AC_DEFINE_UNQUOTED(FILE_TIMESTAMP_HI_RES, $val,
+		   [Use high resolution file timestamps if nonzero.])
+
+if test "$make_cv_file_timestamp_hi_res" = yes; then
+  # Solaris 2.5.1 needs -lposix4 to get the clock_gettime function.
+  # Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4.
+  AC_SEARCH_LIBS(clock_gettime, [rt posix4])
+  if test "$ac_cv_search_clock_gettime" != no; then
+    AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
+	      [Define to 1 if you have the clock_gettime function.])
+  fi
+fi
+
+# Check for DOS-style pathnames.
+pds_AC_DOS_PATHS
+
+# See if we have a standard version of gettimeofday().  Since actual
+# implementations can differ, just make sure we have the most common
+# one.
+AC_CACHE_CHECK([for standard gettimeofday], ac_cv_func_gettimeofday,
+  [ac_cv_func_gettimeofday=no
+   AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <sys/time.h>
+                  int main ()
+	          {
+		    struct timeval t; t.tv_sec = -1; t.tv_usec = -1;
+		    exit (gettimeofday (&t, 0) != 0
+		          || t.tv_sec < 0 || t.tv_usec < 0);
+	          }]])],
+		  [ac_cv_func_gettimeofday=yes],
+		  [ac_cv_func_gettimeofday=no],
+		  [ac_cv_func_gettimeofday="no (cross-compiling)"])])
+if test "$ac_cv_func_gettimeofday" = yes; then
+  AC_DEFINE(HAVE_GETTIMEOFDAY, 1,
+	    [Define to 1 if you have a standard gettimeofday function])
+fi
+
+AC_CHECK_FUNCS( strdup mkstemp mktemp fdopen \
+	        bsd_signal dup2 getcwd realpath sigsetmask sigaction \
+                getgroups seteuid setegid setlinebuf setreuid setregid \
+                getrlimit setrlimit setvbuf pipe strerror strsignal \
+		lstat readlink atexit)
+
+AC_FUNC_SETVBUF_REVERSED
+
+# Rumor has it that strcasecmp lives in -lresolv on some odd systems.
+# It doesn't hurt much to use our own if we can't find it so I don't
+# make the effort here.
+AC_CHECK_FUNCS(strcasecmp strcmpi stricmp)
+
+# strcoll() is used by the GNU glob library
+AC_FUNC_STRCOLL
+
+AC_FUNC_ALLOCA
+AC_FUNC_FORK([])
+AC_FUNC_VPRINTF
+AC_FUNC_CLOSEDIR_VOID
+
+AC_FUNC_GETLOADAVG
+
+# AC_FUNC_GETLOADAVG is documented to set the NLIST_STRUCT value, but it
+# doesn't.  So, we will.
+
+if test "$ac_cv_header_nlist_h" = yes; then
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <nlist.h>]],
+	[[struct nlist nl;
+          nl.n_name = "string";
+          return 0;]])],
+	[make_cv_nlist_struct=yes],
+	[make_cv_nlist_struct=no])
+  if test "$make_cv_nlist_struct" = yes; then
+    AC_DEFINE(NLIST_STRUCT, 1,
+       [Define to 1 if struct nlist.n_name is a pointer rather than an array.])
+  fi
+fi
+
+AC_CHECK_DECLS([sys_siglist, _sys_siglist, __sys_siglist], , ,
+  [AC_INCLUDES_DEFAULT
+#include <signal.h>
+/* NetBSD declares sys_siglist in unistd.h.  */
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+])
+
+
+# Check out the wait reality.
+AC_CHECK_HEADERS(sys/wait.h,,,[[#include <sys/types.h>]])
+AC_CHECK_FUNCS(waitpid wait3)
+AC_MSG_CHECKING(for union wait)
+AC_CACHE_VAL(make_cv_union_wait, [dnl
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#include <sys/wait.h>]],
+     [[union wait status; int pid; pid = wait (&status);
+#ifdef WEXITSTATUS
+/* Some POSIXoid systems have both the new-style macros and the old
+   union wait type, and they do not work together.  If union wait
+   conflicts with WEXITSTATUS et al, we don't want to use it at all.  */
+        if (WEXITSTATUS (status) != 0) pid = -1;
+#ifdef WTERMSIG
+        /* If we have WEXITSTATUS and WTERMSIG, just use them on ints.  */
+        -- blow chunks here --
+#endif
+#endif
+#ifdef HAVE_WAITPID
+        /* Make sure union wait works with waitpid.  */
+        pid = waitpid (-1, &status, 0);
+#endif
+      ]])],
+    [make_cv_union_wait=yes],
+    [make_cv_union_wait=no])])
+if test "$make_cv_union_wait" = yes; then
+  AC_DEFINE(HAVE_UNION_WAIT, 1,
+            [Define to 1 if you have the \`union wait' type in <sys/wait.h>.])
+fi
+AC_MSG_RESULT($make_cv_union_wait)
+
+
+# If we're building on Windows/DOS/OS/2, add some support for DOS drive specs.
+if test "$PATH_SEPARATOR" = ';'; then
+  AC_DEFINE(HAVE_DOS_PATHS, 1,
+            [Define to 1 if your system requires backslashes or drive specs in pathnames.])
+fi
+
+
+# See if the user wants to use pmake's "customs" distributed build capability
+
+AC_SUBST(REMOTE) REMOTE=stub
+use_customs=false
+AC_ARG_WITH(customs,
+  AC_HELP_STRING([--with-customs=DIR],
+		 [enable remote jobs via Customs--see README.customs]),
+  [case $withval in
+    n|no) : ;;
+    *) make_cppflags="$CPPFLAGS"
+       case $withval in
+	 y|ye|yes) : ;;
+	 *) CPPFLAGS="$CPPFLAGS -I$with_customs/include/customs"
+	    make_ldflags="$LDFLAGS -L$with_customs/lib" ;;
+       esac
+       CF_NETLIBS
+       AC_CHECK_HEADER(customs.h,
+		       [use_customs=true
+		         REMOTE=cstms
+			 LIBS="$LIBS -lcustoms" LDFLAGS="$make_ldflags"],
+		       [with_customs=no
+			 CPPFLAGS="$make_cppflags" make_badcust=yes])
+       ;;
+  esac])
+# Tell automake about this, so it can include the right .c files.
+AM_CONDITIONAL(USE_CUSTOMS, test "$use_customs" = true)
+
+# See if the user asked to handle case insensitive file systems.
+
+AH_TEMPLATE(HAVE_CASE_INSENSITIVE_FS, [Use case insensitive file names])
+AC_ARG_ENABLE(case-insensitive-file-system,
+  AC_HELP_STRING([--enable-case-insensitive-file-system],
+		 [assume file systems are case insensitive]),
+  [case $enableval in
+     yes) AC_DEFINE(HAVE_CASE_INSENSITIVE_FS) ;;
+   esac])
+
+# See if we can handle the job server feature, and if the user wants it.
+
+AC_ARG_ENABLE(job-server,
+  AC_HELP_STRING([--disable-job-server],
+                 [disallow recursive make communication during -jN]),
+  [make_cv_job_server="$enableval" user_job_server="$enableval"],
+  [make_cv_job_server="yes"])
+
+has_wait_nohang=yes
+case "$ac_cv_func_waitpid/$ac_cv_func_wait3" in
+  no/no) has_wait_nohang=no ;;
+esac
+
+AC_CACHE_CHECK(for SA_RESTART, make_cv_sa_restart, [
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <signal.h>]],
+      [[return SA_RESTART;]])],
+    [make_cv_sa_restart=yes],
+    [make_cv_sa_restart=no])])
+
+if test "$make_cv_sa_restart" != no; then
+  AC_DEFINE(HAVE_SA_RESTART, 1,
+     [Define to 1 if <signal.h> defines the SA_RESTART constant.])
+fi
+
+# enable make_cv_sa_restart for OS/2 so that the jobserver will be enabled,
+# but do it after HAVE_SA_RESTART has been defined.
+case "$host_os" in
+  os2*) make_cv_sa_restart=yes ;;
+esac
+
+case "$ac_cv_func_pipe/$ac_cv_func_sigaction/$make_cv_sa_restart/$has_wait_nohang/$make_cv_job_server" in
+  yes/yes/yes/yes/yes)
+    AC_DEFINE(MAKE_JOBSERVER, 1,
+              [Define to 1 to enable job server support in GNU make.]);;
+esac
+
+# if we have both lstat() and readlink() then we can support symlink
+# timechecks.
+case "$ac_cv_func_lstat/$ac_cv_func_readlink" in
+  yes/yes)
+    AC_DEFINE(MAKE_SYMLINKS, 1,
+              [Define to 1 to enable symbolic link timestamp checking.]);;
+esac
+
+# Find the SCCS commands, so we can include them in our default rules.
+
+AC_CACHE_CHECK(for location of SCCS get command, make_cv_path_sccs_get, [
+if test -f /usr/sccs/get; then
+  make_cv_path_sccs_get=/usr/sccs/get
+else
+  make_cv_path_sccs_get=get
+fi])
+AC_DEFINE_UNQUOTED(SCCS_GET, ["$make_cv_path_sccs_get"],
+	           [Define to the name of the SCCS 'get' command.])
+
+ac_clean_files="$ac_clean_files s.conftest conftoast" # Remove these later.
+if ( /usr/sccs/admin -n s.conftest || admin -n s.conftest ) >/dev/null 2>&1 &&
+   test -f s.conftest; then
+  # We successfully created an SCCS file.
+  AC_CACHE_CHECK(if SCCS get command understands -G, make_cv_sys_get_minus_G, [
+    if $make_cv_path_sccs_get -Gconftoast s.conftest >/dev/null 2>&1 &&
+       test -f conftoast; then
+       make_cv_sys_get_minus_G=yes
+    else
+       make_cv_sys_get_minus_G=no
+    fi])
+  case "$make_cv_sys_get_minus_G" in
+    yes) AC_DEFINE(SCCS_GET_MINUS_G, 1,
+           [Define to 1 if the SCCS 'get' command understands the '-G<file>' option.]);;
+  esac
+fi
+rm -f s.conftest conftoast
+
+# Check the system to see if it provides GNU glob.  If not, use our
+# local version.
+
+AC_MSG_CHECKING(if system libc has GNU glob)
+AC_CACHE_VAL(make_cv_sys_gnu_glob, [
+ AC_EGREP_CPP(gnu glob,[
+#include <features.h>
+#include <glob.h>
+#include <fnmatch.h>
+
+#define GLOB_INTERFACE_VERSION 1
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
+   gnu glob
+# endif
+#endif
+ ], [AC_MSG_RESULT(yes)
+make_cv_sys_gnu_glob=yes], [AC_MSG_RESULT([no; using local copy])
+AC_SUBST(GLOBINC) GLOBINC='-I$(srcdir)/glob'
+AC_SUBST(GLOBLIB) GLOBLIB=glob/libglob.a
+make_cv_sys_gnu_glob=no])])
+# Tell automake about this, so it can build the right .c files.
+AM_CONDITIONAL(USE_LOCAL_GLOB, test "$make_cv_sys_gnu_glob" = no)
+
+# Let the makefile know what our build host is
+
+AC_DEFINE_UNQUOTED(MAKE_HOST,"$host",[Build host information.])
+MAKE_HOST="$host"
+AC_SUBST(MAKE_HOST)
+
+w32_target_env=no
+AM_CONDITIONAL([WINDOWSENV], false)
+
+case "$host" in
+  *-*-mingw32)
+    AM_CONDITIONAL(WINDOWSENV, true)
+    w32_target_env=yes
+    AC_DEFINE([WINDOWS32], [1], [Use platform specific coding])
+    AC_DEFINE([HAVE_DOS_PATHS], [1], [Use platform specific coding])
+    ;;
+esac
+
+AC_DEFINE_UNQUOTED(PATH_SEPARATOR_CHAR,'$PATH_SEPARATOR',[Define to the character that separates directories in PATH.])
+
+# Include the Maintainer's Makefile section, if it's here.
+
+MAINT_MAKEFILE=/dev/null
+if test -r "$srcdir/maintMakefile"; then
+  MAINT_MAKEFILE="$srcdir/maintMakefile"
+fi
+AC_SUBST_FILE(MAINT_MAKEFILE)
+
+# Allow building with dmalloc
+AM_WITH_DMALLOC
+
+# Forcibly disable SET_MAKE.  If it's set it breaks things like the test
+# scripts, etc.
+SET_MAKE=
+
+# Sanity check and inform the user of what we found
+
+case "$make_badcust" in
+  yes) echo
+       echo "WARNING: --with-customs specified but no customs.h could be found;"
+       echo "         disabling Customs support."
+       echo ;;
+esac
+
+case "$with_customs" in
+  ""|n|no|y|ye|yes) ;;
+  *) if test -f "$with_customs/lib/libcustoms.a"; then
+       :
+     else
+       echo
+       echo "WARNING: '$with_customs/lib' does not appear to contain the"
+       echo "         Customs library.  You must build and install Customs"
+       echo "         before compiling GNU make."
+       echo
+     fi ;;
+esac
+
+case "$has_wait_nohang" in
+  no) echo
+      echo "WARNING: Your system has neither waitpid() nor wait3()."
+      echo "         Without one of these, signal handling is unreliable."
+      echo "         You should be aware that running GNU make with -j"
+      echo "         could result in erratic behavior."
+      echo ;;
+esac
+
+case "$make_cv_job_server/$user_job_server" in
+  no/yes) echo
+	  echo "WARNING: Make job server requires a POSIX-ish system that"
+	  echo "         supports the pipe(), sigaction(), and either"
+          echo "         waitpid() or wait3() functions.  Your system doesn't"
+	  echo "         appear to provide one or more of those."
+	  echo "         Disabling job server support."
+          echo ;;
+esac
+
+
+# Specify what files are to be created.
+#we can safely drop doc and po when bootstrapping kmk.
+#AC_CONFIG_FILES(Makefile glob/Makefile po/Makefile.in config/Makefile doc/Makefile w32/Makefile)
+AC_CONFIG_FILES(Makefile glob/Makefile config/Makefile w32/Makefile)
+
+# OK, do it!
+
+AC_OUTPUT
+
+# We only generate the build.sh if we have a build.sh.in; we won't have
+# one before we've created a distribution.
+if test -f "$srcdir/build.sh.in"; then
+  ./config.status --file build.sh
+  chmod +x build.sh
+fi
+
+dnl Local Variables:
+dnl comment-start: "dnl "
+dnl comment-end: ""
+dnl comment-start-skip: "\\bdnl\\b\\s *"
+dnl compile-command: "make configure config.h.in"
+dnl End:
Index: /tags/kBuild-0.1.4/src/kmk/debug.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/debug.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/debug.h	(revision 1780)
@@ -0,0 +1,67 @@
+/* Debugging macros and interface.
+Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#define DB_NONE         (0x000)
+#define DB_BASIC        (0x001)
+#define DB_VERBOSE      (0x002)
+#define DB_JOBS         (0x004)
+#define DB_IMPLICIT     (0x008)
+#define DB_MAKEFILES    (0x100)
+#ifdef KMK
+# define DB_KMK         (0x800)
+#endif 
+
+#define DB_ALL          (0xfff)
+
+extern int db_level;
+
+#ifdef KMK
+
+/* Some extended info for -j and .NOTPARALLEL tracking. */
+extern unsigned int makelevel;
+extern unsigned int job_slots;
+extern unsigned int job_slots_used;
+
+#define DB_HDR()    do { printf ("[%u:%u/%u]", makelevel, job_slots_used, job_slots); } while (0)
+
+#define ISDB(_l)    ((_l)&db_level)
+
+#define DBS(_l,_x)  do{ if(ISDB(_l)) {DB_HDR(); \
+                                      print_spaces (depth); \
+                                      printf _x; fflush (stdout);} }while(0)
+
+#define DBF(_l,_x)  do{ if(ISDB(_l)) {DB_HDR(); \
+                                      print_spaces (depth); \
+                                      printf (_x, file->name); \
+                                      fflush (stdout);} }while(0)
+
+#define DB(_l,_x)   do{ if(ISDB(_l)) {DB_HDR(); printf _x; fflush (stdout);} }while(0)
+
+#else  /* !KMK */
+
+#define ISDB(_l)    ((_l)&db_level)
+
+#define DBS(_l,_x)  do{ if(ISDB(_l)) {print_spaces (depth); \
+                                      printf _x; fflush (stdout);} }while(0)
+
+#define DBF(_l,_x)  do{ if(ISDB(_l)) {print_spaces (depth); \
+                                      printf (_x, file->name); \
+                                      fflush (stdout);} }while(0)
+
+#define DB(_l,_x)   do{ if(ISDB(_l)) {printf _x; fflush (stdout);} }while(0)
+
+#endif /* !KMK */
Index: /tags/kBuild-0.1.4/src/kmk/default.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/default.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/default.c	(revision 1780)
@@ -0,0 +1,618 @@
+/* Data base of default implicit rules for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "filedef.h"
+#include "variable.h"
+#include "rule.h"
+#include "dep.h"
+#include "job.h"
+#include "commands.h"
+
+/* Define GCC_IS_NATIVE if gcc is the native development environment on
+   your system (gcc/bison/flex vs cc/yacc/lex).  */
+#if defined(__MSDOS__) || defined(__EMX__)
+# define GCC_IS_NATIVE
+#endif
+
+
+/* This is the default list of suffixes for suffix rules.
+   `.s' must come last, so that a `.o' file will be made from
+   a `.c' or `.p' or ... file rather than from a .s file.  */
+
+static char default_suffixes[]
+#ifndef CONFIG_NO_DEFAULT_SUFFIXES
+#ifdef VMS
+  = ".exe .olb .ln .obj .c .cxx .cc .pas .p .for .f .r .y .l .mar \
+.s .ss .i .ii .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
+.w .ch .cweb .web .com .sh .elc .el";
+#elif defined(__EMX__)
+  = ".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \
+.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
+.w .ch .web .sh .elc .el .obj .exe .dll .lib";
+#else
+  = ".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \
+.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
+.w .ch .web .sh .elc .el";
+#endif
+#else  /* CONFIG_NO_DEFAULT_SUFFIXES */
+ = "";
+#endif /* CONFIG_NO_DEFAULT_SUFFIXES */
+
+static struct pspec default_pattern_rules[] =
+  {
+#ifndef CONFIG_NO_DEFAULT_PATTERN_RULES
+    { "(%)", "%",
+	"$(AR) $(ARFLAGS) $@ $<" },
+
+    /* The X.out rules are only in BSD's default set because
+       BSD Make has no null-suffix rules, so `foo.out' and
+       `foo' are the same thing.  */
+#ifdef VMS
+    { "%.exe", "%",
+        "copy $< $@" },
+#else
+    { "%.out", "%",
+	"@rm -f $@ \n cp $< $@" },
+#endif
+    /* Syntax is "ctangle foo.w foo.ch foo.c".  */
+    { "%.c", "%.w %.ch",
+	"$(CTANGLE) $^ $@" },
+    { "%.tex", "%.w %.ch",
+	"$(CWEAVE) $^ $@" },
+#endif /* !CONFIG_NO_DEFAULT_PATTERN_RULES */
+    { 0, 0, 0 }
+  };
+
+static struct pspec default_terminal_rules[] =
+  {
+#ifndef CONFIG_NO_DEFAULT_TERMINAL_RULES
+#ifdef VMS
+    /* RCS.  */
+    { "%", "%$$5lv", /* Multinet style */
+        "if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
+    { "%", "[.$$rcs]%$$5lv", /* Multinet style */
+        "if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
+    { "%", "%_v", /* Normal style */
+        "if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
+    { "%", "[.rcs]%_v", /* Normal style */
+        "if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
+
+    /* SCCS.  */
+	/* ain't no SCCS on vms */
+#else
+    /* RCS.  */
+    { "%", "%,v",
+	"$(CHECKOUT,v)" },
+    { "%", "RCS/%,v",
+	"$(CHECKOUT,v)" },
+    { "%", "RCS/%",
+	"$(CHECKOUT,v)" },
+
+    /* SCCS.  */
+    { "%", "s.%",
+	"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
+    { "%", "SCCS/s.%",
+	"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
+#endif /* !VMS */
+#endif /* !CONFIG_NO_DEFAULT_TERMINAL_RULES */
+    { 0, 0, 0 }
+  };
+
+static char *default_suffix_rules[] =
+  {
+#ifndef CONFIG_NO_DEFAULT_SUFFIX_RULES
+#ifdef VMS
+    ".obj.exe",
+    "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
+    ".mar.exe",
+    "$(COMPILE.mar) $^ \n $(LINK.obj) $(subst .mar,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
+    ".s.exe",
+    "$(COMPILE.s) $^ \n $(LINK.obj) $(subst .s,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
+    ".c.exe",
+    "$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
+    ".cc.exe",
+#ifdef GCC_IS_NATIVE
+    "$(COMPILE.cc) $^ \n $(LINK.obj) $(CXXSTARTUP),sys$$disk:[]$(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
+#else
+    "$(COMPILE.cc) $^ \n $(CXXLINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
+    ".cxx.exe",
+    "$(COMPILE.cxx) $^ \n $(CXXLINK.obj) $(subst .cxx,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
+#endif
+    ".for.exe",
+    "$(COMPILE.for) $^ \n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
+    ".pas.exe",
+    "$(COMPILE.pas) $^ \n $(LINK.obj) $(subst .pas,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
+
+    ".com",
+    "copy $< >$@",
+
+    ".mar.obj",
+    "$(COMPILE.mar) /obj=$@ $<",
+    ".s.obj",
+    "$(COMPILE.s) /obj=$@ $<",
+    ".ss.obj",
+    "$(COMPILE.s) /obj=$@ $<",
+    ".c.i",
+    "$(COMPILE.c)/prep /list=$@ $<",
+    ".c.s",
+    "$(COMPILE.c)/noobj/machine /list=$@ $<",
+    ".i.s",
+    "$(COMPILE.c)/noprep/noobj/machine /list=$@ $<",
+    ".c.obj",
+    "$(COMPILE.c) /obj=$@ $<",
+    ".cc.ii",
+    "$(COMPILE.cc)/prep /list=$@ $<",
+    ".cc.ss",
+    "$(COMPILE.cc)/noobj/machine /list=$@ $<",
+    ".ii.ss",
+    "$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<",
+    ".cc.obj",
+    "$(COMPILE.cc) /obj=$@ $<",
+    ".cxx.obj",
+    "$(COMPILE.cxx) /obj=$@ $<",
+    ".for.obj",
+    "$(COMPILE.for) /obj=$@ $<",
+    ".pas.obj",
+    "$(COMPILE.pas) /obj=$@ $<",
+
+    ".y.c",
+    "$(YACC.y) $< \n rename y_tab.c $@",
+    ".l.c",
+    "$(LEX.l) $< \n rename lexyy.c $@",
+
+    ".texinfo.info",
+    "$(MAKEINFO) $<",
+
+    ".tex.dvi",
+    "$(TEX) $<",
+
+#else /* ! VMS */
+
+    ".o",
+    "$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".s",
+    "$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".S",
+    "$(LINK.S) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".c",
+    "$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".cc",
+    "$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".C",
+    "$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".cpp",
+    "$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".f",
+    "$(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".m",
+    "$(LINK.m) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".p",
+    "$(LINK.p) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".F",
+    "$(LINK.F) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".r",
+    "$(LINK.r) $^ $(LOADLIBES) $(LDLIBS) -o $@",
+    ".mod",
+    "$(COMPILE.mod) -o $@ -e $@ $^",
+
+    ".def.sym",
+    "$(COMPILE.def) -o $@ $<",
+
+    ".sh",
+    "cat $< >$@ \n chmod a+x $@",
+
+    ".s.o",
+    "$(COMPILE.s) -o $@ $<",
+    ".S.o",
+    "$(COMPILE.S) -o $@ $<",
+    ".c.o",
+    "$(COMPILE.c) $(OUTPUT_OPTION) $<",
+    ".cc.o",
+    "$(COMPILE.cc) $(OUTPUT_OPTION) $<",
+    ".C.o",
+    "$(COMPILE.C) $(OUTPUT_OPTION) $<",
+    ".cpp.o",
+    "$(COMPILE.cpp) $(OUTPUT_OPTION) $<",
+    ".f.o",
+    "$(COMPILE.f) $(OUTPUT_OPTION) $<",
+    ".m.o",
+    "$(COMPILE.m) $(OUTPUT_OPTION) $<",
+    ".p.o",
+    "$(COMPILE.p) $(OUTPUT_OPTION) $<",
+    ".F.o",
+    "$(COMPILE.F) $(OUTPUT_OPTION) $<",
+    ".r.o",
+    "$(COMPILE.r) $(OUTPUT_OPTION) $<",
+    ".mod.o",
+    "$(COMPILE.mod) -o $@ $<",
+
+    ".c.ln",
+    "$(LINT.c) -C$* $<",
+    ".y.ln",
+#ifndef __MSDOS__
+    "$(YACC.y) $< \n $(LINT.c) -C$* y.tab.c \n $(RM) y.tab.c",
+#else
+    "$(YACC.y) $< \n $(LINT.c) -C$* y_tab.c \n $(RM) y_tab.c",
+#endif
+    ".l.ln",
+    "@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c",
+
+    ".y.c",
+#ifndef __MSDOS__
+    "$(YACC.y) $< \n mv -f y.tab.c $@",
+#else
+    "$(YACC.y) $< \n mv -f y_tab.c $@",
+#endif
+    ".l.c",
+    "@$(RM) $@ \n $(LEX.l) $< > $@",
+    ".ym.m",
+    "$(YACC.m) $< \n mv -f y.tab.c $@",
+    ".lm.m",
+    "@$(RM) $@ \n $(LEX.m) $< > $@",
+
+    ".F.f",
+    "$(PREPROCESS.F) $(OUTPUT_OPTION) $<",
+    ".r.f",
+    "$(PREPROCESS.r) $(OUTPUT_OPTION) $<",
+
+    /* This might actually make lex.yy.c if there's no %R% directive in $*.l,
+       but in that case why were you trying to make $*.r anyway?  */
+    ".l.r",
+    "$(LEX.l) $< > $@ \n mv -f lex.yy.r $@",
+
+    ".S.s",
+    "$(PREPROCESS.S) $< > $@",
+
+    ".texinfo.info",
+    "$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@",
+
+    ".texi.info",
+    "$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@",
+
+    ".txinfo.info",
+    "$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@",
+
+    ".tex.dvi",
+    "$(TEX) $<",
+
+    ".texinfo.dvi",
+    "$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<",
+
+    ".texi.dvi",
+    "$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<",
+
+    ".txinfo.dvi",
+    "$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<",
+
+    ".w.c",
+    "$(CTANGLE) $< - $@",	/* The `-' says there is no `.ch' file.  */
+
+    ".web.p",
+    "$(TANGLE) $<",
+
+    ".w.tex",
+    "$(CWEAVE) $< - $@",	/* The `-' says there is no `.ch' file.  */
+
+    ".web.tex",
+    "$(WEAVE) $<",
+
+#endif /* !VMS */
+#endif /* !CONFIG_NO_DEFAULT_SUFFIX_RULES */
+    0, 0,
+  };
+
+static const char *default_variables[] =
+  {
+#ifndef CONFIG_NO_DEFAULT_VARIABLES
+#ifdef VMS
+#ifdef __ALPHA
+    "ARCH", "ALPHA",
+#endif
+#ifdef __ia64
+    "ARCH", "IA64",
+#endif
+#ifdef __VAX
+    "ARCH", "VAX",
+#endif
+    "AR", "library/obj",
+    "ARFLAGS", "/replace",
+    "AS", "macro",
+    "MACRO", "macro",
+#ifdef GCC_IS_NATIVE
+    "CC", "gcc",
+#else
+    "CC", "cc",
+#endif
+    "CD", "builtin_cd",
+    "MAKE", "make",
+    "ECHO", "write sys$$output \"",
+#ifdef GCC_IS_NATIVE
+    "C++", "gcc/plus",
+    "CXX", "gcc/plus",
+#else
+    "C++", "cxx",
+    "CXX", "cxx",
+    "CXXLD", "cxxlink",
+#endif
+    "CO", "co",
+    "CPP", "$(CC) /preprocess_only",
+    "FC", "fortran",
+    /* System V uses these, so explicit rules using them should work.
+       However, there is no way to make implicit rules use them and FC.  */
+    "F77", "$(FC)",
+    "F77FLAGS", "$(FFLAGS)",
+    "LD", "link",
+    "LEX", "lex",
+    "PC", "pascal",
+    "YACC", "bison/yacc",
+    "YFLAGS", "/Define/Verbose",
+    "BISON", "bison",
+    "MAKEINFO", "makeinfo",
+    "TEX", "tex",
+    "TEXINDEX", "texindex",
+
+    "RM", "delete/nolog",
+
+    "CSTARTUP", "",
+#ifdef GCC_IS_NATIVE
+    "CRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj",
+    "CXXSTARTUP", "gnu_cc_library:crtbegin.obj",
+    "CXXRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crtend.obj,gnu_cc_library:gxx_main.obj",
+    "LXLIBS", ",gnu_cc_library:libstdcxx.olb/lib,gnu_cc_library:libgccplus.olb/lib",
+    "LDLIBS", ",gnu_cc_library:libgcc.olb/lib",
+#else
+    "CRT0", "",
+    "CXXSTARTUP", "",
+    "CXXRT0", "",
+    "LXLIBS", "",
+    "LDLIBS", "",
+#endif
+
+    "LINK.obj", "$(LD) $(LDFLAGS)",
+#ifndef GCC_IS_NATIVE
+    "CXXLINK.obj", "$(CXXLD) $(LDFLAGS)",
+    "COMPILE.cxx", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+#endif
+    "COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+    "COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+    "YACC.y", "$(YACC) $(YFLAGS)",
+    "LEX.l", "$(LEX) $(LFLAGS)",
+    "COMPILE.for", "$(FC) $(FFLAGS) $(TARGET_ARCH)",
+    "COMPILE.pas", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+    "COMPILE.mar", "$(MACRO) $(MACROFLAGS)",
+    "COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
+    "LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+
+    "MV", "rename/new_version",
+    "CP", "copy",
+
+#else /* !VMS */
+
+    "AR", "ar",
+    "ARFLAGS", "rv",
+    "AS", "as",
+#ifdef GCC_IS_NATIVE
+    "CC", "gcc",
+# ifdef __MSDOS__
+    "CXX", "gpp",	/* g++ is an invalid name on MSDOS */
+# else
+    "CXX", "gcc",
+# endif /* __MSDOS__ */
+    "OBJC", "gcc",
+#else
+    "CC", "cc",
+    "CXX", "g++",
+    "OBJC", "cc",
+#endif
+
+    /* This expands to $(CO) $(COFLAGS) $< $@ if $@ does not exist,
+       and to the empty string if $@ does exist.  */
+    "CHECKOUT,v", "+$(if $(wildcard $@),,$(CO) $(COFLAGS) $< $@)",
+    "CO", "co",
+    "COFLAGS", "",
+
+    "CPP", "$(CC) -E",
+#ifdef	CRAY
+    "CF77PPFLAGS", "-P",
+    "CF77PP", "/lib/cpp",
+    "CFT", "cft77",
+    "CF", "cf77",
+    "FC", "$(CF)",
+#else	/* Not CRAY.  */
+#ifdef	_IBMR2
+    "FC", "xlf",
+#else
+#ifdef	__convex__
+    "FC", "fc",
+#else
+    "FC", "f77",
+#endif /* __convex__ */
+#endif /* _IBMR2 */
+    /* System V uses these, so explicit rules using them should work.
+       However, there is no way to make implicit rules use them and FC.  */
+    "F77", "$(FC)",
+    "F77FLAGS", "$(FFLAGS)",
+#endif	/* Cray.  */
+    "GET", SCCS_GET,
+    "LD", "ld",
+#ifdef GCC_IS_NATIVE
+    "LEX", "flex",
+#else
+    "LEX", "lex",
+#endif
+    "LINT", "lint",
+    "M2C", "m2c",
+#ifdef	pyr
+    "PC", "pascal",
+#else
+#ifdef	CRAY
+    "PC", "PASCAL",
+    "SEGLDR", "segldr",
+#else
+    "PC", "pc",
+#endif	/* CRAY.  */
+#endif	/* pyr.  */
+#ifdef GCC_IS_NATIVE
+    "YACC", "bison -y",
+#else
+    "YACC", "yacc",	/* Or "bison -y"  */
+#endif
+    "MAKEINFO", "makeinfo",
+    "TEX", "tex",
+    "TEXI2DVI", "texi2dvi",
+    "WEAVE", "weave",
+    "CWEAVE", "cweave",
+    "TANGLE", "tangle",
+    "CTANGLE", "ctangle",
+
+    "RM", "rm -f",
+
+    "LINK.o", "$(CC) $(LDFLAGS) $(TARGET_ARCH)",
+    "COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "LINK.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "COMPILE.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "LINK.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "COMPILE.C", "$(COMPILE.cc)",
+    "COMPILE.cpp", "$(COMPILE.cc)",
+    "LINK.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "LINK.C", "$(LINK.cc)",
+    "LINK.cpp", "$(LINK.cc)",
+    "YACC.y", "$(YACC) $(YFLAGS)",
+    "LEX.l", "$(LEX) $(LFLAGS) -t",
+    "YACC.m", "$(YACC) $(YFLAGS)",
+    "LEX.m", "$(LEX) $(LFLAGS) -t",
+    "COMPILE.f", "$(FC) $(FFLAGS) $(TARGET_ARCH) -c",
+    "LINK.f", "$(FC) $(FFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "COMPILE.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "LINK.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "COMPILE.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -c",
+    "LINK.r", "$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "COMPILE.def", "$(M2C) $(M2FLAGS) $(DEFFLAGS) $(TARGET_ARCH)",
+    "COMPILE.mod", "$(M2C) $(M2FLAGS) $(MODFLAGS) $(TARGET_ARCH)",
+    "COMPILE.p", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "LINK.p", "$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)",
+    "LINK.s", "$(CC) $(ASFLAGS) $(LDFLAGS) $(TARGET_MACH)",
+    "COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
+    "LINK.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_MACH)",
+    "COMPILE.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c",
+    "PREPROCESS.S", "$(CC) -E $(CPPFLAGS)",
+    "PREPROCESS.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -F",
+    "PREPROCESS.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -F",
+    "LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+
+#ifndef	NO_MINUS_C_MINUS_O
+    "OUTPUT_OPTION", "-o $@",
+#endif
+
+#ifdef	SCCS_GET_MINUS_G
+    "SCCS_OUTPUT_OPTION", "-G$@",
+#endif
+
+#ifdef _AMIGA
+    ".LIBPATTERNS", "%.lib",
+#else
+#ifdef __MSDOS__
+    ".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a",
+#else
+    ".LIBPATTERNS", "lib%.so lib%.a",
+#endif
+#endif
+
+#endif /* !VMS */
+#endif /* !CONFIG_NO_DEFAULT_VARIABLES */
+    0, 0
+  };
+
+
+/* Set up the default .SUFFIXES list.  */
+
+void
+set_default_suffixes (void)
+{
+  suffix_file = enter_file (strcache_add (".SUFFIXES"));
+
+  if (no_builtin_rules_flag)
+    define_variable ("SUFFIXES", 8, "", o_default, 0);
+  else
+    {
+      char *p = default_suffixes;
+      suffix_file->deps = (struct dep *)
+	multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
+		    sizeof (struct dep));
+      define_variable ("SUFFIXES", 8, default_suffixes, o_default, 0);
+    }
+}
+
+/* Enter the default suffix rules as file rules.  This used to be done in
+   install_default_implicit_rules, but that loses because we want the
+   suffix rules installed before reading makefiles, and the pattern rules
+   installed after.  */
+
+void
+install_default_suffix_rules (void)
+{
+  char **s;
+
+  if (no_builtin_rules_flag)
+    return;
+
+  for (s = default_suffix_rules; *s != 0; s += 2)
+    {
+      struct file *f = enter_file (strcache_add (s[0]));
+      /* Don't clobber cmds given in a makefile if there were any.  */
+      if (f->cmds == 0)
+	{
+	  f->cmds = xmalloc (sizeof (struct commands));
+	  f->cmds->fileinfo.filenm = 0;
+	  f->cmds->commands = s[1];
+	  f->cmds->command_lines = 0;
+	}
+    }
+}
+
+
+/* Install the default pattern rules.  */
+
+void
+install_default_implicit_rules (void)
+{
+  struct pspec *p;
+
+  if (no_builtin_rules_flag)
+    return;
+
+  for (p = default_pattern_rules; p->target != 0; ++p)
+    install_pattern_rule (p, 0);
+
+  for (p = default_terminal_rules; p->target != 0; ++p)
+    install_pattern_rule (p, 1);
+}
+
+void
+define_default_variables (void)
+{
+  const char **s;
+
+  if (no_builtin_variables_flag)
+    return;
+
+  for (s = default_variables; *s != 0; s += 2)
+    define_variable (s[0], strlen (s[0]), s[1], o_default, 1);
+}
Index: /tags/kBuild-0.1.4/src/kmk/dep.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/dep.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/dep.h	(revision 1780)
@@ -0,0 +1,85 @@
+/* Definitions of dependency data structures for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* Flag bits for the second argument to `read_makefile'.
+   These flags are saved in the `changed' field of each
+   `struct dep' in the chain returned by `read_all_makefiles'.  */
+
+#define RM_NO_DEFAULT_GOAL	(1 << 0) /* Do not set default goal.  */
+#define RM_INCLUDED		(1 << 1) /* Search makefile search path.  */
+#define RM_DONTCARE		(1 << 2) /* No error if it doesn't exist.  */
+#define RM_NO_TILDE		(1 << 3) /* Don't expand ~ in file name.  */
+#define RM_NOFLAG		0
+
+/* Structure representing one dependency of a file.
+   Each struct file's `deps' points to a chain of these,
+   chained through the `next'. `stem' is the stem for this
+   dep line of static pattern rule or NULL.
+
+   Note that the first two words of this match a struct nameseq.  */
+
+struct dep
+  {
+    struct dep *next;
+    const char *name;
+    const char *stem;
+    struct file *file;
+    unsigned int changed : 8;
+    unsigned int ignore_mtime : 1;
+    unsigned int staticpattern : 1;
+    unsigned int need_2nd_expansion : 1;
+  };
+
+
+/* Structure used in chains of names, for parsing and globbing.  */
+
+struct nameseq
+  {
+    struct nameseq *next;
+    const char *name;
+  };
+
+
+struct nameseq *multi_glob (struct nameseq *chain, unsigned int size);
+#ifdef VMS
+struct nameseq *parse_file_seq ();
+#else
+struct nameseq *parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip);
+#endif
+char *tilde_expand (const char *name);
+
+#ifndef NO_ARCHIVES
+struct nameseq *ar_glob (const char *arname, const char *member_pattern, unsigned int size);
+#endif
+
+#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name)
+
+struct dep *alloc_dep (void);
+void free_dep (struct dep *d);
+struct dep *copy_dep_chain (const struct dep *d);
+void free_dep_chain (struct dep *d);
+void free_ns_chain (struct nameseq *n);
+struct dep *read_all_makefiles (const char **makefiles);
+int eval_buffer (char *buffer);
+int update_goal_chain (struct dep *goals);
+void uniquize_deps (struct dep *);
+
+#ifdef CONFIG_WITH_INCLUDEDEP
+void eval_include_dep (const char *name, struct floc *f);
+#endif
+
Index: /tags/kBuild-0.1.4/src/kmk/dir.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/dir.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/dir.c	(revision 1780)
@@ -0,0 +1,1273 @@
+/* Directory hashing for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "hash.h"
+
+#ifdef	HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+# ifdef VMS
+char *vmsify (char *name, int type);
+# endif
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+# ifdef HAVE_VMSDIR_H
+#  include "vmsdir.h"
+# endif /* HAVE_VMSDIR_H */
+#endif
+/* bird: FreeBSD + smbfs -> readdir() + EBADF */
+#ifdef __FreeBSD__
+# include <sys/mount.h>
+#endif
+/* bird: end */
+
+/* In GNU systems, <dirent.h> defines this macro for us.  */
+#ifdef _D_NAMLEN
+# undef NAMLEN
+# define NAMLEN(d) _D_NAMLEN(d)
+#endif
+
+#if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
+/* Posix does not require that the d_ino field be present, and some
+   systems do not provide it. */
+# define REAL_DIR_ENTRY(dp) 1
+# define FAKE_DIR_ENTRY(dp)
+#else
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+# define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
+#endif /* POSIX */
+
+
+#ifdef __MSDOS__
+#include <ctype.h>
+#include <fcntl.h>
+
+/* If it's MSDOS that doesn't have _USE_LFN, disable LFN support.  */
+#ifndef _USE_LFN
+#define _USE_LFN 0
+#endif
+
+static const char *
+dosify (const char *filename)
+{
+  static char dos_filename[14];
+  char *df;
+  int i;
+
+  if (filename == 0 || _USE_LFN)
+    return filename;
+
+  /* FIXME: what about filenames which violate
+     8+3 constraints, like "config.h.in", or ".emacs"?  */
+  if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0)
+    return filename;
+
+  df = dos_filename;
+
+  /* First, transform the name part.  */
+  for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i)
+    *df++ = tolower ((unsigned char)*filename++);
+
+  /* Now skip to the next dot.  */
+  while (*filename != '\0' && *filename != '.')
+    ++filename;
+  if (*filename != '\0')
+    {
+      *df++ = *filename++;
+      for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i)
+	*df++ = tolower ((unsigned char)*filename++);
+    }
+
+  /* Look for more dots.  */
+  while (*filename != '\0' && *filename != '.')
+    ++filename;
+  if (*filename == '.')
+    return filename;
+  *df = 0;
+  return dos_filename;
+}
+#endif /* __MSDOS__ */
+
+#ifdef WINDOWS32
+#include "pathstuff.h"
+#endif
+
+#ifdef _AMIGA
+#include <ctype.h>
+#endif
+
+#ifdef HAVE_CASE_INSENSITIVE_FS
+static const char *
+downcase (const char *filename)
+{
+  static PATH_VAR (new_filename);
+  char *df;
+  int i;
+
+  if (filename == 0)
+    return 0;
+
+  df = new_filename;
+
+  /* First, transform the name part.  */
+  while (*filename != '\0')
+    {
+      *df++ = tolower ((unsigned char)*filename);
+      ++filename;
+    }
+
+  *df = 0;
+
+  return new_filename;
+}
+#endif /* HAVE_CASE_INSENSITIVE_FS */
+
+#ifdef VMS
+
+static int
+vms_hash (char *name)
+{
+  int h = 0;
+  int g;
+
+  while (*name)
+    {
+      unsigned char uc = *name;
+#ifdef HAVE_CASE_INSENSITIVE_FS
+      h = (h << 4) + (isupper (uc) ? tolower (uc) : uc);
+#else
+      h = (h << 4) + uc;
+#endif
+      name++;
+      g = h & 0xf0000000;
+      if (g)
+	{
+	  h = h ^ (g >> 24);
+	  h = h ^ g;
+	}
+    }
+  return h;
+}
+
+/* fake stat entry for a directory */
+static int
+vmsstat_dir (char *name, struct stat *st)
+{
+  char *s;
+  int h;
+  DIR *dir;
+
+  dir = opendir (name);
+  if (dir == 0)
+    return -1;
+  closedir (dir);
+  s = strchr (name, ':');	/* find device */
+  if (s)
+    {
+      *s++ = 0;
+      st->st_dev = (char *)vms_hash (name);
+      h = vms_hash (s);
+      *(s-1) = ':';
+    }
+  else
+    {
+      st->st_dev = 0;
+      s = name;
+      h = vms_hash (s);
+    }
+
+  st->st_ino[0] = h & 0xff;
+  st->st_ino[1] = h & 0xff00;
+  st->st_ino[2] = h >> 16;
+
+  return 0;
+}
+#endif /* VMS */
+
+
+/* Hash table of directories.  */
+
+#ifndef	DIRECTORY_BUCKETS
+#ifdef KMK
+# define DIRECTORY_BUCKETS 4096
+# else
+#define DIRECTORY_BUCKETS 199
+# endif 
+#endif
+
+struct directory_contents
+  {
+    dev_t dev;			/* Device and inode numbers of this dir.  */
+#ifdef WINDOWS32
+    /* Inode means nothing on WINDOWS32. Even file key information is
+     * unreliable because it is random per file open and undefined for remote
+     * filesystems. The most unique attribute I can come up with is the fully
+     * qualified name of the directory. Beware though, this is also
+     * unreliable. I'm open to suggestion on a better way to emulate inode.  */
+    char *path_key;
+    int   ctime;
+    int   mtime;        /* controls check for stale directory cache */
+    int   fs_flags;     /* FS_FAT, FS_NTFS, ... */
+# define FS_FAT      0x1
+# define FS_NTFS     0x2
+# define FS_UNKNOWN  0x4
+#else
+# ifdef VMS
+    ino_t ino[3];
+# else
+    ino_t ino;
+# endif
+#endif /* WINDOWS32 */
+    struct hash_table dirfiles;	/* Files in this directory.  */
+    DIR *dirstream;		/* Stream reading this directory.  */
+  };
+
+static unsigned long
+directory_contents_hash_1 (const void *key_0)
+{
+  const struct directory_contents *key = key_0;
+  unsigned long hash;
+
+#ifdef WINDOWS32
+  hash = 0;
+  ISTRING_HASH_1 (key->path_key, hash);
+  hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
+#else
+# ifdef VMS
+  hash = (((unsigned int) key->dev << 4)
+	  ^ ((unsigned int) key->ino[0]
+	     + (unsigned int) key->ino[1]
+	     + (unsigned int) key->ino[2]));
+# else
+  hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;
+# endif
+#endif /* WINDOWS32 */
+  return hash;
+}
+
+static unsigned long
+directory_contents_hash_2 (const void *key_0)
+{
+  const struct directory_contents *key = key_0;
+  unsigned long hash;
+
+#ifdef WINDOWS32
+  hash = 0;
+  ISTRING_HASH_2 (key->path_key, hash);
+  hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
+#else
+# ifdef VMS
+  hash = (((unsigned int) key->dev << 4)
+	  ^ ~((unsigned int) key->ino[0]
+	      + (unsigned int) key->ino[1]
+	      + (unsigned int) key->ino[2]));
+# else
+  hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;
+# endif
+#endif /* WINDOWS32 */
+
+  return hash;
+}
+
+/* Sometimes it's OK to use subtraction to get this value:
+     result = X - Y;
+   But, if we're not sure of the type of X and Y they may be too large for an
+   int (on a 64-bit system for example).  So, use ?: instead.
+   See Savannah bug #15534.
+
+   NOTE!  This macro has side-effects!
+*/
+
+#define MAKECMP(_x,_y)  ((_x)<(_y)?-1:((_x)==(_y)?0:1))
+
+static int
+directory_contents_hash_cmp (const void *xv, const void *yv)
+{
+  const struct directory_contents *x = xv;
+  const struct directory_contents *y = yv;
+  int result;
+
+#ifdef WINDOWS32
+  ISTRING_COMPARE (x->path_key, y->path_key, result);
+  if (result)
+    return result;
+  result = MAKECMP(x->ctime, y->ctime);
+  if (result)
+    return result;
+#else
+# ifdef VMS
+  result = MAKECMP(x->ino[0], y->ino[0]);
+  if (result)
+    return result;
+  result = MAKECMP(x->ino[1], y->ino[1]);
+  if (result)
+    return result;
+  result = MAKECMP(x->ino[2], y->ino[2]);
+  if (result)
+    return result;
+# else
+  result = MAKECMP(x->ino, y->ino);
+  if (result)
+    return result;
+# endif
+#endif /* WINDOWS32 */
+
+  return MAKECMP(x->dev, y->dev);
+}
+
+/* Table of directory contents hashed by device and inode number.  */
+static struct hash_table directory_contents;
+
+struct directory
+  {
+    const char *name;			/* Name of the directory.  */
+
+    /* The directory's contents.  This data may be shared by several
+       entries in the hash table, which refer to the same directory
+       (identified uniquely by `dev' and `ino') under different names.  */
+    struct directory_contents *contents;
+  };
+
+static unsigned long
+directory_hash_1 (const void *key)
+{
+  return_ISTRING_HASH_1 (((const struct directory *) key)->name);
+}
+
+static unsigned long
+directory_hash_2 (const void *key)
+{
+  return_ISTRING_HASH_2 (((const struct directory *) key)->name);
+}
+
+static int
+directory_hash_cmp (const void *x, const void *y)
+{
+  return_ISTRING_COMPARE (((const struct directory *) x)->name,
+			  ((const struct directory *) y)->name);
+}
+
+/* Table of directories hashed by name.  */
+static struct hash_table directories;
+
+/* Never have more than this many directories open at once.  */
+
+#define MAX_OPEN_DIRECTORIES 10
+
+static unsigned int open_directories = 0;
+
+
+/* Hash table of files in each directory.  */
+
+struct dirfile
+  {
+    const char *name;		/* Name of the file.  */
+    short length;
+    short impossible;		/* This file is impossible.  */
+  };
+
+static unsigned long
+dirfile_hash_1 (const void *key)
+{
+  return_ISTRING_HASH_1 (((struct dirfile const *) key)->name);
+}
+
+static unsigned long
+dirfile_hash_2 (const void *key)
+{
+  return_ISTRING_HASH_2 (((struct dirfile const *) key)->name);
+}
+
+static int
+dirfile_hash_cmp (const void *xv, const void *yv)
+{
+  const struct dirfile *x = xv;
+  const struct dirfile *y = yv;
+  int result = x->length - y->length;
+  if (result)
+    return result;
+  return_ISTRING_COMPARE (x->name, y->name);
+}
+
+#ifndef	DIRFILE_BUCKETS
+#define DIRFILE_BUCKETS 107
+#endif
+
+
+static int dir_contents_file_exists_p (struct directory_contents *dir,
+                                       const char *filename);
+static struct directory *find_directory (const char *name);
+
+/* Find the directory named NAME and return its `struct directory'.  */
+
+static struct directory *
+find_directory (const char *name)
+{
+  const char *p;
+  struct directory *dir;
+  struct directory **dir_slot;
+  struct directory dir_key;
+  int r;
+#ifdef WINDOWS32
+  char* w32_path;
+  char  fs_label[BUFSIZ];
+  char  fs_type[BUFSIZ];
+  unsigned long  fs_serno;
+  unsigned long  fs_flags;
+  unsigned long  fs_len;
+#endif
+#ifdef VMS
+  if ((*name == '.') && (*(name+1) == 0))
+    name = "[]";
+  else
+    name = vmsify (name,1);
+#endif
+
+  dir_key.name = name;
+  dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key);
+  dir = *dir_slot;
+
+  if (HASH_VACANT (dir))
+    {
+      struct stat st;
+
+      /* The directory was not found.  Create a new entry for it.  */
+
+      p = name + strlen (name);
+      dir = xmalloc (sizeof (struct directory));
+      dir->name = strcache_add_len (name, p - name);
+      hash_insert_at (&directories, dir, dir_slot);
+      /* The directory is not in the name hash table.
+	 Find its device and inode numbers, and look it up by them.  */
+
+#ifdef WINDOWS32
+      /* Remove any trailing '\'.  Windows32 stat fails even on valid
+         directories if they end in '\'. */
+      if (p[-1] == '\\')
+        ((char *)p)[-1] = '\0';
+#endif
+
+#ifdef VMS
+      r = vmsstat_dir (name, &st);
+#else
+      EINTRLOOP (r, stat (name, &st));
+#endif
+
+#ifdef WINDOWS32
+      /* Put back the trailing '\'.  If we don't, we're permanently
+         truncating the value!  */
+      if (p[-1] == '\0')
+        ((char *)p)[-1] = '\\';
+#endif
+
+      if (r < 0)
+        {
+	/* Couldn't stat the directory.  Mark this by
+	   setting the `contents' member to a nil pointer.  */
+	  dir->contents = 0;
+	}
+      else
+	{
+	  /* Search the contents hash table; device and inode are the key.  */
+
+	  struct directory_contents *dc;
+	  struct directory_contents **dc_slot;
+	  struct directory_contents dc_key;
+
+	  dc_key.dev = st.st_dev;
+#ifdef WINDOWS32
+	  dc_key.path_key = w32_path = w32ify (name, 1);
+	  dc_key.ctime = st.st_ctime;
+#else
+# ifdef VMS
+	  dc_key.ino[0] = st.st_ino[0];
+	  dc_key.ino[1] = st.st_ino[1];
+	  dc_key.ino[2] = st.st_ino[2];
+# else
+	  dc_key.ino = st.st_ino;
+# endif
+#endif
+	  dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);
+	  dc = *dc_slot;
+
+	  if (HASH_VACANT (dc))
+	    {
+	      /* Nope; this really is a directory we haven't seen before.  */
+
+	      dc = (struct directory_contents *)
+		xmalloc (sizeof (struct directory_contents));
+
+	      /* Enter it in the contents hash table.  */
+	      dc->dev = st.st_dev;
+#ifdef WINDOWS32
+              dc->path_key = xstrdup (w32_path);
+	      dc->ctime = st.st_ctime;
+              dc->mtime = st.st_mtime;
+
+              /*
+               * NTFS is the only WINDOWS32 filesystem that bumps mtime
+               * on a directory when files are added/deleted from
+               * a directory.
+               */
+              w32_path[3] = '\0';
+              if (GetVolumeInformation(w32_path,
+                     fs_label, sizeof (fs_label),
+                     &fs_serno, &fs_len,
+                     &fs_flags, fs_type, sizeof (fs_type)) == FALSE)
+                dc->fs_flags = FS_UNKNOWN;
+              else if (!strcmp(fs_type, "FAT"))
+                dc->fs_flags = FS_FAT;
+              else if (!strcmp(fs_type, "NTFS"))
+                dc->fs_flags = FS_NTFS;
+              else
+                dc->fs_flags = FS_UNKNOWN;
+#else
+# ifdef VMS
+	      dc->ino[0] = st.st_ino[0];
+	      dc->ino[1] = st.st_ino[1];
+	      dc->ino[2] = st.st_ino[2];
+# else
+	      dc->ino = st.st_ino;
+# endif
+#endif /* WINDOWS32 */
+	      hash_insert_at (&directory_contents, dc, dc_slot);
+	      ENULLLOOP (dc->dirstream, opendir (name));
+	      if (dc->dirstream == 0)
+                /* Couldn't open the directory.  Mark this by setting the
+                   `files' member to a nil pointer.  */
+                dc->dirfiles.ht_vec = 0;
+	      else
+		{
+		  hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
+			     dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
+		  /* Keep track of how many directories are open.  */
+		  ++open_directories;
+		  if (open_directories == MAX_OPEN_DIRECTORIES)
+		    /* We have too many directories open already.
+		       Read the entire directory and then close it.  */
+		    dir_contents_file_exists_p (dc, 0);
+		}
+	    }
+
+	  /* Point the name-hashed entry for DIR at its contents data.  */
+	  dir->contents = dc;
+	}
+    }
+
+  return dir;
+}
+
+
+/* Return 1 if the name FILENAME is entered in DIR's hash table.
+   FILENAME must contain no slashes.  */
+
+static int
+dir_contents_file_exists_p (struct directory_contents *dir,
+                            const char *filename)
+{
+  unsigned int hash;
+  struct dirfile *df;
+  struct dirent *d;
+#ifdef WINDOWS32
+  struct stat st;
+  int rehash = 0;
+#endif
+
+  if (dir == 0 || dir->dirfiles.ht_vec == 0)
+    /* The directory could not be stat'd or opened.  */
+    return 0;
+
+#ifdef __MSDOS__
+  filename = dosify (filename);
+#endif
+
+#ifdef HAVE_CASE_INSENSITIVE_FS
+  filename = downcase (filename);
+#endif
+
+#ifdef __EMX__
+  if (filename != 0)
+    _fnlwr (filename); /* lower case for FAT drives */
+#endif
+
+#ifdef VMS
+  filename = vmsify (filename,0);
+#endif
+
+  hash = 0;
+  if (filename != 0)
+    {
+      struct dirfile dirfile_key;
+
+      if (*filename == '\0')
+	{
+	  /* Checking if the directory exists.  */
+	  return 1;
+	}
+      dirfile_key.name = filename;
+      dirfile_key.length = strlen (filename);
+      df = hash_find_item (&dir->dirfiles, &dirfile_key);
+      if (df)
+        return !df->impossible;
+    }
+
+  /* The file was not found in the hashed list.
+     Try to read the directory further.  */
+
+  if (dir->dirstream == 0)
+    {
+#ifdef WINDOWS32
+      /*
+       * Check to see if directory has changed since last read. FAT
+       * filesystems force a rehash always as mtime does not change
+       * on directories (ugh!).
+       */
+      if (dir->path_key)
+	{
+          if ((dir->fs_flags & FS_FAT) != 0)
+	    {
+	      dir->mtime = time ((time_t *) 0);
+	      rehash = 1;
+	    }
+	  else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
+	    {
+	      /* reset date stamp to show most recent re-process.  */
+	      dir->mtime = st.st_mtime;
+	      rehash = 1;
+	    }
+
+          /* If it has been already read in, all done.  */
+	  if (!rehash)
+	    return 0;
+
+          /* make sure directory can still be opened; if not return.  */
+          dir->dirstream = opendir (dir->path_key);
+          if (!dir->dirstream)
+            return 0;
+	}
+      else
+#endif
+	/* The directory has been all read in.  */
+	return 0;
+    }
+
+  while (1)
+    {
+      /* Enter the file in the hash table.  */
+      unsigned int len;
+      struct dirfile dirfile_key;
+      struct dirfile **dirfile_slot;
+
+      ENULLLOOP (d, readdir (dir->dirstream));
+      if (d == 0)
+        {
+/* bird: Workaround for smbfs mounts returning EBADF at the end of the search. 
+         To exactly determin the cause here, I should probably do some smbfs
+         tracing, but for now just ignoring the EBADF on seems to work. 
+         (The smb server is 64-bit vista, btw.) */
+#if defined (__FreeBSD__)
+          struct statfs stfs;
+          int saved_errno = errno;
+          errno = 0;
+          if (saved_errno == EBADF
+           && !fstatfs (dirfd (dir->dirstream), &stfs)
+           && !(stfs.f_flags & MNT_LOCAL)
+           && !strcmp(stfs.f_fstypename, "smbfs"))
+            {
+              /*fprintf (stderr, "EBADF on remote fs! dirfd=%d errno=%d\n", 
+                       dirfd (dir->dirstream), errno);*/
+              saved_errno = 0;
+            }
+          errno = saved_errno;
+#endif
+/* bird: end */
+          if (errno)
+            fatal (NILF, "INTERNAL: readdir(%p): %s (filename=%s)\n", dir, strerror (errno), filename);
+          break;
+        }
+
+#if defined(VMS) && defined(HAVE_DIRENT_H)
+      /* In VMS we get file versions too, which have to be stripped off */
+      {
+        char *p = strrchr (d->d_name, ';');
+        if (p)
+          *p = '\0';
+      }
+#endif
+      if (!REAL_DIR_ENTRY (d))
+	continue;
+
+      len = NAMLEN (d);
+      dirfile_key.name = d->d_name;
+      dirfile_key.length = len;
+      dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key);
+#ifdef WINDOWS32
+      /*
+       * If re-reading a directory, don't cache files that have
+       * already been discovered.
+       */
+      if (! rehash || HASH_VACANT (*dirfile_slot))
+#endif
+	{
+	  df = xmalloc (sizeof (struct dirfile));
+	  df->name = strcache_add_len (d->d_name, len);
+	  df->length = len;
+	  df->impossible = 0;
+	  hash_insert_at (&dir->dirfiles, df, dirfile_slot);
+	}
+      /* Check if the name matches the one we're searching for.  */
+      if (filename != 0 && strieq (d->d_name, filename))
+        return 1;
+    }
+
+  /* If the directory has been completely read in,
+     close the stream and reset the pointer to nil.  */
+  if (d == 0)
+    {
+      --open_directories;
+      closedir (dir->dirstream);
+      dir->dirstream = 0;
+    }
+  return 0;
+}
+
+/* Return 1 if the name FILENAME in directory DIRNAME
+   is entered in the dir hash table.
+   FILENAME must contain no slashes.  */
+
+int
+dir_file_exists_p (const char *dirname, const char *filename)
+{
+  return dir_contents_file_exists_p (find_directory (dirname)->contents,
+				     filename);
+}
+
+
+/* Return 1 if the file named NAME exists.  */
+
+int
+file_exists_p (const char *name)
+{
+  const char *dirend;
+  const char *dirname;
+  const char *slash;
+
+#ifndef	NO_ARCHIVES
+  if (ar_name (name))
+    return ar_member_date (name) != (time_t) -1;
+#endif
+
+#ifdef VMS
+  dirend = strrchr (name, ']');
+  if (dirend == 0)
+    dirend = strrchr (name, ':');
+  if (dirend == 0)
+    return dir_file_exists_p ("[]", name);
+#else /* !VMS */
+  dirend = strrchr (name, '/');
+#ifdef HAVE_DOS_PATHS
+  /* Forward and backslashes might be mixed.  We need the rightmost one.  */
+  {
+    const char *bslash = strrchr(name, '\\');
+    if (!dirend || bslash > dirend)
+      dirend = bslash;
+    /* The case of "d:file".  */
+    if (!dirend && name[0] && name[1] == ':')
+      dirend = name + 1;
+  }
+#endif /* HAVE_DOS_PATHS */
+  if (dirend == 0)
+#ifndef _AMIGA
+    return dir_file_exists_p (".", name);
+#else /* !VMS && !AMIGA */
+    return dir_file_exists_p ("", name);
+#endif /* AMIGA */
+#endif /* VMS */
+
+  slash = dirend;
+  if (dirend == name)
+    dirname = "/";
+  else
+    {
+      char *p;
+#ifdef HAVE_DOS_PATHS
+  /* d:/ and d: are *very* different...  */
+      if (dirend < name + 3 && name[1] == ':' &&
+	  (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+	dirend++;
+#endif
+      p = alloca (dirend - name + 1);
+      memcpy (p, name, dirend - name);
+      p[dirend - name] = '\0';
+      dirname = p;
+    }
+  return dir_file_exists_p (dirname, slash + 1);
+}
+
+
+/* Mark FILENAME as `impossible' for `file_impossible_p'.
+   This means an attempt has been made to search for FILENAME
+   as an intermediate file, and it has failed.  */
+
+void
+file_impossible (const char *filename)
+{
+  const char *dirend;
+  const char *p = filename;
+  struct directory *dir;
+  struct dirfile *new;
+
+#ifdef VMS
+  dirend = strrchr (p, ']');
+  if (dirend == 0)
+    dirend = strrchr (p, ':');
+  dirend++;
+  if (dirend == (char *)1)
+    dir = find_directory ("[]");
+#else
+  dirend = strrchr (p, '/');
+# ifdef HAVE_DOS_PATHS
+  /* Forward and backslashes might be mixed.  We need the rightmost one.  */
+  {
+    const char *bslash = strrchr(p, '\\');
+    if (!dirend || bslash > dirend)
+      dirend = bslash;
+    /* The case of "d:file".  */
+    if (!dirend && p[0] && p[1] == ':')
+      dirend = p + 1;
+  }
+# endif /* HAVE_DOS_PATHS */
+  if (dirend == 0)
+# ifdef _AMIGA
+    dir = find_directory ("");
+# else /* !VMS && !AMIGA */
+    dir = find_directory (".");
+# endif /* AMIGA */
+#endif /* VMS */
+  else
+    {
+      const char *dirname;
+      const char *slash = dirend;
+      if (dirend == p)
+	dirname = "/";
+      else
+	{
+          char *cp;
+#ifdef HAVE_DOS_PATHS
+	  /* d:/ and d: are *very* different...  */
+	  if (dirend < p + 3 && p[1] == ':' &&
+	      (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+	    dirend++;
+#endif
+	  cp = alloca (dirend - p + 1);
+	  memcpy (cp, p, dirend - p);
+	  cp[dirend - p] = '\0';
+          dirname = cp;
+	}
+      dir = find_directory (dirname);
+      filename = p = slash + 1;
+    }
+
+  if (dir->contents == 0)
+    {
+      /* The directory could not be stat'd.  We allocate a contents
+	 structure for it, but leave it out of the contents hash table.  */
+      dir->contents = xmalloc (sizeof (struct directory_contents));
+      memset (dir->contents, '\0', sizeof (struct directory_contents));
+    }
+
+  if (dir->contents->dirfiles.ht_vec == 0)
+    {
+      hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,
+		 dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
+    }
+
+  /* Make a new entry and put it in the table.  */
+
+  new = xmalloc (sizeof (struct dirfile));
+  new->length = strlen (filename);
+  new->name = strcache_add_len (filename, new->length);
+  new->impossible = 1;
+  hash_insert (&dir->contents->dirfiles, new);
+}
+
+
+/* Return nonzero if FILENAME has been marked impossible.  */
+
+int
+file_impossible_p (const char *filename)
+{
+  const char *dirend;
+  const char *p = filename;
+  struct directory_contents *dir;
+  struct dirfile *dirfile;
+  struct dirfile dirfile_key;
+
+#ifdef VMS
+  dirend = strrchr (filename, ']');
+  if (dirend == 0)
+    dir = find_directory ("[]")->contents;
+#else
+  dirend = strrchr (filename, '/');
+#ifdef HAVE_DOS_PATHS
+  /* Forward and backslashes might be mixed.  We need the rightmost one.  */
+  {
+    const char *bslash = strrchr(filename, '\\');
+    if (!dirend || bslash > dirend)
+      dirend = bslash;
+    /* The case of "d:file".  */
+    if (!dirend && filename[0] && filename[1] == ':')
+      dirend = filename + 1;
+  }
+#endif /* HAVE_DOS_PATHS */
+  if (dirend == 0)
+#ifdef _AMIGA
+    dir = find_directory ("")->contents;
+#else /* !VMS && !AMIGA */
+    dir = find_directory (".")->contents;
+#endif /* AMIGA */
+#endif /* VMS */
+  else
+    {
+      const char *dirname;
+      const char *slash = dirend;
+      if (dirend == filename)
+	dirname = "/";
+      else
+	{
+          char *cp;
+#ifdef HAVE_DOS_PATHS
+	  /* d:/ and d: are *very* different...  */
+	  if (dirend < filename + 3 && filename[1] == ':' &&
+	      (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+	    dirend++;
+#endif
+	  cp = alloca (dirend - filename + 1);
+	  memcpy (cp, p, dirend - p);
+	  cp[dirend - p] = '\0';
+          dirname = cp;
+	}
+      dir = find_directory (dirname)->contents;
+      p = filename = slash + 1;
+    }
+
+  if (dir == 0 || dir->dirfiles.ht_vec == 0)
+    /* There are no files entered for this directory.  */
+    return 0;
+
+#ifdef __MSDOS__
+  filename = dosify (p);
+#endif
+#ifdef HAVE_CASE_INSENSITIVE_FS
+  filename = downcase (p);
+#endif
+#ifdef VMS
+  filename = vmsify (p, 1);
+#endif
+
+  dirfile_key.name = filename;
+  dirfile_key.length = strlen (filename);
+  dirfile = hash_find_item (&dir->dirfiles, &dirfile_key);
+  if (dirfile)
+    return dirfile->impossible;
+
+  return 0;
+}
+
+
+/* Return the already allocated name in the
+   directory hash table that matches DIR.  */
+
+const char *
+dir_name (const char *dir)
+{
+  return find_directory (dir)->name;
+}
+
+
+/* Print the data base of directories.  */
+
+void
+print_dir_data_base (void)
+{
+  unsigned int files;
+  unsigned int impossible;
+  struct directory **dir_slot;
+  struct directory **dir_end;
+
+  puts (_("\n# Directories\n"));
+
+  files = impossible = 0;
+
+  dir_slot = (struct directory **) directories.ht_vec;
+  dir_end = dir_slot + directories.ht_size;
+  for ( ; dir_slot < dir_end; dir_slot++)
+    {
+      struct directory *dir = *dir_slot;
+      if (! HASH_VACANT (dir))
+	{
+	  if (dir->contents == 0)
+	    printf (_("# %s: could not be stat'd.\n"), dir->name);
+	  else if (dir->contents->dirfiles.ht_vec == 0)
+	    {
+#ifdef WINDOWS32
+	      printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
+		      dir->name, dir->contents->path_key,dir->contents->mtime);
+#else  /* WINDOWS32 */
+#ifdef VMS
+	      printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
+		      dir->name, dir->contents->dev,
+		      dir->contents->ino[0], dir->contents->ino[1],
+		      dir->contents->ino[2]);
+#else
+	      printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
+		      dir->name, (long int) dir->contents->dev,
+		      (long int) dir->contents->ino);
+#endif
+#endif /* WINDOWS32 */
+	    }
+	  else
+	    {
+	      unsigned int f = 0;
+	      unsigned int im = 0;
+	      struct dirfile **files_slot;
+	      struct dirfile **files_end;
+
+	      files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec;
+	      files_end = files_slot + dir->contents->dirfiles.ht_size;
+	      for ( ; files_slot < files_end; files_slot++)
+		{
+		  struct dirfile *df = *files_slot;
+		  if (! HASH_VACANT (df))
+		    {
+		      if (df->impossible)
+			++im;
+		      else
+			++f;
+		    }
+		}
+#ifdef WINDOWS32
+	      printf (_("# %s (key %s, mtime %d): "),
+		      dir->name, dir->contents->path_key, dir->contents->mtime);
+#else  /* WINDOWS32 */
+#ifdef VMS
+	      printf (_("# %s (device %d, inode [%d,%d,%d]): "),
+		      dir->name, dir->contents->dev,
+		      dir->contents->ino[0], dir->contents->ino[1],
+		      dir->contents->ino[2]);
+#else
+	      printf (_("# %s (device %ld, inode %ld): "),
+		      dir->name,
+		      (long)dir->contents->dev, (long)dir->contents->ino);
+#endif
+#endif /* WINDOWS32 */
+	      if (f == 0)
+		fputs (_("No"), stdout);
+	      else
+		printf ("%u", f);
+	      fputs (_(" files, "), stdout);
+	      if (im == 0)
+		fputs (_("no"), stdout);
+	      else
+		printf ("%u", im);
+	      fputs (_(" impossibilities"), stdout);
+	      if (dir->contents->dirstream == 0)
+		puts (".");
+	      else
+		puts (_(" so far."));
+	      files += f;
+	      impossible += im;
+
+#ifdef KMK
+              fputs ("# ", stdout);
+              hash_print_stats (&dir->contents->dirfiles, stdout);
+              fputs ("\n", stdout);
+#endif 
+	    }
+	}
+    }
+
+  fputs ("\n# ", stdout);
+  if (files == 0)
+    fputs (_("No"), stdout);
+  else
+    printf ("%u", files);
+  fputs (_(" files, "), stdout);
+  if (impossible == 0)
+    fputs (_("no"), stdout);
+  else
+    printf ("%u", impossible);
+  printf (_(" impossibilities in %lu directories.\n"), directories.ht_fill);
+#ifdef KMK
+  fputs ("# directories: ", stdout);
+  hash_print_stats (&directories, stdout);
+  fputs ("\n# directory_contents: ", stdout);
+  hash_print_stats (&directory_contents, stdout);
+  fputs ("\n", stdout);
+#endif 
+}
+
+
+/* Hooks for globbing.  */
+
+#include <glob.h>
+
+/* Structure describing state of iterating through a directory hash table.  */
+
+struct dirstream
+  {
+    struct directory_contents *contents; /* The directory being read.  */
+    struct dirfile **dirfile_slot; /* Current slot in table.  */
+  };
+
+/* Forward declarations.  */
+static __ptr_t open_dirstream (const char *);
+static struct dirent *read_dirstream (__ptr_t);
+
+static __ptr_t
+open_dirstream (const char *directory)
+{
+  struct dirstream *new;
+  struct directory *dir = find_directory (directory);
+
+  if (dir->contents == 0 || dir->contents->dirfiles.ht_vec == 0)
+    /* DIR->contents is nil if the directory could not be stat'd.
+       DIR->contents->dirfiles is nil if it could not be opened.  */
+    return 0;
+
+  /* Read all the contents of the directory now.  There is no benefit
+     in being lazy, since glob will want to see every file anyway.  */
+
+  dir_contents_file_exists_p (dir->contents, 0);
+
+  new = xmalloc (sizeof (struct dirstream));
+  new->contents = dir->contents;
+  new->dirfile_slot = (struct dirfile **) new->contents->dirfiles.ht_vec;
+
+  return (__ptr_t) new;
+}
+
+static struct dirent *
+read_dirstream (__ptr_t stream)
+{
+  static char *buf;
+  static unsigned int bufsz;
+
+  struct dirstream *const ds = (struct dirstream *) stream;
+  struct directory_contents *dc = ds->contents;
+  struct dirfile **dirfile_end = (struct dirfile **) dc->dirfiles.ht_vec + dc->dirfiles.ht_size;
+
+  while (ds->dirfile_slot < dirfile_end)
+    {
+      struct dirfile *df = *ds->dirfile_slot++;
+      if (! HASH_VACANT (df) && !df->impossible)
+	{
+	  /* The glob interface wants a `struct dirent', so mock one up.  */
+	  struct dirent *d;
+	  unsigned int len = df->length + 1;
+          unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len;
+	  if (sz > bufsz)
+	    {
+	      bufsz *= 2;
+	      if (sz > bufsz)
+		bufsz = sz;
+	      buf = xrealloc (buf, bufsz);
+	    }
+	  d = (struct dirent *) buf;
+#ifdef __MINGW32__
+# if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \
+				     __MINGW32_MINOR_VERSION == 0)
+	  d->d_name = xmalloc(len);
+# endif
+#endif
+	  FAKE_DIR_ENTRY (d);
+#ifdef _DIRENT_HAVE_D_NAMLEN
+	  d->d_namlen = len - 1;
+#endif
+#ifdef _DIRENT_HAVE_D_TYPE
+	  d->d_type = DT_UNKNOWN;
+#endif
+	  memcpy (d->d_name, df->name, len);
+	  return d;
+	}
+    }
+
+  return 0;
+}
+
+static void
+ansi_free (void *p)
+{
+  if (p)
+    free(p);
+}
+
+/* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a
+ * macro for stat64().  If stat is a macro, make a local wrapper function to
+ * invoke it.
+ */
+#ifndef stat
+# ifndef VMS
+int stat (const char *path, struct stat *sbuf);
+# endif
+# define local_stat stat
+#else
+static int
+local_stat (const char *path, struct stat *buf)
+{
+  int e;
+
+  EINTRLOOP (e, stat (path, buf));
+  return e;
+}
+#endif
+
+void
+dir_setup_glob (glob_t *gl)
+{
+  gl->gl_opendir = open_dirstream;
+  gl->gl_readdir = read_dirstream;
+  gl->gl_closedir = ansi_free;
+  gl->gl_stat = local_stat;
+#ifdef __EMX__ /* The FreeBSD implemenation actually uses gl_lstat!! */
+  gl->gl_lstat = local_stat;
+#endif
+  /* We don't bother setting gl_lstat, since glob never calls it.
+     The slot is only there for compatibility with 4.4 BSD.  */
+}
+
+void
+hash_init_directories (void)
+{
+  hash_init (&directories, DIRECTORY_BUCKETS,
+	     directory_hash_1, directory_hash_2, directory_hash_cmp);
+  hash_init (&directory_contents, DIRECTORY_BUCKETS,
+	     directory_contents_hash_1, directory_contents_hash_2,
+             directory_contents_hash_cmp);
+}
Index: /tags/kBuild-0.1.4/src/kmk/doc/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/doc/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/doc/Makefile.am	(revision 1780)
@@ -0,0 +1,35 @@
+# -*-Makefile-*-, or close enough
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+# Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+TEXI2HTML = texi2html
+TEXI2HTML_FLAGS = -split_chapter
+
+info_TEXINFOS =	make.texi
+make_TEXINFOS = fdl.texi make-stds.texi
+
+CLEANFILES = make*.html
+
+## ----------------------------- ##
+## Other documentation formats.  ##
+## ----------------------------- ##
+
+html: make_1.html
+
+make_1.html: $(info_TEXINFOS) $(make_TEXINFOS)
+	$(TEXI2HTML) $(TEXI2HTML_FLAGS) $(srcdir)/make.texi
+
+.PHONY: html
Index: /tags/kBuild-0.1.4/src/kmk/doc/make.texi
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/doc/make.texi	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/doc/make.texi	(revision 1780)
@@ -0,0 +1,11134 @@
+\input texinfo                @c -*- Texinfo -*-
+@c %**start of header
+@setfilename make.info
+
+@include version.texi
+@set EDITION 0.70
+@set RCSID $Id: make.texi,v 1.47 2007/05/11 20:57:21 psmith Exp $
+
+@settitle GNU @code{make}
+@setchapternewpage odd
+@c Combine the variable and function indices:
+@syncodeindex vr fn
+@c Combine the program and concept indices:
+@syncodeindex pg cp
+@c FSF publishers: format makebook.texi instead of using this file directly.
+@c ISBN provided by Lisa M. Opus Goldstein <opus@gnu.org>, 5 May 2004
+@set ISBN 1-882114-83-5
+@c %**end of header
+
+@copying
+This file documents the GNU @code{make} utility, which determines
+automatically which pieces of a large program need to be recompiled,
+and issues the commands to recompile them.
+
+This is Edition @value{EDITION}, last updated @value{UPDATED},
+of @cite{The GNU Make Manual}, for GNU @code{make} version @value{VERSION}.
+
+Copyright @copyright{} 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
+and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License.''
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+@end quotation
+@end copying
+
+@c finalout
+
+@c ISPELL CHECK: done, 10 June 1993 --roland
+@c ISPELL CHECK: done, 2000-06-25 --Martin Buchholz
+
+
+@dircategory Software development
+@direntry
+* Make: (make).            Remake files automatically.
+@end direntry
+
+@iftex
+@shorttitlepage GNU Make
+@end iftex
+@titlepage
+@title GNU Make
+@subtitle A Program for Directing Recompilation
+@subtitle GNU @code{make} Version @value{VERSION}
+@subtitle @value{UPDATED-MONTH}
+@author Richard M. Stallman, Roland McGrath, Paul D. Smith
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@sp 2
+Published by the Free Software Foundation @*
+51 Franklin St. -- Fifth Floor @*
+Boston, MA 02110-1301 USA @*
+ISBN @value{ISBN} @*
+@sp 2
+Cover art by Etienne Suvasa.
+@end titlepage
+
+@summarycontents
+@contents
+
+@ifnottex
+@node Top, Overview, (dir), (dir)
+@top GNU @code{make}
+
+@insertcopying
+@end ifnottex
+
+@menu
+* Overview::                    Overview of @code{make}.
+* Introduction::                An introduction to @code{make}.
+* Makefiles::                   Makefiles tell @code{make} what to do.
+* Rules::                       Rules describe when a file must be remade.
+* Commands::                    Commands say how to remake a file.
+* Using Variables::             You can use variables to avoid repetition.
+* Conditionals::                Use or ignore parts of the makefile based
+                                  on the values of variables.
+* Functions::                   Many powerful ways to manipulate text.
+* Invoking make: Running.       How to invoke @code{make} on the command line.
+* Implicit Rules::              Use implicit rules to treat many files alike,
+                                  based on their file names.
+* Archives::                    How @code{make} can update library archives.
+* Features::                    Features GNU @code{make} has over other @code{make}s.
+* Missing::                     What GNU @code{make} lacks from other @code{make}s.
+* Makefile Conventions::        Conventions for writing makefiles for
+                                  GNU programs.
+* Quick Reference::             A quick reference for experienced users.
+* Error Messages::              A list of common errors generated by @code{make}.
+* Complex Makefile::            A real example of a straightforward,
+                                  but nontrivial, makefile.
+
+* GNU Free Documentation License::  License for copying this manual
+* Concept Index::               Index of Concepts
+* Name Index::                  Index of Functions, Variables, & Directives
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Overview of @code{make}
+
+* Preparing::                   Preparing and Running Make
+* Reading::                     On Reading this Text
+* Bugs::                        Problems and Bugs
+
+An Introduction to Makefiles
+
+* Rule Introduction::           What a rule looks like.
+* Simple Makefile::             A Simple Makefile
+* How Make Works::              How @code{make} Processes This Makefile
+* Variables Simplify::          Variables Make Makefiles Simpler
+* make Deduces::                Letting @code{make} Deduce the Commands
+* Combine By Prerequisite::     Another Style of Makefile
+* Cleanup::                     Rules for Cleaning the Directory
+
+Writing Makefiles
+
+* Makefile Contents::           What makefiles contain.
+* Makefile Names::              How to name your makefile.
+* Include::                     How one makefile can use another makefile.
+* MAKEFILES Variable::          The environment can specify extra makefiles.
+* MAKEFILE_LIST Variable::      Discover which makefiles have been read.
+* Special Variables::           Other special variables.
+* Remaking Makefiles::          How makefiles get remade.
+* Overriding Makefiles::        How to override part of one makefile
+                                  with another makefile.
+* Reading Makefiles::           How makefiles are parsed.
+* Secondary Expansion::         How and when secondary expansion is performed.
+
+Writing Rules
+
+* Rule Example::                An example explained.
+* Rule Syntax::                 General syntax explained.
+* Prerequisite Types::          There are two types of prerequisites.
+* Wildcards::                   Using wildcard characters such as `*'.
+* Directory Search::            Searching other directories for source files.
+* Phony Targets::               Using a target that is not a real file's name.
+* Force Targets::               You can use a target without commands
+                                  or prerequisites to mark other targets
+                                  as phony.
+* Empty Targets::               When only the date matters and the
+                                  files are empty.
+* Special Targets::             Targets with special built-in meanings.
+* Multiple Targets::            When to make use of several targets in a rule.
+* Multiple Rules::              How to use several rules with the same target.
+* Static Pattern::              Static pattern rules apply to multiple targets
+                                  and can vary the prerequisites according to
+                                  the target name.
+* Double-Colon::                How to use a special kind of rule to allow
+                                  several independent rules for one target.
+* Automatic Prerequisites::     How to automatically generate rules giving
+                                  prerequisites from source files themselves.
+
+Using Wildcard Characters in File Names
+
+* Wildcard Examples::           Several examples
+* Wildcard Pitfall::            Problems to avoid.
+* Wildcard Function::           How to cause wildcard expansion where
+                                  it does not normally take place.
+
+Searching Directories for Prerequisites
+
+* General Search::              Specifying a search path that applies
+                                  to every prerequisite.
+* Selective Search::            Specifying a search path
+                                  for a specified class of names.
+* Search Algorithm::            When and how search paths are applied.
+* Commands/Search::             How to write shell commands that work together
+                                  with search paths.
+* Implicit/Search::             How search paths affect implicit rules.
+* Libraries/Search::            Directory search for link libraries.
+
+Static Pattern Rules
+
+* Static Usage::                The syntax of static pattern rules.
+* Static versus Implicit::      When are they better than implicit rules?
+
+Writing the Commands in Rules
+
+* Command Syntax::              Command syntax features and pitfalls.
+* Echoing::                     How to control when commands are echoed.
+* Execution::                   How commands are executed.
+* Parallel::                    How commands can be executed in parallel.
+* Errors::                      What happens after a command execution error.
+* Interrupts::                  What happens when a command is interrupted.
+* Recursion::                   Invoking @code{make} from makefiles.
+* Sequences::                   Defining canned sequences of commands.
+* Empty Commands::              Defining useful, do-nothing commands.
+
+Command Syntax
+
+* Splitting Lines::             Breaking long command lines for readability.
+* Variables in Commands::       Using @code{make} variables in commands.
+
+Command Execution
+
+* Choosing the Shell::          How @code{make} chooses the shell used
+                                  to run commands.
+
+Recursive Use of @code{make}
+
+* MAKE Variable::               The special effects of using @samp{$(MAKE)}.
+* Variables/Recursion::         How to communicate variables to a sub-@code{make}.
+* Options/Recursion::           How to communicate options to a sub-@code{make}.
+* -w Option::                   How the @samp{-w} or @samp{--print-directory} option
+                                  helps debug use of recursive @code{make} commands.
+
+How to Use Variables
+
+* Reference::                   How to use the value of a variable.
+* Flavors::                     Variables come in two flavors.
+* Advanced::                    Advanced features for referencing a variable.
+* Values::                      All the ways variables get their values.
+* Setting::                     How to set a variable in the makefile.
+* Appending::                   How to append more text to the old value
+                                  of a variable.
+* Override Directive::          How to set a variable in the makefile even if
+                                  the user has set it with a command argument.
+* Defining::                    An alternate way to set a variable
+                                  to a verbatim string.
+* Environment::                 Variable values can come from the environment.
+* Target-specific::             Variable values can be defined on a per-target
+                                  basis.
+* Pattern-specific::            Target-specific variable values can be applied
+                                  to a group of targets that match a pattern.
+
+Advanced Features for Reference to Variables
+
+* Substitution Refs::           Referencing a variable with
+                                  substitutions on the value.
+* Computed Names::              Computing the name of the variable to refer to.
+
+Conditional Parts of Makefiles
+
+* Conditional Example::         Example of a conditional
+* Conditional Syntax::          The syntax of conditionals.
+* Testing Flags::               Conditionals that test flags.
+
+Functions for Transforming Text
+
+* Syntax of Functions::         How to write a function call.
+* Text Functions::              General-purpose text manipulation functions.
+* File Name Functions::         Functions for manipulating file names.
+* Conditional Functions::       Functions that implement conditions.
+* Foreach Function::            Repeat some text with controlled variation.
+* Call Function::               Expand a user-defined function.
+* Value Function::              Return the un-expanded value of a variable.
+* Eval Function::               Evaluate the arguments as makefile syntax.
+* Origin Function::             Find where a variable got its value.
+* Flavor Function::             Find out the flavor of a variable.
+* Shell Function::              Substitute the output of a shell command.
+* Make Control Functions::      Functions that control how make runs.
+
+How to Run @code{make}
+
+* Makefile Arguments::          How to specify which makefile to use.
+* Goals::                       How to use goal arguments to specify which
+                                  parts of the makefile to use.
+* Instead of Execution::        How to use mode flags to specify what
+                                  kind of thing to do with the commands
+                                  in the makefile other than simply
+                                  execute them.
+* Avoiding Compilation::        How to avoid recompiling certain files.
+* Overriding::                  How to override a variable to specify
+                                  an alternate compiler and other things.
+* Testing::                     How to proceed past some errors, to
+                                  test compilation.
+* Options Summary::             Summary of Options
+
+Using Implicit Rules
+
+* Using Implicit::              How to use an existing implicit rule
+                                  to get the commands for updating a file.
+* Catalogue of Rules::          A list of built-in implicit rules.
+* Implicit Variables::          How to change what predefined rules do.
+* Chained Rules::               How to use a chain of implicit rules.
+* Pattern Rules::               How to define new implicit rules.
+* Last Resort::                 How to define commands for rules which
+                                  cannot find any.
+* Suffix Rules::                The old-fashioned style of implicit rule.
+* Implicit Rule Search::        The precise algorithm for applying
+                                  implicit rules.
+
+Defining and Redefining Pattern Rules
+
+* Pattern Intro::               An introduction to pattern rules.
+* Pattern Examples::            Examples of pattern rules.
+* Automatic Variables::         How to use automatic variables in the
+                                  commands of implicit rules.
+* Pattern Match::               How patterns match.
+* Match-Anything Rules::        Precautions you should take prior to
+                                  defining rules that can match any
+                                  target file whatever.
+* Canceling Rules::             How to override or cancel built-in rules.
+
+Using @code{make} to Update Archive Files
+
+* Archive Members::             Archive members as targets.
+* Archive Update::              The implicit rule for archive member targets.
+* Archive Pitfalls::            Dangers to watch out for when using archives.
+* Archive Suffix Rules::        You can write a special kind of suffix rule
+                                  for updating archives.
+
+Implicit Rule for Archive Member Targets
+
+* Archive Symbols::             How to update archive symbol directories.
+
+@end detailmenu
+@end menu
+
+@node Overview, Introduction, Top, Top
+@comment  node-name,  next,  previous,  up
+@chapter Overview of @code{make}
+
+The @code{make} utility automatically determines which pieces of a large
+program need to be recompiled, and issues commands to recompile them.
+This manual describes GNU @code{make}, which was implemented by Richard
+Stallman and Roland McGrath.  Development since Version 3.76 has been
+handled by Paul D. Smith.
+
+GNU @code{make} conforms to section 6.2 of @cite{IEEE Standard
+1003.2-1992} (POSIX.2).
+@cindex POSIX
+@cindex IEEE Standard 1003.2
+@cindex standards conformance
+
+Our examples show C programs, since they are most common, but you can use
+@code{make} with any programming language whose compiler can be run with a
+shell command.  Indeed, @code{make} is not limited to programs.  You can
+use it to describe any task where some files must be updated automatically
+from others whenever the others change.
+
+@menu
+* Preparing::                   Preparing and Running Make
+* Reading::                     On Reading this Text
+* Bugs::                        Problems and Bugs
+@end menu
+
+@node Preparing, Reading, Overview, Overview
+@ifnottex
+@heading Preparing and Running Make
+@end ifnottex
+
+To prepare to use @code{make}, you must write a file called
+the @dfn{makefile} that describes the relationships among files
+in your program and provides commands for updating each file.
+In a program, typically, the executable file is updated from object
+files, which are in turn made by compiling source files.@refill
+
+Once a suitable makefile exists, each time you change some source files,
+this simple shell command:
+
+@example
+make
+@end example
+
+@noindent
+suffices to perform all necessary recompilations.  The @code{make} program
+uses the makefile data base and the last-modification times of the files to
+decide which of the files need to be updated.  For each of those files, it
+issues the commands recorded in the data base.
+
+You can provide command line arguments to @code{make} to control which
+files should be recompiled, or how.  @xref{Running, ,How to Run
+@code{make}}.
+
+@node Reading, Bugs, Preparing, Overview
+@section How to Read This Manual
+
+If you are new to @code{make}, or are looking for a general
+introduction, read the first few sections of each chapter, skipping the
+later sections.  In each chapter, the first few sections contain
+introductory or general information and the later sections contain
+specialized or technical information.
+@ifnottex
+The exception is the second chapter, @ref{Introduction, ,An
+Introduction to Makefiles}, all of which is introductory.
+@end ifnottex
+@iftex
+The exception is @ref{Introduction, ,An Introduction to Makefiles},
+all of which is introductory.
+@end iftex
+
+If you are familiar with other @code{make} programs, see @ref{Features,
+,Features of GNU @code{make}}, which lists the enhancements GNU
+@code{make} has, and @ref{Missing, ,Incompatibilities and Missing
+Features}, which explains the few things GNU @code{make} lacks that
+others have.
+
+For a quick summary, see @ref{Options Summary}, @ref{Quick Reference},
+and @ref{Special Targets}.
+
+@node Bugs,  , Reading, Overview
+@section Problems and Bugs
+@cindex reporting bugs
+@cindex bugs, reporting
+@cindex problems and bugs, reporting
+
+If you have problems with GNU @code{make} or think you've found a bug,
+please report it to the developers; we cannot promise to do anything but
+we might well want to fix it.
+
+Before reporting a bug, make sure you've actually found a real bug.
+Carefully reread the documentation and see if it really says you can do
+what you're trying to do.  If it's not clear whether you should be able
+to do something or not, report that too; it's a bug in the
+documentation!
+
+Before reporting a bug or trying to fix it yourself, try to isolate it
+to the smallest possible makefile that reproduces the problem.  Then
+send us the makefile and the exact results @code{make} gave you,
+including any error or warning messages.  Please don't paraphrase
+these messages: it's best to cut and paste them into your report.
+When generating this small makefile, be sure to not use any non-free
+or unusual tools in your commands: you can almost always emulate what
+such a tool would do with simple shell commands.  Finally, be sure to
+explain what you expected to occur; this will help us decide whether
+the problem was really in the documentation.
+
+Once you have a precise problem you can report it in one of two ways.
+Either send electronic mail to:
+
+@example
+    bug-make@@gnu.org
+@end example
+
+@noindent
+or use our Web-based project management tool, at:
+
+@example
+    http://savannah.gnu.org/projects/make/
+@end example
+
+@noindent
+In addition to the information above, please be careful to include the
+version number of @code{make} you are using.  You can get this
+information with the command @samp{make --version}.  Be sure also to
+include the type of machine and operating system you are using.  One
+way to obtain this information is by looking at the final lines of
+output from the command @samp{make --help}.
+
+@node Introduction, Makefiles, Overview, Top
+@comment  node-name,  next,  previous,  up
+@chapter An Introduction to Makefiles
+
+You need a file called a @dfn{makefile} to tell @code{make} what to do.
+Most often, the makefile tells @code{make} how to compile and link a
+program.
+@cindex makefile
+
+In this chapter, we will discuss a simple makefile that describes how to
+compile and link a text editor which consists of eight C source files
+and three header files.  The makefile can also tell @code{make} how to
+run miscellaneous commands when explicitly asked (for example, to remove
+certain files as a clean-up operation).  To see a more complex example
+of a makefile, see @ref{Complex Makefile}.
+
+When @code{make} recompiles the editor, each changed C source file
+must be recompiled.  If a header file has changed, each C source file
+that includes the header file must be recompiled to be safe.  Each
+compilation produces an object file corresponding to the source file.
+Finally, if any source file has been recompiled, all the object files,
+whether newly made or saved from previous compilations, must be linked
+together to produce the new executable editor.
+@cindex recompilation
+@cindex editor
+
+@menu
+* Rule Introduction::           What a rule looks like.
+* Simple Makefile::             A Simple Makefile
+* How Make Works::              How @code{make} Processes This Makefile
+* Variables Simplify::          Variables Make Makefiles Simpler
+* make Deduces::                Letting @code{make} Deduce the Commands
+* Combine By Prerequisite::     Another Style of Makefile
+* Cleanup::                     Rules for Cleaning the Directory
+@end menu
+
+@node Rule Introduction, Simple Makefile, Introduction, Introduction
+@comment  node-name,  next,  previous,  up
+@section What a Rule Looks Like
+@cindex rule, introduction to
+@cindex makefile rule parts
+@cindex parts of makefile rule
+
+A simple makefile consists of ``rules'' with the following shape:
+
+@cindex targets, introduction to
+@cindex prerequisites, introduction to
+@cindex commands, introduction to
+@example
+@group
+@var{target} @dots{} : @var{prerequisites} @dots{}
+        @var{command}
+        @dots{}
+        @dots{}
+@end group
+@end example
+
+A @dfn{target} is usually the name of a file that is generated by a
+program; examples of targets are executable or object files.  A target
+can also be the name of an action to carry out, such as @samp{clean}
+(@pxref{Phony Targets}).
+
+A @dfn{prerequisite} is a file that is used as input to create the
+target.  A target often depends on several files.
+
+@cindex tabs in rules
+A @dfn{command} is an action that @code{make} carries out.
+A rule may have more than one command, each on its own line.
+@strong{Please note:} you need to put a tab character at the beginning of
+every command line!  This is an obscurity that catches the unwary.
+
+Usually a command is in a rule with prerequisites and serves to create a
+target file if any of the prerequisites change.  However, the rule that
+specifies commands for the target need not have prerequisites.  For
+example, the rule containing the delete command associated with the
+target @samp{clean} does not have prerequisites.
+
+A @dfn{rule}, then, explains how and when to remake certain files
+which are the targets of the particular rule.  @code{make} carries out
+the commands on the prerequisites to create or update the target.  A
+rule can also explain how and when to carry out an action.
+@xref{Rules, , Writing Rules}.
+
+A makefile may contain other text besides rules, but a simple makefile
+need only contain rules.  Rules may look somewhat more complicated
+than shown in this template, but all fit the pattern more or less.
+
+@node Simple Makefile, How Make Works, Rule Introduction, Introduction
+@section A Simple Makefile
+@cindex simple makefile
+@cindex makefile, simple
+
+Here is a straightforward makefile that describes the way an
+executable file called @code{edit} depends on eight object files
+which, in turn, depend on eight C source and three header files.
+
+In this example, all the C files include @file{defs.h}, but only those
+defining editing commands include @file{command.h}, and only low
+level files that change the editor buffer include @file{buffer.h}.
+
+@example
+@group
+edit : main.o kbd.o command.o display.o \
+       insert.o search.o files.o utils.o
+        cc -o edit main.o kbd.o command.o display.o \
+                   insert.o search.o files.o utils.o
+
+main.o : main.c defs.h
+        cc -c main.c
+kbd.o : kbd.c defs.h command.h
+        cc -c kbd.c
+command.o : command.c defs.h command.h
+        cc -c command.c
+display.o : display.c defs.h buffer.h
+        cc -c display.c
+insert.o : insert.c defs.h buffer.h
+        cc -c insert.c
+search.o : search.c defs.h buffer.h
+        cc -c search.c
+files.o : files.c defs.h buffer.h command.h
+        cc -c files.c
+utils.o : utils.c defs.h
+        cc -c utils.c
+clean :
+        rm edit main.o kbd.o command.o display.o \
+           insert.o search.o files.o utils.o
+@end group
+@end example
+
+@noindent
+We split each long line into two lines using backslash-newline; this is
+like using one long line, but is easier to read.
+@cindex continuation lines
+@cindex @code{\} (backslash), for continuation lines
+@cindex backslash (@code{\}), for continuation lines
+@cindex quoting newline, in makefile
+@cindex newline, quoting, in makefile
+
+To use this makefile to create the executable file called @file{edit},
+type:
+
+@example
+make
+@end example
+
+To use this makefile to delete the executable file and all the object
+files from the directory, type:
+
+@example
+make clean
+@end example
+
+In the example makefile, the targets include the executable file
+@samp{edit}, and the object files @samp{main.o} and @samp{kbd.o}.  The
+prerequisites are files such as @samp{main.c} and @samp{defs.h}.
+In fact, each @samp{.o} file is both a target and a prerequisite.
+Commands include @w{@samp{cc -c main.c}} and @w{@samp{cc -c kbd.c}}.
+
+When a target is a file, it needs to be recompiled or relinked if any
+of its prerequisites change.  In addition, any prerequisites that are
+themselves automatically generated should be updated first.  In this
+example, @file{edit} depends on each of the eight object files; the
+object file @file{main.o} depends on the source file @file{main.c} and
+on the header file @file{defs.h}.
+
+A shell command follows each line that contains a target and
+prerequisites.  These shell commands say how to update the target file.
+A tab character must come at the beginning of every command line to
+distinguish command lines from other lines in the makefile.  (Bear in
+mind that @code{make} does not know anything about how the commands
+work.  It is up to you to supply commands that will update the target
+file properly.  All @code{make} does is execute the commands in the rule
+you have specified when the target file needs to be updated.)
+@cindex shell command
+
+The target @samp{clean} is not a file, but merely the name of an
+action.  Since you
+normally
+do not want to carry out the actions in this rule, @samp{clean} is not a prerequisite of any other rule.
+Consequently, @code{make} never does anything with it unless you tell
+it specifically.  Note that this rule not only is not a prerequisite, it
+also does not have any prerequisites, so the only purpose of the rule
+is to run the specified commands.  Targets that do not refer to files
+but are just actions are called @dfn{phony targets}.  @xref{Phony
+Targets}, for information about this kind of target.  @xref{Errors, ,
+Errors in Commands}, to see how to cause @code{make} to ignore errors
+from @code{rm} or any other command.
+@cindex @code{clean} target
+@cindex @code{rm} (shell command)
+
+@node How Make Works, Variables Simplify, Simple Makefile, Introduction
+@comment  node-name,  next,  previous,  up
+@section How @code{make} Processes a Makefile
+@cindex processing a makefile
+@cindex makefile, how @code{make} processes
+
+By default, @code{make} starts with the first target (not targets whose
+names start with @samp{.}).  This is called the @dfn{default goal}.
+(@dfn{Goals} are the targets that @code{make} strives ultimately to
+update.    You can override this behavior using the command line
+(@pxref{Goals, , Arguments to Specify the Goals}) or with the
+@code{.DEFAULT_GOAL} special variable (@pxref{Special Variables, ,
+Other Special Variables}).
+@cindex default goal
+@cindex goal, default
+@cindex goal
+
+In the simple example of the previous section, the default goal is to
+update the executable program @file{edit}; therefore, we put that rule
+first.
+
+Thus, when you give the command:
+
+@example
+make
+@end example
+
+@noindent
+@code{make} reads the makefile in the current directory and begins by
+processing the first rule.  In the example, this rule is for relinking
+@file{edit}; but before @code{make} can fully process this rule, it
+must process the rules for the files that @file{edit} depends on,
+which in this case are the object files.  Each of these files is
+processed according to its own rule.  These rules say to update each
+@samp{.o} file by compiling its source file.  The recompilation must
+be done if the source file, or any of the header files named as
+prerequisites, is more recent than the object file, or if the object
+file does not exist.
+
+The other rules are processed because their targets appear as
+prerequisites of the goal.  If some other rule is not depended on by the
+goal (or anything it depends on, etc.), that rule is not processed,
+unless you tell @code{make} to do so (with a command such as
+@w{@code{make clean}}).
+
+Before recompiling an object file, @code{make} considers updating its
+prerequisites, the source file and header files.  This makefile does not
+specify anything to be done for them---the @samp{.c} and @samp{.h} files
+are not the targets of any rules---so @code{make} does nothing for these
+files.  But @code{make} would update automatically generated C programs,
+such as those made by Bison or Yacc, by their own rules at this time.
+
+After recompiling whichever object files need it, @code{make} decides
+whether to relink @file{edit}.  This must be done if the file
+@file{edit} does not exist, or if any of the object files are newer than
+it.  If an object file was just recompiled, it is now newer than
+@file{edit}, so @file{edit} is relinked.
+@cindex relinking
+
+Thus, if we change the file @file{insert.c} and run @code{make},
+@code{make} will compile that file to update @file{insert.o}, and then
+link @file{edit}.  If we change the file @file{command.h} and run
+@code{make}, @code{make} will recompile the object files @file{kbd.o},
+@file{command.o} and @file{files.o} and then link the file @file{edit}.
+
+@node Variables Simplify, make Deduces, How Make Works, Introduction
+@section Variables Make Makefiles Simpler
+@cindex variables
+@cindex simplifying with variables
+
+In our example, we had to list all the object files twice in the rule for
+@file{edit} (repeated here):
+
+@example
+@group
+edit : main.o kbd.o command.o display.o \
+              insert.o search.o files.o utils.o
+        cc -o edit main.o kbd.o command.o display.o \
+                   insert.o search.o files.o utils.o
+@end group
+@end example
+
+@cindex @code{objects}
+Such duplication is error-prone; if a new object file is added to the
+system, we might add it to one list and forget the other.  We can eliminate
+the risk and simplify the makefile by using a variable.  @dfn{Variables}
+allow a text string to be defined once and substituted in multiple places
+later (@pxref{Using Variables, ,How to Use Variables}).
+
+@cindex @code{OBJECTS}
+@cindex @code{objs}
+@cindex @code{OBJS}
+@cindex @code{obj}
+@cindex @code{OBJ}
+It is standard practice for every makefile to have a variable named
+@code{objects}, @code{OBJECTS}, @code{objs}, @code{OBJS}, @code{obj},
+or @code{OBJ} which is a list of all object file names.  We would
+define such a variable @code{objects} with a line like this in the
+makefile:@refill
+
+@example
+@group
+objects = main.o kbd.o command.o display.o \
+          insert.o search.o files.o utils.o
+@end group
+@end example
+
+@noindent
+Then, each place we want to put a list of the object file names, we can
+substitute the variable's value by writing @samp{$(objects)}
+(@pxref{Using Variables, ,How to Use Variables}).
+
+Here is how the complete simple makefile looks when you use a variable
+for the object files:
+
+@example
+@group
+objects = main.o kbd.o command.o display.o \
+          insert.o search.o files.o utils.o
+
+edit : $(objects)
+        cc -o edit $(objects)
+main.o : main.c defs.h
+        cc -c main.c
+kbd.o : kbd.c defs.h command.h
+        cc -c kbd.c
+command.o : command.c defs.h command.h
+        cc -c command.c
+display.o : display.c defs.h buffer.h
+        cc -c display.c
+insert.o : insert.c defs.h buffer.h
+        cc -c insert.c
+search.o : search.c defs.h buffer.h
+        cc -c search.c
+files.o : files.c defs.h buffer.h command.h
+        cc -c files.c
+utils.o : utils.c defs.h
+        cc -c utils.c
+clean :
+        rm edit $(objects)
+@end group
+@end example
+
+@node make Deduces, Combine By Prerequisite, Variables Simplify, Introduction
+@section Letting @code{make} Deduce the Commands
+@cindex deducing commands (implicit rules)
+@cindex implicit rule, introduction to
+@cindex rule, implicit, introduction to
+
+It is not necessary to spell out the commands for compiling the individual
+C source files, because @code{make} can figure them out: it has an
+@dfn{implicit rule} for updating a @samp{.o} file from a correspondingly
+named @samp{.c} file using a @samp{cc -c} command.  For example, it will
+use the command @samp{cc -c main.c -o main.o} to compile @file{main.c} into
+@file{main.o}.  We can therefore omit the commands from the rules for the
+object files.  @xref{Implicit Rules, ,Using Implicit Rules}.@refill
+
+When a @samp{.c} file is used automatically in this way, it is also
+automatically added to the list of prerequisites.  We can therefore omit
+the @samp{.c} files from the prerequisites, provided we omit the commands.
+
+Here is the entire example, with both of these changes, and a variable
+@code{objects} as suggested above:
+
+@example
+@group
+objects = main.o kbd.o command.o display.o \
+          insert.o search.o files.o utils.o
+
+edit : $(objects)
+        cc -o edit $(objects)
+
+main.o : defs.h
+kbd.o : defs.h command.h
+command.o : defs.h command.h
+display.o : defs.h buffer.h
+insert.o : defs.h buffer.h
+search.o : defs.h buffer.h
+files.o : defs.h buffer.h command.h
+utils.o : defs.h
+
+.PHONY : clean
+clean :
+        rm edit $(objects)
+@end group
+@end example
+
+@noindent
+This is how we would write the makefile in actual practice.  (The
+complications associated with @samp{clean} are described elsewhere.
+See @ref{Phony Targets}, and @ref{Errors, ,Errors in Commands}.)
+
+Because implicit rules are so convenient, they are important.  You
+will see them used frequently.@refill
+
+@node Combine By Prerequisite, Cleanup, make Deduces, Introduction
+@section Another Style of Makefile
+@cindex combining rules by prerequisite
+
+When the objects of a makefile are created only by implicit rules, an
+alternative style of makefile is possible.  In this style of makefile,
+you group entries by their prerequisites instead of by their targets.
+Here is what one looks like:
+
+@example
+@group
+objects = main.o kbd.o command.o display.o \
+          insert.o search.o files.o utils.o
+
+edit : $(objects)
+        cc -o edit $(objects)
+
+$(objects) : defs.h
+kbd.o command.o files.o : command.h
+display.o insert.o search.o files.o : buffer.h
+@end group
+@end example
+
+@noindent
+Here @file{defs.h} is given as a prerequisite of all the object files;
+@file{command.h} and @file{buffer.h} are prerequisites of the specific
+object files listed for them.
+
+Whether this is better is a matter of taste: it is more compact, but some
+people dislike it because they find it clearer to put all the information
+about each target in one place.
+
+@node Cleanup,  , Combine By Prerequisite, Introduction
+@section Rules for Cleaning the Directory
+@cindex cleaning up
+@cindex removing, to clean up
+
+Compiling a program is not the only thing you might want to write rules
+for.  Makefiles commonly tell how to do a few other things besides
+compiling a program: for example, how to delete all the object files
+and executables so that the directory is @samp{clean}.
+
+@cindex @code{clean} target
+Here is how we
+could write a @code{make} rule for cleaning our example editor:
+
+@example
+@group
+clean:
+        rm edit $(objects)
+@end group
+@end example
+
+In practice, we might want to write the rule in a somewhat more
+complicated manner to handle unanticipated situations.  We would do this:
+
+@example
+@group
+.PHONY : clean
+clean :
+        -rm edit $(objects)
+@end group
+@end example
+
+@noindent
+This prevents @code{make} from getting confused by an actual file
+called @file{clean} and causes it to continue in spite of errors from
+@code{rm}.  (See @ref{Phony Targets}, and @ref{Errors, ,Errors in
+Commands}.)
+
+@noindent
+A rule such as this should not be placed at the beginning of the
+makefile, because we do not want it to run by default!  Thus, in the
+example makefile, we want the rule for @code{edit}, which recompiles
+the editor, to remain the default goal.
+
+Since @code{clean} is not a prerequisite of @code{edit}, this rule will not
+run at all if we give the command @samp{make} with no arguments.  In
+order to make the rule run, we have to type @samp{make clean}.
+@xref{Running, ,How to Run @code{make}}.
+
+@node Makefiles, Rules, Introduction, Top
+@chapter Writing Makefiles
+
+@cindex makefile, how to write
+The information that tells @code{make} how to recompile a system comes from
+reading a data base called the @dfn{makefile}.
+
+@menu
+* Makefile Contents::           What makefiles contain.
+* Makefile Names::              How to name your makefile.
+* Include::                     How one makefile can use another makefile.
+* MAKEFILES Variable::          The environment can specify extra makefiles.
+* MAKEFILE_LIST Variable::      Discover which makefiles have been read.
+* Special Variables::           Other special variables.
+* Remaking Makefiles::          How makefiles get remade.
+* Overriding Makefiles::        How to override part of one makefile
+                                  with another makefile.
+* Reading Makefiles::           How makefiles are parsed.
+* Secondary Expansion::         How and when secondary expansion is performed.
+@end menu
+
+@node Makefile Contents, Makefile Names, Makefiles, Makefiles
+@section What Makefiles Contain
+
+Makefiles contain five kinds of things: @dfn{explicit rules},
+@dfn{implicit rules}, @dfn{variable definitions}, @dfn{directives},
+and @dfn{comments}.  Rules, variables, and directives are described at
+length in later chapters.@refill
+
+@itemize @bullet
+@cindex rule, explicit, definition of
+@cindex explicit rule, definition of
+@item
+An @dfn{explicit rule} says when and how to remake one or more files,
+called the rule's @dfn{targets}.  It lists the other files that the
+targets depend on, called the @dfn{prerequisites} of the target, and
+may also give commands to use to create or update the targets.
+@xref{Rules, ,Writing Rules}.
+
+@cindex rule, implicit, definition of
+@cindex implicit rule, definition of
+@item
+An @dfn{implicit rule} says when and how to remake a class of files
+based on their names.  It describes how a target may depend on a file
+with a name similar to the target and gives commands to create or
+update such a target.  @xref{Implicit Rules, ,Using Implicit Rules}.
+
+@cindex variable definition
+@item
+A @dfn{variable definition} is a line that specifies a text string
+value for a variable that can be substituted into the text later.  The
+simple makefile example shows a variable definition for @code{objects}
+as a list of all object files (@pxref{Variables Simplify, , Variables
+Make Makefiles Simpler}).
+
+@cindex directive
+@item
+A @dfn{directive} is a command for @code{make} to do something special while
+reading the makefile.  These include:
+
+@itemize @bullet
+@item
+Reading another makefile (@pxref{Include, ,Including Other Makefiles}).
+
+@item
+Deciding (based on the values of variables) whether to use or
+ignore a part of the makefile (@pxref{Conditionals, ,Conditional Parts of Makefiles}).
+
+@item
+Defining a variable from a verbatim string containing multiple lines
+(@pxref{Defining, ,Defining Variables Verbatim}).
+@end itemize
+
+@cindex comments, in makefile
+@cindex @code{#} (comments), in makefile
+@item
+@samp{#} in a line of a makefile starts a @dfn{comment}.  It and the
+rest of the line are ignored, except that a trailing backslash not
+escaped by another backslash will continue the comment across multiple
+lines.  A line containing just a comment (with perhaps spaces before
+it) is effectively blank, and is ignored.  If you want a literal
+@code{#}, escape it with a backslash (e.g., @code{\#}).  Comments may
+appear on any line in the makefile, although they are treated
+specially in certain situations.
+
+You cannot use comments within variable references or function calls:
+any instance of @code{#} will be treated literally (rather than as the
+start of a comment) inside a variable reference or function call.
+
+Within a command script (if the line begins with a TAB character) the
+entire line is passed to the shell, just as with any other line that
+begins with a TAB.  The shell decides how to interpret the text:
+whether or not this is a comment is up to the shell.
+
+Within a @code{define} directive, comments are not ignored during the
+definition of the variable, but rather kept intact in the value of the
+variable.  When the variable is expanded they will either be treated
+as @code{make} comments or as command script text, depending on the
+context in which the variable is evaluated.
+@end itemize
+
+@node Makefile Names, Include, Makefile Contents, Makefiles
+@section What Name to Give Your Makefile
+@cindex makefile name
+@cindex name of makefile
+@cindex default makefile name
+@cindex file name of makefile
+
+@c following paragraph rewritten to avoid overfull hbox
+By default, when @code{make} looks for the makefile, it tries the
+following names, in order: @file{GNUmakefile}, @file{makefile}
+and @file{Makefile}.@refill
+@findex Makefile
+@findex GNUmakefile
+@findex makefile
+
+@cindex @code{README}
+Normally you should call your makefile either @file{makefile} or
+@file{Makefile}.  (We recommend @file{Makefile} because it appears
+prominently near the beginning of a directory listing, right near other
+important files such as @file{README}.)  The first name checked,
+@file{GNUmakefile}, is not recommended for most makefiles.  You should
+use this name if you have a makefile that is specific to GNU
+@code{make}, and will not be understood by other versions of
+@code{make}.  Other @code{make} programs look for @file{makefile} and
+@file{Makefile}, but not @file{GNUmakefile}.
+
+If @code{make} finds none of these names, it does not use any makefile.
+Then you must specify a goal with a command argument, and @code{make}
+will attempt to figure out how to remake it using only its built-in
+implicit rules.  @xref{Implicit Rules, ,Using Implicit Rules}.
+
+@cindex @code{-f}
+@cindex @code{--file}
+@cindex @code{--makefile}
+If you want to use a nonstandard name for your makefile, you can specify
+the makefile name with the @samp{-f} or @samp{--file} option.  The
+arguments @w{@samp{-f @var{name}}} or @w{@samp{--file=@var{name}}} tell
+@code{make} to read the file @var{name} as the makefile.  If you use
+more than one @samp{-f} or @samp{--file} option, you can specify several
+makefiles.  All the makefiles are effectively concatenated in the order
+specified.  The default makefile names @file{GNUmakefile},
+@file{makefile} and @file{Makefile} are not checked automatically if you
+specify @samp{-f} or @samp{--file}.@refill
+@cindex specifying makefile name
+@cindex makefile name, how to specify
+@cindex name of makefile, how to specify
+@cindex file name of makefile, how to specify
+
+@node Include, MAKEFILES Variable, Makefile Names, Makefiles
+@section Including Other Makefiles
+@cindex including other makefiles
+@cindex makefile, including
+
+@findex include
+The @code{include} directive tells @code{make} to suspend reading the
+current makefile and read one or more other makefiles before continuing.
+The directive is a line in the makefile that looks like this:
+
+@example
+include @var{filenames}@dots{}
+@end example
+
+@noindent
+@var{filenames} can contain shell file name patterns.  If
+@var{filenames} is empty, nothing is included and no error is printed.
+@cindex shell file name pattern (in @code{include})
+@cindex shell wildcards (in @code{include})
+@cindex wildcard, in @code{include}
+
+Extra spaces are allowed and ignored at the beginning of the line, but
+a tab is not allowed.  (If the line begins with a tab, it will be
+considered a command line.)  Whitespace is required between
+@code{include} and the file names, and between file names; extra
+whitespace is ignored there and at the end of the directive.  A
+comment starting with @samp{#} is allowed at the end of the line.  If
+the file names contain any variable or function references, they are
+expanded.  @xref{Using Variables, ,How to Use Variables}.
+
+For example, if you have three @file{.mk} files, @file{a.mk},
+@file{b.mk}, and @file{c.mk}, and @code{$(bar)} expands to
+@code{bish bash}, then the following expression
+
+@example
+include foo *.mk $(bar)
+@end example
+
+is equivalent to
+
+@example
+include foo a.mk b.mk c.mk bish bash
+@end example
+
+When @code{make} processes an @code{include} directive, it suspends
+reading of the containing makefile and reads from each listed file in
+turn.  When that is finished, @code{make} resumes reading the
+makefile in which the directive appears.
+
+One occasion for using @code{include} directives is when several programs,
+handled by individual makefiles in various directories, need to use a
+common set of variable definitions
+(@pxref{Setting, ,Setting Variables}) or pattern rules
+(@pxref{Pattern Rules, ,Defining and Redefining Pattern Rules}).
+
+Another such occasion is when you want to generate prerequisites from
+source files automatically; the prerequisites can be put in a file that
+is included by the main makefile.  This practice is generally cleaner
+than that of somehow appending the prerequisites to the end of the main
+makefile as has been traditionally done with other versions of
+@code{make}.  @xref{Automatic Prerequisites}.
+@cindex prerequisites, automatic generation
+@cindex automatic generation of prerequisites
+@cindex generating prerequisites automatically
+
+@cindex @code{-I}
+@cindex @code{--include-dir}
+@cindex included makefiles, default directories
+@cindex default directories for included makefiles
+@findex /usr/gnu/include
+@findex /usr/local/include
+@findex /usr/include
+If the specified name does not start with a slash, and the file is not
+found in the current directory, several other directories are searched.
+First, any directories you have specified with the @samp{-I} or
+@samp{--include-dir} option are searched
+(@pxref{Options Summary, ,Summary of Options}).
+Then the following directories (if they exist)
+are searched, in this order:
+@file{@var{prefix}/include} (normally @file{/usr/local/include}
+@footnote{GNU Make compiled for MS-DOS and MS-Windows behaves as if
+@var{prefix} has been defined to be the root of the DJGPP tree
+hierarchy.})
+@file{/usr/gnu/include},
+@file{/usr/local/include}, @file{/usr/include}.
+
+If an included makefile cannot be found in any of these directories, a
+warning message is generated, but it is not an immediately fatal error;
+processing of the makefile containing the @code{include} continues.
+Once it has finished reading makefiles, @code{make} will try to remake
+any that are out of date or don't exist.
+@xref{Remaking Makefiles, ,How Makefiles Are Remade}.
+Only after it has tried to find a way to remake a makefile and failed,
+will @code{make} diagnose the missing makefile as a fatal error.
+
+If you want @code{make} to simply ignore a makefile which does not exist
+and cannot be remade, with no error message, use the @w{@code{-include}}
+directive instead of @code{include}, like this:
+
+@example
+-include @var{filenames}@dots{}
+@end example
+
+This acts like @code{include} in every way except that there is no
+error (not even a warning) if any of the @var{filenames} do not exist.
+For compatibility with some other @code{make} implementations,
+@code{sinclude} is another name for @w{@code{-include}}.
+
+@node MAKEFILES Variable, MAKEFILE_LIST Variable, Include, Makefiles
+@section The Variable @code{MAKEFILES}
+@cindex makefile, and @code{MAKEFILES} variable
+@cindex including (@code{MAKEFILES} variable)
+
+@vindex MAKEFILES
+If the environment variable @code{MAKEFILES} is defined, @code{make}
+considers its value as a list of names (separated by whitespace) of
+additional makefiles to be read before the others.  This works much like
+the @code{include} directive: various directories are searched for those
+files (@pxref{Include, ,Including Other Makefiles}).  In addition, the
+default goal is never taken from one of these makefiles and it is not an
+error if the files listed in @code{MAKEFILES} are not found.@refill
+
+@cindex recursion, and @code{MAKEFILES} variable
+The main use of @code{MAKEFILES} is in communication between recursive
+invocations of @code{make} (@pxref{Recursion, ,Recursive Use of
+@code{make}}).  It usually is not desirable to set the environment
+variable before a top-level invocation of @code{make}, because it is
+usually better not to mess with a makefile from outside.  However, if
+you are running @code{make} without a specific makefile, a makefile in
+@code{MAKEFILES} can do useful things to help the built-in implicit
+rules work better, such as defining search paths (@pxref{Directory Search}).
+
+Some users are tempted to set @code{MAKEFILES} in the environment
+automatically on login, and program makefiles to expect this to be done.
+This is a very bad idea, because such makefiles will fail to work if run by
+anyone else.  It is much better to write explicit @code{include} directives
+in the makefiles.  @xref{Include, , Including Other Makefiles}.
+
+@node MAKEFILE_LIST Variable, Special Variables, MAKEFILES Variable, Makefiles
+@comment  node-name,  next,  previous,  up
+@section The Variable @code{MAKEFILE_LIST}
+@cindex makefiles, and @code{MAKEFILE_LIST} variable
+@cindex including (@code{MAKEFILE_LIST} variable)
+@vindex MAKEFILE_LIST
+
+As @code{make} reads various makefiles, including any obtained from the
+@code{MAKEFILES} variable, the command line, the default files, or
+from @code{include} directives, their names will be automatically
+appended to the @code{MAKEFILE_LIST} variable.  They are added right
+before @code{make} begins to parse them.
+
+This means that if the first thing a makefile does is examine the last
+word in this variable, it will be the name of the current makefile.
+Once the current makefile has used @code{include}, however, the last
+word will be the just-included makefile.
+
+If a makefile named @code{Makefile} has this content:
+
+@example
+@group
+name1 := $(lastword $(MAKEFILE_LIST))
+
+include inc.mk
+
+name2 := $(lastword $(MAKEFILE_LIST))
+
+all:
+        @@echo name1 = $(name1)
+        @@echo name2 = $(name2)
+@end group
+@end example
+
+@noindent
+then you would expect to see this output:
+
+@example
+@group
+name1 = Makefile
+name2 = inc.mk
+@end group
+@end example
+
+@xref{Text Functions}, for more information on the @code{lastword}
+function used above.  @xref{Flavors, The Two Flavors of Variables},
+for more information on simply-expanded (@code{:=}) variable
+definitions.
+
+@node Special Variables, Remaking Makefiles, MAKEFILE_LIST Variable, Makefiles
+@comment  node-name,  next,  previous,  up
+@section Other Special Variables
+@cindex makefiles, and special variables
+@cindex special variables
+
+GNU @code{make} also supports other special variables.  Unless
+otherwise documented here, these values lose their special properties
+if they are set by a makefile or on the command line.
+
+@table @code
+
+@vindex .DEFAULT_GOAL @r{(define default goal)}
+@item .DEFAULT_GOAL
+Sets the default goal to be used if no targets were specified on the
+command line (@pxref{Goals, , Arguments to Specify the Goals}).  The
+@code{.DEFAULT_GOAL} variable allows you to discover the current
+default goal, restart the default goal selection algorithm by clearing
+its value, or to explicitly set the default goal.  The following
+example illustrates these cases:
+
+@example
+@group
+# Query the default goal.
+ifeq ($(.DEFAULT_GOAL),)
+  $(warning no default goal is set)
+endif
+
+.PHONY: foo
+foo: ; @@echo $@@
+
+$(warning default goal is $(.DEFAULT_GOAL))
+
+# Reset the default goal.
+.DEFAULT_GOAL :=
+
+.PHONY: bar
+bar: ; @@echo $@@
+
+$(warning default goal is $(.DEFAULT_GOAL))
+
+# Set our own.
+.DEFAULT_GOAL := foo
+@end group
+@end example
+
+This makefile prints:
+
+@example
+@group
+no default goal is set
+default goal is foo
+default goal is bar
+foo
+@end group
+@end example
+
+Note that assigning more than one target name to @code{.DEFAULT_GOAL} is
+illegal and will result in an error.
+
+@vindex MAKE_RESTARTS @r{(number of times @code{make} has restarted)}
+@item MAKE_RESTARTS
+This variable is set only if this instance of @code{make} has
+restarted (@pxref{Remaking Makefiles, , How Makefiles Are Remade}): it
+will contain the number of times this instance has restarted.  Note
+this is not the same as recursion (counted by the @code{MAKELEVEL}
+variable).  You should not set, modify, or export this variable.
+
+@vindex .VARIABLES @r{(list of variables)}
+@item .VARIABLES
+Expands to a list of the @emph{names} of all global variables defined
+so far.  This includes variables which have empty values, as well as
+built-in variables (@pxref{Implicit Variables, , Variables Used by
+Implicit Rules}), but does not include any variables which are only
+defined in a target-specific context.  Note that any value you assign
+to this variable will be ignored; it will always return its special
+value.
+
+@c @vindex .TARGETS @r{(list of targets)}
+@c @item .TARGETS
+@c The second special variable is @code{.TARGETS}.  When expanded, the
+@c value consists of a list of all targets defined in all makefiles read
+@c up until that point.  Note it's not enough for a file to be simply
+@c mentioned in the makefile to be listed in this variable, even if it
+@c would match an implicit rule and become an ``implicit target''.  The
+@c file must appear as a target, on the left-hand side of a ``:'', to be
+@c considered a target for the purposes of this variable.
+
+@vindex .FEATURES @r{(list of supported features)}
+@item .FEATURES
+Expands to a list of special features supported by this version of
+@code{make}.  Possible values include:
+
+@table @samp
+
+@item archives
+Supports @code{ar} (archive) files using special filename syntax.
+@xref{Archives, ,Using @code{make} to Update Archive Files}.
+
+@item check-symlink
+Supports the @code{-L} (@code{--check-symlink-times}) flag.
+@xref{Options Summary, ,Summary of Options}.
+
+@item else-if
+Supports ``else if'' non-nested conditionals.  @xref{Conditional
+Syntax, ,Syntax of Conditionals}.
+
+@item jobserver
+Supports ``job server'' enhanced parallel builds.  @xref{Parallel,
+,Parallel Execution}.
+
+@item second-expansion
+Supports secondary expansion of prerequisite lists.
+
+@item order-only
+Supports order-only prerequisites.  @xref{Prerequisite Types, ,Types
+of Prerequisites}.
+
+@item target-specific
+Supports target-specific and pattern-specific variable assignments.
+@xref{Target-specific, ,Target-specific Variable Values}.
+
+@end table
+
+@vindex .INCLUDE_DIRS @r{(list of include directories)}
+@item .INCLUDE_DIRS
+Expands to a list of directories that @code{make} searches for
+included makefiles (@pxref{Include, , Including Other Makefiles}).
+
+@end table
+
+@node Remaking Makefiles, Overriding Makefiles, Special Variables, Makefiles
+@section How Makefiles Are Remade
+
+@cindex updating makefiles
+@cindex remaking makefiles
+@cindex makefile, remaking of
+Sometimes makefiles can be remade from other files, such as RCS or SCCS
+files.  If a makefile can be remade from other files, you probably want
+@code{make} to get an up-to-date version of the makefile to read in.
+
+To this end, after reading in all makefiles, @code{make} will consider
+each as a goal target and attempt to update it.  If a makefile has a
+rule which says how to update it (found either in that very makefile or
+in another one) or if an implicit rule applies to it (@pxref{Implicit
+Rules, ,Using Implicit Rules}), it will be updated if necessary.  After
+all makefiles have been checked, if any have actually been changed,
+@code{make} starts with a clean slate and reads all the makefiles over
+again.  (It will also attempt to update each of them over again, but
+normally this will not change them again, since they are already up to
+date.)@refill
+
+If you know that one or more of your makefiles cannot be remade and you
+want to keep @code{make} from performing an implicit rule search on
+them, perhaps for efficiency reasons, you can use any normal method of
+preventing implicit rule lookup to do so.  For example, you can write an
+explicit rule with the makefile as the target, and an empty command
+string (@pxref{Empty Commands, ,Using Empty Commands}).
+
+If the makefiles specify a double-colon rule to remake a file with
+commands but no prerequisites, that file will always be remade
+(@pxref{Double-Colon}).  In the case of makefiles, a makefile that has a
+double-colon rule with commands but no prerequisites will be remade every
+time @code{make} is run, and then again after @code{make} starts over
+and reads the makefiles in again.  This would cause an infinite loop:
+@code{make} would constantly remake the makefile, and never do anything
+else.  So, to avoid this, @code{make} will @strong{not} attempt to
+remake makefiles which are specified as targets of a double-colon rule
+with commands but no prerequisites.@refill
+
+If you do not specify any makefiles to be read with @samp{-f} or
+@samp{--file} options, @code{make} will try the default makefile names;
+@pxref{Makefile Names, ,What Name to Give Your Makefile}.  Unlike
+makefiles explicitly requested with @samp{-f} or @samp{--file} options,
+@code{make} is not certain that these makefiles should exist.  However,
+if a default makefile does not exist but can be created by running
+@code{make} rules, you probably want the rules to be run so that the
+makefile can be used.
+
+Therefore, if none of the default makefiles exists, @code{make} will try
+to make each of them in the same order in which they are searched for
+(@pxref{Makefile Names, ,What Name to Give Your Makefile})
+until it succeeds in making one, or it runs out of names to try.  Note
+that it is not an error if @code{make} cannot find or make any makefile;
+a makefile is not always necessary.@refill
+
+When you use the @samp{-t} or @samp{--touch} option
+(@pxref{Instead of Execution, ,Instead of Executing the Commands}),
+you would not want to use an out-of-date makefile to decide which
+targets to touch.  So the @samp{-t} option has no effect on updating
+makefiles; they are really updated even if @samp{-t} is specified.
+Likewise, @samp{-q} (or @samp{--question}) and @samp{-n} (or
+@samp{--just-print}) do not prevent updating of makefiles, because an
+out-of-date makefile would result in the wrong output for other targets.
+Thus, @samp{make -f mfile -n foo} will update @file{mfile}, read it in,
+and then print the commands to update @file{foo} and its prerequisites
+without running them.  The commands printed for @file{foo} will be those
+specified in the updated contents of @file{mfile}.
+
+However, on occasion you might actually wish to prevent updating of even
+the makefiles.  You can do this by specifying the makefiles as goals in
+the command line as well as specifying them as makefiles.  When the
+makefile name is specified explicitly as a goal, the options @samp{-t}
+and so on do apply to them.
+
+Thus, @samp{make -f mfile -n mfile foo} would read the makefile
+@file{mfile}, print the commands needed to update it without actually
+running them, and then print the commands needed to update @file{foo}
+without running them.  The commands for @file{foo} will be those
+specified by the existing contents of @file{mfile}.
+
+@node Overriding Makefiles, Reading Makefiles, Remaking Makefiles, Makefiles
+@section Overriding Part of Another Makefile
+
+@cindex overriding makefiles
+@cindex makefile, overriding
+Sometimes it is useful to have a makefile that is mostly just like
+another makefile.  You can often use the @samp{include} directive to
+include one in the other, and add more targets or variable definitions.
+However, if the two makefiles give different commands for the same
+target, @code{make} will not let you just do this.  But there is another way.
+
+@cindex match-anything rule, used to override
+In the containing makefile (the one that wants to include the other),
+you can use a match-anything pattern rule to say that to remake any
+target that cannot be made from the information in the containing
+makefile, @code{make} should look in another makefile.
+@xref{Pattern Rules}, for more information on pattern rules.
+
+For example, if you have a makefile called @file{Makefile} that says how
+to make the target @samp{foo} (and other targets), you can write a
+makefile called @file{GNUmakefile} that contains:
+
+@example
+foo:
+        frobnicate > foo
+
+%: force
+        @@$(MAKE) -f Makefile $@@
+force: ;
+@end example
+
+If you say @samp{make foo}, @code{make} will find @file{GNUmakefile},
+read it, and see that to make @file{foo}, it needs to run the command
+@samp{frobnicate > foo}.  If you say @samp{make bar}, @code{make} will
+find no way to make @file{bar} in @file{GNUmakefile}, so it will use the
+commands from the pattern rule: @samp{make -f Makefile bar}.  If
+@file{Makefile} provides a rule for updating @file{bar}, @code{make}
+will apply the rule.  And likewise for any other target that
+@file{GNUmakefile} does not say how to make.
+
+The way this works is that the pattern rule has a pattern of just
+@samp{%}, so it matches any target whatever.  The rule specifies a
+prerequisite @file{force}, to guarantee that the commands will be run even
+if the target file already exists.  We give @file{force} target empty
+commands to prevent @code{make} from searching for an implicit rule to
+build it---otherwise it would apply the same match-anything rule to
+@file{force} itself and create a prerequisite loop!
+
+@node Reading Makefiles,  Secondary Expansion, Overriding Makefiles, Makefiles
+@section How @code{make} Reads a Makefile
+@cindex reading makefiles
+@cindex makefile, parsing
+
+GNU @code{make} does its work in two distinct phases.  During the first
+phase it reads all the makefiles, included makefiles, etc. and
+internalizes all the variables and their values, implicit and explicit
+rules, and constructs a dependency graph of all the targets and their
+prerequisites.  During the second phase, @code{make} uses these internal
+structures to determine what targets will need to be rebuilt and to
+invoke the rules necessary to do so.
+
+It's important to understand this two-phase approach because it has a
+direct impact on how variable and function expansion happens; this is
+often a source of some confusion when writing makefiles.  Here we will
+present a summary of the phases in which expansion happens for different
+constructs within the makefile.  We say that expansion is
+@dfn{immediate} if it happens during the first phase: in this case
+@code{make} will expand any variables or functions in that section of a
+construct as the makefile is parsed.  We say that expansion is
+@dfn{deferred} if expansion is not performed immediately.  Expansion of
+deferred construct is not performed until either the construct appears
+later in an immediate context, or until the second phase.
+
+You may not be familiar with some of these constructs yet.  You can
+reference this section as you become familiar with them, in later
+chapters.
+
+@subheading Variable Assignment
+@cindex +=, expansion
+@cindex =, expansion
+@cindex ?=, expansion
+@cindex +=, expansion
+@cindex define, expansion
+
+Variable definitions are parsed as follows:
+
+@example
+@var{immediate} = @var{deferred}
+@var{immediate} ?= @var{deferred}
+@var{immediate} := @var{immediate}
+@var{immediate} += @var{deferred} or @var{immediate}
+
+define @var{immediate}
+  @var{deferred}
+endef
+@end example
+
+For the append operator, @samp{+=}, the right-hand side is considered
+immediate if the variable was previously set as a simple variable
+(@samp{:=}), and deferred otherwise.
+
+@subheading Conditional Statements
+@cindex ifdef, expansion
+@cindex ifeq, expansion
+@cindex ifndef, expansion
+@cindex ifneq, expansion
+
+All instances of conditional syntax are parsed immediately, in their
+entirety; this includes the @code{ifdef}, @code{ifeq}, @code{ifndef},
+and @code{ifneq} forms.  Of course this means that automatic variables
+cannot be used in conditional statements, as automatic variables are
+not set until the command script for that rule is invoked.  If you
+need to use automatic variables in a conditional you @emph{must} use
+shell conditional syntax, in your command script proper, for these
+tests, not @code{make} conditionals.
+
+@subheading Rule Definition
+@cindex target, expansion
+@cindex prerequisite, expansion
+@cindex implicit rule, expansion
+@cindex pattern rule, expansion
+@cindex explicit rule, expansion
+
+A rule is always expanded the same way, regardless of the form:
+
+@example
+@var{immediate} : @var{immediate} ; @var{deferred}
+	@var{deferred}
+@end example
+
+That is, the target and prerequisite sections are expanded immediately,
+and the commands used to construct the target are always deferred.  This
+general rule is true for explicit rules, pattern rules, suffix rules,
+static pattern rules, and simple prerequisite definitions.
+
+@node Secondary Expansion, , Reading Makefiles, Makefiles
+@section Secondary Expansion
+@cindex secondary expansion
+@cindex expansion, secondary
+
+@findex .SECONDEXPANSION
+In the previous section we learned that GNU @code{make} works in two
+distinct phases: a read-in phase and a target-update phase
+(@pxref{Reading Makefiles, , How @code{make} Reads a Makefile}).  GNU
+make also has the ability to enable a @emph{second expansion} of the
+prerequisites (only) for some or all targets defined in the makefile.
+In order for this second expansion to occur, the special target
+@code{.SECONDEXPANSION} must be defined before the first prerequisite
+list that makes use of this feature.
+
+If that special target is defined then in between the two phases
+mentioned above, right at the end of the read-in phase, all the
+prerequisites of the targets defined after the special target are
+expanded a @emph{second time}.  In most circumstances this secondary
+expansion will have no effect, since all variable and function
+references will have been expanded during the initial parsing of the
+makefiles.  In order to take advantage of the secondary expansion
+phase of the parser, then, it's necessary to @emph{escape} the
+variable or function reference in the makefile.  In this case the
+first expansion merely un-escapes the reference but doesn't expand it,
+and expansion is left to the secondary expansion phase.  For example,
+consider this makefile:
+
+@example
+.SECONDEXPANSION:
+ONEVAR = onefile
+TWOVAR = twofile
+myfile: $(ONEVAR) $$(TWOVAR)
+@end example
+
+After the first expansion phase the prerequisites list of the
+@file{myfile} target will be @code{onefile} and @code{$(TWOVAR)}; the
+first (unescaped) variable reference to @var{ONEVAR} is expanded,
+while the second (escaped) variable reference is simply unescaped,
+without being recognized as a variable reference.  Now during the
+secondary expansion the first word is expanded again but since it
+contains no variable or function references it remains the static
+value @file{onefile}, while the second word is now a normal reference
+to the variable @var{TWOVAR}, which is expanded to the value
+@file{twofile}.  The final result is that there are two prerequisites,
+@file{onefile} and @file{twofile}.
+
+Obviously, this is not a very interesting case since the same result
+could more easily have been achieved simply by having both variables
+appear, unescaped, in the prerequisites list.  One difference becomes
+apparent if the variables are reset; consider this example:
+
+@example
+.SECONDEXPANSION:
+AVAR = top
+onefile: $(AVAR)
+twofile: $$(AVAR)
+AVAR = bottom
+@end example
+
+Here the prerequisite of @file{onefile} will be expanded immediately,
+and resolve to the value @file{top}, while the prerequisite of
+@file{twofile} will not be full expanded until the secondary expansion
+and yield a value of @file{bottom}.
+
+This is marginally more exciting, but the true power of this feature
+only becomes apparent when you discover that secondary expansions
+always take place within the scope of the automatic variables for that
+target.  This means that you can use variables such as @code{$@@},
+@code{$*}, etc. during the second expansion and they will have their
+expected values, just as in the command script.  All you have to do is
+defer the expansion by escaping the @code{$}.  Also, secondary
+expansion occurs for both explicit and implicit (pattern) rules.
+Knowing this, the possible uses for this feature increase
+dramatically.  For example:
+
+@example
+.SECONDEXPANSION:
+main_OBJS := main.o try.o test.o
+lib_OBJS := lib.o api.o
+
+main lib: $$($$@@_OBJS)
+@end example
+
+Here, after the initial expansion the prerequisites of both the
+@file{main} and @file{lib} targets will be @code{$($@@_OBJS)}.  During
+the secondary expansion, the @code{$@@} variable is set to the name of
+the target and so the expansion for the @file{main} target will yield
+@code{$(main_OBJS)}, or @code{main.o try.o test.o}, while the
+secondary expansion for the @file{lib} target will yield
+@code{$(lib_OBJS)}, or @code{lib.o api.o}.
+
+You can also mix functions here, as long as they are properly escaped:
+
+@example
+main_SRCS := main.c try.c test.c
+lib_SRCS := lib.c api.c
+
+.SECONDEXPANSION:
+main lib: $$(patsubst %.c,%.o,$$($$@@_SRCS))
+@end example
+
+This version allows users to specify source files rather than object
+files, but gives the same resulting prerequisites list as the previous
+example.
+
+Evaluation of automatic variables during the secondary expansion
+phase, especially of the target name variable @code{$$@@}, behaves
+similarly to evaluation within command scripts.  However, there are
+some subtle differences and ``corner cases'' which come into play for
+the different types of rule definitions that @code{make} understands.
+The subtleties of using the different automatic variables are
+described below.
+
+@subheading Secondary Expansion of Explicit Rules
+@cindex secondary expansion and explicit rules
+@cindex explicit rules, secondary expansion of
+
+During the secondary expansion of explicit rules, @code{$$@@} and
+@code{$$%} evaluate, respectively, to the file name of the target and,
+when the target is an archive member, the target member name.  The
+@code{$$<} variable evaluates to the first prerequisite in the first
+rule for this target.  @code{$$^} and @code{$$+} evaluate to the list
+of all prerequisites of rules @emph{that have already appeared} for
+the same target (@code{$$+} with repetitions and @code{$$^}
+without).  The following example will help illustrate these behaviors:
+
+@example
+.SECONDEXPANSION:
+
+foo: foo.1 bar.1 $$< $$^ $$+    # line #1
+
+foo: foo.2 bar.2 $$< $$^ $$+    # line #2
+
+foo: foo.3 bar.3 $$< $$^ $$+    # line #3
+@end example
+
+In the first prerequisite list, all three variables (@code{$$<},
+@code{$$^}, and @code{$$+}) expand to the empty string.  In the
+second, they will have values @code{foo.1}, @code{foo.1 bar.1}, and
+@code{foo.1 bar.1} respectively.  In the third they will have values
+@code{foo.1}, @code{foo.1 bar.1 foo.2 bar.2}, and @code{foo.1 bar.1
+foo.2 bar.2 foo.1 foo.1 bar.1 foo.1 bar.1} respectively.
+
+Rules undergo secondary expansion in makefile order, except that
+the rule with the command script is always evaluated last.
+
+The variables @code{$$?} and @code{$$*} are not available and expand
+to the empty string.
+
+@subheading Secondary Expansion of Static Pattern Rules
+@cindex secondary expansion and static pattern rules
+@cindex static pattern rules, secondary expansion of
+
+Rules for secondary expansion of static pattern rules are identical to
+those for explicit rules, above, with one exception: for static
+pattern rules the @code{$$*} variable is set to the pattern stem.  As
+with explicit rules, @code{$$?} is not available and expands to the
+empty string.
+
+@subheading Secondary Expansion of Implicit Rules
+@cindex secondary expansion and implicit rules
+@cindex implicit rules, secondary expansion of
+
+As @code{make} searches for an implicit rule, it substitutes the stem
+and then performs secondary expansion for every rule with a matching
+target pattern.  The value of the automatic variables is derived in
+the same fashion as for static pattern rules.  As an example:
+
+@example
+.SECONDEXPANSION:
+
+foo: bar
+
+foo foz: fo%: bo%
+
+%oo: $$< $$^ $$+ $$*
+@end example
+
+When the implicit rule is tried for target @file{foo}, @code{$$<}
+expands to @file{bar}, @code{$$^} expands to @file{bar boo},
+@code{$$+} also expands to @file{bar boo}, and @code{$$*} expands to
+@file{f}.
+
+Note that the directory prefix (D), as described in @ref{Implicit Rule
+Search, ,Implicit Rule Search Algorithm}, is appended (after
+expansion) to all the patterns in the prerequisites list.  As an
+example:
+
+@example
+.SECONDEXPANSION:
+
+/tmp/foo.o:
+
+%.o: $$(addsuffix /%.c,foo bar) foo.h
+@end example
+
+The prerequisite list after the secondary expansion and directory
+prefix reconstruction will be @file{/tmp/foo/foo.c /tmp/var/bar/foo.c
+foo.h}.  If you are not interested in this reconstruction, you can use
+@code{$$*} instead of @code{%} in the prerequisites list.
+
+@node Rules, Commands, Makefiles, Top
+@chapter Writing Rules
+@cindex writing rules
+@cindex rule, how to write
+@cindex target
+@cindex prerequisite
+
+A @dfn{rule} appears in the makefile and says when and how to remake
+certain files, called the rule's @dfn{targets} (most often only one per rule).
+It lists the other files that are the @dfn{prerequisites} of the target, and
+@dfn{commands} to use to create or update the target.
+
+@cindex default goal
+@cindex goal, default
+The order of rules is not significant, except for determining the
+@dfn{default goal}: the target for @code{make} to consider, if you do
+not otherwise specify one.  The default goal is the target of the first
+rule in the first makefile.  If the first rule has multiple targets,
+only the first target is taken as the default.  There are two
+exceptions: a target starting with a period is not a default unless it
+contains one or more slashes, @samp{/}, as well; and, a target that
+defines a pattern rule has no effect on the default goal.
+(@xref{Pattern Rules, ,Defining and Redefining Pattern Rules}.)
+
+Therefore, we usually write the makefile so that the first rule is the
+one for compiling the entire program or all the programs described by
+the makefile (often with a target called @samp{all}).
+@xref{Goals, ,Arguments to Specify the Goals}.
+
+@menu
+* Rule Example::                An example explained.
+* Rule Syntax::                 General syntax explained.
+* Prerequisite Types::          There are two types of prerequisites.
+* Wildcards::                   Using wildcard characters such as `*'.
+* Directory Search::            Searching other directories for source files.
+* Phony Targets::               Using a target that is not a real file's name.
+* Force Targets::               You can use a target without commands
+                                  or prerequisites to mark other targets
+                                  as phony.
+* Empty Targets::               When only the date matters and the
+                                  files are empty.
+* Special Targets::             Targets with special built-in meanings.
+* Multiple Targets::            When to make use of several targets in a rule.
+* Multiple Rules::              How to use several rules with the same target.
+* Static Pattern::              Static pattern rules apply to multiple targets
+                                  and can vary the prerequisites according to
+                                  the target name.
+* Double-Colon::                How to use a special kind of rule to allow
+                                  several independent rules for one target.
+* Automatic Prerequisites::     How to automatically generate rules giving
+                                  prerequisites from source files themselves.
+@end menu
+
+@ifnottex
+@node Rule Example, Rule Syntax, Rules, Rules
+@section Rule Example
+
+Here is an example of a rule:
+
+@example
+foo.o : foo.c defs.h       # module for twiddling the frobs
+        cc -c -g foo.c
+@end example
+
+Its target is @file{foo.o} and its prerequisites are @file{foo.c} and
+@file{defs.h}.  It has one command, which is @samp{cc -c -g foo.c}.
+The command line starts with a tab to identify it as a command.
+
+This rule says two things:
+
+@itemize @bullet
+@item
+How to decide whether @file{foo.o} is out of date: it is out of date
+if it does not exist, or if either @file{foo.c} or @file{defs.h} is
+more recent than it.
+
+@item
+How to update the file @file{foo.o}: by running @code{cc} as stated.
+The command does not explicitly mention @file{defs.h}, but we presume
+that @file{foo.c} includes it, and that that is why @file{defs.h} was
+added to the prerequisites.
+@end itemize
+@end ifnottex
+
+@node Rule Syntax, Prerequisite Types, Rule Example, Rules
+@section Rule Syntax
+
+@cindex rule syntax
+@cindex syntax of rules
+In general, a rule looks like this:
+
+@example
+@var{targets} : @var{prerequisites}
+        @var{command}
+        @dots{}
+@end example
+
+@noindent
+or like this:
+
+@example
+@var{targets} : @var{prerequisites} ; @var{command}
+        @var{command}
+        @dots{}
+@end example
+
+@cindex targets
+@cindex rule targets
+The @var{targets} are file names, separated by spaces.  Wildcard
+characters may be used (@pxref{Wildcards, ,Using Wildcard Characters
+in File Names}) and a name of the form @file{@var{a}(@var{m})}
+represents member @var{m} in archive file @var{a}
+(@pxref{Archive Members, ,Archive Members as Targets}).
+Usually there is only one
+target per rule, but occasionally there is a reason to have more
+(@pxref{Multiple Targets, , Multiple Targets in a Rule}).@refill
+
+@cindex commands
+@cindex tab character (in commands)
+The @var{command} lines start with a tab character.  The first command may
+appear on the line after the prerequisites, with a tab character, or may
+appear on the same line, with a semicolon.  Either way, the effect is the
+same.  There are other differences in the syntax of command lines.
+@xref{Commands, ,Writing the Commands in Rules}.
+
+@cindex dollar sign (@code{$}), in rules
+@cindex @code{$}, in rules
+@cindex rules, and @code{$}
+Because dollar signs are used to start @code{make} variable
+references, if you really want a dollar sign in a target or
+prerequisite you must write two of them, @samp{$$} (@pxref{Using
+Variables, ,How to Use Variables}).  If you have enabled secondary
+expansion (@pxref{Secondary Expansion}) and you want a literal dollar
+sign in the prerequisites list, you must actually write @emph{four}
+dollar signs (@samp{$$$$}).
+
+You may split a long line by inserting a backslash followed by a
+newline, but this is not required, as @code{make} places no limit on
+the length of a line in a makefile.
+
+A rule tells @code{make} two things: when the targets are out of date,
+and how to update them when necessary.
+
+@cindex prerequisites
+@cindex rule prerequisites
+The criterion for being out of date is specified in terms of the
+@var{prerequisites}, which consist of file names separated by spaces.
+(Wildcards and archive members (@pxref{Archives}) are allowed here too.)
+A target is out of date if it does not exist or if it is older than any
+of the prerequisites (by comparison of last-modification times).  The
+idea is that the contents of the target file are computed based on
+information in the prerequisites, so if any of the prerequisites changes,
+the contents of the existing target file are no longer necessarily
+valid.
+
+How to update is specified by @var{commands}.  These are lines to be
+executed by the shell (normally @samp{sh}), but with some extra features
+(@pxref{Commands, ,Writing the Commands in Rules}).
+
+@node Prerequisite Types, Wildcards, Rule Syntax, Rules
+@comment  node-name,  next,  previous,  up
+@section Types of Prerequisites
+@cindex prerequisite types
+@cindex types of prerequisites
+
+@cindex prerequisites, normal
+@cindex normal prerequisites
+@cindex prerequisites, order-only
+@cindex order-only prerequisites
+There are actually two different types of prerequisites understood by
+GNU @code{make}: normal prerequisites such as described in the
+previous section, and @dfn{order-only} prerequisites.  A normal
+prerequisite makes two statements: first, it imposes an order of
+execution of build commands: any commands necessary to build any of a
+target's prerequisites will be fully executed before any commands
+necessary to build the target.  Second, it imposes a dependency
+relationship: if any prerequisite is newer than the target, then the
+target is considered out-of-date and must be rebuilt.
+
+Normally, this is exactly what you want: if a target's prerequisite is
+updated, then the target should also be updated.
+
+Occasionally, however, you have a situation where you want to impose a
+specific ordering on the rules to be invoked @emph{without} forcing
+the target to be updated if one of those rules is executed.  In that
+case, you want to define @dfn{order-only} prerequisites.  Order-only
+prerequisites can be specified by placing a pipe symbol (@code{|})
+in the prerequisites list: any prerequisites to the left of the pipe
+symbol are normal; any prerequisites to the right are order-only:
+
+@example
+@var{targets} : @var{normal-prerequisites} | @var{order-only-prerequisites}
+@end example
+
+The normal prerequisites section may of course be empty.  Also, you
+may still declare multiple lines of prerequisites for the same target:
+they are appended appropriately (normal prerequisites are appended to
+the list of normal prerequisites; order-only prerequisites are
+appended to the list of order-only prerequisites).  Note that if you
+declare the same file to be both a normal and an order-only
+prerequisite, the normal prerequisite takes precedence (since they
+have a strict superset of the behavior of an order-only prerequisite).
+
+Consider an example where your targets are to be placed in a separate
+directory, and that directory might not exist before @code{make} is
+run.  In this situation, you want the directory to be created before
+any targets are placed into it but, because the timestamps on
+directories change whenever a file is added, removed, or renamed, we
+certainly don't want to rebuild all the targets whenever the
+directory's timestamp changes.  One way to manage this is with
+order-only prerequisites: make the directory an order-only
+prerequisite on all the targets:
+
+@example
+OBJDIR := objdir
+OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
+
+$(OBJDIR)/%.o : %.c
+        $(COMPILE.c) $(OUTPUT_OPTION) $<
+
+all: $(OBJS)
+
+$(OBJS): | $(OBJDIR)
+
+$(OBJDIR):
+        mkdir $(OBJDIR)
+@end example
+
+Now the rule to create the @file{objdir} directory will be run, if
+needed, before any @samp{.o} is built, but no @samp{.o} will be built
+because the @file{objdir} directory timestamp changed.
+
+@node Wildcards, Directory Search, Prerequisite Types, Rules
+@section Using Wildcard Characters in File Names
+@cindex wildcard
+@cindex file name with wildcards
+@cindex globbing (wildcards)
+
+@cindex @code{*} (wildcard character)
+@cindex @code{?} (wildcard character)
+@cindex @code{[@dots{}]} (wildcard characters)
+A single file name can specify many files using @dfn{wildcard characters}.
+The wildcard characters in @code{make} are @samp{*}, @samp{?} and
+@samp{[@dots{}]}, the same as in the Bourne shell.  For example, @file{*.c}
+specifies a list of all the files (in the working directory) whose names
+end in @samp{.c}.@refill
+
+@cindex @code{~} (tilde)
+@cindex tilde (@code{~})
+@cindex home directory
+The character @samp{~} at the beginning of a file name also has special
+significance.  If alone, or followed by a slash, it represents your home
+directory.  For example @file{~/bin} expands to @file{/home/you/bin}.
+If the @samp{~} is followed by a word, the string represents the home
+directory of the user named by that word.  For example @file{~john/bin}
+expands to @file{/home/john/bin}.  On systems which don't have a home
+directory for each user (such as MS-DOS or MS-Windows), this
+functionality can be simulated by setting the environment variable
+@var{HOME}.@refill
+
+Wildcard expansion is performed by @code{make} automatically in
+targets and in prerequisites.  In commands the shell is responsible
+for wildcard expansion.  In other contexts, wildcard expansion happens
+only if you request it explicitly with the @code{wildcard} function.
+
+The special significance of a wildcard character can be turned off by
+preceding it with a backslash.  Thus, @file{foo\*bar} would refer to a
+specific file whose name consists of @samp{foo}, an asterisk, and
+@samp{bar}.@refill
+
+@menu
+* Wildcard Examples::           Several examples
+* Wildcard Pitfall::            Problems to avoid.
+* Wildcard Function::           How to cause wildcard expansion where
+                                  it does not normally take place.
+@end menu
+
+@node Wildcard Examples, Wildcard Pitfall, Wildcards, Wildcards
+@subsection Wildcard Examples
+
+Wildcards can be used in the commands of a rule, where they are expanded
+by the shell.  For example, here is a rule to delete all the object files:
+
+@example
+@group
+clean:
+        rm -f *.o
+@end group
+@end example
+@cindex @code{rm} (shell command)
+
+Wildcards are also useful in the prerequisites of a rule.  With the
+following rule in the makefile, @samp{make print} will print all the
+@samp{.c} files that have changed since the last time you printed them:
+
+@example
+print: *.c
+        lpr -p $?
+        touch print
+@end example
+
+@cindex @code{print} target
+@cindex @code{lpr} (shell command)
+@cindex @code{touch} (shell command)
+@noindent
+This rule uses @file{print} as an empty target file; see @ref{Empty
+Targets, ,Empty Target Files to Record Events}.  (The automatic variable
+@samp{$?} is used to print only those files that have changed; see
+@ref{Automatic Variables}.)@refill
+
+Wildcard expansion does not happen when you define a variable.  Thus, if
+you write this:
+
+@example
+objects = *.o
+@end example
+
+@noindent
+then the value of the variable @code{objects} is the actual string
+@samp{*.o}.  However, if you use the value of @code{objects} in a target,
+prerequisite or command, wildcard expansion will take place at that time.
+To set @code{objects} to the expansion, instead use:
+
+@example
+objects := $(wildcard *.o)
+@end example
+
+@noindent
+@xref{Wildcard Function}.
+
+@node Wildcard Pitfall, Wildcard Function, Wildcard Examples, Wildcards
+@subsection Pitfalls of Using Wildcards
+@cindex wildcard pitfalls
+@cindex pitfalls of wildcards
+@cindex mistakes with wildcards
+@cindex errors with wildcards
+@cindex problems with wildcards
+
+Now here is an example of a naive way of using wildcard expansion, that
+does not do what you would intend.  Suppose you would like to say that the
+executable file @file{foo} is made from all the object files in the
+directory, and you write this:
+
+@example
+objects = *.o
+
+foo : $(objects)
+        cc -o foo $(CFLAGS) $(objects)
+@end example
+
+@noindent
+The value of @code{objects} is the actual string @samp{*.o}.  Wildcard
+expansion happens in the rule for @file{foo}, so that each @emph{existing}
+@samp{.o} file becomes a prerequisite of @file{foo} and will be recompiled if
+necessary.
+
+But what if you delete all the @samp{.o} files?  When a wildcard matches
+no files, it is left as it is, so then @file{foo} will depend on the
+oddly-named file @file{*.o}.  Since no such file is likely to exist,
+@code{make} will give you an error saying it cannot figure out how to
+make @file{*.o}.  This is not what you want!
+
+Actually it is possible to obtain the desired result with wildcard
+expansion, but you need more sophisticated techniques, including the
+@code{wildcard} function and string substitution.
+@ifnottex
+@xref{Wildcard Function, ,The Function @code{wildcard}}.
+@end ifnottex
+@iftex
+These are described in the following section.
+@end iftex
+
+@cindex wildcards and MS-DOS/MS-Windows backslashes
+@cindex backslashes in pathnames and wildcard expansion
+
+Microsoft operating systems (MS-DOS and MS-Windows) use backslashes to
+separate directories in pathnames, like so:
+
+@example
+  c:\foo\bar\baz.c
+@end example
+
+This is equivalent to the Unix-style @file{c:/foo/bar/baz.c} (the
+@file{c:} part is the so-called drive letter).  When @code{make} runs on
+these systems, it supports backslashes as well as the Unix-style forward
+slashes in pathnames.  However, this support does @emph{not} include the
+wildcard expansion, where backslash is a quote character.  Therefore,
+you @emph{must} use Unix-style slashes in these cases.
+
+
+@node Wildcard Function,  , Wildcard Pitfall, Wildcards
+@subsection The Function @code{wildcard}
+@findex wildcard
+
+Wildcard expansion happens automatically in rules.  But wildcard expansion
+does not normally take place when a variable is set, or inside the
+arguments of a function.  If you want to do wildcard expansion in such
+places, you need to use the @code{wildcard} function, like this:
+
+@example
+$(wildcard @var{pattern}@dots{})
+@end example
+
+@noindent
+This string, used anywhere in a makefile, is replaced by a
+space-separated list of names of existing files that match one of the
+given file name patterns.  If no existing file name matches a pattern,
+then that pattern is omitted from the output of the @code{wildcard}
+function.  Note that this is different from how unmatched wildcards
+behave in rules, where they are used verbatim rather than ignored
+(@pxref{Wildcard Pitfall}).
+
+One use of the @code{wildcard} function is to get a list of all the C source
+files in a directory, like this:
+
+@example
+$(wildcard *.c)
+@end example
+
+We can change the list of C source files into a list of object files by
+replacing the @samp{.c} suffix with @samp{.o} in the result, like this:
+
+@example
+$(patsubst %.c,%.o,$(wildcard *.c))
+@end example
+
+@noindent
+(Here we have used another function, @code{patsubst}.
+@xref{Text Functions, ,Functions for String Substitution and Analysis}.)@refill
+
+Thus, a makefile to compile all C source files in the directory and then
+link them together could be written as follows:
+
+@example
+objects := $(patsubst %.c,%.o,$(wildcard *.c))
+
+foo : $(objects)
+        cc -o foo $(objects)
+@end example
+
+@noindent
+(This takes advantage of the implicit rule for compiling C programs, so
+there is no need to write explicit rules for compiling the files.
+@xref{Flavors, ,The Two Flavors of Variables}, for an explanation of
+@samp{:=}, which is a variant of @samp{=}.)
+
+@node Directory Search, Phony Targets, Wildcards, Rules
+@section Searching Directories for Prerequisites
+@vindex VPATH
+@findex vpath
+@cindex vpath
+@cindex search path for prerequisites (@code{VPATH})
+@cindex directory search (@code{VPATH})
+
+For large systems, it is often desirable to put sources in a separate
+directory from the binaries.  The @dfn{directory search} features of
+@code{make} facilitate this by searching several directories
+automatically to find a prerequisite.  When you redistribute the files
+among directories, you do not need to change the individual rules,
+just the search paths.
+
+@menu
+* General Search::              Specifying a search path that applies
+                                  to every prerequisite.
+* Selective Search::            Specifying a search path
+                                  for a specified class of names.
+* Search Algorithm::            When and how search paths are applied.
+* Commands/Search::             How to write shell commands that work together
+                                  with search paths.
+* Implicit/Search::             How search paths affect implicit rules.
+* Libraries/Search::            Directory search for link libraries.
+@end menu
+
+@node General Search, Selective Search, Directory Search, Directory Search
+@subsection @code{VPATH}: Search Path for All Prerequisites
+@vindex VPATH
+
+The value of the @code{make} variable @code{VPATH} specifies a list of
+directories that @code{make} should search.  Most often, the
+directories are expected to contain prerequisite files that are not in the
+current directory; however, @code{make} uses @code{VPATH} as a search
+list for both prerequisites and targets of rules.
+
+Thus, if a file that is listed as a target or prerequisite does not exist
+in the current directory, @code{make} searches the directories listed in
+@code{VPATH} for a file with that name.  If a file is found in one of
+them, that file may become the prerequisite (see below).  Rules may then
+specify the names of files in the prerequisite list as if they all
+existed in the current directory.  @xref{Commands/Search, ,Writing Shell
+Commands with Directory Search}.
+
+In the @code{VPATH} variable, directory names are separated by colons or
+blanks.  The order in which directories are listed is the order followed
+by @code{make} in its search.  (On MS-DOS and MS-Windows, semi-colons
+are used as separators of directory names in @code{VPATH}, since the
+colon can be used in the pathname itself, after the drive letter.)
+
+For example,
+
+@example
+VPATH = src:../headers
+@end example
+
+@noindent
+specifies a path containing two directories, @file{src} and
+@file{../headers}, which @code{make} searches in that order.
+
+With this value of @code{VPATH}, the following rule,
+
+@example
+foo.o : foo.c
+@end example
+
+@noindent
+is interpreted as if it were written like this:
+
+@example
+foo.o : src/foo.c
+@end example
+
+@noindent
+assuming the file @file{foo.c} does not exist in the current directory but
+is found in the directory @file{src}.
+
+@node Selective Search, Search Algorithm, General Search, Directory Search
+@subsection The @code{vpath} Directive
+@findex vpath
+
+Similar to the @code{VPATH} variable, but more selective, is the
+@code{vpath} directive (note lower case), which allows you to specify a
+search path for a particular class of file names: those that match a
+particular pattern.  Thus you can supply certain search directories for
+one class of file names and other directories (or none) for other file
+names.
+
+There are three forms of the @code{vpath} directive:
+
+@table @code
+@item vpath @var{pattern} @var{directories}
+Specify the search path @var{directories} for file names that match
+@var{pattern}.
+
+The search path, @var{directories}, is a list of directories to be
+searched, separated by colons (semi-colons on MS-DOS and MS-Windows) or
+blanks, just like the search path used in the @code{VPATH} variable.
+
+@item vpath @var{pattern}
+Clear out the search path associated with @var{pattern}.
+
+@c Extra blank line makes sure this gets two lines.
+@item vpath
+
+Clear all search paths previously specified with @code{vpath} directives.
+@end table
+
+A @code{vpath} pattern is a string containing a @samp{%} character.  The
+string must match the file name of a prerequisite that is being searched
+for, the @samp{%} character matching any sequence of zero or more
+characters (as in pattern rules; @pxref{Pattern Rules, ,Defining and
+Redefining Pattern Rules}).  For example, @code{%.h} matches files that
+end in @code{.h}.  (If there is no @samp{%}, the pattern must match the
+prerequisite exactly, which is not useful very often.)
+
+@cindex @code{%}, quoting in @code{vpath}
+@cindex @code{%}, quoting with @code{\} (backslash)
+@cindex @code{\} (backslash), to quote @code{%}
+@cindex backslash (@code{\}), to quote @code{%}
+@cindex quoting @code{%}, in @code{vpath}
+@samp{%} characters in a @code{vpath} directive's pattern can be quoted
+with preceding backslashes (@samp{\}).  Backslashes that would otherwise
+quote @samp{%} characters can be quoted with more backslashes.
+Backslashes that quote @samp{%} characters or other backslashes are
+removed from the pattern before it is compared to file names.  Backslashes
+that are not in danger of quoting @samp{%} characters go unmolested.@refill
+
+When a prerequisite fails to exist in the current directory, if the
+@var{pattern} in a @code{vpath} directive matches the name of the
+prerequisite file, then the @var{directories} in that directive are searched
+just like (and before) the directories in the @code{VPATH} variable.
+
+For example,
+
+@example
+vpath %.h ../headers
+@end example
+
+@noindent
+tells @code{make} to look for any prerequisite whose name ends in @file{.h}
+in the directory @file{../headers} if the file is not found in the current
+directory.
+
+If several @code{vpath} patterns match the prerequisite file's name, then
+@code{make} processes each matching @code{vpath} directive one by one,
+searching all the directories mentioned in each directive.  @code{make}
+handles multiple @code{vpath} directives in the order in which they
+appear in the makefile; multiple directives with the same pattern are
+independent of each other.
+
+@need 750
+Thus,
+
+@example
+@group
+vpath %.c foo
+vpath %   blish
+vpath %.c bar
+@end group
+@end example
+
+@noindent
+will look for a file ending in @samp{.c} in @file{foo}, then
+@file{blish}, then @file{bar}, while
+
+@example
+@group
+vpath %.c foo:bar
+vpath %   blish
+@end group
+@end example
+
+@noindent
+will look for a file ending in @samp{.c} in @file{foo}, then
+@file{bar}, then @file{blish}.
+
+@node Search Algorithm, Commands/Search, Selective Search, Directory Search
+@subsection How Directory Searches are Performed
+@cindex algorithm for directory search
+@cindex directory search algorithm
+
+When a prerequisite is found through directory search, regardless of type
+(general or selective), the pathname located may not be the one that
+@code{make} actually provides you in the prerequisite list.  Sometimes
+the path discovered through directory search is thrown away.
+
+The algorithm @code{make} uses to decide whether to keep or abandon a
+path found via directory search is as follows:
+
+@enumerate
+@item
+If a target file does not exist at the path specified in the makefile,
+directory search is performed.
+
+@item
+If the directory search is successful, that path is kept and this file
+is tentatively stored as the target.
+
+@item
+All prerequisites of this target are examined using this same method.
+
+@item
+After processing the prerequisites, the target may or may not need to be
+rebuilt:
+
+@enumerate a
+@item
+If the target does @emph{not} need to be rebuilt, the path to the file
+found during directory search is used for any prerequisite lists which
+contain this target.  In short, if @code{make} doesn't need to rebuild
+the target then you use the path found via directory search.
+
+@item
+If the target @emph{does} need to be rebuilt (is out-of-date), the
+pathname found during directory search is @emph{thrown away}, and the
+target is rebuilt using the file name specified in the makefile.  In
+short, if @code{make} must rebuild, then the target is rebuilt locally,
+not in the directory found via directory search.
+@end enumerate
+@end enumerate
+
+This algorithm may seem complex, but in practice it is quite often
+exactly what you want.
+
+@cindex traditional directory search (GPATH)
+@cindex directory search, traditional (GPATH)
+Other versions of @code{make} use a simpler algorithm: if the file does
+not exist, and it is found via directory search, then that pathname is
+always used whether or not the target needs to be built.  Thus, if the
+target is rebuilt it is created at the pathname discovered during
+directory search.
+
+@vindex GPATH
+If, in fact, this is the behavior you want for some or all of your
+directories, you can use the @code{GPATH} variable to indicate this to
+@code{make}.
+
+@code{GPATH} has the same syntax and format as @code{VPATH} (that is, a
+space- or colon-delimited list of pathnames).  If an out-of-date target
+is found by directory search in a directory that also appears in
+@code{GPATH}, then that pathname is not thrown away.  The target is
+rebuilt using the expanded path.
+
+@node Commands/Search, Implicit/Search, Search Algorithm, Directory Search
+@subsection Writing Shell Commands with Directory Search
+@cindex shell command, and directory search
+@cindex directory search (@code{VPATH}), and shell commands
+
+When a prerequisite is found in another directory through directory search,
+this cannot change the commands of the rule; they will execute as written.
+Therefore, you must write the commands with care so that they will look for
+the prerequisite in the directory where @code{make} finds it.
+
+This is done with the @dfn{automatic variables} such as @samp{$^}
+(@pxref{Automatic Variables}).
+For instance, the value of @samp{$^} is a
+list of all the prerequisites of the rule, including the names of
+the directories in which they were found, and the value of
+@samp{$@@} is the target.  Thus:@refill
+
+@example
+foo.o : foo.c
+        cc -c $(CFLAGS) $^ -o $@@
+@end example
+
+@noindent
+(The variable @code{CFLAGS} exists so you can specify flags for C
+compilation by implicit rules; we use it here for consistency so it will
+affect all C compilations uniformly;
+@pxref{Implicit Variables, ,Variables Used by Implicit Rules}.)
+
+Often the prerequisites include header files as well, which you do not
+want to mention in the commands.  The automatic variable @samp{$<} is
+just the first prerequisite:
+
+@example
+VPATH = src:../headers
+foo.o : foo.c defs.h hack.h
+        cc -c $(CFLAGS) $< -o $@@
+@end example
+
+@node Implicit/Search, Libraries/Search, Commands/Search, Directory Search
+@subsection Directory Search and Implicit Rules
+@cindex @code{VPATH}, and implicit rules
+@cindex directory search (@code{VPATH}), and implicit rules
+@cindex search path for prerequisites (@code{VPATH}), and implicit rules
+@cindex implicit rule, and directory search
+@cindex implicit rule, and @code{VPATH}
+@cindex rule, implicit, and directory search
+@cindex rule, implicit, and @code{VPATH}
+
+The search through the directories specified in @code{VPATH} or with
+@code{vpath} also happens during consideration of implicit rules
+(@pxref{Implicit Rules, ,Using Implicit Rules}).
+
+For example, when a file @file{foo.o} has no explicit rule, @code{make}
+considers implicit rules, such as the built-in rule to compile
+@file{foo.c} if that file exists.  If such a file is lacking in the
+current directory, the appropriate directories are searched for it.  If
+@file{foo.c} exists (or is mentioned in the makefile) in any of the
+directories, the implicit rule for C compilation is applied.
+
+The commands of implicit rules normally use automatic variables as a
+matter of necessity; consequently they will use the file names found by
+directory search with no extra effort.
+
+@node Libraries/Search,  , Implicit/Search, Directory Search
+@subsection Directory Search for Link Libraries
+@cindex link libraries, and directory search
+@cindex libraries for linking, directory search
+@cindex directory search (@code{VPATH}), and link libraries
+@cindex @code{VPATH}, and link libraries
+@cindex search path for prerequisites (@code{VPATH}), and link libraries
+@cindex @code{-l} (library search)
+@cindex link libraries, patterns matching
+@cindex @code{.LIBPATTERNS}, and link libraries
+@vindex .LIBPATTERNS
+
+Directory search applies in a special way to libraries used with the
+linker.  This special feature comes into play when you write a prerequisite
+whose name is of the form @samp{-l@var{name}}.  (You can tell something
+strange is going on here because the prerequisite is normally the name of a
+file, and the @emph{file name} of a library generally looks like
+@file{lib@var{name}.a}, not like @samp{-l@var{name}}.)@refill
+
+When a prerequisite's name has the form @samp{-l@var{name}}, @code{make}
+handles it specially by searching for the file @file{lib@var{name}.so} in
+the current directory, in directories specified by matching @code{vpath}
+search paths and the @code{VPATH} search path, and then in the
+directories @file{/lib}, @file{/usr/lib}, and @file{@var{prefix}/lib}
+(normally @file{/usr/local/lib}, but MS-DOS/MS-Windows versions of
+@code{make} behave as if @var{prefix} is defined to be the root of the
+DJGPP installation tree).
+
+If that file is not found, then the file @file{lib@var{name}.a} is
+searched for, in the same directories as above.
+
+For example, if there is a @file{/usr/lib/libcurses.a} library on your
+system (and no @file{/usr/lib/libcurses.so} file), then
+
+@example
+@group
+foo : foo.c -lcurses
+        cc $^ -o $@@
+@end group
+@end example
+
+@noindent
+would cause the command @samp{cc foo.c /usr/lib/libcurses.a -o foo} to
+be executed when @file{foo} is older than @file{foo.c} or than
+@file{/usr/lib/libcurses.a}.@refill
+
+Although the default set of files to be searched for is
+@file{lib@var{name}.so} and @file{lib@var{name}.a}, this is customizable
+via the @code{.LIBPATTERNS} variable.  Each word in the value of this
+variable is a pattern string.  When a prerequisite like
+@samp{-l@var{name}} is seen, @code{make} will replace the percent in
+each pattern in the list with @var{name} and perform the above directory
+searches using that library filename.  If no library is found, the next
+word in the list will be used.
+
+The default value for @code{.LIBPATTERNS} is @samp{lib%.so lib%.a},
+which provides the default behavior described above.
+
+You can turn off link library expansion completely by setting this
+variable to an empty value.
+
+@node Phony Targets, Force Targets, Directory Search, Rules
+@section Phony Targets
+@cindex phony targets
+@cindex targets, phony
+@cindex targets without a file
+
+A phony target is one that is not really the name of a file.  It is just a
+name for some commands to be executed when you make an explicit request.
+There are two reasons to use a phony target: to avoid a conflict with
+a file of the same name, and to improve performance.
+
+If you write a rule whose commands will not create the target file, the
+commands will be executed every time the target comes up for remaking.
+Here is an example:
+
+@example
+@group
+clean:
+        rm *.o temp
+@end group
+@end example
+
+@noindent
+Because the @code{rm} command does not create a file named @file{clean},
+probably no such file will ever exist.  Therefore, the @code{rm} command
+will be executed every time you say @samp{make clean}.
+@cindex @code{rm} (shell command)
+
+@findex .PHONY
+The phony target will cease to work if anything ever does create a file
+named @file{clean} in this directory.  Since it has no prerequisites, the
+file @file{clean} would inevitably be considered up to date, and its
+commands would not be executed.  To avoid this problem, you can explicitly
+declare the target to be phony, using the special target @code{.PHONY}
+(@pxref{Special Targets, ,Special Built-in Target Names}) as follows:
+
+@example
+.PHONY : clean
+@end example
+
+@noindent
+Once this is done, @samp{make clean} will run the commands regardless of
+whether there is a file named @file{clean}.
+
+Since it knows that phony targets do not name actual files that could be
+remade from other files, @code{make} skips the implicit rule search for
+phony targets (@pxref{Implicit Rules}).  This is why declaring a target
+phony is good for performance, even if you are not worried about the
+actual file existing.
+
+Thus, you first write the line that states that @code{clean} is a
+phony target, then you write the rule, like this:
+
+@example
+@group
+.PHONY: clean
+clean:
+        rm *.o temp
+@end group
+@end example
+
+Another example of the usefulness of phony targets is in conjunction
+with recursive invocations of @code{make} (for more information, see
+@ref{Recursion, ,Recursive Use of @code{make}}).  In this case the
+makefile will often contain a variable which lists a number of
+subdirectories to be built.  One way to handle this is with one rule
+whose command is a shell loop over the subdirectories, like this:
+
+@example
+@group
+SUBDIRS = foo bar baz
+
+subdirs:
+        for dir in $(SUBDIRS); do \
+          $(MAKE) -C $$dir; \
+        done
+@end group
+@end example
+
+There are a few problems with this method, however.  First, any error
+detected in a submake is not noted by this rule, so it will continue to
+build the rest of the directories even when one fails.  This can be
+overcome by adding shell commands to note the error and exit, but then
+it will do so even if @code{make} is invoked with the @code{-k} option,
+which is unfortunate.  Second, and perhaps more importantly, you cannot
+take advantage of @code{make}'s ability to build targets in parallel
+(@pxref{Parallel, ,Parallel Execution}), since there is only one rule.
+
+By declaring the subdirectories as phony targets (you must do this as
+the subdirectory obviously always exists; otherwise it won't be built)
+you can remove these problems:
+
+@example
+@group
+SUBDIRS = foo bar baz
+
+.PHONY: subdirs $(SUBDIRS)
+
+subdirs: $(SUBDIRS)
+
+$(SUBDIRS):
+        $(MAKE) -C $@@
+
+foo: baz
+@end group
+@end example
+
+Here we've also declared that the @file{foo} subdirectory cannot be
+built until after the @file{baz} subdirectory is complete; this kind of
+relationship declaration is particularly important when attempting
+parallel builds.
+
+A phony target should not be a prerequisite of a real target file; if it
+is, its commands are run every time @code{make} goes to update that
+file.  As long as a phony target is never a prerequisite of a real
+target, the phony target commands will be executed only when the phony
+target is a specified goal (@pxref{Goals, ,Arguments to Specify the
+Goals}).
+
+Phony targets can have prerequisites.  When one directory contains multiple
+programs, it is most convenient to describe all of the programs in one
+makefile @file{./Makefile}.  Since the target remade by default will be the
+first one in the makefile, it is common to make this a phony target named
+@samp{all} and give it, as prerequisites, all the individual programs.  For
+example:
+
+@example
+all : prog1 prog2 prog3
+.PHONY : all
+
+prog1 : prog1.o utils.o
+        cc -o prog1 prog1.o utils.o
+
+prog2 : prog2.o
+        cc -o prog2 prog2.o
+
+prog3 : prog3.o sort.o utils.o
+        cc -o prog3 prog3.o sort.o utils.o
+@end example
+
+@noindent
+Now you can say just @samp{make} to remake all three programs, or
+specify as arguments the ones to remake (as in @samp{make prog1
+prog3}).  Phoniness is not inherited: the prerequisites of a phony
+target are not themselves phony, unless explicitly declared to be so.
+
+When one phony target is a prerequisite of another, it serves as a subroutine
+of the other.  For example, here @samp{make cleanall} will delete the
+object files, the difference files, and the file @file{program}:
+
+@example
+.PHONY: cleanall cleanobj cleandiff
+
+cleanall : cleanobj cleandiff
+        rm program
+
+cleanobj :
+        rm *.o
+
+cleandiff :
+        rm *.diff
+@end example
+
+@node Force Targets, Empty Targets, Phony Targets, Rules
+@section Rules without Commands or Prerequisites
+@cindex force targets
+@cindex targets, force
+@cindex @code{FORCE}
+@cindex rule, no commands or prerequisites
+
+If a rule has no prerequisites or commands, and the target of the rule
+is a nonexistent file, then @code{make} imagines this target to have
+been updated whenever its rule is run.  This implies that all targets
+depending on this one will always have their commands run.
+
+An example will illustrate this:
+
+@example
+@group
+clean: FORCE
+        rm $(objects)
+FORCE:
+@end group
+@end example
+
+Here the target @samp{FORCE} satisfies the special conditions, so the
+target @file{clean} that depends on it is forced to run its commands.
+There is nothing special about the name @samp{FORCE}, but that is one name
+commonly used this way.
+
+As you can see, using @samp{FORCE} this way has the same results as using
+@samp{.PHONY: clean}.
+
+Using @samp{.PHONY} is more explicit and more efficient.  However,
+other versions of @code{make} do not support @samp{.PHONY}; thus
+@samp{FORCE} appears in many makefiles.  @xref{Phony Targets}.
+
+@node Empty Targets, Special Targets, Force Targets, Rules
+@section Empty Target Files to Record Events
+@cindex empty targets
+@cindex targets, empty
+@cindex recording events with empty targets
+
+The @dfn{empty target} is a variant of the phony target; it is used to hold
+commands for an action that you request explicitly from time to time.
+Unlike a phony target, this target file can really exist; but the file's
+contents do not matter, and usually are empty.
+
+The purpose of the empty target file is to record, with its
+last-modification time, when the rule's commands were last executed.  It
+does so because one of the commands is a @code{touch} command to update the
+target file.
+
+The empty target file should have some prerequisites (otherwise it
+doesn't make sense).  When you ask to remake the empty target, the
+commands are executed if any prerequisite is more recent than the target;
+in other words, if a prerequisite has changed since the last time you
+remade the target.  Here is an example:
+
+@example
+print: foo.c bar.c
+        lpr -p $?
+        touch print
+@end example
+@cindex @code{print} target
+@cindex @code{lpr} (shell command)
+@cindex @code{touch} (shell command)
+
+@noindent
+With this rule, @samp{make print} will execute the @code{lpr} command if
+either source file has changed since the last @samp{make print}.  The
+automatic variable @samp{$?} is used to print only those files that have
+changed (@pxref{Automatic Variables}).
+
+@node Special Targets, Multiple Targets, Empty Targets, Rules
+@section Special Built-in Target Names
+@cindex special targets
+@cindex built-in special targets
+@cindex targets, built-in special
+
+Certain names have special meanings if they appear as targets.
+
+@table @code
+@findex .PHONY
+@item .PHONY
+
+The prerequisites of the special target @code{.PHONY} are considered to
+be phony targets.  When it is time to consider such a target,
+@code{make} will run its commands unconditionally, regardless of
+whether a file with that name exists or what its last-modification
+time is.  @xref{Phony Targets, ,Phony Targets}.
+
+@findex .SUFFIXES
+@item .SUFFIXES
+
+The prerequisites of the special target @code{.SUFFIXES} are the list
+of suffixes to be used in checking for suffix rules.
+@xref{Suffix Rules, , Old-Fashioned Suffix Rules}.
+
+@findex .DEFAULT
+@item .DEFAULT
+
+The commands specified for @code{.DEFAULT} are used for any target for
+which no rules are found (either explicit rules or implicit rules).
+@xref{Last Resort}.  If @code{.DEFAULT} commands are specified, every
+file mentioned as a prerequisite, but not as a target in a rule, will have
+these commands executed on its behalf.  @xref{Implicit Rule Search,
+,Implicit Rule Search Algorithm}.
+
+@findex .PRECIOUS
+@item .PRECIOUS
+@cindex precious targets
+@cindex preserving with @code{.PRECIOUS}
+
+The targets which @code{.PRECIOUS} depends on are given the following
+special treatment: if @code{make} is killed or interrupted during the
+execution of their commands, the target is not deleted.
+@xref{Interrupts, ,Interrupting or Killing @code{make}}.  Also, if the
+target is an intermediate file, it will not be deleted after it is no
+longer needed, as is normally done.  @xref{Chained Rules, ,Chains of
+Implicit Rules}.  In this latter respect it overlaps with the
+@code{.SECONDARY} special target.
+
+You can also list the target pattern of an implicit rule (such as
+@samp{%.o}) as a prerequisite file of the special target @code{.PRECIOUS}
+to preserve intermediate files created by rules whose target patterns
+match that file's name.
+
+@findex .INTERMEDIATE
+@item .INTERMEDIATE
+@cindex intermediate targets, explicit
+
+The targets which @code{.INTERMEDIATE} depends on are treated as
+intermediate files.  @xref{Chained Rules, ,Chains of Implicit Rules}.
+@code{.INTERMEDIATE} with no prerequisites has no effect.
+
+@findex .SECONDARY
+@item .SECONDARY
+@cindex secondary targets
+@cindex preserving with @code{.SECONDARY}
+
+The targets which @code{.SECONDARY} depends on are treated as
+intermediate files, except that they are never automatically deleted.
+@xref{Chained Rules, ,Chains of Implicit Rules}.
+
+@code{.SECONDARY} with no prerequisites causes all targets to be treated
+as secondary (i.e., no target is removed because it is considered
+intermediate).
+
+@findex .SECONDEXPANSION
+@item .SECONDEXPANSION
+
+If @code{.SECONDEXPANSION} is mentioned as a target anywhere in the
+makefile, then all prerequisite lists defined @emph{after} it appears
+will be expanded a second time after all makefiles have been read in.
+@xref{Secondary Expansion, ,Secondary Expansion}.
+
+@findex .DELETE_ON_ERROR
+@item .DELETE_ON_ERROR
+@cindex removing targets on failure
+
+If @code{.DELETE_ON_ERROR} is mentioned as a target anywhere in the
+makefile, then @code{make} will delete the target of a rule if it has
+changed and its commands exit with a nonzero exit status, just as it
+does when it receives a signal.  @xref{Errors, ,Errors in Commands}.
+
+@findex .IGNORE
+@item .IGNORE
+
+If you specify prerequisites for @code{.IGNORE}, then @code{make} will
+ignore errors in execution of the commands run for those particular
+files.  The commands for @code{.IGNORE} are not meaningful.
+
+If mentioned as a target with no prerequisites, @code{.IGNORE} says to
+ignore errors in execution of commands for all files.  This usage of
+@samp{.IGNORE} is supported only for historical compatibility.  Since
+this affects every command in the makefile, it is not very useful; we
+recommend you use the more selective ways to ignore errors in specific
+commands.  @xref{Errors, ,Errors in Commands}.
+
+@findex .LOW_RESOLUTION_TIME
+@item .LOW_RESOLUTION_TIME
+
+If you specify prerequisites for @code{.LOW_RESOLUTION_TIME},
+@command{make} assumes that these files are created by commands that
+generate low resolution time stamps.  The commands for
+@code{.LOW_RESOLUTION_TIME} are not meaningful.
+
+The high resolution file time stamps of many modern hosts lessen the
+chance of @command{make} incorrectly concluding that a file is up to
+date.  Unfortunately, these hosts provide no way to set a high
+resolution file time stamp, so commands like @samp{cp -p} that
+explicitly set a file's time stamp must discard its subsecond part.  If
+a file is created by such a command, you should list it as a
+prerequisite of @code{.LOW_RESOLUTION_TIME} so that @command{make} does
+not mistakenly conclude that the file is out of date.  For example:
+
+@example
+@group
+.LOW_RESOLUTION_TIME: dst
+dst: src
+        cp -p src dst
+@end group
+@end example
+
+Since @samp{cp -p} discards the subsecond part of @file{src}'s time
+stamp, @file{dst} is typically slightly older than @file{src} even when
+it is up to date.  The @code{.LOW_RESOLUTION_TIME} line causes
+@command{make} to consider @file{dst} to be up to date if its time stamp
+is at the start of the same second that @file{src}'s time stamp is in.
+
+Due to a limitation of the archive format, archive member time stamps
+are always low resolution.  You need not list archive members as
+prerequisites of @code{.LOW_RESOLUTION_TIME}, as @command{make} does this
+automatically.
+
+@findex .SILENT
+@item .SILENT
+
+If you specify prerequisites for @code{.SILENT}, then @code{make} will
+not print the commands to remake those particular files before executing
+them.  The commands for @code{.SILENT} are not meaningful.
+
+If mentioned as a target with no prerequisites, @code{.SILENT} says not
+to print any commands before executing them.  This usage of
+@samp{.SILENT} is supported only for historical compatibility.  We
+recommend you use the more selective ways to silence specific commands.
+@xref{Echoing, ,Command Echoing}.  If you want to silence all commands
+for a particular run of @code{make}, use the @samp{-s} or
+@w{@samp{--silent}} option (@pxref{Options Summary}).
+
+@findex .EXPORT_ALL_VARIABLES
+@item .EXPORT_ALL_VARIABLES
+
+Simply by being mentioned as a target, this tells @code{make} to
+export all variables to child processes by default.
+@xref{Variables/Recursion, ,Communicating Variables to a
+Sub-@code{make}}.
+
+@findex .NOTPARALLEL
+@item .NOTPARALLEL
+@cindex parallel execution, overriding
+
+If @code{.NOTPARALLEL} is mentioned as a target, then this invocation
+of @code{make} will be run serially, even if the @samp{-j} option is
+given.  Any recursively invoked @code{make} command will still run
+commands in parallel (unless its makefile also contains this target).
+Any prerequisites on this target are ignored.
+@end table
+
+Any defined implicit rule suffix also counts as a special target if it
+appears as a target, and so does the concatenation of two suffixes, such
+as @samp{.c.o}.  These targets are suffix rules, an obsolete way of
+defining implicit rules (but a way still widely used).  In principle, any
+target name could be special in this way if you break it in two and add
+both pieces to the suffix list.  In practice, suffixes normally begin with
+@samp{.}, so these special target names also begin with @samp{.}.
+@xref{Suffix Rules, ,Old-Fashioned Suffix Rules}.
+
+@node Multiple Targets, Multiple Rules, Special Targets, Rules
+@section Multiple Targets in a Rule
+@cindex multiple targets
+@cindex several targets in a rule
+@cindex targets, multiple
+@cindex rule, with multiple targets
+
+A rule with multiple targets is equivalent to writing many rules, each with
+one target, and all identical aside from that.  The same commands apply to
+all the targets, but their effects may vary because you can substitute the
+actual target name into the command using @samp{$@@}.  The rule contributes
+the same prerequisites to all the targets also.
+
+This is useful in two cases.
+
+@itemize @bullet
+@item
+You want just prerequisites, no commands.  For example:
+
+@example
+kbd.o command.o files.o: command.h
+@end example
+
+@noindent
+gives an additional prerequisite to each of the three object files
+mentioned.
+
+@item
+Similar commands work for all the targets.  The commands do not need
+to be absolutely identical, since the automatic variable @samp{$@@}
+can be used to substitute the particular target to be remade into the
+commands (@pxref{Automatic Variables}).  For example:
+
+@example
+@group
+bigoutput littleoutput : text.g
+        generate text.g -$(subst output,,$@@) > $@@
+@end group
+@end example
+@findex subst
+
+@noindent
+is equivalent to
+
+@example
+bigoutput : text.g
+        generate text.g -big > bigoutput
+littleoutput : text.g
+        generate text.g -little > littleoutput
+@end example
+
+@noindent
+Here we assume the hypothetical program @code{generate} makes two
+types of output, one if given @samp{-big} and one if given
+@samp{-little}.
+@xref{Text Functions, ,Functions for String Substitution and Analysis},
+for an explanation of the @code{subst} function.
+@end itemize
+
+Suppose you would like to vary the prerequisites according to the target,
+much as the variable @samp{$@@} allows you to vary the commands.
+You cannot do this with multiple targets in an ordinary rule, but you can
+do it with a @dfn{static pattern rule}.
+@xref{Static Pattern, ,Static Pattern Rules}.
+
+@node Multiple Rules, Static Pattern, Multiple Targets, Rules
+@section Multiple Rules for One Target
+@cindex multiple rules for one target
+@cindex several rules for one target
+@cindex rule, multiple for one target
+@cindex target, multiple rules for one
+
+One file can be the target of several rules.  All the prerequisites
+mentioned in all the rules are merged into one list of prerequisites for
+the target.  If the target is older than any prerequisite from any rule,
+the commands are executed.
+
+There can only be one set of commands to be executed for a file.  If
+more than one rule gives commands for the same file, @code{make} uses
+the last set given and prints an error message.  (As a special case,
+if the file's name begins with a dot, no error message is printed.
+This odd behavior is only for compatibility with other implementations
+of @code{make}@dots{} you should avoid using it).  Occasionally it is
+useful to have the same target invoke multiple commands which are
+defined in different parts of your makefile; you can use
+@dfn{double-colon rules} (@pxref{Double-Colon}) for this.
+
+An extra rule with just prerequisites can be used to give a few extra
+prerequisites to many files at once.  For example, makefiles often
+have a variable, such as @code{objects}, containing a list of all the
+compiler output files in the system being made.  An easy way to say
+that all of them must be recompiled if @file{config.h} changes is to
+write the following:
+
+@example
+objects = foo.o bar.o
+foo.o : defs.h
+bar.o : defs.h test.h
+$(objects) : config.h
+@end example
+
+This could be inserted or taken out without changing the rules that really
+specify how to make the object files, making it a convenient form to use if
+you wish to add the additional prerequisite intermittently.
+
+Another wrinkle is that the additional prerequisites could be specified with
+a variable that you set with a command argument to @code{make}
+(@pxref{Overriding, ,Overriding Variables}).  For example,
+
+@example
+@group
+extradeps=
+$(objects) : $(extradeps)
+@end group
+@end example
+
+@noindent
+means that the command @samp{make extradeps=foo.h} will consider
+@file{foo.h} as a prerequisite of each object file, but plain @samp{make}
+will not.
+
+If none of the explicit rules for a target has commands, then @code{make}
+searches for an applicable implicit rule to find some commands
+@pxref{Implicit Rules, ,Using Implicit Rules}).
+
+@node Static Pattern, Double-Colon, Multiple Rules, Rules
+@section Static Pattern Rules
+@cindex static pattern rule
+@cindex rule, static pattern
+@cindex pattern rules, static (not implicit)
+@cindex varying prerequisites
+@cindex prerequisites, varying (static pattern)
+
+@dfn{Static pattern rules} are rules which specify multiple targets and
+construct the prerequisite names for each target based on the target name.
+They are more general than ordinary rules with multiple targets because the
+targets do not have to have identical prerequisites.  Their prerequisites must
+be @emph{analogous}, but not necessarily @emph{identical}.
+
+@menu
+* Static Usage::                The syntax of static pattern rules.
+* Static versus Implicit::      When are they better than implicit rules?
+@end menu
+
+@node Static Usage, Static versus Implicit, Static Pattern, Static Pattern
+@subsection Syntax of Static Pattern Rules
+@cindex static pattern rule, syntax of
+@cindex pattern rules, static, syntax of
+
+Here is the syntax of a static pattern rule:
+
+@example
+@var{targets} @dots{}: @var{target-pattern}: @var{prereq-patterns} @dots{}
+        @var{commands}
+        @dots{}
+@end example
+
+@noindent
+The @var{targets} list specifies the targets that the rule applies to.
+The targets can contain wildcard characters, just like the targets of
+ordinary rules (@pxref{Wildcards, ,Using Wildcard Characters in File
+Names}).
+
+@cindex target pattern, static (not implicit)
+@cindex stem
+The @var{target-pattern} and @var{prereq-patterns} say how to compute the
+prerequisites of each target.  Each target is matched against the
+@var{target-pattern} to extract a part of the target name, called the
+@dfn{stem}.  This stem is substituted into each of the @var{prereq-patterns}
+to make the prerequisite names (one from each @var{prereq-pattern}).
+
+Each pattern normally contains the character @samp{%} just once.  When the
+@var{target-pattern} matches a target, the @samp{%} can match any part of
+the target name; this part is called the @dfn{stem}.  The rest of the
+pattern must match exactly.  For example, the target @file{foo.o} matches
+the pattern @samp{%.o}, with @samp{foo} as the stem.  The targets
+@file{foo.c} and @file{foo.out} do not match that pattern.@refill
+
+@cindex prerequisite pattern, static (not implicit)
+The prerequisite names for each target are made by substituting the stem
+for the @samp{%} in each prerequisite pattern.  For example, if one
+prerequisite pattern is @file{%.c}, then substitution of the stem
+@samp{foo} gives the prerequisite name @file{foo.c}.  It is legitimate
+to write a prerequisite pattern that does not contain @samp{%}; then this
+prerequisite is the same for all targets.
+
+@cindex @code{%}, quoting in static pattern
+@cindex @code{%}, quoting with @code{\} (backslash)
+@cindex @code{\} (backslash), to quote @code{%}
+@cindex backslash (@code{\}), to quote @code{%}
+@cindex quoting @code{%}, in static pattern
+@samp{%} characters in pattern rules can be quoted with preceding
+backslashes (@samp{\}).  Backslashes that would otherwise quote @samp{%}
+characters can be quoted with more backslashes.  Backslashes that quote
+@samp{%} characters or other backslashes are removed from the pattern
+before it is compared to file names or has a stem substituted into it.
+Backslashes that are not in danger of quoting @samp{%} characters go
+unmolested.  For example, the pattern @file{the\%weird\\%pattern\\} has
+@samp{the%weird\} preceding the operative @samp{%} character, and
+@samp{pattern\\} following it.  The final two backslashes are left alone
+because they cannot affect any @samp{%} character.@refill
+
+Here is an example, which compiles each of @file{foo.o} and @file{bar.o}
+from the corresponding @file{.c} file:
+
+@example
+@group
+objects = foo.o bar.o
+
+all: $(objects)
+
+$(objects): %.o: %.c
+        $(CC) -c $(CFLAGS) $< -o $@@
+@end group
+@end example
+
+@noindent
+Here @samp{$<} is the automatic variable that holds the name of the
+prerequisite and @samp{$@@} is the automatic variable that holds the name
+of the target; see @ref{Automatic Variables}.
+
+Each target specified must match the target pattern; a warning is issued
+for each target that does not.  If you have a list of files, only some of
+which will match the pattern, you can use the @code{filter} function to
+remove nonmatching file names (@pxref{Text Functions, ,Functions for String Substitution and Analysis}):
+
+@example
+files = foo.elc bar.o lose.o
+
+$(filter %.o,$(files)): %.o: %.c
+        $(CC) -c $(CFLAGS) $< -o $@@
+$(filter %.elc,$(files)): %.elc: %.el
+        emacs -f batch-byte-compile $<
+@end example
+
+@noindent
+In this example the result of @samp{$(filter %.o,$(files))} is
+@file{bar.o lose.o}, and the first static pattern rule causes each of
+these object files to be updated by compiling the corresponding C source
+file.  The result of @w{@samp{$(filter %.elc,$(files))}} is
+@file{foo.elc}, so that file is made from @file{foo.el}.@refill
+
+Another example shows how to use @code{$*} in static pattern rules:
+@vindex $*@r{, and static pattern}
+
+@example
+@group
+bigoutput littleoutput : %output : text.g
+        generate text.g -$* > $@@
+@end group
+@end example
+
+@noindent
+When the @code{generate} command is run, @code{$*} will expand to the
+stem, either @samp{big} or @samp{little}.
+
+@node Static versus Implicit,  , Static Usage, Static Pattern
+@subsection Static Pattern Rules versus Implicit Rules
+@cindex rule, static pattern versus implicit
+@cindex static pattern rule, versus implicit
+
+A static pattern rule has much in common with an implicit rule defined as a
+pattern rule (@pxref{Pattern Rules, ,Defining and Redefining Pattern Rules}).
+Both have a pattern for the target and patterns for constructing the
+names of prerequisites.  The difference is in how @code{make} decides
+@emph{when} the rule applies.
+
+An implicit rule @emph{can} apply to any target that matches its pattern,
+but it @emph{does} apply only when the target has no commands otherwise
+specified, and only when the prerequisites can be found.  If more than one
+implicit rule appears applicable, only one applies; the choice depends on
+the order of rules.
+
+By contrast, a static pattern rule applies to the precise list of targets
+that you specify in the rule.  It cannot apply to any other target and it
+invariably does apply to each of the targets specified.  If two conflicting
+rules apply, and both have commands, that's an error.
+
+The static pattern rule can be better than an implicit rule for these
+reasons:
+
+@itemize @bullet
+@item
+You may wish to override the usual implicit rule for a few
+files whose names cannot be categorized syntactically but
+can be given in an explicit list.
+
+@item
+If you cannot be sure of the precise contents of the directories
+you are using, you may not be sure which other irrelevant files
+might lead @code{make} to use the wrong implicit rule.  The choice
+might depend on the order in which the implicit rule search is done.
+With static pattern rules, there is no uncertainty: each rule applies
+to precisely the targets specified.
+@end itemize
+
+@node Double-Colon, Automatic Prerequisites, Static Pattern, Rules
+@section Double-Colon Rules
+@cindex double-colon rules
+@cindex rule, double-colon (@code{::})
+@cindex multiple rules for one target (@code{::})
+@cindex @code{::} rules (double-colon)
+
+@dfn{Double-colon} rules are rules written with @samp{::} instead of
+@samp{:} after the target names.  They are handled differently from
+ordinary rules when the same target appears in more than one rule.
+
+When a target appears in multiple rules, all the rules must be the same
+type: all ordinary, or all double-colon.  If they are double-colon, each
+of them is independent of the others.  Each double-colon rule's commands
+are executed if the target is older than any prerequisites of that rule.
+If there are no prerequisites for that rule, its commands are always
+executed (even if the target already exists).  This can result in
+executing none, any, or all of the double-colon rules.
+
+Double-colon rules with the same target are in fact completely separate
+from one another.  Each double-colon rule is processed individually, just
+as rules with different targets are processed.
+
+The double-colon rules for a target are executed in the order they appear
+in the makefile.  However, the cases where double-colon rules really make
+sense are those where the order of executing the commands would not matter.
+
+Double-colon rules are somewhat obscure and not often very useful; they
+provide a mechanism for cases in which the method used to update a target
+differs depending on which prerequisite files caused the update, and such
+cases are rare.
+
+Each double-colon rule should specify commands; if it does not, an
+implicit rule will be used if one applies.
+@xref{Implicit Rules, ,Using Implicit Rules}.
+
+@node Automatic Prerequisites,  , Double-Colon, Rules
+@section Generating Prerequisites Automatically
+@cindex prerequisites, automatic generation
+@cindex automatic generation of prerequisites
+@cindex generating prerequisites automatically
+
+In the makefile for a program, many of the rules you need to write often
+say only that some object file depends on some header
+file.  For example, if @file{main.c} uses @file{defs.h} via an
+@code{#include}, you would write:
+
+@example
+main.o: defs.h
+@end example
+
+@noindent
+You need this rule so that @code{make} knows that it must remake
+@file{main.o} whenever @file{defs.h} changes.  You can see that for a
+large program you would have to write dozens of such rules in your
+makefile.  And, you must always be very careful to update the makefile
+every time you add or remove an @code{#include}.
+@cindex @code{#include}
+
+@cindex @code{-M} (to compiler)
+To avoid this hassle, most modern C compilers can write these rules for
+you, by looking at the @code{#include} lines in the source files.
+Usually this is done with the @samp{-M} option to the compiler.
+For example, the command:
+
+@example
+cc -M main.c
+@end example
+
+@noindent
+generates the output:
+
+@example
+main.o : main.c defs.h
+@end example
+
+@noindent
+Thus you no longer have to write all those rules yourself.
+The compiler will do it for you.
+
+Note that such a prerequisite constitutes mentioning @file{main.o} in a
+makefile, so it can never be considered an intermediate file by implicit
+rule search.  This means that @code{make} won't ever remove the file
+after using it; @pxref{Chained Rules, ,Chains of Implicit Rules}.
+
+@cindex @code{make depend}
+With old @code{make} programs, it was traditional practice to use this
+compiler feature to generate prerequisites on demand with a command like
+@samp{make depend}.  That command would create a file @file{depend}
+containing all the automatically-generated prerequisites; then the
+makefile could use @code{include} to read them in (@pxref{Include}).
+
+In GNU @code{make}, the feature of remaking makefiles makes this
+practice obsolete---you need never tell @code{make} explicitly to
+regenerate the prerequisites, because it always regenerates any makefile
+that is out of date.  @xref{Remaking Makefiles}.
+
+The practice we recommend for automatic prerequisite generation is to have
+one makefile corresponding to each source file.  For each source file
+@file{@var{name}.c} there is a makefile @file{@var{name}.d} which lists
+what files the object file @file{@var{name}.o} depends on.  That way
+only the source files that have changed need to be rescanned to produce
+the new prerequisites.
+
+Here is the pattern rule to generate a file of prerequisites (i.e., a makefile)
+called @file{@var{name}.d} from a C source file called @file{@var{name}.c}:
+
+@smallexample
+@group
+%.d: %.c
+        @@set -e; rm -f $@@; \
+         $(CC) -M $(CPPFLAGS) $< > $@@.$$$$; \
+         sed 's,\($*\)\.o[ :]*,\1.o $@@ : ,g' < $@@.$$$$ > $@@; \
+         rm -f $@@.$$$$
+@end group
+@end smallexample
+
+@noindent
+@xref{Pattern Rules}, for information on defining pattern rules.  The
+@samp{-e} flag to the shell causes it to exit immediately if the
+@code{$(CC)} command (or any other command) fails (exits with a
+nonzero status).
+@cindex @code{-e} (shell flag)
+
+@cindex @code{-MM} (to GNU compiler)
+With the GNU C compiler, you may wish to use the @samp{-MM} flag instead
+of @samp{-M}.  This omits prerequisites on system header files.
+@xref{Preprocessor Options, , Options Controlling the Preprocessor,
+gcc.info, Using GNU CC}, for details.
+
+@cindex @code{sed} (shell command)
+The purpose of the @code{sed} command is to translate (for example):
+
+@example
+main.o : main.c defs.h
+@end example
+
+@noindent
+into:
+
+@example
+main.o main.d : main.c defs.h
+@end example
+
+@noindent
+@cindex @code{.d}
+This makes each @samp{.d} file depend on all the source and header files
+that the corresponding @samp{.o} file depends on.  @code{make} then
+knows it must regenerate the prerequisites whenever any of the source or
+header files changes.
+
+Once you've defined the rule to remake the @samp{.d} files,
+you then use the @code{include} directive to read them all in.
+@xref{Include}.  For example:
+
+@example
+@group
+sources = foo.c bar.c
+
+include $(sources:.c=.d)
+@end group
+@end example
+
+@noindent
+(This example uses a substitution variable reference to translate the
+list of source files @samp{foo.c bar.c} into a list of prerequisite
+makefiles, @samp{foo.d bar.d}.  @xref{Substitution Refs}, for full
+information on substitution references.)  Since the @samp{.d} files are
+makefiles like any others, @code{make} will remake them as necessary
+with no further work from you.  @xref{Remaking Makefiles}.
+
+Note that the @samp{.d} files contain target definitions; you should
+be sure to place the @code{include} directive @emph{after} the first,
+default goal in your makefiles or run the risk of having a random
+object file become the default goal.
+@xref{How Make Works}.
+
+@node Commands, Using Variables, Rules, Top
+@chapter Writing the Commands in Rules
+@cindex commands, how to write
+@cindex rule commands
+@cindex writing rule commands
+
+The commands of a rule consist of one or more shell command lines to
+be executed, one at a time, in the order they appear.  Typically, the
+result of executing these commands is that the target of the rule is
+brought up to date.
+
+Users use many different shell programs, but commands in makefiles are
+always interpreted by @file{/bin/sh} unless the makefile specifies
+otherwise.  @xref{Execution, ,Command Execution}.
+
+@menu
+* Command Syntax::              Command syntax features and pitfalls.
+* Echoing::                     How to control when commands are echoed.
+* Execution::                   How commands are executed.
+* Parallel::                    How commands can be executed in parallel.
+* Errors::                      What happens after a command execution error.
+* Interrupts::                  What happens when a command is interrupted.
+* Recursion::                   Invoking @code{make} from makefiles.
+* Sequences::                   Defining canned sequences of commands.
+* Empty Commands::              Defining useful, do-nothing commands.
+@end menu
+
+@node Command Syntax, Echoing, Commands, Commands
+@section Command Syntax
+@cindex command syntax
+@cindex syntax of commands
+
+Makefiles have the unusual property that there are really two distinct
+syntaxes in one file.  Most of the makefile uses @code{make} syntax
+(@pxref{Makefiles, ,Writing Makefiles}).  However, commands are meant to be
+interpreted by the shell and so they are written using shell syntax.
+The @code{make} program does not try to understand shell syntax: it
+performs only a very few specific translations on the content of the
+command before handing it to the shell.
+
+Each command line must start with a tab, except that the first command
+line may be attached to the target-and-prerequisites line with a
+semicolon in between.  @emph{Any} line in the makefile that begins
+with a tab and appears in a ``rule context'' (that is, after a rule
+has been started until another rule or variable definition) will be
+considered a command line for that rule.  Blank lines and lines of
+just comments may appear among the command lines; they are ignored.
+
+Some consequences of these rules include:
+
+@itemize @bullet
+@item
+A blank line that begins with a tab is not blank: it's an empty
+command (@pxref{Empty Commands}).
+
+@cindex comments, in commands
+@cindex commands, comments in
+@cindex @code{#} (comments), in commands
+@item
+A comment in a command line is not a @code{make} comment; it will be
+passed to the shell as-is.  Whether the shell treats it as a comment
+or not depends on your shell.
+
+@item
+A variable definition in a ``rule context'' which is indented by a tab
+as the first character on the line, will be considered a command line,
+not a @code{make} variable definition, and passed to the shell.
+
+@item
+A conditional expression (@code{ifdef}, @code{ifeq},
+etc. @pxref{Conditional Syntax, ,Syntax of Conditionals}) in a ``rule
+context'' which is indented by a tab as the first character on the
+line, will be considered a command line and be passed to the shell.
+
+@end itemize
+
+@menu
+* Splitting Lines::             Breaking long command lines for readability.
+* Variables in Commands::       Using @code{make} variables in commands.
+@end menu
+
+@node Splitting Lines, Variables in Commands, Command Syntax, Command Syntax
+@subsection Splitting Command Lines
+@cindex commands, splitting
+@cindex splitting commands
+@cindex commands, backslash (@code{\}) in
+@cindex commands, quoting newlines in
+@cindex backslash (@code{\}), in commands
+@cindex @code{\} (backslash), in commands
+@cindex quoting newline, in commands
+@cindex newline, quoting, in commands
+
+One of the few ways in which @code{make} does interpret command lines
+is checking for a backslash just before the newline.  As in normal
+makefile syntax, a single command can be split into multiple lines in
+the makefile by placing a backslash before each newline.  A sequence
+of lines like this is considered a single command, and one instance of
+the shell will be invoked to run it.
+
+However, in contrast to how they are treated in other places in a
+makefile, backslash-newline pairs are @emph{not} removed from the
+command.  Both the backslash and the newline characters are preserved
+and passed to the shell.  How the backslash-newline is interpreted
+depends on your shell.  If the first character of the next line
+after the backslash-newline is a tab, then that tab (and only that
+tab) is removed.  Whitespace is never added to the command.
+
+For example, this makefile:
+
+@example
+@group
+all :
+        @@echo no\
+space
+        @@echo no\
+        space
+        @@echo one \
+        space
+        @@echo one\
+         space
+@end group
+@end example
+
+@noindent
+consists of four separate shell commands where the output is:
+
+@example
+@group
+nospace
+nospace
+one space
+one space
+@end group
+@end example
+
+As a more complex example, this makefile:
+
+@example
+@group
+all : ; @@echo 'hello \
+        world' ; echo "hello \
+    world"
+@end group
+@end example
+
+@noindent
+will run one shell with a command script of:
+
+@example
+@group
+echo 'hello \
+world' ; echo "hello \
+    world"
+@end group
+@end example
+
+@noindent
+which, according to shell quoting rules, will yield the following output:
+
+@example
+@group
+hello \
+world
+hello     world
+@end group
+@end example
+
+@noindent
+Notice how the backslash/newline pair was removed inside the string
+quoted with double quotes (@code{"@dots{}"}), but not from the string
+quoted with single quotes (@code{'@dots{}'}).  This is the way the
+default shell (@file{/bin/sh}) handles backslash/newline pairs.  If
+you specify a different shell in your makefiles it may treat them
+differently.
+
+Sometimes you want to split a long line inside of single quotes, but
+you don't want the backslash-newline to appear in the quoted content.
+This is often the case when passing scripts to languages such as Perl,
+where extraneous backslashes inside the script can change its meaning
+or even be a syntax error.  One simple way of handling this is to
+place the quoted string, or even the entire command, into a
+@code{make} variable then use the variable in the command.  In this
+situation the newline quoting rules for makefiles will be used, and
+the backslash-newline will be removed.  If we rewrite our example
+above using this method:
+
+@example
+@group
+HELLO = 'hello \
+world'
+
+all : ; @@echo $(HELLO)
+@end group
+@end example
+
+@noindent
+we will get output like this:
+
+@example
+@group
+hello world
+@end group
+@end example
+
+If you like, you can also use target-specific variables
+(@pxref{Target-specific, ,Target-specific Variable Values}) to obtain
+a tighter correspondence between the variable and the command that
+uses it.
+
+@node Variables in Commands,  , Splitting Lines, Command Syntax
+@subsection Using Variables in Commands
+@cindex variable references in commands
+@cindex commands, using variables in
+
+The other way in which @code{make} processes commands is by expanding
+any variable references in them (@pxref{Reference,Basics of Variable
+References}).  This occurs after make has finished reading all the
+makefiles and the target is determined to be out of date; so, the
+commands for targets which are not rebuilt are never expanded.
+
+Variable and function references in commands have identical syntax and
+semantics to references elsewhere in the makefile.  They also have the
+same quoting rules: if you want a dollar sign to appear in your
+command, you must double it (@samp{$$}).  For shells like the default
+shell, that use dollar signs to introduce variables, it's important to
+keep clear in your mind whether the variable you want to reference is
+a @code{make} variable (use a single dollar sign) or a shell variable
+(use two dollar signs).  For example:
+
+@example
+@group
+LIST = one two three
+all:
+        for i in $(LIST); do \
+            echo $$i; \
+        done
+@end group
+@end example
+
+@noindent
+results in the following command being passed to the shell:
+
+@example
+@group
+for i in one two three; do \
+    echo $i; \
+done
+@end group
+@end example
+
+@noindent
+which generates the expected result:
+
+@example
+@group
+one
+two
+three
+@end group
+@end example
+
+@node Echoing, Execution, Command Syntax, Commands
+@section Command Echoing
+@cindex echoing of commands
+@cindex silent operation
+@cindex @code{@@} (in commands)
+@cindex commands, echoing
+@cindex printing of commands
+
+Normally @code{make} prints each command line before it is executed.
+We call this @dfn{echoing} because it gives the appearance that you
+are typing the commands yourself.
+
+When a line starts with @samp{@@}, the echoing of that line is suppressed.
+The @samp{@@} is discarded before the command is passed to the shell.
+Typically you would use this for a command whose only effect is to print
+something, such as an @code{echo} command to indicate progress through
+the makefile:
+
+@example
+@@echo About to make distribution files
+@end example
+
+@cindex @code{-n}
+@cindex @code{--just-print}
+@cindex @code{--dry-run}
+@cindex @code{--recon}
+When @code{make} is given the flag @samp{-n} or @samp{--just-print}
+it only echoes commands, it won't execute them.  @xref{Options Summary,
+,Summary of Options}.  In this case and only this case, even the
+commands starting with @samp{@@} are printed.  This flag is useful for
+finding out which commands @code{make} thinks are necessary without
+actually doing them.
+
+@cindex @code{-s}
+@cindex @code{--silent}
+@cindex @code{--quiet}
+@findex .SILENT
+The @samp{-s} or @samp{--silent}
+flag to @code{make} prevents all echoing, as if all commands
+started with @samp{@@}.  A rule in the makefile for the special target
+@code{.SILENT} without prerequisites has the same effect
+(@pxref{Special Targets, ,Special Built-in Target Names}).
+@code{.SILENT} is essentially obsolete since @samp{@@} is more flexible.@refill
+
+@node Execution, Parallel, Echoing, Commands
+@section Command Execution
+@cindex commands, execution
+@cindex execution, of commands
+@cindex shell command, execution
+@vindex @code{SHELL} @r{(command execution)}
+
+When it is time to execute commands to update a target, they are
+executed by invoking a new subshell for each command line.  (In
+practice, @code{make} may take shortcuts that do not affect the
+results.)
+
+@cindex @code{cd} (shell command)
+@cindex shell variables, setting in commands
+@cindex commands setting shell variables
+@strong{Please note:} this implies that setting shell variables and
+invoking shell commands such as @code{cd} that set a context local to
+each process will not affect the following command lines.@footnote{On
+MS-DOS, the value of current working directory is @strong{global}, so
+changing it @emph{will} affect the following command lines on those
+systems.}  If you want to use @code{cd} to affect the next statement,
+put both statements in a single command line.  Then @code{make} will
+invoke one shell to run the entire line, and the shell will execute
+the statements in sequence.  For example:
+
+@example
+foo : bar/lose
+        cd $(@@D) && gobble $(@@F) > ../$@@
+@end example
+
+@noindent
+Here we use the shell AND operator (@code{&&}) so that if the
+@code{cd} command fails, the script will fail without trying to invoke
+the @code{gobble} command in the wrong directory, which could cause
+problems (in this case it would certainly cause @file{../foo} to be
+truncated, at least).
+
+@menu
+* Choosing the Shell::          How @code{make} chooses the shell used
+                                  to run commands.
+@end menu
+
+@node Choosing the Shell,  , Execution, Execution
+@subsection Choosing the Shell
+@cindex shell, choosing the
+@cindex @code{SHELL}, value of
+
+@vindex SHELL
+The program used as the shell is taken from the variable @code{SHELL}.
+If this variable is not set in your makefile, the program
+@file{/bin/sh} is used as the shell.
+
+@cindex environment, @code{SHELL} in
+Unlike most variables, the variable @code{SHELL} is never set from the
+environment.  This is because the @code{SHELL} environment variable is
+used to specify your personal choice of shell program for interactive
+use.  It would be very bad for personal choices like this to affect the
+functioning of makefiles.  @xref{Environment, ,Variables from the
+Environment}.
+
+Furthermore, when you do set @code{SHELL} in your makefile that value
+is @emph{not} exported in the environment to commands that @code{make}
+invokes.  Instead, the value inherited from the user's environment, if
+any, is exported.  You can override this behavior by explicitly
+exporting @code{SHELL} (@pxref{Variables/Recursion, ,Communicating
+Variables to a Sub-@code{make}}), forcing it to be passed in the
+environment to commands.
+
+@vindex @code{MAKESHELL} @r{(MS-DOS alternative to @code{SHELL})}
+However, on MS-DOS and MS-Windows the value of @code{SHELL} in the
+environment @strong{is} used, since on those systems most users do not
+set this variable, and therefore it is most likely set specifically to
+be used by @code{make}.  On MS-DOS, if the setting of @code{SHELL} is
+not suitable for @code{make}, you can set the variable
+@code{MAKESHELL} to the shell that @code{make} should use; if set it
+will be used as the shell instead of the value of @code{SHELL}.
+
+@subsubheading Choosing a Shell in DOS and Windows
+@cindex shell, in DOS and Windows
+@cindex DOS, choosing a shell in
+@cindex Windows, choosing a shell in
+
+Choosing a shell in MS-DOS and MS-Windows is much more complex than on
+other systems.
+
+@vindex COMSPEC
+On MS-DOS, if @code{SHELL} is not set, the value of the variable
+@code{COMSPEC} (which is always set) is used instead.
+
+@cindex @code{SHELL}, MS-DOS specifics
+The processing of lines that set the variable @code{SHELL} in Makefiles
+is different on MS-DOS.  The stock shell, @file{command.com}, is
+ridiculously limited in its functionality and many users of @code{make}
+tend to install a replacement shell.  Therefore, on MS-DOS, @code{make}
+examines the value of @code{SHELL}, and changes its behavior based on
+whether it points to a Unix-style or DOS-style shell.  This allows
+reasonable functionality even if @code{SHELL} points to
+@file{command.com}.
+
+If @code{SHELL} points to a Unix-style shell, @code{make} on MS-DOS
+additionally checks whether that shell can indeed be found; if not, it
+ignores the line that sets @code{SHELL}.  In MS-DOS, GNU @code{make}
+searches for the shell in the following places:
+
+@enumerate
+@item
+In the precise place pointed to by the value of @code{SHELL}.  For
+example, if the makefile specifies @samp{SHELL = /bin/sh}, @code{make}
+will look in the directory @file{/bin} on the current drive.
+
+@item
+In the current directory.
+
+@item
+In each of the directories in the @code{PATH} variable, in order.
+
+@end enumerate
+
+In every directory it examines, @code{make} will first look for the
+specific file (@file{sh} in the example above).  If this is not found,
+it will also look in that directory for that file with one of the known
+extensions which identify executable files.  For example @file{.exe},
+@file{.com}, @file{.bat}, @file{.btm}, @file{.sh}, and some others.
+
+If any of these attempts is successful, the value of @code{SHELL} will
+be set to the full pathname of the shell as found.  However, if none of
+these is found, the value of @code{SHELL} will not be changed, and thus
+the line that sets it will be effectively ignored.  This is so
+@code{make} will only support features specific to a Unix-style shell if
+such a shell is actually installed on the system where @code{make} runs.
+
+Note that this extended search for the shell is limited to the cases
+where @code{SHELL} is set from the Makefile; if it is set in the
+environment or command line, you are expected to set it to the full
+pathname of the shell, exactly as things are on Unix.
+
+The effect of the above DOS-specific processing is that a Makefile that
+contains @samp{SHELL = /bin/sh} (as many Unix makefiles do), will work
+on MS-DOS unaltered if you have e.g.@: @file{sh.exe} installed in some
+directory along your @code{PATH}.
+
+@node Parallel, Errors, Execution, Commands
+@section Parallel Execution
+@cindex commands, execution in parallel
+@cindex parallel execution
+@cindex execution, in parallel
+@cindex job slots
+@cindex @code{-j}
+@cindex @code{--jobs}
+
+GNU @code{make} knows how to execute several commands at once.
+Normally, @code{make} will execute only one command at a time, waiting
+for it to finish before executing the next.  However, the @samp{-j} or
+@samp{--jobs} option tells @code{make} to execute many commands
+simultaneously.  You can inhibit parallelism in a particular makefile
+with the @code{.NOTPARALLEL} pseudo-target (@pxref{Special
+Targets,Special Built-in Target Names}).@refill
+
+On MS-DOS, the @samp{-j} option has no effect, since that system doesn't
+support multi-processing.
+
+If the @samp{-j} option is followed by an integer, this is the number of
+commands to execute at once; this is called the number of @dfn{job slots}.
+If there is nothing looking like an integer after the @samp{-j} option,
+there is no limit on the number of job slots.  The default number of job
+slots is one, which means serial execution (one thing at a time).
+
+One unpleasant consequence of running several commands simultaneously is
+that output generated by the commands appears whenever each command
+sends it, so messages from different commands may be interspersed.
+
+Another problem is that two processes cannot both take input from the
+same device; so to make sure that only one command tries to take input
+from the terminal at once, @code{make} will invalidate the standard
+input streams of all but one running command.  This means that
+attempting to read from standard input will usually be a fatal error (a
+@samp{Broken pipe} signal) for most child processes if there are
+several.
+@cindex broken pipe
+@cindex standard input
+
+It is unpredictable which command will have a valid standard input stream
+(which will come from the terminal, or wherever you redirect the standard
+input of @code{make}).  The first command run will always get it first, and
+the first command started after that one finishes will get it next, and so
+on.
+
+We will change how this aspect of @code{make} works if we find a better
+alternative.  In the mean time, you should not rely on any command using
+standard input at all if you are using the parallel execution feature; but
+if you are not using this feature, then standard input works normally in
+all commands.
+
+Finally, handling recursive @code{make} invocations raises issues.  For
+more information on this, see
+@ref{Options/Recursion, ,Communicating Options to a Sub-@code{make}}.
+
+If a command fails (is killed by a signal or exits with a nonzero
+status), and errors are not ignored for that command
+(@pxref{Errors, ,Errors in Commands}),
+the remaining command lines to remake the same target will not be run.
+If a command fails and the @samp{-k} or @samp{--keep-going}
+option was not given
+(@pxref{Options Summary, ,Summary of Options}),
+@code{make} aborts execution.  If make
+terminates for any reason (including a signal) with child processes
+running, it waits for them to finish before actually exiting.@refill
+
+@cindex load average
+@cindex limiting jobs based on load
+@cindex jobs, limiting based on load
+@cindex @code{-l} (load average)
+@cindex @code{--max-load}
+@cindex @code{--load-average}
+When the system is heavily loaded, you will probably want to run fewer jobs
+than when it is lightly loaded.  You can use the @samp{-l} option to tell
+@code{make} to limit the number of jobs to run at once, based on the load
+average.  The @samp{-l} or @samp{--max-load}
+option is followed by a floating-point number.  For
+example,
+
+@example
+-l 2.5
+@end example
+
+@noindent
+will not let @code{make} start more than one job if the load average is
+above 2.5.  The @samp{-l} option with no following number removes the
+load limit, if one was given with a previous @samp{-l} option.@refill
+
+More precisely, when @code{make} goes to start up a job, and it already has
+at least one job running, it checks the current load average; if it is not
+lower than the limit given with @samp{-l}, @code{make} waits until the load
+average goes below that limit, or until all the other jobs finish.
+
+By default, there is no load limit.
+
+@node Errors, Interrupts, Parallel, Commands
+@section Errors in Commands
+@cindex errors (in commands)
+@cindex commands, errors in
+@cindex exit status (errors)
+
+After each shell command returns, @code{make} looks at its exit status.
+If the command completed successfully, the next command line is executed
+in a new shell; after the last command line is finished, the rule is
+finished.
+
+If there is an error (the exit status is nonzero), @code{make} gives up on
+the current rule, and perhaps on all rules.
+
+Sometimes the failure of a certain command does not indicate a problem.
+For example, you may use the @code{mkdir} command to ensure that a
+directory exists.  If the directory already exists, @code{mkdir} will
+report an error, but you probably want @code{make} to continue regardless.
+
+@cindex @code{-} (in commands)
+To ignore errors in a command line, write a @samp{-} at the beginning of
+the line's text (after the initial tab).  The @samp{-} is discarded before
+the command is passed to the shell for execution.
+
+For example,
+
+@example
+@group
+clean:
+        -rm -f *.o
+@end group
+@end example
+@cindex @code{rm} (shell command)
+
+@noindent
+This causes @code{rm} to continue even if it is unable to remove a file.
+
+@cindex @code{-i}
+@cindex @code{--ignore-errors}
+@findex .IGNORE
+When you run @code{make} with the @samp{-i} or @samp{--ignore-errors}
+flag, errors are ignored in all commands of all rules.  A rule in the
+makefile for the special target @code{.IGNORE} has the same effect, if
+there are no prerequisites.  These ways of ignoring errors are obsolete
+because @samp{-} is more flexible.
+
+When errors are to be ignored, because of either a @samp{-} or the
+@samp{-i} flag, @code{make} treats an error return just like success,
+except that it prints out a message that tells you the status code
+the command exited with, and says that the error has been ignored.
+
+When an error happens that @code{make} has not been told to ignore,
+it implies that the current target cannot be correctly remade, and neither
+can any other that depends on it either directly or indirectly.  No further
+commands will be executed for these targets, since their preconditions
+have not been achieved.
+
+
+@cindex @code{-k}
+@cindex @code{--keep-going}
+Normally @code{make} gives up immediately in this circumstance, returning a
+nonzero status.  However, if the @samp{-k} or @samp{--keep-going}
+flag is specified, @code{make}
+continues to consider the other prerequisites of the pending targets,
+remaking them if necessary, before it gives up and returns nonzero status.
+For example, after an error in compiling one object file, @samp{make -k}
+will continue compiling other object files even though it already knows
+that linking them will be impossible.  @xref{Options Summary, ,Summary of Options}.
+
+The usual behavior assumes that your purpose is to get the specified
+targets up to date; once @code{make} learns that this is impossible, it
+might as well report the failure immediately.  The @samp{-k} option says
+that the real purpose is to test as many of the changes made in the
+program as possible, perhaps to find several independent problems so
+that you can correct them all before the next attempt to compile.  This
+is why Emacs' @code{compile} command passes the @samp{-k} flag by
+default.
+@cindex Emacs (@code{M-x compile})
+
+@findex .DELETE_ON_ERROR
+@cindex deletion of target files
+@cindex removal of target files
+@cindex target, deleting on error
+Usually when a command fails, if it has changed the target file at all,
+the file is corrupted and cannot be used---or at least it is not
+completely updated.  Yet the file's time stamp says that it is now up to
+date, so the next time @code{make} runs, it will not try to update that
+file.  The situation is just the same as when the command is killed by a
+signal; @pxref{Interrupts}.  So generally the right thing to do is to
+delete the target file if the command fails after beginning to change
+the file.  @code{make} will do this if @code{.DELETE_ON_ERROR} appears
+as a target.  This is almost always what you want @code{make} to do, but
+it is not historical practice; so for compatibility, you must explicitly
+request it.
+
+@node Interrupts, Recursion, Errors, Commands
+@section Interrupting or Killing @code{make}
+@cindex interrupt
+@cindex signal
+@cindex deletion of target files
+@cindex removal of target files
+@cindex target, deleting on interrupt
+@cindex killing (interruption)
+
+If @code{make} gets a fatal signal while a command is executing, it may
+delete the target file that the command was supposed to update.  This is
+done if the target file's last-modification time has changed since
+@code{make} first checked it.
+
+The purpose of deleting the target is to make sure that it is remade from
+scratch when @code{make} is next run.  Why is this?  Suppose you type
+@kbd{Ctrl-c} while a compiler is running, and it has begun to write an
+object file @file{foo.o}.  The @kbd{Ctrl-c} kills the compiler, resulting
+in an incomplete file whose last-modification time is newer than the source
+file @file{foo.c}.  But @code{make} also receives the @kbd{Ctrl-c} signal
+and deletes this incomplete file.  If @code{make} did not do this, the next
+invocation of @code{make} would think that @file{foo.o} did not require
+updating---resulting in a strange error message from the linker when it
+tries to link an object file half of which is missing.
+
+@findex .PRECIOUS
+You can prevent the deletion of a target file in this way by making the
+special target @code{.PRECIOUS} depend on it.  Before remaking a target,
+@code{make} checks to see whether it appears on the prerequisites of
+@code{.PRECIOUS}, and thereby decides whether the target should be deleted
+if a signal happens.  Some reasons why you might do this are that the
+target is updated in some atomic fashion, or exists only to record a
+modification-time (its contents do not matter), or must exist at all
+times to prevent other sorts of trouble.
+
+@node Recursion, Sequences, Interrupts, Commands
+@section Recursive Use of @code{make}
+@cindex recursion
+@cindex subdirectories, recursion for
+
+Recursive use of @code{make} means using @code{make} as a command in a
+makefile.  This technique is useful when you want separate makefiles for
+various subsystems that compose a larger system.  For example, suppose you
+have a subdirectory @file{subdir} which has its own makefile, and you would
+like the containing directory's makefile to run @code{make} on the
+subdirectory.  You can do it by writing this:
+
+@example
+subsystem:
+        cd subdir && $(MAKE)
+@end example
+
+@noindent
+or, equivalently, this (@pxref{Options Summary, ,Summary of Options}):
+
+@example
+subsystem:
+        $(MAKE) -C subdir
+@end example
+@cindex @code{-C}
+@cindex @code{--directory}
+
+You can write recursive @code{make} commands just by copying this example,
+but there are many things to know about how they work and why, and about
+how the sub-@code{make} relates to the top-level @code{make}.  You may
+also find it useful to declare targets that invoke recursive
+@code{make} commands as @samp{.PHONY} (for more discussion on when
+this is useful, see @ref{Phony Targets}).
+
+@vindex @code{CURDIR}
+For your convenience, when GNU @code{make} starts (after it has
+processed any @code{-C} options) it sets the variable @code{CURDIR} to
+the pathname of the current working directory.  This value is never
+touched by @code{make} again: in particular note that if you include
+files from other directories the value of @code{CURDIR} does not
+change.  The value has the same precedence it would have if it were
+set in the makefile (by default, an environment variable @code{CURDIR}
+will not override this value).  Note that setting this variable has no
+impact on the operation of @code{make} (it does not cause @code{make}
+to change its working directory, for example).
+
+@menu
+* MAKE Variable::               The special effects of using @samp{$(MAKE)}.
+* Variables/Recursion::         How to communicate variables to a sub-@code{make}.
+* Options/Recursion::           How to communicate options to a sub-@code{make}.
+* -w Option::                   How the @samp{-w} or @samp{--print-directory} option
+                                  helps debug use of recursive @code{make} commands.
+@end menu
+
+@node MAKE Variable, Variables/Recursion, Recursion, Recursion
+@subsection How the @code{MAKE} Variable Works
+@vindex MAKE
+@cindex recursion, and @code{MAKE} variable
+
+Recursive @code{make} commands should always use the variable @code{MAKE},
+not the explicit command name @samp{make}, as shown here:
+
+@example
+@group
+subsystem:
+        cd subdir && $(MAKE)
+@end group
+@end example
+
+The value of this variable is the file name with which @code{make} was
+invoked.  If this file name was @file{/bin/make}, then the command executed
+is @samp{cd subdir && /bin/make}.  If you use a special version of
+@code{make} to run the top-level makefile, the same special version will be
+executed for recursive invocations.
+@cindex @code{cd} (shell command)
+
+@cindex +, and commands
+As a special feature, using the variable @code{MAKE} in the commands of
+a rule alters the effects of the @samp{-t} (@samp{--touch}), @samp{-n}
+(@samp{--just-print}), or @samp{-q} (@w{@samp{--question}}) option.
+Using the @code{MAKE} variable has the same effect as using a @samp{+}
+character at the beginning of the command line.  @xref{Instead of
+Execution, ,Instead of Executing the Commands}.  This special feature
+is only enabled if the @code{MAKE} variable appears directly in the
+command script: it does not apply if the @code{MAKE} variable is
+referenced through expansion of another variable.  In the latter case
+you must use the @samp{+} token to get these special effects.@refill
+
+Consider the command @samp{make -t} in the above example.  (The
+@samp{-t} option marks targets as up to date without actually running
+any commands; see @ref{Instead of Execution}.)  Following the usual
+definition of @samp{-t}, a @samp{make -t} command in the example would
+create a file named @file{subsystem} and do nothing else.  What you
+really want it to do is run @samp{@w{cd subdir &&} @w{make -t}}; but that would
+require executing the command, and @samp{-t} says not to execute
+commands.@refill
+@cindex @code{-t}, and recursion
+@cindex recursion, and @code{-t}
+@cindex @code{--touch}, and recursion
+
+The special feature makes this do what you want: whenever a command
+line of a rule contains the variable @code{MAKE}, the flags @samp{-t},
+@samp{-n} and @samp{-q} do not apply to that line.  Command lines
+containing @code{MAKE} are executed normally despite the presence of a
+flag that causes most commands not to be run.  The usual
+@code{MAKEFLAGS} mechanism passes the flags to the sub-@code{make}
+(@pxref{Options/Recursion, ,Communicating Options to a
+Sub-@code{make}}), so your request to touch the files, or print the
+commands, is propagated to the subsystem.@refill
+
+@node Variables/Recursion, Options/Recursion, MAKE Variable, Recursion
+@subsection Communicating Variables to a Sub-@code{make}
+@cindex sub-@code{make}
+@cindex environment, and recursion
+@cindex exporting variables
+@cindex variables, environment
+@cindex variables, exporting
+@cindex recursion, and environment
+@cindex recursion, and variables
+
+Variable values of the top-level @code{make} can be passed to the
+sub-@code{make} through the environment by explicit request.  These
+variables are defined in the sub-@code{make} as defaults, but do not
+override what is specified in the makefile used by the sub-@code{make}
+makefile unless you use the @samp{-e} switch (@pxref{Options Summary,
+,Summary of Options}).@refill
+
+To pass down, or @dfn{export}, a variable, @code{make} adds the variable
+and its value to the environment for running each command.  The
+sub-@code{make}, in turn, uses the environment to initialize its table
+of variable values.  @xref{Environment, ,Variables from the
+Environment}.
+
+Except by explicit request, @code{make} exports a variable only if it
+is either defined in the environment initially or set on the command
+line, and if its name consists only of letters, numbers, and underscores.
+Some shells cannot cope with environment variable names consisting of
+characters other than letters, numbers, and underscores.
+
+@cindex SHELL, exported value
+The value of the @code{make} variable @code{SHELL} is not exported.
+Instead, the value of the @code{SHELL} variable from the invoking
+environment is passed to the sub-@code{make}.  You can force
+@code{make} to export its value for @code{SHELL} by using the
+@code{export} directive, described below.  @xref{Choosing the Shell}.
+
+The special variable @code{MAKEFLAGS} is always exported (unless you
+unexport it).  @code{MAKEFILES} is exported if you set it to anything.
+
+@code{make} automatically passes down variable values that were defined
+on the command line, by putting them in the @code{MAKEFLAGS} variable.
+@iftex
+See the next section.
+@end iftex
+@ifnottex
+@xref{Options/Recursion}.
+@end ifnottex
+
+Variables are @emph{not} normally passed down if they were created by
+default by @code{make} (@pxref{Implicit Variables, ,Variables Used by
+Implicit Rules}).  The sub-@code{make} will define these for
+itself.@refill
+
+@findex export
+If you want to export specific variables to a sub-@code{make}, use the
+@code{export} directive, like this:
+
+@example
+export @var{variable} @dots{}
+@end example
+
+@noindent
+@findex unexport
+If you want to @emph{prevent} a variable from being exported, use the
+@code{unexport} directive, like this:
+
+@example
+unexport @var{variable} @dots{}
+@end example
+
+@noindent
+In both of these forms, the arguments to @code{export} and
+@code{unexport} are expanded, and so could be variables or functions
+which expand to a (list of) variable names to be (un)exported.
+
+As a convenience, you can define a variable and export it at the same
+time by doing:
+
+@example
+export @var{variable} = value
+@end example
+
+@noindent
+has the same result as:
+
+@example
+@var{variable} = value
+export @var{variable}
+@end example
+
+@noindent
+and
+
+@example
+export @var{variable} := value
+@end example
+
+@noindent
+has the same result as:
+
+@example
+@var{variable} := value
+export @var{variable}
+@end example
+
+Likewise,
+
+@example
+export @var{variable} += value
+@end example
+
+@noindent
+is just like:
+
+@example
+@var{variable} += value
+export @var{variable}
+@end example
+
+@noindent
+@xref{Appending, ,Appending More Text to Variables}.
+
+You may notice that the @code{export} and @code{unexport} directives
+work in @code{make} in the same way they work in the shell, @code{sh}.
+
+If you want all variables to be exported by default, you can use
+@code{export} by itself:
+
+@example
+export
+@end example
+
+@noindent
+This tells @code{make} that variables which are not explicitly mentioned
+in an @code{export} or @code{unexport} directive should be exported.
+Any variable given in an @code{unexport} directive will still @emph{not}
+be exported.  If you use @code{export} by itself to export variables by
+default, variables whose names contain characters other than
+alphanumerics and underscores will not be exported unless specifically
+mentioned in an @code{export} directive.@refill
+
+@findex .EXPORT_ALL_VARIABLES
+The behavior elicited by an @code{export} directive by itself was the
+default in older versions of GNU @code{make}.  If your makefiles depend
+on this behavior and you want to be compatible with old versions of
+@code{make}, you can write a rule for the special target
+@code{.EXPORT_ALL_VARIABLES} instead of using the @code{export} directive.
+This will be ignored by old @code{make}s, while the @code{export}
+directive will cause a syntax error.@refill
+@cindex compatibility in exporting
+
+Likewise, you can use @code{unexport} by itself to tell @code{make}
+@emph{not} to export variables by default.  Since this is the default
+behavior, you would only need to do this if @code{export} had been used
+by itself earlier (in an included makefile, perhaps).  You
+@strong{cannot} use @code{export} and @code{unexport} by themselves to
+have variables exported for some commands and not for others.  The last
+@code{export} or @code{unexport} directive that appears by itself
+determines the behavior for the entire run of @code{make}.@refill
+
+@vindex MAKELEVEL
+@cindex recursion, level of
+As a special feature, the variable @code{MAKELEVEL} is changed when it
+is passed down from level to level.  This variable's value is a string
+which is the depth of the level as a decimal number.  The value is
+@samp{0} for the top-level @code{make}; @samp{1} for a sub-@code{make},
+@samp{2} for a sub-sub-@code{make}, and so on.  The incrementation
+happens when @code{make} sets up the environment for a command.@refill
+
+The main use of @code{MAKELEVEL} is to test it in a conditional
+directive (@pxref{Conditionals, ,Conditional Parts of Makefiles}); this
+way you can write a makefile that behaves one way if run recursively and
+another way if run directly by you.@refill
+
+@vindex MAKEFILES
+You can use the variable @code{MAKEFILES} to cause all sub-@code{make}
+commands to use additional makefiles.  The value of @code{MAKEFILES} is
+a whitespace-separated list of file names.  This variable, if defined in
+the outer-level makefile, is passed down through the environment; then
+it serves as a list of extra makefiles for the sub-@code{make} to read
+before the usual or specified ones.  @xref{MAKEFILES Variable, ,The
+Variable @code{MAKEFILES}}.@refill
+
+@node Options/Recursion, -w Option, Variables/Recursion, Recursion
+@subsection Communicating Options to a Sub-@code{make}
+@cindex options, and recursion
+@cindex recursion, and options
+
+@vindex MAKEFLAGS
+Flags such as @samp{-s} and @samp{-k} are passed automatically to the
+sub-@code{make} through the variable @code{MAKEFLAGS}.  This variable is
+set up automatically by @code{make} to contain the flag letters that
+@code{make} received.  Thus, if you do @w{@samp{make -ks}} then
+@code{MAKEFLAGS} gets the value @samp{ks}.@refill
+
+As a consequence, every sub-@code{make} gets a value for @code{MAKEFLAGS}
+in its environment.  In response, it takes the flags from that value and
+processes them as if they had been given as arguments.
+@xref{Options Summary, ,Summary of Options}.
+
+@cindex command line variable definitions, and recursion
+@cindex variables, command line, and recursion
+@cindex recursion, and command line variable definitions
+Likewise variables defined on the command line are passed to the
+sub-@code{make} through @code{MAKEFLAGS}.  Words in the value of
+@code{MAKEFLAGS} that contain @samp{=}, @code{make} treats as variable
+definitions just as if they appeared on the command line.
+@xref{Overriding, ,Overriding Variables}.
+
+@cindex @code{-C}, and recursion
+@cindex @code{-f}, and recursion
+@cindex @code{-o}, and recursion
+@cindex @code{-W}, and recursion
+@cindex @code{--directory}, and recursion
+@cindex @code{--file}, and recursion
+@cindex @code{--old-file}, and recursion
+@cindex @code{--assume-old}, and recursion
+@cindex @code{--assume-new}, and recursion
+@cindex @code{--new-file}, and recursion
+@cindex recursion, and @code{-C}
+@cindex recursion, and @code{-f}
+@cindex recursion, and @code{-o}
+@cindex recursion, and @code{-W}
+The options @samp{-C}, @samp{-f}, @samp{-o}, and @samp{-W} are not put
+into @code{MAKEFLAGS}; these options are not passed down.@refill
+
+@cindex @code{-j}, and recursion
+@cindex @code{--jobs}, and recursion
+@cindex recursion, and @code{-j}
+@cindex job slots, and recursion
+The @samp{-j} option is a special case (@pxref{Parallel, ,Parallel Execution}).
+If you set it to some numeric value @samp{N} and your operating system
+supports it (most any UNIX system will; others typically won't), the
+parent @code{make} and all the sub-@code{make}s will communicate to
+ensure that there are only @samp{N} jobs running at the same time
+between them all.  Note that any job that is marked recursive
+(@pxref{Instead of Execution, ,Instead of Executing the Commands})
+doesn't count against the total jobs (otherwise we could get @samp{N}
+sub-@code{make}s running and have no slots left over for any real work!)
+
+If your operating system doesn't support the above communication, then
+@samp{-j 1} is always put into @code{MAKEFLAGS} instead of the value you
+specified.  This is because if the @w{@samp{-j}} option were passed down
+to sub-@code{make}s, you would get many more jobs running in parallel
+than you asked for.  If you give @samp{-j} with no numeric argument,
+meaning to run as many jobs as possible in parallel, this is passed
+down, since multiple infinities are no more than one.@refill
+
+If you do not want to pass the other flags down, you must change the
+value of @code{MAKEFLAGS}, like this:
+
+@example
+subsystem:
+        cd subdir && $(MAKE) MAKEFLAGS=
+@end example
+
+@vindex MAKEOVERRIDES
+The command line variable definitions really appear in the variable
+@code{MAKEOVERRIDES}, and @code{MAKEFLAGS} contains a reference to this
+variable.  If you do want to pass flags down normally, but don't want to
+pass down the command line variable definitions, you can reset
+@code{MAKEOVERRIDES} to empty, like this:
+
+@example
+MAKEOVERRIDES =
+@end example
+
+@noindent
+@cindex Arg list too long
+@cindex E2BIG
+This is not usually useful to do.  However, some systems have a small
+fixed limit on the size of the environment, and putting so much
+information into the value of @code{MAKEFLAGS} can exceed it.  If you
+see the error message @samp{Arg list too long}, this may be the problem.
+@findex .POSIX
+@cindex POSIX.2
+(For strict compliance with POSIX.2, changing @code{MAKEOVERRIDES} does
+not affect @code{MAKEFLAGS} if the special target @samp{.POSIX} appears
+in the makefile.  You probably do not care about this.)
+
+@vindex MFLAGS
+A similar variable @code{MFLAGS} exists also, for historical
+compatibility.  It has the same value as @code{MAKEFLAGS} except that it
+does not contain the command line variable definitions, and it always
+begins with a hyphen unless it is empty (@code{MAKEFLAGS} begins with a
+hyphen only when it begins with an option that has no single-letter
+version, such as @samp{--warn-undefined-variables}).  @code{MFLAGS} was
+traditionally used explicitly in the recursive @code{make} command, like
+this:
+
+@example
+subsystem:
+        cd subdir && $(MAKE) $(MFLAGS)
+@end example
+
+@noindent
+but now @code{MAKEFLAGS} makes this usage redundant.  If you want your
+makefiles to be compatible with old @code{make} programs, use this
+technique; it will work fine with more modern @code{make} versions too.
+
+@cindex setting options from environment
+@cindex options, setting from environment
+@cindex setting options in makefiles
+@cindex options, setting in makefiles
+The @code{MAKEFLAGS} variable can also be useful if you want to have
+certain options, such as @samp{-k} (@pxref{Options Summary, ,Summary of
+Options}), set each time you run @code{make}.  You simply put a value for
+@code{MAKEFLAGS} in your environment.  You can also set @code{MAKEFLAGS} in
+a makefile, to specify additional flags that should also be in effect for
+that makefile.  (Note that you cannot use @code{MFLAGS} this way.  That
+variable is set only for compatibility; @code{make} does not interpret a
+value you set for it in any way.)
+
+When @code{make} interprets the value of @code{MAKEFLAGS} (either from the
+environment or from a makefile), it first prepends a hyphen if the value
+does not already begin with one.  Then it chops the value into words
+separated by blanks, and parses these words as if they were options given
+on the command line (except that @samp{-C}, @samp{-f}, @samp{-h},
+@samp{-o}, @samp{-W}, and their long-named versions are ignored; and there
+is no error for an invalid option).
+
+If you do put @code{MAKEFLAGS} in your environment, you should be sure not
+to include any options that will drastically affect the actions of
+@code{make} and undermine the purpose of makefiles and of @code{make}
+itself.  For instance, the @samp{-t}, @samp{-n}, and @samp{-q} options, if
+put in one of these variables, could have disastrous consequences and would
+certainly have at least surprising and probably annoying effects.@refill
+
+@node -w Option,  , Options/Recursion, Recursion
+@subsection The @samp{--print-directory} Option
+@cindex directories, printing them
+@cindex printing directories
+@cindex recursion, and printing directories
+
+If you use several levels of recursive @code{make} invocations, the
+@samp{-w} or @w{@samp{--print-directory}} option can make the output a
+lot easier to understand by showing each directory as @code{make}
+starts processing it and as @code{make} finishes processing it.  For
+example, if @samp{make -w} is run in the directory @file{/u/gnu/make},
+@code{make} will print a line of the form:@refill
+
+@example
+make: Entering directory `/u/gnu/make'.
+@end example
+
+@noindent
+before doing anything else, and a line of the form:
+
+@example
+make: Leaving directory `/u/gnu/make'.
+@end example
+
+@noindent
+when processing is completed.
+
+@cindex @code{-C}, and @code{-w}
+@cindex @code{--directory}, and @code{--print-directory}
+@cindex recursion, and @code{-w}
+@cindex @code{-w}, and @code{-C}
+@cindex @code{-w}, and recursion
+@cindex @code{--print-directory}, and @code{--directory}
+@cindex @code{--print-directory}, and recursion
+@cindex @code{--no-print-directory}
+@cindex @code{--print-directory}, disabling
+@cindex @code{-w}, disabling
+Normally, you do not need to specify this option because @samp{make}
+does it for you: @samp{-w} is turned on automatically when you use the
+@samp{-C} option, and in sub-@code{make}s.  @code{make} will not
+automatically turn on @samp{-w} if you also use @samp{-s}, which says to
+be silent, or if you use @samp{--no-print-directory} to explicitly
+disable it.
+
+@node Sequences, Empty Commands, Recursion, Commands
+@section Defining Canned Command Sequences
+@cindex sequences of commands
+@cindex commands, sequences of
+
+When the same sequence of commands is useful in making various targets, you
+can define it as a canned sequence with the @code{define} directive, and
+refer to the canned sequence from the rules for those targets.  The canned
+sequence is actually a variable, so the name must not conflict with other
+variable names.
+
+Here is an example of defining a canned sequence of commands:
+
+@example
+define run-yacc
+yacc $(firstword $^)
+mv y.tab.c $@@
+endef
+@end example
+@cindex @code{yacc}
+
+@noindent
+Here @code{run-yacc} is the name of the variable being defined;
+@code{endef} marks the end of the definition; the lines in between are the
+commands.  The @code{define} directive does not expand variable references
+and function calls in the canned sequence; the @samp{$} characters,
+parentheses, variable names, and so on, all become part of the value of the
+variable you are defining.
+@xref{Defining, ,Defining Variables Verbatim},
+for a complete explanation of @code{define}.
+
+The first command in this example runs Yacc on the first prerequisite of
+whichever rule uses the canned sequence.  The output file from Yacc is
+always named @file{y.tab.c}.  The second command moves the output to the
+rule's target file name.
+
+To use the canned sequence, substitute the variable into the commands of a
+rule.  You can substitute it like any other variable
+(@pxref{Reference, ,Basics of Variable References}).
+Because variables defined by @code{define} are recursively expanded
+variables, all the variable references you wrote inside the @code{define}
+are expanded now.  For example:
+
+@example
+foo.c : foo.y
+        $(run-yacc)
+@end example
+
+@noindent
+@samp{foo.y} will be substituted for the variable @samp{$^} when it occurs in
+@code{run-yacc}'s value, and @samp{foo.c} for @samp{$@@}.@refill
+
+This is a realistic example, but this particular one is not needed in
+practice because @code{make} has an implicit rule to figure out these
+commands based on the file names involved
+(@pxref{Implicit Rules, ,Using Implicit Rules}).
+
+@cindex @@, and @code{define}
+@cindex -, and @code{define}
+@cindex +, and @code{define}
+In command execution, each line of a canned sequence is treated just as
+if the line appeared on its own in the rule, preceded by a tab.  In
+particular, @code{make} invokes a separate subshell for each line.  You
+can use the special prefix characters that affect command lines
+(@samp{@@}, @samp{-}, and @samp{+}) on each line of a canned sequence.
+@xref{Commands, ,Writing the Commands in Rules}.
+For example, using this canned sequence:
+
+@example
+define frobnicate
+@@echo "frobnicating target $@@"
+frob-step-1 $< -o $@@-step-1
+frob-step-2 $@@-step-1 -o $@@
+endef
+@end example
+
+@noindent
+@code{make} will not echo the first line, the @code{echo} command.
+But it @emph{will} echo the following two command lines.
+
+On the other hand, prefix characters on the command line that refers to
+a canned sequence apply to every line in the sequence.  So the rule:
+
+@example
+frob.out: frob.in
+        @@$(frobnicate)
+@end example
+
+@noindent
+does not echo @emph{any} commands.
+(@xref{Echoing, ,Command Echoing}, for a full explanation of @samp{@@}.)
+
+@node Empty Commands,  , Sequences, Commands
+@section Using Empty Commands
+@cindex empty commands
+@cindex commands, empty
+
+It is sometimes useful to define commands which do nothing.  This is done
+simply by giving a command that consists of nothing but whitespace.  For
+example:
+
+@example
+target: ;
+@end example
+
+@noindent
+defines an empty command string for @file{target}.  You could also use a
+line beginning with a tab character to define an empty command string,
+but this would be confusing because such a line looks empty.
+
+@findex .DEFAULT@r{, and empty commands}
+You may be wondering why you would want to define a command string that
+does nothing.  The only reason this is useful is to prevent a target
+from getting implicit commands (from implicit rules or the
+@code{.DEFAULT} special target; @pxref{Implicit Rules} and
+@pxref{Last Resort, ,Defining Last-Resort Default Rules}).@refill
+
+@c !!! another reason is for canonical stamp files:
+@ignore
+@example
+foo: stamp-foo ;
+stamp-foo: foo.in
+        create foo frm foo.in
+        touch $@
+@end example
+@end ignore
+
+You may be inclined to define empty command strings for targets that are
+not actual files, but only exist so that their prerequisites can be
+remade.  However, this is not the best way to do that, because the
+prerequisites may not be remade properly if the target file actually does exist.
+@xref{Phony Targets, ,Phony Targets}, for a better way to do this.
+
+@node Using Variables, Conditionals, Commands, Top
+@chapter How to Use Variables
+@cindex variable
+@cindex value
+@cindex recursive variable expansion
+@cindex simple variable expansion
+
+A @dfn{variable} is a name defined in a makefile to represent a string
+of text, called the variable's @dfn{value}.  These values are
+substituted by explicit request into targets, prerequisites, commands,
+and other parts of the makefile.  (In some other versions of @code{make},
+variables are called @dfn{macros}.)
+@cindex macro
+
+Variables and functions in all parts of a makefile are expanded when
+read, except for the shell commands in rules, the right-hand sides of
+variable definitions using @samp{=}, and the bodies of variable
+definitions using the @code{define} directive.@refill
+
+Variables can represent lists of file names, options to pass to compilers,
+programs to run, directories to look in for source files, directories to
+write output in, or anything else you can imagine.
+
+A variable name may be any sequence of characters not containing @samp{:},
+@samp{#}, @samp{=}, or leading or trailing whitespace.  However,
+variable names containing characters other than letters, numbers, and
+underscores should be avoided, as they may be given special meanings in the
+future, and with some shells they cannot be passed through the environment to a
+sub-@code{make}
+(@pxref{Variables/Recursion, ,Communicating Variables to a Sub-@code{make}}).
+
+Variable names are case-sensitive.  The names @samp{foo}, @samp{FOO},
+and @samp{Foo} all refer to different variables.
+
+It is traditional to use upper case letters in variable names, but we
+recommend using lower case letters for variable names that serve internal
+purposes in the makefile, and reserving upper case for parameters that
+control implicit rules or for parameters that the user should override with
+command options (@pxref{Overriding, ,Overriding Variables}).
+
+A few variables have names that are a single punctuation character or
+just a few characters.  These are the @dfn{automatic variables}, and
+they have particular specialized uses.  @xref{Automatic Variables}.
+
+@menu
+* Reference::                   How to use the value of a variable.
+* Flavors::                     Variables come in two flavors.
+* Advanced::                    Advanced features for referencing a variable.
+* Values::                      All the ways variables get their values.
+* Setting::                     How to set a variable in the makefile.
+* Appending::                   How to append more text to the old value
+                                  of a variable.
+* Override Directive::          How to set a variable in the makefile even if
+                                  the user has set it with a command argument.
+* Defining::                    An alternate way to set a variable
+                                  to a verbatim string.
+* Environment::                 Variable values can come from the environment.
+* Target-specific::             Variable values can be defined on a per-target
+                                  basis.
+* Pattern-specific::            Target-specific variable values can be applied
+                                  to a group of targets that match a pattern.
+@end menu
+
+@node Reference, Flavors, Using Variables, Using Variables
+@section Basics of Variable References
+@cindex variables, how to reference
+@cindex reference to variables
+@cindex @code{$}, in variable reference
+@cindex dollar sign (@code{$}), in variable reference
+
+To substitute a variable's value, write a dollar sign followed by the name
+of the variable in parentheses or braces: either @samp{$(foo)} or
+@samp{$@{foo@}} is a valid reference to the variable @code{foo}.  This
+special significance of @samp{$} is why you must write @samp{$$} to have
+the effect of a single dollar sign in a file name or command.
+
+Variable references can be used in any context: targets, prerequisites,
+commands, most directives, and new variable values.  Here is an
+example of a common case, where a variable holds the names of all the
+object files in a program:
+
+@example
+@group
+objects = program.o foo.o utils.o
+program : $(objects)
+        cc -o program $(objects)
+
+$(objects) : defs.h
+@end group
+@end example
+
+Variable references work by strict textual substitution.  Thus, the rule
+
+@example
+@group
+foo = c
+prog.o : prog.$(foo)
+        $(foo)$(foo) -$(foo) prog.$(foo)
+@end group
+@end example
+
+@noindent
+could be used to compile a C program @file{prog.c}.  Since spaces before
+the variable value are ignored in variable assignments, the value of
+@code{foo} is precisely @samp{c}.  (Don't actually write your makefiles
+this way!)
+
+A dollar sign followed by a character other than a dollar sign,
+open-parenthesis or open-brace treats that single character as the
+variable name.  Thus, you could reference the variable @code{x} with
+@samp{$x}.  However, this practice is strongly discouraged, except in
+the case of the automatic variables (@pxref{Automatic Variables}).
+
+@node Flavors, Advanced, Reference, Using Variables
+@section The Two Flavors of Variables
+@cindex flavors of variables
+@cindex recursive variable expansion
+@cindex variables, flavors
+@cindex recursively expanded variables
+@cindex variables, recursively expanded
+
+There are two ways that a variable in GNU @code{make} can have a value;
+we call them the two @dfn{flavors} of variables.  The two flavors are
+distinguished in how they are defined and in what they do when expanded.
+
+@cindex =
+The first flavor of variable is a @dfn{recursively expanded} variable.
+Variables of this sort are defined by lines using @samp{=}
+(@pxref{Setting, ,Setting Variables}) or by the @code{define} directive
+(@pxref{Defining, ,Defining Variables Verbatim}).  The value you specify
+is installed verbatim; if it contains references to other variables,
+these references are expanded whenever this variable is substituted (in
+the course of expanding some other string).  When this happens, it is
+called @dfn{recursive expansion}.@refill
+
+For example,
+
+@example
+foo = $(bar)
+bar = $(ugh)
+ugh = Huh?
+
+all:;echo $(foo)
+@end example
+
+@noindent
+will echo @samp{Huh?}: @samp{$(foo)} expands to @samp{$(bar)} which
+expands to @samp{$(ugh)} which finally expands to @samp{Huh?}.@refill
+
+This flavor of variable is the only sort supported by other versions of
+@code{make}.  It has its advantages and its disadvantages.  An advantage
+(most would say) is that:
+
+@example
+CFLAGS = $(include_dirs) -O
+include_dirs = -Ifoo -Ibar
+@end example
+
+@noindent
+will do what was intended: when @samp{CFLAGS} is expanded in a command,
+it will expand to @samp{-Ifoo -Ibar -O}.  A major disadvantage is that you
+cannot append something on the end of a variable, as in
+
+@example
+CFLAGS = $(CFLAGS) -O
+@end example
+
+@noindent
+because it will cause an infinite loop in the variable expansion.
+(Actually @code{make} detects the infinite loop and reports an error.)
+@cindex loops in variable expansion
+@cindex variables, loops in expansion
+
+Another disadvantage is that any functions
+(@pxref{Functions, ,Functions for Transforming Text})
+referenced in the definition will be executed every time the variable is
+expanded.  This makes @code{make} run slower; worse, it causes the
+@code{wildcard} and @code{shell} functions to give unpredictable results
+because you cannot easily control when they are called, or even how many
+times.
+
+To avoid all the problems and inconveniences of recursively expanded
+variables, there is another flavor: simply expanded variables.
+
+@cindex simply expanded variables
+@cindex variables, simply expanded
+@cindex :=
+@dfn{Simply expanded variables} are defined by lines using @samp{:=}
+(@pxref{Setting, ,Setting Variables}).
+The value of a simply expanded variable is scanned
+once and for all, expanding any references to other variables and
+functions, when the variable is defined.  The actual value of the simply
+expanded variable is the result of expanding the text that you write.
+It does not contain any references to other variables; it contains their
+values @emph{as of the time this variable was defined}.  Therefore,
+
+@example
+x := foo
+y := $(x) bar
+x := later
+@end example
+
+@noindent
+is equivalent to
+
+@example
+y := foo bar
+x := later
+@end example
+
+When a simply expanded variable is referenced, its value is substituted
+verbatim.
+
+Here is a somewhat more complicated example, illustrating the use of
+@samp{:=} in conjunction with the @code{shell} function.
+(@xref{Shell Function, , The @code{shell} Function}.)  This example
+also shows use of the variable @code{MAKELEVEL}, which is changed
+when it is passed down from level to level.
+(@xref{Variables/Recursion, , Communicating Variables to a
+Sub-@code{make}}, for information about @code{MAKELEVEL}.)
+
+@vindex MAKELEVEL
+@vindex MAKE
+@example
+@group
+ifeq (0,$@{MAKELEVEL@})
+whoami    := $(shell whoami)
+host-type := $(shell arch)
+MAKE := $@{MAKE@} host-type=$@{host-type@} whoami=$@{whoami@}
+endif
+@end group
+@end example
+
+@noindent
+An advantage of this use of @samp{:=} is that a typical
+`descend into a directory' command then looks like this:
+
+@example
+@group
+$@{subdirs@}:
+        $@{MAKE@} -C $@@ all
+@end group
+@end example
+
+Simply expanded variables generally make complicated makefile programming
+more predictable because they work like variables in most programming
+languages.  They allow you to redefine a variable using its own value (or
+its value processed in some way by one of the expansion functions) and to
+use the expansion functions much more efficiently
+(@pxref{Functions, ,Functions for Transforming Text}).
+
+@cindex spaces, in variable values
+@cindex whitespace, in variable values
+@cindex variables, spaces in values
+You can also use them to introduce controlled leading whitespace into
+variable values.  Leading whitespace characters are discarded from your
+input before substitution of variable references and function calls;
+this means you can include leading spaces in a variable value by
+protecting them with variable references, like this:
+
+@example
+nullstring :=
+space := $(nullstring) # end of the line
+@end example
+
+@noindent
+Here the value of the variable @code{space} is precisely one space.  The
+comment @w{@samp{# end of the line}} is included here just for clarity.
+Since trailing space characters are @emph{not} stripped from variable
+values, just a space at the end of the line would have the same effect
+(but be rather hard to read).  If you put whitespace at the end of a
+variable value, it is a good idea to put a comment like that at the end
+of the line to make your intent clear.  Conversely, if you do @emph{not}
+want any whitespace characters at the end of your variable value, you
+must remember not to put a random comment on the end of the line after
+some whitespace, such as this:
+
+@example
+dir := /foo/bar    # directory to put the frobs in
+@end example
+
+@noindent
+Here the value of the variable @code{dir} is @w{@samp{/foo/bar    }}
+(with four trailing spaces), which was probably not the intention.
+(Imagine something like @w{@samp{$(dir)/file}} with this definition!)
+
+@cindex conditional variable assignment
+@cindex variables, conditional assignment
+@cindex ?=
+There is another assignment operator for variables, @samp{?=}.  This
+is called a conditional variable assignment operator, because it only
+has an effect if the variable is not yet defined.  This statement:
+
+@example
+FOO ?= bar
+@end example
+
+@noindent
+is exactly equivalent to this
+(@pxref{Origin Function, ,The @code{origin} Function}):
+
+@example
+ifeq ($(origin FOO), undefined)
+  FOO = bar
+endif
+@end example
+
+Note that a variable set to an empty value is still defined, so
+@samp{?=} will not set that variable.
+
+@node Advanced, Values, Flavors, Using Variables
+@section Advanced Features for Reference to Variables
+@cindex reference to variables
+
+This section describes some advanced features you can use to reference
+variables in more flexible ways.
+
+@menu
+* Substitution Refs::           Referencing a variable with
+                                  substitutions on the value.
+* Computed Names::              Computing the name of the variable to refer to.
+@end menu
+
+@node Substitution Refs, Computed Names, Advanced, Advanced
+@subsection Substitution References
+@cindex modified variable reference
+@cindex substitution variable reference
+@cindex variables, modified reference
+@cindex variables, substitution reference
+
+@cindex variables, substituting suffix in
+@cindex suffix, substituting in variables
+A @dfn{substitution reference} substitutes the value of a variable with
+alterations that you specify.  It has the form
+@samp{$(@var{var}:@var{a}=@var{b})} (or
+@samp{$@{@var{var}:@var{a}=@var{b}@}}) and its meaning is to take the value
+of the variable @var{var}, replace every @var{a} at the end of a word with
+@var{b} in that value, and substitute the resulting string.
+
+When we say ``at the end of a word'', we mean that @var{a} must appear
+either followed by whitespace or at the end of the value in order to be
+replaced; other occurrences of @var{a} in the value are unaltered.  For
+example:@refill
+
+@example
+foo := a.o b.o c.o
+bar := $(foo:.o=.c)
+@end example
+
+@noindent
+sets @samp{bar} to @samp{a.c b.c c.c}.  @xref{Setting, ,Setting Variables}.
+
+A substitution reference is actually an abbreviation for use of the
+@code{patsubst} expansion function (@pxref{Text Functions, ,Functions for String Substitution and Analysis}).  We provide
+substitution references as well as @code{patsubst} for compatibility with
+other implementations of @code{make}.
+
+@findex patsubst
+Another type of substitution reference lets you use the full power of
+the @code{patsubst} function.  It has the same form
+@samp{$(@var{var}:@var{a}=@var{b})} described above, except that now
+@var{a} must contain a single @samp{%} character.  This case is
+equivalent to @samp{$(patsubst @var{a},@var{b},$(@var{var}))}.
+@xref{Text Functions, ,Functions for String Substitution and Analysis},
+for a description of the @code{patsubst} function.@refill
+
+@example
+@group
+@exdent For example:
+
+foo := a.o b.o c.o
+bar := $(foo:%.o=%.c)
+@end group
+@end example
+
+@noindent
+sets @samp{bar} to @samp{a.c b.c c.c}.
+
+@node Computed Names,  , Substitution Refs, Advanced
+@subsection Computed Variable Names
+@cindex nested variable reference
+@cindex computed variable name
+@cindex variables, computed names
+@cindex variables, nested references
+@cindex variables, @samp{$} in name
+@cindex @code{$}, in variable name
+@cindex dollar sign (@code{$}), in variable name
+
+Computed variable names are a complicated concept needed only for
+sophisticated makefile programming.  For most purposes you need not
+consider them, except to know that making a variable with a dollar sign
+in its name might have strange results.  However, if you are the type
+that wants to understand everything, or you are actually interested in
+what they do, read on.
+
+Variables may be referenced inside the name of a variable.  This is
+called a @dfn{computed variable name} or a @dfn{nested variable
+reference}.  For example,
+
+@example
+x = y
+y = z
+a := $($(x))
+@end example
+
+@noindent
+defines @code{a} as @samp{z}: the @samp{$(x)} inside @samp{$($(x))} expands
+to @samp{y}, so @samp{$($(x))} expands to @samp{$(y)} which in turn expands
+to @samp{z}.  Here the name of the variable to reference is not stated
+explicitly; it is computed by expansion of @samp{$(x)}.  The reference
+@samp{$(x)} here is nested within the outer variable reference.
+
+The previous example shows two levels of nesting, but any number of levels
+is possible.  For example, here are three levels:
+
+@example
+x = y
+y = z
+z = u
+a := $($($(x)))
+@end example
+
+@noindent
+Here the innermost @samp{$(x)} expands to @samp{y}, so @samp{$($(x))}
+expands to @samp{$(y)} which in turn expands to @samp{z}; now we have
+@samp{$(z)}, which becomes @samp{u}.
+
+References to recursively-expanded variables within a variable name are
+reexpanded in the usual fashion.  For example:
+
+@example
+x = $(y)
+y = z
+z = Hello
+a := $($(x))
+@end example
+
+@noindent
+defines @code{a} as @samp{Hello}: @samp{$($(x))} becomes @samp{$($(y))}
+which becomes @samp{$(z)} which becomes @samp{Hello}.
+
+Nested variable references can also contain modified references and
+function invocations (@pxref{Functions, ,Functions for Transforming Text}),
+just like any other reference.
+For example, using the @code{subst} function
+(@pxref{Text Functions, ,Functions for String Substitution and Analysis}):
+
+@example
+@group
+x = variable1
+variable2 := Hello
+y = $(subst 1,2,$(x))
+z = y
+a := $($($(z)))
+@end group
+@end example
+
+@noindent
+eventually defines @code{a} as @samp{Hello}.  It is doubtful that anyone
+would ever want to write a nested reference as convoluted as this one, but
+it works: @samp{$($($(z)))} expands to @samp{$($(y))} which becomes
+@samp{$($(subst 1,2,$(x)))}.  This gets the value @samp{variable1} from
+@code{x} and changes it by substitution to @samp{variable2}, so that the
+entire string becomes @samp{$(variable2)}, a simple variable reference
+whose value is @samp{Hello}.@refill
+
+A computed variable name need not consist entirely of a single variable
+reference.  It can contain several variable references, as well as some
+invariant text.  For example,
+
+@example
+@group
+a_dirs := dira dirb
+1_dirs := dir1 dir2
+@end group
+
+@group
+a_files := filea fileb
+1_files := file1 file2
+@end group
+
+@group
+ifeq "$(use_a)" "yes"
+a1 := a
+else
+a1 := 1
+endif
+@end group
+
+@group
+ifeq "$(use_dirs)" "yes"
+df := dirs
+else
+df := files
+endif
+
+dirs := $($(a1)_$(df))
+@end group
+@end example
+
+@noindent
+will give @code{dirs} the same value as @code{a_dirs}, @code{1_dirs},
+@code{a_files} or @code{1_files} depending on the settings of @code{use_a}
+and @code{use_dirs}.@refill
+
+Computed variable names can also be used in substitution references:
+
+@example
+@group
+a_objects := a.o b.o c.o
+1_objects := 1.o 2.o 3.o
+
+sources := $($(a1)_objects:.o=.c)
+@end group
+@end example
+
+@noindent
+defines @code{sources} as either @samp{a.c b.c c.c} or @samp{1.c 2.c 3.c},
+depending on the value of @code{a1}.
+
+The only restriction on this sort of use of nested variable references
+is that they cannot specify part of the name of a function to be called.
+This is because the test for a recognized function name is done before
+the expansion of nested references.  For example,
+
+@example
+@group
+ifdef do_sort
+func := sort
+else
+func := strip
+endif
+@end group
+
+@group
+bar := a d b g q c
+@end group
+
+@group
+foo := $($(func) $(bar))
+@end group
+@end example
+
+@noindent
+attempts to give @samp{foo} the value of the variable @samp{sort a d b g
+q c} or @samp{strip a d b g q c}, rather than giving @samp{a d b g q c}
+as the argument to either the @code{sort} or the @code{strip} function.
+This restriction could be removed in the future if that change is shown
+to be a good idea.
+
+You can also use computed variable names in the left-hand side of a
+variable assignment, or in a @code{define} directive, as in:
+
+@example
+dir = foo
+$(dir)_sources := $(wildcard $(dir)/*.c)
+define $(dir)_print
+lpr $($(dir)_sources)
+endef
+@end example
+
+@noindent
+This example defines the variables @samp{dir}, @samp{foo_sources}, and
+@samp{foo_print}.
+
+Note that @dfn{nested variable references} are quite different from
+@dfn{recursively expanded variables}
+(@pxref{Flavors, ,The Two Flavors of Variables}), though both are
+used together in complex ways when doing makefile programming.@refill
+
+@node Values, Setting, Advanced, Using Variables
+@section How Variables Get Their Values
+@cindex variables, how they get their values
+@cindex value, how a variable gets it
+
+Variables can get values in several different ways:
+
+@itemize @bullet
+@item
+You can specify an overriding value when you run @code{make}.
+@xref{Overriding, ,Overriding Variables}.
+
+@item
+You can specify a value in the makefile, either
+with an assignment (@pxref{Setting, ,Setting Variables}) or with a
+verbatim definition (@pxref{Defining, ,Defining Variables Verbatim}).@refill
+
+@item
+Variables in the environment become @code{make} variables.
+@xref{Environment, ,Variables from the Environment}.
+
+@item
+Several @dfn{automatic} variables are given new values for each rule.
+Each of these has a single conventional use.
+@xref{Automatic Variables}.
+
+@item
+Several variables have constant initial values.
+@xref{Implicit Variables, ,Variables Used by Implicit Rules}.
+@end itemize
+
+@node Setting, Appending, Values, Using Variables
+@section Setting Variables
+@cindex setting variables
+@cindex variables, setting
+@cindex =
+@cindex :=
+@cindex ?=
+
+To set a variable from the makefile, write a line starting with the
+variable name followed by @samp{=} or @samp{:=}.  Whatever follows the
+@samp{=} or @samp{:=} on the line becomes the value.  For example,
+
+@example
+objects = main.o foo.o bar.o utils.o
+@end example
+
+@noindent
+defines a variable named @code{objects}.  Whitespace around the variable
+name and immediately after the @samp{=} is ignored.
+
+Variables defined with @samp{=} are @dfn{recursively expanded} variables.
+Variables defined with @samp{:=} are @dfn{simply expanded} variables; these
+definitions can contain variable references which will be expanded before
+the definition is made.  @xref{Flavors, ,The Two Flavors of Variables}.
+
+The variable name may contain function and variable references, which
+are expanded when the line is read to find the actual variable name to use.
+
+There is no limit on the length of the value of a variable except the
+amount of swapping space on the computer.  When a variable definition is
+long, it is a good idea to break it into several lines by inserting
+backslash-newline at convenient places in the definition.  This will not
+affect the functioning of @code{make}, but it will make the makefile easier
+to read.
+
+Most variable names are considered to have the empty string as a value if
+you have never set them.  Several variables have built-in initial values
+that are not empty, but you can set them in the usual ways
+(@pxref{Implicit Variables, ,Variables Used by Implicit Rules}).
+Several special variables are set
+automatically to a new value for each rule; these are called the
+@dfn{automatic} variables (@pxref{Automatic Variables}).
+
+If you'd like a variable to be set to a value only if it's not already
+set, then you can use the shorthand operator @samp{?=} instead of
+@samp{=}.  These two settings of the variable @samp{FOO} are identical
+(@pxref{Origin Function, ,The @code{origin} Function}):
+
+@example
+FOO ?= bar
+@end example
+
+@noindent
+and
+
+@example
+ifeq ($(origin FOO), undefined)
+FOO = bar
+endif
+@end example
+
+@node Appending, Override Directive, Setting, Using Variables
+@section Appending More Text to Variables
+@cindex +=
+@cindex appending to variables
+@cindex variables, appending to
+
+Often it is useful to add more text to the value of a variable already defined.
+You do this with a line containing @samp{+=}, like this:
+
+@example
+objects += another.o
+@end example
+
+@noindent
+This takes the value of the variable @code{objects}, and adds the text
+@samp{another.o} to it (preceded by a single space).  Thus:
+
+@example
+objects = main.o foo.o bar.o utils.o
+objects += another.o
+@end example
+
+@noindent
+sets @code{objects} to @samp{main.o foo.o bar.o utils.o another.o}.
+
+Using @samp{+=} is similar to:
+
+@example
+objects = main.o foo.o bar.o utils.o
+objects := $(objects) another.o
+@end example
+
+@noindent
+but differs in ways that become important when you use more complex values.
+
+When the variable in question has not been defined before, @samp{+=}
+acts just like normal @samp{=}: it defines a recursively-expanded
+variable.  However, when there @emph{is} a previous definition, exactly
+what @samp{+=} does depends on what flavor of variable you defined
+originally.  @xref{Flavors, ,The Two Flavors of Variables}, for an
+explanation of the two flavors of variables.
+
+When you add to a variable's value with @samp{+=}, @code{make} acts
+essentially as if you had included the extra text in the initial
+definition of the variable.  If you defined it first with @samp{:=},
+making it a simply-expanded variable, @samp{+=} adds to that
+simply-expanded definition, and expands the new text before appending it
+to the old value just as @samp{:=} does
+(see @ref{Setting, ,Setting Variables}, for a full explanation of @samp{:=}).
+In fact,
+
+@example
+variable := value
+variable += more
+@end example
+
+@noindent
+is exactly equivalent to:
+
+@noindent
+@example
+variable := value
+variable := $(variable) more
+@end example
+
+On the other hand, when you use @samp{+=} with a variable that you defined
+first to be recursively-expanded using plain @samp{=}, @code{make} does
+something a bit different.  Recall that when you define a
+recursively-expanded variable, @code{make} does not expand the value you set
+for variable and function references immediately.  Instead it stores the text
+verbatim, and saves these variable and function references to be expanded
+later, when you refer to the new variable (@pxref{Flavors, ,The Two Flavors
+of Variables}).  When you use @samp{+=} on a recursively-expanded variable,
+it is this unexpanded text to which @code{make} appends the new text you
+specify.
+
+@example
+@group
+variable = value
+variable += more
+@end group
+@end example
+
+@noindent
+is roughly equivalent to:
+
+@example
+@group
+temp = value
+variable = $(temp) more
+@end group
+@end example
+
+@noindent
+except that of course it never defines a variable called @code{temp}.
+The importance of this comes when the variable's old value contains
+variable references.  Take this common example:
+
+@example
+CFLAGS = $(includes) -O
+@dots{}
+CFLAGS += -pg # enable profiling
+@end example
+
+@noindent
+The first line defines the @code{CFLAGS} variable with a reference to another
+variable, @code{includes}.  (@code{CFLAGS} is used by the rules for C
+compilation; @pxref{Catalogue of Rules, ,Catalogue of Implicit Rules}.)
+Using @samp{=} for the definition makes @code{CFLAGS} a recursively-expanded
+variable, meaning @w{@samp{$(includes) -O}} is @emph{not} expanded when
+@code{make} processes the definition of @code{CFLAGS}.  Thus, @code{includes}
+need not be defined yet for its value to take effect.  It only has to be
+defined before any reference to @code{CFLAGS}.  If we tried to append to the
+value of @code{CFLAGS} without using @samp{+=}, we might do it like this:
+
+@example
+CFLAGS := $(CFLAGS) -pg # enable profiling
+@end example
+
+@noindent
+This is pretty close, but not quite what we want.  Using @samp{:=}
+redefines @code{CFLAGS} as a simply-expanded variable; this means
+@code{make} expands the text @w{@samp{$(CFLAGS) -pg}} before setting the
+variable.  If @code{includes} is not yet defined, we get @w{@samp{ -O
+-pg}}, and a later definition of @code{includes} will have no effect.
+Conversely, by using @samp{+=} we set @code{CFLAGS} to the
+@emph{unexpanded} value @w{@samp{$(includes) -O -pg}}.  Thus we preserve
+the reference to @code{includes}, so if that variable gets defined at
+any later point, a reference like @samp{$(CFLAGS)} still uses its
+value.
+
+@node Override Directive, Defining, Appending, Using Variables
+@section The @code{override} Directive
+@findex override
+@cindex overriding with @code{override}
+@cindex variables, overriding
+
+If a variable has been set with a command argument
+(@pxref{Overriding, ,Overriding Variables}),
+then ordinary assignments in the makefile are ignored.  If you want to set
+the variable in the makefile even though it was set with a command
+argument, you can use an @code{override} directive, which is a line that
+looks like this:@refill
+
+@example
+override @var{variable} = @var{value}
+@end example
+
+@noindent
+or
+
+@example
+override @var{variable} := @var{value}
+@end example
+
+To append more text to a variable defined on the command line, use:
+
+@example
+override @var{variable} += @var{more text}
+@end example
+
+@noindent
+@xref{Appending, ,Appending More Text to Variables}.
+
+The @code{override} directive was not invented for escalation in the war
+between makefiles and command arguments.  It was invented so you can alter
+and add to values that the user specifies with command arguments.
+
+For example, suppose you always want the @samp{-g} switch when you run the
+C compiler, but you would like to allow the user to specify the other
+switches with a command argument just as usual.  You could use this
+@code{override} directive:
+
+@example
+override CFLAGS += -g
+@end example
+
+You can also use @code{override} directives with @code{define} directives.
+This is done as you might expect:
+
+@example
+override define foo
+bar
+endef
+@end example
+
+@noindent
+@iftex
+See the next section for information about @code{define}.
+@end iftex
+@ifnottex
+@xref{Defining, ,Defining Variables Verbatim}.
+@end ifnottex
+
+@node Defining, Environment, Override Directive, Using Variables
+@section Defining Variables Verbatim
+@findex define
+@findex endef
+@cindex verbatim variable definition
+@cindex defining variables verbatim
+@cindex variables, defining verbatim
+
+Another way to set the value of a variable is to use the @code{define}
+directive.  This directive has an unusual syntax which allows newline
+characters to be included in the value, which is convenient for defining
+both canned sequences of commands
+(@pxref{Sequences, ,Defining Canned Command Sequences}), and also
+sections of makefile syntax to use with @code{eval} (@pxref{Eval Function}).
+
+The @code{define} directive is followed on the same line by the name of the
+variable and nothing more.  The value to give the variable appears on the
+following lines.  The end of the value is marked by a line containing just
+the word @code{endef}.  Aside from this difference in syntax, @code{define}
+works just like @samp{=}: it creates a recursively-expanded variable
+(@pxref{Flavors, ,The Two Flavors of Variables}).
+The variable name may contain function and variable references, which
+are expanded when the directive is read to find the actual variable name
+to use.
+
+You may nest @code{define} directives: @code{make} will keep track of
+nested directives and report an error if they are not all properly
+closed with @code{endef}.  Note that lines beginning with tab
+characters are considered part of a command script, so any
+@code{define} or @code{endef} strings appearing on such a line will
+not be considered @code{make} operators.
+
+@example
+define two-lines
+echo foo
+echo $(bar)
+endef
+@end example
+
+The value in an ordinary assignment cannot contain a newline; but the
+newlines that separate the lines of the value in a @code{define} become
+part of the variable's value (except for the final newline which precedes
+the @code{endef} and is not considered part of the value).@refill
+
+@need 800
+When used in a command script, the previous example is functionally
+equivalent to this:
+
+@example
+two-lines = echo foo; echo $(bar)
+@end example
+
+@noindent
+since two commands separated by semicolon behave much like two separate
+shell commands.  However, note that using two separate lines means
+@code{make} will invoke the shell twice, running an independent subshell
+for each line.  @xref{Execution, ,Command Execution}.
+
+If you want variable definitions made with @code{define} to take
+precedence over command-line variable definitions, you can use the
+@code{override} directive together with @code{define}:
+
+@example
+override define two-lines
+foo
+$(bar)
+endef
+@end example
+
+@noindent
+@xref{Override Directive, ,The @code{override} Directive}.
+
+@node Environment, Target-specific, Defining, Using Variables
+@section Variables from the Environment
+
+@cindex variables, environment
+@cindex environment
+Variables in @code{make} can come from the environment in which
+@code{make} is run.  Every environment variable that @code{make} sees
+when it starts up is transformed into a @code{make} variable with the
+same name and value.  However, an explicit assignment in the makefile,
+or with a command argument, overrides the environment.  (If the
+@samp{-e} flag is specified, then values from the environment override
+assignments in the makefile.  @xref{Options Summary, ,Summary of
+Options}.  But this is not recommended practice.)
+
+Thus, by setting the variable @code{CFLAGS} in your environment, you can
+cause all C compilations in most makefiles to use the compiler switches you
+prefer.  This is safe for variables with standard or conventional meanings
+because you know that no makefile will use them for other things.  (Note
+this is not totally reliable; some makefiles set @code{CFLAGS} explicitly
+and therefore are not affected by the value in the environment.)
+
+When @code{make} runs a command script, variables defined in the
+makefile are placed into the environment of that command.  This allows
+you to pass values to sub-@code{make} invocations (@pxref{Recursion,
+,Recursive Use of @code{make}}).  By default, only variables that came
+from the environment or the command line are passed to recursive
+invocations.  You can use the @code{export} directive to pass other
+variables.  @xref{Variables/Recursion, , Communicating Variables to a
+Sub-@code{make}}, for full details.
+
+Other use of variables from the environment is not recommended.  It is not
+wise for makefiles to depend for their functioning on environment variables
+set up outside their control, since this would cause different users to get
+different results from the same makefile.  This is against the whole
+purpose of most makefiles.
+
+@cindex SHELL, import from environment
+Such problems would be especially likely with the variable
+@code{SHELL}, which is normally present in the environment to specify
+the user's choice of interactive shell.  It would be very undesirable
+for this choice to affect @code{make}; so, @code{make} handles the
+@code{SHELL} environment variable in a special way; see @ref{Choosing
+the Shell}.@refill
+
+@node Target-specific, Pattern-specific, Environment, Using Variables
+@section Target-specific Variable Values
+@cindex target-specific variables
+@cindex variables, target-specific
+
+Variable values in @code{make} are usually global; that is, they are the
+same regardless of where they are evaluated (unless they're reset, of
+course).  One exception to that is automatic variables
+(@pxref{Automatic Variables}).
+
+The other exception is @dfn{target-specific variable values}.  This
+feature allows you to define different values for the same variable,
+based on the target that @code{make} is currently building.  As with
+automatic variables, these values are only available within the context
+of a target's command script (and in other target-specific assignments).
+
+Set a target-specific variable value like this:
+
+@example
+@var{target} @dots{} : @var{variable-assignment}
+@end example
+
+@noindent
+or like this:
+
+@example
+@var{target} @dots{} : override @var{variable-assignment}
+@end example
+
+@noindent
+or like this:
+
+@example
+@var{target} @dots{} : export @var{variable-assignment}
+@end example
+
+Multiple @var{target} values create a target-specific variable value for
+each member of the target list individually.
+
+The @var{variable-assignment} can be any valid form of assignment;
+recursive (@samp{=}), static (@samp{:=}), appending (@samp{+=}), or
+conditional (@samp{?=}).  All variables that appear within the
+@var{variable-assignment} are evaluated within the context of the
+target: thus, any previously-defined target-specific variable values
+will be in effect.  Note that this variable is actually distinct from
+any ``global'' value: the two variables do not have to have the same
+flavor (recursive vs.@: static).
+
+Target-specific variables have the same priority as any other makefile
+variable.  Variables provided on the command-line (and in the
+environment if the @samp{-e} option is in force) will take precedence.
+Specifying the @code{override} directive will allow the target-specific
+variable value to be preferred.
+
+There is one more special feature of target-specific variables: when
+you define a target-specific variable that variable value is also in
+effect for all prerequisites of this target, and all their
+prerequisites, etc.@: (unless those prerequisites override that variable
+with their own target-specific variable value).  So, for example, a
+statement like this:
+
+@example
+prog : CFLAGS = -g
+prog : prog.o foo.o bar.o
+@end example
+
+@noindent
+will set @code{CFLAGS} to @samp{-g} in the command script for
+@file{prog}, but it will also set @code{CFLAGS} to @samp{-g} in the
+command scripts that create @file{prog.o}, @file{foo.o}, and
+@file{bar.o}, and any command scripts which create their
+prerequisites.
+
+Be aware that a given prerequisite will only be built once per
+invocation of make, at most.  If the same file is a prerequisite of
+multiple targets, and each of those targets has a different value for
+the same target-specific variable, then the first target to be built
+will cause that prerequisite to be built and the prerequisite will
+inherit the target-specific value from the first target.  It will
+ignore the target-specific values from any other targets.
+
+@node Pattern-specific,  , Target-specific, Using Variables
+@section Pattern-specific Variable Values
+@cindex pattern-specific variables
+@cindex variables, pattern-specific
+
+In addition to target-specific variable values
+(@pxref{Target-specific, ,Target-specific Variable Values}), GNU
+@code{make} supports pattern-specific variable values.  In this form,
+the variable is defined for any target that matches the pattern
+specified.  If a target matches more than one pattern, all the
+matching pattern-specific variables are interpreted in the order in
+which they were defined in the makefile, and collected together into
+one set.  Variables defined in this way are searched after any
+target-specific variables defined explicitly for that target, and
+before target-specific variables defined for the parent target.
+
+Set a pattern-specific variable value like this:
+
+@example
+@var{pattern} @dots{} : @var{variable-assignment}
+@end example
+
+@noindent
+or like this:
+
+@example
+@var{pattern} @dots{} : override @var{variable-assignment}
+@end example
+
+@noindent
+where @var{pattern} is a %-pattern.  As with target-specific variable
+values, multiple @var{pattern} values create a pattern-specific variable
+value for each pattern individually.  The @var{variable-assignment} can
+be any valid form of assignment.  Any command-line variable setting will
+take precedence, unless @code{override} is specified.
+
+For example:
+
+@example
+%.o : CFLAGS = -O
+@end example
+
+@noindent
+will assign @code{CFLAGS} the value of @samp{-O} for all targets
+matching the pattern @code{%.o}.
+
+@node Conditionals, Functions, Using Variables, Top
+@chapter Conditional Parts of Makefiles
+
+@cindex conditionals
+A @dfn{conditional} causes part of a makefile to be obeyed or ignored
+depending on the values of variables.  Conditionals can compare the
+value of one variable to another, or the value of a variable to
+a constant string.  Conditionals control what @code{make} actually
+``sees'' in the makefile, so they @emph{cannot} be used to control shell
+commands at the time of execution.@refill
+
+@menu
+* Conditional Example::         Example of a conditional
+* Conditional Syntax::          The syntax of conditionals.
+* Testing Flags::               Conditionals that test flags.
+@end menu
+
+@node Conditional Example, Conditional Syntax, Conditionals, Conditionals
+@section Example of a Conditional
+
+The following example of a conditional tells @code{make} to use one set
+of libraries if the @code{CC} variable is @samp{gcc}, and a different
+set of libraries otherwise.  It works by controlling which of two
+command lines will be used as the command for a rule.  The result is
+that @samp{CC=gcc} as an argument to @code{make} changes not only which
+compiler is used but also which libraries are linked.
+
+@example
+libs_for_gcc = -lgnu
+normal_libs =
+
+foo: $(objects)
+ifeq ($(CC),gcc)
+        $(CC) -o foo $(objects) $(libs_for_gcc)
+else
+        $(CC) -o foo $(objects) $(normal_libs)
+endif
+@end example
+
+This conditional uses three directives: one @code{ifeq}, one @code{else}
+and one @code{endif}.
+
+The @code{ifeq} directive begins the conditional, and specifies the
+condition.  It contains two arguments, separated by a comma and surrounded
+by parentheses.  Variable substitution is performed on both arguments and
+then they are compared.  The lines of the makefile following the
+@code{ifeq} are obeyed if the two arguments match; otherwise they are
+ignored.
+
+The @code{else} directive causes the following lines to be obeyed if the
+previous conditional failed.  In the example above, this means that the
+second alternative linking command is used whenever the first alternative
+is not used.  It is optional to have an @code{else} in a conditional.
+
+The @code{endif} directive ends the conditional.  Every conditional must
+end with an @code{endif}.  Unconditional makefile text follows.
+
+As this example illustrates, conditionals work at the textual level:
+the lines of the conditional are treated as part of the makefile, or
+ignored, according to the condition.  This is why the larger syntactic
+units of the makefile, such as rules, may cross the beginning or the
+end of the conditional.
+
+When the variable @code{CC} has the value @samp{gcc}, the above example has
+this effect:
+
+@example
+foo: $(objects)
+        $(CC) -o foo $(objects) $(libs_for_gcc)
+@end example
+
+@noindent
+When the variable @code{CC} has any other value, the effect is this:
+
+@example
+foo: $(objects)
+        $(CC) -o foo $(objects) $(normal_libs)
+@end example
+
+Equivalent results can be obtained in another way by conditionalizing a
+variable assignment and then using the variable unconditionally:
+
+@example
+libs_for_gcc = -lgnu
+normal_libs =
+
+ifeq ($(CC),gcc)
+  libs=$(libs_for_gcc)
+else
+  libs=$(normal_libs)
+endif
+
+foo: $(objects)
+        $(CC) -o foo $(objects) $(libs)
+@end example
+
+@node Conditional Syntax, Testing Flags, Conditional Example, Conditionals
+@section Syntax of Conditionals
+@findex ifdef
+@findex ifeq
+@findex ifndef
+@findex ifneq
+@findex else
+@findex endif
+
+The syntax of a simple conditional with no @code{else} is as follows:
+
+@example
+@var{conditional-directive}
+@var{text-if-true}
+endif
+@end example
+
+@noindent
+The @var{text-if-true} may be any lines of text, to be considered as part
+of the makefile if the condition is true.  If the condition is false, no
+text is used instead.
+
+The syntax of a complex conditional is as follows:
+
+@example
+@var{conditional-directive}
+@var{text-if-true}
+else
+@var{text-if-false}
+endif
+@end example
+
+or:
+
+@example
+@var{conditional-directive}
+@var{text-if-one-is-true}
+else @var{conditional-directive}
+@var{text-if-true}
+else
+@var{text-if-false}
+endif
+@end example
+
+@noindent
+There can be as many ``@code{else} @var{conditional-directive}''
+clauses as necessary.  Once a given condition is true,
+@var{text-if-true} is used and no other clause is used; if no
+condition is true then @var{text-if-false} is used.  The
+@var{text-if-true} and @var{text-if-false} can be any number of lines
+of text.
+
+The syntax of the @var{conditional-directive} is the same whether the
+conditional is simple or complex; after an @code{else} or not.  There
+are four different directives that test different conditions.  Here is
+a table of them:
+
+@table @code
+@item ifeq (@var{arg1}, @var{arg2})
+@itemx ifeq '@var{arg1}' '@var{arg2}'
+@itemx ifeq "@var{arg1}" "@var{arg2}"
+@itemx ifeq "@var{arg1}" '@var{arg2}'
+@itemx ifeq '@var{arg1}' "@var{arg2}"
+Expand all variable references in @var{arg1} and @var{arg2} and
+compare them.  If they are identical, the @var{text-if-true} is
+effective; otherwise, the @var{text-if-false}, if any, is effective.
+
+Often you want to test if a variable has a non-empty value.  When the
+value results from complex expansions of variables and functions,
+expansions you would consider empty may actually contain whitespace
+characters and thus are not seen as empty.  However, you can use the
+@code{strip} function (@pxref{Text Functions}) to avoid interpreting
+whitespace as a non-empty value.  For example:
+
+@example
+@group
+ifeq ($(strip $(foo)),)
+@var{text-if-empty}
+endif
+@end group
+@end example
+
+@noindent
+will evaluate @var{text-if-empty} even if the expansion of
+@code{$(foo)} contains whitespace characters.
+
+@item ifneq (@var{arg1}, @var{arg2})
+@itemx ifneq '@var{arg1}' '@var{arg2}'
+@itemx ifneq "@var{arg1}" "@var{arg2}"
+@itemx ifneq "@var{arg1}" '@var{arg2}'
+@itemx ifneq '@var{arg1}' "@var{arg2}"
+Expand all variable references in @var{arg1} and @var{arg2} and
+compare them.  If they are different, the @var{text-if-true} is
+effective; otherwise, the @var{text-if-false}, if any, is effective.
+
+@item ifdef @var{variable-name}
+The @code{ifdef} form takes the @emph{name} of a variable as its
+argument, not a reference to a variable.  The value of that variable
+has a non-empty value, the @var{text-if-true} is effective; otherwise,
+the @var{text-if-false}, if any, is effective.  Variables that have
+never been defined have an empty value.  The text @var{variable-name}
+is expanded, so it could be a variable or function that expands
+to the name of a variable.  For example:
+
+@example
+bar = true
+foo = bar
+ifdef $(foo)
+frobozz = yes
+endif
+@end example
+
+The variable reference @code{$(foo)} is expanded, yielding @code{bar},
+which is considered to be the name of a variable.  The variable
+@code{bar} is not expanded, but its value is examined to determine if
+it is non-empty.
+
+Note that @code{ifdef} only tests whether a variable has a value.  It
+does not expand the variable to see if that value is nonempty.
+Consequently, tests using @code{ifdef} return true for all definitions
+except those like @code{foo =}.  To test for an empty value, use
+@w{@code{ifeq ($(foo),)}}.  For example,
+
+@example
+bar =
+foo = $(bar)
+ifdef foo
+frobozz = yes
+else
+frobozz = no
+endif
+@end example
+
+@noindent
+sets @samp{frobozz} to @samp{yes}, while:
+
+@example
+foo =
+ifdef foo
+frobozz = yes
+else
+frobozz = no
+endif
+@end example
+
+@noindent
+sets @samp{frobozz} to @samp{no}.
+
+@item ifndef @var{variable-name}
+If the variable @var{variable-name} has an empty value, the
+@var{text-if-true} is effective; otherwise, the @var{text-if-false},
+if any, is effective.  The rules for expansion and testing of
+@var{variable-name} are identical to the @code{ifdef} directive.
+@end table
+
+Extra spaces are allowed and ignored at the beginning of the conditional
+directive line, but a tab is not allowed.  (If the line begins with a tab,
+it will be considered a command for a rule.)  Aside from this, extra spaces
+or tabs may be inserted with no effect anywhere except within the directive
+name or within an argument.  A comment starting with @samp{#} may appear at
+the end of the line.
+
+The other two directives that play a part in a conditional are @code{else}
+and @code{endif}.  Each of these directives is written as one word, with no
+arguments.  Extra spaces are allowed and ignored at the beginning of the
+line, and spaces or tabs at the end.  A comment starting with @samp{#} may
+appear at the end of the line.
+
+Conditionals affect which lines of the makefile @code{make} uses.  If
+the condition is true, @code{make} reads the lines of the
+@var{text-if-true} as part of the makefile; if the condition is false,
+@code{make} ignores those lines completely.  It follows that syntactic
+units of the makefile, such as rules, may safely be split across the
+beginning or the end of the conditional.@refill
+
+@code{make} evaluates conditionals when it reads a makefile.
+Consequently, you cannot use automatic variables in the tests of
+conditionals because they are not defined until commands are run
+(@pxref{Automatic Variables}).
+
+To prevent intolerable confusion, it is not permitted to start a
+conditional in one makefile and end it in another.  However, you may
+write an @code{include} directive within a conditional, provided you do
+not attempt to terminate the conditional inside the included file.
+
+@node Testing Flags,  , Conditional Syntax, Conditionals
+@section Conditionals that Test Flags
+
+You can write a conditional that tests @code{make} command flags such as
+@samp{-t} by using the variable @code{MAKEFLAGS} together with the
+@code{findstring} function
+(@pxref{Text Functions, , Functions for String Substitution and Analysis}).
+This is useful when @code{touch} is not enough to make a file appear up
+to date.
+
+The @code{findstring} function determines whether one string appears as a
+substring of another.  If you want to test for the @samp{-t} flag,
+use @samp{t} as the first string and the value of @code{MAKEFLAGS} as
+the other.
+
+For example, here is how to arrange to use @samp{ranlib -t} to finish
+marking an archive file up to date:
+
+@example
+archive.a: @dots{}
+ifneq (,$(findstring t,$(MAKEFLAGS)))
+        +touch archive.a
+        +ranlib -t archive.a
+else
+        ranlib archive.a
+endif
+@end example
+
+@noindent
+The @samp{+} prefix marks those command lines as ``recursive'' so
+that they will be executed despite use of the @samp{-t} flag.
+@xref{Recursion, ,Recursive Use of @code{make}}.
+
+@node Functions, Running, Conditionals, Top
+@chapter Functions for Transforming Text
+@cindex functions
+
+@dfn{Functions} allow you to do text processing in the makefile to compute
+the files to operate on or the commands to use.  You use a function in a
+@dfn{function call}, where you give the name of the function and some text
+(the @dfn{arguments}) for the function to operate on.  The result of the
+function's processing is substituted into the makefile at the point of the
+call, just as a variable might be substituted.
+
+@menu
+* Syntax of Functions::         How to write a function call.
+* Text Functions::              General-purpose text manipulation functions.
+* File Name Functions::         Functions for manipulating file names.
+* Conditional Functions::       Functions that implement conditions.
+* Foreach Function::            Repeat some text with controlled variation.
+* Call Function::               Expand a user-defined function.
+* Value Function::              Return the un-expanded value of a variable.
+* Eval Function::               Evaluate the arguments as makefile syntax.
+* Origin Function::             Find where a variable got its value.
+* Flavor Function::             Find out the flavor of a variable.
+* Shell Function::              Substitute the output of a shell command.
+* Make Control Functions::      Functions that control how make runs.
+@end menu
+
+@node Syntax of Functions, Text Functions, Functions, Functions
+@section Function Call Syntax
+@cindex @code{$}, in function call
+@cindex dollar sign (@code{$}), in function call
+@cindex arguments of functions
+@cindex functions, syntax of
+
+A function call resembles a variable reference.  It looks like this:
+
+@example
+$(@var{function} @var{arguments})
+@end example
+
+@noindent
+or like this:
+
+@example
+$@{@var{function} @var{arguments}@}
+@end example
+
+Here @var{function} is a function name; one of a short list of names
+that are part of @code{make}.  You can also essentially create your own
+functions by using the @code{call} builtin function.
+
+The @var{arguments} are the arguments of the function.  They are
+separated from the function name by one or more spaces or tabs, and if
+there is more than one argument, then they are separated by commas.
+Such whitespace and commas are not part of an argument's value.  The
+delimiters which you use to surround the function call, whether
+parentheses or braces, can appear in an argument only in matching pairs;
+the other kind of delimiters may appear singly.  If the arguments
+themselves contain other function calls or variable references, it is
+wisest to use the same kind of delimiters for all the references; write
+@w{@samp{$(subst a,b,$(x))}}, not @w{@samp{$(subst a,b,$@{x@})}}.  This
+is because it is clearer, and because only one type of delimiter is
+matched to find the end of the reference.
+
+The text written for each argument is processed by substitution of
+variables and function calls to produce the argument value, which
+is the text on which the function acts.  The substitution is done in the
+order in which the arguments appear.
+
+Commas and unmatched parentheses or braces cannot appear in the text of an
+argument as written; leading spaces cannot appear in the text of the first
+argument as written.  These characters can be put into the argument value
+by variable substitution.  First define variables @code{comma} and
+@code{space} whose values are isolated comma and space characters, then
+substitute these variables where such characters are wanted, like this:
+
+@example
+@group
+comma:= ,
+empty:=
+space:= $(empty) $(empty)
+foo:= a b c
+bar:= $(subst $(space),$(comma),$(foo))
+# @r{bar is now `a,b,c'.}
+@end group
+@end example
+
+@noindent
+Here the @code{subst} function replaces each space with a comma, through
+the value of @code{foo}, and substitutes the result.
+
+@node Text Functions, File Name Functions, Syntax of Functions, Functions
+@section Functions for String Substitution and Analysis
+@cindex functions, for text
+
+Here are some functions that operate on strings:
+
+@table @code
+@item $(subst @var{from},@var{to},@var{text})
+@findex subst
+Performs a textual replacement on the text @var{text}: each occurrence
+of @var{from} is replaced by @var{to}.  The result is substituted for
+the function call.  For example,
+
+@example
+$(subst ee,EE,feet on the street)
+@end example
+
+substitutes the string @samp{fEEt on the strEEt}.
+
+@item $(patsubst @var{pattern},@var{replacement},@var{text})
+@findex patsubst
+Finds whitespace-separated words in @var{text} that match
+@var{pattern} and replaces them with @var{replacement}.  Here
+@var{pattern} may contain a @samp{%} which acts as a wildcard,
+matching any number of any characters within a word.  If
+@var{replacement} also contains a @samp{%}, the @samp{%} is replaced
+by the text that matched the @samp{%} in @var{pattern}.  Only the first
+@samp{%} in the @var{pattern} and @var{replacement} is treated this
+way; any subsequent @samp{%} is unchanged.@refill
+
+@cindex @code{%}, quoting in @code{patsubst}
+@cindex @code{%}, quoting with @code{\} (backslash)
+@cindex @code{\} (backslash), to quote @code{%}
+@cindex backslash (@code{\}), to quote @code{%}
+@cindex quoting @code{%}, in @code{patsubst}
+@samp{%} characters in @code{patsubst} function invocations can be
+quoted with preceding backslashes (@samp{\}).  Backslashes that would
+otherwise quote @samp{%} characters can be quoted with more backslashes.
+Backslashes that quote @samp{%} characters or other backslashes are
+removed from the pattern before it is compared file names or has a stem
+substituted into it.  Backslashes that are not in danger of quoting
+@samp{%} characters go unmolested.  For example, the pattern
+@file{the\%weird\\%pattern\\} has @samp{the%weird\} preceding the
+operative @samp{%} character, and @samp{pattern\\} following it.  The
+final two backslashes are left alone because they cannot affect any
+@samp{%} character.@refill
+
+Whitespace between words is folded into single space characters;
+leading and trailing whitespace is discarded.
+
+For example,
+
+@example
+$(patsubst %.c,%.o,x.c.c bar.c)
+@end example
+
+@noindent
+produces the value @samp{x.c.o bar.o}.
+
+Substitution references (@pxref{Substitution Refs, ,Substitution
+References}) are a simpler way to get the effect of the @code{patsubst}
+function:
+
+@example
+$(@var{var}:@var{pattern}=@var{replacement})
+@end example
+
+@noindent
+is equivalent to
+
+@example
+$(patsubst @var{pattern},@var{replacement},$(@var{var}))
+@end example
+
+The second shorthand simplifies one of the most common uses of
+@code{patsubst}: replacing the suffix at the end of file names.
+
+@example
+$(@var{var}:@var{suffix}=@var{replacement})
+@end example
+
+@noindent
+is equivalent to
+
+@example
+$(patsubst %@var{suffix},%@var{replacement},$(@var{var}))
+@end example
+
+@noindent
+For example, you might have a list of object files:
+
+@example
+objects = foo.o bar.o baz.o
+@end example
+
+@noindent
+To get the list of corresponding source files, you could simply write:
+
+@example
+$(objects:.o=.c)
+@end example
+
+@noindent
+instead of using the general form:
+
+@example
+$(patsubst %.o,%.c,$(objects))
+@end example
+
+@item $(strip @var{string})
+@cindex stripping whitespace
+@cindex whitespace, stripping
+@cindex spaces, stripping
+@findex strip
+Removes leading and trailing whitespace from @var{string} and replaces
+each internal sequence of one or more whitespace characters with a
+single space.  Thus, @samp{$(strip a b  c )} results in @w{@samp{a b c}}.
+
+The function @code{strip} can be very useful when used in conjunction
+with conditionals.  When comparing something with the empty string
+@samp{} using @code{ifeq} or @code{ifneq}, you usually want a string of
+just whitespace to match the empty string (@pxref{Conditionals}).
+
+Thus, the following may fail to have the desired results:
+
+@example
+.PHONY: all
+ifneq   "$(needs_made)" ""
+all: $(needs_made)
+else
+all:;@@echo 'Nothing to make!'
+endif
+@end example
+
+@noindent
+Replacing the variable reference @w{@samp{$(needs_made)}} with the
+function call @w{@samp{$(strip $(needs_made))}} in the @code{ifneq}
+directive would make it more robust.@refill
+
+@item $(findstring @var{find},@var{in})
+@findex findstring
+@cindex searching for strings
+@cindex finding strings
+@cindex strings, searching for
+Searches @var{in} for an occurrence of @var{find}.  If it occurs, the
+value is @var{find}; otherwise, the value is empty.  You can use this
+function in a conditional to test for the presence of a specific
+substring in a given string.  Thus, the two examples,
+
+@example
+$(findstring a,a b c)
+$(findstring a,b c)
+@end example
+
+@noindent
+produce the values @samp{a} and @samp{} (the empty string),
+respectively.  @xref{Testing Flags}, for a practical application of
+@code{findstring}.@refill
+
+@need 750
+@findex filter
+@cindex filtering words
+@cindex words, filtering
+@item $(filter @var{pattern}@dots{},@var{text})
+Returns all whitespace-separated words in @var{text} that @emph{do} match
+any of the @var{pattern} words, removing any words that @emph{do not}
+match.  The patterns are written using @samp{%}, just like the patterns
+used in the @code{patsubst} function above.@refill
+
+The @code{filter} function can be used to separate out different types
+of strings (such as file names) in a variable.  For example:
+
+@example
+sources := foo.c bar.c baz.s ugh.h
+foo: $(sources)
+        cc $(filter %.c %.s,$(sources)) -o foo
+@end example
+
+@noindent
+says that @file{foo} depends of @file{foo.c}, @file{bar.c},
+@file{baz.s} and @file{ugh.h} but only @file{foo.c}, @file{bar.c} and
+@file{baz.s} should be specified in the command to the
+compiler.@refill
+
+@item $(filter-out @var{pattern}@dots{},@var{text})
+@findex filter-out
+@cindex filtering out words
+@cindex words, filtering out
+Returns all whitespace-separated words in @var{text} that @emph{do not}
+match any of the @var{pattern} words, removing the words that @emph{do}
+match one or more.  This is the exact opposite of the @code{filter}
+function.@refill
+
+For example, given:
+
+@example
+@group
+objects=main1.o foo.o main2.o bar.o
+mains=main1.o main2.o
+@end group
+@end example
+
+@noindent
+the following generates a list which contains all the object files not
+in @samp{mains}:
+
+@example
+$(filter-out $(mains),$(objects))
+@end example
+
+@need 1500
+@findex sort
+@cindex sorting words
+@item $(sort @var{list})
+Sorts the words of @var{list} in lexical order, removing duplicate
+words.  The output is a list of words separated by single spaces.
+Thus,
+
+@example
+$(sort foo bar lose)
+@end example
+
+@noindent
+returns the value @samp{bar foo lose}.
+
+@cindex removing duplicate words
+@cindex duplicate words, removing
+@cindex words, removing duplicates
+Incidentally, since @code{sort} removes duplicate words, you can use
+it for this purpose even if you don't care about the sort order.
+
+@item $(word @var{n},@var{text})
+@findex word
+@cindex word, selecting a
+@cindex selecting a word
+Returns the @var{n}th word of @var{text}.  The legitimate values of
+@var{n} start from 1.  If @var{n} is bigger than the number of words
+in @var{text}, the value is empty.  For example,
+
+@example
+$(word 2, foo bar baz)
+@end example
+
+@noindent
+returns @samp{bar}.
+
+@item $(wordlist @var{s},@var{e},@var{text})
+@findex wordlist
+@cindex words, selecting lists of
+@cindex selecting word lists
+Returns the list of words in @var{text} starting with word @var{s} and
+ending with word @var{e} (inclusive).  The legitimate values of @var{s}
+start from 1; @var{e} may start from 0.  If @var{s} is bigger than the
+number of words in @var{text}, the value is empty.  If @var{e} is
+bigger than the number of words in @var{text}, words up to the end of
+@var{text} are returned.  If @var{s} is greater than @var{e}, nothing
+is returned.  For example,
+
+@example
+$(wordlist 2, 3, foo bar baz)
+@end example
+
+@noindent
+returns @samp{bar baz}.
+
+@c Following item phrased to prevent overfull hbox.  --RJC 17 Jul 92
+@item $(words @var{text})
+@findex words
+@cindex words, finding number
+Returns the number of words in @var{text}.
+Thus, the last word of @var{text} is
+@w{@code{$(word $(words @var{text}),@var{text})}}.@refill
+
+@item $(firstword @var{names}@dots{})
+@findex firstword
+@cindex words, extracting first
+The argument @var{names} is regarded as a series of names, separated
+by whitespace.  The value is the first name in the series.  The rest
+of the names are ignored.
+
+For example,
+
+@example
+$(firstword foo bar)
+@end example
+
+@noindent
+produces the result @samp{foo}.  Although @code{$(firstword
+@var{text})} is the same as @code{$(word 1,@var{text})}, the
+@code{firstword} function is retained for its simplicity.@refill
+
+
+@item $(lastword @var{names}@dots{})
+@findex lastword
+@cindex words, extracting last
+The argument @var{names} is regarded as a series of names, separated
+by whitespace.  The value is the last name in the series.
+
+For example,
+
+@example
+$(lastword foo bar)
+@end example
+
+@noindent
+produces the result @samp{bar}.  Although @code{$(lastword
+@var{text})} is the same as @code{$(word $(words @var{text}),@var{text})},
+the @code{lastword} function was added for its simplicity and better
+performance.@refill
+@end table
+
+
+Here is a realistic example of the use of @code{subst} and
+@code{patsubst}.  Suppose that a makefile uses the @code{VPATH} variable
+to specify a list of directories that @code{make} should search for
+prerequisite files
+(@pxref{General Search, , @code{VPATH} Search Path for All Prerequisites}).
+This example shows how to
+tell the C compiler to search for header files in the same list of
+directories.@refill
+
+The value of @code{VPATH} is a list of directories separated by colons,
+such as @samp{src:../headers}.  First, the @code{subst} function is used to
+change the colons to spaces:
+
+@example
+$(subst :, ,$(VPATH))
+@end example
+
+@noindent
+This produces @samp{src ../headers}.  Then @code{patsubst} is used to turn
+each directory name into a @samp{-I} flag.  These can be added to the
+value of the variable @code{CFLAGS}, which is passed automatically to the C
+compiler, like this:
+
+@example
+override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH)))
+@end example
+
+@noindent
+The effect is to append the text @samp{-Isrc -I../headers} to the
+previously given value of @code{CFLAGS}.  The @code{override} directive is
+used so that the new value is assigned even if the previous value of
+@code{CFLAGS} was specified with a command argument (@pxref{Override
+Directive, , The @code{override} Directive}).
+
+@node File Name Functions, Conditional Functions, Text Functions, Functions
+@section Functions for File Names
+@cindex functions, for file names
+@cindex file name functions
+
+Several of the built-in expansion functions relate specifically to
+taking apart file names or lists of file names.
+
+Each of the following functions performs a specific transformation on a
+file name.  The argument of the function is regarded as a series of file
+names, separated by whitespace.  (Leading and trailing whitespace is
+ignored.)  Each file name in the series is transformed in the same way and
+the results are concatenated with single spaces between them.
+
+@table @code
+@item $(dir @var{names}@dots{})
+@findex dir
+@cindex directory part
+@cindex file name, directory part
+Extracts the directory-part of each file name in @var{names}.  The
+directory-part of the file name is everything up through (and
+including) the last slash in it.  If the file name contains no slash,
+the directory part is the string @samp{./}.  For example,
+
+@example
+$(dir src/foo.c hacks)
+@end example
+
+@noindent
+produces the result @samp{src/ ./}.
+
+@item $(notdir @var{names}@dots{})
+@findex notdir
+@cindex file name, nondirectory part
+@cindex nondirectory part
+Extracts all but the directory-part of each file name in @var{names}.
+If the file name contains no slash, it is left unchanged.  Otherwise,
+everything through the last slash is removed from it.
+
+A file name that ends with a slash becomes an empty string.  This is
+unfortunate, because it means that the result does not always have the
+same number of whitespace-separated file names as the argument had;
+but we do not see any other valid alternative.
+
+For example,
+
+@example
+$(notdir src/foo.c hacks)
+@end example
+
+@noindent
+produces the result @samp{foo.c hacks}.
+
+@item $(suffix @var{names}@dots{})
+@findex suffix
+@cindex suffix, function to find
+@cindex file name suffix
+Extracts the suffix of each file name in @var{names}.  If the file name
+contains a period, the suffix is everything starting with the last
+period.  Otherwise, the suffix is the empty string.  This frequently
+means that the result will be empty when @var{names} is not, and if
+@var{names} contains multiple file names, the result may contain fewer
+file names.
+
+For example,
+
+@example
+$(suffix src/foo.c src-1.0/bar.c hacks)
+@end example
+
+@noindent
+produces the result @samp{.c .c}.
+
+@item $(basename @var{names}@dots{})
+@findex basename
+@cindex basename
+@cindex file name, basename of
+Extracts all but the suffix of each file name in @var{names}.  If the
+file name contains a period, the basename is everything starting up to
+(and not including) the last period.  Periods in the directory part are
+ignored.  If there is no period, the basename is the entire file name.
+For example,
+
+@example
+$(basename src/foo.c src-1.0/bar hacks)
+@end example
+
+@noindent
+produces the result @samp{src/foo src-1.0/bar hacks}.
+
+@c plural convention with dots (be consistent)
+@item $(addsuffix @var{suffix},@var{names}@dots{})
+@findex addsuffix
+@cindex suffix, adding
+@cindex file name suffix, adding
+The argument @var{names} is regarded as a series of names, separated
+by whitespace; @var{suffix} is used as a unit.  The value of
+@var{suffix} is appended to the end of each individual name and the
+resulting larger names are concatenated with single spaces between
+them.  For example,
+
+@example
+$(addsuffix .c,foo bar)
+@end example
+
+@noindent
+produces the result @samp{foo.c bar.c}.
+
+@item $(addprefix @var{prefix},@var{names}@dots{})
+@findex addprefix
+@cindex prefix, adding
+@cindex file name prefix, adding
+The argument @var{names} is regarded as a series of names, separated
+by whitespace; @var{prefix} is used as a unit.  The value of
+@var{prefix} is prepended to the front of each individual name and the
+resulting larger names are concatenated with single spaces between
+them.  For example,
+
+@example
+$(addprefix src/,foo bar)
+@end example
+
+@noindent
+produces the result @samp{src/foo src/bar}.
+
+@item $(join @var{list1},@var{list2})
+@findex join
+@cindex joining lists of words
+@cindex words, joining lists
+Concatenates the two arguments word by word: the two first words (one
+from each argument) concatenated form the first word of the result, the
+two second words form the second word of the result, and so on.  So the
+@var{n}th word of the result comes from the @var{n}th word of each
+argument.  If one argument has more words that the other, the extra
+words are copied unchanged into the result.
+
+For example, @samp{$(join a b,.c .o)} produces @samp{a.c b.o}.
+
+Whitespace between the words in the lists is not preserved; it is
+replaced with a single space.
+
+This function can merge the results of the @code{dir} and
+@code{notdir} functions, to produce the original list of files which
+was given to those two functions.@refill
+
+@item $(wildcard @var{pattern})
+@findex wildcard
+@cindex wildcard, function
+The argument @var{pattern} is a file name pattern, typically containing
+wildcard characters (as in shell file name patterns).  The result of
+@code{wildcard} is a space-separated list of the names of existing files
+that match the pattern.
+@xref{Wildcards, ,Using Wildcard Characters in File Names}.
+
+@item $(realpath @var{names}@dots{})
+@findex realpath
+@cindex realpath
+@cindex file name, realpath of
+For each file name in @var{names} return the canonical absolute name.
+A canonical name does not contain any @code{.} or @code{..} components,
+nor any repeated path separators (@code{/}) or symlinks.  In case of a
+failure the empty string is returned.  Consult the @code{realpath(3)}
+documentation for a list of possible failure causes.
+
+@item $(abspath @var{names}@dots{})
+@findex abspath
+@cindex abspath
+@cindex file name, abspath of
+For each file name in @var{names} return an absolute name that does
+not contain any @code{.} or @code{..} components, nor any repeated path
+separators (@code{/}).  Note that, in contrast to @code{realpath}
+function, @code{abspath} does not resolve symlinks and does not require
+the file names to refer to an existing file or directory.  Use the
+@code{wildcard} function to test for existence.
+@end table
+
+@node Conditional Functions, Foreach Function, File Name Functions, Functions
+@section Functions for Conditionals
+@findex if
+@cindex conditional expansion
+There are three functions that provide conditional expansion.  A key
+aspect of these functions is that not all of the arguments are
+expanded initially.  Only those arguments which need to be expanded,
+will be expanded.
+
+@table @code
+@item $(if @var{condition},@var{then-part}[,@var{else-part}])
+@findex if
+The @code{if} function provides support for conditional expansion in a
+functional context (as opposed to the GNU @code{make} makefile
+conditionals such as @code{ifeq} (@pxref{Conditional Syntax, ,Syntax of
+Conditionals}).
+
+The first argument, @var{condition}, first has all preceding and
+trailing whitespace stripped, then is expanded.  If it expands to any
+non-empty string, then the condition is considered to be true.  If it
+expands to an empty string, the condition is considered to be false.
+
+If the condition is true then the second argument, @var{then-part}, is
+evaluated and this is used as the result of the evaluation of the entire
+@code{if} function.
+
+If the condition is false then the third argument, @var{else-part}, is
+evaluated and this is the result of the @code{if} function.  If there is
+no third argument, the @code{if} function evaluates to nothing (the
+empty string).
+
+Note that only one of the @var{then-part} or the @var{else-part} will be
+evaluated, never both.  Thus, either can contain side-effects (such as
+@code{shell} function calls, etc.)
+
+@item $(or @var{condition1}[,@var{condition2}[,@var{condition3}@dots{}]])
+@findex or
+The @code{or} function provides a ``short-circuiting'' OR operation.
+Each argument is expanded, in order.  If an argument expands to a
+non-empty string the processing stops and the result of the expansion
+is that string.  If, after all arguments are expanded, all of them are
+false (empty), then the result of the expansion is the empty string.
+
+@item $(and @var{condition1}[,@var{condition2}[,@var{condition3}@dots{}]])
+@findex and
+The @code{and} function provides a ``short-circuiting'' AND operation.
+Each argument is expanded, in order.  If an argument expands to an
+empty string the processing stops and the result of the expansion is
+the empty string.  If all arguments expand to a non-empty string then
+the result of the expansion is the expansion of the last argument.
+
+@end table
+
+@node Foreach Function, Call Function, Conditional Functions, Functions
+@section The @code{foreach} Function
+@findex foreach
+@cindex words, iterating over
+
+The @code{foreach} function is very different from other functions.  It
+causes one piece of text to be used repeatedly, each time with a different
+substitution performed on it.  It resembles the @code{for} command in the
+shell @code{sh} and the @code{foreach} command in the C-shell @code{csh}.
+
+The syntax of the @code{foreach} function is:
+
+@example
+$(foreach @var{var},@var{list},@var{text})
+@end example
+
+@noindent
+The first two arguments, @var{var} and @var{list}, are expanded before
+anything else is done; note that the last argument, @var{text}, is
+@strong{not} expanded at the same time.  Then for each word of the expanded
+value of @var{list}, the variable named by the expanded value of @var{var}
+is set to that word, and @var{text} is expanded.  Presumably @var{text}
+contains references to that variable, so its expansion will be different
+each time.
+
+The result is that @var{text} is expanded as many times as there are
+whitespace-separated words in @var{list}.  The multiple expansions of
+@var{text} are concatenated, with spaces between them, to make the result
+of @code{foreach}.
+
+This simple example sets the variable @samp{files} to the list of all files
+in the directories in the list @samp{dirs}:
+
+@example
+dirs := a b c d
+files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
+@end example
+
+Here @var{text} is @samp{$(wildcard $(dir)/*)}.  The first repetition
+finds the value @samp{a} for @code{dir}, so it produces the same result
+as @samp{$(wildcard a/*)}; the second repetition produces the result
+of @samp{$(wildcard b/*)}; and the third, that of @samp{$(wildcard c/*)}.
+
+This example has the same result (except for setting @samp{dirs}) as
+the following example:
+
+@example
+files := $(wildcard a/* b/* c/* d/*)
+@end example
+
+When @var{text} is complicated, you can improve readability by giving it
+a name, with an additional variable:
+
+@example
+find_files = $(wildcard $(dir)/*)
+dirs := a b c d
+files := $(foreach dir,$(dirs),$(find_files))
+@end example
+
+@noindent
+Here we use the variable @code{find_files} this way.  We use plain @samp{=}
+to define a recursively-expanding variable, so that its value contains an
+actual function call to be reexpanded under the control of @code{foreach};
+a simply-expanded variable would not do, since @code{wildcard} would be
+called only once at the time of defining @code{find_files}.
+
+The @code{foreach} function has no permanent effect on the variable
+@var{var}; its value and flavor after the @code{foreach} function call are
+the same as they were beforehand.  The other values which are taken from
+@var{list} are in effect only temporarily, during the execution of
+@code{foreach}.  The variable @var{var} is a simply-expanded variable
+during the execution of @code{foreach}.  If @var{var} was undefined
+before the @code{foreach} function call, it is undefined after the call.
+@xref{Flavors, ,The Two Flavors of Variables}.@refill
+
+You must take care when using complex variable expressions that result in
+variable names because many strange things are valid variable names, but
+are probably not what you intended.  For example,
+
+@smallexample
+files := $(foreach Esta escrito en espanol!,b c ch,$(find_files))
+@end smallexample
+
+@noindent
+might be useful if the value of @code{find_files} references the variable
+whose name is @samp{Esta escrito en espanol!} (es un nombre bastante largo,
+no?), but it is more likely to be a mistake.
+
+@node Call Function, Value Function, Foreach Function, Functions
+@section The @code{call} Function
+@findex call
+@cindex functions, user defined
+@cindex user defined functions
+
+The @code{call} function is unique in that it can be used to create new
+parameterized functions.  You can write a complex expression as the
+value of a variable, then use @code{call} to expand it with different
+values.
+
+The syntax of the @code{call} function is:
+
+@example
+$(call @var{variable},@var{param},@var{param},@dots{})
+@end example
+
+When @code{make} expands this function, it assigns each @var{param} to
+temporary variables @code{$(1)}, @code{$(2)}, etc.  The variable
+@code{$(0)} will contain @var{variable}.  There is no maximum number of
+parameter arguments.  There is no minimum, either, but it doesn't make
+sense to use @code{call} with no parameters.
+
+Then @var{variable} is expanded as a @code{make} variable in the context
+of these temporary assignments.  Thus, any reference to @code{$(1)} in
+the value of @var{variable} will resolve to the first @var{param} in the
+invocation of @code{call}.
+
+Note that @var{variable} is the @emph{name} of a variable, not a
+@emph{reference} to that variable.  Therefore you would not normally use
+a @samp{$} or parentheses when writing it.  (You can, however, use a
+variable reference in the name if you want the name not to be a
+constant.)
+
+If @var{variable} is the name of a builtin function, the builtin function
+is always invoked (even if a @code{make} variable by that name also
+exists).
+
+The @code{call} function expands the @var{param} arguments before
+assigning them to temporary variables.  This means that @var{variable}
+values containing references to builtin functions that have special
+expansion rules, like @code{foreach} or @code{if}, may not work as you
+expect.
+
+Some examples may make this clearer.
+
+This macro simply reverses its arguments:
+
+@smallexample
+reverse = $(2) $(1)
+
+foo = $(call reverse,a,b)
+@end smallexample
+
+@noindent
+Here @var{foo} will contain @samp{b a}.
+
+This one is slightly more interesting: it defines a macro to search for
+the first instance of a program in @code{PATH}:
+
+@smallexample
+pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
+
+LS := $(call pathsearch,ls)
+@end smallexample
+
+@noindent
+Now the variable LS contains @code{/bin/ls} or similar.
+
+The @code{call} function can be nested.  Each recursive invocation gets
+its own local values for @code{$(1)}, etc.@: that mask the values of
+higher-level @code{call}.  For example, here is an implementation of a
+@dfn{map} function:
+
+@smallexample
+map = $(foreach a,$(2),$(call $(1),$(a)))
+@end smallexample
+
+Now you can @var{map} a function that normally takes only one argument,
+such as @code{origin}, to multiple values in one step:
+
+@smallexample
+o = $(call map,origin,o map MAKE)
+@end smallexample
+
+and end up with @var{o} containing something like @samp{file file default}.
+
+A final caution: be careful when adding whitespace to the arguments to
+@code{call}.  As with other functions, any whitespace contained in the
+second and subsequent arguments is kept; this can cause strange
+effects.  It's generally safest to remove all extraneous whitespace when
+providing parameters to @code{call}.
+
+@node Value Function, Eval Function, Call Function, Functions
+@comment  node-name,  next,  previous,  up
+@section The @code{value} Function
+@findex value
+@cindex variables, unexpanded value
+
+The @code{value} function provides a way for you to use the value of a
+variable @emph{without} having it expanded.  Please note that this
+does not undo expansions which have already occurred; for example if
+you create a simply expanded variable its value is expanded during the
+definition; in that case the @code{value} function will return the
+same result as using the variable directly.
+
+The syntax of the @code{value} function is:
+
+@example
+$(value @var{variable})
+@end example
+
+Note that @var{variable} is the @emph{name} of a variable; not a
+@emph{reference} to that variable.  Therefore you would not normally
+use a @samp{$} or parentheses when writing it.  (You can, however, use
+a variable reference in the name if you want the name not to be a
+constant.)
+
+The result of this function is a string containing the value of
+@var{variable}, without any expansion occurring.  For example, in this
+makefile:
+
+@example
+@group
+FOO = $PATH
+
+all:
+        @@echo $(FOO)
+        @@echo $(value FOO)
+@end group
+@end example
+
+@noindent
+The first output line would be @code{ATH}, since the ``$P'' would be
+expanded as a @code{make} variable, while the second output line would
+be the current value of your @code{$PATH} environment variable, since
+the @code{value} function avoided the expansion.
+
+The @code{value} function is most often used in conjunction with the
+@code{eval} function (@pxref{Eval Function}).
+
+@node Eval Function, Origin Function, Value Function, Functions
+@comment  node-name,  next,  previous,  up
+@section The @code{eval} Function
+@findex eval
+@cindex evaluating makefile syntax
+@cindex makefile syntax, evaluating
+
+The @code{eval} function is very special: it allows you to define new
+makefile constructs that are not constant; which are the result of
+evaluating other variables and functions.  The argument to the
+@code{eval} function is expanded, then the results of that expansion
+are parsed as makefile syntax.  The expanded results can define new
+@code{make} variables, targets, implicit or explicit rules, etc.
+
+The result of the @code{eval} function is always the empty string;
+thus, it can be placed virtually anywhere in a makefile without
+causing syntax errors.
+
+It's important to realize that the @code{eval} argument is expanded
+@emph{twice}; first by the @code{eval} function, then the results of
+that expansion are expanded again when they are parsed as makefile
+syntax.  This means you may need to provide extra levels of escaping
+for ``$'' characters when using @code{eval}.  The @code{value}
+function (@pxref{Value Function}) can sometimes be useful in these
+situations, to circumvent unwanted expansions.
+
+Here is an example of how @code{eval} can be used; this example
+combines a number of concepts and other functions.  Although it might
+seem overly complex to use @code{eval} in this example, rather than
+just writing out the rules, consider two things: first, the template
+definition (in @code{PROGRAM_template}) could need to be much more
+complex than it is here; and second, you might put the complex,
+``generic'' part of this example into another makefile, then include
+it in all the individual makefiles.  Now your individual makefiles are
+quite straightforward.
+
+@example
+@group
+PROGRAMS    = server client
+
+server_OBJS = server.o server_priv.o server_access.o
+server_LIBS = priv protocol
+
+client_OBJS = client.o client_api.o client_mem.o
+client_LIBS = protocol
+
+# Everything after this is generic
+
+.PHONY: all
+all: $(PROGRAMS)
+
+define PROGRAM_template
+ $(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)
+ ALL_OBJS   += $$($(1)_OBJS)
+endef
+
+$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
+
+$(PROGRAMS):
+        $(LINK.o) $^ $(LDLIBS) -o $@@
+
+clean:
+        rm -f $(ALL_OBJS) $(PROGRAMS)
+@end group
+@end example
+
+@node Origin Function, Flavor Function, Eval Function, Functions
+@section The @code{origin} Function
+@findex origin
+@cindex variables, origin of
+@cindex origin of variable
+
+The @code{origin} function is unlike most other functions in that it does
+not operate on the values of variables; it tells you something @emph{about}
+a variable.  Specifically, it tells you where it came from.
+
+The syntax of the @code{origin} function is:
+
+@example
+$(origin @var{variable})
+@end example
+
+Note that @var{variable} is the @emph{name} of a variable to inquire about;
+not a @emph{reference} to that variable.  Therefore you would not normally
+use a @samp{$} or parentheses when writing it.  (You can, however, use a
+variable reference in the name if you want the name not to be a constant.)
+
+The result of this function is a string telling you how the variable
+@var{variable} was defined:
+
+@table @samp
+@item undefined
+
+if @var{variable} was never defined.
+
+@item default
+
+if @var{variable} has a default definition, as is usual with @code{CC}
+and so on.  @xref{Implicit Variables, ,Variables Used by Implicit Rules}.
+Note that if you have redefined a default variable, the @code{origin}
+function will return the origin of the later definition.
+
+@item environment
+
+if @var{variable} was defined as an environment variable and the
+@samp{-e} option is @emph{not} turned on (@pxref{Options Summary, ,Summary of Options}).
+
+@item environment override
+
+if @var{variable} was defined as an environment variable and the
+@w{@samp{-e}} option @emph{is} turned on (@pxref{Options Summary,
+,Summary of Options}).@refill
+
+@item file
+
+if @var{variable} was defined in a makefile.
+
+@item command line
+
+if @var{variable} was defined on the command line.
+
+@item override
+
+if @var{variable} was defined with an @code{override} directive in a
+makefile (@pxref{Override Directive, ,The @code{override} Directive}).
+
+@item automatic
+
+if @var{variable} is an automatic variable defined for the
+execution of the commands for each rule
+(@pxref{Automatic Variables}).
+@end table
+
+This information is primarily useful (other than for your curiosity) to
+determine if you want to believe the value of a variable.  For example,
+suppose you have a makefile @file{foo} that includes another makefile
+@file{bar}.  You want a variable @code{bletch} to be defined in @file{bar}
+if you run the command @w{@samp{make -f bar}}, even if the environment contains
+a definition of @code{bletch}.  However, if @file{foo} defined
+@code{bletch} before including @file{bar}, you do not want to override that
+definition.  This could be done by using an @code{override} directive in
+@file{foo}, giving that definition precedence over the later definition in
+@file{bar}; unfortunately, the @code{override} directive would also
+override any command line definitions.  So, @file{bar} could
+include:@refill
+
+@example
+@group
+ifdef bletch
+ifeq "$(origin bletch)" "environment"
+bletch = barf, gag, etc.
+endif
+endif
+@end group
+@end example
+
+@noindent
+If @code{bletch} has been defined from the environment, this will redefine
+it.
+
+If you want to override a previous definition of @code{bletch} if it came
+from the environment, even under @samp{-e}, you could instead write:
+
+@example
+@group
+ifneq "$(findstring environment,$(origin bletch))" ""
+bletch = barf, gag, etc.
+endif
+@end group
+@end example
+
+Here the redefinition takes place if @samp{$(origin bletch)} returns either
+@samp{environment} or @samp{environment override}.
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@node Flavor Function, Shell Function, Origin Function, Functions
+@section The @code{flavor} Function
+@findex flavor
+@cindex variables, flavor of
+@cindex flavor of variable
+
+The @code{flavor} function is unlike most other functions (and like
+@code{origin} function) in that it does not operate on the values of
+variables; it tells you something @emph{about} a variable.
+Specifically, it tells you the flavor of a variable (@pxref{Flavors,
+,The Two Flavors of Variables}).
+
+The syntax of the @code{flavor} function is:
+
+@example
+$(flavor @var{variable})
+@end example
+
+Note that @var{variable} is the @emph{name} of a variable to inquire about;
+not a @emph{reference} to that variable.  Therefore you would not normally
+use a @samp{$} or parentheses when writing it.  (You can, however, use a
+variable reference in the name if you want the name not to be a constant.)
+
+The result of this function is a string that identifies the flavor of the
+variable @var{variable}:
+
+@table @samp
+@item undefined
+
+if @var{variable} was never defined.
+
+@item recursive
+
+if @var{variable} is a recursively expanded variable.
+
+@item simple
+
+if @var{variable} is a simply expanded variable.
+
+@end table
+
+
+@node Shell Function, Make Control Functions, Flavor Function, Functions
+@section The @code{shell} Function
+@findex shell
+@cindex commands, expansion
+@cindex backquotes
+@cindex shell command, function for
+
+The @code{shell} function is unlike any other function other than the
+@code{wildcard} function
+(@pxref{Wildcard Function, ,The Function @code{wildcard}}) in that it
+communicates with the world outside of @code{make}.
+
+The @code{shell} function performs the same function that backquotes
+(@samp{`}) perform in most shells: it does @dfn{command expansion}.
+This means that it takes as an argument a shell command and evaluates
+to the output of the command.  The only processing @code{make} does on
+the result is to convert each newline (or carriage-return / newline
+pair) to a single space.  If there is a trailing (carriage-return
+and) newline it will simply be removed.@refill
+
+The commands run by calls to the @code{shell} function are run when the
+function calls are expanded (@pxref{Reading Makefiles, , How
+@code{make} Reads a Makefile}).  Because this function involves
+spawning a new shell, you should carefully consider the performance
+implications of using the @code{shell} function within recursively
+expanded variables vs.@: simply expanded variables (@pxref{Flavors, ,The
+Two Flavors of Variables}).
+
+Here are some examples of the use of the @code{shell} function:
+
+@example
+contents := $(shell cat foo)
+@end example
+
+@noindent
+sets @code{contents} to the contents of the file @file{foo}, with a space
+(rather than a newline) separating each line.
+
+@example
+files := $(shell echo *.c)
+@end example
+
+@noindent
+sets @code{files} to the expansion of @samp{*.c}.  Unless @code{make} is
+using a very strange shell, this has the same result as
+@w{@samp{$(wildcard *.c)}} (as long as at least one @samp{.c} file
+exists).@refill
+
+@node Make Control Functions,  , Shell Function, Functions
+@section Functions That Control Make
+@cindex functions, for controlling make
+@cindex controlling make
+
+These functions control the way make runs.  Generally, they are used to
+provide information to the user of the makefile or to cause make to stop
+if some sort of environmental error is detected.
+
+@table @code
+@item $(error @var{text}@dots{})
+@findex error
+@cindex error, stopping on
+@cindex stopping make
+Generates a fatal error where the message is @var{text}.  Note that the
+error is generated whenever this function is evaluated.  So, if you put
+it inside a command script or on the right side of a recursive variable
+assignment, it won't be evaluated until later.  The @var{text} will be
+expanded before the error is generated.
+
+For example,
+
+@example
+ifdef ERROR1
+$(error error is $(ERROR1))
+endif
+@end example
+
+@noindent
+will generate a fatal error during the read of the makefile if the
+@code{make} variable @code{ERROR1} is defined.  Or,
+
+@example
+ERR = $(error found an error!)
+
+.PHONY: err
+err: ; $(ERR)
+@end example
+
+@noindent
+will generate a fatal error while @code{make} is running, if the
+@code{err} target is invoked.
+
+@item $(warning @var{text}@dots{})
+@findex warning
+@cindex warnings, printing
+@cindex printing user warnings
+This function works similarly to the @code{error} function, above,
+except that @code{make} doesn't exit.  Instead, @var{text} is expanded
+and the resulting message is displayed, but processing of the makefile
+continues.
+
+The result of the expansion of this function is the empty string.
+
+@item $(info @var{text}@dots{})
+@findex info
+@cindex printing messages
+This function does nothing more than print its (expanded) argument(s)
+to standard output.  No makefile name or line number is added.  The
+result of the expansion of this function is the empty string.
+@end table
+
+@node Running, Implicit Rules, Functions, Top
+@chapter How to Run @code{make}
+
+A makefile that says how to recompile a program can be used in more
+than one way.  The simplest use is to recompile every file that is out
+of date.  Usually, makefiles are written so that if you run
+@code{make} with no arguments, it does just that.
+
+But you might want to update only some of the files; you might want to use
+a different compiler or different compiler options; you might want just to
+find out which files are out of date without changing them.
+
+By giving arguments when you run @code{make}, you can do any of these
+things and many others.
+
+@cindex exit status of make
+The exit status of @code{make} is always one of three values:
+@table @code
+@item 0
+The exit status is zero if @code{make} is successful.
+@item 2
+The exit status is two if @code{make} encounters any errors.
+It will print messages describing the particular errors.
+@item 1
+The exit status is one if you use the @samp{-q} flag and @code{make}
+determines that some target is not already up to date.
+@xref{Instead of Execution, ,Instead of Executing the Commands}.
+@end table
+
+@menu
+* Makefile Arguments::          How to specify which makefile to use.
+* Goals::                       How to use goal arguments to specify which
+                                  parts of the makefile to use.
+* Instead of Execution::        How to use mode flags to specify what
+                                  kind of thing to do with the commands
+                                  in the makefile other than simply
+                                  execute them.
+* Avoiding Compilation::        How to avoid recompiling certain files.
+* Overriding::                  How to override a variable to specify
+                                  an alternate compiler and other things.
+* Testing::                     How to proceed past some errors, to
+                                  test compilation.
+* Options Summary::             Summary of Options
+@end menu
+
+@node Makefile Arguments, Goals, Running, Running
+@section Arguments to Specify the Makefile
+@cindex @code{--file}
+@cindex @code{--makefile}
+@cindex @code{-f}
+
+The way to specify the name of the makefile is with the @samp{-f} or
+@samp{--file} option (@samp{--makefile} also works).  For example,
+@samp{-f altmake} says to use the file @file{altmake} as the makefile.
+
+If you use the @samp{-f} flag several times and follow each @samp{-f}
+with an argument, all the specified files are used jointly as
+makefiles.
+
+If you do not use the @samp{-f} or @samp{--file} flag, the default is
+to try @file{GNUmakefile}, @file{makefile}, and @file{Makefile}, in
+that order, and use the first of these three which exists or can be made
+(@pxref{Makefiles, ,Writing Makefiles}).@refill
+
+@node Goals, Instead of Execution, Makefile Arguments, Running
+@section Arguments to Specify the Goals
+@cindex goal, how to specify
+
+The @dfn{goals} are the targets that @code{make} should strive ultimately
+to update.  Other targets are updated as well if they appear as
+prerequisites of goals, or prerequisites of prerequisites of goals, etc.
+
+By default, the goal is the first target in the makefile (not counting
+targets that start with a period).  Therefore, makefiles are usually
+written so that the first target is for compiling the entire program or
+programs they describe.  If the first rule in the makefile has several
+targets, only the first target in the rule becomes the default goal, not
+the whole list.  You can manage the selection of the default goal from
+within your makefile using the @code{.DEFAULT_GOAL} variable
+(@pxref{Special Variables, , Other Special Variables}).
+
+You can also specify a different goal or goals with command-line
+arguments to @code{make}.  Use the name of the goal as an argument.
+If you specify several goals, @code{make} processes each of them in
+turn, in the order you name them.
+
+Any target in the makefile may be specified as a goal (unless it
+starts with @samp{-} or contains an @samp{=}, in which case it will be
+parsed as a switch or variable definition, respectively).  Even
+targets not in the makefile may be specified, if @code{make} can find
+implicit rules that say how to make them.
+
+@vindex MAKECMDGOALS
+@code{Make} will set the special variable @code{MAKECMDGOALS} to the
+list of goals you specified on the command line.  If no goals were given
+on the command line, this variable is empty.  Note that this variable
+should be used only in special circumstances.
+
+An example of appropriate use is to avoid including @file{.d} files
+during @code{clean} rules (@pxref{Automatic Prerequisites}), so
+@code{make} won't create them only to immediately remove them
+again:@refill
+
+@example
+@group
+sources = foo.c bar.c
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(sources:.c=.d)
+endif
+@end group
+@end example
+
+One use of specifying a goal is if you want to compile only a part of
+the program, or only one of several programs.  Specify as a goal each
+file that you wish to remake.  For example, consider a directory containing
+several programs, with a makefile that starts like this:
+
+@example
+.PHONY: all
+all: size nm ld ar as
+@end example
+
+If you are working on the program @code{size}, you might want to say
+@w{@samp{make size}} so that only the files of that program are recompiled.
+
+Another use of specifying a goal is to make files that are not normally
+made.  For example, there may be a file of debugging output, or a
+version of the program that is compiled specially for testing, which has
+a rule in the makefile but is not a prerequisite of the default goal.
+
+Another use of specifying a goal is to run the commands associated with
+a phony target (@pxref{Phony Targets}) or empty target (@pxref{Empty
+Targets, ,Empty Target Files to Record Events}).  Many makefiles contain
+a phony target named @file{clean} which deletes everything except source
+files.  Naturally, this is done only if you request it explicitly with
+@w{@samp{make clean}}.  Following is a list of typical phony and empty
+target names.  @xref{Standard Targets}, for a detailed list of all the
+standard target names which GNU software packages use.
+
+@table @file
+@item all
+@cindex @code{all} @r{(standard target)}
+Make all the top-level targets the makefile knows about.
+
+@item clean
+@cindex @code{clean} @r{(standard target)}
+Delete all files that are normally created by running @code{make}.
+
+@item mostlyclean
+@cindex @code{mostlyclean} @r{(standard target)}
+Like @samp{clean}, but may refrain from deleting a few files that people
+normally don't want to recompile.  For example, the @samp{mostlyclean}
+target for GCC does not delete @file{libgcc.a}, because recompiling it
+is rarely necessary and takes a lot of time.
+
+@item distclean
+@cindex @code{distclean} @r{(standard target)}
+@itemx realclean
+@cindex @code{realclean} @r{(standard target)}
+@itemx clobber
+@cindex @code{clobber} @r{(standard target)}
+Any of these targets might be defined to delete @emph{more} files than
+@samp{clean} does.  For example, this would delete configuration files
+or links that you would normally create as preparation for compilation,
+even if the makefile itself cannot create these files.
+
+@item install
+@cindex @code{install} @r{(standard target)}
+Copy the executable file into a directory that users typically search
+for commands; copy any auxiliary files that the executable uses into
+the directories where it will look for them.
+
+@item print
+@cindex @code{print} @r{(standard target)}
+Print listings of the source files that have changed.
+
+@item tar
+@cindex @code{tar} @r{(standard target)}
+Create a tar file of the source files.
+
+@item shar
+@cindex @code{shar} @r{(standard target)}
+Create a shell archive (shar file) of the source files.
+
+@item dist
+@cindex @code{dist} @r{(standard target)}
+Create a distribution file of the source files.  This might
+be a tar file, or a shar file, or a compressed version of one of the
+above, or even more than one of the above.
+
+@item TAGS
+@cindex @code{TAGS} @r{(standard target)}
+Update a tags table for this program.
+
+@item check
+@cindex @code{check} @r{(standard target)}
+@itemx test
+@cindex @code{test} @r{(standard target)}
+Perform self tests on the program this makefile builds.
+@end table
+
+@node Instead of Execution, Avoiding Compilation, Goals, Running
+@section Instead of Executing the Commands
+@cindex execution, instead of
+@cindex commands, instead of executing
+
+The makefile tells @code{make} how to tell whether a target is up to date,
+and how to update each target.  But updating the targets is not always
+what you want.  Certain options specify other activities for @code{make}.
+
+@comment Extra blank lines make it print better.
+@table @samp
+@item -n
+@itemx --just-print
+@itemx --dry-run
+@itemx --recon
+@cindex @code{--just-print}
+@cindex @code{--dry-run}
+@cindex @code{--recon}
+@cindex @code{-n}
+
+``No-op''.  The activity is to print what commands would be used to make
+the targets up to date, but not actually execute them.
+
+@item -t
+@itemx --touch
+@cindex @code{--touch}
+@cindex touching files
+@cindex target, touching
+@cindex @code{-t}
+
+``Touch''.  The activity is to mark the targets as up to date without
+actually changing them.  In other words, @code{make} pretends to compile
+the targets but does not really change their contents.
+
+@item -q
+@itemx --question
+@cindex @code{--question}
+@cindex @code{-q}
+@cindex question mode
+
+``Question''.  The activity is to find out silently whether the targets
+are up to date already; but execute no commands in either case.  In other
+words, neither compilation nor output will occur.
+
+@item -W @var{file}
+@itemx --what-if=@var{file}
+@itemx --assume-new=@var{file}
+@itemx --new-file=@var{file}
+@cindex @code{--what-if}
+@cindex @code{-W}
+@cindex @code{--assume-new}
+@cindex @code{--new-file}
+@cindex what if
+@cindex files, assuming new
+
+``What if''.  Each @samp{-W} flag is followed by a file name.  The given
+files' modification times are recorded by @code{make} as being the present
+time, although the actual modification times remain the same.
+You can use the @samp{-W} flag in conjunction with the @samp{-n} flag
+to see what would happen if you were to modify specific files.@refill
+@end table
+
+With the @samp{-n} flag, @code{make} prints the commands that it would
+normally execute but does not execute them.
+
+With the @samp{-t} flag, @code{make} ignores the commands in the rules
+and uses (in effect) the command @code{touch} for each target that needs to
+be remade.  The @code{touch} command is also printed, unless @samp{-s} or
+@code{.SILENT} is used.  For speed, @code{make} does not actually invoke
+the program @code{touch}.  It does the work directly.
+
+With the @samp{-q} flag, @code{make} prints nothing and executes no
+commands, but the exit status code it returns is zero if and only if the
+targets to be considered are already up to date.  If the exit status is
+one, then some updating needs to be done.  If @code{make} encounters an
+error, the exit status is two, so you can distinguish an error from a
+target that is not up to date.
+
+It is an error to use more than one of these three flags in the same
+invocation of @code{make}.
+
+@cindex +, and command execution
+The @samp{-n}, @samp{-t}, and @samp{-q} options do not affect command
+lines that begin with @samp{+} characters or contain the strings
+@samp{$(MAKE)} or @samp{$@{MAKE@}}.  Note that only the line containing
+the @samp{+} character or the strings @samp{$(MAKE)} or @samp{$@{MAKE@}}
+is run regardless of these options.  Other lines in the same rule are
+not run unless they too begin with @samp{+} or contain @samp{$(MAKE)} or
+@samp{$@{MAKE@}} (@xref{MAKE Variable, ,How the @code{MAKE} Variable Works}.)
+
+The @samp{-W} flag provides two features:
+
+@itemize @bullet
+@item
+If you also use the @samp{-n} or @samp{-q} flag, you can see what
+@code{make} would do if you were to modify some files.
+
+@item
+Without the @samp{-n} or @samp{-q} flag, when @code{make} is actually
+executing commands, the @samp{-W} flag can direct @code{make} to act
+as if some files had been modified, without actually modifying the
+files.@refill
+@end itemize
+
+Note that the options @samp{-p} and @samp{-v} allow you to obtain other
+information about @code{make} or about the makefiles in use
+(@pxref{Options Summary, ,Summary of Options}).@refill
+
+@node Avoiding Compilation, Overriding, Instead of Execution, Running
+@section Avoiding Recompilation of Some Files
+@cindex @code{-o}
+@cindex @code{--old-file}
+@cindex @code{--assume-old}
+@cindex files, assuming old
+@cindex files, avoiding recompilation of
+@cindex recompilation, avoiding
+
+Sometimes you may have changed a source file but you do not want to
+recompile all the files that depend on it.  For example, suppose you add
+a macro or a declaration to a header file that many other files depend
+on.  Being conservative, @code{make} assumes that any change in the
+header file requires recompilation of all dependent files, but you know
+that they do not need to be recompiled and you would rather not waste
+the time waiting for them to compile.
+
+If you anticipate the problem before changing the header file, you can
+use the @samp{-t} flag.  This flag tells @code{make} not to run the
+commands in the rules, but rather to mark the target up to date by
+changing its last-modification date.  You would follow this procedure:
+
+@enumerate
+@item
+Use the command @samp{make} to recompile the source files that really
+need recompilation, ensuring that the object files are up-to-date
+before you begin.
+
+@item
+Make the changes in the header files.
+
+@item
+Use the command @samp{make -t} to mark all the object files as
+up to date.  The next time you run @code{make}, the changes in the
+header files will not cause any recompilation.
+@end enumerate
+
+If you have already changed the header file at a time when some files
+do need recompilation, it is too late to do this.  Instead, you can
+use the @w{@samp{-o @var{file}}} flag, which marks a specified file as
+``old'' (@pxref{Options Summary, ,Summary of Options}).  This means
+that the file itself will not be remade, and nothing else will be
+remade on its account.  Follow this procedure:
+
+@enumerate
+@item
+Recompile the source files that need compilation for reasons independent
+of the particular header file, with @samp{make -o @var{headerfile}}.
+If several header files are involved, use a separate @samp{-o} option
+for each header file.
+
+@item
+Touch all the object files with @samp{make -t}.
+@end enumerate
+
+@node Overriding, Testing, Avoiding Compilation, Running
+@section Overriding Variables
+@cindex overriding variables with arguments
+@cindex variables, overriding with arguments
+@cindex command line variables
+@cindex variables, command line
+
+An argument that contains @samp{=} specifies the value of a variable:
+@samp{@var{v}=@var{x}} sets the value of the variable @var{v} to @var{x}.
+If you specify a value in this way, all ordinary assignments of the same
+variable in the makefile are ignored; we say they have been
+@dfn{overridden} by the command line argument.
+
+The most common way to use this facility is to pass extra flags to
+compilers.  For example, in a properly written makefile, the variable
+@code{CFLAGS} is included in each command that runs the C compiler, so a
+file @file{foo.c} would be compiled something like this:
+
+@example
+cc -c $(CFLAGS) foo.c
+@end example
+
+Thus, whatever value you set for @code{CFLAGS} affects each compilation
+that occurs.  The makefile probably specifies the usual value for
+@code{CFLAGS}, like this:
+
+@example
+CFLAGS=-g
+@end example
+
+Each time you run @code{make}, you can override this value if you
+wish.  For example, if you say @samp{make CFLAGS='-g -O'}, each C
+compilation will be done with @samp{cc -c -g -O}.  (This also
+illustrates how you can use quoting in the shell to enclose spaces and
+other special characters in the value of a variable when you override
+it.)
+
+The variable @code{CFLAGS} is only one of many standard variables that
+exist just so that you can change them this way.  @xref{Implicit
+Variables, , Variables Used by Implicit Rules}, for a complete list.
+
+You can also program the makefile to look at additional variables of your
+own, giving the user the ability to control other aspects of how the
+makefile works by changing the variables.
+
+When you override a variable with a command argument, you can define either
+a recursively-expanded variable or a simply-expanded variable.  The
+examples shown above make a recursively-expanded variable; to make a
+simply-expanded variable, write @samp{:=} instead of @samp{=}.  But, unless
+you want to include a variable reference or function call in the
+@emph{value} that you specify, it makes no difference which kind of
+variable you create.
+
+There is one way that the makefile can change a variable that you have
+overridden.  This is to use the @code{override} directive, which is a line
+that looks like this: @samp{override @var{variable} = @var{value}}
+(@pxref{Override Directive, ,The @code{override} Directive}).
+
+@node Testing, Options Summary, Overriding, Running
+@section Testing the Compilation of a Program
+@cindex testing compilation
+@cindex compilation, testing
+
+Normally, when an error happens in executing a shell command, @code{make}
+gives up immediately, returning a nonzero status.  No further commands are
+executed for any target.  The error implies that the goal cannot be
+correctly remade, and @code{make} reports this as soon as it knows.
+
+When you are compiling a program that you have just changed, this is not
+what you want.  Instead, you would rather that @code{make} try compiling
+every file that can be tried, to show you as many compilation errors
+as possible.
+
+@cindex @code{-k}
+@cindex @code{--keep-going}
+On these occasions, you should use the @samp{-k} or
+@samp{--keep-going} flag.  This tells @code{make} to continue to
+consider the other prerequisites of the pending targets, remaking them
+if necessary, before it gives up and returns nonzero status.  For
+example, after an error in compiling one object file, @samp{make -k}
+will continue compiling other object files even though it already
+knows that linking them will be impossible.  In addition to continuing
+after failed shell commands, @samp{make -k} will continue as much as
+possible after discovering that it does not know how to make a target
+or prerequisite file.  This will always cause an error message, but
+without @samp{-k}, it is a fatal error (@pxref{Options Summary,
+,Summary of Options}).@refill
+
+The usual behavior of @code{make} assumes that your purpose is to get the
+goals up to date; once @code{make} learns that this is impossible, it might
+as well report the failure immediately.  The @samp{-k} flag says that the
+real purpose is to test as much as possible of the changes made in the
+program, perhaps to find several independent problems so that you can
+correct them all before the next attempt to compile.  This is why Emacs'
+@kbd{M-x compile} command passes the @samp{-k} flag by default.
+
+@node Options Summary,  , Testing, Running
+@section Summary of Options
+@cindex options
+@cindex flags
+@cindex switches
+
+Here is a table of all the options @code{make} understands:
+
+@table @samp
+@item -b
+@cindex @code{-b}
+@itemx -m
+@cindex @code{-m}
+These options are ignored for compatibility with other versions of @code{make}.
+
+@item -B
+@cindex @code{-B}
+@itemx --always-make
+@cindex @code{--always-make}
+Consider all targets out-of-date.  GNU @code{make} proceeds to
+consider targets and their prerequisites using the normal algorithms;
+however, all targets so considered are always remade regardless of the
+status of their prerequisites.  To avoid infinite recursion, if
+@code{MAKE_RESTARTS} (@pxref{Special Variables, , Other Special
+Variables}) is set to a number greater than 0 this option is disabled
+when considering whether to remake makefiles (@pxref{Remaking
+Makefiles, , How Makefiles Are Remade}).
+
+@item -C @var{dir}
+@cindex @code{-C}
+@itemx --directory=@var{dir}
+@cindex @code{--directory}
+Change to directory @var{dir} before reading the makefiles.  If multiple
+@samp{-C} options are specified, each is interpreted relative to the
+previous one: @samp{-C / -C etc} is equivalent to @samp{-C /etc}.
+This is typically used with recursive invocations of @code{make}
+(@pxref{Recursion, ,Recursive Use of @code{make}}).
+
+@item -d
+@cindex @code{-d}
+@c Extra blank line here makes the table look better.
+
+Print debugging information in addition to normal processing.  The
+debugging information says which files are being considered for
+remaking, which file-times are being compared and with what results,
+which files actually need to be remade, which implicit rules are
+considered and which are applied---everything interesting about how
+@code{make} decides what to do.  The @code{-d} option is equivalent to
+@samp{--debug=a} (see below).
+
+@item --debug[=@var{options}]
+@cindex @code{--debug}
+@c Extra blank line here makes the table look better.
+
+Print debugging information in addition to normal processing.  Various
+levels and types of output can be chosen.  With no arguments, print the
+``basic'' level of debugging.  Possible arguments are below; only the
+first character is considered, and values must be comma- or
+space-separated.
+
+@table @code
+@item a (@i{all})
+All types of debugging output are enabled.  This is equivalent to using
+@samp{-d}.
+
+@item b (@i{basic})
+Basic debugging prints each target that was found to be out-of-date, and
+whether the build was successful or not.
+
+@item v (@i{verbose})
+A level above @samp{basic}; includes messages about which makefiles were
+parsed, prerequisites that did not need to be rebuilt, etc.  This option
+also enables @samp{basic} messages.
+
+@item i (@i{implicit})
+Prints messages describing the implicit rule searches for each target.
+This option also enables @samp{basic} messages.
+
+@item j (@i{jobs})
+Prints messages giving details on the invocation of specific subcommands.
+
+@item m (@i{makefile})
+By default, the above messages are not enabled while trying to remake
+the makefiles.  This option enables messages while rebuilding makefiles,
+too.  Note that the @samp{all} option does enable this option.  This
+option also enables @samp{basic} messages.
+@end table
+
+@item -e
+@cindex @code{-e}
+@itemx --environment-overrides
+@cindex @code{--environment-overrides}
+Give variables taken from the environment precedence
+over variables from makefiles.
+@xref{Environment, ,Variables from the Environment}.
+
+@item -f @var{file}
+@cindex @code{-f}
+@itemx --file=@var{file}
+@cindex @code{--file}
+@itemx --makefile=@var{file}
+@cindex @code{--makefile}
+Read the file named @var{file} as a makefile.
+@xref{Makefiles, ,Writing Makefiles}.
+
+@item -h
+@cindex @code{-h}
+@itemx --help
+@cindex @code{--help}
+@c Extra blank line here makes the table look better.
+
+Remind you of the options that @code{make} understands and then exit.
+
+@item -i
+@cindex @code{-i}
+@itemx --ignore-errors
+@cindex @code{--ignore-errors}
+Ignore all errors in commands executed to remake files.
+@xref{Errors, ,Errors in Commands}.
+
+@item -I @var{dir}
+@cindex @code{-I}
+@itemx --include-dir=@var{dir}
+@cindex @code{--include-dir}
+Specifies a directory @var{dir} to search for included makefiles.
+@xref{Include, ,Including Other Makefiles}.  If several @samp{-I}
+options are used to specify several directories, the directories are
+searched in the order specified.
+
+@item -j [@var{jobs}]
+@cindex @code{-j}
+@itemx --jobs[=@var{jobs}]
+@cindex @code{--jobs}
+Specifies the number of jobs (commands) to run simultaneously.  With no
+argument, @code{make} runs as many jobs simultaneously as possible.  If
+there is more than one @samp{-j} option, the last one is effective.
+@xref{Parallel, ,Parallel Execution},
+for more information on how commands are run.
+Note that this option is ignored on MS-DOS.
+
+@item -k
+@cindex @code{-k}
+@itemx --keep-going
+@cindex @code{--keep-going}
+Continue as much as possible after an error.  While the target that
+failed, and those that depend on it, cannot be remade, the other
+prerequisites of these targets can be processed all the same.
+@xref{Testing, ,Testing the Compilation of a Program}.
+
+@item -l [@var{load}]
+@cindex @code{-l}
+@itemx --load-average[=@var{load}]
+@cindex @code{--load-average}
+@itemx --max-load[=@var{load}]
+@cindex @code{--max-load}
+Specifies that no new jobs (commands) should be started if there are
+other jobs running and the load average is at least @var{load} (a
+floating-point number).  With no argument, removes a previous load
+limit.  @xref{Parallel, ,Parallel Execution}.
+
+@item -L
+@cindex @code{-L}
+@itemx --check-symlink-times
+@cindex @code{--check-symlink-times}
+On systems that support symbolic links, this option causes @code{make}
+to consider the timestamps on any symbolic links in addition to the
+timestamp on the file referenced by those links.  When this option is
+provided, the most recent timestamp among the file and the symbolic
+links is taken as the modification time for this target file.
+
+@item -n
+@cindex @code{-n}
+@itemx --just-print
+@cindex @code{--just-print}
+@itemx --dry-run
+@cindex @code{--dry-run}
+@itemx --recon
+@cindex @code{--recon}
+@c Extra blank line here makes the table look better.
+
+Print the commands that would be executed, but do not execute them.
+@xref{Instead of Execution, ,Instead of Executing the Commands}.
+
+@item -o @var{file}
+@cindex @code{-o}
+@itemx --old-file=@var{file}
+@cindex @code{--old-file}
+@itemx --assume-old=@var{file}
+@cindex @code{--assume-old}
+Do not remake the file @var{file} even if it is older than its
+prerequisites, and do not remake anything on account of changes in
+@var{file}.  Essentially the file is treated as very old and its rules
+are ignored.  @xref{Avoiding Compilation, ,Avoiding Recompilation of
+Some Files}.@refill
+
+@item -p
+@cindex @code{-p}
+@itemx --print-data-base
+@cindex @code{--print-data-base}
+@cindex data base of @code{make} rules
+@cindex predefined rules and variables, printing
+Print the data base (rules and variable values) that results from
+reading the makefiles; then execute as usual or as otherwise specified.
+This also prints the version information given by the @samp{-v} switch
+(see below).  To print the data base without trying to remake any files,
+use @w{@samp{make -qp}}.  To print the data base of predefined rules and
+variables, use @w{@samp{make -p -f /dev/null}}.  The data base output
+contains filename and linenumber information for command and variable
+definitions, so it can be a useful debugging tool in complex environments.
+
+@item -q
+@cindex @code{-q}
+@itemx --question
+@cindex @code{--question}
+``Question mode''.  Do not run any commands, or print anything; just
+return an exit status that is zero if the specified targets are already
+up to date, one if any remaking is required, or two if an error is
+encountered.  @xref{Instead of Execution, ,Instead of Executing the
+Commands}.@refill
+
+@item -r
+@cindex @code{-r}
+@itemx --no-builtin-rules
+@cindex @code{--no-builtin-rules}
+Eliminate use of the built-in implicit rules (@pxref{Implicit Rules,
+,Using Implicit Rules}).  You can still define your own by writing
+pattern rules (@pxref{Pattern Rules, ,Defining and Redefining Pattern
+Rules}).  The @samp{-r} option also clears out the default list of
+suffixes for suffix rules (@pxref{Suffix Rules, ,Old-Fashioned Suffix
+Rules}).  But you can still define your own suffixes with a rule for
+@code{.SUFFIXES}, and then define your own suffix rules.  Note that only
+@emph{rules} are affected by the @code{-r} option; default variables
+remain in effect (@pxref{Implicit Variables, ,Variables Used by Implicit
+Rules}); see the @samp{-R} option below.
+
+@item -R
+@cindex @code{-R}
+@itemx --no-builtin-variables
+@cindex @code{--no-builtin-variables}
+Eliminate use of the built-in rule-specific variables (@pxref{Implicit
+Variables, ,Variables Used by Implicit Rules}).  You can still define
+your own, of course.  The @samp{-R} option also automatically enables
+the @samp{-r} option (see above), since it doesn't make sense to have
+implicit rules without any definitions for the variables that they use.
+
+@item -s
+@cindex @code{-s}
+@itemx --silent
+@cindex @code{--silent}
+@itemx --quiet
+@cindex @code{--quiet}
+@c Extra blank line here makes the table look better.
+
+Silent operation; do not print the commands as they are executed.
+@xref{Echoing, ,Command Echoing}.
+
+@item -S
+@cindex @code{-S}
+@itemx --no-keep-going
+@cindex @code{--no-keep-going}
+@itemx --stop
+@cindex @code{--stop}
+@c Extra blank line here makes the table look better.
+
+Cancel the effect of the @samp{-k} option.  This is never necessary
+except in a recursive @code{make} where @samp{-k} might be inherited
+from the top-level @code{make} via @code{MAKEFLAGS}
+(@pxref{Recursion, ,Recursive Use of @code{make}})
+or if you set @samp{-k} in @code{MAKEFLAGS} in your environment.@refill
+
+@item -t
+@cindex @code{-t}
+@itemx --touch
+@cindex @code{--touch}
+@c Extra blank line here makes the table look better.
+
+Touch files (mark them up to date without really changing them)
+instead of running their commands.  This is used to pretend that the
+commands were done, in order to fool future invocations of
+@code{make}.  @xref{Instead of Execution, ,Instead of Executing the Commands}.
+
+@item -v
+@cindex @code{-v}
+@itemx --version
+@cindex @code{--version}
+Print the version of the @code{make} program plus a copyright, a list
+of authors, and a notice that there is no warranty; then exit.
+
+@item -w
+@cindex @code{-w}
+@itemx --print-directory
+@cindex @code{--print-directory}
+Print a message containing the working directory both before and after
+executing the makefile.  This may be useful for tracking down errors
+from complicated nests of recursive @code{make} commands.
+@xref{Recursion, ,Recursive Use of @code{make}}.  (In practice, you
+rarely need to specify this option since @samp{make} does it for you;
+see @ref{-w Option, ,The @samp{--print-directory} Option}.)
+
+@itemx --no-print-directory
+@cindex @code{--no-print-directory}
+Disable printing of the working directory under @code{-w}.
+This option is useful when @code{-w} is turned on automatically,
+but you do not want to see the extra messages.
+@xref{-w Option, ,The @samp{--print-directory} Option}.
+
+@item -W @var{file}
+@cindex @code{-W}
+@itemx --what-if=@var{file}
+@cindex @code{--what-if}
+@itemx --new-file=@var{file}
+@cindex @code{--new-file}
+@itemx --assume-new=@var{file}
+@cindex @code{--assume-new}
+Pretend that the target @var{file} has just been modified.  When used
+with the @samp{-n} flag, this shows you what would happen if you were
+to modify that file.  Without @samp{-n}, it is almost the same as
+running a @code{touch} command on the given file before running
+@code{make}, except that the modification time is changed only in the
+imagination of @code{make}.
+@xref{Instead of Execution, ,Instead of Executing the Commands}.
+
+@item --warn-undefined-variables
+@cindex @code{--warn-undefined-variables}
+@cindex variables, warning for undefined
+@cindex undefined variables, warning message
+Issue a warning message whenever @code{make} sees a reference to an
+undefined variable.  This can be helpful when you are trying to debug
+makefiles which use variables in complex ways.
+@end table
+
+@node Implicit Rules, Archives, Running, Top
+@chapter Using Implicit Rules
+@cindex implicit rule
+@cindex rule, implicit
+
+Certain standard ways of remaking target files are used very often.  For
+example, one customary way to make an object file is from a C source file
+using the C compiler, @code{cc}.
+
+@dfn{Implicit rules} tell @code{make} how to use customary techniques so
+that you do not have to specify them in detail when you want to use
+them.  For example, there is an implicit rule for C compilation.  File
+names determine which implicit rules are run.  For example, C
+compilation typically takes a @file{.c} file and makes a @file{.o} file.
+So @code{make} applies the implicit rule for C compilation when it sees
+this combination of file name endings.@refill
+
+A chain of implicit rules can apply in sequence; for example, @code{make}
+will remake a @file{.o} file from a @file{.y} file by way of a @file{.c} file.
+@iftex
+@xref{Chained Rules, ,Chains of Implicit Rules}.
+@end iftex
+
+The built-in implicit rules use several variables in their commands so
+that, by changing the values of the variables, you can change the way the
+implicit rule works.  For example, the variable @code{CFLAGS} controls the
+flags given to the C compiler by the implicit rule for C compilation.
+@iftex
+@xref{Implicit Variables, ,Variables Used by Implicit Rules}.
+@end iftex
+
+You can define your own implicit rules by writing @dfn{pattern rules}.
+@iftex
+@xref{Pattern Rules, ,Defining and Redefining Pattern Rules}.
+@end iftex
+
+@dfn{Suffix rules} are a more limited way to define implicit rules.
+Pattern rules are more general and clearer, but suffix rules are
+retained for compatibility.
+@iftex
+@xref{Suffix Rules, ,Old-Fashioned Suffix Rules}.
+@end iftex
+
+@menu
+* Using Implicit::              How to use an existing implicit rule
+                                  to get the commands for updating a file.
+* Catalogue of Rules::          A list of built-in implicit rules.
+* Implicit Variables::          How to change what predefined rules do.
+* Chained Rules::               How to use a chain of implicit rules.
+* Pattern Rules::               How to define new implicit rules.
+* Last Resort::                 How to define commands for rules which
+                                  cannot find any.
+* Suffix Rules::                The old-fashioned style of implicit rule.
+* Implicit Rule Search::        The precise algorithm for applying
+                                  implicit rules.
+@end menu
+
+@node Using Implicit, Catalogue of Rules, Implicit Rules, Implicit Rules
+@section Using Implicit Rules
+@cindex implicit rule, how to use
+@cindex rule, implicit, how to use
+
+To allow @code{make} to find a customary method for updating a target file,
+all you have to do is refrain from specifying commands yourself.  Either
+write a rule with no command lines, or don't write a rule at all.  Then
+@code{make} will figure out which implicit rule to use based on which
+kind of source file exists or can be made.
+
+For example, suppose the makefile looks like this:
+
+@example
+foo : foo.o bar.o
+        cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
+@end example
+
+@noindent
+Because you mention @file{foo.o} but do not give a rule for it, @code{make}
+will automatically look for an implicit rule that tells how to update it.
+This happens whether or not the file @file{foo.o} currently exists.
+
+If an implicit rule is found, it can supply both commands and one or
+more prerequisites (the source files).  You would want to write a rule
+for @file{foo.o} with no command lines if you need to specify additional
+prerequisites, such as header files, that the implicit rule cannot
+supply.
+
+Each implicit rule has a target pattern and prerequisite patterns.  There may
+be many implicit rules with the same target pattern.  For example, numerous
+rules make @samp{.o} files: one, from a @samp{.c} file with the C compiler;
+another, from a @samp{.p} file with the Pascal compiler; and so on.  The rule
+that actually applies is the one whose prerequisites exist or can be made.
+So, if you have a file @file{foo.c}, @code{make} will run the C compiler;
+otherwise, if you have a file @file{foo.p}, @code{make} will run the Pascal
+compiler; and so on.
+
+Of course, when you write the makefile, you know which implicit rule you
+want @code{make} to use, and you know it will choose that one because you
+know which possible prerequisite files are supposed to exist.
+@xref{Catalogue of Rules, ,Catalogue of Implicit Rules},
+for a catalogue of all the predefined implicit rules.
+
+Above, we said an implicit rule applies if the required prerequisites ``exist
+or can be made''.  A file ``can be made'' if it is mentioned explicitly in
+the makefile as a target or a prerequisite, or if an implicit rule can be
+recursively found for how to make it.  When an implicit prerequisite is the
+result of another implicit rule, we say that @dfn{chaining} is occurring.
+@xref{Chained Rules, ,Chains of Implicit Rules}.
+
+In general, @code{make} searches for an implicit rule for each target, and
+for each double-colon rule, that has no commands.  A file that is mentioned
+only as a prerequisite is considered a target whose rule specifies nothing,
+so implicit rule search happens for it.  @xref{Implicit Rule Search, ,Implicit Rule Search Algorithm}, for the
+details of how the search is done.
+
+Note that explicit prerequisites do not influence implicit rule search.
+For example, consider this explicit rule:
+
+@example
+foo.o: foo.p
+@end example
+
+@noindent
+The prerequisite on @file{foo.p} does not necessarily mean that
+@code{make} will remake @file{foo.o} according to the implicit rule to
+make an object file, a @file{.o} file, from a Pascal source file, a
+@file{.p} file.  For example, if @file{foo.c} also exists, the implicit
+rule to make an object file from a C source file is used instead,
+because it appears before the Pascal rule in the list of predefined
+implicit rules (@pxref{Catalogue of Rules, , Catalogue of Implicit
+Rules}).
+
+If you do not want an implicit rule to be used for a target that has no
+commands, you can give that target empty commands by writing a semicolon
+(@pxref{Empty Commands, ,Defining Empty Commands}).
+
+@node Catalogue of Rules, Implicit Variables, Using Implicit, Implicit Rules
+@section Catalogue of Implicit Rules
+@cindex implicit rule, predefined
+@cindex rule, implicit, predefined
+
+Here is a catalogue of predefined implicit rules which are always
+available unless the makefile explicitly overrides or cancels them.
+@xref{Canceling Rules, ,Canceling Implicit Rules}, for information on
+canceling or overriding an implicit rule.  The @samp{-r} or
+@samp{--no-builtin-rules} option cancels all predefined rules.
+
+This manual only documents the default rules available on POSIX-based
+operating systems.  Other operating systems, such as VMS, Windows,
+OS/2, etc. may have different sets of default rules.  To see the full
+list of default rules and variables available in your version of GNU
+@code{make}, run @samp{make -p} in a directory with no makefile.
+
+Not all of these rules will always be defined, even when the @samp{-r}
+option is not given.  Many of the predefined implicit rules are
+implemented in @code{make} as suffix rules, so which ones will be
+defined depends on the @dfn{suffix list} (the list of prerequisites of
+the special target @code{.SUFFIXES}).  The default suffix list is:
+@code{.out}, @code{.a}, @code{.ln}, @code{.o}, @code{.c}, @code{.cc},
+@code{.C}, @code{.cpp}, @code{.p}, @code{.f}, @code{.F}, @code{.m},
+@code{.r}, @code{.y}, @code{.l}, @code{.ym}, @code{.lm}, @code{.s},
+@code{.S}, @code{.mod}, @code{.sym}, @code{.def}, @code{.h},
+@code{.info}, @code{.dvi}, @code{.tex}, @code{.texinfo}, @code{.texi},
+@code{.txinfo}, @code{.w}, @code{.ch} @code{.web}, @code{.sh},
+@code{.elc}, @code{.el}.  All of the implicit rules described below
+whose prerequisites have one of these suffixes are actually suffix
+rules.  If you modify the suffix list, the only predefined suffix
+rules in effect will be those named by one or two of the suffixes that
+are on the list you specify; rules whose suffixes fail to be on the
+list are disabled.  @xref{Suffix Rules, ,Old-Fashioned Suffix Rules},
+for full details on suffix rules.
+
+@table @asis
+@item Compiling C programs
+@cindex C, rule to compile
+@pindex cc
+@pindex gcc
+@pindex .o
+@pindex .c
+@file{@var{n}.o} is made automatically from @file{@var{n}.c} with
+a command of the form @samp{$(CC) -c $(CPPFLAGS) $(CFLAGS)}.@refill
+
+@item Compiling C++ programs
+@cindex C++, rule to compile
+@pindex g++
+@pindex .cc
+@pindex .cpp
+@pindex .C
+@file{@var{n}.o} is made automatically from @file{@var{n}.cc},
+@file{@var{n}.cpp}, or @file{@var{n}.C} with a command of the form
+@samp{$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)}.  We encourage you to use the
+suffix @samp{.cc} for C++ source files instead of @samp{.C}.@refill
+
+@item Compiling Pascal programs
+@cindex Pascal, rule to compile
+@pindex pc
+@pindex .p
+@file{@var{n}.o} is made automatically from @file{@var{n}.p}
+with the command @samp{$(PC) -c $(PFLAGS)}.@refill
+
+@item Compiling Fortran and Ratfor programs
+@cindex Fortran, rule to compile
+@cindex Ratfor, rule to compile
+@pindex f77
+@pindex .f
+@pindex .r
+@pindex .F
+@file{@var{n}.o} is made automatically from @file{@var{n}.r},
+@file{@var{n}.F} or @file{@var{n}.f} by running the
+Fortran compiler.  The precise command used is as follows:@refill
+
+@table @samp
+@item .f
+@samp{$(FC) -c $(FFLAGS)}.
+@item .F
+@samp{$(FC) -c $(FFLAGS) $(CPPFLAGS)}.
+@item .r
+@samp{$(FC) -c $(FFLAGS) $(RFLAGS)}.
+@end table
+
+@item Preprocessing Fortran and Ratfor programs
+@file{@var{n}.f} is made automatically from @file{@var{n}.r} or
+@file{@var{n}.F}.  This rule runs just the preprocessor to convert a
+Ratfor or preprocessable Fortran program into a strict Fortran
+program.  The precise command used is as follows:@refill
+
+@table @samp
+@item .F
+@samp{$(FC) -F $(CPPFLAGS) $(FFLAGS)}.
+@item .r
+@samp{$(FC) -F $(FFLAGS) $(RFLAGS)}.
+@end table
+
+@item Compiling Modula-2 programs
+@cindex Modula-2, rule to compile
+@pindex m2c
+@pindex .sym
+@pindex .def
+@pindex .mod
+@file{@var{n}.sym} is made from @file{@var{n}.def} with a command
+of the form @samp{$(M2C) $(M2FLAGS) $(DEFFLAGS)}.  @file{@var{n}.o}
+is made from @file{@var{n}.mod}; the form is:
+@w{@samp{$(M2C) $(M2FLAGS) $(MODFLAGS)}}.@refill
+
+@need 1200
+@item Assembling and preprocessing assembler programs
+@cindex assembly, rule to compile
+@pindex as
+@pindex .s
+@file{@var{n}.o} is made automatically from @file{@var{n}.s} by
+running the assembler, @code{as}.  The precise command is
+@samp{$(AS) $(ASFLAGS)}.@refill
+
+@pindex .S
+@file{@var{n}.s} is made automatically from @file{@var{n}.S} by
+running the C preprocessor, @code{cpp}.  The precise command is
+@w{@samp{$(CPP) $(CPPFLAGS)}}.
+
+@item Linking a single object file
+@cindex linking, predefined rule for
+@pindex ld
+@pindex .o
+@file{@var{n}} is made automatically from @file{@var{n}.o} by running
+the linker (usually called @code{ld}) via the C compiler.  The precise
+command used is @w{@samp{$(CC) $(LDFLAGS) @var{n}.o $(LOADLIBES) $(LDLIBS)}}.
+
+This rule does the right thing for a simple program with only one
+source file.  It will also do the right thing if there are multiple
+object files (presumably coming from various other source files), one
+of which has a name matching that of the executable file.  Thus,
+
+@example
+x: y.o z.o
+@end example
+
+@noindent
+when @file{x.c}, @file{y.c} and @file{z.c} all exist will execute:
+
+@example
+@group
+cc -c x.c -o x.o
+cc -c y.c -o y.o
+cc -c z.c -o z.o
+cc x.o y.o z.o -o x
+rm -f x.o
+rm -f y.o
+rm -f z.o
+@end group
+@end example
+
+@noindent
+In more complicated cases, such as when there is no object file whose
+name derives from the executable file name, you must write an explicit
+command for linking.
+
+Each kind of file automatically made into @samp{.o} object files will
+be automatically linked by using the compiler (@samp{$(CC)},
+@samp{$(FC)} or @samp{$(PC)}; the C compiler @samp{$(CC)} is used to
+assemble @samp{.s} files) without the @samp{-c} option.  This could be
+done by using the @samp{.o} object files as intermediates, but it is
+faster to do the compiling and linking in one step, so that's how it's
+done.@refill
+
+@item Yacc for C programs
+@pindex yacc
+@cindex Yacc, rule to run
+@pindex .y
+@file{@var{n}.c} is made automatically from @file{@var{n}.y} by
+running Yacc with the command @samp{$(YACC) $(YFLAGS)}.
+
+@item Lex for C programs
+@pindex lex
+@cindex Lex, rule to run
+@pindex .l
+@file{@var{n}.c} is made automatically from @file{@var{n}.l} by
+running Lex.  The actual command is @samp{$(LEX) $(LFLAGS)}.
+
+@item Lex for Ratfor programs
+@file{@var{n}.r} is made automatically from @file{@var{n}.l} by
+running Lex.  The actual command is @samp{$(LEX) $(LFLAGS)}.
+
+The convention of using the same suffix @samp{.l} for all Lex files
+regardless of whether they produce C code or Ratfor code makes it
+impossible for @code{make} to determine automatically which of the two
+languages you are using in any particular case.  If @code{make} is
+called upon to remake an object file from a @samp{.l} file, it must
+guess which compiler to use.  It will guess the C compiler, because
+that is more common.  If you are using Ratfor, make sure @code{make}
+knows this by mentioning @file{@var{n}.r} in the makefile.  Or, if you
+are using Ratfor exclusively, with no C files, remove @samp{.c} from
+the list of implicit rule suffixes with:@refill
+
+@example
+@group
+.SUFFIXES:
+.SUFFIXES: .o .r .f .l @dots{}
+@end group
+@end example
+
+@item Making Lint Libraries from C, Yacc, or Lex programs
+@pindex lint
+@cindex @code{lint}, rule to run
+@pindex .ln
+@file{@var{n}.ln} is made from @file{@var{n}.c} by running @code{lint}.
+The precise command is @w{@samp{$(LINT) $(LINTFLAGS) $(CPPFLAGS) -i}}.
+The same command is used on the C code produced from
+@file{@var{n}.y} or @file{@var{n}.l}.@refill
+
+@item @TeX{} and Web
+@cindex @TeX{}, rule to run
+@cindex Web, rule to run
+@pindex tex
+@pindex cweave
+@pindex weave
+@pindex tangle
+@pindex ctangle
+@pindex .dvi
+@pindex .tex
+@pindex .web
+@pindex .w
+@pindex .ch
+@file{@var{n}.dvi} is made from @file{@var{n}.tex} with the command
+@samp{$(TEX)}.  @file{@var{n}.tex} is made from @file{@var{n}.web} with
+@samp{$(WEAVE)}, or from @file{@var{n}.w} (and from @file{@var{n}.ch} if
+it exists or can be made) with @samp{$(CWEAVE)}.  @file{@var{n}.p} is
+made from @file{@var{n}.web} with @samp{$(TANGLE)} and @file{@var{n}.c}
+is made from @file{@var{n}.w} (and from @file{@var{n}.ch} if it exists
+or can be made) with @samp{$(CTANGLE)}.@refill
+
+@item Texinfo and Info
+@cindex Texinfo, rule to format
+@cindex Info, rule to format
+@pindex texi2dvi
+@pindex makeinfo
+@pindex .texinfo
+@pindex .info
+@pindex .texi
+@pindex .txinfo
+@file{@var{n}.dvi} is made from @file{@var{n}.texinfo},
+@file{@var{n}.texi}, or @file{@var{n}.txinfo}, with the command
+@w{@samp{$(TEXI2DVI) $(TEXI2DVI_FLAGS)}}.  @file{@var{n}.info} is made from
+@file{@var{n}.texinfo}, @file{@var{n}.texi}, or @file{@var{n}.txinfo}, with
+the command @w{@samp{$(MAKEINFO) $(MAKEINFO_FLAGS)}}.
+
+@item RCS
+@cindex RCS, rule to extract from
+@pindex co
+@pindex ,v @r{(RCS file extension)}
+Any file @file{@var{n}} is extracted if necessary from an RCS file
+named either @file{@var{n},v} or @file{RCS/@var{n},v}.  The precise
+command used is @w{@samp{$(CO) $(COFLAGS)}}.  @file{@var{n}} will not be
+extracted from RCS if it already exists, even if the RCS file is
+newer.  The rules for RCS are terminal
+(@pxref{Match-Anything Rules, ,Match-Anything Pattern Rules}),
+so RCS files cannot be generated from another source; they must
+actually exist.@refill
+
+@item SCCS
+@cindex SCCS, rule to extract from
+@pindex get
+@pindex s. @r{(SCCS file prefix)}
+Any file @file{@var{n}} is extracted if necessary from an SCCS file
+named either @file{s.@var{n}} or @file{SCCS/s.@var{n}}.  The precise
+command used is @w{@samp{$(GET) $(GFLAGS)}}.  The rules for SCCS are
+terminal (@pxref{Match-Anything Rules, ,Match-Anything Pattern Rules}),
+so SCCS files cannot be generated from another source; they must
+actually exist.@refill
+
+@pindex .sh
+For the benefit of SCCS, a file @file{@var{n}} is copied from
+@file{@var{n}.sh} and made executable (by everyone).  This is for
+shell scripts that are checked into SCCS.  Since RCS preserves the
+execution permission of a file, you do not need to use this feature
+with RCS.@refill
+
+We recommend that you avoid using of SCCS.  RCS is widely held to be
+superior, and is also free.  By choosing free software in place of
+comparable (or inferior) proprietary software, you support the free
+software movement.
+@end table
+
+Usually, you want to change only the variables listed in the table
+above, which are documented in the following section.
+
+However, the commands in built-in implicit rules actually use
+variables such as @code{COMPILE.c}, @code{LINK.p}, and
+@code{PREPROCESS.S}, whose values contain the commands listed above.
+
+@code{make} follows the convention that the rule to compile a
+@file{.@var{x}} source file uses the variable @code{COMPILE.@var{x}}.
+Similarly, the rule to produce an executable from a @file{.@var{x}}
+file uses @code{LINK.@var{x}}; and the rule to preprocess a
+@file{.@var{x}} file uses @code{PREPROCESS.@var{x}}.
+
+@vindex OUTPUT_OPTION
+Every rule that produces an object file uses the variable
+@code{OUTPUT_OPTION}.  @code{make} defines this variable either to
+contain @samp{-o $@@}, or to be empty, depending on a compile-time
+option.  You need the @samp{-o} option to ensure that the output goes
+into the right file when the source file is in a different directory,
+as when using @code{VPATH} (@pxref{Directory Search}).  However,
+compilers on some systems do not accept a @samp{-o} switch for object
+files.  If you use such a system, and use @code{VPATH}, some
+compilations will put their output in the wrong place.
+A possible workaround for this problem is to give @code{OUTPUT_OPTION}
+the value @w{@samp{; mv $*.o $@@}}.
+
+@node Implicit Variables, Chained Rules, Catalogue of Rules, Implicit Rules
+@section Variables Used by Implicit Rules
+@cindex flags for compilers
+
+The commands in built-in implicit rules make liberal use of certain
+predefined variables.  You can alter the values of these variables in
+the makefile, with arguments to @code{make}, or in the environment to
+alter how the implicit rules work without redefining the rules
+themselves.  You can cancel all variables used by implicit rules with
+the @samp{-R} or @samp{--no-builtin-variables} option.
+
+For example, the command used to compile a C source file actually says
+@samp{$(CC) -c $(CFLAGS) $(CPPFLAGS)}.  The default values of the variables
+used are @samp{cc} and nothing, resulting in the command @samp{cc -c}.  By
+redefining @samp{CC} to @samp{ncc}, you could cause @samp{ncc} to be
+used for all C compilations performed by the implicit rule.  By redefining
+@samp{CFLAGS} to be @samp{-g}, you could pass the @samp{-g} option to
+each compilation.  @emph{All} implicit rules that do C compilation use
+@samp{$(CC)} to get the program name for the compiler and @emph{all}
+include @samp{$(CFLAGS)} among the arguments given to the compiler.@refill
+
+The variables used in implicit rules fall into two classes: those that are
+names of programs (like @code{CC}) and those that contain arguments for the
+programs (like @code{CFLAGS}).  (The ``name of a program'' may also contain
+some command arguments, but it must start with an actual executable program
+name.)  If a variable value contains more than one argument, separate them
+with spaces.
+
+The following tables describe of some of the more commonly-used predefined
+variables.  This list is not exhaustive, and the default values shown here may
+not be what are selected by @code{make} for your environment.  To see the
+complete list of predefined variables for your instance of GNU @code{make} you
+can run @samp{make -p} in a directory with no makefiles.
+
+Here is a table of some of the more common variables used as names of
+programs in built-in rules:
+makefiles.
+
+@table @code
+@item AR
+@vindex AR
+Archive-maintaining program; default @samp{ar}.
+@pindex ar
+
+@item AS
+@vindex AS
+Program for compiling assembly files; default @samp{as}.
+@pindex as
+
+@item CC
+@vindex CC
+Program for compiling C programs; default @samp{cc}.
+@pindex cc
+
+@item CXX
+@vindex CXX
+Program for compiling C++ programs; default @samp{g++}.
+@pindex g++
+
+@item CPP
+@vindex CPP
+Program for running the C preprocessor, with results to standard output;
+default @samp{$(CC) -E}.
+
+@item FC
+@vindex FC
+Program for compiling or preprocessing Fortran and Ratfor programs;
+default @samp{f77}.
+@pindex f77
+
+@item M2C
+@vindex M2C
+Program to use to compile Modula-2 source code; default @samp{m2c}.
+@pindex m2c
+
+@item PC
+@vindex PC
+Program for compiling Pascal programs; default @samp{pc}.
+@pindex pc
+
+@item CO
+@vindex CO
+Program for extracting a file from RCS; default @samp{co}.
+@pindex co
+
+@item GET
+@vindex GET
+Program for extracting a file from SCCS; default @samp{get}.
+@pindex get
+
+@item LEX
+@vindex LEX
+Program to use to turn Lex grammars into source code; default @samp{lex}.
+@pindex lex
+
+@item YACC
+@vindex YACC
+Program to use to turn Yacc grammars into source code; default @samp{yacc}.
+@pindex yacc
+
+@item LINT
+@vindex LINT
+Program to use to run lint on source code; default @samp{lint}.
+@pindex lint
+
+@item MAKEINFO
+@vindex MAKEINFO
+Program to convert a Texinfo source file into an Info file; default
+@samp{makeinfo}.
+@pindex makeinfo
+
+@item TEX
+@vindex TEX
+Program to make @TeX{} @sc{dvi} files from @TeX{} source;
+default @samp{tex}.
+@pindex tex
+
+@item TEXI2DVI
+@vindex TEXI2DVI
+Program to make @TeX{} @sc{dvi} files from Texinfo source;
+default @samp{texi2dvi}.
+@pindex texi2dvi
+
+@item WEAVE
+@vindex WEAVE
+Program to translate Web into @TeX{}; default @samp{weave}.
+@pindex weave
+
+@item CWEAVE
+@vindex CWEAVE
+Program to translate C Web into @TeX{}; default @samp{cweave}.
+@pindex cweave
+
+@item TANGLE
+@vindex TANGLE
+Program to translate Web into Pascal; default @samp{tangle}.
+@pindex tangle
+
+@item CTANGLE
+@vindex CTANGLE
+Program to translate C Web into C; default @samp{ctangle}.
+@pindex ctangle
+
+@item RM
+@vindex RM
+Command to remove a file; default @samp{rm -f}.
+@pindex rm
+@end table
+
+Here is a table of variables whose values are additional arguments for the
+programs above.  The default values for all of these is the empty
+string, unless otherwise noted.
+
+@table @code
+@item ARFLAGS
+@vindex ARFLAGS
+Flags to give the archive-maintaining program; default @samp{rv}.
+
+@item ASFLAGS
+@vindex ASFLAGS
+Extra flags to give to the assembler (when explicitly
+invoked on a @samp{.s} or @samp{.S} file).
+
+@item CFLAGS
+@vindex CFLAGS
+Extra flags to give to the C compiler.
+
+@item CXXFLAGS
+@vindex CXXFLAGS
+Extra flags to give to the C++ compiler.
+
+@item COFLAGS
+@vindex COFLAGS
+Extra flags to give to the RCS @code{co} program.
+
+@item CPPFLAGS
+@vindex CPPFLAGS
+Extra flags to give to the C preprocessor and programs
+that use it (the C and Fortran compilers).
+
+@item FFLAGS
+@vindex FFLAGS
+Extra flags to give to the Fortran compiler.
+
+@item GFLAGS
+@vindex GFLAGS
+Extra flags to give to the SCCS @code{get} program.
+
+@item LDFLAGS
+@vindex LDFLAGS
+Extra flags to give to compilers when they are supposed to invoke the linker,
+@samp{ld}.
+
+@item LFLAGS
+@vindex LFLAGS
+Extra flags to give to Lex.
+
+@item YFLAGS
+@vindex YFLAGS
+Extra flags to give to Yacc.
+
+@item PFLAGS
+@vindex PFLAGS
+Extra flags to give to the Pascal compiler.
+
+@item RFLAGS
+@vindex RFLAGS
+Extra flags to give to the Fortran compiler for Ratfor programs.
+
+@item LINTFLAGS
+@vindex LINTFLAGS
+Extra flags to give to lint.
+@end table
+
+@node Chained Rules, Pattern Rules, Implicit Variables, Implicit Rules
+@section Chains of Implicit Rules
+
+@cindex chains of rules
+@cindex rule, implicit, chains of
+Sometimes a file can be made by a sequence of implicit rules.  For example,
+a file @file{@var{n}.o} could be made from @file{@var{n}.y} by running
+first Yacc and then @code{cc}.  Such a sequence is called a @dfn{chain}.
+
+If the file @file{@var{n}.c} exists, or is mentioned in the makefile, no
+special searching is required: @code{make} finds that the object file can
+be made by C compilation from @file{@var{n}.c}; later on, when considering
+how to make @file{@var{n}.c}, the rule for running Yacc is
+used.  Ultimately both @file{@var{n}.c} and @file{@var{n}.o} are
+updated.@refill
+
+@cindex intermediate files
+@cindex files, intermediate
+However, even if @file{@var{n}.c} does not exist and is not mentioned,
+@code{make} knows how to envision it as the missing link between
+@file{@var{n}.o} and @file{@var{n}.y}!  In this case, @file{@var{n}.c} is
+called an @dfn{intermediate file}.  Once @code{make} has decided to use the
+intermediate file, it is entered in the data base as if it had been
+mentioned in the makefile, along with the implicit rule that says how to
+create it.@refill
+
+Intermediate files are remade using their rules just like all other
+files.  But intermediate files are treated differently in two ways.
+
+The first difference is what happens if the intermediate file does not
+exist.  If an ordinary file @var{b} does not exist, and @code{make}
+considers a target that depends on @var{b}, it invariably creates
+@var{b} and then updates the target from @var{b}.  But if @var{b} is an
+intermediate file, then @code{make} can leave well enough alone.  It
+won't bother updating @var{b}, or the ultimate target, unless some
+prerequisite of @var{b} is newer than that target or there is some other
+reason to update that target.
+
+The second difference is that if @code{make} @emph{does} create @var{b}
+in order to update something else, it deletes @var{b} later on after it
+is no longer needed.  Therefore, an intermediate file which did not
+exist before @code{make} also does not exist after @code{make}.
+@code{make} reports the deletion to you by printing a @samp{rm -f}
+command showing which file it is deleting.
+
+Ordinarily, a file cannot be intermediate if it is mentioned in the
+makefile as a target or prerequisite.  However, you can explicitly mark a
+file as intermediate by listing it as a prerequisite of the special target
+@code{.INTERMEDIATE}.  This takes effect even if the file is mentioned
+explicitly in some other way.
+
+@cindex intermediate files, preserving
+@cindex preserving intermediate files
+@cindex secondary files
+You can prevent automatic deletion of an intermediate file by marking it
+as a @dfn{secondary} file.  To do this, list it as a prerequisite of the
+special target @code{.SECONDARY}.  When a file is secondary, @code{make}
+will not create the file merely because it does not already exist, but
+@code{make} does not automatically delete the file.  Marking a file as
+secondary also marks it as intermediate.
+
+You can list the target pattern of an implicit rule (such as @samp{%.o})
+as a prerequisite of the special target @code{.PRECIOUS} to preserve
+intermediate files made by implicit rules whose target patterns match
+that file's name; see @ref{Interrupts}.@refill
+@cindex preserving with @code{.PRECIOUS}
+@cindex @code{.PRECIOUS} intermediate files
+
+A chain can involve more than two implicit rules.  For example, it is
+possible to make a file @file{foo} from @file{RCS/foo.y,v} by running RCS,
+Yacc and @code{cc}.  Then both @file{foo.y} and @file{foo.c} are
+intermediate files that are deleted at the end.@refill
+
+No single implicit rule can appear more than once in a chain.  This means
+that @code{make} will not even consider such a ridiculous thing as making
+@file{foo} from @file{foo.o.o} by running the linker twice.  This
+constraint has the added benefit of preventing any infinite loop in the
+search for an implicit rule chain.
+
+There are some special implicit rules to optimize certain cases that would
+otherwise be handled by rule chains.  For example, making @file{foo} from
+@file{foo.c} could be handled by compiling and linking with separate
+chained rules, using @file{foo.o} as an intermediate file.  But what
+actually happens is that a special rule for this case does the compilation
+and linking with a single @code{cc} command.  The optimized rule is used in
+preference to the step-by-step chain because it comes earlier in the
+ordering of rules.
+
+@node Pattern Rules, Last Resort, Chained Rules, Implicit Rules
+@section Defining and Redefining Pattern Rules
+
+You define an implicit rule by writing a @dfn{pattern rule}.  A pattern
+rule looks like an ordinary rule, except that its target contains the
+character @samp{%} (exactly one of them).  The target is considered a
+pattern for matching file names; the @samp{%} can match any nonempty
+substring, while other characters match only themselves.  The prerequisites
+likewise use @samp{%} to show how their names relate to the target name.
+
+Thus, a pattern rule @samp{%.o : %.c} says how to make any file
+@file{@var{stem}.o} from another file @file{@var{stem}.c}.@refill
+
+Note that expansion using @samp{%} in pattern rules occurs
+@strong{after} any variable or function expansions, which take place
+when the makefile is read.  @xref{Using Variables, , How to Use
+Variables}, and @ref{Functions, ,Functions for Transforming Text}.
+
+@menu
+* Pattern Intro::               An introduction to pattern rules.
+* Pattern Examples::            Examples of pattern rules.
+* Automatic Variables::         How to use automatic variables in the
+                                  commands of implicit rules.
+* Pattern Match::               How patterns match.
+* Match-Anything Rules::        Precautions you should take prior to
+                                  defining rules that can match any
+                                  target file whatever.
+* Canceling Rules::             How to override or cancel built-in rules.
+@end menu
+
+@node Pattern Intro, Pattern Examples, Pattern Rules, Pattern Rules
+@subsection Introduction to Pattern Rules
+@cindex pattern rule
+@cindex rule, pattern
+
+A pattern rule contains the character @samp{%} (exactly one of them)
+in the target; otherwise, it looks exactly like an ordinary rule.  The
+target is a pattern for matching file names; the @samp{%} matches any
+nonempty substring, while other characters match only themselves.
+@cindex target pattern, implicit
+@cindex @code{%}, in pattern rules
+
+For example, @samp{%.c} as a pattern matches any file name that ends in
+@samp{.c}.  @samp{s.%.c} as a pattern matches any file name that starts
+with @samp{s.}, ends in @samp{.c} and is at least five characters long.
+(There must be at least one character to match the @samp{%}.)  The substring
+that the @samp{%} matches is called the @dfn{stem}.@refill
+
+@samp{%} in a prerequisite of a pattern rule stands for the same stem
+that was matched by the @samp{%} in the target.  In order for the
+pattern rule to apply, its target pattern must match the file name
+under consideration and all of its prerequisites (after pattern
+substitution) must name files that exist or can be made.  These files
+become prerequisites of the target.
+@cindex prerequisite pattern, implicit
+
+Thus, a rule of the form
+
+@example
+%.o : %.c ; @var{command}@dots{}
+@end example
+
+@noindent
+specifies how to make a file @file{@var{n}.o}, with another file
+@file{@var{n}.c} as its prerequisite, provided that @file{@var{n}.c}
+exists or can be made.
+
+There may also be prerequisites that do not use @samp{%}; such a prerequisite
+attaches to every file made by this pattern rule.  These unvarying
+prerequisites are useful occasionally.
+
+A pattern rule need not have any prerequisites that contain @samp{%}, or
+in fact any prerequisites at all.  Such a rule is effectively a general
+wildcard.  It provides a way to make any file that matches the target
+pattern.  @xref{Last Resort}.
+
+@c !!! The end of of this paragraph should be rewritten.  --bob
+Pattern rules may have more than one target.  Unlike normal rules, this
+does not act as many different rules with the same prerequisites and
+commands.  If a pattern rule has multiple targets, @code{make} knows that
+the rule's commands are responsible for making all of the targets.  The
+commands are executed only once to make all the targets.  When searching
+for a pattern rule to match a target, the target patterns of a rule other
+than the one that matches the target in need of a rule are incidental:
+@code{make} worries only about giving commands and prerequisites to the file
+presently in question.  However, when this file's commands are run, the
+other targets are marked as having been updated themselves.
+@cindex multiple targets, in pattern rule
+@cindex target, multiple in pattern rule
+
+The order in which pattern rules appear in the makefile is important
+since this is the order in which they are considered.
+Of equally applicable
+rules, only the first one found is used.  The rules you write take precedence
+over those that are built in.  Note however, that a rule whose
+prerequisites actually exist or are mentioned always takes priority over a
+rule with prerequisites that must be made by chaining other implicit rules.
+@cindex pattern rules, order of
+@cindex order of pattern rules
+
+@node Pattern Examples, Automatic Variables, Pattern Intro, Pattern Rules
+@subsection Pattern Rule Examples
+
+Here are some examples of pattern rules actually predefined in
+@code{make}.  First, the rule that compiles @samp{.c} files into @samp{.o}
+files:@refill
+
+@example
+%.o : %.c
+        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@@
+@end example
+
+@noindent
+defines a rule that can make any file @file{@var{x}.o} from
+@file{@var{x}.c}.  The command uses the automatic variables @samp{$@@} and
+@samp{$<} to substitute the names of the target file and the source file
+in each case where the rule applies (@pxref{Automatic Variables}).@refill
+
+Here is a second built-in rule:
+
+@example
+% :: RCS/%,v
+        $(CO) $(COFLAGS) $<
+@end example
+
+@noindent
+defines a rule that can make any file @file{@var{x}} whatsoever from a
+corresponding file @file{@var{x},v} in the subdirectory @file{RCS}.  Since
+the target is @samp{%}, this rule will apply to any file whatever, provided
+the appropriate prerequisite file exists.  The double colon makes the rule
+@dfn{terminal}, which means that its prerequisite may not be an intermediate
+file (@pxref{Match-Anything Rules, ,Match-Anything Pattern Rules}).@refill
+
+@need 500
+This pattern rule has two targets:
+
+@example
+@group
+%.tab.c %.tab.h: %.y
+        bison -d $<
+@end group
+@end example
+
+@noindent
+@c The following paragraph is rewritten to avoid overfull hboxes
+This tells @code{make} that the command @samp{bison -d @var{x}.y} will
+make both @file{@var{x}.tab.c} and @file{@var{x}.tab.h}.  If the file
+@file{foo} depends on the files @file{parse.tab.o} and @file{scan.o}
+and the file @file{scan.o} depends on the file @file{parse.tab.h},
+when @file{parse.y} is changed, the command @samp{bison -d parse.y}
+will be executed only once, and the prerequisites of both
+@file{parse.tab.o} and @file{scan.o} will be satisfied.  (Presumably
+the file @file{parse.tab.o} will be recompiled from @file{parse.tab.c}
+and the file @file{scan.o} from @file{scan.c}, while @file{foo} is
+linked from @file{parse.tab.o}, @file{scan.o}, and its other
+prerequisites, and it will execute happily ever after.)@refill
+
+@node Automatic Variables, Pattern Match, Pattern Examples, Pattern Rules
+@subsection Automatic Variables
+@cindex automatic variables
+@cindex variables, automatic
+@cindex variables, and implicit rule
+
+Suppose you are writing a pattern rule to compile a @samp{.c} file into a
+@samp{.o} file: how do you write the @samp{cc} command so that it operates
+on the right source file name?  You cannot write the name in the command,
+because the name is different each time the implicit rule is applied.
+
+What you do is use a special feature of @code{make}, the @dfn{automatic
+variables}.  These variables have values computed afresh for each rule that
+is executed, based on the target and prerequisites of the rule.  In this
+example, you would use @samp{$@@} for the object file name and @samp{$<}
+for the source file name.
+
+@cindex automatic variables in prerequisites
+@cindex prerequisites, and automatic variables
+It's very important that you recognize the limited scope in which
+automatic variable values are available: they only have values within
+the command script.  In particular, you cannot use them anywhere
+within the target list of a rule; they have no value there and will
+expand to the empty string.  Also, they cannot be accessed directly
+within the prerequisite list of a rule.  A common mistake is
+attempting to use @code{$@@} within the prerequisites list; this will
+not work.  However, there is a special feature of GNU @code{make},
+secondary expansion (@pxref{Secondary Expansion}), which will allow
+automatic variable values to be used in prerequisite lists.
+
+Here is a table of automatic variables:
+
+@table @code
+@vindex $@@
+@vindex @@ @r{(automatic variable)}
+@item $@@
+The file name of the target of the rule.  If the target is an archive
+member, then @samp{$@@} is the name of the archive file.  In a pattern
+rule that has multiple targets (@pxref{Pattern Intro, ,Introduction to
+Pattern Rules}), @samp{$@@} is the name of whichever target caused the
+rule's commands to be run.
+
+@vindex $%
+@vindex % @r{(automatic variable)}
+@item $%
+The target member name, when the target is an archive member.
+@xref{Archives}.  For example, if the target is @file{foo.a(bar.o)} then
+@samp{$%} is @file{bar.o} and @samp{$@@} is @file{foo.a}.  @samp{$%} is
+empty when the target is not an archive member.
+
+@vindex $<
+@vindex < @r{(automatic variable)}
+@item $<
+The name of the first prerequisite.  If the target got its commands from
+an implicit rule, this will be the first prerequisite added by the
+implicit rule (@pxref{Implicit Rules}).
+
+@vindex $?
+@vindex ? @r{(automatic variable)}
+@item $?
+The names of all the prerequisites that are newer than the target, with
+spaces between them.  For prerequisites which are archive members, only
+the member named is used (@pxref{Archives}).
+@cindex prerequisites, list of changed
+@cindex list of changed prerequisites
+
+@vindex $^
+@vindex ^ @r{(automatic variable)}
+@item $^
+The names of all the prerequisites, with spaces between them.  For
+prerequisites which are archive members, only the member named is used
+(@pxref{Archives}).  A target has only one prerequisite on each other file
+it depends on, no matter how many times each file is listed as a
+prerequisite.  So if you list a prerequisite more than once for a target,
+the value of @code{$^} contains just one copy of the name.  This list
+does @strong{not} contain any of the order-only prerequisites; for those
+see the @samp{$|} variable, below.
+@cindex prerequisites, list of all
+@cindex list of all prerequisites
+
+@vindex $+
+@vindex + @r{(automatic variable)}
+@item $+
+This is like @samp{$^}, but prerequisites listed more than once are
+duplicated in the order they were listed in the makefile.  This is
+primarily useful for use in linking commands where it is meaningful to
+repeat library file names in a particular order.
+
+@vindex $|
+@vindex | @r{(automatic variable)}
+@item $|
+The names of all the order-only prerequisites, with spaces between
+them.
+
+@vindex $*
+@vindex * @r{(automatic variable)}
+@item $*
+The stem with which an implicit rule matches (@pxref{Pattern Match, ,How
+Patterns Match}).  If the target is @file{dir/a.foo.b} and the target
+pattern is @file{a.%.b} then the stem is @file{dir/foo}.  The stem is
+useful for constructing names of related files.@refill
+@cindex stem, variable for
+
+In a static pattern rule, the stem is part of the file name that matched
+the @samp{%} in the target pattern.
+
+In an explicit rule, there is no stem; so @samp{$*} cannot be determined
+in that way.  Instead, if the target name ends with a recognized suffix
+(@pxref{Suffix Rules, ,Old-Fashioned Suffix Rules}), @samp{$*} is set to
+the target name minus the suffix.  For example, if the target name is
+@samp{foo.c}, then @samp{$*} is set to @samp{foo}, since @samp{.c} is a
+suffix.  GNU @code{make} does this bizarre thing only for compatibility
+with other implementations of @code{make}.  You should generally avoid
+using @samp{$*} except in implicit rules or static pattern rules.@refill
+
+If the target name in an explicit rule does not end with a recognized
+suffix, @samp{$*} is set to the empty string for that rule.
+@end table
+
+@samp{$?} is useful even in explicit rules when you wish to operate on only
+the prerequisites that have changed.  For example, suppose that an archive
+named @file{lib} is supposed to contain copies of several object files.
+This rule copies just the changed object files into the archive:
+
+@example
+@group
+lib: foo.o bar.o lose.o win.o
+        ar r lib $?
+@end group
+@end example
+
+Of the variables listed above, four have values that are single file
+names, and three have values that are lists of file names.  These seven
+have variants that get just the file's directory name or just the file
+name within the directory.  The variant variables' names are formed by
+appending @samp{D} or @samp{F}, respectively.  These variants are
+semi-obsolete in GNU @code{make} since the functions @code{dir} and
+@code{notdir} can be used to get a similar effect (@pxref{File Name
+Functions, , Functions for File Names}).  Note, however, that the
+@samp{D} variants all omit the trailing slash which always appears in
+the output of the @code{dir} function.  Here is a table of the variants:
+
+@table @samp
+@vindex $(@@D)
+@vindex @@D @r{(automatic variable)}
+@item $(@@D)
+The directory part of the file name of the target, with the trailing
+slash removed.  If the value of @samp{$@@} is @file{dir/foo.o} then
+@samp{$(@@D)} is @file{dir}.  This value is @file{.} if @samp{$@@} does
+not contain a slash.
+
+@vindex $(@@F)
+@vindex @@F @r{(automatic variable)}
+@item $(@@F)
+The file-within-directory part of the file name of the target.  If the
+value of @samp{$@@} is @file{dir/foo.o} then @samp{$(@@F)} is
+@file{foo.o}.  @samp{$(@@F)} is equivalent to @samp{$(notdir $@@)}.
+
+@vindex $(*D)
+@vindex *D @r{(automatic variable)}
+@item $(*D)
+@vindex $(*F)
+@vindex *F @r{(automatic variable)}
+@itemx $(*F)
+The directory part and the file-within-directory
+part of the stem; @file{dir} and @file{foo} in this example.
+
+@vindex $(%D)
+@vindex %D @r{(automatic variable)}
+@item $(%D)
+@vindex $(%F)
+@vindex %F @r{(automatic variable)}
+@itemx $(%F)
+The directory part and the file-within-directory part of the target
+archive member name.  This makes sense only for archive member targets
+of the form @file{@var{archive}(@var{member})} and is useful only when
+@var{member} may contain a directory name.  (@xref{Archive Members,
+,Archive Members as Targets}.)
+
+@vindex $(<D)
+@vindex <D @r{(automatic variable)}
+@item $(<D)
+@vindex $(<F)
+@vindex <F @r{(automatic variable)}
+@itemx $(<F)
+The directory part and the file-within-directory
+part of the first prerequisite.
+
+@vindex $(^D)
+@vindex ^D @r{(automatic variable)}
+@item $(^D)
+@vindex $(^F)
+@vindex ^F @r{(automatic variable)}
+@itemx $(^F)
+Lists of the directory parts and the file-within-directory
+parts of all prerequisites.
+
+@vindex $(+D)
+@vindex +D @r{(automatic variable)}
+@item $(+D)
+@vindex $(+F)
+@vindex +F @r{(automatic variable)}
+@itemx $(+F)
+Lists of the directory parts and the file-within-directory
+parts of all prerequisites, including multiple instances of duplicated
+prerequisites.
+
+@vindex $(?D)
+@vindex ?D @r{(automatic variable)}
+@item $(?D)
+@vindex $(?F)
+@vindex ?F @r{(automatic variable)}
+@itemx $(?F)
+Lists of the directory parts and the file-within-directory parts of
+all prerequisites that are newer than the target.
+@end table
+
+Note that we use a special stylistic convention when we talk about these
+automatic variables; we write ``the value of @samp{$<}'', rather than
+@w{``the variable @code{<}''} as we would write for ordinary variables
+such as @code{objects} and @code{CFLAGS}.  We think this convention
+looks more natural in this special case.  Please do not assume it has a
+deep significance; @samp{$<} refers to the variable named @code{<} just
+as @samp{$(CFLAGS)} refers to the variable named @code{CFLAGS}.
+You could just as well use @samp{$(<)} in place of @samp{$<}.
+
+@node Pattern Match, Match-Anything Rules, Automatic Variables, Pattern Rules
+@subsection How Patterns Match
+
+@cindex stem
+A target pattern is composed of a @samp{%} between a prefix and a suffix,
+either or both of which may be empty.  The pattern matches a file name only
+if the file name starts with the prefix and ends with the suffix, without
+overlap.  The text between the prefix and the suffix is called the
+@dfn{stem}.  Thus, when the pattern @samp{%.o} matches the file name
+@file{test.o}, the stem is @samp{test}.  The pattern rule prerequisites are
+turned into actual file names by substituting the stem for the character
+@samp{%}.  Thus, if in the same example one of the prerequisites is written
+as @samp{%.c}, it expands to @samp{test.c}.@refill
+
+When the target pattern does not contain a slash (and it usually does
+not), directory names in the file names are removed from the file name
+before it is compared with the target prefix and suffix.  After the
+comparison of the file name to the target pattern, the directory
+names, along with the slash that ends them, are added on to the
+prerequisite file names generated from the pattern rule's prerequisite
+patterns and the file name.  The directories are ignored only for the
+purpose of finding an implicit rule to use, not in the application of
+that rule.  Thus, @samp{e%t} matches the file name @file{src/eat},
+with @samp{src/a} as the stem.  When prerequisites are turned into file
+names, the directories from the stem are added at the front, while the
+rest of the stem is substituted for the @samp{%}.  The stem
+@samp{src/a} with a prerequisite pattern @samp{c%r} gives the file name
+@file{src/car}.@refill
+
+@node Match-Anything Rules, Canceling Rules, Pattern Match, Pattern Rules
+@subsection Match-Anything Pattern Rules
+
+@cindex match-anything rule
+@cindex terminal rule
+When a pattern rule's target is just @samp{%}, it matches any file name
+whatever.  We call these rules @dfn{match-anything} rules.  They are very
+useful, but it can take a lot of time for @code{make} to think about them,
+because it must consider every such rule for each file name listed either
+as a target or as a prerequisite.
+
+Suppose the makefile mentions @file{foo.c}.  For this target, @code{make}
+would have to consider making it by linking an object file @file{foo.c.o},
+or by C compilation-and-linking in one step from @file{foo.c.c}, or by
+Pascal compilation-and-linking from @file{foo.c.p}, and many other
+possibilities.
+
+We know these possibilities are ridiculous since @file{foo.c} is a C source
+file, not an executable.  If @code{make} did consider these possibilities,
+it would ultimately reject them, because files such as @file{foo.c.o} and
+@file{foo.c.p} would not exist.  But these possibilities are so
+numerous that @code{make} would run very slowly if it had to consider
+them.@refill
+
+To gain speed, we have put various constraints on the way @code{make}
+considers match-anything rules.  There are two different constraints that
+can be applied, and each time you define a match-anything rule you must
+choose one or the other for that rule.
+
+One choice is to mark the match-anything rule as @dfn{terminal} by defining
+it with a double colon.  When a rule is terminal, it does not apply unless
+its prerequisites actually exist.  Prerequisites that could be made with
+other implicit rules are not good enough.  In other words, no further
+chaining is allowed beyond a terminal rule.
+
+For example, the built-in implicit rules for extracting sources from RCS
+and SCCS files are terminal; as a result, if the file @file{foo.c,v} does
+not exist, @code{make} will not even consider trying to make it as an
+intermediate file from @file{foo.c,v.o} or from @file{RCS/SCCS/s.foo.c,v}.
+RCS and SCCS files are generally ultimate source files, which should not be
+remade from any other files; therefore, @code{make} can save time by not
+looking for ways to remake them.@refill
+
+If you do not mark the match-anything rule as terminal, then it is
+nonterminal.  A nonterminal match-anything rule cannot apply to a file name
+that indicates a specific type of data.  A file name indicates a specific
+type of data if some non-match-anything implicit rule target matches it.
+
+For example, the file name @file{foo.c} matches the target for the pattern
+rule @samp{%.c : %.y} (the rule to run Yacc).  Regardless of whether this
+rule is actually applicable (which happens only if there is a file
+@file{foo.y}), the fact that its target matches is enough to prevent
+consideration of any nonterminal match-anything rules for the file
+@file{foo.c}.  Thus, @code{make} will not even consider trying to make
+@file{foo.c} as an executable file from @file{foo.c.o}, @file{foo.c.c},
+@file{foo.c.p}, etc.@refill
+
+The motivation for this constraint is that nonterminal match-anything
+rules are used for making files containing specific types of data (such as
+executable files) and a file name with a recognized suffix indicates some
+other specific type of data (such as a C source file).
+
+Special built-in dummy pattern rules are provided solely to recognize
+certain file names so that nonterminal match-anything rules will not be
+considered.  These dummy rules have no prerequisites and no commands, and
+they are ignored for all other purposes.  For example, the built-in
+implicit rule
+
+@example
+%.p :
+@end example
+
+@noindent
+exists to make sure that Pascal source files such as @file{foo.p} match a
+specific target pattern and thereby prevent time from being wasted looking
+for @file{foo.p.o} or @file{foo.p.c}.
+
+Dummy pattern rules such as the one for @samp{%.p} are made for every
+suffix listed as valid for use in suffix rules (@pxref{Suffix Rules, ,Old-Fashioned Suffix Rules}).
+
+@node Canceling Rules,  , Match-Anything Rules, Pattern Rules
+@subsection Canceling Implicit Rules
+
+You can override a built-in implicit rule (or one you have defined
+yourself) by defining a new pattern rule with the same target and
+prerequisites, but different commands.  When the new rule is defined, the
+built-in one is replaced.  The new rule's position in the sequence of
+implicit rules is determined by where you write the new rule.
+
+You can cancel a built-in implicit rule by defining a pattern rule with the
+same target and prerequisites, but no commands.  For example, the following
+would cancel the rule that runs the assembler:
+
+@example
+%.o : %.s
+@end example
+
+@node Last Resort, Suffix Rules, Pattern Rules, Implicit Rules
+@section Defining Last-Resort Default Rules
+@cindex last-resort default rules
+@cindex default rules, last-resort
+
+You can define a last-resort implicit rule by writing a terminal
+match-anything pattern rule with no prerequisites (@pxref{Match-Anything
+Rules}).  This is just like any other pattern rule; the only thing
+special about it is that it will match any target.  So such a rule's
+commands are used for all targets and prerequisites that have no commands
+of their own and for which no other implicit rule applies.
+
+For example, when testing a makefile, you might not care if the source
+files contain real data, only that they exist.  Then you might do this:
+
+@example
+%::
+        touch $@@
+@end example
+
+@noindent
+to cause all the source files needed (as prerequisites) to be created
+automatically.
+
+@findex .DEFAULT
+You can instead define commands to be used for targets for which there
+are no rules at all, even ones which don't specify commands.  You do
+this by writing a rule for the target @code{.DEFAULT}.  Such a rule's
+commands are used for all prerequisites which do not appear as targets in
+any explicit rule, and for which no implicit rule applies.  Naturally,
+there is no @code{.DEFAULT} rule unless you write one.
+
+If you use @code{.DEFAULT} with no commands or prerequisites:
+
+@example
+.DEFAULT:
+@end example
+
+@noindent
+the commands previously stored for @code{.DEFAULT} are cleared.
+Then @code{make} acts as if you had never defined @code{.DEFAULT} at all.
+
+If you do not want a target to get the commands from a match-anything
+pattern rule or @code{.DEFAULT}, but you also do not want any commands
+to be run for the target, you can give it empty commands (@pxref{Empty
+Commands, ,Defining Empty Commands}).@refill
+
+You can use a last-resort rule to override part of another makefile.
+@xref{Overriding Makefiles, , Overriding Part of Another Makefile}.
+
+@node Suffix Rules, Implicit Rule Search, Last Resort, Implicit Rules
+@section Old-Fashioned Suffix Rules
+@cindex old-fashioned suffix rules
+@cindex suffix rule
+
+@dfn{Suffix rules} are the old-fashioned way of defining implicit rules for
+@code{make}.  Suffix rules are obsolete because pattern rules are more
+general and clearer.  They are supported in GNU @code{make} for
+compatibility with old makefiles.  They come in two kinds:
+@dfn{double-suffix} and @dfn{single-suffix}.@refill
+
+A double-suffix rule is defined by a pair of suffixes: the target suffix
+and the source suffix.  It matches any file whose name ends with the
+target suffix.  The corresponding implicit prerequisite is made by
+replacing the target suffix with the source suffix in the file name.  A
+two-suffix rule whose target and source suffixes are @samp{.o} and
+@samp{.c} is equivalent to the pattern rule @samp{%.o : %.c}.
+
+A single-suffix rule is defined by a single suffix, which is the source
+suffix.  It matches any file name, and the corresponding implicit
+prerequisite name is made by appending the source suffix.  A single-suffix
+rule whose source suffix is @samp{.c} is equivalent to the pattern rule
+@samp{% : %.c}.
+
+Suffix rule definitions are recognized by comparing each rule's target
+against a defined list of known suffixes.  When @code{make} sees a rule
+whose target is a known suffix, this rule is considered a single-suffix
+rule.  When @code{make} sees a rule whose target is two known suffixes
+concatenated, this rule is taken as a double-suffix rule.
+
+For example, @samp{.c} and @samp{.o} are both on the default list of
+known suffixes.  Therefore, if you define a rule whose target is
+@samp{.c.o}, @code{make} takes it to be a double-suffix rule with source
+suffix @samp{.c} and target suffix @samp{.o}.  Here is the old-fashioned
+way to define the rule for compiling a C source file:@refill
+
+@example
+.c.o:
+        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@@ $<
+@end example
+
+Suffix rules cannot have any prerequisites of their own.  If they have any,
+they are treated as normal files with funny names, not as suffix rules.
+Thus, the rule:
+
+@example
+.c.o: foo.h
+        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@@ $<
+@end example
+
+@noindent
+tells how to make the file @file{.c.o} from the prerequisite file
+@file{foo.h}, and is not at all like the pattern rule:
+
+@example
+%.o: %.c foo.h
+        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@@ $<
+@end example
+
+@noindent
+which tells how to make @samp{.o} files from @samp{.c} files, and makes all
+@samp{.o} files using this pattern rule also depend on @file{foo.h}.
+
+Suffix rules with no commands are also meaningless.  They do not remove
+previous rules as do pattern rules with no commands (@pxref{Canceling
+Rules, , Canceling Implicit Rules}).  They simply enter the suffix or pair of suffixes concatenated as
+a target in the data base.@refill
+
+@findex .SUFFIXES
+The known suffixes are simply the names of the prerequisites of the special
+target @code{.SUFFIXES}.  You can add your own suffixes by writing a rule
+for @code{.SUFFIXES} that adds more prerequisites, as in:
+
+@example
+.SUFFIXES: .hack .win
+@end example
+
+@noindent
+which adds @samp{.hack} and @samp{.win} to the end of the list of suffixes.
+
+If you wish to eliminate the default known suffixes instead of just adding
+to them, write a rule for @code{.SUFFIXES} with no prerequisites.  By
+special dispensation, this eliminates all existing prerequisites of
+@code{.SUFFIXES}.  You can then write another rule to add the suffixes you
+want.  For example,
+
+@example
+@group
+.SUFFIXES:            # @r{Delete the default suffixes}
+.SUFFIXES: .c .o .h   # @r{Define our suffix list}
+@end group
+@end example
+
+The @samp{-r} or @samp{--no-builtin-rules} flag causes the default
+list of suffixes to be empty.
+
+@vindex SUFFIXES
+The variable @code{SUFFIXES} is defined to the default list of suffixes
+before @code{make} reads any makefiles.  You can change the list of suffixes
+with a rule for the special target @code{.SUFFIXES}, but that does not alter
+this variable.
+
+@node Implicit Rule Search,  , Suffix Rules, Implicit Rules
+@section Implicit Rule Search Algorithm
+@cindex implicit rule, search algorithm
+@cindex search algorithm, implicit rule
+
+Here is the procedure @code{make} uses for searching for an implicit rule
+for a target @var{t}.  This procedure is followed for each double-colon
+rule with no commands, for each target of ordinary rules none of which have
+commands, and for each prerequisite that is not the target of any rule.  It
+is also followed recursively for prerequisites that come from implicit
+rules, in the search for a chain of rules.
+
+Suffix rules are not mentioned in this algorithm because suffix rules are
+converted to equivalent pattern rules once the makefiles have been read in.
+
+For an archive member target of the form
+@samp{@var{archive}(@var{member})}, the following algorithm is run
+twice, first using the entire target name @var{t}, and second using
+@samp{(@var{member})} as the target @var{t} if the first run found no
+rule.@refill
+
+@enumerate
+@item
+Split @var{t} into a directory part, called @var{d}, and the rest,
+called @var{n}.  For example, if @var{t} is @samp{src/foo.o}, then
+@var{d} is @samp{src/} and @var{n} is @samp{foo.o}.@refill
+
+@item
+Make a list of all the pattern rules one of whose targets matches
+@var{t} or @var{n}.  If the target pattern contains a slash, it is
+matched against @var{t}; otherwise, against @var{n}.
+
+@item
+If any rule in that list is @emph{not} a match-anything rule, then
+remove all nonterminal match-anything rules from the list.
+
+@item
+Remove from the list all rules with no commands.
+
+@item
+For each pattern rule in the list:
+
+@enumerate a
+@item
+Find the stem @var{s}, which is the nonempty part of @var{t} or @var{n}
+matched by the @samp{%} in the target pattern.@refill
+
+@item
+Compute the prerequisite names by substituting @var{s} for @samp{%}; if
+the target pattern does not contain a slash, append @var{d} to
+the front of each prerequisite name.@refill
+
+@item
+Test whether all the prerequisites exist or ought to exist.  (If a
+file name is mentioned in the makefile as a target or as an explicit
+prerequisite, then we say it ought to exist.)
+
+If all prerequisites exist or ought to exist, or there are no prerequisites,
+then this rule applies.
+@end enumerate
+
+@item
+If no pattern rule has been found so far, try harder.
+For each pattern rule in the list:
+
+@enumerate a
+@item
+If the rule is terminal, ignore it and go on to the next rule.
+
+@item
+Compute the prerequisite names as before.
+
+@item
+Test whether all the prerequisites exist or ought to exist.
+
+@item
+For each prerequisite that does not exist, follow this algorithm
+recursively to see if the prerequisite can be made by an implicit
+rule.
+
+@item
+If all prerequisites exist, ought to exist, or can be
+made by implicit rules, then this rule applies.
+@end enumerate
+
+@item
+If no implicit rule applies, the rule for @code{.DEFAULT}, if any,
+applies.  In that case, give @var{t} the same commands that
+@code{.DEFAULT} has.  Otherwise, there are no commands for @var{t}.
+@end enumerate
+
+Once a rule that applies has been found, for each target pattern of the
+rule other than the one that matched @var{t} or @var{n}, the @samp{%} in
+the pattern is replaced with @var{s} and the resultant file name is stored
+until the commands to remake the target file @var{t} are executed.  After
+these commands are executed, each of these stored file names are entered
+into the data base and marked as having been updated and having the same
+update status as the file @var{t}.
+
+When the commands of a pattern rule are executed for @var{t}, the automatic
+variables are set corresponding to the target and prerequisites.
+@xref{Automatic Variables}.
+
+@node Archives, Features, Implicit Rules, Top
+@chapter Using @code{make} to Update Archive Files
+@cindex archive
+
+@dfn{Archive files} are files containing named subfiles called
+@dfn{members}; they are maintained with the program @code{ar} and their
+main use is as subroutine libraries for linking.
+
+@menu
+* Archive Members::             Archive members as targets.
+* Archive Update::              The implicit rule for archive member targets.
+* Archive Pitfalls::            Dangers to watch out for when using archives.
+* Archive Suffix Rules::        You can write a special kind of suffix rule
+                                  for updating archives.
+@end menu
+
+@node Archive Members, Archive Update, Archives, Archives
+@section Archive Members as Targets
+@cindex archive member targets
+
+An individual member of an archive file can be used as a target or
+prerequisite in @code{make}.  You specify the member named @var{member} in
+archive file @var{archive} as follows:
+
+@example
+@var{archive}(@var{member})
+@end example
+
+@noindent
+This construct is available only in targets and prerequisites, not in
+commands!  Most programs that you might use in commands do not support this
+syntax and cannot act directly on archive members.  Only @code{ar} and
+other programs specifically designed to operate on archives can do so.
+Therefore, valid commands to update an archive member target probably must
+use @code{ar}.  For example, this rule says to create a member
+@file{hack.o} in archive @file{foolib} by copying the file @file{hack.o}:
+
+@example
+foolib(hack.o) : hack.o
+        ar cr foolib hack.o
+@end example
+
+In fact, nearly all archive member targets are updated in just this way
+and there is an implicit rule to do it for you.  @strong{Please note:} The
+@samp{c} flag to @code{ar} is required if the archive file does not
+already exist.
+
+To specify several members in the same archive, you can write all the
+member names together between the parentheses.  For example:
+
+@example
+foolib(hack.o kludge.o)
+@end example
+
+@noindent
+is equivalent to:
+
+@example
+foolib(hack.o) foolib(kludge.o)
+@end example
+
+@cindex wildcard, in archive member
+You can also use shell-style wildcards in an archive member reference.
+@xref{Wildcards, ,Using Wildcard Characters in File Names}.  For
+example, @w{@samp{foolib(*.o)}} expands to all existing members of the
+@file{foolib} archive whose names end in @samp{.o}; perhaps
+@samp{@w{foolib(hack.o)} @w{foolib(kludge.o)}}.
+
+@node Archive Update, Archive Pitfalls, Archive Members, Archives
+@section Implicit Rule for Archive Member Targets
+
+Recall that a target that looks like @file{@var{a}(@var{m})} stands for the
+member named @var{m} in the archive file @var{a}.
+
+When @code{make} looks for an implicit rule for such a target, as a special
+feature it considers implicit rules that match @file{(@var{m})}, as well as
+those that match the actual target @file{@var{a}(@var{m})}.
+
+This causes one special rule whose target is @file{(%)} to match.  This
+rule updates the target @file{@var{a}(@var{m})} by copying the file @var{m}
+into the archive.  For example, it will update the archive member target
+@file{foo.a(bar.o)} by copying the @emph{file} @file{bar.o} into the
+archive @file{foo.a} as a @emph{member} named @file{bar.o}.
+
+When this rule is chained with others, the result is very powerful.
+Thus, @samp{make "foo.a(bar.o)"} (the quotes are needed to protect the
+@samp{(} and @samp{)} from being interpreted specially by the shell) in
+the presence of a file @file{bar.c} is enough to cause the following
+commands to be run, even without a makefile:
+
+@example
+cc -c bar.c -o bar.o
+ar r foo.a bar.o
+rm -f bar.o
+@end example
+
+@noindent
+Here @code{make} has envisioned the file @file{bar.o} as an intermediate
+file.  @xref{Chained Rules, ,Chains of Implicit Rules}.
+
+Implicit rules such as this one are written using the automatic variable
+@samp{$%}.  @xref{Automatic Variables}.
+
+An archive member name in an archive cannot contain a directory name, but
+it may be useful in a makefile to pretend that it does.  If you write an
+archive member target @file{foo.a(dir/file.o)}, @code{make} will perform
+automatic updating with this command:
+
+@example
+ar r foo.a dir/file.o
+@end example
+
+@noindent
+which has the effect of copying the file @file{dir/file.o} into a member
+named @file{file.o}.  In connection with such usage, the automatic variables
+@code{%D} and @code{%F} may be useful.
+
+@menu
+* Archive Symbols::             How to update archive symbol directories.
+@end menu
+
+@node Archive Symbols,  , Archive Update, Archive Update
+@subsection Updating Archive Symbol Directories
+@cindex @code{__.SYMDEF}
+@cindex updating archive symbol directories
+@cindex archive symbol directory updating
+@cindex symbol directories, updating archive
+@cindex directories, updating archive symbol
+
+An archive file that is used as a library usually contains a special member
+named @file{__.SYMDEF} that contains a directory of the external symbol
+names defined by all the other members.  After you update any other
+members, you need to update @file{__.SYMDEF} so that it will summarize the
+other members properly.  This is done by running the @code{ranlib} program:
+
+@example
+ranlib @var{archivefile}
+@end example
+
+Normally you would put this command in the rule for the archive file,
+and make all the members of the archive file prerequisites of that rule.
+For example,
+
+@example
+libfoo.a: libfoo.a(x.o) libfoo.a(y.o) @dots{}
+        ranlib libfoo.a
+@end example
+
+@noindent
+The effect of this is to update archive members @file{x.o}, @file{y.o},
+etc., and then update the symbol directory member @file{__.SYMDEF} by
+running @code{ranlib}.  The rules for updating the members are not shown
+here; most likely you can omit them and use the implicit rule which copies
+files into the archive, as described in the preceding section.
+
+This is not necessary when using the GNU @code{ar} program, which
+updates the @file{__.SYMDEF} member automatically.
+
+@node Archive Pitfalls, Archive Suffix Rules, Archive Update, Archives
+@section Dangers When Using Archives
+@cindex archive, and parallel execution
+@cindex parallel execution, and archive update
+@cindex archive, and @code{-j}
+@cindex @code{-j}, and archive update
+
+It is important to be careful when using parallel execution (the
+@code{-j} switch; @pxref{Parallel, ,Parallel Execution}) and archives.
+If multiple @code{ar} commands run at the same time on the same archive
+file, they will not know about each other and can corrupt the file.
+
+Possibly a future version of @code{make} will provide a mechanism to
+circumvent this problem by serializing all commands that operate on the
+same archive file.  But for the time being, you must either write your
+makefiles to avoid this problem in some other way, or not use @code{-j}.
+
+@node Archive Suffix Rules,  , Archive Pitfalls, Archives
+@section Suffix Rules for Archive Files
+@cindex suffix rule, for archive
+@cindex archive, suffix rule for
+@cindex library archive, suffix rule for
+@cindex @code{.a} (archives)
+
+You can write a special kind of suffix rule for dealing with archive
+files.  @xref{Suffix Rules}, for a full explanation of suffix rules.
+Archive suffix rules are obsolete in GNU @code{make}, because pattern
+rules for archives are a more general mechanism (@pxref{Archive
+Update}).  But they are retained for compatibility with other
+@code{make}s.
+
+To write a suffix rule for archives, you simply write a suffix rule
+using the target suffix @samp{.a} (the usual suffix for archive files).
+For example, here is the old-fashioned suffix rule to update a library
+archive from C source files:
+
+@example
+@group
+.c.a:
+        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
+        $(AR) r $@@ $*.o
+        $(RM) $*.o
+@end group
+@end example
+
+@noindent
+This works just as if you had written the pattern rule:
+
+@example
+@group
+(%.o): %.c
+        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
+        $(AR) r $@@ $*.o
+        $(RM) $*.o
+@end group
+@end example
+
+In fact, this is just what @code{make} does when it sees a suffix rule
+with @samp{.a} as the target suffix.  Any double-suffix rule
+@w{@samp{.@var{x}.a}} is converted to a pattern rule with the target
+pattern @samp{(%.o)} and a prerequisite pattern of @samp{%.@var{x}}.
+
+Since you might want to use @samp{.a} as the suffix for some other kind
+of file, @code{make} also converts archive suffix rules to pattern rules
+in the normal way (@pxref{Suffix Rules}).  Thus a double-suffix rule
+@w{@samp{.@var{x}.a}} produces two pattern rules: @samp{@w{(%.o):}
+@w{%.@var{x}}} and @samp{@w{%.a}: @w{%.@var{x}}}.@refill
+
+@node Features, Missing, Archives, Top
+@chapter Features of GNU @code{make}
+@cindex features of GNU @code{make}
+@cindex portability
+@cindex compatibility
+
+Here is a summary of the features of GNU @code{make}, for comparison
+with and credit to other versions of @code{make}.  We consider the
+features of @code{make} in 4.2 BSD systems as a baseline.  If you are
+concerned with writing portable makefiles, you should not use the
+features of @code{make} listed here, nor the ones in @ref{Missing}.
+
+Many features come from the version of @code{make} in System V.
+
+@itemize @bullet
+@item
+The @code{VPATH} variable and its special meaning.
+@xref{Directory Search, , Searching Directories for Prerequisites}.
+This feature exists in System V @code{make}, but is undocumented.
+It is documented in 4.3 BSD @code{make} (which says it mimics System V's
+@code{VPATH} feature).@refill
+
+@item
+Included makefiles.  @xref{Include, ,Including Other Makefiles}.
+Allowing multiple files to be included with a single directive is a GNU
+extension.
+
+@item
+Variables are read from and communicated via the environment.
+@xref{Environment, ,Variables from the Environment}.
+
+@item
+Options passed through the variable @code{MAKEFLAGS} to recursive
+invocations of @code{make}.
+@xref{Options/Recursion, ,Communicating Options to a Sub-@code{make}}.
+
+@item
+The automatic variable @code{$%} is set to the member name
+in an archive reference.  @xref{Automatic Variables}.
+
+@item
+The automatic variables @code{$@@}, @code{$*}, @code{$<}, @code{$%},
+and @code{$?} have corresponding forms like @code{$(@@F)} and
+@code{$(@@D)}.  We have generalized this to @code{$^} as an obvious
+extension.  @xref{Automatic Variables}.@refill
+
+@item
+Substitution variable references.
+@xref{Reference, ,Basics of Variable References}.
+
+@item
+The command-line options @samp{-b} and @samp{-m}, accepted and
+ignored.  In System V @code{make}, these options actually do something.
+
+@item
+Execution of recursive commands to run @code{make} via the variable
+@code{MAKE} even if @samp{-n}, @samp{-q} or @samp{-t} is specified.
+@xref{Recursion, ,Recursive Use of @code{make}}.
+
+@item
+Support for suffix @samp{.a} in suffix rules.  @xref{Archive Suffix
+Rules}.  This feature is obsolete in GNU @code{make}, because the
+general feature of rule chaining (@pxref{Chained Rules, ,Chains of
+Implicit Rules}) allows one pattern rule for installing members in an
+archive (@pxref{Archive Update}) to be sufficient.
+
+@item
+The arrangement of lines and backslash-newline combinations in
+commands is retained when the commands are printed, so they appear as
+they do in the makefile, except for the stripping of initial
+whitespace.
+@end itemize
+
+The following features were inspired by various other versions of
+@code{make}.  In some cases it is unclear exactly which versions inspired
+which others.
+
+@itemize @bullet
+@item
+Pattern rules using @samp{%}.
+This has been implemented in several versions of @code{make}.
+We're not sure who invented it first, but it's been spread around a bit.
+@xref{Pattern Rules, ,Defining and Redefining Pattern Rules}.@refill
+
+@item
+Rule chaining and implicit intermediate files.
+This was implemented by Stu Feldman in his version of @code{make}
+for AT&T Eighth Edition Research Unix, and later by Andrew Hume of
+AT&T Bell Labs in his @code{mk} program (where he terms it
+``transitive closure'').  We do not really know if
+we got this from either of them or thought it up ourselves at the
+same time.  @xref{Chained Rules, ,Chains of Implicit Rules}.
+
+@item
+The automatic variable @code{$^} containing a list of all prerequisites
+of the current target.  We did not invent this, but we have no idea who
+did.  @xref{Automatic Variables}.  The automatic variable
+@code{$+} is a simple extension of @code{$^}.
+
+@item
+The ``what if'' flag (@samp{-W} in GNU @code{make}) was (as far as we know)
+invented by Andrew Hume in @code{mk}.
+@xref{Instead of Execution, ,Instead of Executing the Commands}.
+
+@item
+The concept of doing several things at once (parallelism) exists in
+many incarnations of @code{make} and similar programs, though not in the
+System V or BSD implementations.  @xref{Execution, ,Command Execution}.
+
+@item
+Modified variable references using pattern substitution come from
+SunOS 4.  @xref{Reference, ,Basics of Variable References}.
+This functionality was provided in GNU @code{make} by the
+@code{patsubst} function before the alternate syntax was implemented
+for compatibility with SunOS 4.  It is not altogether clear who
+inspired whom, since GNU @code{make} had @code{patsubst} before SunOS
+4 was released.@refill
+
+@item
+The special significance of @samp{+} characters preceding command lines
+(@pxref{Instead of Execution, ,Instead of Executing the Commands}) is
+mandated by
+@cite{IEEE Standard 1003.2-1992} (POSIX.2).
+
+@item
+The @samp{+=} syntax to append to the value of a variable comes from SunOS
+4 @code{make}.  @xref{Appending, , Appending More Text to Variables}.
+
+@item
+The syntax @w{@samp{@var{archive}(@var{mem1} @var{mem2}@dots{})}} to list
+multiple members in a single archive file comes from SunOS 4 @code{make}.
+@xref{Archive Members}.
+
+@item
+The @code{-include} directive to include makefiles with no error for a
+nonexistent file comes from SunOS 4 @code{make}.  (But note that SunOS 4
+@code{make} does not allow multiple makefiles to be specified in one
+@code{-include} directive.)  The same feature appears with the name
+@code{sinclude} in SGI @code{make} and perhaps others.
+@end itemize
+
+The remaining features are inventions new in GNU @code{make}:
+
+@itemize @bullet
+@item
+Use the @samp{-v} or @samp{--version} option to print version and
+copyright information.
+
+@item
+Use the @samp{-h} or @samp{--help} option to summarize the options to
+@code{make}.
+
+@item
+Simply-expanded variables.  @xref{Flavors, ,The Two Flavors of Variables}.
+
+@item
+Pass command-line variable assignments automatically through the
+variable @code{MAKE} to recursive @code{make} invocations.
+@xref{Recursion, ,Recursive Use of @code{make}}.
+
+@item
+Use the @samp{-C} or @samp{--directory} command option to change
+directory.  @xref{Options Summary, ,Summary of Options}.
+
+@item
+Make verbatim variable definitions with @code{define}.
+@xref{Defining, ,Defining Variables Verbatim}.
+
+@item
+Declare phony targets with the special target @code{.PHONY}.
+
+Andrew Hume of AT&T Bell Labs implemented a similar feature with a
+different syntax in his @code{mk} program.  This seems to be a case of
+parallel discovery.  @xref{Phony Targets, ,Phony Targets}.
+
+@item
+Manipulate text by calling functions.
+@xref{Functions, ,Functions for Transforming Text}.
+
+@item
+Use the @samp{-o} or @samp{--old-file}
+option to pretend a file's modification-time is old.
+@xref{Avoiding Compilation, ,Avoiding Recompilation of Some Files}.
+
+@item
+Conditional execution.
+
+This feature has been implemented numerous times in various versions
+of @code{make}; it seems a natural extension derived from the features
+of the C preprocessor and similar macro languages and is not a
+revolutionary concept.  @xref{Conditionals, ,Conditional Parts of Makefiles}.
+
+@item
+Specify a search path for included makefiles.
+@xref{Include, ,Including Other Makefiles}.
+
+@item
+Specify extra makefiles to read with an environment variable.
+@xref{MAKEFILES Variable, ,The Variable @code{MAKEFILES}}.
+
+@item
+Strip leading sequences of @samp{./} from file names, so that
+@file{./@var{file}} and @file{@var{file}} are considered to be the
+same file.@refill
+
+@item
+Use a special search method for library prerequisites written in the
+form @samp{-l@var{name}}.
+@xref{Libraries/Search, ,Directory Search for Link Libraries}.
+
+@item
+Allow suffixes for suffix rules
+(@pxref{Suffix Rules, ,Old-Fashioned Suffix Rules}) to contain any
+characters.  In other versions of @code{make}, they must begin with
+@samp{.} and not contain any @samp{/} characters.
+
+@item
+Keep track of the current level of @code{make} recursion using the
+variable @code{MAKELEVEL}.  @xref{Recursion, ,Recursive Use of @code{make}}.
+
+@item
+Provide any goals given on the command line in the variable
+@code{MAKECMDGOALS}.  @xref{Goals, ,Arguments to Specify the Goals}.
+
+@item
+Specify static pattern rules.  @xref{Static Pattern, ,Static Pattern Rules}.
+
+@item
+Provide selective @code{vpath} search.
+@xref{Directory Search, ,Searching Directories for Prerequisites}.
+
+@item
+Provide computed variable references.
+@xref{Reference, ,Basics of Variable References}.
+
+@item
+Update makefiles.  @xref{Remaking Makefiles, ,How Makefiles Are Remade}.
+System V @code{make} has a very, very limited form of this
+functionality in that it will check out SCCS files for makefiles.
+
+@item
+Various new built-in implicit rules.
+@xref{Catalogue of Rules, ,Catalogue of Implicit Rules}.
+
+@item
+The built-in variable @samp{MAKE_VERSION} gives the version number of
+@code{make}.
+@vindex MAKE_VERSION
+@end itemize
+
+@node Missing, Makefile Conventions, Features, Top
+@chapter Incompatibilities and Missing Features
+@cindex incompatibilities
+@cindex missing features
+@cindex features, missing
+
+The @code{make} programs in various other systems support a few features
+that are not implemented in GNU @code{make}.  The POSIX.2 standard
+(@cite{IEEE Standard 1003.2-1992}) which specifies @code{make} does not
+require any of these features.@refill
+
+@itemize @bullet
+@item
+A target of the form @samp{@var{file}((@var{entry}))} stands for a member
+of archive file @var{file}.  The member is chosen, not by name, but by
+being an object file which defines the linker symbol @var{entry}.@refill
+
+This feature was not put into GNU @code{make} because of the
+nonmodularity of putting knowledge into @code{make} of the internal
+format of archive file symbol tables.
+@xref{Archive Symbols, ,Updating Archive Symbol Directories}.
+
+@item
+Suffixes (used in suffix rules) that end with the character @samp{~}
+have a special meaning to System V @code{make};
+they refer to the SCCS file that corresponds
+to the file one would get without the @samp{~}.  For example, the
+suffix rule @samp{.c~.o} would make the file @file{@var{n}.o} from
+the SCCS file @file{s.@var{n}.c}.  For complete coverage, a whole
+series of such suffix rules is required.
+@xref{Suffix Rules, ,Old-Fashioned Suffix Rules}.
+
+In GNU @code{make}, this entire series of cases is handled by two
+pattern rules for extraction from SCCS, in combination with the
+general feature of rule chaining.
+@xref{Chained Rules, ,Chains of Implicit Rules}.
+
+@item
+In System V and 4.3 BSD @code{make}, files found by @code{VPATH} search
+(@pxref{Directory Search, ,Searching Directories for Prerequisites}) have their names changed inside command
+strings.  We feel it is much cleaner to always use automatic variables
+and thus make this feature obsolete.@refill
+
+@item
+In some Unix @code{make}s, the automatic variable @code{$*} appearing in
+the prerequisites of a rule has the amazingly strange ``feature'' of
+expanding to the full name of the @emph{target of that rule}.  We cannot
+imagine what went on in the minds of Unix @code{make} developers to do
+this; it is utterly inconsistent with the normal definition of @code{$*}.
+@vindex * @r{(automatic variable), unsupported bizarre usage}
+
+@item
+In some Unix @code{make}s, implicit rule search
+(@pxref{Implicit Rules, ,Using Implicit Rules}) is apparently done for
+@emph{all} targets, not just those without commands.  This means you can
+do:@refill
+
+@example
+@group
+foo.o:
+        cc -c foo.c
+@end group
+@end example
+
+@noindent
+and Unix @code{make} will intuit that @file{foo.o} depends on
+@file{foo.c}.@refill
+
+We feel that such usage is broken.  The prerequisite properties of
+@code{make} are well-defined (for GNU @code{make}, at least),
+and doing such a thing simply does not fit the model.@refill
+
+@item
+GNU @code{make} does not include any built-in implicit rules for
+compiling or preprocessing EFL programs.  If we hear of anyone who is
+using EFL, we will gladly add them.
+
+@item
+It appears that in SVR4 @code{make}, a suffix rule can be specified with
+no commands, and it is treated as if it had empty commands
+(@pxref{Empty Commands}).  For example:
+
+@example
+.c.a:
+@end example
+
+@noindent
+will override the built-in @file{.c.a} suffix rule.
+
+We feel that it is cleaner for a rule without commands to always simply
+add to the prerequisite list for the target.  The above example can be
+easily rewritten to get the desired behavior in GNU @code{make}:
+
+@example
+.c.a: ;
+@end example
+
+@item
+Some versions of @code{make} invoke the shell with the @samp{-e} flag,
+except under @samp{-k} (@pxref{Testing, ,Testing the Compilation of a
+Program}).  The @samp{-e} flag tells the shell to exit as soon as any
+program it runs returns a nonzero status.  We feel it is cleaner to
+write each shell command line to stand on its own and not require this
+special treatment.
+@end itemize
+
+@comment The makefile standards are in a separate file that is also
+@comment included by standards.texi.
+@include make-stds.texi
+
+@node Quick Reference, Error Messages, Makefile Conventions, Top
+@appendix Quick Reference
+
+This appendix summarizes the directives, text manipulation functions,
+and special variables which GNU @code{make} understands.
+@xref{Special Targets}, @ref{Catalogue of Rules, ,Catalogue of Implicit Rules},
+and @ref{Options Summary, ,Summary of Options},
+for other summaries.
+
+Here is a summary of the directives GNU @code{make} recognizes:
+
+@table @code
+@item define @var{variable}
+@itemx endef
+
+Define a multi-line, recursively-expanded variable.@*
+@xref{Sequences}.
+
+@item ifdef @var{variable}
+@itemx ifndef @var{variable}
+@itemx ifeq (@var{a},@var{b})
+@itemx ifeq "@var{a}" "@var{b}"
+@itemx ifeq '@var{a}' '@var{b}'
+@itemx ifneq (@var{a},@var{b})
+@itemx ifneq "@var{a}" "@var{b}"
+@itemx ifneq '@var{a}' '@var{b}'
+@itemx else
+@itemx endif
+
+Conditionally evaluate part of the makefile.@*
+@xref{Conditionals}.
+
+@item include @var{file}
+@itemx -include @var{file}
+@itemx sinclude @var{file}
+
+Include another makefile.@*
+@xref{Include, ,Including Other Makefiles}.
+
+@item override @var{variable} = @var{value}
+@itemx override @var{variable} := @var{value}
+@itemx override @var{variable} += @var{value}
+@itemx override @var{variable} ?= @var{value}
+@itemx override define @var{variable}
+@itemx endef
+
+Define a variable, overriding any previous definition, even one from
+the command line.@*
+@xref{Override Directive, ,The @code{override} Directive}.
+
+@item export
+
+Tell @code{make} to export all variables to child processes by default.@*
+@xref{Variables/Recursion, , Communicating Variables to a Sub-@code{make}}.
+
+@item export @var{variable}
+@itemx export @var{variable} = @var{value}
+@itemx export @var{variable} := @var{value}
+@itemx export @var{variable} += @var{value}
+@itemx export @var{variable} ?= @var{value}
+@itemx unexport @var{variable}
+Tell @code{make} whether or not to export a particular variable to child
+processes.@*
+@xref{Variables/Recursion, , Communicating Variables to a Sub-@code{make}}.
+
+@item vpath @var{pattern} @var{path}
+Specify a search path for files matching a @samp{%} pattern.@*
+@xref{Selective Search, , The @code{vpath} Directive}.
+
+@item vpath @var{pattern}
+Remove all search paths previously specified for @var{pattern}.
+
+@item vpath
+Remove all search paths previously specified in any @code{vpath}
+directive.
+@end table
+
+Here is a summary of the built-in functions (@pxref{Functions}):
+
+@table @code
+@item $(subst @var{from},@var{to},@var{text})
+Replace @var{from} with @var{to} in @var{text}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(patsubst @var{pattern},@var{replacement},@var{text})
+Replace words matching @var{pattern} with @var{replacement} in @var{text}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(strip @var{string})
+Remove excess whitespace characters from @var{string}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(findstring @var{find},@var{text})
+Locate @var{find} in @var{text}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(filter @var{pattern}@dots{},@var{text})
+Select words in @var{text} that match one of the @var{pattern} words.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(filter-out @var{pattern}@dots{},@var{text})
+Select words in @var{text} that @emph{do not} match any of the @var{pattern} words.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(sort @var{list})
+Sort the words in @var{list} lexicographically, removing duplicates.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(word @var{n},@var{text})
+Extract the @var{n}th word (one-origin) of @var{text}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(words @var{text})
+Count the number of words in @var{text}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(wordlist @var{s},@var{e},@var{text})
+Returns the list of words in @var{text} from @var{s} to @var{e}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(firstword @var{names}@dots{})
+Extract the first word of @var{names}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(lastword @var{names}@dots{})
+Extract the last word of @var{names}.@*
+@xref{Text Functions, , Functions for String Substitution and Analysis}.
+
+@item $(dir @var{names}@dots{})
+Extract the directory part of each file name.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(notdir @var{names}@dots{})
+Extract the non-directory part of each file name.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(suffix @var{names}@dots{})
+Extract the suffix (the last @samp{.} and following characters) of each file name.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(basename @var{names}@dots{})
+Extract the base name (name without suffix) of each file name.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(addsuffix @var{suffix},@var{names}@dots{})
+Append @var{suffix} to each word in @var{names}.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(addprefix @var{prefix},@var{names}@dots{})
+Prepend @var{prefix} to each word in @var{names}.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(join @var{list1},@var{list2})
+Join two parallel lists of words.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(wildcard @var{pattern}@dots{})
+Find file names matching a shell file name pattern (@emph{not} a
+@samp{%} pattern).@*
+@xref{Wildcard Function, ,The Function @code{wildcard}}.
+
+@item $(realpath @var{names}@dots{})
+For each file name in @var{names}, expand to an absolute name that
+does not contain any @code{.}, @code{..}, nor symlinks.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(abspath @var{names}@dots{})
+For each file name in @var{names}, expand to an absolute name that
+does not contain any @code{.} or @code{..} components, but preserves
+symlinks.@*
+@xref{File Name Functions, ,Functions for File Names}.
+
+@item $(error @var{text}@dots{})
+
+When this function is evaluated, @code{make} generates a fatal error
+with the message @var{text}.@*
+@xref{Make Control Functions, ,Functions That Control Make}.
+
+@item $(warning @var{text}@dots{})
+
+When this function is evaluated, @code{make} generates a warning with
+the message @var{text}.@*
+@xref{Make Control Functions, ,Functions That Control Make}.
+
+@item $(shell @var{command})
+
+Execute a shell command and return its output.@*
+@xref{Shell Function, , The @code{shell} Function}.
+
+@item $(origin @var{variable})
+
+Return a string describing how the @code{make} variable @var{variable} was
+defined.@*
+@xref{Origin Function, , The @code{origin} Function}.
+
+@item $(flavor @var{variable})
+
+Return a string describing the flavor of the @code{make} variable
+@var{variable}.@*
+@xref{Flavor Function, , The @code{flavor} Function}.
+
+@item $(foreach @var{var},@var{words},@var{text})
+
+Evaluate @var{text} with @var{var} bound to each word in @var{words},
+and concatenate the results.@*
+@xref{Foreach Function, ,The @code{foreach} Function}.
+
+@item $(call @var{var},@var{param},@dots{})
+
+Evaluate the variable @var{var} replacing any references to @code{$(1)},
+@code{$(2)} with the first, second, etc.@: @var{param} values.@*
+@xref{Call Function, ,The @code{call} Function}.
+
+@item $(eval @var{text})
+
+Evaluate @var{text} then read the results as makefile commands.
+Expands to the empty string.@*
+@xref{Eval Function, ,The @code{eval} Function}.
+
+@item $(value @var{var})
+
+Evaluates to the contents of the variable @var{var}, with no expansion
+performed on it.@*
+@xref{Value Function, ,The @code{value} Function}.
+@end table
+
+Here is a summary of the automatic variables.
+@xref{Automatic Variables},
+for full information.
+
+@table @code
+@item $@@
+The file name of the target.
+
+@item $%
+The target member name, when the target is an archive member.
+
+@item $<
+The name of the first prerequisite.
+
+@item $?
+The names of all the prerequisites that are
+newer than the target, with spaces between them.
+For prerequisites which are archive members, only
+the member named is used (@pxref{Archives}).
+
+@item $^
+@itemx $+
+The names of all the prerequisites, with spaces between them.  For
+prerequisites which are archive members, only the member named is used
+(@pxref{Archives}).  The value of @code{$^} omits duplicate
+prerequisites, while @code{$+} retains them and preserves their order.
+
+@item $*
+The stem with which an implicit rule matches
+(@pxref{Pattern Match, ,How Patterns Match}).
+
+@item $(@@D)
+@itemx $(@@F)
+The directory part and the file-within-directory part of @code{$@@}.
+
+@item $(*D)
+@itemx $(*F)
+The directory part and the file-within-directory part of @code{$*}.
+
+@item $(%D)
+@itemx $(%F)
+The directory part and the file-within-directory part of @code{$%}.
+
+@item $(<D)
+@itemx $(<F)
+The directory part and the file-within-directory part of @code{$<}.
+
+@item $(^D)
+@itemx $(^F)
+The directory part and the file-within-directory part of @code{$^}.
+
+@item $(+D)
+@itemx $(+F)
+The directory part and the file-within-directory part of @code{$+}.
+
+@item $(?D)
+@itemx $(?F)
+The directory part and the file-within-directory part of @code{$?}.
+@end table
+
+These variables are used specially by GNU @code{make}:
+
+@table @code
+@item MAKEFILES
+
+Makefiles to be read on every invocation of @code{make}.@*
+@xref{MAKEFILES Variable, ,The Variable @code{MAKEFILES}}.
+
+@item VPATH
+
+Directory search path for files not found in the current directory.@*
+@xref{General Search, , @code{VPATH} Search Path for All Prerequisites}.
+
+@item SHELL
+
+The name of the system default command interpreter, usually @file{/bin/sh}.
+You can set @code{SHELL} in the makefile to change the shell used to run
+commands.  @xref{Execution, ,Command Execution}.  The @code{SHELL}
+variable is handled specially when importing from and exporting to the
+environment.  @xref{Choosing the Shell}.
+
+@item MAKESHELL
+
+On MS-DOS only, the name of the command interpreter that is to be used
+by @code{make}.  This value takes precedence over the value of
+@code{SHELL}.  @xref{Execution, ,MAKESHELL variable}.
+
+@item MAKE
+
+The name with which @code{make} was invoked.
+Using this variable in commands has special meaning.
+@xref{MAKE Variable, ,How the @code{MAKE} Variable Works}.
+
+@item MAKELEVEL
+
+The number of levels of recursion (sub-@code{make}s).@*
+@xref{Variables/Recursion}.
+
+@item MAKEFLAGS
+
+The flags given to @code{make}.  You can set this in the environment or
+a makefile to set flags.@*
+@xref{Options/Recursion, ,Communicating Options to a Sub-@code{make}}.
+
+It is @emph{never} appropriate to use @code{MAKEFLAGS} directly on a
+command line: its contents may not be quoted correctly for use in the
+shell.  Always allow recursive @code{make}'s to obtain these values
+through the environment from its parent.
+
+@item MAKECMDGOALS
+
+The targets given to @code{make} on the command line.  Setting this
+variable has no effect on the operation of @code{make}.@*
+@xref{Goals, ,Arguments to Specify the Goals}.
+
+@item CURDIR
+
+Set to the pathname of the current working directory (after all
+@code{-C} options are processed, if any).  Setting this variable has no
+effect on the operation of @code{make}.@*
+@xref{Recursion, ,Recursive Use of @code{make}}.
+
+@item SUFFIXES
+
+The default list of suffixes before @code{make} reads any makefiles.
+
+@item .LIBPATTERNS
+Defines the naming of the libraries @code{make} searches for, and their
+order.@*
+@xref{Libraries/Search, ,Directory Search for Link Libraries}.
+@end table
+
+@node Error Messages, Complex Makefile, Quick Reference, Top
+@comment  node-name,  next,  previous,  up
+@appendix Errors Generated by Make
+
+Here is a list of the more common errors you might see generated by
+@code{make}, and some information about what they mean and how to fix
+them.
+
+Sometimes @code{make} errors are not fatal, especially in the presence
+of a @code{-} prefix on a command script line, or the @code{-k} command
+line option.  Errors that are fatal are prefixed with the string
+@code{***}.
+
+Error messages are all either prefixed with the name of the program
+(usually @samp{make}), or, if the error is found in a makefile, the name
+of the file and linenumber containing the problem.
+
+In the table below, these common prefixes are left off.
+
+@table @samp
+
+@item [@var{foo}] Error @var{NN}
+@itemx [@var{foo}] @var{signal description}
+These errors are not really @code{make} errors at all.  They mean that a
+program that @code{make} invoked as part of a command script returned a
+non-0 error code (@samp{Error @var{NN}}), which @code{make} interprets
+as failure, or it exited in some other abnormal fashion (with a
+signal of some type).  @xref{Errors, ,Errors in Commands}.
+
+If no @code{***} is attached to the message, then the subprocess failed
+but the rule in the makefile was prefixed with the @code{-} special
+character, so @code{make} ignored the error.
+
+@item missing separator.  Stop.
+@itemx missing separator (did you mean TAB instead of 8 spaces?).  Stop.
+This means that @code{make} could not understand much of anything about
+the command line it just read.  GNU @code{make} looks for various kinds
+of separators (@code{:}, @code{=}, TAB characters, etc.) to help it
+decide what kind of commandline it's seeing.  This means it couldn't
+find a valid one.
+
+One of the most common reasons for this message is that you (or perhaps
+your oh-so-helpful editor, as is the case with many MS-Windows editors)
+have attempted to indent your command scripts with spaces instead of a
+TAB character.  In this case, @code{make} will use the second form of
+the error above.  Remember that every line in the command script must
+begin with a TAB character.  Eight spaces do not count.  @xref{Rule
+Syntax}.
+
+@item commands commence before first target.  Stop.
+@itemx missing rule before commands.  Stop.
+This means the first thing in the makefile seems to be part of a command
+script: it begins with a TAB character and doesn't appear to be a legal
+@code{make} command (such as a variable assignment).  Command scripts
+must always be associated with a target.
+
+The second form is generated if the line has a semicolon as the first
+non-whitespace character; @code{make} interprets this to mean you left
+out the "target: prerequisite" section of a rule.  @xref{Rule Syntax}.
+
+@item No rule to make target `@var{xxx}'.
+@itemx No rule to make target `@var{xxx}', needed by `@var{yyy}'.
+This means that @code{make} decided it needed to build a target, but
+then couldn't find any instructions in the makefile on how to do that,
+either explicit or implicit (including in the default rules database).
+
+If you want that file to be built, you will need to add a rule to your
+makefile describing how that target can be built.  Other possible
+sources of this problem are typos in the makefile (if that filename is
+wrong) or a corrupted source tree (if that file is not supposed to be
+built, but rather only a prerequisite).
+
+@item No targets specified and no makefile found.  Stop.
+@itemx No targets.  Stop.
+The former means that you didn't provide any targets to be built on the
+command line, and @code{make} couldn't find any makefiles to read in.
+The latter means that some makefile was found, but it didn't contain any
+default goal and none was given on the command line.  GNU @code{make}
+has nothing to do in these situations.
+@xref{Makefile Arguments, ,Arguments to Specify the Makefile}.@refill
+
+@item Makefile `@var{xxx}' was not found.
+@itemx Included makefile `@var{xxx}' was not found.
+A makefile specified on the command line (first form) or included
+(second form) was not found.
+
+@item warning: overriding commands for target `@var{xxx}'
+@itemx warning: ignoring old commands for target `@var{xxx}'
+GNU @code{make} allows commands to be specified only once per target
+(except for double-colon rules).  If you give commands for a target
+which already has been defined to have commands, this warning is issued
+and the second set of commands will overwrite the first set.
+@xref{Multiple Rules, ,Multiple Rules for One Target}.
+
+@item Circular @var{xxx} <- @var{yyy} dependency dropped.
+This means that @code{make} detected a loop in the dependency graph:
+after tracing the prerequisite @var{yyy} of target @var{xxx}, and its
+prerequisites, etc., one of them depended on @var{xxx} again.
+
+@item Recursive variable `@var{xxx}' references itself (eventually).  Stop.
+This means you've defined a normal (recursive) @code{make} variable
+@var{xxx} that, when it's expanded, will refer to itself (@var{xxx}).
+This is not allowed; either use simply-expanded variables (@code{:=}) or
+use the append operator (@code{+=}).  @xref{Using Variables, ,How to Use
+Variables}.
+
+@item Unterminated variable reference.  Stop.
+This means you forgot to provide the proper closing parenthesis
+or brace in your variable or function reference.
+
+@item insufficient arguments to function `@var{xxx}'.  Stop.
+This means you haven't provided the requisite number of arguments for
+this function.  See the documentation of the function for a description
+of its arguments.  @xref{Functions, ,Functions for Transforming Text}.
+
+@item missing target pattern.  Stop.
+@itemx multiple target patterns.  Stop.
+@itemx target pattern contains no `%'.  Stop.
+@itemx mixed implicit and static pattern rules.  Stop.
+These are generated for malformed static pattern rules.  The first means
+there's no pattern in the target section of the rule; the second means
+there are multiple patterns in the target section; the third means
+the target doesn't contain a pattern character (@code{%}); and the
+fourth means that all three parts of the static pattern rule contain
+pattern characters (@code{%})--only the first two parts should.
+@xref{Static Usage, ,Syntax of Static Pattern Rules}.
+
+@item warning: -jN forced in submake: disabling jobserver mode.
+This warning and the next are generated if @code{make} detects error
+conditions related to parallel processing on systems where
+sub-@code{make}s can communicate (@pxref{Options/Recursion,
+,Communicating Options to a Sub-@code{make}}).  This warning is
+generated if a recursive invocation of a @code{make} process is forced
+to have @samp{-j@var{N}} in its argument list (where @var{N} is greater
+than one).  This could happen, for example, if you set the @code{MAKE}
+environment variable to @samp{make -j2}.  In this case, the
+sub-@code{make} doesn't communicate with other @code{make} processes and
+will simply pretend it has two jobs of its own.
+
+@item warning: jobserver unavailable: using -j1.  Add `+' to parent make rule.
+In order for @code{make} processes to communicate, the parent will pass
+information to the child.  Since this could result in problems if the
+child process isn't actually a @code{make}, the parent will only do this
+if it thinks the child is a @code{make}.  The parent uses the normal
+algorithms to determine this (@pxref{MAKE Variable, ,How the @code{MAKE}
+Variable Works}).  If the makefile is constructed such that the parent
+doesn't know the child is a @code{make} process, then the child will
+receive only part of the information necessary.  In this case, the child
+will generate this warning message and proceed with its build in a
+sequential manner.
+
+@end table
+
+@node Complex Makefile, GNU Free Documentation License, Error Messages, Top
+@appendix Complex Makefile Example
+
+Here is the makefile for the GNU @code{tar} program.  This is a
+moderately complex makefile.
+
+Because it is the first target, the default goal is @samp{all}.  An
+interesting feature of this makefile is that @file{testpad.h} is a
+source file automatically created by the @code{testpad} program,
+itself compiled from @file{testpad.c}.
+
+If you type @samp{make} or @samp{make all}, then @code{make} creates
+the @file{tar} executable, the @file{rmt} daemon that provides
+remote tape access, and the @file{tar.info} Info file.
+
+If you type @samp{make install}, then @code{make} not only creates
+@file{tar}, @file{rmt}, and @file{tar.info}, but also installs
+them.
+
+If you type @samp{make clean}, then @code{make} removes the @samp{.o}
+files, and the @file{tar}, @file{rmt}, @file{testpad},
+@file{testpad.h}, and @file{core} files.
+
+If you type @samp{make distclean}, then @code{make} not only removes
+the same files as does @samp{make clean} but also the
+@file{TAGS}, @file{Makefile}, and @file{config.status} files.
+(Although it is not evident, this makefile (and
+@file{config.status}) is generated by the user with the
+@code{configure} program, which is provided in the @code{tar}
+distribution, but is not shown here.)
+
+If you type @samp{make realclean}, then @code{make} removes the same
+files as does @samp{make distclean} and also removes the Info files
+generated from @file{tar.texinfo}.
+
+In addition, there are targets @code{shar} and @code{dist} that create
+distribution kits.
+
+@example
+@group
+# Generated automatically from Makefile.in by configure.
+# Un*x Makefile for GNU tar program.
+# Copyright (C) 1991 Free Software Foundation, Inc.
+@end group
+
+@group
+# This program is free software; you can redistribute
+# it and/or modify it under the terms of the GNU
+# General Public License @dots{}
+@dots{}
+@dots{}
+@end group
+
+SHELL = /bin/sh
+
+#### Start of system configuration section. ####
+
+srcdir = .
+
+@group
+# If you use gcc, you should either run the
+# fixincludes script that comes with it or else use
+# gcc with the -traditional option.  Otherwise ioctl
+# calls will be compiled incorrectly on some systems.
+CC = gcc -O
+YACC = bison -y
+INSTALL = /usr/local/bin/install -c
+INSTALLDATA = /usr/local/bin/install -c -m 644
+@end group
+
+# Things you might add to DEFS:
+# -DSTDC_HEADERS        If you have ANSI C headers and
+#                       libraries.
+# -DPOSIX               If you have POSIX.1 headers and
+#                       libraries.
+# -DBSD42               If you have sys/dir.h (unless
+#                       you use -DPOSIX), sys/file.h,
+#                       and st_blocks in `struct stat'.
+# -DUSG                 If you have System V/ANSI C
+#                       string and memory functions
+#                       and headers, sys/sysmacros.h,
+#                       fcntl.h, getcwd, no valloc,
+#                       and ndir.h (unless
+#                       you use -DDIRENT).
+# -DNO_MEMORY_H         If USG or STDC_HEADERS but do not
+#                       include memory.h.
+# -DDIRENT              If USG and you have dirent.h
+#                       instead of ndir.h.
+# -DSIGTYPE=int         If your signal handlers
+#                       return int, not void.
+# -DNO_MTIO             If you lack sys/mtio.h
+#                       (magtape ioctls).
+# -DNO_REMOTE           If you do not have a remote shell
+#                       or rexec.
+# -DUSE_REXEC           To use rexec for remote tape
+#                       operations instead of
+#                       forking rsh or remsh.
+# -DVPRINTF_MISSING     If you lack vprintf function
+#                       (but have _doprnt).
+# -DDOPRNT_MISSING      If you lack _doprnt function.
+#                       Also need to define
+#                       -DVPRINTF_MISSING.
+# -DFTIME_MISSING       If you lack ftime system call.
+# -DSTRSTR_MISSING      If you lack strstr function.
+# -DVALLOC_MISSING      If you lack valloc function.
+# -DMKDIR_MISSING       If you lack mkdir and
+#                       rmdir system calls.
+# -DRENAME_MISSING      If you lack rename system call.
+# -DFTRUNCATE_MISSING   If you lack ftruncate
+#                       system call.
+# -DV7                  On Version 7 Unix (not
+#                       tested in a long time).
+# -DEMUL_OPEN3          If you lack a 3-argument version
+#                       of open, and want to emulate it
+#                       with system calls you do have.
+# -DNO_OPEN3            If you lack the 3-argument open
+#                       and want to disable the tar -k
+#                       option instead of emulating open.
+# -DXENIX               If you have sys/inode.h
+#                       and need it 94 to be included.
+
+DEFS =  -DSIGTYPE=int -DDIRENT -DSTRSTR_MISSING \
+        -DVPRINTF_MISSING -DBSD42
+# Set this to rtapelib.o unless you defined NO_REMOTE,
+# in which case make it empty.
+RTAPELIB = rtapelib.o
+LIBS =
+DEF_AR_FILE = /dev/rmt8
+DEFBLOCKING = 20
+
+@group
+CDEBUG = -g
+CFLAGS = $(CDEBUG) -I. -I$(srcdir) $(DEFS) \
+        -DDEF_AR_FILE=\"$(DEF_AR_FILE)\" \
+        -DDEFBLOCKING=$(DEFBLOCKING)
+LDFLAGS = -g
+@end group
+
+@group
+prefix = /usr/local
+# Prefix for each installed program,
+# normally empty or `g'.
+binprefix =
+
+# The directory to install tar in.
+bindir = $(prefix)/bin
+
+# The directory to install the info files in.
+infodir = $(prefix)/info
+@end group
+
+#### End of system configuration section. ####
+
+SRC1 =  tar.c create.c extract.c buffer.c \
+        getoldopt.c update.c gnu.c mangle.c
+SRC2 =  version.c list.c names.c diffarch.c \
+        port.c wildmat.c getopt.c
+SRC3 =  getopt1.c regex.c getdate.y
+SRCS =  $(SRC1) $(SRC2) $(SRC3)
+OBJ1 =  tar.o create.o extract.o buffer.o \
+        getoldopt.o update.o gnu.o mangle.o
+OBJ2 =  version.o list.o names.o diffarch.o \
+        port.o wildmat.o getopt.o
+OBJ3 =  getopt1.o regex.o getdate.o $(RTAPELIB)
+OBJS =  $(OBJ1) $(OBJ2) $(OBJ3)
+@group
+AUX =   README COPYING ChangeLog Makefile.in  \
+        makefile.pc configure configure.in \
+        tar.texinfo tar.info* texinfo.tex \
+        tar.h port.h open3.h getopt.h regex.h \
+        rmt.h rmt.c rtapelib.c alloca.c \
+        msd_dir.h msd_dir.c tcexparg.c \
+        level-0 level-1 backup-specs testpad.c
+@end group
+
+.PHONY: all
+all:    tar rmt tar.info
+
+@group
+.PHONY: tar
+tar:    $(OBJS)
+        $(CC) $(LDFLAGS) -o $@@ $(OBJS) $(LIBS)
+@end group
+
+@group
+rmt:    rmt.c
+        $(CC) $(CFLAGS) $(LDFLAGS) -o $@@ rmt.c
+@end group
+
+@group
+tar.info: tar.texinfo
+        makeinfo tar.texinfo
+@end group
+
+@group
+.PHONY: install
+install: all
+        $(INSTALL) tar $(bindir)/$(binprefix)tar
+        -test ! -f rmt || $(INSTALL) rmt /etc/rmt
+        $(INSTALLDATA) $(srcdir)/tar.info* $(infodir)
+@end group
+
+@group
+$(OBJS): tar.h port.h testpad.h
+regex.o buffer.o tar.o: regex.h
+# getdate.y has 8 shift/reduce conflicts.
+@end group
+
+@group
+testpad.h: testpad
+        ./testpad
+@end group
+
+@group
+testpad: testpad.o
+        $(CC) -o $@@ testpad.o
+@end group
+
+@group
+TAGS:   $(SRCS)
+        etags $(SRCS)
+@end group
+
+@group
+.PHONY: clean
+clean:
+        rm -f *.o tar rmt testpad testpad.h core
+@end group
+
+@group
+.PHONY: distclean
+distclean: clean
+        rm -f TAGS Makefile config.status
+@end group
+
+@group
+.PHONY: realclean
+realclean: distclean
+        rm -f tar.info*
+@end group
+
+@group
+.PHONY: shar
+shar: $(SRCS) $(AUX)
+        shar $(SRCS) $(AUX) | compress \
+          > tar-`sed -e '/version_string/!d' \
+                     -e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
+                     -e q
+                     version.c`.shar.Z
+@end group
+
+@group
+.PHONY: dist
+dist: $(SRCS) $(AUX)
+        echo tar-`sed \
+             -e '/version_string/!d' \
+             -e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
+             -e q
+             version.c` > .fname
+        -rm -rf `cat .fname`
+        mkdir `cat .fname`
+        ln $(SRCS) $(AUX) `cat .fname`
+        tar chZf `cat .fname`.tar.Z `cat .fname`
+        -rm -rf `cat .fname` .fname
+@end group
+
+@group
+tar.zoo: $(SRCS) $(AUX)
+        -rm -rf tmp.dir
+        -mkdir tmp.dir
+        -rm tar.zoo
+        for X in $(SRCS) $(AUX) ; do \
+            echo $$X ; \
+            sed 's/$$/^M/' $$X \
+            > tmp.dir/$$X ; done
+        cd tmp.dir ; zoo aM ../tar.zoo *
+        -rm -rf tmp.dir
+@end group
+@end example
+
+@raisesections
+@include fdl.texi
+@lowersections
+
+@node Concept Index, Name Index, GNU Free Documentation License, Top
+@unnumbered Index of Concepts
+
+@printindex cp
+
+@node Name Index,  , Concept Index, Top
+@unnumbered Index of Functions, Variables, & Directives
+
+@printindex fn
+
+@bye
Index: /tags/kBuild-0.1.4/src/kmk/dosbuild.bat
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/dosbuild.bat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/dosbuild.bat	(revision 1780)
@@ -0,0 +1,62 @@
+@echo off
+rem Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free
+rem Software Foundation, Inc.
+rem This file is part of GNU Make.
+
+rem GNU Make is free software; you can redistribute it and/or modify it under the
+rem terms of the GNU General Public License as published by the Free Software
+rem Foundation; either version 2, or (at your option) any later version.
+
+rem GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+rem WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+rem A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+rem You should have received a copy of the GNU General Public License along with
+rem GNU Make; see the file COPYING.  If not, write to the Free Software
+rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+echo Building Make for MSDOS
+
+rem Echo ON so they will see what is going on.
+@echo on
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g commands.c -o commands.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g job.c -o job.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g dir.c -o dir.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g file.c -o file.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g misc.c -o misc.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g main.c -o main.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -DINCLUDEDIR=\"c:/djgpp/include\" -O2 -g read.c -o read.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -DLIBDIR=\"c:/djgpp/lib\" -O2 -g remake.c -o remake.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g rule.c -o rule.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g implicit.c -o implicit.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g default.c -o default.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g variable.c -o variable.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g expand.c -o expand.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g function.c -o function.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g vpath.c -o vpath.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g hash.c -o hash.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g strcache.c -o strcache.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g version.c -o version.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g ar.c -o ar.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g arscan.c -o arscan.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g signame.c -o signame.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g remote-stub.c -o remote-stub.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g getopt.c -o getopt.o
+gcc  -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g getopt1.c -o getopt1.o
+@cd glob
+@if exist libglob.a del libglob.a
+gcc -I. -c -DHAVE_CONFIG_H -I.. -O2 -g glob.c -o glob.o
+gcc -I. -c -DHAVE_CONFIG_H -I.. -O2 -g fnmatch.c -o fnmatch.o
+ar rv libglob.a glob.o fnmatch.o
+@echo off
+cd ..
+echo commands.o > respf.$$$
+for %%f in (job dir file misc main read remake rule implicit default variable) do echo %%f.o >> respf.$$$
+for %%f in (expand function vpath hash strcache version ar arscan signame remote-stub getopt getopt1) do echo %%f.o >> respf.$$$
+echo glob/libglob.a >> respf.$$$
+@echo Linking...
+@echo on
+gcc -o make.new @respf.$$$
+@if exist make.exe echo Make.exe is now built!
+@if not exist make.exe echo Make.exe build failed...
+@if exist make.exe del respf.$$$
Index: /tags/kBuild-0.1.4/src/kmk/electric.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/electric.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/electric.c	(revision 1780)
@@ -0,0 +1,191 @@
+/* $Id$ */
+/** @file
+ *
+ * A simple electric heap implementation.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This program 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 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ */
+
+#ifdef ELECTRIC_HEAP
+
+# ifdef WINDOWS32
+#  include <windows.h>
+# else
+#  include <sys/mman.h>
+#  include <errno.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+# include <stdio.h>
+
+
+# define FREED_ENTRIES 512
+static struct
+{
+  void *ptr;
+  unsigned aligned;
+} freed[FREED_ENTRIES];
+static unsigned freed_head = 0;
+static unsigned freed_tail = 0;
+
+
+static void fatal_error (const char *msg)
+{
+#ifdef _MSC_VER
+  fprintf (stderr, "electric heap error: %s\n", msg);
+  __debugbreak ();
+#else
+  fprintf (stderr, "electric heap error: %s (errno=%d)\n", msg, errno);
+  __asm__ ("int3"); /* not portable... */
+#endif 
+  abort ();
+  exit (1);
+}
+
+static void free_it (void *ptr, unsigned aligned)
+{
+# ifdef WINDOWS32
+  if (!VirtualFree (ptr, 0, MEM_RELEASE))
+    fatal_error ("VirtualFree failed");
+# else
+  if (munmap(ptr, aligned))
+    fatal_error ("munmap failed");
+# endif
+}
+
+/* Return 1 if something was freed, 0 otherwise. */
+static int free_up_some (void)
+{
+  if (freed_tail == freed_head)
+    return 0;
+  free_it (freed[freed_tail].ptr, freed[freed_tail].aligned);
+  freed[freed_tail].ptr = NULL;
+  freed[freed_tail].aligned = 0;
+  freed_tail = (freed_tail + 1) % FREED_ENTRIES;
+  return 1;
+}
+
+static unsigned *get_hdr (void *ptr)
+{
+  if (((uintptr_t)ptr & 0xfff) < sizeof(unsigned))
+    return (unsigned *)(((uintptr_t)ptr - 0x1000) & ~0xfff);
+  return (unsigned *)((uintptr_t)ptr & ~0xfff);
+}
+
+void xfree (void *ptr)
+{
+  unsigned int size, aligned;
+  unsigned *hdr;
+# ifdef WINDOWS32
+  DWORD fFlags = PAGE_NOACCESS;
+# endif
+
+  if (!ptr)
+    return;
+
+  hdr = get_hdr (ptr);
+  size = *hdr;
+  aligned = (size + 0x1fff + sizeof(unsigned)) & ~0xfff;
+# ifdef WINDOWS32
+  if (!VirtualProtect (hdr, aligned - 0x1000, fFlags, &fFlags))
+    fatal_error ("failed to protect freed memory");
+# else
+  if (mprotect(hdr, aligned - 0x1000, PROT_NONE))
+    fatal_error ("failed to protect freed memory");
+# endif
+
+  freed[freed_head].ptr = hdr;
+  freed[freed_head].aligned = aligned;
+  if (((freed_head + 1) % FREED_ENTRIES) == freed_tail)
+    free_up_some();
+  freed_head = (freed_head + 1) % FREED_ENTRIES;
+}
+
+void *
+xmalloc (unsigned int size)
+{
+  /* Make sure we don't allocate 0, for pre-ANSI libraries.  */
+  unsigned int aligned = (size + 0x1fff + sizeof(unsigned)) & ~0xfff;
+  unsigned *hdr;
+  unsigned i;
+  for (i = 0; i < FREED_ENTRIES; i++)
+    {
+# ifdef WINDOWS32
+      DWORD fFlags = PAGE_NOACCESS;
+      hdr = VirtualAlloc(NULL, aligned, MEM_COMMIT, PAGE_READWRITE);
+      if (hdr
+       && !VirtualProtect((char *)hdr + aligned - 0x1000, 0x1000, fFlags, &fFlags))
+        fatal_error ("failed to set guard page protection");
+# else
+      hdr = mmap(NULL, aligned, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+      if (hdr == MAP_FAILED)
+        hdr = 0;
+      if (hdr
+       && mprotect((char *)hdr + aligned - 0x1000, 0x1000, PROT_NONE))
+        fatal_error ("failed to set guard page protection");
+# endif
+      if (hdr)
+        break;
+      if (!free_up_some ())
+        break;
+    }
+  if (hdr == 0)
+    fatal_error ("virtual memory exhausted");
+
+  *hdr = size;
+# if 0
+  return hdr + 1;
+# else
+  return (char *)hdr + aligned - 0x1000 - size;
+# endif
+}
+
+void *
+xcalloc (size_t size, size_t items)
+{
+    void *result;
+    result = xmalloc (size * items);
+    return memset (result, 0, size * items);
+}
+
+void *
+xrealloc (void *ptr, unsigned int size)
+{
+  void *result;
+  result = xmalloc (size);
+  if (ptr)
+    {
+      unsigned *hdr = get_hdr (ptr);
+      unsigned int oldsize = *hdr;
+      memcpy (result, ptr, oldsize >= size ? size : oldsize);
+      xfree (ptr);
+    }
+  return result;
+}
+
+char *
+xstrdup (const char *ptr)
+{
+  size_t size = strlen (ptr) + 1;
+  char *result = xmalloc (size);
+  return memcpy (result, ptr, size);
+}
+
+#endif /* ELECTRIC_HEAP */
+
Index: /tags/kBuild-0.1.4/src/kmk/electric.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/electric.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/electric.h	(revision 1780)
@@ -0,0 +1,46 @@
+/* $Id$ */
+/** @file
+ *
+ * A simple electric heap implementation, wrapper header.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This program 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 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ *
+ */
+
+#ifdef ELECTRIC_HEAP
+
+#include <stdlib.h>
+#ifdef WINDOWS32
+# include <malloc.h>
+#endif
+#include <string.h> /* strdup */
+
+void xfree (void *);
+void *xcalloc (size_t, size_t);
+void *xmalloc (unsigned int);
+void *xrealloc (void *, unsigned int);
+char *xstrdup (const char *);
+
+#define free(a)         xfree(a)
+#define calloc(a,b)     xcalloc((a),(b))
+#define malloc(a)       xmalloc(a)
+#define realloc(a,b)    xrealloc((a),(b))
+#define strdup(a)       xstrdup(a)
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/kmk/expand.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/expand.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/expand.c	(revision 1780)
@@ -0,0 +1,739 @@
+/* Variable expansion functions for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#include <assert.h>
+
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "variable.h"
+#include "rule.h"
+
+/* Initially, any errors reported when expanding strings will be reported
+   against the file where the error appears.  */
+const struct floc **expanding_var = &reading_file;
+
+/* The next two describe the variable output buffer.
+   This buffer is used to hold the variable-expansion of a line of the
+   makefile.  It is made bigger with realloc whenever it is too small.
+   variable_buffer_length is the size currently allocated.
+   variable_buffer is the address of the buffer.
+
+   For efficiency, it's guaranteed that the buffer will always have
+   VARIABLE_BUFFER_ZONE extra bytes allocated.  This allows you to add a few
+   extra chars without having to call a function.  Note you should never use
+   these bytes unless you're _sure_ you have room (you know when the buffer
+   length was last checked.  */
+
+#define VARIABLE_BUFFER_ZONE    5
+
+static unsigned int variable_buffer_length;
+char *variable_buffer;
+
+/* Subroutine of variable_expand and friends:
+   The text to add is LENGTH chars starting at STRING to the variable_buffer.
+   The text is added to the buffer at PTR, and the updated pointer into
+   the buffer is returned as the value.  Thus, the value returned by
+   each call to variable_buffer_output should be the first argument to
+   the following call.  */
+
+char *
+variable_buffer_output (char *ptr, const char *string, unsigned int length)
+{
+  register unsigned int newlen = length + (ptr - variable_buffer);
+
+  if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length)
+    {
+      unsigned int offset = ptr - variable_buffer;
+#ifdef KMK
+      variable_buffer_length = variable_buffer_length <= 1024
+                             ? 2048 : variable_buffer_length * 4;
+      if (variable_buffer_length < newlen + 100)
+          variable_buffer_length = (newlen + 100 + 1023) & ~1023U;
+#else
+      variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length
+                               ? newlen + 100
+                               : 2 * variable_buffer_length);
+#endif
+      variable_buffer = xrealloc (variable_buffer, variable_buffer_length);
+      ptr = variable_buffer + offset;
+    }
+
+  memcpy (ptr, string, length);
+  return ptr + length;
+}
+
+/* Return a pointer to the beginning of the variable buffer.  */
+
+static char *
+initialize_variable_output (void)
+{
+  /* If we don't have a variable output buffer yet, get one.  */
+
+  if (variable_buffer == 0)
+    {
+#ifdef KMK
+      variable_buffer_length = 384;
+#else
+      variable_buffer_length = 200;
+#endif
+      variable_buffer = xmalloc (variable_buffer_length);
+      variable_buffer[0] = '\0';
+    }
+
+  return variable_buffer;
+}
+
+
+/* Recursively expand V.  The returned string is malloc'd.  */
+
+static char *allocated_variable_append (const struct variable *v);
+
+char *
+recursively_expand_for_file (struct variable *v, struct file *file)
+{
+  char *value;
+  const struct floc *this_var;
+  const struct floc **saved_varp;
+  struct variable_set_list *save = 0;
+  int set_reading = 0;
+
+  /* Don't install a new location if this location is empty.
+     This can happen for command-line variables, builtin variables, etc.  */
+  saved_varp = expanding_var;
+  if (v->fileinfo.filenm)
+    {
+      this_var = &v->fileinfo;
+      expanding_var = &this_var;
+    }
+
+  /* If we have no other file-reading context, use the variable's context. */
+  if (!reading_file)
+    {
+      set_reading = 1;
+      reading_file = &v->fileinfo;
+    }
+
+  if (v->expanding)
+    {
+      if (!v->exp_count)
+        /* Expanding V causes infinite recursion.  Lose.  */
+        fatal (*expanding_var,
+               _("Recursive variable `%s' references itself (eventually)"),
+               v->name);
+      --v->exp_count;
+    }
+
+  if (file)
+    {
+      save = current_variable_set_list;
+      current_variable_set_list = file->variables;
+    }
+
+  v->expanding = 1;
+  if (v->append)
+    value = allocated_variable_append (v);
+  else
+    value = allocated_variable_expand (v->value);
+  v->expanding = 0;
+
+  if (set_reading)
+    reading_file = 0;
+
+  if (file)
+    current_variable_set_list = save;
+
+  expanding_var = saved_varp;
+
+  return value;
+}
+
+/* Expand a simple reference to variable NAME, which is LENGTH chars long.  */
+
+#if defined(__GNUC__) || defined(_MSC_VER) /* bird added MSC */
+__inline
+#endif
+static char *
+reference_variable (char *o, const char *name, unsigned int length)
+{
+  struct variable *v;
+  char *value;
+
+  v = lookup_variable (name, length);
+
+  if (v == 0)
+    warn_undefined (name, length);
+
+  /* If there's no variable by that name or it has no value, stop now.  */
+  if (v == 0 || (*v->value == '\0' && !v->append))
+    return o;
+
+#ifdef CONFIG_WITH_VALUE_LENGTH
+  if (!v->recursive)
+    {
+      assert (v->value_length == strlen (v->value));
+      o = variable_buffer_output (o, v->value, v->value_length);
+    }
+  else
+   {
+     value = recursively_expand (v);
+     o = variable_buffer_output (o, value, strlen (value));
+     free (value);
+   }
+#else  /* !CONFIG_WITH_VALUE_LENGTH */
+  value = (v->recursive ? recursively_expand (v) : v->value);
+
+  o = variable_buffer_output (o, value, strlen (value));
+
+  if (v->recursive)
+    free (value);
+#endif /* !CONFIG_WITH_VALUE_LENGTH */
+
+  return o;
+}
+
+
+/* Scan STRING for variable references and expansion-function calls.  Only
+   LENGTH bytes of STRING are actually scanned.  If LENGTH is -1, scan until
+   a null byte is found.
+
+   Write the results to LINE, which must point into `variable_buffer'.  If
+   LINE is NULL, start at the beginning of the buffer.
+   Return a pointer to LINE, or to the beginning of the buffer if LINE is
+   NULL.
+ */
+char *
+variable_expand_string (char *line, const char *string, long length)
+{
+  struct variable *v;
+  const char *p, *p1;
+  char *abuf = NULL;
+  char *o;
+  unsigned int line_offset;
+
+  if (!line)
+    line = initialize_variable_output();
+  o = line;
+  line_offset = line - variable_buffer;
+
+  if (length == 0)
+    {
+      variable_buffer_output (o, "", 1);
+      return (variable_buffer);
+    }
+
+  /* If we want a subset of the string, allocate a temporary buffer for it.
+     Most of the functions we use here don't work with length limits.  */
+  if (length > 0 && string[length] != '\0')
+    {
+      abuf = xmalloc(length+1);
+      memcpy(abuf, string, length);
+      abuf[length] = '\0';
+      string = abuf;
+    }
+  p = string;
+
+  while (1)
+    {
+      /* Copy all following uninteresting chars all at once to the
+         variable output buffer, and skip them.  Uninteresting chars end
+	 at the next $ or the end of the input.  */
+
+      p1 = strchr (p, '$');
+
+      o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p) + 1);
+
+      if (p1 == 0)
+	break;
+      p = p1 + 1;
+
+      /* Dispatch on the char that follows the $.  */
+
+      switch (*p)
+	{
+	case '$':
+	  /* $$ seen means output one $ to the variable output buffer.  */
+	  o = variable_buffer_output (o, p, 1);
+	  break;
+
+	case '(':
+	case '{':
+	  /* $(...) or ${...} is the general case of substitution.  */
+	  {
+	    char openparen = *p;
+	    char closeparen = (openparen == '(') ? ')' : '}';
+            const char *begp;
+	    const char *beg = p + 1;
+	    char *op;
+            char *abeg = NULL;
+	    const char *end, *colon;
+
+	    op = o;
+	    begp = p;
+	    if (handle_function (&op, &begp))
+	      {
+		o = op;
+		p = begp;
+		break;
+	      }
+
+	    /* Is there a variable reference inside the parens or braces?
+	       If so, expand it before expanding the entire reference.  */
+
+	    end = strchr (beg, closeparen);
+	    if (end == 0)
+              /* Unterminated variable reference.  */
+              fatal (*expanding_var, _("unterminated variable reference"));
+	    p1 = lindex (beg, end, '$');
+	    if (p1 != 0)
+	      {
+		/* BEG now points past the opening paren or brace.
+		   Count parens or braces until it is matched.  */
+		int count = 0;
+		for (p = beg; *p != '\0'; ++p)
+		  {
+		    if (*p == openparen)
+		      ++count;
+		    else if (*p == closeparen && --count < 0)
+		      break;
+		  }
+		/* If COUNT is >= 0, there were unmatched opening parens
+		   or braces, so we go to the simple case of a variable name
+		   such as `$($(a)'.  */
+		if (count < 0)
+		  {
+		    abeg = expand_argument (beg, p); /* Expand the name.  */
+		    beg = abeg;
+		    end = strchr (beg, '\0');
+		  }
+	      }
+	    else
+	      /* Advance P to the end of this reference.  After we are
+                 finished expanding this one, P will be incremented to
+                 continue the scan.  */
+	      p = end;
+
+	    /* This is not a reference to a built-in function and
+	       any variable references inside are now expanded.
+	       Is the resultant text a substitution reference?  */
+
+	    colon = lindex (beg, end, ':');
+	    if (colon)
+	      {
+		/* This looks like a substitution reference: $(FOO:A=B).  */
+		const char *subst_beg, *subst_end, *replace_beg, *replace_end;
+
+		subst_beg = colon + 1;
+		subst_end = lindex (subst_beg, end, '=');
+		if (subst_end == 0)
+		  /* There is no = in sight.  Punt on the substitution
+		     reference and treat this as a variable name containing
+		     a colon, in the code below.  */
+		  colon = 0;
+		else
+		  {
+		    replace_beg = subst_end + 1;
+		    replace_end = end;
+
+		    /* Extract the variable name before the colon
+		       and look up that variable.  */
+		    v = lookup_variable (beg, colon - beg);
+		    if (v == 0)
+		      warn_undefined (beg, colon - beg);
+
+                    /* If the variable is not empty, perform the
+                       substitution.  */
+		    if (v != 0 && *v->value != '\0')
+		      {
+			char *pattern, *replace, *ppercent, *rpercent;
+			char *value = (v->recursive
+                                       ? recursively_expand (v)
+				       : v->value);
+
+                        /* Copy the pattern and the replacement.  Add in an
+                           extra % at the beginning to use in case there
+                           isn't one in the pattern.  */
+                        pattern = alloca (subst_end - subst_beg + 2);
+                        *(pattern++) = '%';
+                        memcpy (pattern, subst_beg, subst_end - subst_beg);
+                        pattern[subst_end - subst_beg] = '\0';
+
+                        replace = alloca (replace_end - replace_beg + 2);
+                        *(replace++) = '%';
+                        memcpy (replace, replace_beg,
+                               replace_end - replace_beg);
+                        replace[replace_end - replace_beg] = '\0';
+
+                        /* Look for %.  Set the percent pointers properly
+                           based on whether we find one or not.  */
+			ppercent = find_percent (pattern);
+			if (ppercent)
+                          {
+                            ++ppercent;
+                            rpercent = find_percent (replace);
+                            if (rpercent)
+                              ++rpercent;
+                          }
+			else
+                          {
+                            ppercent = pattern;
+                            rpercent = replace;
+                            --pattern;
+                            --replace;
+                          }
+
+                        o = patsubst_expand_pat (o, value, pattern, replace,
+                                                 ppercent, rpercent);
+
+			if (v->recursive)
+			  free (value);
+		      }
+		  }
+	      }
+
+	    if (colon == 0)
+	      /* This is an ordinary variable reference.
+		 Look up the value of the variable.  */
+		o = reference_variable (o, beg, end - beg);
+
+	  if (abeg)
+	    free (abeg);
+	  }
+	  break;
+
+	case '\0':
+	  break;
+
+	default:
+	  if (isblank ((unsigned char)p[-1]))
+	    break;
+
+	  /* A $ followed by a random char is a variable reference:
+	     $a is equivalent to $(a).  */
+          o = reference_variable (o, p, 1);
+
+	  break;
+	}
+
+      if (*p == '\0')
+	break;
+      else
+	++p;
+    }
+
+  if (abuf)
+    free (abuf);
+
+  variable_buffer_output (o, "", 1);
+  return (variable_buffer + line_offset);
+}
+
+
+/* Scan LINE for variable references and expansion-function calls.
+   Build in `variable_buffer' the result of expanding the references and calls.
+   Return the address of the resulting string, which is null-terminated
+   and is valid only until the next time this function is called.  */
+
+char *
+variable_expand (const char *line)
+{
+  return variable_expand_string(NULL, line, (long)-1);
+}
+
+
+/* Expand an argument for an expansion function.
+   The text starting at STR and ending at END is variable-expanded
+   into a null-terminated string that is returned as the value.
+   This is done without clobbering `variable_buffer' or the current
+   variable-expansion that is in progress.  */
+
+char *
+expand_argument (const char *str, const char *end)
+{
+  char *tmp;
+
+  if (str == end)
+    return xstrdup("");
+
+  if (!end || *end == '\0')
+    return allocated_variable_expand (str);
+
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+  {
+    const char saved_char = *end;
+    *(char *)end = '\0';
+    tmp = allocated_variable_expand ((char *)str);
+    *(char *)end = saved_char;
+    return tmp;
+  }
+#else
+  tmp = alloca (end - str + 1);
+  memcpy (tmp, str, end - str);
+  tmp[end - str] = '\0';
+
+  return allocated_variable_expand (tmp);
+#endif
+}
+
+
+/* Expand LINE for FILE.  Error messages refer to the file and line where
+   FILE's commands were found.  Expansion uses FILE's variable set list.  */
+
+char *
+variable_expand_for_file (const char *line, struct file *file)
+{
+  char *result;
+  struct variable_set_list *save;
+
+  if (file == 0)
+    return variable_expand (line);
+
+  save = current_variable_set_list;
+  current_variable_set_list = file->variables;
+  if (file->cmds && file->cmds->fileinfo.filenm)
+    reading_file = &file->cmds->fileinfo;
+  else
+    reading_file = 0;
+  result = variable_expand (line);
+  current_variable_set_list = save;
+  reading_file = 0;
+
+  return result;
+}
+
+
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+/* Expand LINE for FILE.  Error messages refer to the file and line where
+   FILE's commands were found.  Expansion uses FILE's variable set list.
+
+   Differs from variable_expand_for_file in that it takes a pointer to
+   where in the variable buffer to start outputting the expanded string.  */
+
+char *
+variable_expand_for_file_2 (char *o, const char *line, struct file *file)
+{
+  char *result;
+  struct variable_set_list *save;
+  const struct floc *reading_file_saved;
+
+  if (file == 0)
+    return variable_expand_string (o, line, (long)-1);
+
+  save = current_variable_set_list;
+  current_variable_set_list = file->variables;
+  reading_file_saved = reading_file;
+  if (file->cmds && file->cmds->fileinfo.filenm)
+    reading_file = &file->cmds->fileinfo;
+  else
+    reading_file = 0;
+  result = variable_expand_string (o, line, (long)-1);
+  current_variable_set_list = save;
+  reading_file = reading_file_saved;
+
+  return result;
+}
+
+
+#endif /* CONFIG_WITH_COMMANDS_FUNC */
+/* Like allocated_variable_expand, but for += target-specific variables.
+   First recursively construct the variable value from its appended parts in
+   any upper variable sets.  Then expand the resulting value.  */
+
+static char *
+variable_append (const char *name, unsigned int length,
+                 const struct variable_set_list *set)
+{
+  const struct variable *v;
+  char *buf = 0;
+
+  /* If there's nothing left to check, return the empty buffer.  */
+  if (!set)
+    return initialize_variable_output ();
+
+  /* Try to find the variable in this variable set.  */
+  v = lookup_variable_in_set (name, length, set->set);
+
+  /* If there isn't one, look to see if there's one in a set above us.  */
+  if (!v)
+    return variable_append (name, length, set->next);
+
+  /* If this variable type is append, first get any upper values.
+     If not, initialize the buffer.  */
+  if (v->append)
+    buf = variable_append (name, length, set->next);
+  else
+    buf = initialize_variable_output ();
+
+  /* Append this value to the buffer, and return it.
+     If we already have a value, first add a space.  */
+  if (buf > variable_buffer)
+    buf = variable_buffer_output (buf, " ", 1);
+#ifdef CONFIG_WITH_VALUE_LENGTH
+  assert (v->value_length == strlen (v->value));
+#endif
+
+  /* Either expand it or copy it, depending.  */
+  if (! v->recursive)
+#ifdef CONFIG_WITH_VALUE_LENGTH
+    return variable_buffer_output (buf, v->value, v->value_length);
+#else
+    return variable_buffer_output (buf, v->value, strlen (v->value));
+#endif
+
+#ifdef CONFIG_WITH_VALUE_LENGTH
+  buf = variable_expand_string (buf, v->value, v->value_length);
+#else
+  buf = variable_expand_string (buf, v->value, strlen (v->value));
+#endif
+  return (buf + strlen (buf));
+}
+
+#ifdef CONFIG_WITH_VALUE_LENGTH
+/* Expands the specified string, appending it to the specified variable value. */
+void
+append_expanded_string_to_variable (struct variable *v, const char *value, int append)
+{
+  unsigned int value_len = strlen (value);
+  char *p = (char *) memchr (value, '$', value_len);
+  if (!p)
+    /* fast path */
+    append_string_to_variable (v,value, value_len, append);
+  else if (value_len)
+    {
+      unsigned int off_dollar = p - (char *)value;
+
+      /* Install a fresh variable buffer. */
+      char *saved_buffer;
+      unsigned int saved_buffer_length;
+      install_variable_buffer (&saved_buffer, &saved_buffer_length);
+
+      p = variable_buffer;
+      if (append || !v->value_length)
+        {
+          /* Copy the current value into it and append a space. */
+          if (v->value_length)
+            {
+              p = variable_buffer_output (p, v->value, v->value_length);
+              p = variable_buffer_output (p, " ", 1);
+            }
+
+          /* Append the assignment value. */
+          p = variable_buffer_output (p, value, off_dollar);
+          p = variable_expand_string (p, value + off_dollar, value_len - off_dollar);
+          p = strchr (p, '\0');
+        }
+      else
+        {
+          /* Expand the assignemnt value. */
+          p = variable_buffer_output (p, value, off_dollar);
+          p = variable_expand_string (p, value + off_dollar, value_len - off_dollar);
+          p = strchr (p, '\0');
+
+          /* Append a space followed by the old value. */
+          p = variable_buffer_output (p, " ", 1);
+          p = variable_buffer_output (p, v->value, v->value_length + 1) - 1;
+        }
+
+      /* Replace the variable with the variable buffer. */
+      free (v->value);
+      v->value = variable_buffer;
+      v->value_length = p - v->value;
+      v->value_alloc_len = variable_buffer_length;
+
+      /* Restore the variable buffer, but without freeing the current. */
+      variable_buffer = NULL;
+      restore_variable_buffer (saved_buffer, saved_buffer_length);
+    }
+  /* else: Drop empty strings. Use $(NO_SUCH_VARIABLE) if a space is wanted. */
+}
+#endif /* CONFIG_WITH_VALUE_LENGTH */
+
+static char *
+allocated_variable_append (const struct variable *v)
+{
+  char *val;
+
+  /* Construct the appended variable value.  */
+
+  char *obuf = variable_buffer;
+  unsigned int olen = variable_buffer_length;
+
+  variable_buffer = 0;
+
+  val = variable_append (v->name, strlen (v->name), current_variable_set_list);
+  variable_buffer_output (val, "", 1);
+  val = variable_buffer;
+
+  variable_buffer = obuf;
+  variable_buffer_length = olen;
+
+  return val;
+}
+
+/* Like variable_expand_for_file, but the returned string is malloc'd.
+   This function is called a lot.  It wants to be efficient.  */
+
+char *
+allocated_variable_expand_for_file (const char *line, struct file *file)
+{
+  char *value;
+
+  char *obuf = variable_buffer;
+  unsigned int olen = variable_buffer_length;
+
+  variable_buffer = 0;
+
+  value = variable_expand_for_file (line, file);
+
+#if 0
+  /* Waste a little memory and save time.  */
+  value = xrealloc (value, strlen (value))
+#endif
+
+  variable_buffer = obuf;
+  variable_buffer_length = olen;
+
+  return value;
+}
+
+/* Install a new variable_buffer context, returning the current one for
+   safe-keeping.  */
+
+void
+install_variable_buffer (char **bufp, unsigned int *lenp)
+{
+  *bufp = variable_buffer;
+  *lenp = variable_buffer_length;
+
+  variable_buffer = 0;
+  initialize_variable_output ();
+}
+
+/* Restore a previously-saved variable_buffer setting (free the current one).
+ */
+
+void
+restore_variable_buffer (char *buf, unsigned int len)
+{
+  free (variable_buffer);
+
+  variable_buffer = buf;
+  variable_buffer_length = len;
+}
Index: /tags/kBuild-0.1.4/src/kmk/expreval.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/expreval.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/expreval.c	(revision 1780)
@@ -0,0 +1,2125 @@
+#ifdef CONFIG_WITH_IF_CONDITIONALS
+/* $Id$ */
+/** @file
+ * expreval - Expressions evaluator, C / BSD make / nmake style.
+ */
+
+/*
+ * Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "make.h"
+#include <assert.h>
+
+#include <glob.h>
+
+#include "dep.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "variable.h"
+#include "rule.h"
+#include "debug.h"
+#include "hash.h"
+#include <ctype.h>
+#ifndef _MSC_VER
+# include <stdint.h>
+#endif
+#include <stdarg.h>
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** The max length of a string representation of a number. */
+#define EXPR_NUM_LEN  ((sizeof("-9223372036854775802") + 4) & ~3)
+
+/** The max operator stack depth. */
+#define EXPR_MAX_OPERATORS  72
+/** The max operand depth. */
+#define EXPR_MAX_OPERANDS   128
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/** The 64-bit signed integer type we're using. */
+#ifdef _MSC_VER
+typedef __int64 EXPRINT64;
+#else
+# include <stdint.h>
+typedef int64_t EXPRINT64;
+#endif
+
+/** Pointer to a evaluator instance. */
+typedef struct EXPR *PEXPR;
+
+
+/**
+ * Operand variable type.
+ */
+typedef enum
+{
+    /** Invalid zero entry. */
+    kExprVar_Invalid = 0,
+    /** A number. */
+    kExprVar_Num,
+    /** A string in need of expanding (perhaps). */
+    kExprVar_String,
+    /** A simple string that doesn't need expanding. */
+    kExprVar_SimpleString,
+    /** A quoted string in need of expanding (perhaps). */
+    kExprVar_QuotedString,
+    /** A simple quoted string that doesn't need expanding. */
+    kExprVar_QuotedSimpleString,
+    /** The end of the valid variable types. */
+    kExprVar_End
+} EXPRVARTYPE;
+
+/**
+ * Operand variable.
+ */
+typedef struct
+{
+    /** The variable type. */
+    EXPRVARTYPE enmType;
+    /** The variable. */
+    union
+    {
+        /** Pointer to the string. */
+        char *psz;
+        /** The variable. */
+        EXPRINT64 i;
+    } uVal;
+} EXPRVAR;
+/** Pointer to a operand variable. */
+typedef EXPRVAR *PEXPRVAR;
+/** Pointer to a const operand variable. */
+typedef EXPRVAR const *PCEXPRVAR;
+
+/**
+ * Operator return statuses.
+ */
+typedef enum
+{
+    kExprRet_Error = -1,
+    kExprRet_Ok = 0,
+    kExprRet_Operator,
+    kExprRet_Operand,
+    kExprRet_EndOfExpr,
+    kExprRet_End
+} EXPRRET;
+
+/**
+ * Operator.
+ */
+typedef struct
+{
+    /** The operator. */
+    char szOp[11];
+    /** The length of the operator string. */
+    char cchOp;
+    /** The pair operator.
+     * This is used with '(' and '?'. */
+    char chPair;
+    /** The precedence. Higher means higher. */
+    char iPrecedence;
+    /** The number of arguments it takes. */
+    signed char cArgs;
+    /** Pointer to the method implementing the operator. */
+    EXPRRET (*pfn)(PEXPR pThis);
+} EXPROP;
+/** Pointer to a const operator. */
+typedef EXPROP const *PCEXPROP;
+
+/**
+ * Expression evaluator instance.
+ */
+typedef struct EXPR
+{
+    /** The full expression. */
+    const char *pszExpr;
+    /** The current location. */
+    const char *psz;
+    /** The current file location, used for errors. */
+    const struct floc *pFileLoc;
+    /** Pending binary operator. */
+    PCEXPROP pPending;
+    /** Top of the operator stack. */
+    int iOp;
+    /** Top of the operand stack. */
+    int iVar;
+    /** The operator stack. */
+    PCEXPROP apOps[EXPR_MAX_OPERATORS];
+    /** The operand stack. */
+    EXPRVAR aVars[EXPR_MAX_OPERANDS];
+} EXPR;
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Operator start character map.
+ * This indicates which characters that are starting operators and which aren't. */
+static char g_auchOpStartCharMap[256];
+/** Whether we've initialized the map. */
+static int g_fExprInitializedMap = 0;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static void expr_unget_op(PEXPR pThis);
+static EXPRRET expr_get_binary_or_eoe_or_rparen(PEXPR pThis);
+
+
+
+
+/**
+ * Displays an error message.
+ *
+ * The total string length must not exceed 256 bytes.
+ *
+ * @param   pThis       The evaluator instance.
+ * @param   pszError    The message format string.
+ * @param   ...         The message format args.
+ */
+static void expr_error(PEXPR pThis, const char *pszError, ...)
+{
+    char szTmp[256];
+    va_list va;
+
+    va_start(va, pszError);
+    vsprintf(szTmp, pszError, va);
+    va_end(va);
+
+    fatal(pThis->pFileLoc, "%s", szTmp);
+}
+
+
+/**
+ * Converts a number to a string.
+ *
+ * @returns pszDst.
+ * @param   pszDst  The string buffer to write into. Assumes length of EXPR_NUM_LEN.
+ * @param   iSrc    The number to convert.
+ */
+static char *expr_num_to_string(char *pszDst, EXPRINT64 iSrc)
+{
+    static const char s_szDigits[17] = "0123456789abcdef";
+    char szTmp[EXPR_NUM_LEN];
+    char *psz = &szTmp[EXPR_NUM_LEN - 1];
+    int fNegative;
+
+    fNegative = iSrc < 0;
+    if (fNegative)
+    {
+        /** @todo this isn't right for INT64_MIN. */
+        iSrc = -iSrc;
+    }
+
+    *psz = '\0';
+    do
+    {
+#if 0
+        *--psz = s_szDigits[iSrc & 0xf];
+        iSrc >>= 4;
+#else
+        *--psz = s_szDigits[iSrc % 10];
+        iSrc /= 10;
+#endif
+    } while (iSrc);
+
+#if 0
+    *--psz = 'x';
+    *--psz = '0';
+#endif
+
+    if (fNegative)
+      *--psz = '-';
+
+    /* copy it into the output buffer. */
+    return (char *)memcpy(pszDst, psz, &szTmp[EXPR_NUM_LEN] - psz);
+}
+
+
+/**
+ * Attempts to convert a (simple) string into a number.
+ *
+ * @returns status code.
+ * @param   pThis   The evaluator instance. This is optional when fQuiet is true.
+ * @param   piSrc   Where to store the numeric value on success.
+ * @param   pszSrc  The string to try convert.
+ * @param   fQuiet  Whether we should be quiet or grumpy on failure.
+ */
+static EXPRRET expr_string_to_num(PEXPR pThis, EXPRINT64 *piDst, const char *pszSrc, int fQuiet)
+{
+    EXPRRET rc = kExprRet_Ok;
+    char const *psz = pszSrc;
+    EXPRINT64 i;
+    unsigned uBase;
+    int fNegative;
+
+
+    /*
+     * Skip blanks.
+     */
+    while (isblank(*psz))
+        psz++;
+
+    /*
+     * Check for '-'.
+     *
+     * At this point we will not need to deal with operators, this is
+     * just an indicator of negative numbers. If some operator ends up
+     * here it's because it came from a string expansion and thus shall
+     * not be interpreted. If this turns out to be an stupid restriction
+     * it can be fixed, but for now it stays like this.
+     */
+    fNegative = *psz == '-';
+    if (fNegative)
+        psz++;
+
+    /*
+     * Determin base                                                        .
+     *                                                                      .
+     * Recognize some exsotic prefixes here in addition to the two standard ones.
+     */
+    if (*psz != '0' || psz[1] == '\0' || isblank((unsigned int)psz[1]))
+        uBase = 10;
+    else if (psz[1] == 'x' || psz[1] == 'X')
+    {
+        uBase = 16;
+        psz += 2;
+    }
+    else if (psz[1] == 'b' || psz[1] == 'B')
+    {
+        uBase = 2;
+        psz += 2;
+    }
+    else if (psz[1] == 'd' || psz[1] == 'D')
+    {
+        uBase = 10;
+        psz += 2;
+    }
+    else if (psz[1] == 'o' || psz[1] == 'O')
+    {
+        uBase = 8;
+        psz += 2;
+    }
+    else if (isdigit(psz[1]) && psz[1] != '9' && psz[1] != '8')
+    {
+        uBase = 8;
+        psz++;
+    }
+    else
+        uBase = 10;
+
+    /*
+     * Convert until we hit a non-digit.
+     */
+    i = 0;
+    for (;;)
+    {
+        unsigned iDigit;
+        int ch = *psz;
+        switch (ch)
+        {
+            case '0':   iDigit =  0; break;
+            case '1':   iDigit =  1; break;
+            case '2':   iDigit =  2; break;
+            case '3':   iDigit =  3; break;
+            case '4':   iDigit =  4; break;
+            case '5':   iDigit =  5; break;
+            case '6':   iDigit =  6; break;
+            case '7':   iDigit =  7; break;
+            case '8':   iDigit =  8; break;
+            case '9':   iDigit =  9; break;
+            case 'a':
+            case 'A':   iDigit = 10; break;
+            case 'b':
+            case 'B':   iDigit = 11; break;
+            case 'c':
+            case 'C':   iDigit = 12; break;
+            case 'd':
+            case 'D':   iDigit = 13; break;
+            case 'e':
+            case 'E':   iDigit = 14; break;
+            case 'f':
+            case 'F':   iDigit = 15; break;
+
+            default:
+                /* is the rest white space? */
+                while (isspace((unsigned int)*psz))
+                    psz++;
+                if (*psz != '\0')
+                {
+                    iDigit = uBase;
+                    break;
+                }
+                /* fall thru */
+
+            case '\0':
+                if (fNegative)
+                    i = -i;
+                *piDst = i;
+                return rc;
+        }
+        if (iDigit >= uBase)
+        {
+            if (fNegative)
+                i = -i;
+            *piDst = i;
+            if (!fQuiet)
+                expr_error(pThis, "Invalid a number \"%.80s\"", pszSrc);
+            return kExprRet_Error;
+        }
+
+        /* add the digit and advance */
+        i *= uBase;
+        i += iDigit;
+        psz++;
+    }
+    /* not reached */
+}
+
+
+/**
+ * Checks if the variable is a string or not.
+ *
+ * @returns 1 if it's a string, 0 otherwise.
+ * @param   pVar    The variable.
+ */
+static int expr_var_is_string(PCEXPRVAR pVar)
+{
+    return pVar->enmType >= kExprVar_String;
+}
+
+
+/**
+ * Checks if the variable contains a string that was quoted
+ * in the expression.
+ *
+ * @returns 1 if if was a quoted string, otherwise 0.
+ * @param   pVar    The variable.
+ */
+static int expr_var_was_quoted(PCEXPRVAR pVar)
+{
+    return pVar->enmType >= kExprVar_QuotedString;
+}
+
+
+/**
+ * Deletes a variable.
+ *
+ * @param   pVar    The variable.
+ */
+static void expr_var_delete(PEXPRVAR pVar)
+{
+    if (expr_var_is_string(pVar))
+    {
+        free(pVar->uVal.psz);
+        pVar->uVal.psz = NULL;
+    }
+    pVar->enmType = kExprVar_Invalid;
+}
+
+
+/**
+ * Initializes a new variables with a sub-string value.
+ *
+ * @param   pVar    The new variable.
+ * @param   psz     The start of the string value.
+ * @param   cch     The number of chars to copy.
+ * @param   enmType The string type.
+ */
+static void expr_var_init_substring(PEXPRVAR pVar, const char *psz, size_t cch, EXPRVARTYPE enmType)
+{
+    /* convert string needing expanding into simple ones if possible.  */
+    if (    enmType == kExprVar_String
+        &&  !memchr(psz, '$', cch))
+        enmType = kExprVar_SimpleString;
+    else if (   enmType == kExprVar_QuotedString
+             && !memchr(psz, '$', cch))
+        enmType = kExprVar_QuotedSimpleString;
+
+    pVar->enmType = enmType;
+    pVar->uVal.psz = xmalloc(cch + 1);
+    memcpy(pVar->uVal.psz, psz, cch);
+    pVar->uVal.psz[cch] = '\0';
+}
+
+
+#if 0  /* unused */
+/**
+ * Initializes a new variables with a string value.
+ *
+ * @param   pVar    The new variable.
+ * @param   psz     The string value.
+ * @param   enmType The string type.
+ */
+static void expr_var_init_string(PEXPRVAR pVar, const char *psz, EXPRVARTYPE enmType)
+{
+    expr_var_init_substring(pVar, psz, strlen(psz), enmType);
+}
+
+
+/**
+ * Assigns a sub-string value to a variable.
+ *
+ * @param   pVar    The new variable.
+ * @param   psz     The start of the string value.
+ * @param   cch     The number of chars to copy.
+ * @param   enmType The string type.
+ */
+static void expr_var_assign_substring(PEXPRVAR pVar, const char *psz, size_t cch, EXPRVARTYPE enmType)
+{
+    expr_var_delete(pVar);
+    expr_var_init_substring(pVar, psz, cch, enmType);
+}
+
+
+/**
+ * Assignes a string value to a variable.
+ *
+ * @param   pVar    The variable.
+ * @param   psz     The string value.
+ * @param   enmType The string type.
+ */
+static void expr_var_assign_string(PEXPRVAR pVar, const char *psz, EXPRVARTYPE enmType)
+{
+    expr_var_delete(pVar);
+    expr_var_init_string(pVar, psz, enmType);
+}
+#endif /* unused */
+
+
+/**
+ * Simplifies a string variable.
+ *
+ * @param   pVar    The variable.
+ */
+static void expr_var_make_simple_string(PEXPRVAR pVar)
+{
+    switch (pVar->enmType)
+    {
+        case kExprVar_Num:
+        {
+            char *psz = (char *)xmalloc(EXPR_NUM_LEN);
+            expr_num_to_string(psz, pVar->uVal.i);
+            pVar->uVal.psz = psz;
+            pVar->enmType = kExprVar_SimpleString;
+            break;
+        }
+
+        case kExprVar_String:
+        case kExprVar_QuotedString:
+        {
+            char *psz;
+            assert(strchr(pVar->uVal.psz, '$'));
+
+            psz = allocated_variable_expand(pVar->uVal.psz);
+            free(pVar->uVal.psz);
+            pVar->uVal.psz = psz;
+
+            pVar->enmType = pVar->enmType == kExprVar_String
+                          ? kExprVar_SimpleString
+                          : kExprVar_QuotedSimpleString;
+            break;
+        }
+
+        case kExprVar_SimpleString:
+        case kExprVar_QuotedSimpleString:
+            /* nothing to do. */
+            break;
+
+        default:
+            assert(0);
+    }
+}
+
+
+#if 0 /* unused */
+/**
+ * Turns a variable into a string value.
+ *
+ * @param   pVar    The variable.
+ */
+static void expr_var_make_string(PEXPRVAR pVar)
+{
+    switch (pVar->enmType)
+    {
+        case kExprVar_Num:
+            expr_var_make_simple_string(pVar);
+            break;
+
+        case kExprVar_String:
+        case kExprVar_SimpleString:
+        case kExprVar_QuotedString:
+        case kExprVar_QuotedSimpleString:
+            /* nothing to do. */
+            break;
+
+        default:
+            assert(0);
+    }
+}
+#endif /* unused */
+
+
+/**
+ * Initializes a new variables with a integer value.
+ *
+ * @param   pVar    The new variable.
+ * @param   i       The integer value.
+ */
+static void expr_var_init_num(PEXPRVAR pVar, EXPRINT64 i)
+{
+    pVar->enmType = kExprVar_Num;
+    pVar->uVal.i = i;
+}
+
+
+/**
+ * Assigns a integer value to a variable.
+ *
+ * @param   pVar    The variable.
+ * @param   i       The integer value.
+ */
+static void expr_var_assign_num(PEXPRVAR pVar, EXPRINT64 i)
+{
+    expr_var_delete(pVar);
+    expr_var_init_num(pVar, i);
+}
+
+
+/**
+ * Turns the variable into a number.
+ *
+ * @returns status code.
+ * @param   pThis   The evaluator instance.
+ * @param   pVar    The variable.
+ */
+static EXPRRET expr_var_make_num(PEXPR pThis, PEXPRVAR pVar)
+{
+    switch (pVar->enmType)
+    {
+        case kExprVar_Num:
+            /* nothing to do. */
+            break;
+
+        case kExprVar_String:
+            expr_var_make_simple_string(pVar);
+            /* fall thru */
+        case kExprVar_SimpleString:
+        {
+            EXPRINT64 i;
+            EXPRRET rc = expr_string_to_num(pThis, &i, pVar->uVal.psz, 0 /* fQuiet */);
+            if (rc < kExprRet_Ok)
+                return rc;
+            expr_var_assign_num(pVar, i);
+            break;
+        }
+
+        case kExprVar_QuotedString:
+        case kExprVar_QuotedSimpleString:
+            expr_error(pThis, "Cannot convert a quoted string to a number");
+            return kExprRet_Error;
+
+        default:
+            assert(0);
+            return kExprRet_Error;
+    }
+
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Try to turn the variable into a number.
+ *
+ * @returns status code.
+ * @param   pVar    The variable.
+ */
+static EXPRRET expr_var_try_make_num(PEXPRVAR pVar)
+{
+    switch (pVar->enmType)
+    {
+        case kExprVar_Num:
+            /* nothing to do. */
+            break;
+
+        case kExprVar_String:
+            expr_var_make_simple_string(pVar);
+            /* fall thru */
+        case kExprVar_SimpleString:
+        {
+            EXPRINT64 i;
+            EXPRRET rc = expr_string_to_num(NULL, &i, pVar->uVal.psz, 1 /* fQuiet */);
+            if (rc < kExprRet_Ok)
+                return rc;
+            expr_var_assign_num(pVar, i);
+            break;
+        }
+
+        default:
+            assert(0);
+        case kExprVar_QuotedString:
+        case kExprVar_QuotedSimpleString:
+            /* can't do this */
+            return kExprRet_Error;
+    }
+
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Initializes a new variables with a boolean value.
+ *
+ * @param   pVar    The new variable.
+ * @param   f       The boolean value.
+ */
+static void expr_var_init_bool(PEXPRVAR pVar, int f)
+{
+    pVar->enmType = kExprVar_Num;
+    pVar->uVal.i = !!f;
+}
+
+
+/**
+ * Assigns a boolean value to a variable.
+ *
+ * @param   pVar    The variable.
+ * @param   f       The boolean value.
+ */
+static void expr_var_assign_bool(PEXPRVAR pVar, int f)
+{
+    expr_var_delete(pVar);
+    expr_var_init_bool(pVar, f);
+}
+
+
+/**
+ * Turns the variable into an boolean.
+ *
+ * @returns the boolean interpretation.
+ * @param   pVar    The variable.
+ */
+static int expr_var_make_bool(PEXPRVAR pVar)
+{
+    switch (pVar->enmType)
+    {
+        case kExprVar_Num:
+            pVar->uVal.i = !!pVar->uVal.i;
+            break;
+
+        case kExprVar_String:
+            expr_var_make_simple_string(pVar);
+            /* fall thru */
+        case kExprVar_SimpleString:
+        {
+            /*
+             * Try convert it to a number. If that fails, use the
+             * GNU make boolean logic - not empty string means true.
+             */
+            EXPRINT64 iVal;
+            char const *psz = pVar->uVal.psz;
+            while (isblank((unsigned char)*psz))
+                psz++;
+            if (    *psz
+                &&  expr_string_to_num(NULL, &iVal, psz, 1 /* fQuiet */) >= kExprRet_Ok)
+                expr_var_assign_bool(pVar, iVal != 0);
+            else
+                expr_var_assign_bool(pVar, *psz != '\0');
+            break;
+        }
+
+        case kExprVar_QuotedString:
+            expr_var_make_simple_string(pVar);
+            /* fall thru */
+        case kExprVar_QuotedSimpleString:
+            /*
+             * Use GNU make boolean logic (not empty string means true).
+             * No stripping here, the string is quoted.
+             */
+            expr_var_assign_bool(pVar, *pVar->uVal.psz != '\0');
+            break;
+
+        default:
+            assert(0);
+            break;
+    }
+
+    return pVar->uVal.i;
+}
+
+
+/**
+ * Pops a varable off the stack and deletes it.
+ * @param   pThis   The evaluator instance.
+ */
+static void expr_pop_and_delete_var(PEXPR pThis)
+{
+    expr_var_delete(&pThis->aVars[pThis->iVar]);
+    pThis->iVar--;
+}
+
+
+
+/**
+ * Tries to make the variables the same type.
+ *
+ * This will not convert numbers to strings, unless one of them
+ * is a quoted string.
+ *
+ * this will try convert both to numbers if neither is quoted. Both
+ * conversions will have to suceed for this to be commited.
+ *
+ * All strings will be simplified.
+ *
+ * @returns status code. Done complaining on failure.
+ *
+ * @param   pThis   The evaluator instance.
+ * @param   pVar1   The first variable.
+ * @param   pVar2   The second variable.
+ */
+static EXPRRET expr_var_unify_types(PEXPR pThis, PEXPRVAR pVar1, PEXPRVAR pVar2, const char *pszOp)
+{
+    /*
+     * Try make the variables the same type before comparing.
+     */
+    if (    !expr_var_was_quoted(pVar1)
+        &&  !expr_var_was_quoted(pVar2))
+    {
+        if (    expr_var_is_string(pVar1)
+            ||  expr_var_is_string(pVar2))
+        {
+            if (!expr_var_is_string(pVar1))
+                expr_var_try_make_num(pVar2);
+            else if (!expr_var_is_string(pVar2))
+                expr_var_try_make_num(pVar1);
+            else
+            {
+                /*
+                 * Both are strings, simplify them then see if both can be made into numbers.
+                 */
+                EXPRINT64 iVar1;
+                EXPRINT64 iVar2;
+
+                expr_var_make_simple_string(pVar1);
+                expr_var_make_simple_string(pVar2);
+
+                if (    expr_string_to_num(NULL, &iVar1, pVar1->uVal.psz, 1 /* fQuiet */) >= kExprRet_Ok
+                    &&  expr_string_to_num(NULL, &iVar2, pVar2->uVal.psz, 1 /* fQuiet */) >= kExprRet_Ok)
+                {
+                    expr_var_assign_num(pVar1, iVar1);
+                    expr_var_assign_num(pVar2, iVar2);
+                }
+            }
+        }
+    }
+    else
+    {
+        expr_var_make_simple_string(pVar1);
+        expr_var_make_simple_string(pVar2);
+    }
+
+    /*
+     * Complain if they aren't the same type now.
+     */
+    if (expr_var_is_string(pVar1) != expr_var_is_string(pVar2))
+    {
+        expr_error(pThis, "Unable to unify types for \"%s\"", pszOp);
+        return kExprRet_Error;
+    }
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Is variable defined, unary.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_defined(PEXPR pThis)
+{
+    PEXPRVAR            pVar = &pThis->aVars[pThis->iVar];
+    struct variable    *pMakeVar;
+
+    expr_var_make_simple_string(pVar);
+    pMakeVar = lookup_variable(pVar->uVal.psz, strlen(pVar->uVal.psz));
+    expr_var_assign_bool(pVar, pMakeVar && *pMakeVar->value != '\0');
+
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Is target defined, unary.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_target(PEXPR pThis)
+{
+    PEXPRVAR            pVar = &pThis->aVars[pThis->iVar];
+    struct file        *pFile = NULL;
+
+    /*
+     * Because of secondary target expansion, lookup the unexpanded
+     * name first.
+     */
+#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
+    if (    pVar->enmType == kExprVar_String
+        ||  pVar->enmType == kExprVar_QuotedString)
+    {
+        pFile = lookup_file(pVar->uVal.psz);
+        if (    pFile
+            &&  !pFile->need_2nd_target_expansion)
+            pFile = NULL;
+    }
+    if (!pFile)
+#endif
+    {
+        expr_var_make_simple_string(pVar);
+        pFile = lookup_file(pVar->uVal.psz);
+    }
+
+    /*
+     * Always inspect the head of a multiple target rule
+     * and look for a file with commands.
+     */
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+    if (pFile && pFile->multi_head)
+        pFile = pFile->multi_head;
+#endif
+
+    while (pFile && !pFile->cmds)
+        pFile = pFile->prev;
+
+    expr_var_assign_bool(pVar, pFile != NULL && pFile->is_target);
+
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Convert to boolean.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_bool(PEXPR pThis)
+{
+    expr_var_make_bool(&pThis->aVars[pThis->iVar]);
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Convert to number, works on quoted strings too.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_num(PEXPR pThis)
+{
+    PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
+
+    /* unquote the string */
+    if (pVar->enmType == kExprVar_QuotedSimpleString)
+        pVar->enmType = kExprVar_SimpleString;
+    else if (pVar->enmType == kExprVar_QuotedString)
+        pVar->enmType = kExprVar_String;
+
+    return expr_var_make_num(pThis, pVar);
+}
+
+
+/**
+ * Convert to string (simplified and quoted)
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_str(PEXPR pThis)
+{
+    PEXPRVAR pVar = &pThis->aVars[pThis->iVar];
+
+    expr_var_make_simple_string(pVar);
+    pVar->enmType = kExprVar_QuotedSimpleString;
+
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Pluss (dummy / make_integer)
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_pluss(PEXPR pThis)
+{
+    return expr_var_make_num(pThis, &pThis->aVars[pThis->iVar]);
+}
+
+
+/**
+ * Minus (negate)
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_minus(PEXPR pThis)
+{
+    EXPRRET     rc;
+    PEXPRVAR    pVar = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar);
+    if (rc >= kExprRet_Ok)
+        pVar->uVal.i = -pVar->uVal.i;
+
+    return rc;
+}
+
+
+
+/**
+ * Bitwise NOT.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_bitwise_not(PEXPR pThis)
+{
+    EXPRRET     rc;
+    PEXPRVAR    pVar = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar);
+    if (rc >= kExprRet_Ok)
+        pVar->uVal.i = ~pVar->uVal.i;
+
+    return rc;
+}
+
+
+/**
+ * Logical NOT.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_logical_not(PEXPR pThis)
+{
+    PEXPRVAR    pVar = &pThis->aVars[pThis->iVar];
+
+    expr_var_make_bool(pVar);
+    pVar->uVal.i = !pVar->uVal.i;
+
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Multiplication.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_multiply(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i *= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+
+/**
+ * Division.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_divide(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i /= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+
+/**
+ * Modulus.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_modulus(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i %= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+
+/**
+ * Addition (numeric).
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_add(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i += pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+/**
+ * Subtract (numeric).
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_sub(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i -= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+/**
+ * Bitwise left shift.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_shift_left(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i <<= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+/**
+ * Bitwise right shift.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_shift_right(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i >>= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+/**
+ * Less than or equal
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_less_or_equal_than(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_unify_types(pThis, pVar1, pVar2, "<=");
+    if (rc >= kExprRet_Ok)
+    {
+        if (!expr_var_is_string(pVar1))
+            expr_var_assign_bool(pVar1, pVar1->uVal.i <= pVar2->uVal.i);
+        else
+            expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) <= 0);
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+/**
+ * Less than.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_less_than(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_unify_types(pThis, pVar1, pVar2, "<");
+    if (rc >= kExprRet_Ok)
+    {
+        if (!expr_var_is_string(pVar1))
+            expr_var_assign_bool(pVar1, pVar1->uVal.i < pVar2->uVal.i);
+        else
+            expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) < 0);
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+/**
+ * Greater or equal than
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_greater_or_equal_than(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_unify_types(pThis, pVar1, pVar2, ">=");
+    if (rc >= kExprRet_Ok)
+    {
+        if (!expr_var_is_string(pVar1))
+            expr_var_assign_bool(pVar1, pVar1->uVal.i >= pVar2->uVal.i);
+        else
+            expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) >= 0);
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+/**
+ * Greater than.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_greater_than(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    rc = expr_var_unify_types(pThis, pVar1, pVar2, ">");
+    if (rc >= kExprRet_Ok)
+    {
+        if (!expr_var_is_string(pVar1))
+            expr_var_assign_bool(pVar1, pVar1->uVal.i > pVar2->uVal.i);
+        else
+            expr_var_assign_bool(pVar1, strcmp(pVar1->uVal.psz, pVar2->uVal.psz) > 0);
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return rc;
+}
+
+
+/**
+ * Equal.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_equal(PEXPR pThis)
+{
+    EXPRRET     rc = kExprRet_Ok;
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    /*
+     * The same type?
+     */
+    if (expr_var_is_string(pVar1) == expr_var_is_string(pVar2))
+    {
+        if (!expr_var_is_string(pVar1))
+            /* numbers are simple */
+            expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
+        else
+        {
+            /* try a normal string compare. */
+            expr_var_make_simple_string(pVar1);
+            expr_var_make_simple_string(pVar2);
+            if (!strcmp(pVar1->uVal.psz, pVar2->uVal.psz))
+                expr_var_assign_bool(pVar1, 1);
+            /* try convert and compare as number instead. */
+            else if (   expr_var_try_make_num(pVar1) >= kExprRet_Ok
+                     && expr_var_try_make_num(pVar2) >= kExprRet_Ok)
+                expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
+            /* ok, they really aren't equal. */
+            else
+                expr_var_assign_bool(pVar1, 0);
+        }
+    }
+    else
+    {
+        /*
+         * If the type differs, there are now two options:
+         *  1. Convert the string to a valid number and compare the numbers.
+         *  2. Convert an empty string to a 'false' boolean value and compare
+         *     numerically. This one is a bit questionable, so we don't try this.
+         */
+        if (   expr_var_try_make_num(pVar1) >= kExprRet_Ok
+            && expr_var_try_make_num(pVar2) >= kExprRet_Ok)
+            expr_var_assign_bool(pVar1, pVar1->uVal.i == pVar2->uVal.i);
+        else
+        {
+            expr_error(pThis, "Cannot compare strings and numbers");
+            rc = kExprRet_Error;
+        }
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Not equal.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_not_equal(PEXPR pThis)
+{
+    EXPRRET rc = expr_op_equal(pThis);
+    if (rc >= kExprRet_Ok)
+        rc = expr_op_logical_not(pThis);
+    return rc;
+}
+
+
+/**
+ * Bitwise AND.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_bitwise_and(PEXPR pThis)
+{
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+    EXPRRET     rc;
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i &= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Bitwise XOR.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_bitwise_xor(PEXPR pThis)
+{
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+    EXPRRET     rc;
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i ^= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Bitwise OR.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_bitwise_or(PEXPR pThis)
+{
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+    EXPRRET     rc;
+
+    rc = expr_var_make_num(pThis, pVar1);
+    if (rc >= kExprRet_Ok)
+    {
+        rc = expr_var_make_num(pThis, pVar2);
+        if (rc >= kExprRet_Ok)
+            pVar1->uVal.i |= pVar2->uVal.i;
+    }
+
+    expr_pop_and_delete_var(pThis);
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Logical AND.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_logical_and(PEXPR pThis)
+{
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    if (   expr_var_make_bool(pVar1)
+        && expr_var_make_bool(pVar2))
+        expr_var_assign_bool(pVar1, 1);
+    else
+        expr_var_assign_bool(pVar1, 0);
+
+    expr_pop_and_delete_var(pThis);
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Logical OR.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_logical_or(PEXPR pThis)
+{
+    PEXPRVAR    pVar1 = &pThis->aVars[pThis->iVar - 1];
+    PEXPRVAR    pVar2 = &pThis->aVars[pThis->iVar];
+
+    if (   expr_var_make_bool(pVar1)
+        || expr_var_make_bool(pVar2))
+        expr_var_assign_bool(pVar1, 1);
+    else
+        expr_var_assign_bool(pVar1, 0);
+
+    expr_pop_and_delete_var(pThis);
+    return kExprRet_Ok;
+}
+
+
+/**
+ * Left parenthesis.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_left_parenthesis(PEXPR pThis)
+{
+    /*
+     * There should be a right parenthesis operator lined up for us now,
+     * eat it. If not found there is an inbalance.
+     */
+    EXPRRET rc = expr_get_binary_or_eoe_or_rparen(pThis);
+    if (    rc == kExprRet_Operator
+        &&  pThis->apOps[pThis->iOp]->szOp[0] == ')')
+    {
+        /* pop it and get another one which we can leave pending. */
+        pThis->iOp--;
+        rc = expr_get_binary_or_eoe_or_rparen(pThis);
+        if (rc >= kExprRet_Ok)
+            expr_unget_op(pThis);
+    }
+    else
+    {
+        expr_error(pThis, "Missing ')'");
+        rc = kExprRet_Error;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Right parenthesis, dummy that's never actually called.
+ *
+ * @returns Status code.
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_op_right_parenthesis(PEXPR pThis)
+{
+    assert(0);
+    (void)pThis;
+    return kExprRet_Ok;
+}
+
+
+
+
+
+/**
+ * The operator table.
+ *
+ * This table is NOT ordered by precedence, but for linear search
+ * allowing for first match to return the correct operator. This
+ * means that || must come before |, or else | will match all.
+ */
+static const EXPROP g_aExprOps[] =
+{
+#define EXPR_OP(szOp, iPrecedence, cArgs, pfn)  {  szOp, sizeof(szOp) - 1, '\0', iPrecedence, cArgs, pfn }
+    /*        Name, iPrecedence,  cArgs,    pfn    */
+    EXPR_OP("defined",     90,      1,    expr_op_defined),
+    EXPR_OP("target",      90,      1,    expr_op_target),
+    EXPR_OP("bool",        90,      1,    expr_op_bool),
+    EXPR_OP("num",         90,      1,    expr_op_num),
+    EXPR_OP("str",         90,      1,    expr_op_str),
+    EXPR_OP("+",           80,      1,    expr_op_pluss),
+    EXPR_OP("-",           80,      1,    expr_op_minus),
+    EXPR_OP("~",           80,      1,    expr_op_bitwise_not),
+    EXPR_OP("*",           75,      2,    expr_op_multiply),
+    EXPR_OP("/",           75,      2,    expr_op_divide),
+    EXPR_OP("%",           75,      2,    expr_op_modulus),
+    EXPR_OP("+",           70,      2,    expr_op_add),
+    EXPR_OP("-",           70,      2,    expr_op_sub),
+    EXPR_OP("<<",          65,      2,    expr_op_shift_left),
+    EXPR_OP(">>",          65,      2,    expr_op_shift_right),
+    EXPR_OP("<=",          60,      2,    expr_op_less_or_equal_than),
+    EXPR_OP("<",           60,      2,    expr_op_less_than),
+    EXPR_OP(">=",          60,      2,    expr_op_greater_or_equal_than),
+    EXPR_OP(">",           60,      2,    expr_op_greater_than),
+    EXPR_OP("==",          55,      2,    expr_op_equal),
+    EXPR_OP("!=",          55,      2,    expr_op_not_equal),
+    EXPR_OP("!",           80,      1,    expr_op_logical_not),
+    EXPR_OP("^",           45,      2,    expr_op_bitwise_xor),
+    EXPR_OP("&&",          35,      2,    expr_op_logical_and),
+    EXPR_OP("&",           50,      2,    expr_op_bitwise_and),
+    EXPR_OP("||",          30,      2,    expr_op_logical_or),
+    EXPR_OP("|",           40,      2,    expr_op_bitwise_or),
+            { "(", 1, ')',   10,      1,    expr_op_left_parenthesis },
+            { ")", 1, '(',   10,      0,    expr_op_right_parenthesis },
+ /*         { "?", 1, ':',    5,      2,    expr_op_question },
+            { ":", 1, '?',    5,      2,    expr_op_colon }, -- too weird for now. */
+#undef EXPR_OP
+};
+
+/** Dummy end of expression fake. */
+static const EXPROP g_ExprEndOfExpOp =
+{
+              "", 0, '\0',    0,      0,    NULL
+};
+
+
+/**
+ * Initializes the opcode character map if necessary.
+ */
+static void expr_map_init(void)
+{
+    unsigned i;
+    if (g_fExprInitializedMap)
+        return;
+
+    /*
+     * Initialize it.
+     */
+    memset(&g_auchOpStartCharMap, 0, sizeof(g_auchOpStartCharMap));
+    for (i = 0; i < sizeof(g_aExprOps) / sizeof(g_aExprOps[0]); i++)
+    {
+        unsigned int ch = (unsigned int)g_aExprOps[i].szOp[0];
+        if (!g_auchOpStartCharMap[ch])
+            g_auchOpStartCharMap[ch] = (i << 1) | 1;
+    }
+
+    g_fExprInitializedMap = 1;
+}
+
+
+/**
+ * Looks up a character in the map.
+ *
+ * @returns the value for that char.
+ * @retval  0 if not a potential opcode start char.
+ * @retval  non-zero if it's a potential operator. The low bit is always set
+ *          while the remaining 7 bits is the index into the operator table
+ *          of the first match.
+ *
+ * @param   ch      The character.
+ */
+static unsigned char expr_map_get(char ch)
+{
+    return g_auchOpStartCharMap[(unsigned int)ch];
+}
+
+
+/**
+ * Searches the operator table given a potential operator start char.
+ *
+ * @returns Pointer to the matching operator. NULL if not found.
+ * @param   psz     Pointer to what can be an operator.
+ * @param   uchVal  The expr_map_get value.
+ * @param   fUnary  Whether it must be an unary operator or not.
+ */
+static PCEXPROP expr_lookup_op(char const *psz, unsigned char uchVal, int fUnary)
+{
+    char ch = *psz;
+    unsigned i;
+
+    for (i = uchVal >> 1; i < sizeof(g_aExprOps) / sizeof(g_aExprOps[0]); i++)
+    {
+        /* compare the string... */
+        switch (g_aExprOps[i].cchOp)
+        {
+            case 1:
+                if (g_aExprOps[i].szOp[0] != ch)
+                    continue;
+                break;
+            case 2:
+                if (    g_aExprOps[i].szOp[0] != ch
+                    ||  g_aExprOps[i].szOp[1] != psz[1])
+                    continue;
+                break;
+            default:
+                if (    g_aExprOps[i].szOp[0] != ch
+                    ||  strncmp(&g_aExprOps[i].szOp[1], psz + 1, g_aExprOps[i].cchOp - 1))
+                    continue;
+                break;
+        }
+
+        /* ... and the operator type. */
+        if (fUnary == (g_aExprOps[i].cArgs == 1))
+        {
+            /* got a match! */
+            return &g_aExprOps[i];
+        }
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Ungets a binary operator.
+ *
+ * The operator is poped from the stack and put in the pending position.
+ *
+ * @param   pThis       The evaluator instance.
+ */
+static void expr_unget_op(PEXPR pThis)
+{
+    assert(pThis->pPending == NULL);
+    assert(pThis->iOp >= 0);
+
+    pThis->pPending = pThis->apOps[pThis->iOp];
+    pThis->apOps[pThis->iOp] = NULL;
+    pThis->iOp--;
+}
+
+
+
+/**
+ * Get the next token, it should be a binary operator, or the end of
+ * the expression, or a right parenthesis.
+ *
+ * The operator is pushed onto the stack and the status code indicates
+ * which of the two we found.
+ *
+ * @returns status code. Will grumble on failure.
+ * @retval  kExprRet_EndOfExpr if we encountered the end of the expression.
+ * @retval  kExprRet_Operator if we encountered a binary operator or right
+ *          parenthesis. It's on the operator stack.
+ *
+ * @param   pThis       The evaluator instance.
+ */
+static EXPRRET expr_get_binary_or_eoe_or_rparen(PEXPR pThis)
+{
+    /*
+     * See if there is anything pending first.
+     */
+    PCEXPROP pOp = pThis->pPending;
+    if (pOp)
+        pThis->pPending = NULL;
+    else
+    {
+        /*
+         * Eat more of the expression.
+         */
+        char const *psz = pThis->psz;
+
+        /* spaces */
+        while (isspace((unsigned int)*psz))
+            psz++;
+        /* see what we've got. */
+        if (*psz)
+        {
+            unsigned char uchVal = expr_map_get(*psz);
+            if (uchVal)
+                pOp = expr_lookup_op(psz, uchVal, 0 /* fUnary */);
+            if (!pOp)
+            {
+                expr_error(pThis, "Expected binary operator, found \"%.42s\"...", psz);
+                return kExprRet_Error;
+            }
+            psz += pOp->cchOp;
+        }
+        else
+            pOp = &g_ExprEndOfExpOp;
+        pThis->psz = psz;
+    }
+
+    /*
+     * Push it.
+     */
+    if (pThis->iOp >= EXPR_MAX_OPERATORS - 1)
+    {
+        expr_error(pThis, "Operator stack overflow");
+        return kExprRet_Error;
+    }
+    pThis->apOps[++pThis->iOp] = pOp;
+
+    return pOp->iPrecedence
+         ? kExprRet_Operator
+         : kExprRet_EndOfExpr;
+}
+
+
+
+/**
+ * Get the next token, it should be an unary operator or an operand.
+ *
+ * This will fail if encountering the end of the expression since
+ * it is implied that there should be something more.
+ *
+ * The token is pushed onto the respective stack and the status code
+ * indicates which it is.
+ *
+ * @returns status code. On failure we'll be done bitching already.
+ * @retval  kExprRet_Operator if we encountered an unary operator.
+ *          It's on the operator stack.
+ * @retval  kExprRet_Operand if we encountered an operand operator.
+ *          It's on the operand stack.
+ *
+ * @param   This        The evaluator instance.
+ */
+static EXPRRET expr_get_unary_or_operand(PEXPR pThis)
+{
+    EXPRRET       rc;
+    unsigned char   uchVal;
+    PCEXPROP      pOp;
+    char const     *psz = pThis->psz;
+
+    /*
+     * Eat white space and make sure there is something after it.
+     */
+    while (isspace((unsigned int)*psz))
+        psz++;
+    if (!*psz)
+    {
+        expr_error(pThis, "Unexpected end of expression");
+        return kExprRet_Error;
+    }
+
+    /*
+     * Is it an operator?
+     */
+    pOp = NULL;
+    uchVal = expr_map_get(*psz);
+    if (uchVal)
+        pOp = expr_lookup_op(psz, uchVal, 1 /* fUnary */);
+    if (pOp)
+    {
+        /*
+         * Push the operator onto the stack.
+         */
+        if (pThis->iVar < EXPR_MAX_OPERANDS - 1)
+        {
+            pThis->apOps[++pThis->iOp] = pOp;
+            rc = kExprRet_Operator;
+        }
+        else
+        {
+            expr_error(pThis, "Operator stack overflow");
+            rc = kExprRet_Error;
+        }
+        psz += pOp->cchOp;
+    }
+    else if (pThis->iVar < EXPR_MAX_OPERANDS - 1)
+    {
+        /*
+         * It's an operand. Figure out where it ends and
+         * push it onto the stack.
+         */
+        const char *pszStart;
+
+        rc = kExprRet_Ok;
+        if (*psz == '"')
+        {
+            pszStart = ++psz;
+            while (*psz && *psz != '"')
+                psz++;
+            expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_QuotedString);
+            if (*psz)
+                psz++;
+        }
+        else if (*psz == '\'')
+        {
+            pszStart = ++psz;
+            while (*psz && *psz != '\'')
+                psz++;
+            expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_QuotedSimpleString);
+            if (*psz)
+                psz++;
+        }
+        else
+        {
+            char    achPars[20];
+            int     iPar = -1;
+            char    chEndPar = '\0';
+            char    ch;
+
+            pszStart = psz;
+            while ((ch = *psz) != '\0')
+            {
+                /* $(adsf) or ${asdf} needs special handling. */
+                if (    ch == '$'
+                    &&  (   psz[1] == '('
+                         || psz[1] == '{'))
+                {
+                    psz++;
+                    if (iPar > (int)(sizeof(achPars) / sizeof(achPars[0])))
+                    {
+                        expr_error(pThis, "Too deep nesting of variable expansions");
+                        rc = kExprRet_Error;
+                        break;
+                    }
+                    achPars[++iPar] = chEndPar = ch == '(' ? ')' : '}';
+                }
+                else if (ch == chEndPar)
+                {
+                    iPar--;
+                    chEndPar = iPar >= 0 ? achPars[iPar] : '\0';
+                }
+                else if (!chEndPar)
+                {
+                    /** @todo combine isspace and expr_map_get! */
+                    unsigned chVal = expr_map_get(ch);
+                    if (chVal)
+                    {
+                        PCEXPROP pOp = expr_lookup_op(psz, uchVal, 0 /* fUnary */);
+                        if (pOp)
+                            break;
+                    }
+                    if (isspace((unsigned char)ch))
+                        break;
+                }
+
+                /* next */
+                psz++;
+            }
+
+            if (rc == kExprRet_Ok)
+                expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_String);
+        }
+    }
+    else
+    {
+        expr_error(pThis, "Operand stack overflow");
+        rc = kExprRet_Error;
+    }
+    pThis->psz = psz;
+
+    return rc;
+}
+
+
+/**
+ * Evaluates the current expression.
+ *
+ * @returns status code.
+ *
+ * @param   pThis       The instance.
+ */
+static EXPRRET expr_eval(PEXPR pThis)
+{
+    EXPRRET  rc;
+    PCEXPROP pOp;
+
+    /*
+     * The main loop.
+     */
+    for (;;)
+    {
+        /*
+         * Eat unary operators until we hit an operand.
+         */
+        do  rc = expr_get_unary_or_operand(pThis);
+        while (rc == kExprRet_Operator);
+        if (rc < kExprRet_Error)
+            break;
+
+        /*
+         * Look for a binary operator, right parenthesis or end of expression.
+         */
+        rc = expr_get_binary_or_eoe_or_rparen(pThis);
+        if (rc < kExprRet_Error)
+            break;
+        expr_unget_op(pThis);
+
+        /*
+         * Pop operators and apply them.
+         *
+         * Parenthesis will be handed via precedence, where the left parenthesis
+         * will go pop the right one and make another operator pending.
+         */
+        while (   pThis->iOp >= 0
+               && pThis->apOps[pThis->iOp]->iPrecedence >= pThis->pPending->iPrecedence)
+        {
+            pOp = pThis->apOps[pThis->iOp--];
+            assert(pThis->iVar + 1 >= pOp->cArgs);
+            rc = pOp->pfn(pThis);
+            if (rc < kExprRet_Error)
+                break;
+        }
+        if (rc < kExprRet_Error)
+            break;
+
+        /*
+         * Get the next binary operator or end of expression.
+         * There should be no right parenthesis here.
+         */
+        rc = expr_get_binary_or_eoe_or_rparen(pThis);
+        if (rc < kExprRet_Error)
+            break;
+        pOp = pThis->apOps[pThis->iOp];
+        if (!pOp->iPrecedence)
+            break;  /* end of expression */
+        if (!pOp->cArgs)
+        {
+            expr_error(pThis, "Unexpected \"%s\"", pOp->szOp);
+            rc = kExprRet_Error;
+            break;
+        }
+    }
+
+    return rc;
+}
+
+
+/**
+ * Destroys the given instance.
+ *
+ * @param   pThis       The instance to destroy.
+ */
+static void expr_destroy(PEXPR pThis)
+{
+    while (pThis->iVar >= 0)
+    {
+        expr_var_delete(pThis->aVars);
+        pThis->iVar--;
+    }
+    free(pThis);
+}
+
+
+/**
+ * Instantiates an expression evaluator.
+ *
+ * @returns The instance.
+ *
+ * @param   pszExpr     What to parse.
+ *                      This must stick around until expr_destroy.
+ */
+static PEXPR expr_create(char const *pszExpr)
+{
+    PEXPR pThis = (PEXPR)xmalloc(sizeof(*pThis));
+    pThis->pszExpr = pszExpr;
+    pThis->psz = pszExpr;
+    pThis->pFileLoc = NULL;
+    pThis->pPending = NULL;
+    pThis->iVar = -1;
+    pThis->iOp = -1;
+
+    expr_map_init();
+    return pThis;
+}
+
+
+/**
+ * Evaluates the given if expression.
+ *
+ * @returns -1, 0 or 1.
+ * @retval  -1 if the expression is invalid.
+ * @retval  0 if the expression is true
+ * @retval  1 if the expression is false.
+ *
+ * @param   line    The expression. Can modify this as we like.
+ * @param   flocp   The file location, used for errors.
+ */
+int expr_eval_if_conditionals(char *line, const struct floc *flocp)
+{
+    /*
+     * Instantiate the expression evaluator and let
+     * it have a go at it.
+     */
+    int rc = -1;
+    PEXPR pExpr = expr_create(line);
+    pExpr->pFileLoc = flocp;
+    if (expr_eval(pExpr) >= kExprRet_Ok)
+    {
+        /*
+         * Convert the result (on top of the stack) to boolean and
+         * set our return value accordingly.
+         */
+        if (expr_var_make_bool(&pExpr->aVars[0]))
+            rc = 0;
+        else
+            rc = 1;
+    }
+    expr_destroy(pExpr);
+
+    return rc;
+}
+
+
+/**
+ * Evaluates the given expression and returns the result as a string.
+ *
+ * @returns variable buffer position.
+ *
+ * @param   o       The current variable buffer position.
+ * @param   expr    The expression.
+ */
+char *expr_eval_to_string(char *o, char *expr)
+{
+    /*
+     * Instantiate the expression evaluator and let
+     * it have a go at it.
+     */
+    PEXPR pExpr = expr_create(expr);
+    if (expr_eval(pExpr) >= kExprRet_Ok)
+    {
+        /*
+         * Convert the result (on top of the stack) to a string
+         * and copy it out the variable buffer.
+         */
+        PEXPRVAR pVar = &pExpr->aVars[0];
+        expr_var_make_simple_string(pVar);
+        o = variable_buffer_output(o, pVar->uVal.psz, strlen(pVar->uVal.psz));
+    }
+    else
+        o = variable_buffer_output(o, "<expression evaluation failed>", sizeof("<expression evaluation failed>") - 1);
+    expr_destroy(pExpr);
+
+    return o;
+}
+
+
+#endif /* CONFIG_WITH_IF_CONDITIONALS */
+
Index: /tags/kBuild-0.1.4/src/kmk/file.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/file.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/file.c	(revision 1780)
@@ -0,0 +1,1200 @@
+/* Target file management for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#include <assert.h>
+
+#include "dep.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "variable.h"
+#include "debug.h"
+#include "hash.h"
+
+
+/* Remember whether snap_deps has been invoked: we need this to be sure we
+   don't add new rules (via $(eval ...)) afterwards.  In the future it would
+   be nice to support this, but it means we'd need to re-run snap_deps() or
+   at least its functionality... it might mean changing snap_deps() to be run
+   per-file, so we can invoke it after the eval... or remembering which files
+   in the hash have been snapped (a new boolean flag?) and having snap_deps()
+   only work on files which have not yet been snapped. */
+int snapped_deps = 0;
+
+/* Hash table of files the makefile knows how to make.  */
+
+static unsigned long
+file_hash_1 (const void *key)
+{
+  return_ISTRING_HASH_1 (((struct file const *) key)->hname);
+}
+
+static unsigned long
+file_hash_2 (const void *key)
+{
+  return_ISTRING_HASH_2 (((struct file const *) key)->hname);
+}
+
+static int
+file_hash_cmp (const void *x, const void *y)
+{
+  return_ISTRING_COMPARE (((struct file const *) x)->hname,
+			  ((struct file const *) y)->hname);
+}
+
+#ifndef	FILE_BUCKETS
+#define FILE_BUCKETS	1007
+#endif
+static struct hash_table files;
+
+/* Whether or not .SECONDARY with no prerequisites was given.  */
+static int all_secondary = 0;
+
+/* Access the hash table of all file records.
+   lookup_file  given a name, return the struct file * for that name,
+                or nil if there is none.
+*/
+
+struct file *
+lookup_file (const char *name)
+{
+  struct file *f;
+  struct file file_key;
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
+  char *lname;
+#endif
+
+  assert (*name != '\0');
+
+  /* This is also done in parse_file_seq, so this is redundant
+     for names read from makefiles.  It is here for names passed
+     on the command line.  */
+#ifdef VMS
+# ifndef WANT_CASE_SENSITIVE_TARGETS
+  if (*name != '.')
+    {
+      const char *n;
+      char *ln;
+      lname = xstrdup (name);
+      for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
+        *ln = isupper ((unsigned char)*n) ? tolower ((unsigned char)*n) : *n;
+      *ln = '\0';
+      name = lname;
+    }
+# endif
+
+  while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
+      name += 2;
+#endif
+  while (name[0] == '.' && name[1] == '/' && name[2] != '\0')
+    {
+      name += 2;
+      while (*name == '/')
+	/* Skip following slashes: ".//foo" is "foo", not "/foo".  */
+	++name;
+    }
+
+  if (*name == '\0')
+    /* It was all slashes after a dot.  */
+#if defined(VMS)
+    name = "[]";
+#elif defined(_AMIGA)
+    name = "";
+#else
+    name = "./";
+#endif
+
+  file_key.hname = name;
+  f = hash_find_item (&files, &file_key);
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
+  if (*name != '.')
+    free (lname);
+#endif
+
+  return f;
+}
+
+/* Look up a file record for file NAME and return it.
+   Create a new record if one doesn't exist.  NAME will be stored in the
+   new record so it should be constant or in the strcache etc.
+ */
+
+struct file *
+enter_file (const char *name)
+{
+  struct file *f;
+  struct file *new;
+  struct file **file_slot;
+  struct file file_key;
+
+  assert (*name != '\0');
+  assert (strcache_iscached (name));
+
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
+  if (*name != '.')
+    {
+      const char *n;
+      char *lname, *ln;
+      lname = xstrdup (name);
+      for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
+        if (isupper ((unsigned char)*n))
+          *ln = tolower ((unsigned char)*n);
+        else
+          *ln = *n;
+
+      *ln = '\0';
+      name = strcache_add (lname);
+      free (lname);
+    }
+#endif
+
+  file_key.hname = name;
+  file_slot = (struct file **) hash_find_slot (&files, &file_key);
+  f = *file_slot;
+  if (! HASH_VACANT (f) && !f->double_colon)
+    return f;
+
+  new = xmalloc (sizeof (struct file));
+  memset (new, '\0', sizeof (struct file));
+  new->name = new->hname = name;
+  new->update_status = -1;
+
+  if (HASH_VACANT (f))
+    {
+      new->last = new;
+      hash_insert_at (&files, new, file_slot);
+    }
+  else
+    {
+      /* There is already a double-colon entry for this file.  */
+      new->double_colon = f;
+      f->last->prev = new;
+      f->last = new;
+    }
+
+#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
+  /* Check if the name needs 2nd expansion or not. */
+  if (second_target_expansion && strchr (name, '$') != NULL)
+    new->need_2nd_target_expansion = 1;
+#endif 
+
+  return new;
+}
+
+
+/* Rehash FILE to NAME.  This is not as simple as resetting
+   the `hname' member, since it must be put in a new hash bucket,
+   and possibly merged with an existing file called NAME.  */
+
+void
+rehash_file (struct file *from_file, const char *to_hname)
+{
+  struct file file_key;
+  struct file **file_slot;
+  struct file *to_file;
+  struct file *deleted_file;
+  struct file *f;
+
+  /* If it's already that name, we're done.  */
+  file_key.hname = to_hname;
+  if (! file_hash_cmp (from_file, &file_key))
+    return;
+
+  /* Find the end of the renamed list for the "from" file.  */
+  file_key.hname = from_file->hname;
+  while (from_file->renamed != 0)
+    from_file = from_file->renamed;
+  if (file_hash_cmp (from_file, &file_key))
+    /* hname changed unexpectedly!! */
+    abort ();
+
+  /* Remove the "from" file from the hash.  */
+  deleted_file = hash_delete (&files, from_file);
+  if (deleted_file != from_file)
+    /* from_file isn't the one stored in files */
+    abort ();
+
+  /* Find where the newly renamed file will go in the hash.  */
+  file_key.hname = to_hname;
+  file_slot = (struct file **) hash_find_slot (&files, &file_key);
+  to_file = *file_slot;
+
+  /* Change the hash name for this file.  */
+  from_file->hname = to_hname;
+  for (f = from_file->double_colon; f != 0; f = f->prev)
+    f->hname = to_hname;
+
+  /* If the new name doesn't exist yet just set it to the renamed file.  */
+  if (HASH_VACANT (to_file))
+    {
+      hash_insert_at (&files, from_file, file_slot);
+      return;
+    }
+
+  /* TO_FILE already exists under TO_HNAME.
+     We must retain TO_FILE and merge FROM_FILE into it.  */
+
+  if (from_file->cmds != 0)
+    {
+      if (to_file->cmds == 0)
+        to_file->cmds = from_file->cmds;
+      else if (from_file->cmds != to_file->cmds)
+        {
+          /* We have two sets of commands.  We will go with the
+             one given in the rule explicitly mentioning this name,
+             but give a message to let the user know what's going on.  */
+          if (to_file->cmds->fileinfo.filenm != 0)
+            error (&from_file->cmds->fileinfo,
+                   _("Commands were specified for file `%s' at %s:%lu,"),
+                   from_file->name, to_file->cmds->fileinfo.filenm,
+                   to_file->cmds->fileinfo.lineno);
+          else
+            error (&from_file->cmds->fileinfo,
+                   _("Commands for file `%s' were found by implicit rule search,"),
+                   from_file->name);
+          error (&from_file->cmds->fileinfo,
+                 _("but `%s' is now considered the same file as `%s'."),
+                 from_file->name, to_hname);
+          error (&from_file->cmds->fileinfo,
+                 _("Commands for `%s' will be ignored in favor of those for `%s'."),
+                 to_hname, from_file->name);
+        }
+    }
+
+  /* Merge the dependencies of the two files.  */
+
+  if (to_file->deps == 0)
+    to_file->deps = from_file->deps;
+  else
+    {
+      struct dep *deps = to_file->deps;
+      while (deps->next != 0)
+        deps = deps->next;
+      deps->next = from_file->deps;
+    }
+
+  merge_variable_set_lists (&to_file->variables, from_file->variables);
+
+  if (to_file->double_colon && from_file->is_target && !from_file->double_colon)
+    fatal (NILF, _("can't rename single-colon `%s' to double-colon `%s'"),
+           from_file->name, to_hname);
+  if (!to_file->double_colon  && from_file->double_colon)
+    {
+      if (to_file->is_target)
+        fatal (NILF, _("can't rename double-colon `%s' to single-colon `%s'"),
+               from_file->name, to_hname);
+      else
+        to_file->double_colon = from_file->double_colon;
+    }
+
+  if (from_file->last_mtime > to_file->last_mtime)
+    /* %%% Kludge so -W wins on a file that gets vpathized.  */
+    to_file->last_mtime = from_file->last_mtime;
+
+  to_file->mtime_before_update = from_file->mtime_before_update;
+
+#define MERGE(field) to_file->field |= from_file->field
+  MERGE (precious);
+  MERGE (tried_implicit);
+  MERGE (updating);
+  MERGE (updated);
+  MERGE (is_target);
+  MERGE (cmd_target);
+  MERGE (phony);
+  MERGE (ignore_vpath);
+#undef MERGE
+
+  from_file->renamed = to_file;
+}
+
+/* Rename FILE to NAME.  This is not as simple as resetting
+   the `name' member, since it must be put in a new hash bucket,
+   and possibly merged with an existing file called NAME.  */
+
+void
+rename_file (struct file *from_file, const char *to_hname)
+{
+  rehash_file (from_file, to_hname);
+  while (from_file)
+    {
+      from_file->name = from_file->hname;
+      from_file = from_file->prev;
+    }
+}
+
+
+#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
+/* Performs secondary target name expansion and then renames
+   the file using rename_file. */
+static void 
+do_2nd_target_expansion (struct file *f)
+{
+   char *tmp_name = allocated_variable_expand (f->name);
+   const char *name = strcache_add (tmp_name);
+   free (tmp_name);
+   rename_file (f, name);
+}
+#endif /* CONFIG_WITH_2ND_TARGET_EXPANSION */
+
+
+/* Remove all nonprecious intermediate files.
+   If SIG is nonzero, this was caused by a fatal signal,
+   meaning that a different message will be printed, and
+   the message will go to stderr rather than stdout.  */
+
+void
+remove_intermediates (int sig)
+{
+  struct file **file_slot;
+  struct file **file_end;
+  int doneany = 0;
+
+  /* If there's no way we will ever remove anything anyway, punt early.  */
+  if (question_flag || touch_flag || all_secondary)
+    return;
+
+  if (sig && just_print_flag)
+    return;
+
+  file_slot = (struct file **) files.ht_vec;
+  file_end = file_slot + files.ht_size;
+  for ( ; file_slot < file_end; file_slot++)
+    if (! HASH_VACANT (*file_slot))
+      {
+	struct file *f = *file_slot;
+        /* Is this file eligible for automatic deletion?
+           Yes, IFF: it's marked intermediate, it's not secondary, it wasn't
+           given on the command-line, and it's either a -include makefile or
+           it's not precious.  */
+	if (f->intermediate && (f->dontcare || !f->precious)
+	    && !f->secondary && !f->cmd_target)
+	  {
+	    int status;
+	    if (f->update_status == -1)
+	      /* If nothing would have created this file yet,
+		 don't print an "rm" command for it.  */
+	      continue;
+	    if (just_print_flag)
+	      status = 0;
+	    else
+	      {
+		status = unlink (f->name);
+		if (status < 0 && errno == ENOENT)
+		  continue;
+	      }
+	    if (!f->dontcare)
+	      {
+		if (sig)
+		  error (NILF, _("*** Deleting intermediate file `%s'"), f->name);
+		else
+		  {
+		    if (! doneany)
+		      DB (DB_BASIC, (_("Removing intermediate files...\n")));
+		    if (!silent_flag)
+		      {
+			if (! doneany)
+			  {
+			    fputs ("rm ", stdout);
+			    doneany = 1;
+			  }
+			else
+			  putchar (' ');
+			fputs (f->name, stdout);
+			fflush (stdout);
+		      }
+		  }
+		if (status < 0)
+		  perror_with_name ("unlink: ", f->name);
+	      }
+	  }
+      }
+
+  if (doneany && !sig)
+    {
+      putchar ('\n');
+      fflush (stdout);
+    }
+}
+
+
+struct dep *
+parse_prereqs (char *p)
+{
+  struct dep *new = (struct dep *)
+    multi_glob (parse_file_seq (&p, '|', sizeof (struct dep), 1),
+                sizeof (struct dep));
+
+  if (*p)
+    {
+      /* Files that follow '|' are "order-only" prerequisites that satisfy the
+         dependency by existing: their modification times are irrelevant.  */
+      struct dep *ood;
+
+      ++p;
+      ood = (struct dep *)
+        multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
+                    sizeof (struct dep));
+
+      if (! new)
+        new = ood;
+      else
+        {
+          struct dep *dp;
+          for (dp = new; dp->next != NULL; dp = dp->next)
+            ;
+          dp->next = ood;
+        }
+
+      for (; ood != NULL; ood = ood->next)
+        ood->ignore_mtime = 1;
+    }
+
+  return new;
+}
+
+/* Set the intermediate flag.  */
+
+static void
+set_intermediate (const void *item)
+{
+  struct file *f = (struct file *) item;
+  f->intermediate = 1;
+}
+
+/* Expand and parse each dependency line. */
+static void
+expand_deps (struct file *f)
+{
+  struct dep *d;
+  struct dep *old = f->deps;
+  const char *file_stem = f->stem;
+  unsigned int last_dep_has_cmds = f->updating;
+  int initialized = 0;
+
+  f->updating = 0;
+  f->deps = 0;
+
+  for (d = old; d != 0; d = d->next)
+    {
+      size_t buffer_offset; /* bird */
+      struct dep *new, *d1;
+      char *p;
+
+      if (! d->name)
+        continue;
+
+      /* Create the dependency list.
+         If we're not doing 2nd expansion, then it's just the name.  We will
+         still need to massage it though.  */
+      if (! d->need_2nd_expansion)
+        {
+          p = variable_expand ("");
+          buffer_offset = p - variable_buffer;
+          variable_buffer_output (p, d->name, strlen (d->name) + 1);
+          p = variable_buffer + buffer_offset; /* bird - variable_buffer may have been reallocated. (observed it) */
+        }
+      else
+        {
+          /* If it's from a static pattern rule, convert the patterns into
+             "$*" so they'll expand properly.  */
+          if (d->staticpattern)
+            {
+              char *o;
+              char *buffer = variable_expand ("");
+              buffer_offset = buffer - variable_buffer; /* bird */
+
+              o = subst_expand (buffer, d->name, "%", "$*", 1, 2, 0);
+              buffer = variable_buffer + buffer_offset; /* bird - variable_buffer may have been reallocated. */
+
+              d->name = strcache_add_len (buffer, o - buffer);
+              d->staticpattern = 0; /* Clear staticpattern so that we don't
+                                       re-expand %s below. */
+            }
+
+          /* We are going to do second expansion so initialize file variables
+             for the file. Since the stem for static pattern rules comes from
+             individual dep lines, we will temporarily set f->stem to d->stem.
+          */
+          if (!initialized)
+            {
+              initialize_file_variables (f, 0);
+              initialized = 1;
+            }
+
+          if (d->stem != 0)
+            f->stem = d->stem;
+
+          set_file_variables (f);
+
+          p = variable_expand_for_file (d->name, f);
+
+          if (d->stem != 0)
+            f->stem = file_stem;
+        }
+
+      /* Parse the prerequisites.  */
+      new = parse_prereqs (p);
+
+      /* If this dep list was from a static pattern rule, expand the %s.  We
+         use patsubst_expand to translate the prerequisites' patterns into
+         plain prerequisite names.  */
+      if (new && d->staticpattern)
+        {
+          const char *pattern = "%";
+          char *buffer = variable_expand ("");
+          const size_t buffer_offset = buffer - variable_buffer; /* bird */
+          struct dep *dp = new, *dl = 0;
+
+          while (dp != 0)
+            {
+              char *percent;
+              int nl = strlen (dp->name) + 1;
+              char *nm = alloca (nl);
+              memcpy (nm, dp->name, nl);
+              percent = find_percent (nm);
+              if (percent)
+                {
+                  char *o;
+
+                  /* We have to handle empty stems specially, because that
+                     would be equivalent to $(patsubst %,dp->name,) which
+                     will always be empty.  */
+                  if (d->stem[0] == '\0')
+                    {
+                      memmove (percent, percent+1, strlen (percent));
+                      o = variable_buffer_output (buffer, nm, strlen (nm) + 1);
+                    }
+                  else
+                    o = patsubst_expand_pat (buffer, d->stem, pattern, nm,
+                                             pattern+1, percent+1);
+                  buffer = variable_buffer + buffer_offset; /* bird - variable_buffer may have been reallocated. */
+
+
+                  /* If the name expanded to the empty string, ignore it.  */
+                  if (buffer[0] == '\0')
+                    {
+                      struct dep *df = dp;
+                      if (dp == new)
+                        dp = new = new->next;
+                      else
+                        dp = dl->next = dp->next;
+                      free_dep (df);
+                      continue;
+                    }
+
+                  /* Save the name.  */
+                  dp->name = strcache_add_len (buffer, o - buffer);
+                }
+              dl = dp;
+              dp = dp->next;
+            }
+        }
+
+      /* Enter them as files. */
+      for (d1 = new; d1 != 0; d1 = d1->next)
+        {
+          d1->file = lookup_file (d1->name);
+          if (d1->file == 0)
+            d1->file = enter_file (d1->name);
+          d1->name = 0;
+          d1->staticpattern = 0;
+          d1->need_2nd_expansion = 0;
+        }
+
+      /* Add newly parsed deps to f->deps. If this is the last dependency
+         line and this target has commands then put it in front so the
+         last dependency line (the one with commands) ends up being the
+         first. This is important because people expect $< to hold first
+         prerequisite from the rule with commands. If it is not the last
+         dependency line or the rule does not have commands then link it
+         at the end so it appears in makefile order.  */
+
+      if (new != 0)
+        {
+          if (d->next == 0 && last_dep_has_cmds)
+            {
+              struct dep **d_ptr;
+              for (d_ptr = &new; *d_ptr; d_ptr = &(*d_ptr)->next)
+                ;
+
+              *d_ptr = f->deps;
+              f->deps = new;
+            }
+          else
+            {
+              struct dep **d_ptr;
+              for (d_ptr = &f->deps; *d_ptr; d_ptr = &(*d_ptr)->next)
+                ;
+
+              *d_ptr = new;
+            }
+        }
+    }
+
+  free_dep_chain (old);
+}
+
+/* For each dependency of each file, make the `struct dep' point
+   at the appropriate `struct file' (which may have to be created).
+
+   Also mark the files depended on by .PRECIOUS, .PHONY, .SILENT,
+   and various other special targets.  */
+
+void
+snap_deps (void)
+{
+  struct file *f;
+  struct file *f2;
+  struct dep *d;
+  struct file **file_slot_0;
+  struct file **file_slot;
+  struct file **file_end;
+
+  /* Perform second expansion and enter each dependency name as a file. */
+
+  /* Expand .SUFFIXES first; it's dependencies are used for $$* calculation. */
+  for (f = lookup_file (".SUFFIXES"); f != 0; f = f->prev)
+    expand_deps (f);
+
+#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
+  /* Perform 2nd target expansion on files which requires this. This will
+     be re-inserting (delete+insert) hash table entries so we have to use
+     hash_dump(). */
+  if (second_target_expansion)
+    {
+# ifdef KMK /* turn on warnings here. */
+      int save = warn_undefined_variables_flag;
+      warn_undefined_variables_flag = 1;
+# endif
+
+      file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
+      file_end = file_slot_0 + files.ht_fill;
+      for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
+        for (f = *file_slot; f != 0; f = f->prev)
+          if (f->need_2nd_target_expansion)
+            do_2nd_target_expansion (f);
+      free (file_slot_0);
+
+# ifdef KMK
+      warn_undefined_variables_flag = save;
+# endif 
+    
+      /* Disable second target expansion now since we won't expand files
+         entered after this point. (saves CPU cycles in enter_file()). */
+      second_target_expansion = 0;
+    }
+#endif /* CONFIG_WITH_2ND_TARGET_EXPANSION */
+
+  /* For every target that's not .SUFFIXES, expand its dependencies.
+     We must use hash_dump (), because within this loop we might add new files
+     to the table, possibly causing an in-situ table expansion.  */
+  file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
+  file_end = file_slot_0 + files.ht_fill;
+  for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
+    for (f = *file_slot; f != 0; f = f->prev)
+      if (strcmp (f->name, ".SUFFIXES") != 0)
+        expand_deps (f);
+  free (file_slot_0);
+
+  /* Now manage all the special targets.  */
+
+  for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev)
+    for (d = f->deps; d != 0; d = d->next)
+      for (f2 = d->file; f2 != 0; f2 = f2->prev)
+	f2->precious = 1;
+
+  for (f = lookup_file (".LOW_RESOLUTION_TIME"); f != 0; f = f->prev)
+    for (d = f->deps; d != 0; d = d->next)
+      for (f2 = d->file; f2 != 0; f2 = f2->prev)
+	f2->low_resolution_time = 1;
+
+  for (f = lookup_file (".PHONY"); f != 0; f = f->prev)
+    for (d = f->deps; d != 0; d = d->next)
+      for (f2 = d->file; f2 != 0; f2 = f2->prev)
+	{
+	  /* Mark this file as phony nonexistent target.  */
+	  f2->phony = 1;
+          f2->is_target = 1;
+	  f2->last_mtime = NONEXISTENT_MTIME;
+	  f2->mtime_before_update = NONEXISTENT_MTIME;
+	}
+
+  for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
+    /* Mark .INTERMEDIATE deps as intermediate files.  */
+    for (d = f->deps; d != 0; d = d->next)
+      for (f2 = d->file; f2 != 0; f2 = f2->prev)
+        f2->intermediate = 1;
+    /* .INTERMEDIATE with no deps does nothing.
+       Marking all files as intermediates is useless since the goal targets
+       would be deleted after they are built.  */
+
+  for (f = lookup_file (".SECONDARY"); f != 0; f = f->prev)
+    /* Mark .SECONDARY deps as both intermediate and secondary.  */
+    if (f->deps)
+      for (d = f->deps; d != 0; d = d->next)
+        for (f2 = d->file; f2 != 0; f2 = f2->prev)
+          f2->intermediate = f2->secondary = 1;
+    /* .SECONDARY with no deps listed marks *all* files that way.  */
+    else
+      {
+        all_secondary = 1;
+        hash_map (&files, set_intermediate);
+      }
+
+  f = lookup_file (".EXPORT_ALL_VARIABLES");
+  if (f != 0 && f->is_target)
+    export_all_variables = 1;
+
+  f = lookup_file (".IGNORE");
+  if (f != 0 && f->is_target)
+    {
+      if (f->deps == 0)
+	ignore_errors_flag = 1;
+      else
+	for (d = f->deps; d != 0; d = d->next)
+	  for (f2 = d->file; f2 != 0; f2 = f2->prev)
+	    f2->command_flags |= COMMANDS_NOERROR;
+    }
+
+  f = lookup_file (".SILENT");
+  if (f != 0 && f->is_target)
+    {
+      if (f->deps == 0)
+	silent_flag = 1;
+      else
+	for (d = f->deps; d != 0; d = d->next)
+	  for (f2 = d->file; f2 != 0; f2 = f2->prev)
+	    f2->command_flags |= COMMANDS_SILENT;
+    }
+
+  f = lookup_file (".NOTPARALLEL");
+  if (f != 0 && f->is_target)
+#ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL
+    not_parallel = 1;
+#else /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+    {
+      if (f->deps == 0)
+        {
+          DB (DB_KMK, (_("not_parallel -1\n")));
+          not_parallel = -1;
+        }
+      else
+        for (d = f->deps; d != 0; d = d->next)
+          for (f2 = d->file; f2 != 0; f2 = f2->prev)
+            f2->command_flags |= COMMANDS_NOTPARALLEL;
+    }
+#endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+
+#ifndef NO_MINUS_C_MINUS_O
+  /* If .POSIX was defined, remove OUTPUT_OPTION to comply.  */
+  /* This needs more work: what if the user sets this in the makefile?
+  if (posix_pedantic)
+    define_variable (STRING_SIZE_TUPLE("OUTPUT_OPTION"), "", o_default, 1);
+  */
+#endif
+
+  /* Remember that we've done this. */
+  snapped_deps = 1;
+}
+
+
+/* Set the `command_state' member of FILE and all its `also_make's.  */
+
+void
+set_command_state (struct file *file, enum cmd_state state)
+{
+  struct dep *d;
+
+  file->command_state = state;
+
+  for (d = file->also_make; d != 0; d = d->next)
+    d->file->command_state = state;
+
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  if (file->multi_head)
+    for (file = file->multi_head; file != 0; file = file->multi_next)
+      file->command_state = state;
+#endif
+}
+
+
+/* Convert an external file timestamp to internal form.  */
+
+FILE_TIMESTAMP
+file_timestamp_cons (const char *fname, time_t s, int ns)
+{
+  int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0);
+  FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS;
+  FILE_TIMESTAMP ts = product + offset;
+
+  if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX)
+	 && product <= ts && ts <= ORDINARY_MTIME_MAX))
+    {
+      char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
+      ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;
+      file_timestamp_sprintf (buf, ts);
+      error (NILF, _("%s: Timestamp out of range; substituting %s"),
+	     fname ? fname : _("Current time"), buf);
+    }
+
+  return ts;
+}
+
+
+/* Return the current time as a file timestamp, setting *RESOLUTION to
+   its resolution.  */
+FILE_TIMESTAMP
+file_timestamp_now (int *resolution)
+{
+  int r;
+  time_t s;
+  int ns;
+
+  /* Don't bother with high-resolution clocks if file timestamps have
+     only one-second resolution.  The code below should work, but it's
+     not worth the hassle of debugging it on hosts where it fails.  */
+#if FILE_TIMESTAMP_HI_RES
+# if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
+  {
+    struct timespec timespec;
+    if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
+      {
+	r = 1;
+	s = timespec.tv_sec;
+	ns = timespec.tv_nsec;
+	goto got_time;
+      }
+  }
+# endif
+# if HAVE_GETTIMEOFDAY
+  {
+    struct timeval timeval;
+    if (gettimeofday (&timeval, 0) == 0)
+      {
+	r = 1000;
+	s = timeval.tv_sec;
+	ns = timeval.tv_usec * 1000;
+	goto got_time;
+      }
+  }
+# endif
+#endif
+
+  r = 1000000000;
+  s = time ((time_t *) 0);
+  ns = 0;
+
+#if FILE_TIMESTAMP_HI_RES
+ got_time:
+#endif
+  *resolution = r;
+  return file_timestamp_cons (0, s, ns);
+}
+
+/* Place into the buffer P a printable representation of the file
+   timestamp TS.  */
+void
+file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
+{
+  time_t t = FILE_TIMESTAMP_S (ts);
+  struct tm *tm = localtime (&t);
+
+  if (tm)
+    sprintf (p, "%04d-%02d-%02d %02d:%02d:%02d",
+	     tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+	     tm->tm_hour, tm->tm_min, tm->tm_sec);
+  else if (t < 0)
+    sprintf (p, "%ld", (long) t);
+  else
+    sprintf (p, "%lu", (unsigned long) t);
+  p += strlen (p);
+
+  /* Append nanoseconds as a fraction, but remove trailing zeros.  We don't
+     know the actual timestamp resolution, since clock_getres applies only to
+     local times, whereas this timestamp might come from a remote filesystem.
+     So removing trailing zeros is the best guess that we can do.  */
+  sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts));
+  p += strlen (p) - 1;
+  while (*p == '0')
+    p--;
+  p += *p != '.';
+
+  *p = '\0';
+}
+
+
+/* Print the data base of files.  */
+
+static void
+print_file (const void *item)
+{
+  const struct file *f = item;
+  struct dep *d;
+  struct dep *ood = 0;
+
+  putchar ('\n');
+  if (!f->is_target)
+    puts (_("# Not a target:"));
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  if (f->multi_head)
+    {
+      const struct file *f2;
+      if (f->multi_head == f)
+        {
+          int multi_maybe = -1;
+          assert (!f->multi_maybe);
+          assert (!f->double_colon);
+
+          printf ("%s", f->name);
+          for (f2 = f->multi_next; f2 != 0; f2 = f2->multi_next)
+            {
+              printf (" %s%s", f2->multi_maybe != multi_maybe
+                      ? f2->multi_maybe ? "+| " : "+ " : "",
+                      f2->name);
+              multi_maybe = f2->multi_maybe;
+            }
+          putchar (':');
+        }
+      else
+        printf ("%s:%s", f->name, f->double_colon ? ":" : "");
+    }
+  else
+#endif
+    printf ("%s:%s", f->name, f->double_colon ? ":" : "");
+
+  /* Print all normal dependencies; note any order-only deps.  */
+  for (d = f->deps; d != 0; d = d->next)
+    if (! d->ignore_mtime)
+      printf (" %s", dep_name (d));
+    else if (! ood)
+      ood = d;
+
+  /* Print order-only deps, if we have any.  */
+  if (ood)
+    {
+      printf (" | %s", dep_name (ood));
+      for (d = ood->next; d != 0; d = d->next)
+        if (d->ignore_mtime)
+          printf (" %s", dep_name (d));
+    }
+
+  putchar ('\n');
+
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  if (f->multi_head && f->multi_head != f)
+    {
+      const struct file *f2;
+      fputs (_("#  In multi target list:"), stdout);
+      for (f2 = f->multi_head; f2 != 0; f2 = f2->multi_next)
+        printf (" %s%s", f2->name, f == f2 ? "(*)" : "");
+      putchar ('\n');
+      if (f->multi_maybe)
+        puts (_("#  File is an optional multi target member."));
+    }
+#endif
+
+  if (f->precious)
+    puts (_("#  Precious file (prerequisite of .PRECIOUS)."));
+  if (f->phony)
+    puts (_("#  Phony target (prerequisite of .PHONY)."));
+  if (f->cmd_target)
+    puts (_("#  Command-line target."));
+  if (f->dontcare)
+    puts (_("#  A default, MAKEFILES, or -include/sinclude makefile."));
+  puts (f->tried_implicit
+        ? _("#  Implicit rule search has been done.")
+        : _("#  Implicit rule search has not been done."));
+  if (f->stem != 0)
+    printf (_("#  Implicit/static pattern stem: `%s'\n"), f->stem);
+  if (f->intermediate)
+    puts (_("#  File is an intermediate prerequisite."));
+  if (f->also_make != 0)
+    {
+      fputs (_("#  Also makes:"), stdout);
+      for (d = f->also_make; d != 0; d = d->next)
+	printf (" %s", dep_name (d));
+      putchar ('\n');
+    }
+  if (f->last_mtime == UNKNOWN_MTIME)
+    puts (_("#  Modification time never checked."));
+  else if (f->last_mtime == NONEXISTENT_MTIME)
+    puts (_("#  File does not exist."));
+  else if (f->last_mtime == OLD_MTIME)
+    puts (_("#  File is very old."));
+  else
+    {
+      char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
+      file_timestamp_sprintf (buf, f->last_mtime);
+      printf (_("#  Last modified %s\n"), buf);
+    }
+  puts (f->updated
+        ? _("#  File has been updated.") : _("#  File has not been updated."));
+  switch (f->command_state)
+    {
+    case cs_running:
+      puts (_("#  Commands currently running (THIS IS A BUG)."));
+      break;
+    case cs_deps_running:
+      puts (_("#  Dependencies commands running (THIS IS A BUG)."));
+      break;
+    case cs_not_started:
+    case cs_finished:
+      switch (f->update_status)
+	{
+	case -1:
+	  break;
+	case 0:
+	  puts (_("#  Successfully updated."));
+	  break;
+	case 1:
+	  assert (question_flag);
+	  puts (_("#  Needs to be updated (-q is set)."));
+	  break;
+	case 2:
+	  puts (_("#  Failed to be updated."));
+	  break;
+	default:
+	  puts (_("#  Invalid value in `update_status' member!"));
+	  fflush (stdout);
+	  fflush (stderr);
+	  abort ();
+	}
+      break;
+    default:
+      puts (_("#  Invalid value in `command_state' member!"));
+      fflush (stdout);
+      fflush (stderr);
+      abort ();
+    }
+
+  if (f->variables != 0)
+    print_file_variables (f);
+
+  if (f->cmds != 0)
+    print_commands (f->cmds);
+
+  if (f->prev)
+    print_file ((const void *) f->prev);
+}
+
+void
+print_file_data_base (void)
+{
+  puts (_("\n# Files"));
+
+  hash_map (&files, print_file);
+
+  fputs (_("\n# files hash-table stats:\n# "), stdout);
+  hash_print_stats (&files, stdout);
+}
+
+
+/* Verify the integrity of the data base of files.  */
+
+#define VERIFY_CACHED(_p,_n) \
+    do{\
+        if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \
+          printf ("%s: Field %s not cached: %s\n", _p->name, # _n, _p->_n); \
+    }while(0)
+
+static void
+verify_file (const void *item)
+{
+  const struct file *f = item;
+  const struct dep *d;
+
+  VERIFY_CACHED (f, name);
+  VERIFY_CACHED (f, hname);
+  VERIFY_CACHED (f, vpath);
+  VERIFY_CACHED (f, stem);
+
+  /* Check the deps.  */
+  for (d = f->deps; d != 0; d = d->next)
+    {
+      VERIFY_CACHED (d, name);
+      VERIFY_CACHED (d, stem);
+    }
+}
+
+void
+verify_file_data_base (void)
+{
+  hash_map (&files, verify_file);
+}
+
+#define EXPANSION_INCREMENT(_l)  ((((_l) / 500) + 1) * 500)
+
+char *
+build_target_list (char *value)
+{
+  static unsigned long last_targ_count = 0;
+
+  if (files.ht_fill != last_targ_count)
+    {
+      unsigned long max = EXPANSION_INCREMENT (strlen (value));
+      unsigned long len;
+      char *p;
+      struct file **fp = (struct file **) files.ht_vec;
+      struct file **end = &fp[files.ht_size];
+
+      /* Make sure we have at least MAX bytes in the allocated buffer.  */
+      value = xrealloc (value, max);
+
+      p = value;
+      len = 0;
+      for (; fp < end; ++fp)
+        if (!HASH_VACANT (*fp) && (*fp)->is_target)
+          {
+            struct file *f = *fp;
+            int l = strlen (f->name);
+
+            len += l + 1;
+            if (len > max)
+              {
+                unsigned long off = p - value;
+
+                max += EXPANSION_INCREMENT (l + 1);
+                value = xrealloc (value, max);
+                p = &value[off];
+              }
+
+            memcpy (p, f->name, l);
+            p += l;
+            *(p++) = ' ';
+          }
+      *(p-1) = '\0';
+
+      last_targ_count = files.ht_fill;
+    }
+
+  return value;
+}
+
+void
+init_hash_files (void)
+{
+#ifdef KMK
+  hash_init (&files, 8192, file_hash_1, file_hash_2, file_hash_cmp);
+#else
+  hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp);
+#endif
+}
+
+/* EOF */
Index: /tags/kBuild-0.1.4/src/kmk/filedef.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/filedef.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/filedef.h	(revision 1780)
@@ -0,0 +1,220 @@
+/* Definition of target file data structures for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+
+/* Structure that represents the info on one file
+   that the makefile says how to make.
+   All of these are chained together through `next'.  */
+
+#include "hash.h"
+
+struct file
+  {
+    const char *name;
+    const char *hname;          /* Hashed filename */
+    const char *vpath;          /* VPATH/vpath pathname */
+    struct dep *deps;		/* all dependencies, including duplicates */
+    struct commands *cmds;	/* Commands to execute for this target.  */
+    int command_flags;		/* Flags OR'd in for cmds; see commands.h.  */
+    const char *stem;		/* Implicit stem, if an implicit
+                                   rule has been used */
+    struct dep *also_make;	/* Targets that are made by making this.  */
+    FILE_TIMESTAMP last_mtime;	/* File's modtime, if already known.  */
+    FILE_TIMESTAMP mtime_before_update;	/* File's modtime before any updating
+                                           has been performed.  */
+    struct file *prev;		/* Previous entry for same file name;
+				   used when there are multiple double-colon
+				   entries for the same file.  */
+    struct file *last;          /* Last entry for the same file name.  */
+
+    /* File that this file was renamed to.  After any time that a
+       file could be renamed, call `check_renamed' (below).  */
+    struct file *renamed;
+
+    /* List of variable sets used for this file.  */
+    struct variable_set_list *variables;
+
+    /* Pattern-specific variable reference for this target, or null if there
+       isn't one.  Also see the pat_searched flag, below.  */
+    struct variable_set_list *pat_variables;
+
+    /* Immediate dependent that caused this target to be remade,
+       or nil if there isn't one.  */
+    struct file *parent;
+
+    /* For a double-colon entry, this is the first double-colon entry for
+       the same file.  Otherwise this is null.  */
+    struct file *double_colon;
+
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+    /* For a target of an explicit multi target rule, this points to the
+       primary target.  Otherwise this is null. */
+    struct file *multi_head;
+    /* Pointer to next target of an explicit multi target rule. */
+    struct file *multi_next;
+#endif
+
+    short int update_status;	/* Status of the last attempt to update,
+				   or -1 if none has been made.  */
+
+    enum cmd_state		/* State of the commands.  */
+      {		/* Note: It is important that cs_not_started be zero.  */
+	cs_not_started,		/* Not yet started.  */
+	cs_deps_running,	/* Dep commands running.  */
+	cs_running,		/* Commands running.  */
+	cs_finished		/* Commands finished.  */
+      } command_state ENUM_BITFIELD (2);
+
+    unsigned int precious:1;	/* Non-0 means don't delete file on quit */
+    unsigned int low_resolution_time:1;	/* Nonzero if this file's time stamp
+					   has only one-second resolution.  */
+    unsigned int tried_implicit:1; /* Nonzero if have searched
+				      for implicit rule for making
+				      this file; don't search again.  */
+    unsigned int updating:1;	/* Nonzero while updating deps of this file */
+    unsigned int updated:1;	/* Nonzero if this file has been remade.  */
+    unsigned int is_target:1;	/* Nonzero if file is described as target.  */
+    unsigned int cmd_target:1;	/* Nonzero if file was given on cmd line.  */
+    unsigned int phony:1;	/* Nonzero if this is a phony file
+				   i.e., a prerequisite of .PHONY.  */
+    unsigned int intermediate:1;/* Nonzero if this is an intermediate file.  */
+    unsigned int secondary:1;   /* Nonzero means remove_intermediates should
+                                   not delete it.  */
+    unsigned int dontcare:1;	/* Nonzero if no complaint is to be made if
+				   this target cannot be remade.  */
+    unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name.  */
+    unsigned int pat_searched:1;/* Nonzero if we already searched for
+                                   pattern-specific variables.  */
+    unsigned int considered:1;  /* equal to 'considered' if file has been
+                                   considered on current scan of goal chain */
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+    unsigned int multi_maybe:1; /* Nonzero if this file isn't always updated
+                                   by the explicit multi target rule. */
+#endif
+#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION	  
+    unsigned int need_2nd_target_expansion:1; /* Nonzero if this file needs 
+                                  second expansion of its name. Whether it
+                                  can receive this is decided at parse time,
+                                  and the expanding done in snap_deps. */
+#endif
+
+  };
+
+
+extern struct file *default_goal_file, *suffix_file, *default_file;
+extern char **default_goal_name;
+
+
+struct file *lookup_file (const char *name);
+struct file *enter_file (const char *name);
+struct dep *parse_prereqs (char *prereqs);
+void remove_intermediates (int sig);
+void snap_deps (void);
+void rename_file (struct file *file, const char *name);
+void rehash_file (struct file *file, const char *name);
+void set_command_state (struct file *file, enum cmd_state state);
+void notice_finished_file (struct file *file);
+void init_hash_files (void);
+char *build_target_list (char *old_list);
+
+#if FILE_TIMESTAMP_HI_RES
+# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \
+    file_timestamp_cons (fname, (st).st_mtime, (st).st_mtim.ST_MTIM_NSEC)
+#else
+# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \
+    file_timestamp_cons (fname, (st).st_mtime, 0)
+#endif
+
+/* If FILE_TIMESTAMP is 64 bits (or more), use nanosecond resolution.
+   (Multiply by 2**30 instead of by 10**9 to save time at the cost of
+   slightly decreasing the number of available timestamps.)  With
+   64-bit FILE_TIMESTAMP, this stops working on 2514-05-30 01:53:04
+   UTC, but by then uintmax_t should be larger than 64 bits.  */
+#define FILE_TIMESTAMPS_PER_S (FILE_TIMESTAMP_HI_RES ? 1000000000 : 1)
+#define FILE_TIMESTAMP_LO_BITS (FILE_TIMESTAMP_HI_RES ? 30 : 0)
+
+#define FILE_TIMESTAMP_S(ts) (((ts) - ORDINARY_MTIME_MIN) \
+			      >> FILE_TIMESTAMP_LO_BITS)
+#define FILE_TIMESTAMP_NS(ts) ((int) (((ts) - ORDINARY_MTIME_MIN) \
+				      & ((1 << FILE_TIMESTAMP_LO_BITS) - 1)))
+
+/* Upper bound on length of string "YYYY-MM-DD HH:MM:SS.NNNNNNNNN"
+   representing a file timestamp.  The upper bound is not necessarily 19,
+   since the year might be less than -999 or greater than 9999.
+
+   Subtract one for the sign bit if in case file timestamps can be negative;
+   subtract FLOOR_LOG2_SECONDS_PER_YEAR to yield an upper bound on how many
+   file timestamp bits might affect the year;
+   302 / 1000 is log10 (2) rounded up;
+   add one for integer division truncation;
+   add one more for a minus sign if file timestamps can be negative;
+   add 4 to allow for any 4-digit epoch year (e.g. 1970);
+   add 25 to allow for "-MM-DD HH:MM:SS.NNNNNNNNN".  */
+#define FLOOR_LOG2_SECONDS_PER_YEAR 24
+#define FILE_TIMESTAMP_PRINT_LEN_BOUND \
+  (((sizeof (FILE_TIMESTAMP) * CHAR_BIT - 1 - FLOOR_LOG2_SECONDS_PER_YEAR) \
+    * 302 / 1000) \
+   + 1 + 1 + 4 + 25)
+
+FILE_TIMESTAMP file_timestamp_cons (char const *, time_t, int);
+FILE_TIMESTAMP file_timestamp_now (int *);
+void file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts);
+
+/* Return the mtime of file F (a struct file *), caching it.
+   The value is NONEXISTENT_MTIME if the file does not exist.  */
+#define file_mtime(f) file_mtime_1 ((f), 1)
+/* Return the mtime of file F (a struct file *), caching it.
+   Don't search using vpath for the file--if it doesn't actually exist,
+   we don't find it.
+   The value is NONEXISTENT_MTIME if the file does not exist.  */
+#define file_mtime_no_search(f) file_mtime_1 ((f), 0)
+FILE_TIMESTAMP f_mtime (struct file *file, int search);
+#define file_mtime_1(f, v) \
+  ((f)->last_mtime == UNKNOWN_MTIME ? f_mtime ((f), v) : (f)->last_mtime)
+
+/* Special timestamp values.  */
+
+/* The file's timestamp is not yet known.  */
+#define UNKNOWN_MTIME 0
+
+/* The file does not exist.  */
+#define NONEXISTENT_MTIME 1
+
+/* The file does not exist, and we assume that it is older than any
+   actual file.  */
+#define OLD_MTIME 2
+
+/* The smallest and largest ordinary timestamps.  */
+#define ORDINARY_MTIME_MIN (OLD_MTIME + 1)
+#define ORDINARY_MTIME_MAX ((FILE_TIMESTAMP_S (NEW_MTIME) \
+			     << FILE_TIMESTAMP_LO_BITS) \
+			    + ORDINARY_MTIME_MIN + (FILE_TIMESTAMPS_PER_S - 1)) /* bird: MSC overflow fix */
+
+/* Modtime value to use for `infinitely new'.  We used to get the current time
+   from the system and use that whenever we wanted `new'.  But that causes
+   trouble when the machine running make and the machine holding a file have
+   different ideas about what time it is; and can also lose for `force'
+   targets, which need to be considered newer than anything that depends on
+   them, even if said dependents' modtimes are in the future.  */
+#define NEW_MTIME INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP)
+
+#define check_renamed(file) \
+  while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here.  */
+
+/* Have we snapped deps yet?  */
+extern int snapped_deps;
Index: /tags/kBuild-0.1.4/src/kmk/function.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/function.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/function.c	(revision 1780)
@@ -0,0 +1,4364 @@
+/* Builtin function expansion for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "filedef.h"
+#include "variable.h"
+#include "dep.h"
+#include "job.h"
+#include "commands.h"
+#include "debug.h"
+
+#ifdef _AMIGA
+#include "amiga.h"
+#endif
+
+#ifdef WINDOWS32 /* bird */
+# include "pathstuff.h"
+#endif
+
+#ifdef KMK_HELPERS
+# include "kbuild.h"
+#endif
+#ifdef CONFIG_WITH_XARGS /* bird */
+# ifdef HAVE_LIMITS_H
+#  include <limits.h>
+# endif
+#endif
+#include <assert.h> /* bird */
+
+#if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_FILE_SIZE) /* bird */
+# include <ctype.h>
+# ifdef _MSC_VER
+typedef __int64 math_int;
+# else
+#  include <stdint.h>
+typedef int64_t math_int;
+# endif
+static char *math_int_to_variable_buffer (char *, math_int);
+#endif
+
+#ifdef CONFIG_WITH_NANOTS /* bird */
+# ifdef WINDOWS32
+#  include <Windows.h>
+# endif
+#endif
+
+#ifdef __OS2__
+# define CONFIG_WITH_OS2_LIBPATH 1
+#endif
+#ifdef CONFIG_WITH_OS2_LIBPATH
+# define INCL_BASE
+# define INCL_ERRROS
+# include <os2.h>
+
+# define QHINF_EXEINFO       1 /* NE exeinfo. */
+# define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
+# define QHINF_READFILE      3 /* Reads from the executable file. */
+# define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
+# define QHINF_LIBPATH       5 /* Gets the entire libpath. */
+# define QHINF_FIXENTRY      6 /* NE only */
+# define QHINF_STE           7 /* NE only */
+# define QHINF_MAPSEL        8 /* NE only */
+  extern APIRET APIENTRY DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
+#endif /* CONFIG_WITH_OS2_LIBPATH */
+
+
+struct function_table_entry
+  {
+    const char *name;
+    unsigned char len;
+    unsigned char minimum_args;
+    unsigned char maximum_args;
+    char expand_args;
+    char *(*func_ptr) (char *output, char **argv, const char *fname);
+  };
+
+static unsigned long
+function_table_entry_hash_1 (const void *keyv)
+{
+  const struct function_table_entry *key = keyv;
+  return_STRING_N_HASH_1 (key->name, key->len);
+}
+
+static unsigned long
+function_table_entry_hash_2 (const void *keyv)
+{
+  const struct function_table_entry *key = keyv;
+  return_STRING_N_HASH_2 (key->name, key->len);
+}
+
+static int
+function_table_entry_hash_cmp (const void *xv, const void *yv)
+{
+  const struct function_table_entry *x = xv;
+  const struct function_table_entry *y = yv;
+  int result = x->len - y->len;
+  if (result)
+    return result;
+  return_STRING_N_COMPARE (x->name, y->name, x->len);
+}
+
+static struct hash_table function_table;
+
+#ifdef CONFIG_WITH_MAKE_STATS
+unsigned long make_stats_allocations = 0;
+unsigned long make_stats_allocated = 0;
+unsigned long make_stats_allocated_sum = 0;
+unsigned long make_stats_ht_lookups = 0;
+unsigned long make_stats_ht_collisions = 0;
+#endif
+
+
+
+/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
+   each occurrence of SUBST with REPLACE. TEXT is null-terminated.  SLEN is
+   the length of SUBST and RLEN is the length of REPLACE.  If BY_WORD is
+   nonzero, substitutions are done only on matches which are complete
+   whitespace-delimited words.  */
+
+char *
+subst_expand (char *o, const char *text, const char *subst, const char *replace,
+              unsigned int slen, unsigned int rlen, int by_word)
+{
+  const char *t = text;
+  const char *p;
+
+  if (slen == 0 && !by_word)
+    {
+      /* The first occurrence of "" in any string is its end.  */
+      o = variable_buffer_output (o, t, strlen (t));
+      if (rlen > 0)
+	o = variable_buffer_output (o, replace, rlen);
+      return o;
+    }
+
+  do
+    {
+      if (by_word && slen == 0)
+	/* When matching by words, the empty string should match
+	   the end of each word, rather than the end of the whole text.  */
+	p = end_of_token (next_token (t));
+      else
+	{
+	  p = strstr (t, subst);
+	  if (p == 0)
+	    {
+	      /* No more matches.  Output everything left on the end.  */
+	      o = variable_buffer_output (o, t, strlen (t));
+	      return o;
+	    }
+	}
+
+      /* Output everything before this occurrence of the string to replace.  */
+      if (p > t)
+	o = variable_buffer_output (o, t, p - t);
+
+      /* If we're substituting only by fully matched words,
+	 or only at the ends of words, check that this case qualifies.  */
+      if (by_word
+          && ((p > text && !isblank ((unsigned char)p[-1]))
+              || (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
+	/* Struck out.  Output the rest of the string that is
+	   no longer to be replaced.  */
+	o = variable_buffer_output (o, subst, slen);
+      else if (rlen > 0)
+	/* Output the replacement string.  */
+	o = variable_buffer_output (o, replace, rlen);
+
+      /* Advance T past the string to be replaced.  */
+      t = p + slen;
+    } while (*t != '\0');
+
+  return o;
+}
+
+
+
+/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
+   and replacing strings matching PATTERN with REPLACE.
+   If PATTERN_PERCENT is not nil, PATTERN has already been
+   run through find_percent, and PATTERN_PERCENT is the result.
+   If REPLACE_PERCENT is not nil, REPLACE has already been
+   run through find_percent, and REPLACE_PERCENT is the result.
+   Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
+   character _AFTER_ the %, not to the % itself.
+*/
+
+char *
+patsubst_expand_pat (char *o, const char *text,
+                     const char *pattern, const char *replace,
+                     const char *pattern_percent, const char *replace_percent)
+{
+  unsigned int pattern_prepercent_len, pattern_postpercent_len;
+  unsigned int replace_prepercent_len, replace_postpercent_len;
+  const char *t;
+  unsigned int len;
+  int doneany = 0;
+
+  /* Record the length of REPLACE before and after the % so we don't have to
+     compute these lengths more than once.  */
+  if (replace_percent)
+    {
+      replace_prepercent_len = replace_percent - replace - 1;
+      replace_postpercent_len = strlen (replace_percent);
+    }
+  else
+    {
+      replace_prepercent_len = strlen (replace);
+      replace_postpercent_len = 0;
+    }
+
+  if (!pattern_percent)
+    /* With no % in the pattern, this is just a simple substitution.  */
+    return subst_expand (o, text, pattern, replace,
+			 strlen (pattern), strlen (replace), 1);
+
+  /* Record the length of PATTERN before and after the %
+     so we don't have to compute it more than once.  */
+  pattern_prepercent_len = pattern_percent - pattern - 1;
+  pattern_postpercent_len = strlen (pattern_percent);
+
+  while ((t = find_next_token (&text, &len)) != 0)
+    {
+      int fail = 0;
+
+      /* Is it big enough to match?  */
+      if (len < pattern_prepercent_len + pattern_postpercent_len)
+	fail = 1;
+
+      /* Does the prefix match? */
+      if (!fail && pattern_prepercent_len > 0
+	  && (*t != *pattern
+	      || t[pattern_prepercent_len - 1] != pattern_percent[-2]
+	      || !strneq (t + 1, pattern + 1, pattern_prepercent_len - 1)))
+	fail = 1;
+
+      /* Does the suffix match? */
+      if (!fail && pattern_postpercent_len > 0
+	  && (t[len - 1] != pattern_percent[pattern_postpercent_len - 1]
+	      || t[len - pattern_postpercent_len] != *pattern_percent
+	      || !strneq (&t[len - pattern_postpercent_len],
+			  pattern_percent, pattern_postpercent_len - 1)))
+	fail = 1;
+
+      if (fail)
+	/* It didn't match.  Output the string.  */
+	o = variable_buffer_output (o, t, len);
+      else
+	{
+	  /* It matched.  Output the replacement.  */
+
+	  /* Output the part of the replacement before the %.  */
+	  o = variable_buffer_output (o, replace, replace_prepercent_len);
+
+	  if (replace_percent != 0)
+	    {
+	      /* Output the part of the matched string that
+		 matched the % in the pattern.  */
+	      o = variable_buffer_output (o, t + pattern_prepercent_len,
+					  len - (pattern_prepercent_len
+						 + pattern_postpercent_len));
+	      /* Output the part of the replacement after the %.  */
+	      o = variable_buffer_output (o, replace_percent,
+					  replace_postpercent_len);
+	    }
+	}
+
+      /* Output a space, but not if the replacement is "".  */
+      if (fail || replace_prepercent_len > 0
+	  || (replace_percent != 0 && len + replace_postpercent_len > 0))
+	{
+	  o = variable_buffer_output (o, " ", 1);
+	  doneany = 1;
+	}
+    }
+  if (doneany)
+    /* Kill the last space.  */
+    --o;
+
+  return o;
+}
+
+/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
+   and replacing strings matching PATTERN with REPLACE.
+   If PATTERN_PERCENT is not nil, PATTERN has already been
+   run through find_percent, and PATTERN_PERCENT is the result.
+   If REPLACE_PERCENT is not nil, REPLACE has already been
+   run through find_percent, and REPLACE_PERCENT is the result.
+   Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the
+   character _AFTER_ the %, not to the % itself.
+*/
+
+char *
+patsubst_expand (char *o, const char *text, char *pattern, char *replace)
+{
+  const char *pattern_percent = find_percent (pattern);
+  const char *replace_percent = find_percent (replace);
+
+  /* If there's a percent in the pattern or replacement skip it.  */
+  if (replace_percent)
+    ++replace_percent;
+  if (pattern_percent)
+    ++pattern_percent;
+
+  return patsubst_expand_pat (o, text, pattern, replace,
+                              pattern_percent, replace_percent);
+}
+
+
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+/* The maximum length of a function, once reached there is
+   it can't be function and we can skip the hash lookup drop out. */
+
+# ifdef KMK
+#  define MAX_FUNCTION_LENGTH 12
+# else
+#  define MAX_FUNCTION_LENGTH 10
+# endif
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+
+/* Look up a function by name.  */
+
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+__inline
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+static const struct function_table_entry *
+lookup_function (const char *s)
+{
+  const char *e = s;
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+  int left = MAX_FUNCTION_LENGTH;
+  int ch;
+  while (((ch = *e) >= 'a' && ch <='z') || ch == '-')
+    {
+      if (!left--)
+        return 0;
+      e++;
+    }
+#else
+  while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-'))
+    e++;
+#endif
+  if (*e == '\0' || isblank ((unsigned char) *e))
+    {
+      struct function_table_entry function_table_entry_key;
+      function_table_entry_key.name = s;
+      function_table_entry_key.len = e - s;
+
+      return hash_find_item (&function_table, &function_table_entry_key);
+    }
+  return 0;
+}
+
+
+
+/* Return 1 if PATTERN matches STR, 0 if not.  */
+
+int
+pattern_matches (const char *pattern, const char *percent, const char *str)
+{
+  unsigned int sfxlen, strlength;
+
+  if (percent == 0)
+    {
+      unsigned int len = strlen (pattern) + 1;
+      char *new_chars = alloca (len);
+      memcpy (new_chars, pattern, len);
+      percent = find_percent (new_chars);
+      if (percent == 0)
+	return streq (new_chars, str);
+      pattern = new_chars;
+    }
+
+  sfxlen = strlen (percent + 1);
+  strlength = strlen (str);
+
+  if (strlength < (percent - pattern) + sfxlen
+      || !strneq (pattern, str, percent - pattern))
+    return 0;
+
+  return !strcmp (percent + 1, str + (strlength - sfxlen));
+}
+
+
+
+/* Find the next comma or ENDPAREN (counting nested STARTPAREN and
+   ENDPARENtheses), starting at PTR before END.  Return a pointer to
+   next character.
+
+   If no next argument is found, return NULL.
+*/
+
+static char *
+find_next_argument (char startparen, char endparen,
+                    const char *ptr, const char *end)
+{
+  int count = 0;
+
+  for (; ptr < end; ++ptr)
+    if (*ptr == startparen)
+      ++count;
+
+    else if (*ptr == endparen)
+      {
+	--count;
+	if (count < 0)
+	  return NULL;
+      }
+
+    else if (*ptr == ',' && !count)
+      return (char *)ptr;
+
+  /* We didn't find anything.  */
+  return NULL;
+}
+
+
+
+/* Glob-expand LINE.  The returned pointer is
+   only good until the next call to string_glob.  */
+
+static char *
+string_glob (char *line)
+{
+  static char *result = 0;
+  static unsigned int length;
+  struct nameseq *chain;
+  unsigned int idx;
+
+  chain = multi_glob (parse_file_seq
+		      (&line, '\0', sizeof (struct nameseq),
+		       /* We do not want parse_file_seq to strip `./'s.
+			  That would break examples like:
+			  $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)).  */
+		       0),
+		      sizeof (struct nameseq));
+
+  if (result == 0)
+    {
+      length = 100;
+      result = xmalloc (100);
+    }
+
+  idx = 0;
+  while (chain != 0)
+    {
+      const char *name = chain->name;
+      unsigned int len = strlen (name);
+
+      struct nameseq *next = chain->next;
+      free (chain);
+      chain = next;
+
+      /* multi_glob will pass names without globbing metacharacters
+	 through as is, but we want only files that actually exist.  */
+      if (file_exists_p (name))
+	{
+	  if (idx + len + 1 > length)
+	    {
+	      length += (len + 1) * 2;
+	      result = xrealloc (result, length);
+	    }
+	  memcpy (&result[idx], name, len);
+	  idx += len;
+	  result[idx++] = ' ';
+	}
+    }
+
+  /* Kill the last space and terminate the string.  */
+  if (idx == 0)
+    result[0] = '\0';
+  else
+    result[idx - 1] = '\0';
+
+  return result;
+}
+
+
+/*
+  Builtin functions
+ */
+
+static char *
+func_patsubst (char *o, char **argv, const char *funcname UNUSED)
+{
+  o = patsubst_expand (o, argv[2], argv[0], argv[1]);
+  return o;
+}
+
+
+static char *
+func_join (char *o, char **argv, const char *funcname UNUSED)
+{
+  int doneany = 0;
+
+  /* Write each word of the first argument directly followed
+     by the corresponding word of the second argument.
+     If the two arguments have a different number of words,
+     the excess words are just output separated by blanks.  */
+  const char *tp;
+  const char *pp;
+  const char *list1_iterator = argv[0];
+  const char *list2_iterator = argv[1];
+  do
+    {
+      unsigned int len1, len2;
+
+      tp = find_next_token (&list1_iterator, &len1);
+      if (tp != 0)
+	o = variable_buffer_output (o, tp, len1);
+
+      pp = find_next_token (&list2_iterator, &len2);
+      if (pp != 0)
+	o = variable_buffer_output (o, pp, len2);
+
+      if (tp != 0 || pp != 0)
+	{
+	  o = variable_buffer_output (o, " ", 1);
+	  doneany = 1;
+	}
+    }
+  while (tp != 0 || pp != 0);
+  if (doneany)
+    /* Kill the last blank.  */
+    --o;
+
+  return o;
+}
+
+
+static char *
+func_origin (char *o, char **argv, const char *funcname UNUSED)
+{
+  /* Expand the argument.  */
+  struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
+  if (v == 0)
+    o = variable_buffer_output (o, "undefined", 9);
+  else
+    switch (v->origin)
+      {
+      default:
+      case o_invalid:
+	abort ();
+	break;
+      case o_default:
+	o = variable_buffer_output (o, "default", 7);
+	break;
+      case o_env:
+	o = variable_buffer_output (o, "environment", 11);
+	break;
+      case o_file:
+	o = variable_buffer_output (o, "file", 4);
+	break;
+      case o_env_override:
+	o = variable_buffer_output (o, "environment override", 20);
+	break;
+      case o_command:
+	o = variable_buffer_output (o, "command line", 12);
+	break;
+      case o_override:
+	o = variable_buffer_output (o, "override", 8);
+	break;
+      case o_automatic:
+	o = variable_buffer_output (o, "automatic", 9);
+	break;
+#ifdef CONFIG_WITH_LOCAL_VARIABLES
+      case o_local:
+        o = variable_buffer_output (o, "local", 5);
+        break;
+#endif
+      }
+
+  return o;
+}
+
+static char *
+func_flavor (char *o, char **argv, const char *funcname UNUSED)
+{
+  struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
+
+  if (v == 0)
+    o = variable_buffer_output (o, "undefined", 9);
+  else
+    if (v->recursive)
+      o = variable_buffer_output (o, "recursive", 9);
+    else
+      o = variable_buffer_output (o, "simple", 6);
+
+  return o;
+}
+
+#ifdef VMS
+# define IS_PATHSEP(c) ((c) == ']')
+#else
+# ifdef HAVE_DOS_PATHS
+#  define IS_PATHSEP(c) ((c) == '/' || (c) == '\\')
+# else
+#  define IS_PATHSEP(c) ((c) == '/')
+# endif
+#endif
+
+
+static char *
+func_notdir_suffix (char *o, char **argv, const char *funcname)
+{
+  /* Expand the argument.  */
+  const char *list_iterator = argv[0];
+  const char *p2;
+  int doneany =0;
+  unsigned int len=0;
+
+  int is_suffix = streq (funcname, "suffix");
+  int is_notdir = !is_suffix;
+  while ((p2 = find_next_token (&list_iterator, &len)) != 0)
+    {
+      const char *p = p2 + len;
+
+
+      while (p >= p2 && (!is_suffix || *p != '.'))
+	{
+	  if (IS_PATHSEP (*p))
+	    break;
+	  --p;
+	}
+
+      if (p >= p2)
+	{
+	  if (is_notdir)
+	    ++p;
+	  else if (*p != '.')
+	    continue;
+	  o = variable_buffer_output (o, p, len - (p - p2));
+	}
+#ifdef HAVE_DOS_PATHS
+      /* Handle the case of "d:foo/bar".  */
+      else if (streq (funcname, "notdir") && p2[0] && p2[1] == ':')
+	{
+	  p = p2 + 2;
+	  o = variable_buffer_output (o, p, len - (p - p2));
+	}
+#endif
+      else if (is_notdir)
+	o = variable_buffer_output (o, p2, len);
+
+      if (is_notdir || p >= p2)
+	{
+	  o = variable_buffer_output (o, " ", 1);
+	  doneany = 1;
+	}
+    }
+
+  if (doneany)
+    /* Kill last space.  */
+    --o;
+
+  return o;
+}
+
+
+static char *
+func_basename_dir (char *o, char **argv, const char *funcname)
+{
+  /* Expand the argument.  */
+  const char *p3 = argv[0];
+  const char *p2;
+  int doneany=0;
+  unsigned int len=0;
+
+  int is_basename= streq (funcname, "basename");
+  int is_dir= !is_basename;
+
+  while ((p2 = find_next_token (&p3, &len)) != 0)
+    {
+      const char *p = p2 + len;
+      while (p >= p2 && (!is_basename  || *p != '.'))
+        {
+          if (IS_PATHSEP (*p))
+            break;
+          --p;
+        }
+
+      if (p >= p2 && (is_dir))
+        o = variable_buffer_output (o, p2, ++p - p2);
+      else if (p >= p2 && (*p == '.'))
+        o = variable_buffer_output (o, p2, p - p2);
+#ifdef HAVE_DOS_PATHS
+      /* Handle the "d:foobar" case */
+      else if (p2[0] && p2[1] == ':' && is_dir)
+        o = variable_buffer_output (o, p2, 2);
+#endif
+      else if (is_dir)
+#ifdef VMS
+        o = variable_buffer_output (o, "[]", 2);
+#else
+#ifndef _AMIGA
+      o = variable_buffer_output (o, "./", 2);
+#else
+      ; /* Just a nop...  */
+#endif /* AMIGA */
+#endif /* !VMS */
+      else
+        /* The entire name is the basename.  */
+        o = variable_buffer_output (o, p2, len);
+
+      o = variable_buffer_output (o, " ", 1);
+      doneany = 1;
+    }
+
+  if (doneany)
+    /* Kill last space.  */
+    --o;
+
+  return o;
+}
+
+static char *
+func_addsuffix_addprefix (char *o, char **argv, const char *funcname)
+{
+  int fixlen = strlen (argv[0]);
+  const char *list_iterator = argv[1];
+  int is_addprefix = streq (funcname, "addprefix");
+  int is_addsuffix = !is_addprefix;
+
+  int doneany = 0;
+  const char *p;
+  unsigned int len;
+
+  while ((p = find_next_token (&list_iterator, &len)) != 0)
+    {
+      if (is_addprefix)
+	o = variable_buffer_output (o, argv[0], fixlen);
+      o = variable_buffer_output (o, p, len);
+      if (is_addsuffix)
+	o = variable_buffer_output (o, argv[0], fixlen);
+      o = variable_buffer_output (o, " ", 1);
+      doneany = 1;
+    }
+
+  if (doneany)
+    /* Kill last space.  */
+    --o;
+
+  return o;
+}
+
+static char *
+func_subst (char *o, char **argv, const char *funcname UNUSED)
+{
+  o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),
+		    strlen (argv[1]), 0);
+
+  return o;
+}
+
+
+static char *
+func_firstword (char *o, char **argv, const char *funcname UNUSED)
+{
+  unsigned int i;
+  const char *words = argv[0];    /* Use a temp variable for find_next_token */
+  const char *p = find_next_token (&words, &i);
+
+  if (p != 0)
+    o = variable_buffer_output (o, p, i);
+
+  return o;
+}
+
+static char *
+func_lastword (char *o, char **argv, const char *funcname UNUSED)
+{
+  unsigned int i;
+  const char *words = argv[0];    /* Use a temp variable for find_next_token */
+  const char *p = NULL;
+  const char *t;
+
+  while ((t = find_next_token (&words, &i)))
+    p = t;
+
+  if (p != 0)
+    o = variable_buffer_output (o, p, i);
+
+  return o;
+}
+
+static char *
+func_words (char *o, char **argv, const char *funcname UNUSED)
+{
+  int i = 0;
+  const char *word_iterator = argv[0];
+  char buf[20];
+
+  while (find_next_token (&word_iterator, (unsigned int *) 0) != 0)
+    ++i;
+
+  sprintf (buf, "%d", i);
+  o = variable_buffer_output (o, buf, strlen (buf));
+
+  return o;
+}
+
+/* Set begpp to point to the first non-whitespace character of the string,
+ * and endpp to point to the last non-whitespace character of the string.
+ * If the string is empty or contains nothing but whitespace, endpp will be
+ * begpp-1.
+ */
+char *
+strip_whitespace (const char **begpp, const char **endpp)
+{
+  while (*begpp <= *endpp && isspace ((unsigned char)**begpp))
+    (*begpp) ++;
+  while (*endpp >= *begpp && isspace ((unsigned char)**endpp))
+    (*endpp) --;
+  return (char *)*begpp;
+}
+
+static void
+check_numeric (const char *s, const char *msg)
+{
+  const char *end = s + strlen (s) - 1;
+  const char *beg = s;
+  strip_whitespace (&s, &end);
+
+  for (; s <= end; ++s)
+    if (!ISDIGIT (*s))  /* ISDIGIT only evals its arg once: see make.h.  */
+      break;
+
+  if (s <= end || end - beg < 0)
+    fatal (*expanding_var, "%s: '%s'", msg, beg);
+}
+
+
+
+static char *
+func_word (char *o, char **argv, const char *funcname UNUSED)
+{
+  const char *end_p;
+  const char *p;
+  int i;
+
+  /* Check the first argument.  */
+  check_numeric (argv[0], _("non-numeric first argument to `word' function"));
+  i = atoi (argv[0]);
+
+  if (i == 0)
+    fatal (*expanding_var,
+           _("first argument to `word' function must be greater than 0"));
+
+  end_p = argv[1];
+  while ((p = find_next_token (&end_p, 0)) != 0)
+    if (--i == 0)
+      break;
+
+  if (i == 0)
+    o = variable_buffer_output (o, p, end_p - p);
+
+  return o;
+}
+
+static char *
+func_wordlist (char *o, char **argv, const char *funcname UNUSED)
+{
+  int start, count;
+
+  /* Check the arguments.  */
+  check_numeric (argv[0],
+		 _("non-numeric first argument to `wordlist' function"));
+  check_numeric (argv[1],
+		 _("non-numeric second argument to `wordlist' function"));
+
+  start = atoi (argv[0]);
+  if (start < 1)
+    fatal (*expanding_var,
+           "invalid first argument to `wordlist' function: `%d'", start);
+
+  count = atoi (argv[1]) - start + 1;
+
+  if (count > 0)
+    {
+      const char *p;
+      const char *end_p = argv[2];
+
+      /* Find the beginning of the "start"th word.  */
+      while (((p = find_next_token (&end_p, 0)) != 0) && --start)
+        ;
+
+      if (p)
+        {
+          /* Find the end of the "count"th word from start.  */
+          while (--count && (find_next_token (&end_p, 0) != 0))
+            ;
+
+          /* Return the stuff in the middle.  */
+          o = variable_buffer_output (o, p, end_p - p);
+        }
+    }
+
+  return o;
+}
+
+static char *
+func_findstring (char *o, char **argv, const char *funcname UNUSED)
+{
+  /* Find the first occurrence of the first string in the second.  */
+  if (strstr (argv[1], argv[0]) != 0)
+    o = variable_buffer_output (o, argv[0], strlen (argv[0]));
+
+  return o;
+}
+
+static char *
+func_foreach (char *o, char **argv, const char *funcname UNUSED)
+{
+  /* expand only the first two.  */
+  char *varname = expand_argument (argv[0], NULL);
+  char *list = expand_argument (argv[1], NULL);
+  const char *body = argv[2];
+
+  int doneany = 0;
+  const char *list_iterator = list;
+  const char *p;
+  unsigned int len;
+  struct variable *var;
+
+  push_new_variable_scope ();
+  var = define_variable (varname, strlen (varname), "", o_automatic, 0);
+
+  /* loop through LIST,  put the value in VAR and expand BODY */
+  while ((p = find_next_token (&list_iterator, &len)) != 0)
+    {
+      char *result = 0;
+#ifdef CONFIG_WITH_VALUE_LENGTH
+      if (len >= (unsigned int)var->value_alloc_len)
+        {
+          free (var->value);
+          var->value_alloc_len = (len + 32) & ~31;
+          var->value = xmalloc (var->value_alloc_len);
+        }
+      memcpy (var->value, p, len);
+      var->value[len] = '\0';
+      var->value_length = len;
+#else
+      free (var->value);
+      var->value = savestring (p, len);
+#endif
+
+      result = allocated_variable_expand (body);
+
+      o = variable_buffer_output (o, result, strlen (result));
+      o = variable_buffer_output (o, " ", 1);
+      doneany = 1;
+      free (result);
+    }
+
+  if (doneany)
+    /* Kill the last space.  */
+    --o;
+
+  pop_variable_scope ();
+  free (varname);
+  free (list);
+
+  return o;
+}
+
+struct a_word
+{
+  struct a_word *next;
+  struct a_word *chain;
+  char *str;
+  int length;
+  int matched;
+};
+
+static unsigned long
+a_word_hash_1 (const void *key)
+{
+  return_STRING_HASH_1 (((struct a_word const *) key)->str);
+}
+
+static unsigned long
+a_word_hash_2 (const void *key)
+{
+  return_STRING_HASH_2 (((struct a_word const *) key)->str);
+}
+
+static int
+a_word_hash_cmp (const void *x, const void *y)
+{
+  int result = ((struct a_word const *) x)->length - ((struct a_word const *) y)->length;
+  if (result)
+    return result;
+  return_STRING_COMPARE (((struct a_word const *) x)->str,
+			 ((struct a_word const *) y)->str);
+}
+
+struct a_pattern
+{
+  struct a_pattern *next;
+  char *str;
+  char *percent;
+  int length;
+  int save_c;
+};
+
+static char *
+func_filter_filterout (char *o, char **argv, const char *funcname)
+{
+  struct a_word *wordhead;
+  struct a_word **wordtail;
+  struct a_word *wp;
+  struct a_pattern *pathead;
+  struct a_pattern **pattail;
+  struct a_pattern *pp;
+
+  struct hash_table a_word_table;
+  int is_filter = streq (funcname, "filter");
+  const char *pat_iterator = argv[0];
+  const char *word_iterator = argv[1];
+  int literals = 0;
+  int words = 0;
+  int hashing = 0;
+  char *p;
+  unsigned int len;
+
+  /* Chop ARGV[0] up into patterns to match against the words.  */
+
+  pattail = &pathead;
+  while ((p = find_next_token (&pat_iterator, &len)) != 0)
+    {
+      struct a_pattern *pat = alloca (sizeof (struct a_pattern));
+
+      *pattail = pat;
+      pattail = &pat->next;
+
+      if (*pat_iterator != '\0')
+	++pat_iterator;
+
+      pat->str = p;
+      pat->length = len;
+      pat->save_c = p[len];
+      p[len] = '\0';
+      pat->percent = find_percent (p);
+      if (pat->percent == 0)
+	literals++;
+    }
+  *pattail = 0;
+
+  /* Chop ARGV[1] up into words to match against the patterns.  */
+
+  wordtail = &wordhead;
+  while ((p = find_next_token (&word_iterator, &len)) != 0)
+    {
+      struct a_word *word = alloca (sizeof (struct a_word));
+
+      *wordtail = word;
+      wordtail = &word->next;
+
+      if (*word_iterator != '\0')
+	++word_iterator;
+
+      p[len] = '\0';
+      word->str = p;
+      word->length = len;
+      word->matched = 0;
+      word->chain = 0;
+      words++;
+    }
+  *wordtail = 0;
+
+  /* Only use a hash table if arg list lengths justifies the cost.  */
+  hashing = (literals >= 2 && (literals * words) >= 10);
+  if (hashing)
+    {
+      hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2,
+                 a_word_hash_cmp);
+      for (wp = wordhead; wp != 0; wp = wp->next)
+	{
+	  struct a_word *owp = hash_insert (&a_word_table, wp);
+	  if (owp)
+	    wp->chain = owp;
+	}
+    }
+
+  if (words)
+    {
+      int doneany = 0;
+
+      /* Run each pattern through the words, killing words.  */
+      for (pp = pathead; pp != 0; pp = pp->next)
+	{
+	  if (pp->percent)
+	    for (wp = wordhead; wp != 0; wp = wp->next)
+	      wp->matched |= pattern_matches (pp->str, pp->percent, wp->str);
+	  else if (hashing)
+	    {
+	      struct a_word a_word_key;
+	      a_word_key.str = pp->str;
+	      a_word_key.length = pp->length;
+	      wp = hash_find_item (&a_word_table, &a_word_key);
+	      while (wp)
+		{
+		  wp->matched |= 1;
+		  wp = wp->chain;
+		}
+	    }
+	  else
+	    for (wp = wordhead; wp != 0; wp = wp->next)
+	      wp->matched |= (wp->length == pp->length
+			      && strneq (pp->str, wp->str, wp->length));
+	}
+
+      /* Output the words that matched (or didn't, for filter-out).  */
+      for (wp = wordhead; wp != 0; wp = wp->next)
+	if (is_filter ? wp->matched : !wp->matched)
+	  {
+	    o = variable_buffer_output (o, wp->str, strlen (wp->str));
+	    o = variable_buffer_output (o, " ", 1);
+	    doneany = 1;
+	  }
+
+      if (doneany)
+	/* Kill the last space.  */
+	--o;
+    }
+
+  for (pp = pathead; pp != 0; pp = pp->next)
+    pp->str[pp->length] = pp->save_c;
+
+  if (hashing)
+    hash_free (&a_word_table, 0);
+
+  return o;
+}
+
+
+static char *
+func_strip (char *o, char **argv, const char *funcname UNUSED)
+{
+  const char *p = argv[0];
+  int doneany = 0;
+
+  while (*p != '\0')
+    {
+      int i=0;
+      const char *word_start;
+
+      while (isspace ((unsigned char)*p))
+	++p;
+      word_start = p;
+      for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i)
+	{}
+      if (!i)
+	break;
+      o = variable_buffer_output (o, word_start, i);
+      o = variable_buffer_output (o, " ", 1);
+      doneany = 1;
+    }
+
+  if (doneany)
+    /* Kill the last space.  */
+    --o;
+
+  return o;
+}
+
+/*
+  Print a warning or fatal message.
+*/
+static char *
+func_error (char *o, char **argv, const char *funcname)
+{
+  char **argvp;
+  char *msg, *p;
+  int len;
+
+  /* The arguments will be broken on commas.  Rather than create yet
+     another special case where function arguments aren't broken up,
+     just create a format string that puts them back together.  */
+  for (len=0, argvp=argv; *argvp != 0; ++argvp)
+    len += strlen (*argvp) + 2;
+
+  p = msg = alloca (len + 1);
+
+  for (argvp=argv; argvp[1] != 0; ++argvp)
+    {
+      strcpy (p, *argvp);
+      p += strlen (*argvp);
+      *(p++) = ',';
+      *(p++) = ' ';
+    }
+  strcpy (p, *argvp);
+
+  switch (*funcname) {
+    case 'e':
+      fatal (reading_file, "%s", msg);
+
+    case 'w':
+      error (reading_file, "%s", msg);
+      break;
+
+    case 'i':
+      printf ("%s\n", msg);
+      fflush(stdout);
+      break;
+
+    default:
+      fatal (*expanding_var, "Internal error: func_error: '%s'", funcname);
+  }
+
+  /* The warning function expands to the empty string.  */
+  return o;
+}
+
+
+/*
+  chop argv[0] into words, and sort them.
+ */
+static char *
+func_sort (char *o, char **argv, const char *funcname UNUSED)
+{
+  const char *t;
+  char **words;
+  int wordi;
+  char *p;
+  unsigned int len;
+  int i;
+
+  /* Find the maximum number of words we'll have.  */
+  t = argv[0];
+  wordi = 1;
+  while (*t != '\0')
+    {
+      char c = *(t++);
+
+      if (! isspace ((unsigned char)c))
+        continue;
+
+      ++wordi;
+
+      while (isspace ((unsigned char)*t))
+        ++t;
+    }
+
+  words = xmalloc (wordi * sizeof (char *));
+
+  /* Now assign pointers to each string in the array.  */
+  t = argv[0];
+  wordi = 0;
+  while ((p = find_next_token (&t, &len)) != 0)
+    {
+      ++t;
+      p[len] = '\0';
+      words[wordi++] = p;
+    }
+
+  if (wordi)
+    {
+      /* Now sort the list of words.  */
+      qsort (words, wordi, sizeof (char *), alpha_compare);
+
+      /* Now write the sorted list, uniquified.  */
+#ifdef CONFIG_WITH_RSORT
+      if (strcmp (funcname, "rsort"))
+        {
+          /* sort */
+#endif
+          for (i = 0; i < wordi; ++i)
+            {
+              len = strlen (words[i]);
+              if (i == wordi - 1 || strlen (words[i + 1]) != len
+                  || strcmp (words[i], words[i + 1]))
+                {
+                  o = variable_buffer_output (o, words[i], len);
+                  o = variable_buffer_output (o, " ", 1);
+                }
+            }
+#ifdef CONFIG_WITH_RSORT
+        }
+      else
+        {
+          /* rsort - reverse the result */
+          i = wordi;
+          while (i-- > 0)
+            {
+              len = strlen (words[i]);
+              if (i == 0 || strlen (words[i - 1]) != len
+                  || strcmp (words[i], words[i - 1]))
+                {
+                  o = variable_buffer_output (o, words[i], len);
+                  o = variable_buffer_output (o, " ", 1);
+                }
+            }
+        }
+#endif
+
+      /* Kill the last space.  */
+      --o;
+    }
+
+  free (words);
+
+  return o;
+}
+
+/*
+  $(if condition,true-part[,false-part])
+
+  CONDITION is false iff it evaluates to an empty string.  White
+  space before and after condition are stripped before evaluation.
+
+  If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is
+  evaluated (if it exists).  Because only one of the two PARTs is evaluated,
+  you can use $(if ...) to create side-effects (with $(shell ...), for
+  example).
+*/
+
+static char *
+func_if (char *o, char **argv, const char *funcname UNUSED)
+{
+  const char *begp = argv[0];
+  const char *endp = begp + strlen (argv[0]) - 1;
+  int result = 0;
+
+  /* Find the result of the condition: if we have a value, and it's not
+     empty, the condition is true.  If we don't have a value, or it's the
+     empty string, then it's false.  */
+
+  strip_whitespace (&begp, &endp);
+
+  if (begp <= endp)
+    {
+      char *expansion = expand_argument (begp, endp+1);
+
+      result = strlen (expansion);
+      free (expansion);
+    }
+
+  /* If the result is true (1) we want to eval the first argument, and if
+     it's false (0) we want to eval the second.  If the argument doesn't
+     exist we do nothing, otherwise expand it and add to the buffer.  */
+
+  argv += 1 + !result;
+
+  if (*argv)
+    {
+      char *expansion = expand_argument (*argv, NULL);
+
+      o = variable_buffer_output (o, expansion, strlen (expansion));
+
+      free (expansion);
+    }
+
+  return o;
+}
+
+/*
+  $(or condition1[,condition2[,condition3[...]]])
+
+  A CONDITION is false iff it evaluates to an empty string.  White
+  space before and after CONDITION are stripped before evaluation.
+
+  CONDITION1 is evaluated.  If it's true, then this is the result of
+  expansion.  If it's false, CONDITION2 is evaluated, and so on.  If none of
+  the conditions are true, the expansion is the empty string.
+
+  Once a CONDITION is true no further conditions are evaluated
+  (short-circuiting).
+*/
+
+static char *
+func_or (char *o, char **argv, const char *funcname UNUSED)
+{
+  for ( ; *argv ; ++argv)
+    {
+      const char *begp = *argv;
+      const char *endp = begp + strlen (*argv) - 1;
+      char *expansion;
+      int result = 0;
+
+      /* Find the result of the condition: if it's false keep going.  */
+
+      strip_whitespace (&begp, &endp);
+
+      if (begp > endp)
+        continue;
+
+      expansion = expand_argument (begp, endp+1);
+      result = strlen (expansion);
+
+      /* If the result is false keep going.  */
+      if (!result)
+        {
+          free (expansion);
+          continue;
+        }
+
+      /* It's true!  Keep this result and return.  */
+      o = variable_buffer_output (o, expansion, result);
+      free (expansion);
+      break;
+    }
+
+  return o;
+}
+
+/*
+  $(and condition1[,condition2[,condition3[...]]])
+
+  A CONDITION is false iff it evaluates to an empty string.  White
+  space before and after CONDITION are stripped before evaluation.
+
+  CONDITION1 is evaluated.  If it's false, then this is the result of
+  expansion.  If it's true, CONDITION2 is evaluated, and so on.  If all of
+  the conditions are true, the expansion is the result of the last condition.
+
+  Once a CONDITION is false no further conditions are evaluated
+  (short-circuiting).
+*/
+
+static char *
+func_and (char *o, char **argv, const char *funcname UNUSED)
+{
+  char *expansion;
+  int result;
+
+  while (1)
+    {
+      const char *begp = *argv;
+      const char *endp = begp + strlen (*argv) - 1;
+
+      /* An empty condition is always false.  */
+      strip_whitespace (&begp, &endp);
+      if (begp > endp)
+        return o;
+
+      expansion = expand_argument (begp, endp+1);
+      result = strlen (expansion);
+
+      /* If the result is false, stop here: we're done.  */
+      if (!result)
+        break;
+
+      /* Otherwise the result is true.  If this is the last one, keep this
+         result and quit.  Otherwise go on to the next one!  */
+
+      if (*(++argv))
+        free (expansion);
+      else
+        {
+          o = variable_buffer_output (o, expansion, result);
+          break;
+        }
+    }
+
+  free (expansion);
+
+  return o;
+}
+
+static char *
+func_wildcard (char *o, char **argv, const char *funcname UNUSED)
+{
+#ifdef _AMIGA
+   o = wildcard_expansion (argv[0], o);
+#else
+   char *p = string_glob (argv[0]);
+   o = variable_buffer_output (o, p, strlen (p));
+#endif
+   return o;
+}
+
+/*
+  $(eval <makefile string>)
+
+  Always resolves to the empty string.
+
+  Treat the arguments as a segment of makefile, and parse them.
+*/
+
+static char *
+func_eval (char *o, char **argv, const char *funcname UNUSED)
+{
+  char *buf;
+  unsigned int len;
+
+  /* Eval the buffer.  Pop the current variable buffer setting so that the
+     eval'd code can use its own without conflicting.  */
+
+  install_variable_buffer (&buf, &len);
+
+  eval_buffer (argv[0]);
+
+  restore_variable_buffer (buf, len);
+
+  return o;
+}
+
+
+#ifdef CONFIG_WITH_EVALPLUS
+/* Same as func_eval except that we push and pop the local variable
+   context before evaluating the buffer. */
+static char *
+func_evalctx (char *o, char **argv, const char *funcname UNUSED)
+{
+  char *buf;
+  unsigned int len;
+
+  /* Eval the buffer.  Pop the current variable buffer setting so that the
+     eval'd code can use its own without conflicting.  */
+
+  install_variable_buffer (&buf, &len);
+
+  push_new_variable_scope ();
+
+  eval_buffer (argv[0]);
+
+  pop_variable_scope ();
+
+  restore_variable_buffer (buf, len);
+
+  return o;
+}
+
+/* A mix of func_eval and func_value, saves memory for the expansion.
+  This implements both evalval and evalvalctx, the latter has its own
+  variable context just like evalctx. */
+static char *
+func_evalval (char *o, char **argv, const char *funcname)
+{
+  /* Look up the variable.  */
+  struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
+  if (v)
+    {
+      char *buf;
+      unsigned int len;
+      int var_ctx;
+      size_t off;
+      const struct floc *reading_file_saved = reading_file;
+
+      /* Make a copy of the value to the variable buffer since
+         eval_buffer will make changes to its input. */
+
+      off = o - variable_buffer;
+      o = variable_buffer_output (o, v->value, v->value_length + 1);
+      o = variable_buffer + off;
+      assert (!o[v->value_length]);
+
+      /* Eval the value.  Pop the current variable buffer setting so that the
+         eval'd code can use its own without conflicting. (really necessary?)  */
+
+      install_variable_buffer (&buf, &len);
+      var_ctx = !strcmp (funcname, "evalvalctx");
+      if (var_ctx)
+        push_new_variable_scope ();
+      if (v->fileinfo.filenm)
+        reading_file = &v->fileinfo;
+
+      eval_buffer (o);
+
+      reading_file = reading_file_saved;
+      if (var_ctx)
+        pop_variable_scope ();
+      restore_variable_buffer (buf, len);
+    }
+
+  return o;
+}
+#endif /* CONFIG_WITH_EVALPLUS */
+
+static char *
+func_value (char *o, char **argv, const char *funcname UNUSED)
+{
+  /* Look up the variable.  */
+  struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
+
+  /* Copy its value into the output buffer without expanding it.  */
+  if (v)
+#ifdef CONFIG_WITH_VALUE_LENGTH
+    o = variable_buffer_output (o, v->value,
+                                v->value_length >= 0 ? v->value_length : strlen(v->value));
+#else
+    o = variable_buffer_output (o, v->value, strlen(v->value));
+#endif
+
+  return o;
+}
+
+/*
+  \r  is replaced on UNIX as well. Is this desirable?
+ */
+static void
+fold_newlines (char *buffer, unsigned int *length)
+{
+  char *dst = buffer;
+  char *src = buffer;
+  char *last_nonnl = buffer -1;
+  src[*length] = 0;
+  for (; *src != '\0'; ++src)
+    {
+      if (src[0] == '\r' && src[1] == '\n')
+	continue;
+      if (*src == '\n')
+	{
+	  *dst++ = ' ';
+	}
+      else
+	{
+	  last_nonnl = dst;
+	  *dst++ = *src;
+	}
+    }
+  *(++last_nonnl) = '\0';
+  *length = last_nonnl - buffer;
+}
+
+
+
+int shell_function_pid = 0, shell_function_completed;
+
+
+#ifdef WINDOWS32
+/*untested*/
+
+#include <windows.h>
+#include <io.h>
+#include "sub_proc.h"
+
+
+void
+windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp)
+{
+  SECURITY_ATTRIBUTES saAttr;
+  HANDLE hIn;
+  HANDLE hErr;
+  HANDLE hChildOutRd;
+  HANDLE hChildOutWr;
+  HANDLE hProcess;
+
+
+  saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
+  saAttr.bInheritHandle = TRUE;
+  saAttr.lpSecurityDescriptor = NULL;
+
+  if (DuplicateHandle (GetCurrentProcess(),
+		      GetStdHandle(STD_INPUT_HANDLE),
+		      GetCurrentProcess(),
+		      &hIn,
+		      0,
+		      TRUE,
+		      DUPLICATE_SAME_ACCESS) == FALSE) {
+    fatal (NILF, _("create_child_process: DuplicateHandle(In) failed (e=%ld)\n"),
+	   GetLastError());
+
+  }
+  if (DuplicateHandle(GetCurrentProcess(),
+		      GetStdHandle(STD_ERROR_HANDLE),
+		      GetCurrentProcess(),
+		      &hErr,
+		      0,
+		      TRUE,
+		      DUPLICATE_SAME_ACCESS) == FALSE) {
+    fatal (NILF, _("create_child_process: DuplicateHandle(Err) failed (e=%ld)\n"),
+	   GetLastError());
+  }
+
+  if (!CreatePipe(&hChildOutRd, &hChildOutWr, &saAttr, 0))
+    fatal (NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError());
+
+  hProcess = process_init_fd(hIn, hChildOutWr, hErr);
+
+  if (!hProcess)
+    fatal (NILF, _("windows32_openpipe (): process_init_fd() failed\n"));
+
+  /* make sure that CreateProcess() has Path it needs */
+  sync_Path_environment();
+
+  if (!process_begin(hProcess, command_argv, envp, command_argv[0], NULL)) {
+    /* register process for wait */
+    process_register(hProcess);
+
+    /* set the pid for returning to caller */
+    *pid_p = (int) hProcess;
+
+  /* set up to read data from child */
+  pipedes[0] = _open_osfhandle((long) hChildOutRd, O_RDONLY);
+
+  /* this will be closed almost right away */
+  pipedes[1] = _open_osfhandle((long) hChildOutWr, O_APPEND);
+  } else {
+    /* reap/cleanup the failed process */
+	process_cleanup(hProcess);
+
+    /* close handles which were duplicated, they weren't used */
+	CloseHandle(hIn);
+	CloseHandle(hErr);
+
+	/* close pipe handles, they won't be used */
+	CloseHandle(hChildOutRd);
+	CloseHandle(hChildOutWr);
+
+    /* set status for return */
+    pipedes[0] = pipedes[1] = -1;
+    *pid_p = -1;
+  }
+}
+#endif
+
+
+#ifdef __MSDOS__
+FILE *
+msdos_openpipe (int* pipedes, int *pidp, char *text)
+{
+  FILE *fpipe=0;
+  /* MSDOS can't fork, but it has `popen'.  */
+  struct variable *sh = lookup_variable ("SHELL", 5);
+  int e;
+  extern int dos_command_running, dos_status;
+
+  /* Make sure not to bother processing an empty line.  */
+  while (isblank ((unsigned char)*text))
+    ++text;
+  if (*text == '\0')
+    return 0;
+
+  if (sh)
+    {
+      char buf[PATH_MAX + 7];
+      /* This makes sure $SHELL value is used by $(shell), even
+	 though the target environment is not passed to it.  */
+      sprintf (buf, "SHELL=%s", sh->value);
+      putenv (buf);
+    }
+
+  e = errno;
+  errno = 0;
+  dos_command_running = 1;
+  dos_status = 0;
+  /* If dos_status becomes non-zero, it means the child process
+     was interrupted by a signal, like SIGINT or SIGQUIT.  See
+     fatal_error_signal in commands.c.  */
+  fpipe = popen (text, "rt");
+  dos_command_running = 0;
+  if (!fpipe || dos_status)
+    {
+      pipedes[0] = -1;
+      *pidp = -1;
+      if (dos_status)
+	errno = EINTR;
+      else if (errno == 0)
+	errno = ENOMEM;
+      shell_function_completed = -1;
+    }
+  else
+    {
+      pipedes[0] = fileno (fpipe);
+      *pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */
+      errno = e;
+      shell_function_completed = 1;
+    }
+  return fpipe;
+}
+#endif
+
+/*
+  Do shell spawning, with the naughty bits for different OSes.
+ */
+
+#ifdef VMS
+
+/* VMS can't do $(shell ...)  */
+#define func_shell 0
+
+#else
+#ifndef _AMIGA
+static char *
+func_shell (char *o, char **argv, const char *funcname UNUSED)
+{
+  char *batch_filename = NULL;
+
+#ifdef __MSDOS__
+  FILE *fpipe;
+#endif
+  char **command_argv;
+  const char *error_prefix;
+  char **envp;
+  int pipedes[2];
+  int pid;
+
+#ifndef __MSDOS__
+  /* Construct the argument list.  */
+  command_argv = construct_command_argv (argv[0], NULL, NULL, &batch_filename);
+  if (command_argv == 0)
+    return o;
+#endif
+
+  /* Using a target environment for `shell' loses in cases like:
+     export var = $(shell echo foobie)
+     because target_environment hits a loop trying to expand $(var)
+     to put it in the environment.  This is even more confusing when
+     var was not explicitly exported, but just appeared in the
+     calling environment.
+
+     See Savannah bug #10593.
+
+  envp = target_environment (NILF);
+  */
+
+  envp = environ;
+
+  /* For error messages.  */
+  if (reading_file && reading_file->filenm)
+    {
+      char *p = alloca (strlen (reading_file->filenm)+11+4);
+      sprintf (p, "%s:%lu: ", reading_file->filenm, reading_file->lineno);
+      error_prefix = p;
+    }
+  else
+    error_prefix = "";
+
+#if defined(__MSDOS__)
+  fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
+  if (pipedes[0] < 0)
+    {
+      perror_with_name (error_prefix, "pipe");
+      return o;
+    }
+#elif defined(WINDOWS32)
+  windows32_openpipe (pipedes, &pid, command_argv, envp);
+  if (pipedes[0] < 0)
+    {
+      /* open of the pipe failed, mark as failed execution */
+      shell_function_completed = -1;
+
+      return o;
+    }
+  else
+#else
+  if (pipe (pipedes) < 0)
+    {
+      perror_with_name (error_prefix, "pipe");
+      return o;
+    }
+
+# ifdef __EMX__
+  /* close some handles that are unnecessary for the child process */
+  CLOSE_ON_EXEC(pipedes[1]);
+  CLOSE_ON_EXEC(pipedes[0]);
+  /* Never use fork()/exec() here! Use spawn() instead in exec_command() */
+  pid = child_execute_job (0, pipedes[1], command_argv, envp);
+  if (pid < 0)
+    perror_with_name (error_prefix, "spawn");
+# else /* ! __EMX__ */
+  pid = vfork ();
+  if (pid < 0)
+    perror_with_name (error_prefix, "fork");
+  else if (pid == 0)
+    child_execute_job (0, pipedes[1], command_argv, envp);
+  else
+# endif
+#endif
+    {
+      /* We are the parent.  */
+      char *buffer;
+      unsigned int maxlen, i;
+      int cc;
+
+      /* Record the PID for reap_children.  */
+      shell_function_pid = pid;
+#ifndef  __MSDOS__
+      shell_function_completed = 0;
+
+      /* Free the storage only the child needed.  */
+      free (command_argv[0]);
+      free (command_argv);
+
+      /* Close the write side of the pipe.  */
+# ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */
+      if (pipedes[1] != -1)
+# endif
+      close (pipedes[1]);
+#endif
+
+      /* Set up and read from the pipe.  */
+
+      maxlen = 200;
+      buffer = xmalloc (maxlen + 1);
+
+      /* Read from the pipe until it gets EOF.  */
+      for (i = 0; ; i += cc)
+	{
+	  if (i == maxlen)
+	    {
+	      maxlen += 512;
+	      buffer = xrealloc (buffer, maxlen + 1);
+	    }
+
+	  EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i));
+	  if (cc <= 0)
+	    break;
+	}
+      buffer[i] = '\0';
+
+      /* Close the read side of the pipe.  */
+#ifdef  __MSDOS__
+      if (fpipe)
+	(void) pclose (fpipe);
+#else
+# ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */
+      if (pipedes[0] != -1)
+# endif
+      (void) close (pipedes[0]);
+#endif
+
+      /* Loop until child_handler or reap_children()  sets
+         shell_function_completed to the status of our child shell.  */
+      while (shell_function_completed == 0)
+	reap_children (1, 0);
+
+      if (batch_filename) {
+	DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"),
+                       batch_filename));
+	remove (batch_filename);
+	free (batch_filename);
+      }
+      shell_function_pid = 0;
+
+      /* The child_handler function will set shell_function_completed
+	 to 1 when the child dies normally, or to -1 if it
+	 dies with status 127, which is most likely an exec fail.  */
+
+      if (shell_function_completed == -1)
+	{
+	  /* This likely means that the execvp failed, so we should just
+	     write the error message in the pipe from the child.  */
+	  fputs (buffer, stderr);
+	  fflush (stderr);
+	}
+      else
+	{
+	  /* The child finished normally.  Replace all newlines in its output
+	     with spaces, and put that in the variable output buffer.  */
+	  fold_newlines (buffer, &i);
+	  o = variable_buffer_output (o, buffer, i);
+	}
+
+      free (buffer);
+    }
+
+  return o;
+}
+
+#else	/* _AMIGA */
+
+/* Do the Amiga version of func_shell.  */
+
+static char *
+func_shell (char *o, char **argv, const char *funcname)
+{
+  /* Amiga can't fork nor spawn, but I can start a program with
+     redirection of my choice.  However, this means that we
+     don't have an opportunity to reopen stdout to trap it.  Thus,
+     we save our own stdout onto a new descriptor and dup a temp
+     file's descriptor onto our stdout temporarily.  After we
+     spawn the shell program, we dup our own stdout back to the
+     stdout descriptor.  The buffer reading is the same as above,
+     except that we're now reading from a file.  */
+
+#include <dos/dos.h>
+#include <proto/dos.h>
+
+  BPTR child_stdout;
+  char tmp_output[FILENAME_MAX];
+  unsigned int maxlen = 200, i;
+  int cc;
+  char * buffer, * ptr;
+  char ** aptr;
+  int len = 0;
+  char* batch_filename = NULL;
+
+  /* Construct the argument list.  */
+  command_argv = construct_command_argv (argv[0], (char **) NULL,
+                                         (struct file *) 0, &batch_filename);
+  if (command_argv == 0)
+    return o;
+
+  /* Note the mktemp() is a security hole, but this only runs on Amiga.
+     Ideally we would use main.c:open_tmpfile(), but this uses a special
+     Open(), not fopen(), and I'm not familiar enough with the code to mess
+     with it.  */
+  strcpy (tmp_output, "t:MakeshXXXXXXXX");
+  mktemp (tmp_output);
+  child_stdout = Open (tmp_output, MODE_NEWFILE);
+
+  for (aptr=command_argv; *aptr; aptr++)
+    len += strlen (*aptr) + 1;
+
+  buffer = xmalloc (len + 1);
+  ptr = buffer;
+
+  for (aptr=command_argv; *aptr; aptr++)
+    {
+      strcpy (ptr, *aptr);
+      ptr += strlen (ptr) + 1;
+      *ptr ++ = ' ';
+      *ptr = 0;
+    }
+
+  ptr[-1] = '\n';
+
+  Execute (buffer, NULL, child_stdout);
+  free (buffer);
+
+  Close (child_stdout);
+
+  child_stdout = Open (tmp_output, MODE_OLDFILE);
+
+  buffer = xmalloc (maxlen);
+  i = 0;
+  do
+    {
+      if (i == maxlen)
+	{
+	  maxlen += 512;
+	  buffer = xrealloc (buffer, maxlen + 1);
+	}
+
+      cc = Read (child_stdout, &buffer[i], maxlen - i);
+      if (cc > 0)
+	i += cc;
+    } while (cc > 0);
+
+  Close (child_stdout);
+
+  fold_newlines (buffer, &i);
+  o = variable_buffer_output (o, buffer, i);
+  free (buffer);
+  return o;
+}
+#endif  /* _AMIGA */
+#endif  /* !VMS */
+
+#ifdef EXPERIMENTAL
+
+/*
+  equality. Return is string-boolean, ie, the empty string is false.
+ */
+static char *
+func_eq (char *o, char **argv, const char *funcname)
+{
+  int result = ! strcmp (argv[0], argv[1]);
+  o = variable_buffer_output (o,  result ? "1" : "", result);
+  return o;
+}
+
+
+/*
+  string-boolean not operator.
+ */
+static char *
+func_not (char *o, char **argv, const char *funcname)
+{
+  const char *s = argv[0];
+  int result = 0;
+  while (isspace ((unsigned char)*s))
+    s++;
+  result = ! (*s);
+  o = variable_buffer_output (o,  result ? "1" : "", result);
+  return o;
+}
+#endif
+
+
+
+#ifdef CONFIG_WITH_DEFINED
+/* Similar to ifdef. */
+static char *
+func_defined (char *o, char **argv, const char *funcname)
+{
+  struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
+  int result = v != NULL && *v->value != '\0';
+  o = variable_buffer_output (o,  result ? "1" : "", result);
+  return o;
+}
+#endif /* CONFIG_WITH_DEFINED*/
+
+
+
+/* Return the absolute name of file NAME which does not contain any `.',
+   `..' components nor any repeated path separators ('/').   */
+#ifdef KMK
+char *
+#else
+static char *
+#endif
+abspath (const char *name, char *apath)
+{
+  char *dest;
+  const char *start, *end, *apath_limit;
+
+  if (name[0] == '\0' || apath == NULL)
+    return NULL;
+
+#ifdef WINDOWS32                                                    /* bird */
+  dest = w32ify((char *)name, 1);
+  if (!dest)
+    return NULL;
+  {
+  size_t len = strlen(dest);
+  memcpy(apath, dest, len);
+  dest = apath + len;
+  }
+
+  (void)end; (void)start; (void)apath_limit;
+
+#elif defined __OS2__                                               /* bird */
+  if (_abspath(apath, name, GET_PATH_MAX))
+    return NULL;
+  dest = strchr(apath, '\0');
+
+  (void)end; (void)start; (void)apath_limit; (void)dest;
+
+#else /* !WINDOWS32 && !__OS2__ */
+  apath_limit = apath + GET_PATH_MAX;
+
+#ifdef HAVE_DOS_PATHS /* bird added this */
+  if (isalpha(name[0]) && name[1] == ':')
+    {
+      /* drive spec */
+      apath[0] = toupper(name[0]);
+      apath[1] = ':';
+      apath[2] = '/';
+      name += 2;
+    }
+  else
+#endif /* HAVE_DOS_PATHS */
+  if (name[0] != '/')
+    {
+      /* It is unlikely we would make it until here but just to make sure. */
+      if (!starting_directory)
+	return NULL;
+
+      strcpy (apath, starting_directory);
+
+      dest = strchr (apath, '\0');
+    }
+  else
+    {
+      apath[0] = '/';
+      dest = apath + 1;
+    }
+
+  for (start = end = name; *start != '\0'; start = end)
+    {
+      unsigned long len;
+
+      /* Skip sequence of multiple path-separators.  */
+      while (*start == '/')
+	++start;
+
+      /* Find end of path component.  */
+      for (end = start; *end != '\0' && *end != '/'; ++end)
+        ;
+
+      len = end - start;
+
+      if (len == 0)
+	break;
+      else if (len == 1 && start[0] == '.')
+	/* nothing */;
+      else if (len == 2 && start[0] == '.' && start[1] == '.')
+	{
+	  /* Back up to previous component, ignore if at root already.  */
+	  if (dest > apath + 1)
+	    while ((--dest)[-1] != '/');
+	}
+      else
+	{
+	  if (dest[-1] != '/')
+            *dest++ = '/';
+
+	  if (dest + len >= apath_limit)
+            return NULL;
+
+	  dest = memcpy (dest, start, len);
+          dest += len;
+	  *dest = '\0';
+	}
+    }
+#endif /* !WINDOWS32 && !__OS2__ */
+
+  /* Unless it is root strip trailing separator.  */
+#ifdef HAVE_DOS_PATHS /* bird (is this correct? what about UNC?) */
+  if (dest > apath + 1 + (apath[0] != '/') && dest[-1] == '/')
+#else
+  if (dest > apath + 1 && dest[-1] == '/')
+#endif
+    --dest;
+
+  *dest = '\0';
+
+  return apath;
+}
+
+
+static char *
+func_realpath (char *o, char **argv, const char *funcname UNUSED)
+{
+  /* Expand the argument.  */
+  const char *p = argv[0];
+  const char *path = 0;
+  int doneany = 0;
+  unsigned int len = 0;
+  PATH_VAR (in);
+  PATH_VAR (out);
+
+  while ((path = find_next_token (&p, &len)) != 0)
+    {
+      if (len < GET_PATH_MAX)
+        {
+          strncpy (in, path, len);
+          in[len] = '\0';
+
+          if (
+#ifdef HAVE_REALPATH
+              realpath (in, out)
+#else
+              abspath (in, out)
+#endif
+             )
+            {
+              o = variable_buffer_output (o, out, strlen (out));
+              o = variable_buffer_output (o, " ", 1);
+              doneany = 1;
+            }
+        }
+    }
+
+  /* Kill last space.  */
+  if (doneany)
+    --o;
+
+  return o;
+}
+
+static char *
+func_abspath (char *o, char **argv, const char *funcname UNUSED)
+{
+  /* Expand the argument.  */
+  const char *p = argv[0];
+  const char *path = 0;
+  int doneany = 0;
+  unsigned int len = 0;
+  PATH_VAR (in);
+  PATH_VAR (out);
+
+  while ((path = find_next_token (&p, &len)) != 0)
+    {
+      if (len < GET_PATH_MAX)
+        {
+          strncpy (in, path, len);
+          in[len] = '\0';
+
+          if (abspath (in, out))
+            {
+              o = variable_buffer_output (o, out, strlen (out));
+              o = variable_buffer_output (o, " ", 1);
+              doneany = 1;
+            }
+        }
+    }
+
+  /* Kill last space.  */
+  if (doneany)
+    --o;
+
+  return o;
+}
+
+#ifdef CONFIG_WITH_ABSPATHEX
+/* Same as abspath except that the current path may be given as the
+   2nd argument. */
+static char *
+func_abspathex (char *o, char **argv, const char *funcname UNUSED)
+{
+  char *cwd = argv[1];
+
+  /* cwd needs leading spaces chopped and may be optional,
+     in which case we're exactly like $(abspath ). */
+  while (isblank(*cwd))
+    cwd++;
+  if (!*cwd)
+    o = func_abspath (o, argv, funcname);
+  else
+    {
+      /* Expand the argument.  */
+      const char *p = argv[0];
+      unsigned int cwd_len = ~0U;
+      char *path = 0;
+      int doneany = 0;
+      unsigned int len = 0;
+      PATH_VAR (in);
+      PATH_VAR (out);
+
+      while ((path = find_next_token (&p, &len)) != 0)
+        {
+          if (len < GET_PATH_MAX)
+            {
+#ifdef HAVE_DOS_PATHS
+              if (path[0] != '/' && path[0] != '\\' && (len < 2 || path[1] != ':') && cwd)
+#else
+              if (path[0] != '/' && cwd)
+#endif
+                {
+                  /* relative path, prefix with cwd. */
+                  if (cwd_len == ~0U)
+                    cwd_len = strlen (cwd);
+                  if (cwd_len + len + 1 >= GET_PATH_MAX)
+                      continue;
+                  memcpy (in, cwd, cwd_len);
+                  in[cwd_len] = '/';
+                  memcpy (in + cwd_len + 1, path, len);
+                  in[cwd_len + len + 1] = '\0';
+                }
+              else
+                {
+                  /* absolute path pass it as-is. */
+                  memcpy (in, path, len);
+                  in[len] = '\0';
+                }
+
+              if (abspath (in, out))
+                {
+                  o = variable_buffer_output (o, out, strlen (out));
+                  o = variable_buffer_output (o, " ", 1);
+                  doneany = 1;
+                }
+            }
+        }
+
+      /* Kill last space.  */
+      if (doneany)
+        --o;
+    }
+
+   return o;
+}
+#endif
+
+#ifdef CONFIG_WITH_XARGS
+/* Create one or more command lines avoiding the max argument
+   lenght restriction of the host OS.
+
+   The last argument is the list of arguments that the normal
+   xargs command would be fed from stdin.
+
+   The first argument is initial command and it's arguments.
+
+   If there are three or more arguments, the 2nd argument is
+   the command and arguments to be used on subsequent
+   command lines. Defaults to the initial command.
+
+   If there are four or more arguments, the 3rd argument is
+   the command to be used at the final command line. Defaults
+   to the sub sequent or initial command .
+
+   A future version of this function may define more arguments
+   and therefor anyone specifying six or more arguments will
+   cause fatal errors.
+
+   Typical usage is:
+        $(xargs ar cas mylib.a,$(objects))
+   or
+        $(xargs ar cas mylib.a,ar as mylib.a,$(objects))
+
+   It will then create one or more "ar mylib.a ..." command
+   lines with proper \n\t separation so it can be used when
+   writing rules. */
+static char *
+func_xargs (char *o, char **argv, const char *funcname UNUSED)
+{
+  int argc;
+  const char *initial_cmd;
+  size_t initial_cmd_len;
+  const char *subsequent_cmd;
+  size_t subsequent_cmd_len;
+  const char *final_cmd;
+  size_t final_cmd_len;
+  const char *args;
+  size_t max_args;
+  int i;
+
+#ifdef ARG_MAX
+  /* ARG_MAX is a bit unreliable (environment), so drop 25% of the max. */
+# define XARGS_MAX  (ARG_MAX - (ARG_MAX / 4))
+#else /* FIXME: update configure with a command line length test. */
+# define XARGS_MAX  10240
+#endif
+
+  argc = 0;
+  while (argv[argc])
+    argc++;
+  if (argc > 4)
+    fatal (NILF, _("Too many arguments for $(xargs)!\n"));
+
+  /* first: the initial / default command.*/
+  initial_cmd = argv[0];
+  while (isspace ((unsigned char)*initial_cmd))
+    initial_cmd++;
+  max_args = initial_cmd_len = strlen (initial_cmd);
+
+  /* second: the command for the subsequent command lines. defaults to the initial cmd. */
+  subsequent_cmd = argc > 2 && argv[1][0] != '\0' ? argv[1] : "";
+  while (isspace ((unsigned char)*subsequent_cmd))
+    subsequent_cmd++;
+  if (*subsequent_cmd)
+    {
+      subsequent_cmd_len = strlen (subsequent_cmd);
+      if (subsequent_cmd_len > max_args)
+        max_args = subsequent_cmd_len;
+    }
+  else
+    {
+      subsequent_cmd = initial_cmd;
+      subsequent_cmd_len = initial_cmd_len;
+    }
+
+  /* third: the final command. defaults to the subseq cmd. */
+  final_cmd = argc > 3 && argv[2][0] != '\0' ? argv[2] : "";
+  while (isspace ((unsigned char)*final_cmd))
+    final_cmd++;
+  if (*final_cmd)
+    {
+      final_cmd_len = strlen (final_cmd);
+      if (final_cmd_len > max_args)
+        max_args = final_cmd_len;
+    }
+  else
+    {
+      final_cmd = subsequent_cmd;
+      final_cmd_len = subsequent_cmd_len;
+    }
+
+  /* last: the arguments to split up into sensible portions. */
+  args = argv[argc - 1];
+
+  /* calc the max argument length. */
+  if (XARGS_MAX <= max_args + 2)
+    fatal (NILF, _("$(xargs): the commands are longer than the max exec argument length. (%lu <= %lu)\n"),
+           (unsigned long)XARGS_MAX, (unsigned long)max_args + 2);
+  max_args = XARGS_MAX - max_args - 1;
+
+  /* generate the commands. */
+  i = 0;
+  for (i = 0; ; i++)
+    {
+      unsigned int len;
+      const char *iterator = args;
+      const char *end = args;
+      const char *cur;
+      const char *tmp;
+
+      /* scan the arguments till we reach the end or the max length. */
+      while ((cur = find_next_token(&iterator, &len))
+          && (size_t)((cur + len) - args) < max_args)
+        end = cur + len;
+      if (cur && end == args)
+        fatal (NILF, _("$(xargs): command + one single arg is too much. giving up.\n"));
+
+      /* emit the command. */
+      if (i == 0)
+        {
+          o = variable_buffer_output (o, (char *)initial_cmd, initial_cmd_len);
+          o = variable_buffer_output (o, " ", 1);
+        }
+      else if (cur)
+        {
+          o = variable_buffer_output (o, "\n\t", 2);
+          o = variable_buffer_output (o, (char *)subsequent_cmd, subsequent_cmd_len);
+          o = variable_buffer_output (o, " ", 1);
+        }
+      else
+        {
+          o = variable_buffer_output (o, "\n\t", 2);
+          o = variable_buffer_output (o, (char *)final_cmd, final_cmd_len);
+          o = variable_buffer_output (o, " ", 1);
+        }
+
+      tmp = end;
+      while (tmp > args && isspace ((unsigned char)tmp[-1])) /* drop trailing spaces. */
+        tmp--;
+      o = variable_buffer_output (o, (char *)args, tmp - args);
+
+
+      /* next */
+      if (!cur)
+        break;
+      args = end;
+      while (isspace ((unsigned char)*args))
+        args++;
+    }
+
+  return o;
+}
+#endif
+
+#ifdef CONFIG_WITH_TOUPPER_TOLOWER
+static char *
+func_toupper_tolower (char *o, char **argv, const char *funcname)
+{
+  /* Expand the argument.  */
+  const char *p = argv[0];
+  while (*p)
+    {
+      /* convert to temporary buffer */
+      char tmp[256];
+      unsigned int i;
+      if (!strcmp(funcname, "toupper"))
+        for (i = 0; i < sizeof(tmp) && *p; i++, p++)
+          tmp[i] = toupper(*p);
+      else
+        for (i = 0; i < sizeof(tmp) && *p; i++, p++)
+          tmp[i] = tolower(*p);
+      o = variable_buffer_output (o, tmp, i);
+    }
+
+  return o;
+}
+#endif /* CONFIG_WITH_TOUPPER_TOLOWER */
+
+#if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE)
+
+/* Strip leading spaces and other things off a command. */
+static const char *
+comp_cmds_strip_leading (const char *s, const char *e)
+{
+    while (s < e)
+      {
+        const char ch = *s;
+        if (!isblank (ch)
+         && ch != '@'
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+         && ch != '%'
+#endif
+         && ch != '+'
+         && ch != '-')
+          break;
+        s++;
+      }
+    return s;
+}
+
+/* Worker for func_comp_vars() which is called if the comparision failed.
+   It will do the slow command by command comparision of the commands
+   when there invoked as comp-cmds. */
+static char *
+comp_vars_ne (char *o, const char *s1, const char *e1, const char *s2, const char *e2,
+              char *ne_retval, const char *funcname)
+{
+    /* give up at once if not comp-cmds or comp-cmds-ex. */
+    if (strcmp (funcname, "comp-cmds") != 0
+     && strcmp (funcname, "comp-cmds-ex") != 0)
+      o = variable_buffer_output (o, ne_retval, strlen (ne_retval));
+    else
+      {
+        const char * const s1_start = s1;
+        int new_cmd = 1;
+        int diff;
+        for (;;)
+          {
+            /* if it's a new command, strip leading stuff. */
+            if (new_cmd)
+              {
+                s1 = comp_cmds_strip_leading (s1, e1);
+                s2 = comp_cmds_strip_leading (s2, e2);
+                new_cmd = 0;
+              }
+            if (s1 >= e1 || s2 >= e2)
+              break;
+
+            /*
+             * Inner compare loop which compares one line.
+             * FIXME: parse quoting!
+             */
+            for (;;)
+              {
+                const char ch1 = *s1;
+                const char ch2 = *s2;
+                diff = ch1 - ch2;
+                if (diff)
+                  break;
+                if (ch1 == '\n')
+                  break;
+                assert (ch1 != '\r');
+
+                /* next */
+                s1++;
+                s2++;
+                if (s1 >= e1 || s2 >= e2)
+                  break;
+              }
+
+            /*
+             * If we exited because of a difference try to end-of-command
+             * comparision, e.g. ignore trailing spaces.
+             */
+            if (diff)
+              {
+                /* strip */
+                while (s1 < e1 && isblank (*s1))
+                  s1++;
+                while (s2 < e2 && isblank (*s2))
+                  s2++;
+                if (s1 >= e1 || s2 >= e2)
+                  break;
+
+                /* compare again and check that it's a newline. */
+                if (*s2 != '\n' || *s1 != '\n')
+                  break;
+              }
+            /* Break out if we exited because of EOS. */
+            else if (s1 >= e1 || s2 >= e2)
+                break;
+
+            /*
+             * Detect the end of command lines.
+             */
+            if (*s1 == '\n')
+              new_cmd = s1 == s1_start || s1[-1] != '\\';
+            s1++;
+            s2++;
+          }
+
+        /*
+         * Ignore trailing empty lines.
+         */
+        if (s1 < e1 || s2 < e2)
+          {
+            while (s1 < e1 && (isblank (*s1) || *s1 == '\n'))
+              if (*s1++ == '\n')
+                s1 = comp_cmds_strip_leading (s1, e1);
+            while (s2 < e2 && (isblank (*s2) || *s2 == '\n'))
+              if (*s2++ == '\n')
+                s2 = comp_cmds_strip_leading (s2, e2);
+          }
+
+        /* emit the result. */
+        if (s1 == e1 && s2 == e2)
+          o = variable_buffer_output (o, "", 1);
+        else
+          o = variable_buffer_output (o, ne_retval, strlen (ne_retval));
+      }
+    return o;
+}
+
+/*
+    $(comp-vars var1,var2,not-equal-return)
+  or
+    $(comp-cmds cmd-var1,cmd-var2,not-equal-return)
+
+  Compares the two variables (that's given by name to avoid unnecessary
+  expanding) and return the string in the third argument if not equal.
+  If equal, nothing is returned.
+
+  comp-vars will to an exact comparision only stripping leading and
+  trailing spaces.
+
+  comp-cmds will compare command by command, ignoring not only leading
+  and trailing spaces on each line but also leading one leading '@',
+  '-', '+' and '%'
+*/
+static char *
+func_comp_vars (char *o, char **argv, const char *funcname)
+{
+  const char *s1, *e1, *x1, *s2, *e2, *x2;
+  char *a1 = NULL, *a2 = NULL;
+  size_t l, l1, l2;
+  struct variable *var1 = lookup_variable (argv[0], strlen (argv[0]));
+  struct variable *var2 = lookup_variable (argv[1], strlen (argv[1]));
+
+  /* the simple cases */
+  if (var1 == var2)
+    return variable_buffer_output (o, "", 0);       /* eq */
+  if (!var1 || !var2)
+    return variable_buffer_output (o, argv[2], strlen(argv[2]));
+  if (var1->value == var2->value)
+    return variable_buffer_output (o, "", 0);       /* eq */
+  if (!var1->recursive && !var2->recursive)
+  {
+    if (    var1->value_length == var2->value_length
+        &&  !memcmp (var1->value, var2->value, var1->value_length))
+      return variable_buffer_output (o, "", 0);     /* eq */
+
+    /* ignore trailing and leading blanks */
+    s1 = var1->value;
+    e1 = s1 + var1->value_length;
+    while (isblank ((unsigned char) *s1))
+      s1++;
+    while (e1 > s1 && isblank ((unsigned char) e1[-1]))
+      e1--;
+
+    s2 = var2->value;
+    e2 = s2 + var2->value_length;
+    while (isblank ((unsigned char) *s2))
+      s2++;
+    while (e2 > s2 && isblank ((unsigned char) e2[-1]))
+      e2--;
+
+    if (e1 - s1 != e2 - s2)
+      return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
+    if (!memcmp (s1, s2, e1 - s1))
+      return variable_buffer_output (o, "", 0);     /* eq */
+    return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
+  }
+
+  /* ignore trailing and leading blanks */
+  s1 = var1->value;
+  e1 = s1 + var1->value_length;
+  while (isblank ((unsigned char) *s1))
+    s1++;
+  while (e1 > s1 && isblank ((unsigned char) e1[-1]))
+    e1--;
+
+  s2 = var2->value;
+  e2 = s2 + var2->value_length;
+  while (isblank((unsigned char)*s2))
+    s2++;
+  while (e2 > s2 && isblank ((unsigned char) e2[-1]))
+    e2--;
+
+  /* both empty after stripping? */
+  if (s1 == e1 && s2 == e2)
+    return variable_buffer_output (o, "", 0);       /* eq */
+
+  /* optimist. */
+  if (   e1 - s1 == e2 - s2
+      && !memcmp(s1, s2, e1 - s1))
+    return variable_buffer_output (o, "", 0);       /* eq */
+
+  /* compare up to the first '$' or the end. */
+  x1 = var1->recursive ? memchr (s1, '$', e1 - s1) : NULL;
+  x2 = var2->recursive ? memchr (s2, '$', e2 - s2) : NULL;
+  if (!x1 && !x2)
+    return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
+
+  l1 = x1 ? x1 - s1 : e1 - s1;
+  l2 = x2 ? x2 - s2 : e2 - s2;
+  l = l1 <= l2 ? l1 : l2;
+  if (l && memcmp (s1, s2, l))
+    return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
+
+  /* one or both buffers now require expanding. */
+  if (!x1)
+    s1 += l;
+  else
+    {
+      s1 = a1 = allocated_variable_expand ((char *)s1 + l);
+      if (!l)
+        while (isblank ((unsigned char) *s1))
+          s1++;
+      e1 = strchr (s1, '\0');
+      while (e1 > s1 && isblank ((unsigned char) e1[-1]))
+        e1--;
+    }
+
+  if (!x2)
+    s2 += l;
+  else
+    {
+      s2 = a2 = allocated_variable_expand ((char *)s2 + l);
+      if (!l)
+        while (isblank ((unsigned char) *s2))
+          s2++;
+      e2 = strchr (s2, '\0');
+      while (e2 > s2 && isblank ((unsigned char) e2[-1]))
+        e2--;
+    }
+
+  /* the final compare */
+  if (   e1 - s1 != e2 - s2
+      || memcmp (s1, s2, e1 - s1))
+      o = comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
+  else
+      o = variable_buffer_output (o, "", 1);        /* eq */
+  if (a1)
+    free (a1);
+  if (a2)
+    free (a2);
+  return o;
+}
+
+/*
+  $(comp-cmds-ex cmds1,cmds2,not-equal-return)
+
+  Compares the two strings and return the string in the third argument
+  if not equal. If equal, nothing is returned.
+
+  The comparision will be performed command by command, ignoring not
+  only leading and trailing spaces on each line but also leading one
+  leading '@', '-', '+' and '%'.
+*/
+static char *
+func_comp_cmds_ex (char *o, char **argv, const char *funcname)
+{
+  const char *s1, *e1, *s2, *e2;
+  size_t l1, l2;
+
+  /* the simple cases */
+  s1 = argv[0];
+  s2 = argv[1];
+  if (s1 == s2)
+    return variable_buffer_output (o, "", 0);       /* eq */
+  l1 = strlen (argv[0]);
+  l2 = strlen (argv[1]);
+
+  if (    l1 == l2
+      &&  !memcmp (s1, s2, l1))
+    return variable_buffer_output (o, "", 0);       /* eq */
+
+  /* ignore trailing and leading blanks */
+  e1 = s1 + l1;
+  s1 = comp_cmds_strip_leading (s1, e1);
+
+  e2 = s2 + l2;
+  s2 = comp_cmds_strip_leading (s2, e2);
+
+  if (e1 - s1 != e2 - s2)
+    return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
+  if (!memcmp (s1, s2, e1 - s1))
+    return variable_buffer_output (o, "", 0);       /* eq */
+  return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname);
+}
+#endif
+
+#ifdef CONFIG_WITH_DATE
+# if defined (_MSC_VER) /* FIXME: !defined (HAVE_STRPTIME) */
+char *strptime(const char *s, const char *format, struct tm *tm)
+{
+  return (char *)"strptime is not implemented";
+}
+# endif
+/* Check if the string is all blanks or not. */
+static int
+all_blanks (const char *s)
+{
+  if (!s)
+    return 1;
+  while (isspace ((unsigned char)*s))
+    s++;
+  return *s == '\0';
+}
+
+/* The first argument is the strftime format string, a iso
+   timestamp is the default if nothing is given.
+
+   The second argument is a time value if given. The format
+   is either the format from the first argument or given as
+   an additional third argument. */
+static char *
+func_date (char *o, char **argv, const char *funcname)
+{
+  char *p;
+  char *buf;
+  size_t buf_size;
+  struct tm t;
+  const char *format;
+
+  /* determin the format - use a single word as the default. */
+  format = !strcmp (funcname, "date-utc")
+         ? "%Y-%m-%dT%H:%M:%SZ"
+         : "%Y-%m-%dT%H:%M:%S";
+  if (!all_blanks (argv[0]))
+    format = argv[0];
+
+  /* get the time. */
+  memset (&t, 0, sizeof(t));
+  if (argv[0] && !all_blanks (argv[1]))
+    {
+      const char *input_format = !all_blanks (argv[2]) ? argv[2] : format;
+      p = strptime (argv[1], input_format, &t);
+      if (!p || *p != '\0')
+        {
+          error (NILF, _("$(%s): strptime(%s,%s,) -> %s\n"), funcname,
+                 argv[1], input_format, p ? p : "<null>");
+          return variable_buffer_output (o, "", 0);
+        }
+    }
+  else
+    {
+      time_t tval;
+      time (&tval);
+      if (!strcmp (funcname, "date-utc"))
+        t = *gmtime (&tval);
+      else
+        t = *localtime (&tval);
+    }
+
+  /* format it. note that zero isn't necessarily an error, so we'll
+     have to keep shut about failures. */
+  buf_size = 64;
+  buf = xmalloc (buf_size);
+  while (strftime (buf, buf_size, format, &t) == 0)
+    {
+      if (buf_size >= 4096)
+        {
+          *buf = '\0';
+          break;
+        }
+      buf = xrealloc (buf, buf_size <<= 1);
+    }
+  o = variable_buffer_output (o, buf, strlen (buf));
+  free (buf);
+  return o;
+}
+#endif
+
+#ifdef CONFIG_WITH_FILE_SIZE
+/* Prints the size of the specified file. Only one file is
+   permitted, notthing is stripped. -1 is returned if stat
+   fails. */
+static char *
+func_file_size (char *o, char **argv, const char *funcname UNUSED)
+{
+  struct stat st;
+  if (stat (argv[0], &st))
+    return variable_buffer_output (o, "-1", 2);
+  return math_int_to_variable_buffer (o, st.st_size);
+}
+#endif
+
+#ifdef CONFIG_WITH_WHICH
+/* Checks if the specified file exists an is executable.
+   On systems employing executable extensions, the name may
+   be modified to include the extension. */
+static int func_which_test_x (char *file)
+{
+  struct stat st;
+# if defined(WINDOWS32) || defined(__OS2__)
+  char *ext;
+  char *slash;
+
+  /* fix slashes first. */
+  slash = file;
+  while ((slash = strchr (slash, '\\')) != NULL)
+    *slash++ = '/';
+
+  /* straight */
+  if (stat (file, &st) == 0
+    && S_ISREG (st.st_mode))
+    return 1;
+
+  /* don't try add an extension if there already is one */
+  ext = strchr (file, '\0');
+  if (ext - file >= 4
+   && (   !stricmp (ext - 4, ".exe")
+       || !stricmp (ext - 4, ".cmd")
+       || !stricmp (ext - 4, ".bat")
+       || !stricmp (ext - 4, ".com")))
+    return 0;
+
+  /* try the extensions. */
+  strcpy (ext, ".exe");
+  if (stat (file, &st) == 0
+    && S_ISREG (st.st_mode))
+    return 1;
+
+  strcpy (ext, ".cmd");
+  if (stat (file, &st) == 0
+    && S_ISREG (st.st_mode))
+    return 1;
+
+  strcpy (ext, ".bat");
+  if (stat (file, &st) == 0
+    && S_ISREG (st.st_mode))
+    return 1;
+
+  strcpy (ext, ".com");
+  if (stat (file, &st) == 0
+    && S_ISREG (st.st_mode))
+    return 1;
+
+  return 0;
+
+# else
+
+  return access (file, X_OK) == 0
+     && stat (file, &st) == 0
+     && S_ISREG (st.st_mode);
+# endif
+}
+
+/* Searches for the specified programs in the PATH and print
+   their full location if found. Prints nothing if not found. */
+static char *
+func_which (char *o, char **argv, const char *funcname UNUSED)
+{
+  const char *path;
+  struct variable *path_var;
+  unsigned i;
+  int first = 1;
+  PATH_VAR (buf);
+
+  path_var = lookup_variable ("PATH", 4);
+  if (path_var)
+    path = path_var->value;
+  else
+    path = ".";
+
+  /* iterate input */
+  for (i = 0; argv[i]; i++)
+    {
+      unsigned int len;
+      const char *iterator = argv[i];
+      char *cur;
+
+      while ((cur = find_next_token (&iterator, &len)))
+        {
+          /* if there is a separator, don't walk the path. */
+          if (memchr (cur, '/', len)
+#ifdef HAVE_DOS_PATHS
+           || memchr (cur, '\\', len)
+           || memchr (cur, ':', len)
+#endif
+             )
+            {
+              if (len + 1 + 4 < GET_PATH_MAX) /* +4 for .exe */
+                {
+                  memcpy (buf, cur, len);
+                  buf[len] = '\0';
+                  if (func_which_test_x (buf))
+                    o = variable_buffer_output (o, buf, strlen (buf));
+                }
+            }
+          else
+            {
+              const char *comp = path;
+              for (;;)
+                {
+                  const char *src = comp;
+                  const char *end = strchr (comp, PATH_SEPARATOR_CHAR);
+                  size_t comp_len = end ? end - comp : strlen (comp);
+                  if (!comp_len)
+                    {
+                      comp_len = 1;
+                      src = ".";
+                    }
+                  if (len + comp_len + 2 + 4 < GET_PATH_MAX) /* +4 for .exe */
+                    {
+                      memcpy (buf, comp, comp_len);
+                      buf [comp_len] = '/';
+                      memcpy (&buf[comp_len + 1], cur, len);
+                      buf[comp_len + 1 + len] = '\0';
+
+                      if (func_which_test_x (buf))
+                        {
+                          if (!first)
+                            o = variable_buffer_output (o, " ", 1);
+                          o = variable_buffer_output (o, buf, strlen (buf));
+                          first = 0;
+                          break;
+                        }
+                    }
+
+                  /* next */
+                  if (!end)
+                    break;
+                  comp = end + 1;
+                }
+            }
+        }
+    }
+
+  return variable_buffer_output (o, "", 0);
+}
+#endif /* CONFIG_WITH_WHICH */
+
+#ifdef CONFIG_WITH_IF_CONDITIONALS
+
+/* Evaluates the expression given in the argument using the
+   same evaluator as for the new 'if' statements, except now
+   we don't force the result into a boolean like for 'if' and
+   '$(if-expr ,,)'. */
+static char *
+func_expr (char *o, char **argv, const char *funcname UNUSED)
+{
+  o = expr_eval_to_string (o, argv[0]);
+  return o;
+}
+
+/* Same as '$(if ,,)' except the first argument is evaluated
+   using the same evaluator as for the new 'if' statements. */
+static char *
+func_if_expr (char *o, char **argv, const char *funcname UNUSED)
+{
+    int rc;
+    char *to_expand;
+
+    /* Evaluate the condition in argv[0] and expand the 2nd or
+       3rd argument according to the result. */
+    rc = expr_eval_if_conditionals (argv[0], NULL);
+    to_expand = rc == 0 ? argv[1] : argv[2];
+    if (*to_expand)
+      {
+        char *expansion = expand_argument (to_expand, NULL);
+
+        o = variable_buffer_output (o, expansion, strlen (expansion));
+
+        free (expansion);
+      }
+
+    return o;
+}
+
+#endif /* CONFIG_WITH_IF_CONDITIONALS */
+
+#ifdef CONFIG_WITH_STACK
+
+/* Push an item (string without spaces). */
+static char *
+func_stack_push (char *o, char **argv, const char *funcname UNUSED)
+{
+  do_variable_definition(NILF, argv[0], argv[1], o_file, f_append, 0 /* !target_var */);
+  return o;
+}
+
+/* Pops an item off the stack / get the top stack element.
+   (This is what's tricky to do in pure GNU make syntax.) */
+static char *
+func_stack_pop_top (char *o, char **argv, const char *funcname)
+{
+  struct variable *stack_var;
+  const char *stack = argv[0];
+
+  stack_var = lookup_variable (stack, strlen (stack) );
+  if (stack_var)
+    {
+      unsigned int len;
+      const char *iterator = stack_var->value;
+      char *lastitem = NULL;
+      char *cur;
+
+      while ((cur = find_next_token (&iterator, &len)))
+        lastitem = cur;
+
+      if (lastitem != NULL)
+        {
+          if (strcmp (funcname, "stack-popv") != 0)
+            o = variable_buffer_output (o, lastitem, len);
+          if (strcmp (funcname, "stack-top") != 0)
+            {
+              *lastitem = '\0';
+              while (lastitem > stack_var->value && isspace (lastitem[-1]))
+                *--lastitem = '\0';
+#ifdef CONFIG_WITH_VALUE_LENGTH
+              stack_var->value_length = lastitem - stack_var->value;
+#endif
+            }
+        }
+    }
+  return o;
+}
+#endif /* CONFIG_WITH_STACK */
+
+#if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_FILE_SIZE)
+/* outputs the number (as a string) into the variable buffer. */
+static char *
+math_int_to_variable_buffer (char *o, math_int num)
+{
+  static const char xdigits[17] = "0123456789abcdef";
+  int negative;
+  char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20
+                              or 20 dec + sign + term => 22 */
+  char *str = &strbuf[sizeof (strbuf) - 1];
+
+  negative = num < 0;
+  if (negative)
+    num = -num;
+
+  *str = '\0';
+
+  do
+    {
+#ifdef HEX_MATH_NUMBERS
+      *--str = xdigits[num & 0xf];
+      num >>= 4;
+#else
+      *--str = xdigits[num % 10];
+      num /= 10;
+#endif
+    }
+  while (num);
+
+#ifdef HEX_MATH_NUMBERS
+  *--str = 'x';
+  *--str = '0';
+#endif
+
+  if (negative)
+    *--str = '-';
+
+  return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str);
+}
+#endif /* CONFIG_WITH_MATH || CONFIG_WITH_NANOTS */
+
+#ifdef CONFIG_WITH_MATH
+
+/* Converts a string to an integer, causes an error if the format is invalid. */
+static math_int
+math_int_from_string (const char *str)
+{
+  const char *start;
+  unsigned base = 0;
+  int      negative = 0;
+  math_int num = 0;
+
+  /* strip spaces */
+  while (isspace (*str))
+    str++;
+  if (!*str)
+    {
+      error (NILF, _("bad number: empty\n"));
+      return 0;
+    }
+  start = str;
+
+  /* check for +/- */
+  while (*str == '+' || *str == '-' || isspace (*str))
+      if (*str++ == '-')
+        negative = !negative;
+
+  /* check for prefix - we do not accept octal numbers, sorry. */
+  if (*str == '0' && (str[1] == 'x' || str[1] == 'X'))
+    {
+      base = 16;
+      str += 2;
+    }
+  else
+    {
+      /* look for a hex digit, if not found treat it as decimal */
+      const char *p2 = str;
+      for ( ; *p2; p2++)
+        if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) )
+          {
+            base = 16;
+            break;
+          }
+      if (base == 0)
+        base = 10;
+    }
+
+  /* must have at least one digit! */
+  if (    !isascii (*str)
+      ||  !(base == 16 ? isxdigit (*str) : isdigit (*str)) )
+    {
+      error (NILF, _("bad number: '%s'\n"), start);
+      return 0;
+    }
+
+  /* convert it! */
+  while (*str && !isspace (*str))
+    {
+      int ch = *str++;
+      if (ch >= '0' && ch <= '9')
+        ch -= '0';
+      else if (base == 16 && ch >= 'a' && ch <= 'f')
+        ch -= 'a' - 10;
+      else if (base == 16 && ch >= 'A' && ch <= 'F')
+        ch -= 'A' - 10;
+      else
+        {
+          error (NILF, _("bad number: '%s' (base=%d, pos=%d)\n"), start, base, str - start);
+          return 0;
+        }
+      num *= base;
+      num += ch;
+    }
+
+  /* check trailing spaces. */
+  while (isspace (*str))
+    str++;
+  if (*str)
+    {
+      error (NILF, _("bad number: '%s'\n"), start);
+      return 0;
+    }
+
+  return negative ? -num : num;
+}
+
+/* Add two or more integer numbers. */
+static char *
+func_int_add (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num += math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+/* Subtract two or more integer numbers. */
+static char *
+func_int_sub (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num -= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+/* Multiply two or more integer numbers. */
+static char *
+func_int_mul (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num *= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+/* Divide an integer number by one or more divisors. */
+static char *
+func_int_div (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+  math_int divisor;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    {
+      divisor = math_int_from_string (argv[i]);
+      if (!divisor)
+        {
+          error (NILF, _("divide by zero ('%s')\n"), argv[i]);
+          return math_int_to_variable_buffer (o, 0);
+        }
+      num /= divisor;
+    }
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+
+/* Divide and return the remainder. */
+static char *
+func_int_mod (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+  math_int divisor;
+
+  num = math_int_from_string (argv[0]);
+  divisor = math_int_from_string (argv[1]);
+  if (!divisor)
+    {
+      error (NILF, _("divide by zero ('%s')\n"), argv[1]);
+      return math_int_to_variable_buffer (o, 0);
+    }
+  num %= divisor;
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+/* 2-complement. */
+static char *
+func_int_not (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+
+  num = math_int_from_string (argv[0]);
+  num = ~num;
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+/* Bitwise AND (two or more numbers). */
+static char *
+func_int_and (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num &= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+/* Bitwise OR (two or more numbers). */
+static char *
+func_int_or (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num |= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+/* Bitwise XOR (two or more numbers). */
+static char *
+func_int_xor (char *o, char **argv, const char *funcname UNUSED)
+{
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num ^= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
+}
+
+/* Compare two integer numbers. Returns make boolean (true="1"; false=""). */
+static char *
+func_int_cmp (char *o, char **argv, const char *funcname)
+{
+    math_int num1;
+    math_int num2;
+    int rc;
+
+    num1 = math_int_from_string (argv[0]);
+    num2 = math_int_from_string (argv[1]);
+
+    funcname += sizeof ("int-") - 1;
+    if (!strcmp (funcname, "eq"))
+      rc = num1 == num2;
+    else if (!strcmp (funcname, "ne"))
+      rc = num1 != num2;
+    else if (!strcmp (funcname, "gt"))
+      rc = num1 > num2;
+    else if (!strcmp (funcname, "ge"))
+      rc = num1 >= num2;
+    else if (!strcmp (funcname, "lt"))
+      rc = num1 < num2;
+    else /*if (!strcmp (funcname, "le"))*/
+      rc = num1 <= num2;
+
+    return variable_buffer_output (o, rc ? "1" : "", rc);
+}
+
+#endif /* CONFIG_WITH_MATH */
+
+#ifdef CONFIG_WITH_NANOTS
+/* Returns the current timestamp as nano seconds. The time
+   source is a high res monotone one if the platform provides
+   this (and we know about it).
+
+   Tip. Use this with int-sub to profile makefile reading
+        and similar. */
+static char *
+func_nanots (char *o, char **argv, const char *funcname)
+{
+  math_int ts;
+
+#if defined (WINDOWS32)
+  static int s_state = -1;
+  static LARGE_INTEGER s_freq;
+
+  if (s_state == -1)
+    s_state = QueryPerformanceFrequency (&s_freq);
+  if (s_state)
+    {
+      LARGE_INTEGER pc;
+      if (!QueryPerformanceCounter (&pc))
+        {
+          s_state = 0;
+          return func_nanots (o, argv, funcname);
+        }
+      ts = (math_int)((long double)pc.QuadPart / (long double)s_freq.QuadPart * 1000000000);
+    }
+  else
+    {
+      /* fall back to low resolution system time. */
+      LARGE_INTEGER bigint;
+      FILETIME ft = {0,0};
+      GetSystemTimeAsFileTime (&ft);
+      bigint.u.LowPart = ft.dwLowDateTime;
+      bigint.u.HighPart = ft.dwLowDateTime;
+      ts = bigint.QuadPart * 100;
+    }
+
+/* FIXME: Linux and others have the realtime clock_* api, detect and use it. */
+
+#elif HAVE_GETTIMEOFDAY
+  struct timeval tv;
+  if (!gettimeofday (&tv, NULL))
+    ts = (math_int)tv.tv_sec * 1000000000
+       + tv.tv_usec * 1000;
+  else
+    {
+      error (NILF, _("$(nanots): gettimeofday failed"));
+      ts = 0;
+    }
+
+#else
+# error "PORTME"
+#endif
+
+  return math_int_to_variable_buffer (o, ts);
+}
+#endif
+
+#ifdef CONFIG_WITH_OS2_LIBPATH
+/* Sets or gets the OS/2 libpath variables.
+
+   The first argument indicates which variable - BEGINLIBPATH,
+   ENDLIBPATH, LIBPATHSTRICT or LIBPATH.
+
+   The second indicates whether this is a get (not present) or
+   set (present) operation. When present it is the new value for
+   the variable. */
+static char *
+func_os2_libpath (char *o, char **argv, const char *funcname UNUSED)
+{
+  char buf[4096];
+  ULONG fVar;
+  APIRET rc;
+
+  /* translate variable name (first arg) */
+  if (!strcmp (argv[0], "BEGINLIBPATH"))
+    fVar = BEGIN_LIBPATH;
+  else if (!strcmp (argv[0], "ENDLIBPATH"))
+    fVar = END_LIBPATH;
+  else if (!strcmp (argv[0], "LIBPATHSTRICT"))
+    fVar = LIBPATHSTRICT;
+  else if (!strcmp (argv[0], "LIBPATH"))
+    fVar = 0;
+  else
+    {
+      error (NILF, _("$(libpath): unknown variable `%s'"), argv[0]);
+      return variable_buffer_output (o, "", 0);
+    }
+
+  if (!argv[1])
+    {
+      /* get the variable value. */
+      if (fVar != 0)
+        {
+          buf[0] = buf[1] = buf[2] = buf[3] = '\0';
+          rc = DosQueryExtLIBPATH (buf, fVar);
+        }
+      else
+        rc = DosQueryHeaderInfo (NULLHANDLE, 0, buf, sizeof(buf), QHINF_LIBPATH);
+      if (rc != NO_ERROR)
+        {
+          error (NILF, _("$(libpath): failed to query `%s', rc=%d"), argv[0], rc);
+          return variable_buffer_output (o, "", 0);
+        }
+      o = variable_buffer_output (o, buf, strlen (buf));
+    }
+  else
+    {
+      /* set the variable value. */
+      size_t len;
+      size_t len_max = sizeof (buf) < 2048 ? sizeof (buf) : 2048;
+      const char *val;
+      const char *end;
+
+      if (fVar == 0)
+        {
+          error (NILF, _("$(libpath): LIBPATH is read-only"));
+          return variable_buffer_output (o, "", 0);
+        }
+
+      /* strip leading and trailing spaces and check for max length. */
+      val = argv[1];
+      while (isspace (*val))
+        val++;
+      end = strchr (val, '\0');
+      while (end > val && isspace (end[-1]))
+        end--;
+
+      len = end - val;
+      if (len >= len_max)
+        {
+          error (NILF, _("$(libpath): The new `%s' value is too long (%d bytes, max %d)"),
+                 argv[0], len, len_max);
+          return variable_buffer_output (o, "", 0);
+        }
+
+      /* make a stripped copy in low memory and try set it. */
+      memcpy (buf, val, len);
+      buf[len] = '\0';
+      rc = DosSetExtLIBPATH (buf, fVar);
+      if (rc != NO_ERROR)
+        {
+          error (NILF, _("$(libpath): failed to set `%s' to `%s', rc=%d"), argv[0], buf, rc);
+          return variable_buffer_output (o, "", 0);
+        }
+
+      o = variable_buffer_output (o, "", 0);
+    }
+  return o;
+}
+#endif  /* CONFIG_WITH_OS2_LIBPATH */
+
+#ifdef CONFIG_WITH_MAKE_STATS
+/* Retrieve make statistics. */
+static char *
+func_make_stats (char *o, char **argv, const char *funcname UNUSED)
+{
+  char buf[512];
+  int len;
+
+  if (!argv[0] || (!argv[0][0] && !argv[1]))
+    {
+      len = sprintf (buf, "alloc-cur: %5lu %6luKB (/%3luMB)  hash: %5lu %2lu%%",
+                     make_stats_allocations,
+                     make_stats_allocated / 1024,
+                     make_stats_allocated_sum / (1024*1024),
+                     make_stats_ht_lookups,
+                     (make_stats_ht_collisions * 100) / make_stats_ht_lookups);
+      o = variable_buffer_output (o, buf, len);
+    }
+  else
+    {
+      /* selective */
+      int i;
+      for (i = 0; argv[i]; i++)
+        {
+          unsigned long val;
+          if (i != 0)
+            o = variable_buffer_output (o, " ", 1);
+          if (!strcmp(argv[i], "allocations"))
+            val = make_stats_allocations;
+          else if (!strcmp(argv[i], "allocated"))
+            val = make_stats_allocated;
+          else if (!strcmp(argv[i], "allocated_sum"))
+            val = make_stats_allocated_sum;
+          else if (!strcmp(argv[i], "ht_lookups"))
+            val = make_stats_ht_lookups;
+          else if (!strcmp(argv[i], "ht_collisions"))
+            val = make_stats_ht_collisions;
+          else if (!strcmp(argv[i], "ht_collisions_pct"))
+            val = (make_stats_ht_collisions * 100) / make_stats_ht_lookups;
+          else
+            {
+              o = variable_buffer_output (o, argv[i], strlen (argv[i]));
+              continue;
+            }
+
+          len = sprintf (buf, "%ld", val);
+          o = variable_buffer_output (o, buf, len);
+        }
+    }
+  return o;
+}
+#endif  /* CONFIG_WITH_MAKE_STATS */
+
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+/* Gets all the commands for a target, separated by newlines.
+
+   This is useful when creating and checking target dependencies since
+   it reduces the amount of work and the memory consuption. A new prefix
+   character '%' has been introduced for skipping certain lines, like
+   for instance the one calling this function and pushing to a dep file.
+   Blank lines are also skipped.
+
+   The commands function takes exactly one argument, which is the name of
+   the target which commands should be returned.
+
+   The commands-sc is identical to commands except that it uses a ';' to
+   separate the commands.
+
+   The commands-usr is similar to commands except that it takes a 2nd
+   argument that is used to separate the commands. */
+char *
+func_commands (char *o, char **argv, const char *funcname)
+{
+  struct file *file;
+  static int recursive = 0;
+
+  if (recursive)
+    {
+      error (reading_file, _("$(%s ) was invoked recursivly"), funcname);
+      return variable_buffer_output (o, "recursive", sizeof ("recursive") - 1);
+    }
+  if (*argv[0] == '\0')
+    {
+      error (reading_file, _("$(%s ) was invoked with an empty target name"), funcname);
+      return o;
+    }
+  recursive = 1;
+  
+  file = lookup_file (argv[0]);
+  if (file && file->cmds)
+    {
+      unsigned int i;
+      int cmd_sep_len;
+      struct commands *cmds = file->cmds;
+      const char *cmd_sep;
+
+      if (!strcmp (funcname, "commands"))
+        {
+          cmd_sep = "\n";
+          cmd_sep_len = 1;
+        }
+      else if (!strcmp (funcname, "commands-sc"))
+        {
+          cmd_sep = ";";
+          cmd_sep_len = 1;
+        }
+      else /*if (!strcmp (funcname, "commands-usr"))*/
+        {
+          cmd_sep = argv[1];
+          cmd_sep_len = strlen (cmd_sep);
+        }
+
+      initialize_file_variables (file, 1 /* reading - FIXME: we don't know? */);
+      set_file_variables (file);
+      chop_commands (cmds);
+
+      for (i = 0; i < cmds->ncommand_lines; i++)
+        {
+          char *p;
+          char *in, *out, *ref;
+
+          /* Skip it if it has a '%' prefix or is blank. */
+          if (cmds->lines_flags[i] & COMMAND_GETTER_SKIP_IT)
+            continue;
+          p = cmds->command_lines[i];
+          while (isblank ((unsigned char)*p))
+            p++;
+          if (*p == '\0')
+            continue;
+
+          /* --- copied from new_job() in job.c --- */
+
+          /* Collapse backslash-newline combinations that are inside variable
+             or function references.  These are left alone by the parser so
+             that they will appear in the echoing of commands (where they look
+             nice); and collapsed by construct_command_argv when it tokenizes.
+             But letting them survive inside function invocations loses because
+             we don't want the functions to see them as part of the text.  */
+
+          /* IN points to where in the line we are scanning.
+             OUT points to where in the line we are writing.
+             When we collapse a backslash-newline combination,
+             IN gets ahead of OUT.  */
+
+          in = out = p;
+          while ((ref = strchr (in, '$')) != 0)
+            {
+              ++ref;		/* Move past the $.  */
+
+              if (out != in)
+                /* Copy the text between the end of the last chunk
+                   we processed (where IN points) and the new chunk
+                   we are about to process (where REF points).  */
+                memmove (out, in, ref - in);
+
+              /* Move both pointers past the boring stuff.  */
+              out += ref - in;
+              in = ref;
+
+              if (*ref == '(' || *ref == '{')
+                {
+                  char openparen = *ref;
+                  char closeparen = openparen == '(' ? ')' : '}';
+                  int count;
+                  char *p;
+
+                  *out++ = *in++;	/* Copy OPENPAREN.  */
+                  /* IN now points past the opening paren or brace.
+                     Count parens or braces until it is matched.  */
+                  count = 0;
+                  while (*in != '\0')
+                    {
+                      if (*in == closeparen && --count < 0)
+                        break;
+                      else if (*in == '\\' && in[1] == '\n')
+                        {
+                          /* We have found a backslash-newline inside a
+                             variable or function reference.  Eat it and
+                             any following whitespace.  */
+
+                          int quoted = 0;
+                          for (p = in - 1; p > ref && *p == '\\'; --p)
+                            quoted = !quoted;
+
+                          if (quoted)
+                            /* There were two or more backslashes, so this is
+                               not really a continuation line.  We don't collapse
+                               the quoting backslashes here as is done in
+                               collapse_continuations, because the line will
+                               be collapsed again after expansion.  */
+                            *out++ = *in++;
+                          else
+                            {
+                              /* Skip the backslash, newline and
+                                 any following whitespace.  */
+                              in = next_token (in + 2);
+
+                              /* Discard any preceding whitespace that has
+                                 already been written to the output.  */
+                              while (out > ref
+                                     && isblank ((unsigned char)out[-1]))
+                                --out;
+
+                              /* Replace it all with a single space.  */
+                              *out++ = ' ';
+                            }
+                        }
+                      else
+                        {
+                          if (*in == openparen)
+                            ++count;
+
+                          *out++ = *in++;
+                        }
+                    }
+                }
+              /* Some of these can be amended ($< perhaps), but we're likely to be called while the
+                 dep expansion happens, so it would have to be on a hackish basis. sad... */
+              else if (*ref == '<' || *ref == '*' || *ref == '%' || *ref == '^' || *ref == '+')
+                error (reading_file, _("$(%s ) does not work reliably with $%c in all cases"), funcname, *ref);
+            }
+
+          /* There are no more references in this line to worry about.
+             Copy the remaining uninteresting text to the output.  */
+          if (out != in)
+            strcpy (out, in);
+
+          /* --- copied from new_job() in job.c --- */
+
+          /* Finally, expand the line.  */
+          if (i)
+            o = variable_buffer_output (o, cmd_sep, cmd_sep_len);
+          o = variable_expand_for_file_2 (o, cmds->command_lines[i], file);
+
+          /* Skip it if it has a '%' prefix or is blank. */
+          p = o;
+          while (isblank ((unsigned char)*o)
+              || *o == '@'
+              || *o == '-'
+              || *o == '+')
+            o++;
+          if (*o != '\0' && *o != '%')
+            o = strchr (o, '\0');
+          else if (i)
+            o = p - cmd_sep_len;
+          else
+            o = p;
+        } /* for each command line */
+    }
+  /* else FIXME: bitch about it? */
+
+  recursive = 0;
+  return o;
+}
+#endif  /* CONFIG_WITH_COMMANDS_FUNC */
+
+#ifdef KMK
+/* Useful when debugging kmk and/or makefiles. */
+char *
+func_breakpoint (char *o, char **argv, const char *funcname)
+{
+#ifdef _MSC_VER
+  __debugbreak();
+#elif defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386) \
+   || defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64)
+  __asm__ __volatile__ ("int3\n\t");
+#else
+  char *p = (char *)0;
+  *p = '\0';
+#endif
+  return o;
+}
+#endif /* KMK */
+
+
+/* Lookup table for builtin functions.
+
+   This doesn't have to be sorted; we use a straight lookup.  We might gain
+   some efficiency by moving most often used functions to the start of the
+   table.
+
+   If MAXIMUM_ARGS is 0, that means there is no maximum and all
+   comma-separated values are treated as arguments.
+
+   EXPAND_ARGS means that all arguments should be expanded before invocation.
+   Functions that do namespace tricks (foreach) don't automatically expand.  */
+
+static char *func_call (char *o, char **argv, const char *funcname);
+
+
+static struct function_table_entry function_table_init[] =
+{
+ /* Name/size */                    /* MIN MAX EXP? Function */
+  { STRING_SIZE_TUPLE("abspath"),       0,  1,  1,  func_abspath},
+  { STRING_SIZE_TUPLE("addprefix"),     2,  2,  1,  func_addsuffix_addprefix},
+  { STRING_SIZE_TUPLE("addsuffix"),     2,  2,  1,  func_addsuffix_addprefix},
+  { STRING_SIZE_TUPLE("basename"),      0,  1,  1,  func_basename_dir},
+  { STRING_SIZE_TUPLE("dir"),           0,  1,  1,  func_basename_dir},
+  { STRING_SIZE_TUPLE("notdir"),        0,  1,  1,  func_notdir_suffix},
+  { STRING_SIZE_TUPLE("subst"),         3,  3,  1,  func_subst},
+  { STRING_SIZE_TUPLE("suffix"),        0,  1,  1,  func_notdir_suffix},
+  { STRING_SIZE_TUPLE("filter"),        2,  2,  1,  func_filter_filterout},
+  { STRING_SIZE_TUPLE("filter-out"),    2,  2,  1,  func_filter_filterout},
+  { STRING_SIZE_TUPLE("findstring"),    2,  2,  1,  func_findstring},
+  { STRING_SIZE_TUPLE("firstword"),     0,  1,  1,  func_firstword},
+  { STRING_SIZE_TUPLE("flavor"),        0,  1,  1,  func_flavor},
+  { STRING_SIZE_TUPLE("join"),          2,  2,  1,  func_join},
+  { STRING_SIZE_TUPLE("lastword"),      0,  1,  1,  func_lastword},
+  { STRING_SIZE_TUPLE("patsubst"),      3,  3,  1,  func_patsubst},
+  { STRING_SIZE_TUPLE("realpath"),      0,  1,  1,  func_realpath},
+#ifdef CONFIG_WITH_RSORT
+  { STRING_SIZE_TUPLE("rsort"),         0,  1,  1,  func_sort},
+#endif
+  { STRING_SIZE_TUPLE("shell"),         0,  1,  1,  func_shell},
+  { STRING_SIZE_TUPLE("sort"),          0,  1,  1,  func_sort},
+  { STRING_SIZE_TUPLE("strip"),         0,  1,  1,  func_strip},
+  { STRING_SIZE_TUPLE("wildcard"),      0,  1,  1,  func_wildcard},
+  { STRING_SIZE_TUPLE("word"),          2,  2,  1,  func_word},
+  { STRING_SIZE_TUPLE("wordlist"),      3,  3,  1,  func_wordlist},
+  { STRING_SIZE_TUPLE("words"),         0,  1,  1,  func_words},
+  { STRING_SIZE_TUPLE("origin"),        0,  1,  1,  func_origin},
+  { STRING_SIZE_TUPLE("foreach"),       3,  3,  0,  func_foreach},
+  { STRING_SIZE_TUPLE("call"),          1,  0,  1,  func_call},
+  { STRING_SIZE_TUPLE("info"),          0,  1,  1,  func_error},
+  { STRING_SIZE_TUPLE("error"),         0,  1,  1,  func_error},
+  { STRING_SIZE_TUPLE("warning"),       0,  1,  1,  func_error},
+  { STRING_SIZE_TUPLE("if"),            2,  3,  0,  func_if},
+  { STRING_SIZE_TUPLE("or"),            1,  0,  0,  func_or},
+  { STRING_SIZE_TUPLE("and"),           1,  0,  0,  func_and},
+  { STRING_SIZE_TUPLE("value"),         0,  1,  1,  func_value},
+  { STRING_SIZE_TUPLE("eval"),          0,  1,  1,  func_eval},
+#ifdef CONFIG_WITH_EVALPLUS
+  { STRING_SIZE_TUPLE("evalctx"),       0,  1,  1,  func_evalctx},
+  { STRING_SIZE_TUPLE("evalval"),       1,  1,  1,  func_evalval},
+  { STRING_SIZE_TUPLE("evalvalctx"),    1,  1,  1,  func_evalval},
+  { STRING_SIZE_TUPLE("evalcall"),      1,  0,  1,  func_call},
+  { STRING_SIZE_TUPLE("evalcall2"),     1,  0,  1,  func_call},
+#endif
+#ifdef EXPERIMENTAL
+  { STRING_SIZE_TUPLE("eq"),            2,  2,  1,  func_eq},
+  { STRING_SIZE_TUPLE("not"),           0,  1,  1,  func_not},
+#endif
+#ifdef CONFIG_WITH_DEFINED
+  { STRING_SIZE_TUPLE("defined"),       1,  1,  1,  func_defined},
+#endif 
+#ifdef CONFIG_WITH_TOUPPER_TOLOWER
+  { STRING_SIZE_TUPLE("toupper"),       0,  1,  1,  func_toupper_tolower},
+  { STRING_SIZE_TUPLE("tolower"),       0,  1,  1,  func_toupper_tolower},
+#endif
+#ifdef CONFIG_WITH_ABSPATHEX
+  { STRING_SIZE_TUPLE("abspathex"),     0,  2,  1,  func_abspathex},
+#endif
+#ifdef CONFIG_WITH_XARGS
+  { STRING_SIZE_TUPLE("xargs"),         2,  0,  1,  func_xargs},
+#endif
+#if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE)
+  { STRING_SIZE_TUPLE("comp-vars"),     3,  3,  1,  func_comp_vars},
+  { STRING_SIZE_TUPLE("comp-cmds"),     3,  3,  1,  func_comp_vars},
+  { STRING_SIZE_TUPLE("comp-cmds-ex"),  3,  3,  1,  func_comp_cmds_ex},
+#endif
+#ifdef CONFIG_WITH_DATE
+  { STRING_SIZE_TUPLE("date"),          0,  1,  1,  func_date},
+  { STRING_SIZE_TUPLE("date-utc"),      0,  3,  1,  func_date},
+#endif
+#ifdef CONFIG_WITH_FILE_SIZE
+  { STRING_SIZE_TUPLE("file-size"),     1,  1,  1,  func_file_size},
+#endif
+#ifdef CONFIG_WITH_WHICH
+  { STRING_SIZE_TUPLE("which"),         0,  0,  1,  func_which},
+#endif
+#ifdef CONFIG_WITH_IF_CONDITIONALS
+  { STRING_SIZE_TUPLE("expr"),          1,  1,  0,  func_expr},
+  { STRING_SIZE_TUPLE("if-expr"),       2,  3,  0,  func_if_expr},
+#endif
+#ifdef CONFIG_WITH_STACK
+  { STRING_SIZE_TUPLE("stack-push"),    2,  2,  1,  func_stack_push},
+  { STRING_SIZE_TUPLE("stack-pop"),     1,  1,  1,  func_stack_pop_top},
+  { STRING_SIZE_TUPLE("stack-popv"),    1,  1,  1,  func_stack_pop_top},
+  { STRING_SIZE_TUPLE("stack-top"),     1,  1,  1,  func_stack_pop_top},
+#endif
+#ifdef CONFIG_WITH_MATH
+  { STRING_SIZE_TUPLE("int-add"),       2,  0,  1,  func_int_add},
+  { STRING_SIZE_TUPLE("int-sub"),       2,  0,  1,  func_int_sub},
+  { STRING_SIZE_TUPLE("int-mul"),       2,  0,  1,  func_int_mul},
+  { STRING_SIZE_TUPLE("int-div"),       2,  0,  1,  func_int_div},
+  { STRING_SIZE_TUPLE("int-mod"),       2,  2,  1,  func_int_mod},
+  { STRING_SIZE_TUPLE("int-not"),       1,  1,  1,  func_int_not},
+  { STRING_SIZE_TUPLE("int-and"),       2,  0,  1,  func_int_and},
+  { STRING_SIZE_TUPLE("int-or"),        2,  0,  1,  func_int_or},
+  { STRING_SIZE_TUPLE("int-xor"),       2,  0,  1,  func_int_xor},
+  { STRING_SIZE_TUPLE("int-eq"),        2,  2,  1,  func_int_cmp},
+  { STRING_SIZE_TUPLE("int-ne"),        2,  2,  1,  func_int_cmp},
+  { STRING_SIZE_TUPLE("int-gt"),        2,  2,  1,  func_int_cmp},
+  { STRING_SIZE_TUPLE("int-ge"),        2,  2,  1,  func_int_cmp},
+  { STRING_SIZE_TUPLE("int-lt"),        2,  2,  1,  func_int_cmp},
+  { STRING_SIZE_TUPLE("int-le"),        2,  2,  1,  func_int_cmp},
+#endif
+#ifdef CONFIG_WITH_NANOTS
+  { STRING_SIZE_TUPLE("nanots"),        0,  0,  0,  func_nanots},
+#endif
+#ifdef CONFIG_WITH_OS2_LIBPATH
+  { STRING_SIZE_TUPLE("libpath"),       1,  2,  1,  func_os2_libpath},
+#endif
+#ifdef CONFIG_WITH_MAKE_STATS
+  { STRING_SIZE_TUPLE("make-stats"),    0,  0,  0,  func_make_stats},
+#endif
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+  { STRING_SIZE_TUPLE("commands"),      1,  1,  1,  func_commands},
+  { STRING_SIZE_TUPLE("commands-sc"),   1,  1,  1,  func_commands},
+  { STRING_SIZE_TUPLE("commands-usr"),  2,  2,  1,  func_commands},
+#endif
+#ifdef KMK_HELPERS
+  { STRING_SIZE_TUPLE("kb-src-tool"),   1,  1,  0,  func_kbuild_source_tool},
+  { STRING_SIZE_TUPLE("kb-obj-base"),   1,  1,  0,  func_kbuild_object_base},
+  { STRING_SIZE_TUPLE("kb-obj-suff"),   1,  1,  0,  func_kbuild_object_suffix},
+  { STRING_SIZE_TUPLE("kb-src-prop"),   3,  4,  0,  func_kbuild_source_prop},
+  { STRING_SIZE_TUPLE("kb-src-one"),    0,  1,  0,  func_kbuild_source_one},
+#endif
+#ifdef KMK
+  { STRING_SIZE_TUPLE("breakpoint"),    0,  0,  0,  func_breakpoint},
+#endif
+};
+
+#define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
+
+
+
+/* These must come after the definition of function_table.  */
+
+static char *
+expand_builtin_function (char *o, int argc, char **argv,
+                         const struct function_table_entry *entry_p)
+{
+  if (argc < (int)entry_p->minimum_args)
+    fatal (*expanding_var,
+           _("insufficient number of arguments (%d) to function `%s'"),
+           argc, entry_p->name);
+
+  /* I suppose technically some function could do something with no
+     arguments, but so far none do, so just test it for all functions here
+     rather than in each one.  We can change it later if necessary.  */
+
+  if (!argc)
+    return o;
+
+  if (!entry_p->func_ptr)
+    fatal (*expanding_var,
+           _("unimplemented on this platform: function `%s'"), entry_p->name);
+
+  return entry_p->func_ptr (o, argv, entry_p->name);
+}
+
+/* Check for a function invocation in *STRINGP.  *STRINGP points at the
+   opening ( or { and is not null-terminated.  If a function invocation
+   is found, expand it into the buffer at *OP, updating *OP, incrementing
+   *STRINGP past the reference and returning nonzero.  If not, return zero.  */
+
+static int
+handle_function2 (const struct function_table_entry *entry_p, char **op, const char **stringp) /* bird split it up. */
+{
+  char openparen = (*stringp)[0];
+  char closeparen = openparen == '(' ? ')' : '}';
+  const char *beg;
+  const char *end;
+  int count = 0;
+  char *abeg = NULL;
+  char **argv, **argvp;
+  int nargs;
+
+  beg = *stringp + 1;
+
+  /* We found a builtin function.  Find the beginning of its arguments (skip
+     whitespace after the name).  */
+
+  beg = next_token (beg + entry_p->len);
+
+  /* Find the end of the function invocation, counting nested use of
+     whichever kind of parens we use.  Since we're looking, count commas
+     to get a rough estimate of how many arguments we might have.  The
+     count might be high, but it'll never be low.  */
+
+  for (nargs=1, end=beg; *end != '\0'; ++end)
+    if (*end == ',')
+      ++nargs;
+    else if (*end == openparen)
+      ++count;
+    else if (*end == closeparen && --count < 0)
+      break;
+
+  if (count >= 0)
+    fatal (*expanding_var,
+	   _("unterminated call to function `%s': missing `%c'"),
+	   entry_p->name, closeparen);
+
+  *stringp = end;
+
+  /* Get some memory to store the arg pointers.  */
+  argvp = argv = alloca (sizeof (char *) * (nargs + 2));
+
+  /* Chop the string into arguments, then a nul.  As soon as we hit
+     MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
+     last argument.
+
+     If we're expanding, store pointers to the expansion of each one.  If
+     not, make a duplicate of the string and point into that, nul-terminating
+     each argument.  */
+
+  if (entry_p->expand_args)
+    {
+      const char *p;
+      for (p=beg, nargs=0; p <= end; ++argvp)
+        {
+          const char *next;
+
+          ++nargs;
+
+          if (nargs == entry_p->maximum_args
+              || (! (next = find_next_argument (openparen, closeparen, p, end))))
+            next = end;
+
+          *argvp = expand_argument (p, next);
+          p = next + 1;
+        }
+    }
+  else
+    {
+      int len = end - beg;
+      char *p, *aend;
+
+      abeg = xmalloc (len+1);
+      memcpy (abeg, beg, len);
+      abeg[len] = '\0';
+      aend = abeg + len;
+
+      for (p=abeg, nargs=0; p <= aend; ++argvp)
+        {
+          char *next;
+
+          ++nargs;
+
+          if (nargs == entry_p->maximum_args
+              || (! (next = find_next_argument (openparen, closeparen, p, aend))))
+            next = aend;
+
+          *argvp = p;
+          *next = '\0';
+          p = next + 1;
+        }
+    }
+  *argvp = NULL;
+
+  /* Finally!  Run the function...  */
+  *op = expand_builtin_function (*op, nargs, argv, entry_p);
+
+  /* Free memory.  */
+  if (entry_p->expand_args)
+    for (argvp=argv; *argvp != 0; ++argvp)
+      free (*argvp);
+  if (abeg)
+    free (abeg);
+
+  return 1;
+}
+
+int
+handle_function (char **op, const char **stringp) /* bird split it up */
+{
+  const struct function_table_entry *entry_p = lookup_function (*stringp + 1);
+  if (!entry_p)
+    return 0;
+  return handle_function2 (entry_p, op, stringp);
+}
+
+
+
+/* User-defined functions.  Expand the first argument as either a builtin
+   function or a make variable, in the context of the rest of the arguments
+   assigned to $1, $2, ... $N.  $0 is the name of the function.  */
+
+static char *
+func_call (char *o, char **argv, const char *funcname UNUSED)
+{
+  static int max_args = 0;
+  char *fname;
+  char *cp;
+  char *body;
+  int flen;
+  int i;
+  int saved_args;
+  const struct function_table_entry *entry_p;
+  struct variable *v;
+#ifdef CONFIG_WITH_EVALPLUS
+  char *buf;
+  unsigned int len;
+#endif
+
+  /* There is no way to define a variable with a space in the name, so strip
+     leading and trailing whitespace as a favor to the user.  */
+  fname = argv[0];
+  while (*fname != '\0' && isspace ((unsigned char)*fname))
+    ++fname;
+
+  cp = fname + strlen (fname) - 1;
+  while (cp > fname && isspace ((unsigned char)*cp))
+    --cp;
+  cp[1] = '\0';
+
+  /* Calling nothing is a no-op */
+  if (*fname == '\0')
+    return o;
+
+  /* Are we invoking a builtin function?  */
+
+  entry_p = lookup_function (fname);
+  if (entry_p)
+    {
+      /* How many arguments do we have?  */
+      for (i=0; argv[i+1]; ++i)
+        ;
+      return expand_builtin_function (o, i, argv+1, entry_p);
+    }
+
+  /* Not a builtin, so the first argument is the name of a variable to be
+     expanded and interpreted as a function.  Find it.  */
+  flen = strlen (fname);
+
+  v = lookup_variable (fname, flen);
+
+  if (v == 0)
+    warn_undefined (fname, flen);
+
+  if (v == 0 || *v->value == '\0')
+    return o;
+
+  body = alloca (flen + 4);
+  body[0] = '$';
+  body[1] = '(';
+  memcpy (body + 2, fname, flen);
+  body[flen+2] = ')';
+  body[flen+3] = '\0';
+
+  /* Set up arguments $(1) .. $(N).  $(0) is the function name.  */
+
+  push_new_variable_scope ();
+
+  for (i=0; *argv; ++i, ++argv)
+    {
+      char num[11];
+
+      sprintf (num, "%d", i);
+      define_variable (num, strlen (num), *argv, o_automatic, 0);
+    }
+
+  /* If the number of arguments we have is < max_args, it means we're inside
+     a recursive invocation of $(call ...).  Fill in the remaining arguments
+     in the new scope with the empty value, to hide them from this
+     invocation.  */
+
+  for (; i < max_args; ++i)
+    {
+      char num[11];
+
+      sprintf (num, "%d", i);
+      define_variable (num, strlen (num), "", o_automatic, 0);
+    }
+
+  saved_args = max_args;
+  max_args = i;
+
+#ifdef CONFIG_WITH_EVALPLUS
+  if (!strcmp (funcname, "call"))
+    {
+#endif
+      /* Expand the body in the context of the arguments, adding the result to
+         the variable buffer.  */
+
+      v->exp_count = EXP_COUNT_MAX;
+      o = variable_expand_string (o, body, flen+3);
+      v->exp_count = 0;
+
+      o += strlen (o);
+#ifdef CONFIG_WITH_EVALPLUS
+    }
+  else
+    {
+      const struct floc *reading_file_saved = reading_file;
+
+      if (!strcmp (funcname, "evalcall"))
+        {
+          /* Evaluate the variable value without expanding it. We
+             need a copy since eval_buffer is destructive.  */
+
+          size_t off = o - variable_buffer;
+          o = variable_buffer_output (o, v->value, v->value_length + 1);
+          o = variable_buffer + off;
+          if (v->fileinfo.filenm)
+            reading_file = &v->fileinfo;
+        }
+      else
+        {
+          /* Expand the body first and then evaluate the output. */
+
+          v->exp_count = EXP_COUNT_MAX;
+          o = variable_expand_string (o, body, flen+3);
+          v->exp_count = 0;
+        }
+
+      install_variable_buffer (&buf, &len);
+      eval_buffer (o);
+      restore_variable_buffer (buf, len);
+      reading_file = reading_file_saved;
+    }
+#endif /* CONFIG_WITH_EVALPLUS */
+
+  max_args = saved_args;
+
+  pop_variable_scope ();
+
+  return o;
+}
+
+void
+hash_init_function_table (void)
+{
+  hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2,
+	     function_table_entry_hash_1, function_table_entry_hash_2,
+	     function_table_entry_hash_cmp);
+  hash_load (&function_table, function_table_init,
+	     FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry));
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+  {
+    unsigned i;
+    for (i = 0; i < FUNCTION_TABLE_ENTRIES; i++)
+        assert (function_table_init[i].len <= MAX_FUNCTION_LENGTH);
+  }
+#endif
+}
Index: /tags/kBuild-0.1.4/src/kmk/getloadavg.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/getloadavg.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/getloadavg.c	(revision 1780)
@@ -0,0 +1,1033 @@
+/* Get the system load averages.
+Copyright (C) 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free
+Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* Compile-time symbols that this file uses:
+
+   HAVE_PSTAT_GETDYNAMIC	Define this if your system has the
+                                pstat_getdynamic function.  I think it
+				is unique to HPUX9.  The best way to get the
+				definition is through the AC_FUNC_GETLOADAVG
+				macro that comes with autoconf 2.13 or newer.
+				If that isn't an option, then just put
+				AC_CHECK_FUNCS(pstat_getdynamic) in your
+				configure.in file.
+   FIXUP_KERNEL_SYMBOL_ADDR()	Adjust address in returned struct nlist.
+   KERNEL_FILE			Pathname of the kernel to nlist.
+   LDAV_CVT()			Scale the load average from the kernel.
+				Returns a double.
+   LDAV_SYMBOL			Name of kernel symbol giving load average.
+   LOAD_AVE_TYPE		Type of the load average array in the kernel.
+				Must be defined unless one of
+				apollo, DGUX, NeXT, or UMAX is defined;
+                                or we have libkstat;
+				otherwise, no load average is available.
+   NLIST_STRUCT			Include nlist.h, not a.out.h, and
+				the nlist n_name element is a pointer,
+				not an array.
+   HAVE_STRUCT_NLIST_N_UN_N_NAME struct nlist has an n_un member, not n_name.
+   LINUX_LDAV_FILE		[__linux__]: File containing load averages.
+
+   Specific system predefines this file uses, aside from setting
+   default values if not emacs:
+
+   apollo
+   BSD				Real BSD, not just BSD-like.
+   convex
+   DGUX
+   eunice			UNIX emulator under VMS.
+   hpux
+   __MSDOS__			No-op for MSDOS.
+   NeXT
+   sgi
+   sequent			Sequent Dynix 3.x.x (BSD)
+   _SEQUENT_			Sequent DYNIX/ptx 1.x.x (SYSV)
+   sony_news                    NEWS-OS (works at least for 4.1C)
+   UMAX
+   UMAX4_3
+   VMS
+   WINDOWS32			No-op for Windows95/NT.
+   __linux__			Linux: assumes /proc filesystem mounted.
+   				Support from Michael K. Johnson.
+   __NetBSD__			NetBSD: assumes /kern filesystem mounted.
+
+   In addition, to avoid nesting many #ifdefs, we internally set
+   LDAV_DONE to indicate that the load average has been computed.
+
+   We also #define LDAV_PRIVILEGED if a program will require
+   special installation to be able to call getloadavg.  */
+
+/* This should always be first.  */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+/* Both the Emacs and non-Emacs sections want this.  Some
+   configuration files' definitions for the LOAD_AVE_CVT macro (like
+   sparc.h's) use macros like FSCALE, defined here.  */
+#if defined (unix) || defined (__unix)
+# include <sys/param.h>
+#endif
+
+
+/* Exclude all the code except the test program at the end
+   if the system has its own `getloadavg' function.
+
+   The declaration of `errno' is needed by the test program
+   as well as the function itself, so it comes first.  */
+
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+#if HAVE_LOCALE_H
+# include <locale.h>
+#endif
+#if !HAVE_SETLOCALE
+# define setlocale(Category, Locale) /* empty */
+#endif
+
+#ifndef HAVE_GETLOADAVG
+
+
+/* The existing Emacs configuration files define a macro called
+   LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and
+   returns the load average multiplied by 100.  What we actually want
+   is a macro called LDAV_CVT, which returns the load average as an
+   unmultiplied double.
+
+   For backwards compatibility, we'll define LDAV_CVT in terms of
+   LOAD_AVE_CVT, but future machine config files should just define
+   LDAV_CVT directly.  */
+
+# if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT)
+#  define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0)
+# endif
+
+# if !defined (BSD) && defined (ultrix)
+/* Ultrix behaves like BSD on Vaxen.  */
+#  define BSD
+# endif
+
+# ifdef NeXT
+/* NeXT in the 2.{0,1,2} releases defines BSD in <sys/param.h>, which
+   conflicts with the definition understood in this file, that this
+   really is BSD. */
+#  undef BSD
+
+/* NeXT defines FSCALE in <sys/param.h>.  However, we take FSCALE being
+   defined to mean that the nlist method should be used, which is not true.  */
+#  undef FSCALE
+# endif
+
+/* Same issues as for NeXT apply to the HURD-based GNU system.  */
+# ifdef __GNU__
+#  undef BSD
+#  undef FSCALE
+# endif /* __GNU__ */
+
+/* Set values that are different from the defaults, which are
+   set a little farther down with #ifndef.  */
+
+
+/* Some shorthands.  */
+
+# if defined (HPUX) && !defined (hpux)
+#  define hpux
+# endif
+
+# if defined (__hpux) && !defined (hpux)
+#  define hpux
+# endif
+
+# if defined (__sun) && !defined (sun)
+#  define sun
+# endif
+
+# if defined(hp300) && !defined(hpux)
+#  define MORE_BSD
+# endif
+
+# if defined(ultrix) && defined(mips)
+#  define decstation
+# endif
+
+# if defined (__SVR4) && !defined (SVR4)
+#  define SVR4
+# endif
+
+# if (defined(sun) && defined(SVR4)) || defined (SOLARIS2)
+#  define SUNOS_5
+# endif
+
+# if defined (__osf__) && (defined (__alpha) || defined (__alpha__))
+#  define OSF_ALPHA
+#  include <sys/mbuf.h>
+#  include <sys/socket.h>
+#  include <net/route.h>
+#  include <sys/table.h>
+# endif
+
+# if defined (__osf__) && (defined (mips) || defined (__mips__))
+#  define OSF_MIPS
+#  include <sys/table.h>
+# endif
+
+/* UTek's /bin/cc on the 4300 has no architecture specific cpp define by
+   default, but _MACH_IND_SYS_TYPES is defined in <sys/types.h>.  Combine
+   that with a couple of other things and we'll have a unique match.  */
+# if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES)
+#  define tek4300			/* Define by emacs, but not by other users.  */
+# endif
+
+/* AC_FUNC_GETLOADAVG thinks QNX is SVR4, but it isn't. */
+# if defined(__QNX__)
+#  undef SVR4
+# endif
+
+/* VAX C can't handle multi-line #ifs, or lines longer than 256 chars.  */
+# ifndef LOAD_AVE_TYPE
+
+#  ifdef MORE_BSD
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef sun
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef decstation
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef _SEQUENT_
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef sgi
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef SVR4
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef sony_news
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef sequent
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef OSF_ALPHA
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  if defined (ardent) && defined (titan)
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef tek4300
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  if defined(alliant) && defined(i860) /* Alliant FX/2800 */
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef _AIX
+#   define LOAD_AVE_TYPE long
+#  endif
+
+#  ifdef convex
+#   define LOAD_AVE_TYPE double
+#   ifndef LDAV_CVT
+#    define LDAV_CVT(n) (n)
+#   endif
+#  endif
+
+# endif /* No LOAD_AVE_TYPE.  */
+
+# ifdef OSF_ALPHA
+/* <sys/param.h> defines an incorrect value for FSCALE on Alpha OSF/1,
+   according to ghazi@noc.rutgers.edu.  */
+#  undef FSCALE
+#  define FSCALE 1024.0
+# endif
+
+# if defined(alliant) && defined(i860) /* Alliant FX/2800 */
+/* <sys/param.h> defines an incorrect value for FSCALE on an
+   Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu.  */
+#  undef FSCALE
+#  define FSCALE 100.0
+# endif
+
+
+# ifndef	FSCALE
+
+/* SunOS and some others define FSCALE in sys/param.h.  */
+
+#  ifdef MORE_BSD
+#   define FSCALE 2048.0
+#  endif
+
+#  if defined(MIPS) || defined(SVR4) || defined(decstation)
+#   define FSCALE 256
+#  endif
+
+#  if defined (sgi) || defined (sequent)
+/* Sometimes both MIPS and sgi are defined, so FSCALE was just defined
+   above under #ifdef MIPS.  But we want the sgi value.  */
+#   undef FSCALE
+#   define	FSCALE 1000.0
+#  endif
+
+#  if defined (ardent) && defined (titan)
+#   define FSCALE 65536.0
+#  endif
+
+#  ifdef tek4300
+#   define FSCALE 100.0
+#  endif
+
+#  ifdef _AIX
+#   define FSCALE 65536.0
+#  endif
+
+# endif	/* Not FSCALE.  */
+
+# if !defined (LDAV_CVT) && defined (FSCALE)
+#  define	LDAV_CVT(n) (((double) (n)) / FSCALE)
+# endif
+
+
+# if defined(sgi) || (defined(mips) && !defined(BSD))
+#  define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31))
+# endif
+
+
+# if !defined (KERNEL_FILE) && defined (sequent)
+#  define KERNEL_FILE "/dynix"
+# endif
+
+# if !defined (KERNEL_FILE) && defined (hpux)
+#  define KERNEL_FILE "/hp-ux"
+# endif
+
+# if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || (defined (ardent) && defined (titan)))
+#  define KERNEL_FILE "/unix"
+# endif
+
+
+# if !defined (LDAV_SYMBOL) && defined (alliant)
+#  define LDAV_SYMBOL "_Loadavg"
+# endif
+
+# if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)) || defined (_AIX))
+#  define LDAV_SYMBOL "avenrun"
+# endif
+
+# ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+# endif
+
+# include <stdio.h>
+
+/* LOAD_AVE_TYPE should only get defined if we're going to use the
+   nlist method.  */
+# if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL)) && !defined(__riscos__)
+#  define LOAD_AVE_TYPE double
+# endif
+
+# ifdef LOAD_AVE_TYPE
+
+#  ifndef VMS
+#   ifndef __linux__
+#    ifdef HAVE_NLIST_H
+#     include <nlist.h>
+#    else
+#     include <a.out.h>
+#    endif
+
+#    ifdef SUNOS_5
+#     include <fcntl.h>
+#     include <kvm.h>
+#     include <kstat.h>
+#    endif
+
+#    if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
+#     include <sys/pstat.h>
+#    endif
+
+#    ifndef KERNEL_FILE
+#     define KERNEL_FILE "/vmunix"
+#    endif /* KERNEL_FILE */
+
+#    ifndef LDAV_SYMBOL
+#     define LDAV_SYMBOL "_avenrun"
+#    endif /* LDAV_SYMBOL */
+#   endif /* __linux__ */
+
+#  else /* VMS */
+
+#   ifndef eunice
+#    include <iodef.h>
+#    include <descrip.h>
+#   else /* eunice */
+#    include <vms/iodef.h>
+#   endif /* eunice */
+#  endif /* VMS */
+
+#  ifndef LDAV_CVT
+#   define LDAV_CVT(n) ((double) (n))
+#  endif /* !LDAV_CVT */
+
+# endif /* LOAD_AVE_TYPE */
+
+# if defined(__GNU__) && !defined (NeXT)
+/* Note that NeXT Openstep defines __GNU__ even though it should not.  */
+/* GNU system acts much like NeXT, for load average purposes,
+   but not exactly.  */
+#  define NeXT
+#  define host_self mach_host_self
+# endif
+
+# ifdef NeXT
+#  ifdef HAVE_MACH_MACH_H
+#   include <mach/mach.h>
+#  else
+#   include <mach.h>
+#  endif
+# endif /* NeXT */
+
+# ifdef sgi
+#  include <sys/sysmp.h>
+# endif /* sgi */
+
+# ifdef UMAX
+#  include <stdio.h>
+#  include <signal.h>
+#  include <sys/time.h>
+#  include <sys/wait.h>
+#  include <sys/syscall.h>
+
+#  ifdef UMAX_43
+#   include <machine/cpu.h>
+#   include <inq_stats/statistics.h>
+#   include <inq_stats/sysstats.h>
+#   include <inq_stats/cpustats.h>
+#   include <inq_stats/procstats.h>
+#  else /* Not UMAX_43.  */
+#   include <sys/sysdefs.h>
+#   include <sys/statistics.h>
+#   include <sys/sysstats.h>
+#   include <sys/cpudefs.h>
+#   include <sys/cpustats.h>
+#   include <sys/procstats.h>
+#  endif /* Not UMAX_43.  */
+# endif /* UMAX */
+
+# ifdef DGUX
+#  include <sys/dg_sys_info.h>
+# endif
+
+# if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION)
+#  include <fcntl.h>
+# else
+#  include <sys/file.h>
+# endif
+
+
+
+/* Avoid static vars inside a function since in HPUX they dump as pure.  */
+
+# ifdef NeXT
+static processor_set_t default_set;
+static int getloadavg_initialized;
+# endif /* NeXT */
+
+# ifdef UMAX
+static unsigned int cpus = 0;
+static unsigned int samples;
+# endif /* UMAX */
+
+# ifdef DGUX
+static struct dg_sys_info_load_info load_info;	/* what-a-mouthful! */
+# endif /* DGUX */
+
+#if !defined(HAVE_LIBKSTAT) && defined(LOAD_AVE_TYPE)
+/* File descriptor open to /dev/kmem or VMS load ave driver.  */
+static int channel;
+/* Nonzero iff channel is valid.  */
+static int getloadavg_initialized;
+/* Offset in kmem to seek to read load average, or 0 means invalid.  */
+static long offset;
+
+#if !defined(VMS) && !defined(sgi) && !defined(__linux__)
+static struct nlist nl[2];
+#endif /* Not VMS or sgi */
+
+#ifdef SUNOS_5
+static kvm_t *kd;
+#endif /* SUNOS_5 */
+
+#endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */
+
+
+/* Put the 1 minute, 5 minute and 15 minute load averages
+   into the first NELEM elements of LOADAVG.
+   Return the number written (never more than 3, but may be less than NELEM),
+   or -1 if an error occurred.  */
+
+int
+getloadavg (double loadavg[], int nelem)
+{
+  int elem = 0;			/* Return value.  */
+
+# ifdef NO_GET_LOAD_AVG
+#  define LDAV_DONE
+  /* Set errno to zero to indicate that there was no particular error;
+     this function just can't work at all on this system.  */
+  errno = 0;
+  elem = -1;
+# endif
+
+# if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT)
+/* Use libkstat because we don't have to be root.  */
+#  define LDAV_DONE
+  kstat_ctl_t *kc;
+  kstat_t *ksp;
+  kstat_named_t *kn;
+
+  kc = kstat_open ();
+  if (kc == 0)
+    return -1;
+  ksp = kstat_lookup (kc, "unix", 0, "system_misc");
+  if (ksp == 0 )
+    return -1;
+  if (kstat_read (kc, ksp, 0) == -1)
+    return -1;
+
+
+  kn = kstat_data_lookup (ksp, "avenrun_1min");
+  if (kn == 0)
+    {
+      /* Return -1 if no load average information is available.  */
+      nelem = 0;
+      elem = -1;
+    }
+
+  if (nelem >= 1)
+    loadavg[elem++] = (double) kn->value.ul/FSCALE;
+
+  if (nelem >= 2)
+    {
+      kn = kstat_data_lookup (ksp, "avenrun_5min");
+      if (kn != 0)
+	{
+	  loadavg[elem++] = (double) kn->value.ul/FSCALE;
+
+	  if (nelem >= 3)
+	    {
+	      kn = kstat_data_lookup (ksp, "avenrun_15min");
+	      if (kn != 0)
+		loadavg[elem++] = (double) kn->value.ul/FSCALE;
+	    }
+	}
+    }
+
+  kstat_close (kc);
+# endif /* HAVE_LIBKSTAT */
+
+# if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
+/* Use pstat_getdynamic() because we don't have to be root.  */
+#  define LDAV_DONE
+#  undef LOAD_AVE_TYPE
+
+  struct pst_dynamic dyn_info;
+  if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0)
+    return -1;
+  if (nelem > 0)
+    loadavg[elem++] = dyn_info.psd_avg_1_min;
+  if (nelem > 1)
+    loadavg[elem++] = dyn_info.psd_avg_5_min;
+  if (nelem > 2)
+    loadavg[elem++] = dyn_info.psd_avg_15_min;
+
+# endif /* hpux && HAVE_PSTAT_GETDYNAMIC */
+
+# if !defined (LDAV_DONE) && defined (__linux__)
+#  define LDAV_DONE
+#  undef LOAD_AVE_TYPE
+
+#  ifndef LINUX_LDAV_FILE
+#   define LINUX_LDAV_FILE "/proc/loadavg"
+#  endif
+
+  char ldavgbuf[40];
+  double load_ave[3];
+  int fd, count;
+
+  fd = open (LINUX_LDAV_FILE, O_RDONLY);
+  if (fd == -1)
+    return -1;
+  count = read (fd, ldavgbuf, 40);
+  (void) close (fd);
+  if (count <= 0)
+    return -1;
+
+  /* The following sscanf must use the C locale.  */
+  setlocale (LC_NUMERIC, "C");
+  count = sscanf (ldavgbuf, "%lf %lf %lf",
+		  &load_ave[0], &load_ave[1], &load_ave[2]);
+  setlocale (LC_NUMERIC, "");
+  if (count < 1)
+    return -1;
+
+  for (elem = 0; elem < nelem && elem < count; elem++)
+    loadavg[elem] = load_ave[elem];
+
+  return elem;
+
+# endif /* __linux__ */
+
+# if !defined (LDAV_DONE) && defined (__NetBSD__)
+#  define LDAV_DONE
+#  undef LOAD_AVE_TYPE
+
+#  ifndef NETBSD_LDAV_FILE
+#   define NETBSD_LDAV_FILE "/kern/loadavg"
+#  endif
+
+  unsigned long int load_ave[3], scale;
+  int count;
+  FILE *fp;
+
+  fp = fopen (NETBSD_LDAV_FILE, "r");
+  if (fp == NULL)
+    return -1;
+  count = fscanf (fp, "%lu %lu %lu %lu\n",
+		  &load_ave[0], &load_ave[1], &load_ave[2],
+		  &scale);
+  (void) fclose (fp);
+  if (count != 4)
+    return -1;
+
+  for (elem = 0; elem < nelem; elem++)
+    loadavg[elem] = (double) load_ave[elem] / (double) scale;
+
+  return elem;
+
+# endif /* __NetBSD__ */
+
+# if !defined (LDAV_DONE) && defined (NeXT)
+#  define LDAV_DONE
+  /* The NeXT code was adapted from iscreen 3.2.  */
+
+  host_t host;
+  struct processor_set_basic_info info;
+  unsigned info_count;
+
+  /* We only know how to get the 1-minute average for this system,
+     so even if the caller asks for more than 1, we only return 1.  */
+
+  if (!getloadavg_initialized)
+    {
+      if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
+	getloadavg_initialized = 1;
+    }
+
+  if (getloadavg_initialized)
+    {
+      info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
+      if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
+			      (processor_set_info_t) &info, &info_count)
+	  != KERN_SUCCESS)
+	getloadavg_initialized = 0;
+      else
+	{
+	  if (nelem > 0)
+	    loadavg[elem++] = (double) info.load_average / LOAD_SCALE;
+	}
+    }
+
+  if (!getloadavg_initialized)
+    return -1;
+# endif /* NeXT */
+
+# if !defined (LDAV_DONE) && defined (UMAX)
+#  define LDAV_DONE
+/* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
+   have a /dev/kmem.  Information about the workings of the running kernel
+   can be gathered with inq_stats system calls.
+   We only know how to get the 1-minute average for this system.  */
+
+  struct proc_summary proc_sum_data;
+  struct stat_descr proc_info;
+  double load;
+  register unsigned int i, j;
+
+  if (cpus == 0)
+    {
+      register unsigned int c, i;
+      struct cpu_config conf;
+      struct stat_descr desc;
+
+      desc.sd_next = 0;
+      desc.sd_subsys = SUBSYS_CPU;
+      desc.sd_type = CPUTYPE_CONFIG;
+      desc.sd_addr = (char *) &conf;
+      desc.sd_size = sizeof conf;
+
+      if (inq_stats (1, &desc))
+	return -1;
+
+      c = 0;
+      for (i = 0; i < conf.config_maxclass; ++i)
+	{
+	  struct class_stats stats;
+	  memset (&stats, '\0', sizeof stats);
+
+	  desc.sd_type = CPUTYPE_CLASS;
+	  desc.sd_objid = i;
+	  desc.sd_addr = (char *) &stats;
+	  desc.sd_size = sizeof stats;
+
+	  if (inq_stats (1, &desc))
+	    return -1;
+
+	  c += stats.class_numcpus;
+	}
+      cpus = c;
+      samples = cpus < 2 ? 3 : (2 * cpus / 3);
+    }
+
+  proc_info.sd_next = 0;
+  proc_info.sd_subsys = SUBSYS_PROC;
+  proc_info.sd_type = PROCTYPE_SUMMARY;
+  proc_info.sd_addr = (char *) &proc_sum_data;
+  proc_info.sd_size = sizeof (struct proc_summary);
+  proc_info.sd_sizeused = 0;
+
+  if (inq_stats (1, &proc_info) != 0)
+    return -1;
+
+  load = proc_sum_data.ps_nrunnable;
+  j = 0;
+  for (i = samples - 1; i > 0; --i)
+    {
+      load += proc_sum_data.ps_nrun[j];
+      if (j++ == PS_NRUNSIZE)
+	j = 0;
+    }
+
+  if (nelem > 0)
+    loadavg[elem++] = load / samples / cpus;
+# endif /* UMAX */
+
+# if !defined (LDAV_DONE) && defined (DGUX)
+#  define LDAV_DONE
+  /* This call can return -1 for an error, but with good args
+     it's not supposed to fail.  The first argument is for no
+     apparent reason of type `long int *'.  */
+  dg_sys_info ((long int *) &load_info,
+	       DG_SYS_INFO_LOAD_INFO_TYPE,
+	       DG_SYS_INFO_LOAD_VERSION_0);
+
+  if (nelem > 0)
+    loadavg[elem++] = load_info.one_minute;
+  if (nelem > 1)
+    loadavg[elem++] = load_info.five_minute;
+  if (nelem > 2)
+    loadavg[elem++] = load_info.fifteen_minute;
+# endif /* DGUX */
+
+# if !defined (LDAV_DONE) && defined (apollo)
+#  define LDAV_DONE
+/* Apollo code from lisch@mentorg.com (Ray Lischner).
+
+   This system call is not documented.  The load average is obtained as
+   three long integers, for the load average over the past minute,
+   five minutes, and fifteen minutes.  Each value is a scaled integer,
+   with 16 bits of integer part and 16 bits of fraction part.
+
+   I'm not sure which operating system first supported this system call,
+   but I know that SR10.2 supports it.  */
+
+  extern void proc1_$get_loadav ();
+  unsigned long load_ave[3];
+
+  proc1_$get_loadav (load_ave);
+
+  if (nelem > 0)
+    loadavg[elem++] = load_ave[0] / 65536.0;
+  if (nelem > 1)
+    loadavg[elem++] = load_ave[1] / 65536.0;
+  if (nelem > 2)
+    loadavg[elem++] = load_ave[2] / 65536.0;
+# endif /* apollo */
+
+# if !defined (LDAV_DONE) && defined (OSF_MIPS)
+#  define LDAV_DONE
+
+  struct tbl_loadavg load_ave;
+  table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
+  loadavg[elem++]
+    = (load_ave.tl_lscale == 0
+       ? load_ave.tl_avenrun.d[0]
+       : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale));
+# endif	/* OSF_MIPS */
+
+# if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32))
+#  define LDAV_DONE
+
+  /* A faithful emulation is going to have to be saved for a rainy day.  */
+  for ( ; elem < nelem; elem++)
+    {
+      loadavg[elem] = 0.0;
+    }
+# endif  /* __MSDOS__ || WINDOWS32 */
+
+# if !defined (LDAV_DONE) && defined (OSF_ALPHA)
+#  define LDAV_DONE
+
+  struct tbl_loadavg load_ave;
+  table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
+  for (elem = 0; elem < nelem; elem++)
+    loadavg[elem]
+      = (load_ave.tl_lscale == 0
+       ? load_ave.tl_avenrun.d[elem]
+       : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale));
+# endif /* OSF_ALPHA */
+
+# if !defined (LDAV_DONE) && defined (VMS)
+  /* VMS specific code -- read from the Load Ave driver.  */
+
+  LOAD_AVE_TYPE load_ave[3];
+  static int getloadavg_initialized = 0;
+#  ifdef eunice
+  struct
+  {
+    int dsc$w_length;
+    char *dsc$a_pointer;
+  } descriptor;
+#  endif
+
+  /* Ensure that there is a channel open to the load ave device.  */
+  if (!getloadavg_initialized)
+    {
+      /* Attempt to open the channel.  */
+#  ifdef eunice
+      descriptor.dsc$w_length = 18;
+      descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE";
+#  else
+      $DESCRIPTOR (descriptor, "LAV0:");
+#  endif
+      if (sys$assign (&descriptor, &channel, 0, 0) & 1)
+	getloadavg_initialized = 1;
+    }
+
+  /* Read the load average vector.  */
+  if (getloadavg_initialized
+      && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0,
+		     load_ave, 12, 0, 0, 0, 0) & 1))
+    {
+      sys$dassgn (channel);
+      getloadavg_initialized = 0;
+    }
+
+  if (!getloadavg_initialized)
+    return -1;
+# endif /* VMS */
+
+# if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS)
+
+  /* UNIX-specific code -- read the average from /dev/kmem.  */
+
+#  define LDAV_PRIVILEGED		/* This code requires special installation.  */
+
+  LOAD_AVE_TYPE load_ave[3];
+
+  /* Get the address of LDAV_SYMBOL.  */
+  if (offset == 0)
+    {
+#  ifndef sgi
+#   ifndef NLIST_STRUCT
+      strcpy (nl[0].n_name, LDAV_SYMBOL);
+      strcpy (nl[1].n_name, "");
+#   else /* NLIST_STRUCT */
+#    ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME
+      nl[0].n_un.n_name = LDAV_SYMBOL;
+      nl[1].n_un.n_name = 0;
+#    else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
+      nl[0].n_name = LDAV_SYMBOL;
+      nl[1].n_name = 0;
+#    endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
+#   endif /* NLIST_STRUCT */
+
+#   ifndef SUNOS_5
+      if (
+#    if !(defined (_AIX) && !defined (ps2))
+	  nlist (KERNEL_FILE, nl)
+#    else  /* _AIX */
+	  knlist (nl, 1, sizeof (nl[0]))
+#    endif
+	  >= 0)
+	  /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i.  */
+	  {
+#    ifdef FIXUP_KERNEL_SYMBOL_ADDR
+	    FIXUP_KERNEL_SYMBOL_ADDR (nl);
+#    endif
+	    offset = nl[0].n_value;
+	  }
+#   endif /* !SUNOS_5 */
+#  else  /* sgi */
+      int ldav_off;
+
+      ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
+      if (ldav_off != -1)
+	offset = (long) ldav_off & 0x7fffffff;
+#  endif /* sgi */
+    }
+
+  /* Make sure we have /dev/kmem open.  */
+  if (!getloadavg_initialized)
+    {
+#  ifndef SUNOS_5
+      channel = open ("/dev/kmem", 0);
+      if (channel >= 0)
+	{
+	  /* Set the channel to close on exec, so it does not
+	     litter any child's descriptor table.  */
+#   ifdef F_SETFD
+#    ifndef FD_CLOEXEC
+#     define FD_CLOEXEC 1
+#    endif
+	  (void) fcntl (channel, F_SETFD, FD_CLOEXEC);
+#   endif
+	  getloadavg_initialized = 1;
+	}
+#  else /* SUNOS_5 */
+      /* We pass 0 for the kernel, corefile, and swapfile names
+	 to use the currently running kernel.  */
+      kd = kvm_open (0, 0, 0, O_RDONLY, 0);
+      if (kd != 0)
+	{
+	  /* nlist the currently running kernel.  */
+	  kvm_nlist (kd, nl);
+	  offset = nl[0].n_value;
+	  getloadavg_initialized = 1;
+	}
+#  endif /* SUNOS_5 */
+    }
+
+  /* If we can, get the load average values.  */
+  if (offset && getloadavg_initialized)
+    {
+      /* Try to read the load.  */
+#  ifndef SUNOS_5
+      if (lseek (channel, offset, 0) == -1L
+	  || read (channel, (char *) load_ave, sizeof (load_ave))
+	  != sizeof (load_ave))
+	{
+	  close (channel);
+	  getloadavg_initialized = 0;
+	}
+#  else  /* SUNOS_5 */
+      if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
+	  != sizeof (load_ave))
+        {
+          kvm_close (kd);
+          getloadavg_initialized = 0;
+	}
+#  endif /* SUNOS_5 */
+    }
+
+  if (offset == 0 || !getloadavg_initialized)
+    return -1;
+# endif /* LOAD_AVE_TYPE and not VMS */
+
+# if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS.  */
+  if (nelem > 0)
+    loadavg[elem++] = LDAV_CVT (load_ave[0]);
+  if (nelem > 1)
+    loadavg[elem++] = LDAV_CVT (load_ave[1]);
+  if (nelem > 2)
+    loadavg[elem++] = LDAV_CVT (load_ave[2]);
+
+#  define LDAV_DONE
+# endif /* !LDAV_DONE && LOAD_AVE_TYPE */
+
+# ifdef LDAV_DONE
+  return elem;
+# else
+  /* Set errno to zero to indicate that there was no particular error;
+     this function just can't work at all on this system.  */
+  errno = 0;
+  return -1;
+# endif
+}
+
+#endif /* ! HAVE_GETLOADAVG */
+
+
+#ifdef TEST
+#include "make.h"
+
+int
+main (int argc, char **argv)
+{
+  int naptime = 0;
+
+  if (argc > 1)
+    naptime = atoi (argv[1]);
+
+  while (1)
+    {
+      double avg[3];
+      int loads;
+
+      errno = 0;		/* Don't be misled if it doesn't set errno.  */
+      loads = getloadavg (avg, 3);
+      if (loads == -1)
+	{
+	  perror ("Error getting load average");
+	  exit (1);
+	}
+      if (loads > 0)
+	printf ("1-minute: %f  ", avg[0]);
+      if (loads > 1)
+	printf ("5-minute: %f  ", avg[1]);
+      if (loads > 2)
+	printf ("15-minute: %f  ", avg[2]);
+      if (loads > 0)
+	putchar ('\n');
+
+      if (naptime == 0)
+	break;
+      sleep (naptime);
+    }
+
+  exit (0);
+}
+#endif /* TEST */
Index: /tags/kBuild-0.1.4/src/kmk/getopt.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/getopt.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/getopt.c	(revision 1780)
@@ -0,0 +1,1034 @@
+/* Getopt for GNU.
+NOTE: getopt is now part of the C library, so if you don't know what
+"Keep this file name-space clean" means, talk to drepper@gnu.org
+before changing it!
+
+Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+   Ditto for AIX 3.2 and <stdlib.h>.  */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+# ifndef const
+#  define const
+# endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef	__GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+# include <stdlib.h>
+# include <unistd.h>
+#endif	/* GNU C library.  */
+
+#ifdef VMS
+# include <unixlib.h>
+# if HAVE_STRING_H - 0
+#  include <string.h>
+# endif
+#endif
+
+/* This is for other GNU distributions with internationalized messages.
+   When compiling libc, the _ macro is predefined.  */
+#include "gettext.h"
+#define _(msgid)    gettext (msgid)
+
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* 1003.2 says this must be 1 before any call.  */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+   causes problems with re-calling getopt as programs generally don't
+   know that. */
+
+int __getopt_initialized = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable.  */
+static char *posixly_correct;
+
+
+#ifdef	__GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+# include <string.h>
+# define my_index	strchr
+#else
+
+# if HAVE_STRING_H
+#  include <string.h>
+# else
+#  include <strings.h>
+# endif
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+
+static char *
+my_index (const char *str, int chr)
+{
+  while (*str)
+    {
+      if (*str == chr)
+	return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+   That was relevant to code that was here before.  */
+# if (!defined __STDC__ || !__STDC__) && !defined strlen
+/* gcc with -traditional declares the built-in strlen to return int,
+   and has done so at least since version 2.4.5. -- rms.  */
+extern int strlen (const char *);
+# endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+   indicating ARGV elements that should not be considered arguments.  */
+
+/* Defined in getopt_init.c  */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+   is valid for the getopt call we must make sure that the ARGV passed
+   to getopt is that one passed to the process.  */
+static void __attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+  /* XXX This is no good solution.  We should rather copy the args so
+     that we can compare them later.  But we must not use malloc(3).  */
+  original_argc = argc;
+  original_argv = argv;
+}
+# ifdef text_set_element
+text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
+
+# define SWAP_FLAGS(ch1, ch2) \
+  if (nonoption_flags_len > 0)						      \
+    {									      \
+      char __tmp = __getopt_nonoption_flags[ch1];			      \
+      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \
+      __getopt_nonoption_flags[ch2] = __tmp;				      \
+    }
+#else	/* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif	/* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+#if defined __STDC__ && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (char **argv)
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+#ifdef _LIBC
+  /* First make sure the handling of the `__getopt_nonoption_flags'
+     string can work normally.  Our top argument must be in the range
+     of the string.  */
+  if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+    {
+      /* We must extend the array.  The user plays games with us and
+	 presents new arguments.  */
+      char *new_str = malloc (top + 1);
+      if (new_str == NULL)
+	nonoption_flags_len = nonoption_flags_max_len = 0;
+      else
+	{
+	  memset (__mempcpy (new_str, __getopt_nonoption_flags,
+			     nonoption_flags_max_len),
+		  '\0', top + 1 - nonoption_flags_max_len);
+	  nonoption_flags_max_len = top + 1;
+	  __getopt_nonoption_flags = new_str;
+	}
+    }
+#endif
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	      SWAP_FLAGS (bottom + i, middle + i);
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+#if defined __STDC__ && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (int argc, char *const *argv, const char *optstring)
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  first_nonopt = last_nonopt = optind;
+
+  nextchar = NULL;
+
+  posixly_correct = getenv ("POSIXLY_CORRECT");
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (posixly_correct != NULL)
+    ordering = REQUIRE_ORDER;
+  else
+    ordering = PERMUTE;
+
+#ifdef _LIBC
+  if (posixly_correct == NULL
+      && argc == original_argc && argv == original_argv)
+    {
+      if (nonoption_flags_max_len == 0)
+	{
+	  if (__getopt_nonoption_flags == NULL
+	      || __getopt_nonoption_flags[0] == '\0')
+	    nonoption_flags_max_len = -1;
+	  else
+	    {
+	      const char *orig_str = __getopt_nonoption_flags;
+	      int len = nonoption_flags_max_len = strlen (orig_str);
+	      if (nonoption_flags_max_len < argc)
+		nonoption_flags_max_len = argc;
+	      __getopt_nonoption_flags =
+		(char *) malloc (nonoption_flags_max_len);
+	      if (__getopt_nonoption_flags == NULL)
+		nonoption_flags_max_len = -1;
+	      else
+		memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+			'\0', nonoption_flags_max_len - len);
+	    }
+	}
+      nonoption_flags_len = nonoption_flags_max_len;
+    }
+  else
+    nonoption_flags_len = 0;
+#endif
+
+  return optstring;
+}
+
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns -1.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (int argc, char *const *argv, const char *optstring,
+                  const struct option *longopts, int *longind, int long_only)
+{
+  optarg = NULL;
+
+  if (optind == 0 || !__getopt_initialized)
+    {
+      if (optind == 0)
+	optind = 1;	/* Don't scan ARGV[0], the program name.  */
+      optstring = _getopt_initialize (argc, argv, optstring);
+      __getopt_initialized = 1;
+    }
+
+  /* Test whether ARGV[optind] points to a non-option argument.
+     Either it does not have option syntax, or there is an environment flag
+     from the shell indicating it is not an option.  The later information
+     is only used when the used in the GNU libc.  */
+#ifdef _LIBC
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0'	      \
+		      || (optind < nonoption_flags_len			      \
+			  && __getopt_nonoption_flags[optind] == '1'))
+#else
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+	 moved back by the user (who may also have changed the arguments).  */
+      if (last_nonopt > optind)
+	last_nonopt = optind;
+      if (first_nonopt > optind)
+	first_nonopt = optind;
+
+      if (ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (last_nonopt != optind)
+	    first_nonopt = optind;
+
+	  /* Skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (optind < argc && NONOPTION_P)
+	    optind++;
+	  last_nonopt = optind;
+	}
+
+      /* The special ARGV-element `--' means premature end of options.
+	 Skip it like a null option,
+	 then exchange with previous non-options as if it were an option,
+	 then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+	{
+	  optind++;
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (first_nonopt == last_nonopt)
+	    first_nonopt = optind;
+	  last_nonopt = argc;
+
+	  optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+	 and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (first_nonopt != last_nonopt)
+	    optind = first_nonopt;
+	  return -1;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+	 either stop the scan or describe it to the caller and pass it by.  */
+
+      if (NONOPTION_P)
+	{
+	  if (ordering == REQUIRE_ORDER)
+	    return -1;
+	  optarg = argv[optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+	 Skip the initial punctuation.  */
+
+      nextchar = (argv[optind] + 1
+		  + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[optind][1] == '-'
+	  || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = -1;
+      int option_index;
+
+      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+	/* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+	 or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, nextchar, nameend - nextchar))
+	  {
+	    if ((unsigned int) (nameend - nextchar)
+		== (unsigned int) strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else
+	      /* Second or later nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (opterr)
+	    fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+		     argv[0], argv[optind]);
+	  nextchar += strlen (nextchar);
+	  optind++;
+	  optopt = 0;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  optind++;
+	  if (*nameend)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+		 allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		optarg = nameend + 1;
+	      else
+		{
+		  if (opterr)
+		   if (argv[optind - 1][1] == '-')
+		    /* --option */
+		    fprintf (stderr,
+		     _("%s: option `--%s' doesn't allow an argument\n"),
+		     argv[0], pfound->name);
+		   else
+		    /* +option or -option */
+		    fprintf (stderr,
+		     _("%s: option `%c%s' doesn't allow an argument\n"),
+		     argv[0], argv[optind - 1][0], pfound->name);
+
+		  nextchar += strlen (nextchar);
+
+		  optopt = pfound->val;
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (optind < argc)
+		optarg = argv[optind++];
+	      else
+		{
+		  if (opterr)
+		    fprintf (stderr,
+			   _("%s: option `%s' requires an argument\n"),
+			   argv[0], argv[optind - 1]);
+		  nextchar += strlen (nextchar);
+		  optopt = pfound->val;
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  nextchar += strlen (nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short
+	 option, then it's an error.
+	 Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+	  || my_index (optstring, *nextchar) == NULL)
+	{
+	  if (opterr)
+	    {
+	      if (argv[optind][1] == '-')
+		/* --option */
+		fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+			 argv[0], nextchar);
+	      else
+		/* +option or -option */
+		fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+			 argv[0], argv[optind][0], nextchar);
+	    }
+	  nextchar = (char *) "";
+	  optind++;
+	  optopt = 0;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (opterr)
+	  {
+	    if (posixly_correct)
+	      /* 1003.2 specifies the format of this message.  */
+	      fprintf (stderr, _("%s: illegal option -- %c\n"),
+		       argv[0], c);
+	    else
+	      fprintf (stderr, _("%s: invalid option -- %c\n"),
+		       argv[0], c);
+	  }
+	optopt = c;
+	return '?';
+      }
+    /* Convenience. Treat POSIX -W foo same as long option --foo */
+    if (temp[0] == 'W' && temp[1] == ';')
+      {
+	char *nameend;
+	const struct option *p;
+	const struct option *pfound = NULL;
+	int exact = 0;
+	int ambig = 0;
+	int indfound = 0;
+	int option_index;
+
+	/* This is an option that requires an argument.  */
+	if (*nextchar != '\0')
+	  {
+	    optarg = nextchar;
+	    /* If we end this ARGV-element by taking the rest as an arg,
+	       we must advance to the next element now.  */
+	    optind++;
+	  }
+	else if (optind == argc)
+	  {
+	    if (opterr)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+		fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+			 argv[0], c);
+	      }
+	    optopt = c;
+	    if (optstring[0] == ':')
+	      c = ':';
+	    else
+	      c = '?';
+	    return c;
+	  }
+	else
+	  /* We already incremented `optind' once;
+	     increment it again when taking next ARGV-elt as argument.  */
+	  optarg = argv[optind++];
+
+	/* optarg is now the argument, see if it's in the
+	   table of longopts.  */
+
+	for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+	  /* Do nothing.  */ ;
+
+	/* Test all long options for either exact match
+	   or abbreviated matches.  */
+	for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	  if (!strncmp (p->name, nextchar, nameend - nextchar))
+	    {
+	      if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+		{
+		  /* Exact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		  exact = 1;
+		  break;
+		}
+	      else if (pfound == NULL)
+		{
+		  /* First nonexact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		}
+	      else
+		/* Second or later nonexact match found.  */
+		ambig = 1;
+	    }
+	if (ambig && !exact)
+	  {
+	    if (opterr)
+	      fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+		       argv[0], argv[optind]);
+	    nextchar += strlen (nextchar);
+	    optind++;
+	    return '?';
+	  }
+	if (pfound != NULL)
+	  {
+	    option_index = indfound;
+	    if (*nameend)
+	      {
+		/* Don't test has_arg with >, because some C compilers don't
+		   allow it to be used on enums.  */
+		if (pfound->has_arg)
+		  optarg = nameend + 1;
+		else
+		  {
+		    if (opterr)
+		      fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+			       argv[0], pfound->name);
+
+		    nextchar += strlen (nextchar);
+		    return '?';
+		  }
+	      }
+	    else if (pfound->has_arg == 1)
+	      {
+		if (optind < argc)
+		  optarg = argv[optind++];
+		else
+		  {
+		    if (opterr)
+		      fprintf (stderr,
+			       _("%s: option `%s' requires an argument\n"),
+			       argv[0], argv[optind - 1]);
+		    nextchar += strlen (nextchar);
+		    return optstring[0] == ':' ? ':' : '?';
+		  }
+	      }
+	    nextchar += strlen (nextchar);
+	    if (longind != NULL)
+	      *longind = option_index;
+	    if (pfound->flag)
+	      {
+		*(pfound->flag) = pfound->val;
+		return 0;
+	      }
+	    return pfound->val;
+	  }
+	  nextchar = NULL;
+	  return 'W';	/* Let the application handle it.   */
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		optind++;
+	      }
+	    else
+	      optarg = NULL;
+	    nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		optind++;
+	      }
+	    else if (optind == argc)
+	      {
+		if (opterr)
+		  {
+		    /* 1003.2 specifies the format of this message.  */
+		    fprintf (stderr,
+			   _("%s: option requires an argument -- %c\n"),
+			   argv[0], c);
+		  }
+		optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+		 increment it again when taking next ARGV-elt as argument.  */
+	      optarg = argv[optind++];
+	    nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+getopt (int argc, char *const *argv, const char *optstring)
+{
+  return _getopt_internal (argc, argv, optstring,
+			   (const struct option *) 0,
+			   (int *) 0,
+			   0);
+}
+
+#endif	/* Not ELIDE_CODE.  */
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (int argc, char **argv)
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /tags/kBuild-0.1.4/src/kmk/getopt.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/getopt.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/getopt.h	(revision 1780)
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument 	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define	no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+		        const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind,
+			     int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* getopt.h */
Index: /tags/kBuild-0.1.4/src/kmk/getopt1.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/getopt1.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/getopt1.c	(revision 1780)
@@ -0,0 +1,182 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "getopt.h"
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef	NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (int argc, char *const *argv, const char *options,
+             const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (int argc, char *const *argv, const char *options,
+                  const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif	/* Not ELIDE_CODE.  */
+
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /tags/kBuild-0.1.4/src/kmk/gettext.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/gettext.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/gettext.h	(revision 1780)
@@ -0,0 +1,58 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */
Index: /tags/kBuild-0.1.4/src/kmk/glob/COPYING.LIB
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/COPYING.LIB	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/COPYING.LIB	(revision 1780)
@@ -0,0 +1,490 @@
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, 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 library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, 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 companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, 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 library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+  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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+  If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  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.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+  9. 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 Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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.
+
+
+  11. 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 Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  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 library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
Index: /tags/kBuild-0.1.4/src/kmk/glob/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/ChangeLog	(revision 1780)
@@ -0,0 +1,175 @@
+2006-02-24  Eli Zaretskii  <eliz@gnu.org>
+
+	* glob.c (my_malloc) [WINDOWS32]: Provide a full ISO C prototype,
+        to avoid compiler warnings.
+
+2005-06-25  Paul D. Smith  <psmith@gnu.org>
+
+	* fnmatch.h, glob.h [WINDOWS32]: Fix ifdefs in headers.
+	Fixes Savannah bug #13477.
+
+2005-03-11  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c (glob_in_dir): Change FNM_CASEFOLD to be enabled if
+	HAVE_CASE_INSENSITIVE_FS is defined.
+
+2003-01-30  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.h: Patch for FreeBSD by Mike Barcroft <mike@freebsd.org>
+	Reported by Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>.  On
+	FreeBSD, declare __size_t to simply size_t.
+
+2002-04-22  Paul D. Smith  <psmith@gnu.org>
+
+	* Makefile.am: Use automake 1.6.
+	Use new automake condition USE_LOCAL_GLOB to decide whether or not
+	to build the local GNU glob library or use the system one.
+
+1999-09-12  Paul D. Smith  <psmith@gnu.org>
+
+	* fnmatch.c: Last GLIBC version wouldn't compile outside of GLIBC
+	(undefined reference to internal_function).  Update to the latest
+	version
+
+1999-09-11  Paul Eggert  <eggert@twinsun.com>
+
+	* glob.h (glob): If #defining to glob64, do this before
+	declaring it, so that all declarations and uses match, and
+	do not declare glob64, to avoid a declaration clash.
+	(globfree): Likewise with globfree64.
+
+1999-09-08  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* glob.c (prefix_array) [__MSDOS__,WINDOWS32]: Keep the trailing
+	slash unless DIRNAME is just "x:/".
+
+1999-09-06  Paul D. Smith  <psmith@gnu.org>
+
+	* fnmatch.c: Update to latest version from GLIBC.
+
+1999-07-21  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c, glob.h, fnmatch.c, fnmatch.h: Update to latest version
+	from GLIBC.
+
+	* fnmatch.c (internal_fnmatch): Use K&R definition syntax, not ANSI.
+	(__strchrnul): This won't exist outside GLIBC, so create one.
+
+	* glob.c: Move getlogin{,_r} prototypes below glob.h to get __P()
+	macro.
+
+1998-08-05  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Remove; configuration for glob is handled by the
+	make configure.in.
+
+1998-07-29  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c, fnmatch.c: New versions from the GLIBC folks (Ulrich
+	Drepper).  Fixes a bug reported by Eli Zaretski.  Integrates
+	DOS/Windows32 support.
+
+1998-07-27  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+	* glob.c (glob): Cast away const on assignment of pattern to dirname.
+	Cast the return type of __alloca() for traditional C compilers.
+
+1998-07-23  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c, fnmatch.c: New versions of these files from the GLIBC
+	folks (Ulrich Drepper).  Had to re-integrate some DOS/Windows
+	code.
+
+1998-07-10  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c (glob_in_dir): If no meta chars exist in PATTERN and
+	GLOB_NOCHECK is present, don't look for the file--whether it's
+	found or not, we'll always return it, so why bother searching?
+
+	Also, if we are searching and there are no meta chars, don't
+	bother trying fnmatch() if the strcmp() fails.
+
+1998-05-30  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* glob.c (glob) [__MSDOS__, WINDOWS32]: Compute the directory and
+	filename parts of the pattern correctly when it includes a drive
+	spec.  Disallow wildcards in the drive spec.  Prevent recursion
+	when dirname is of the form "d:/" or "d:".
+	(prefix_array) [__MSDOS__, WINDOWS32]: Don't append a slash to
+	"d:/" and "d:".
+
+1998-05-13  Paul D. Smith  <psmith@gnu.org>
+
+	* SMakefile, Makefile.ami, glob.c, glob.h, fnmatch.c: Updated from
+	the latest glibc version.
+
+1998-04-17  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Create a config.h file instead of setting things
+	on the compile line.  This is because when build.sh runs it merely
+	passes -DHAVE_CONFIG_H to the glob files, just as it does to the
+	make files.
+	* config.h.in: Created by autoheader.
+
+Tue Aug 12 10:52:34 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* configure.in: Require autoconf 2.12.
+
+	* glob: Updates from latest GNU libc glob code.
+
+	* glob.c,glob.h,fnmatch.h: Change all WIN32 references to WINDOWS32.
+
+	* glob.h: OSF4 defines macros in such a way that GLOB_ALTDIRFUNC
+	is not defined.  Added a test to the #if which defines it if
+	_GNU_SOURCE is defined; that's set by both glob.c and GNU make.
+
+	* glob.c: SunOS4 w/ cc needs #include <stdio.h>, since assert.h
+	requires stderr but doesn't include stdio.h :-/.
+	(next_brace_sub): De-protoize function definition.
+	(glob): Cast __alloca(); on SunOS4 it uses the default return type
+	of int.
+	(glob): Irix defines getlogin_r() to return a char*; move the
+	extern for that into the _LIBC area since it isn't used except in
+	LIBC anyway.  Likewise, move extern getlogin() into the "else".
+
+Sat Jul 20 21:55:31 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	Win32 hacks from <Rob_Tulloh@tivoli.com>.
+	* posix/glob.c [WIN32]: Don't include <pwd.h>; don't use d_ino;
+	use void * for my_realloc; include <malloc.h> for alloca.
+	(glob) [WIN32]: Use "c:/users/default" for ~ if no HOME variable.
+	* posix/fnmatch.h [WIN32]: Use prototypes even if [!__STDC__].
+	* posix/glob.h: Likewise.
+
+Fri Jul 19 16:56:41 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* posix/glob.h [!_AMIGA && !VMS]: Check this instead of just [!_AMIGA]
+	for `struct stat;' forward decl.
+
+Sat Jun 22 10:44:09 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* posix/glob.c: Include <alloca.h> only [HAVE_ALLOCA_H], not [sparc].
+
+Fri Jun 21 00:27:51 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* posix/fnmatch.c (fnmatch): Fix \*[*?]+ case to increment name ptr
+ 	only for ?s, not for *s.  Fix from Chet Ramey.
+
+
+
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/glob/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/Makefile.am	(revision 1780)
@@ -0,0 +1,29 @@
+# -*-Makefile-*-, or close enough
+# Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+AUTOMAKE_OPTIONS =	foreign
+
+# Only build the library when the system doesn't already have GNU glob.
+if USE_LOCAL_GLOB
+  noinst_LIBRARIES =	libglob.a
+endif
+
+libglob_a_SOURCES =	glob.c glob.h fnmatch.c fnmatch.h
+
+
+EXTRA_DIST =		COPYING.LIB Makefile.ami SCOPTIONS SMakefile \
+			configure.bat
Index: /tags/kBuild-0.1.4/src/kmk/glob/Makefile.ami
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/Makefile.ami	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/Makefile.ami	(revision 1780)
@@ -0,0 +1,66 @@
+# Makefile for standalone libglob.a (fnmatch, glob).             -*-Makefile-*-
+# Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Ultrix 2.2 make doesn't expand the value of VPATH.
+VPATH = /glob/
+# This must repeat the value, because configure will remove `VPATH = .'.
+srcdir = /glob/
+
+CC = sc
+RM = delete
+CPPFLAGS =
+CFLAGS =
+
+# Information determined by configure.
+DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \
+	Define HAVE_DIRENT_H
+
+# How to invoke ar.
+AR = join
+ARFLAGS = as
+
+# How to invoke ranlib.
+RANLIB = ;
+
+.PHONY: all
+all: glob.lib
+
+glob.lib : glob.o fnmatch.o
+	$(AR) $(ARFLAGS) $@ glob.o fnmatch.o
+	$(RANLIB) $@
+
+# For some reason, Unix make wants the dependencies on the source files.
+# Otherwise it refuses to use an implicit rule!
+# And, get this: it doesn't work to use $(srcdir)foo.c!!
+glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c
+fnmatch.o: $(srcdir)fnmatch.h fnmatch.c
+
+OUTPUT_OPTION =
+.c.o:
+	$(CC) IDir "" \
+	      $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION)
+
+.PHONY: clean realclean glob-clean glob-realclean distclean
+clean glob-clean:
+	-$(RM) glob.lib "#?.o" core
+distclean glob-realclean: clean
+	-$(RM) TAGS tags Makefile config.status config.h config.log
+realcean: distclean
+
+# For inside the C library.
+glob.tar glob.tar.Z:
+	$(MAKE) -C .. $@
Index: /tags/kBuild-0.1.4/src/kmk/glob/SCOPTIONS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/SCOPTIONS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/SCOPTIONS	(revision 1780)
@@ -0,0 +1,13 @@
+ERRORREXX
+OPTIMIZE
+NOVERSION
+OPTIMIZERTIME
+OPTIMIZERALIAS
+DEFINE INCLUDEDIR="include:"
+DEFINE LIBDIR="lib:"
+DEFINE NO_ALLOCA
+DEFINE NO_FLOAT
+DEFINE NO_ARCHIVES
+IGNORE=161
+IGNORE=100
+STARTUP=cres
Index: /tags/kBuild-0.1.4/src/kmk/glob/SMakefile
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/SMakefile	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/SMakefile	(revision 1780)
@@ -0,0 +1,66 @@
+# Makefile for standalone distribution of libglob.a (fnmatch, glob).
+# Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Ultrix 2.2 make doesn't expand the value of VPATH.
+VPATH = /glob/
+# This must repeat the value, because configure will remove `VPATH = .'.
+srcdir = /glob/
+
+CC = sc
+CPPFLAGS =
+CFLAGS =
+MAKE = smake
+RM = delete
+
+# Information determined by configure.
+DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \
+	Define HAVE_DIRENT_H
+
+# How to invoke ar.
+AR = join
+ARFLAGS = as
+
+# How to invoke ranlib.
+RANLIB = ;
+
+.PHONY: all
+all: glob.lib
+
+glob.lib : glob.o fnmatch.o
+	$(AR) $(ARFLAGS) $@ glob.o fnmatch.o
+	$(RANLIB) $@
+
+# For some reason, Unix make wants the dependencies on the source files.
+# Otherwise it refuses to use an implicit rule!
+# And, get this: it doesn't work to use $(srcdir)foo.c!!
+glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c
+fnmatch.o: $(srcdir)fnmatch.h fnmatch.c
+
+.c.o:
+	$(CC) IDir "" \
+	      $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION)
+
+.PHONY: clean realclean glob-clean glob-realclean distclean
+clean glob-clean:
+	-$(RM) -f glob.lib *.o core
+distclean glob-realclean: clean
+	-$(RM) -f TAGS tags Makefile config.status config.h config.log
+realcean: distclean
+
+# For inside the C library.
+glob.tar glob.tar.Z:
+	$(MAKE) -C .. $@
Index: /tags/kBuild-0.1.4/src/kmk/glob/configure.bat
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/configure.bat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/configure.bat	(revision 1780)
@@ -0,0 +1,44 @@
+@echo off
+rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+rem 2004, 2005, 2006 Free Software Foundation, Inc.
+rem This file is part of GNU Make.
+
+rem GNU Make is free software; you can redistribute it and/or modify it under
+rem the terms of the GNU General Public License as published by the Free
+rem Software Foundation; either version 2, or (at your option) any later
+rem version.
+
+rem GNU Make is distributed in the hope that it will be useful, but WITHOUT
+rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+rem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+rem more details.
+
+rem You should have received a copy of the GNU General Public License along
+rem with GNU Make; see the file COPYING.  If not, write to the Free Software
+rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+echo Configuring glob for DJGPP
+rem This batch file assumes a unix-type "sed" program
+
+echo # Makefile generated by "configure.bat"> Makefile
+
+if exist config.sed del config.sed
+
+echo "s/@srcdir@/./					">> config.sed
+echo "s/@CC@/gcc/					">> config.sed
+echo "s/@CFLAGS@/-O2 -g/				">> config.sed
+echo "s/@CPPFLAGS@/-DHAVE_CONFIG_H -I../		">> config.sed
+echo "s/@AR@/ar/					">> config.sed
+echo "s/@RANLIB@/ranlib/				">> config.sed
+echo "s/@LDFLAGS@//					">> config.sed
+echo "s/@DEFS@//					">> config.sed
+echo "s/@ALLOCA@//					">> config.sed
+echo "s/@LIBS@//					">> config.sed
+echo "s/@LIBOBJS@//					">> config.sed
+echo "s/^Makefile *:/_Makefile:/			">> config.sed
+echo "s/^config.h *:/_config.h:/			">> config.sed
+
+sed -e "s/^\"//" -e "s/\"$//" -e "s/[ 	]*$//" config.sed > config2.sed
+sed -f config2.sed Makefile.in >> Makefile
+del config.sed
+del config2.sed
Index: /tags/kBuild-0.1.4/src/kmk/glob/fnmatch.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/fnmatch.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/fnmatch.c	(revision 1780)
@@ -0,0 +1,488 @@
+/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this library; see the file COPYING.LIB.  If not, write to the Free
+Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Enable GNU extensions in fnmatch.h.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#include <errno.h>
+#include <fnmatch.h>
+#include <ctype.h>
+
+#if HAVE_STRING_H || defined _LIBC
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+#endif
+
+/* For platform which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+# include <wchar.h>
+# include <wctype.h>
+#endif
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined _LIBC || !defined __GNU_LIBRARY__
+
+
+# if defined STDC_HEADERS || !defined isascii
+#  define ISASCII(c) 1
+# else
+#  define ISASCII(c) isascii(c)
+# endif
+
+# ifdef isblank
+#  define ISBLANK(c) (ISASCII (c) && isblank (c))
+# else
+#  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# endif
+# ifdef isgraph
+#  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+# else
+#  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+# endif
+
+# define ISPRINT(c) (ISASCII (c) && isprint (c))
+# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+# define ISALNUM(c) (ISASCII (c) && isalnum (c))
+# define ISALPHA(c) (ISASCII (c) && isalpha (c))
+# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+# define ISLOWER(c) (ISASCII (c) && islower (c))
+# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+# define ISSPACE(c) (ISASCII (c) && isspace (c))
+# define ISUPPER(c) (ISASCII (c) && isupper (c))
+# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* The GNU C library provides support for user-defined character classes
+   and the functions from ISO C amendement 1.  */
+#  ifdef CHARCLASS_NAME_MAX
+#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+#  else
+/* This shouldn't happen but some implementation might still have this
+   problem.  Use a reasonable default value.  */
+#   define CHAR_CLASS_MAX_LENGTH 256
+#  endif
+
+#  ifdef _LIBC
+#   define IS_CHAR_CLASS(string) __wctype (string)
+#  else
+#   define IS_CHAR_CLASS(string) wctype (string)
+#  endif
+# else
+#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#  define IS_CHAR_CLASS(string)						      \
+   (STREQ (string, "alpha") || STREQ (string, "upper")			      \
+    || STREQ (string, "lower") || STREQ (string, "digit")		      \
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")		      \
+    || STREQ (string, "space") || STREQ (string, "print")		      \
+    || STREQ (string, "punct") || STREQ (string, "graph")		      \
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+# endif
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+# if !defined _LIBC && !defined getenv && !defined _MSC_VER
+extern char *getenv ();
+# endif
+
+# ifndef errno
+extern int errno;
+# endif
+
+/* This function doesn't exist on most systems.  */
+
+# if !defined HAVE___STRCHRNUL && !defined _LIBC
+static char *
+__strchrnul (s, c)
+     const char *s;
+     int c;
+{
+  char *result = strchr (s, c);
+  if (result == NULL)
+    result = strchr (s, '\0');
+  return result;
+}
+# endif
+
+# ifndef internal_function
+/* Inside GNU libc we mark some function in a special way.  In other
+   environments simply ignore the marking.  */
+#  define internal_function
+# endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, nonzero if not.  */
+static int internal_fnmatch __P ((const char *pattern, const char *string,
+				  int no_leading_period, int flags))
+     internal_function;
+static int
+internal_function
+internal_fnmatch (pattern, string, no_leading_period, flags)
+     const char *pattern;
+     const char *string;
+     int no_leading_period;
+     int flags;
+{
+  register const char *p = pattern, *n = string;
+  register unsigned char c;
+
+/* Note that this evaluates C many times.  */
+# ifdef _LIBC
+#  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+# else
+#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+# endif
+
+  while ((c = *p++) != '\0')
+    {
+      c = FOLD (c);
+
+      switch (c)
+	{
+	case '?':
+	  if (*n == '\0')
+	    return FNM_NOMATCH;
+	  else if (*n == '/' && (flags & FNM_FILE_NAME))
+	    return FNM_NOMATCH;
+	  else if (*n == '.' && no_leading_period
+		   && (n == string
+		       || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
+	    return FNM_NOMATCH;
+	  break;
+
+	case '\\':
+	  if (!(flags & FNM_NOESCAPE))
+	    {
+	      c = *p++;
+	      if (c == '\0')
+		/* Trailing \ loses.  */
+		return FNM_NOMATCH;
+	      c = FOLD (c);
+	    }
+	  if (FOLD ((unsigned char) *n) != c)
+	    return FNM_NOMATCH;
+	  break;
+
+	case '*':
+	  if (*n == '.' && no_leading_period
+	      && (n == string
+		  || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
+	    return FNM_NOMATCH;
+
+	  for (c = *p++; c == '?' || c == '*'; c = *p++)
+	    {
+	      if (*n == '/' && (flags & FNM_FILE_NAME))
+		/* A slash does not match a wildcard under FNM_FILE_NAME.  */
+		return FNM_NOMATCH;
+	      else if (c == '?')
+		{
+		  /* A ? needs to match one character.  */
+		  if (*n == '\0')
+		    /* There isn't another character; no match.  */
+		    return FNM_NOMATCH;
+		  else
+		    /* One character of the string is consumed in matching
+		       this ? wildcard, so *??? won't match if there are
+		       less than three characters.  */
+		    ++n;
+		}
+	    }
+
+	  if (c == '\0')
+	    /* The wildcard(s) is/are the last element of the pattern.
+	       If the name is a file name and contains another slash
+	       this does mean it cannot match.  */
+	    return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
+		    ? FNM_NOMATCH : 0);
+	  else
+	    {
+	      const char *endp;
+
+	      endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
+
+	      if (c == '[')
+		{
+		  int flags2 = ((flags & FNM_FILE_NAME)
+				? flags : (flags & ~FNM_PERIOD));
+
+		  for (--p; n < endp; ++n)
+		    if (internal_fnmatch (p, n,
+					  (no_leading_period
+					   && (n == string
+					       || (n[-1] == '/'
+						   && (flags
+						       & FNM_FILE_NAME)))),
+					  flags2)
+			== 0)
+		      return 0;
+		}
+	      else if (c == '/' && (flags & FNM_FILE_NAME))
+		{
+		  while (*n != '\0' && *n != '/')
+		    ++n;
+		  if (*n == '/'
+		      && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
+					    flags) == 0))
+		    return 0;
+		}
+	      else
+		{
+		  int flags2 = ((flags & FNM_FILE_NAME)
+				? flags : (flags & ~FNM_PERIOD));
+
+		  if (c == '\\' && !(flags & FNM_NOESCAPE))
+		    c = *p;
+		  c = FOLD (c);
+		  for (--p; n < endp; ++n)
+		    if (FOLD ((unsigned char) *n) == c
+			&& (internal_fnmatch (p, n,
+					      (no_leading_period
+					       && (n == string
+						   || (n[-1] == '/'
+						       && (flags
+							   & FNM_FILE_NAME)))),
+					      flags2) == 0))
+		      return 0;
+		}
+	    }
+
+	  /* If we come here no match is possible with the wildcard.  */
+	  return FNM_NOMATCH;
+
+	case '[':
+	  {
+	    /* Nonzero if the sense of the character class is inverted.  */
+	    static int posixly_correct;
+	    register int not;
+	    char cold;
+
+	    if (posixly_correct == 0)
+	      posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+	    if (*n == '\0')
+	      return FNM_NOMATCH;
+
+	    if (*n == '.' && no_leading_period && (n == string
+						   || (n[-1] == '/'
+						       && (flags
+							   & FNM_FILE_NAME))))
+	      return FNM_NOMATCH;
+
+	    if (*n == '/' && (flags & FNM_FILE_NAME))
+	      /* `/' cannot be matched.  */
+	      return FNM_NOMATCH;
+
+	    not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
+	    if (not)
+	      ++p;
+
+	    c = *p++;
+	    for (;;)
+	      {
+		unsigned char fn = FOLD ((unsigned char) *n);
+
+		if (!(flags & FNM_NOESCAPE) && c == '\\')
+		  {
+		    if (*p == '\0')
+		      return FNM_NOMATCH;
+		    c = FOLD ((unsigned char) *p);
+		    ++p;
+
+		    if (c == fn)
+		      goto matched;
+		  }
+		else if (c == '[' && *p == ':')
+		  {
+		    /* Leave room for the null.  */
+		    char str[CHAR_CLASS_MAX_LENGTH + 1];
+		    size_t c1 = 0;
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+		    wctype_t wt;
+# endif
+		    const char *startp = p;
+
+		    for (;;)
+		      {
+			if (c1 == CHAR_CLASS_MAX_LENGTH)
+			  /* The name is too long and therefore the pattern
+			     is ill-formed.  */
+			  return FNM_NOMATCH;
+
+			c = *++p;
+			if (c == ':' && p[1] == ']')
+			  {
+			    p += 2;
+			    break;
+			  }
+			if (c < 'a' || c >= 'z')
+			  {
+			    /* This cannot possibly be a character class name.
+			       Match it as a normal range.  */
+			    p = startp;
+			    c = '[';
+			    goto normal_bracket;
+			  }
+			str[c1++] = c;
+		      }
+		    str[c1] = '\0';
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+		    wt = IS_CHAR_CLASS (str);
+		    if (wt == 0)
+		      /* Invalid character class name.  */
+		      return FNM_NOMATCH;
+
+		    if (__iswctype (__btowc ((unsigned char) *n), wt))
+		      goto matched;
+# else
+		    if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
+			|| (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
+			|| (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
+			|| (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
+			|| (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
+			|| (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
+			|| (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
+			|| (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
+			|| (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
+			|| (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
+			|| (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
+			|| (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
+		      goto matched;
+# endif
+		  }
+		else if (c == '\0')
+		  /* [ (unterminated) loses.  */
+		  return FNM_NOMATCH;
+		else
+		  {
+		  normal_bracket:
+		    if (FOLD (c) == fn)
+		      goto matched;
+
+		    cold = c;
+		    c = *p++;
+
+		    if (c == '-' && *p != ']')
+		      {
+			/* It is a range.  */
+			unsigned char cend = *p++;
+			if (!(flags & FNM_NOESCAPE) && cend == '\\')
+			  cend = *p++;
+			if (cend == '\0')
+			  return FNM_NOMATCH;
+
+			if (cold <= fn && fn <= FOLD (cend))
+			  goto matched;
+
+			c = *p++;
+		      }
+		  }
+
+		if (c == ']')
+		  break;
+	      }
+
+	    if (!not)
+	      return FNM_NOMATCH;
+	    break;
+
+	  matched:
+	    /* Skip the rest of the [...] that already matched.  */
+	    while (c != ']')
+	      {
+		if (c == '\0')
+		  /* [... (unterminated) loses.  */
+		  return FNM_NOMATCH;
+
+		c = *p++;
+		if (!(flags & FNM_NOESCAPE) && c == '\\')
+		  {
+		    if (*p == '\0')
+		      return FNM_NOMATCH;
+		    /* XXX 1003.2d11 is unclear if this is right.  */
+		    ++p;
+		  }
+		else if (c == '[' && *p == ':')
+		  {
+		    do
+		      if (*++p == '\0')
+			return FNM_NOMATCH;
+		    while (*p != ':' || p[1] == ']');
+		    p += 2;
+		    c = *p;
+		  }
+	      }
+	    if (not)
+	      return FNM_NOMATCH;
+	  }
+	  break;
+
+	default:
+	  if (c != FOLD ((unsigned char) *n))
+	    return FNM_NOMATCH;
+	}
+
+      ++n;
+    }
+
+  if (*n == '\0')
+    return 0;
+
+  if ((flags & FNM_LEADING_DIR) && *n == '/')
+    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+    return 0;
+
+  return FNM_NOMATCH;
+
+# undef FOLD
+}
+
+
+int
+fnmatch (pattern, string, flags)
+     const char *pattern;
+     const char *string;
+     int flags;
+{
+  return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
+}
+
+#endif	/* _LIBC or not __GNU_LIBRARY__.  */
Index: /tags/kBuild-0.1.4/src/kmk/glob/fnmatch.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/fnmatch.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/fnmatch.h	(revision 1780)
@@ -0,0 +1,84 @@
+/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
+This file is 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 Library General Public License as
+published by the Free Software Foundation; either version 2 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this library; see the file COPYING.LIB.  If not, write to the Free
+Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA.  */
+
+#ifndef	_FNMATCH_H
+#define	_FNMATCH_H	1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
+# if !defined __GLIBC__
+#  undef	__P
+#  define __P(protos)	protos
+# endif
+#else /* Not C++ or ANSI C.  */
+# undef	__P
+# define __P(protos)	()
+/* We can get away without defining `const' here only because in this file
+   it is used only inside the prototype for `fnmatch', which is elided in
+   non-ANSI C where `const' is problematical.  */
+#endif /* C++ or ANSI C.  */
+
+#ifndef const
+# if (defined __STDC__ && __STDC__) || defined __cplusplus || defined WINDOWS32
+#  define __const	const
+# else
+#  define __const
+# endif
+#endif
+
+/* We #undef these before defining them because some losing systems
+   (HP-UX A.08.07 for example) define these in <unistd.h>.  */
+#undef	FNM_PATHNAME
+#undef	FNM_NOESCAPE
+#undef	FNM_PERIOD
+
+/* Bits set in the FLAGS argument to `fnmatch'.  */
+#define	FNM_PATHNAME	(1 << 0) /* No wildcard can ever match `/'.  */
+#define	FNM_NOESCAPE	(1 << 1) /* Backslashes don't quote special chars.  */
+#define	FNM_PERIOD	(1 << 2) /* Leading `.' is matched only explicitly.  */
+
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
+# define FNM_FILE_NAME	 FNM_PATHNAME	/* Preferred GNU name.  */
+# define FNM_LEADING_DIR (1 << 3)	/* Ignore `/...' after a match.  */
+# define FNM_CASEFOLD	 (1 << 4)	/* Compare without regard to case.  */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN.  */
+#define	FNM_NOMATCH	1
+
+/* This value is returned if the implementation does not support
+   `fnmatch'.  Since this is not the case here it will never be
+   returned but the conformance test suites still require the symbol
+   to be defined.  */
+#ifdef _XOPEN_SOURCE
+# define FNM_NOSYS	(-1)
+#endif
+
+/* Match NAME against the filename pattern PATTERN,
+   returning zero if it matches, FNM_NOMATCH if not.  */
+extern int fnmatch __P ((__const char *__pattern, __const char *__name,
+			 int __flags));
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
Index: /tags/kBuild-0.1.4/src/kmk/glob/glob.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/glob.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/glob.c	(revision 1780)
@@ -0,0 +1,1428 @@
+/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this library; see the file COPYING.LIB.  If not, write to the Free
+Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA.  */
+
+/* AIX requires this to be the first thing in the file.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef	HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Enable GNU extensions in glob.h.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* Outcomment the following line for production quality code.  */
+/* #define NDEBUG 1 */
+#include <assert.h>
+
+#include <stdio.h>		/* Needed on stupid SunOS for assert.  */
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GLOB_INTERFACE_VERSION 1
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <stddef.h>
+#endif
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+# ifndef POSIX
+#  ifdef _POSIX_VERSION
+#   define POSIX
+#  endif
+# endif
+#endif
+
+#if !defined _AMIGA && !defined VMS && !defined WINDOWS32
+# include <pwd.h>
+#endif
+
+#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+#ifndef	NULL
+# define NULL	0
+#endif
+
+
+#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+# ifdef HAVE_VMSDIR_H
+#  include "vmsdir.h"
+# endif /* HAVE_VMSDIR_H */
+#endif
+
+
+/* In GNU systems, <dirent.h> defines this macro for us.  */
+#ifdef _D_NAMLEN
+# undef NAMLEN
+# define NAMLEN(d) _D_NAMLEN(d)
+#endif
+
+/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
+   if the `d_type' member for `struct dirent' is available.  */
+#ifdef _DIRENT_HAVE_D_TYPE
+# define HAVE_D_TYPE	1
+#endif
+
+
+#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+/* Posix does not require that the d_ino field be present, and some
+   systems do not provide it. */
+# define REAL_DIR_ENTRY(dp) 1
+#else
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+#endif /* POSIX */
+
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <stdlib.h>
+# include <string.h>
+# define	ANSI_STRING
+#else	/* No standard headers.  */
+
+extern char *getenv ();
+
+# ifdef HAVE_STRING_H
+#  include <string.h>
+#  define ANSI_STRING
+# else
+#  include <strings.h>
+# endif
+# ifdef	HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+
+extern char *malloc (), *realloc ();
+extern void free ();
+
+extern void qsort ();
+extern void abort (), exit ();
+
+#endif	/* Standard headers.  */
+
+#ifndef	ANSI_STRING
+
+# ifndef bzero
+extern void bzero ();
+# endif
+# ifndef bcopy
+extern void bcopy ();
+# endif
+
+# define memcpy(d, s, n)	bcopy ((s), (d), (n))
+# define strrchr	rindex
+/* memset is only used for zero here, but let's be paranoid.  */
+# define memset(s, better_be_zero, n) \
+  ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
+#endif	/* Not ANSI_STRING.  */
+
+#if !defined HAVE_STRCOLL && !defined _LIBC
+# define strcoll	strcmp
+#endif
+
+#if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1
+# define HAVE_MEMPCPY	1
+# undef  mempcpy
+# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
+#endif
+
+#if !defined(__GNU_LIBRARY__) && !defined(ELECTRIC_HEAP) && !defined(__APPLE__) /* bird (last two) */
+# ifdef	__GNUC__
+__inline
+# endif
+# ifndef __SASC
+#  ifdef WINDOWS32
+#   include <malloc.h>
+static void *
+my_realloc (void *p, unsigned int n)
+#  else
+static char *
+my_realloc (p, n)
+     char *p;
+     unsigned int n;
+# endif
+{
+  /* These casts are the for sake of the broken Ultrix compiler,
+     which warns of illegal pointer combinations otherwise.  */
+  if (p == NULL)
+    return (char *) malloc (n);
+  return (char *) realloc (p, n);
+}
+# define	realloc	my_realloc
+# endif /* __SASC */
+#endif /* __GNU_LIBRARY__ */
+
+
+#if !defined __alloca && !defined __GNU_LIBRARY__
+
+# ifdef	__GNUC__
+#  undef alloca
+#  define alloca(n)	__builtin_alloca (n)
+# else	/* Not GCC.  */
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else	/* Not HAVE_ALLOCA_H.  */
+#   ifndef _AIX
+#    ifdef WINDOWS32
+#     include <malloc.h>
+#    else
+extern char *alloca ();
+#    endif /* WINDOWS32 */
+#   endif /* Not _AIX.  */
+#  endif /* sparc or HAVE_ALLOCA_H.  */
+# endif	/* GCC.  */
+
+# define __alloca	alloca
+
+#endif
+
+#ifndef __GNU_LIBRARY__
+# define __stat stat
+# ifdef STAT_MACROS_BROKEN
+#  undef S_ISDIR
+# endif
+# ifndef S_ISDIR
+#  define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+# endif
+#endif
+
+#ifdef _LIBC
+# undef strdup
+# define strdup(str) __strdup (str)
+# define sysconf(id) __sysconf (id)
+# define closedir(dir) __closedir (dir)
+# define opendir(name) __opendir (name)
+# define readdir(str) __readdir (str)
+# define getpwnam_r(name, bufp, buf, len, res) \
+   __getpwnam_r (name, bufp, buf, len, res)
+# ifndef __stat
+#  define __stat(fname, buf) __xstat (_STAT_VER, fname, buf)
+# endif
+#endif
+
+#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
+# undef	size_t
+# define size_t	unsigned int
+#endif
+
+/* Some system header files erroneously define these.
+   We want our own definitions from <fnmatch.h> to take precedence.  */
+#ifndef __GNU_LIBRARY__
+# undef	FNM_PATHNAME
+# undef	FNM_NOESCAPE
+# undef	FNM_PERIOD
+#endif
+#include <fnmatch.h>
+
+/* Some system header files erroneously define these.
+   We want our own definitions from <glob.h> to take precedence.  */
+#ifndef __GNU_LIBRARY__
+# undef	GLOB_ERR
+# undef	GLOB_MARK
+# undef	GLOB_NOSORT
+# undef	GLOB_DOOFFS
+# undef	GLOB_NOCHECK
+# undef	GLOB_APPEND
+# undef	GLOB_NOESCAPE
+# undef	GLOB_PERIOD
+#endif
+#include <glob.h>
+
+#ifdef HAVE_GETLOGIN_R
+extern int getlogin_r __P ((char *, size_t));
+#else
+extern char *getlogin __P ((void));
+#endif
+
+
+static
+#if __GNUC__ - 0 >= 2
+inline
+#endif
+const char *next_brace_sub __P ((const char *begin));
+static int glob_in_dir __P ((const char *pattern, const char *directory,
+			     int flags,
+			     int (*errfunc) (const char *, int),
+			     glob_t *pglob));
+static int prefix_array __P ((const char *prefix, char **array, size_t n));
+static int collated_compare __P ((const __ptr_t, const __ptr_t));
+
+#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
+int __glob_pattern_p __P ((const char *pattern, int quote));
+#endif
+
+/* Find the end of the sub-pattern in a brace expression.  We define
+   this as an inline function if the compiler permits.  */
+static
+#if __GNUC__ - 0 >= 2
+inline
+#endif
+const char *
+next_brace_sub (begin)
+     const char *begin;
+{
+  unsigned int depth = 0;
+  const char *cp = begin;
+
+  while (1)
+    {
+      if (depth == 0)
+	{
+	  if (*cp != ',' && *cp != '}' && *cp != '\0')
+	    {
+	      if (*cp == '{')
+		++depth;
+	      ++cp;
+	      continue;
+	    }
+	}
+      else
+	{
+	  while (*cp != '\0' && (*cp != '}' || depth > 0))
+	    {
+	      if (*cp == '}')
+		--depth;
+	      ++cp;
+	    }
+	  if (*cp == '\0')
+	    /* An incorrectly terminated brace expression.  */
+	    return NULL;
+
+	  continue;
+	}
+      break;
+    }
+
+  return cp;
+}
+
+/* Do glob searching for PATTERN, placing results in PGLOB.
+   The bits defined above may be set in FLAGS.
+   If a directory cannot be opened or read and ERRFUNC is not nil,
+   it is called with the pathname that caused the error, and the
+   `errno' value from the failing call; if it returns non-zero
+   `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
+   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+   Otherwise, `glob' returns zero.  */
+int
+glob (pattern, flags, errfunc, pglob)
+     const char *pattern;
+     int flags;
+     int (*errfunc) __P ((const char *, int));
+     glob_t *pglob;
+{
+  const char *filename;
+  const char *dirname;
+  size_t dirlen;
+  int status;
+  __size_t oldcount; /* bird: correct type. */
+
+  if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  if (flags & GLOB_BRACE)
+    {
+      const char *begin = strchr (pattern, '{');
+      if (begin != NULL)
+	{
+	  /* Allocate working buffer large enough for our work.  Note that
+	    we have at least an opening and closing brace.  */
+	  int firstc;
+	  char *alt_start;
+	  const char *p;
+	  const char *next;
+	  const char *rest;
+	  size_t rest_len;
+#ifdef __GNUC__
+	  char onealt[strlen (pattern) - 1];
+#else
+	  char *onealt = (char *) malloc (strlen (pattern) - 1);
+	  if (onealt == NULL)
+	    {
+	      if (!(flags & GLOB_APPEND))
+		globfree (pglob);
+	      return GLOB_NOSPACE;
+	    }
+#endif
+
+	  /* We know the prefix for all sub-patterns.  */
+#ifdef HAVE_MEMPCPY
+	  alt_start = mempcpy (onealt, pattern, begin - pattern);
+#else
+	  memcpy (onealt, pattern, begin - pattern);
+	  alt_start = &onealt[begin - pattern];
+#endif
+
+	  /* Find the first sub-pattern and at the same time find the
+	     rest after the closing brace.  */
+	  next = next_brace_sub (begin + 1);
+	  if (next == NULL)
+	    {
+	      /* It is an illegal expression.  */
+#ifndef __GNUC__
+	      free (onealt);
+#endif
+	      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+	    }
+
+	  /* Now find the end of the whole brace expression.  */
+	  rest = next;
+	  while (*rest != '}')
+	    {
+	      rest = next_brace_sub (rest + 1);
+	      if (rest == NULL)
+		{
+		  /* It is an illegal expression.  */
+#ifndef __GNUC__
+		  free (onealt);
+#endif
+		  return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+		}
+	    }
+	  /* Please note that we now can be sure the brace expression
+	     is well-formed.  */
+	  rest_len = strlen (++rest) + 1;
+
+	  /* We have a brace expression.  BEGIN points to the opening {,
+	     NEXT points past the terminator of the first element, and END
+	     points past the final }.  We will accumulate result names from
+	     recursive runs for each brace alternative in the buffer using
+	     GLOB_APPEND.  */
+
+	  if (!(flags & GLOB_APPEND))
+	    {
+	      /* This call is to set a new vector, so clear out the
+		 vector so we can append to it.  */
+	      pglob->gl_pathc = 0;
+	      pglob->gl_pathv = NULL;
+	    }
+	  firstc = pglob->gl_pathc;
+
+	  p = begin + 1;
+	  while (1)
+	    {
+	      int result;
+
+	      /* Construct the new glob expression.  */
+#ifdef HAVE_MEMPCPY
+	      mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
+#else
+	      memcpy (alt_start, p, next - p);
+	      memcpy (&alt_start[next - p], rest, rest_len);
+#endif
+
+	      result = glob (onealt,
+			     ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
+			      | GLOB_APPEND), errfunc, pglob);
+
+	      /* If we got an error, return it.  */
+	      if (result && result != GLOB_NOMATCH)
+		{
+#ifndef __GNUC__
+		  free (onealt);
+#endif
+		  if (!(flags & GLOB_APPEND))
+		    globfree (pglob);
+		  return result;
+		}
+
+	      if (*next == '}')
+		/* We saw the last entry.  */
+		break;
+
+	      p = next + 1;
+	      next = next_brace_sub (p);
+	      assert (next != NULL);
+	    }
+
+#ifndef __GNUC__
+	  free (onealt);
+#endif
+
+	  if (pglob->gl_pathc != firstc)
+	    /* We found some entries.  */
+	    return 0;
+	  else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+	    return GLOB_NOMATCH;
+	}
+    }
+
+  /* Find the filename.  */
+  filename = strrchr (pattern, '/');
+#if defined __MSDOS__ || defined WINDOWS32
+  /* The case of "d:pattern".  Since `:' is not allowed in
+     file names, we can safely assume that wherever it
+     happens in pattern, it signals the filename part.  This
+     is so we could some day support patterns like "[a-z]:foo".  */
+  if (filename == NULL)
+    filename = strchr (pattern, ':');
+#endif /* __MSDOS__ || WINDOWS32 */
+  if (filename == NULL)
+    {
+      /* This can mean two things: a simple name or "~name".  The later
+	 case is nothing but a notation for a directory.  */
+      if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
+	{
+	  dirname = pattern;
+	  dirlen = strlen (pattern);
+
+	  /* Set FILENAME to NULL as a special flag.  This is ugly but
+	     other solutions would require much more code.  We test for
+	     this special case below.  */
+	  filename = NULL;
+	}
+      else
+	{
+	  filename = pattern;
+#ifdef _AMIGA
+	  dirname = "";
+#else
+	  dirname = ".";
+#endif
+	  dirlen = 0;
+	}
+    }
+  else if (filename == pattern)
+    {
+      /* "/pattern".  */
+      dirname = "/";
+      dirlen = 1;
+      ++filename;
+    }
+  else
+    {
+      char *newp;
+      dirlen = filename - pattern;
+#if defined __MSDOS__ || defined WINDOWS32
+      if (*filename == ':'
+	  || (filename > pattern + 1 && filename[-1] == ':'))
+	{
+	  char *drive_spec;
+
+	  ++dirlen;
+	  drive_spec = (char *) __alloca (dirlen + 1);
+#ifdef HAVE_MEMPCPY
+	  *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
+#else
+	  memcpy (drive_spec, pattern, dirlen);
+	  drive_spec[dirlen] = '\0';
+#endif
+	  /* For now, disallow wildcards in the drive spec, to
+	     prevent infinite recursion in glob.  */
+	  if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
+	    return GLOB_NOMATCH;
+	  /* If this is "d:pattern", we need to copy `:' to DIRNAME
+	     as well.  If it's "d:/pattern", don't remove the slash
+	     from "d:/", since "d:" and "d:/" are not the same.*/
+	}
+#endif
+      newp = (char *) __alloca (dirlen + 1);
+#ifdef HAVE_MEMPCPY
+      *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
+#else
+      memcpy (newp, pattern, dirlen);
+      newp[dirlen] = '\0';
+#endif
+      dirname = newp;
+      ++filename;
+
+      if (filename[0] == '\0'
+#if defined __MSDOS__ || defined WINDOWS32
+          && dirname[dirlen - 1] != ':'
+	  && (dirlen < 3 || dirname[dirlen - 2] != ':'
+	      || dirname[dirlen - 1] != '/')
+#endif
+	  && dirlen > 1)
+	/* "pattern/".  Expand "pattern", appending slashes.  */
+	{
+	  int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+	  if (val == 0)
+	    pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
+			       | (flags & GLOB_MARK));
+	  return val;
+	}
+    }
+
+  if (!(flags & GLOB_APPEND))
+    {
+      pglob->gl_pathc = 0;
+      pglob->gl_pathv = NULL;
+    }
+
+  oldcount = pglob->gl_pathc;
+
+#ifndef VMS
+  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
+    {
+      if (dirname[1] == '\0' || dirname[1] == '/')
+	{
+	  /* Look up home directory.  */
+#ifdef VMS
+/* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */
+          const char *home_dir = getenv ("SYS$LOGIN");
+#else
+          const char *home_dir = getenv ("HOME");
+#endif
+# ifdef _AMIGA
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    home_dir = "SYS:";
+# else
+#  ifdef WINDOWS32
+	  if (home_dir == NULL || home_dir[0] == '\0')
+            home_dir = "c:/users/default"; /* poor default */
+#  else
+#   ifdef VMS
+/* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    home_dir = "SYS$DISK:[]";
+#   else
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    {
+	      int success;
+	      char *name;
+#   if defined HAVE_GETLOGIN_R || defined _LIBC
+	      size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
+
+	      if (buflen == 0)
+		/* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
+		   a moderate value.  */
+		buflen = 20;
+	      name = (char *) __alloca (buflen);
+
+	      success = getlogin_r (name, buflen) >= 0;
+#   else
+	      success = (name = getlogin ()) != NULL;
+#   endif
+	      if (success)
+		{
+		  struct passwd *p;
+#   if defined HAVE_GETPWNAM_R || defined _LIBC
+		  size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+		  char *pwtmpbuf;
+		  struct passwd pwbuf;
+		  int save = errno;
+
+		  if (pwbuflen == -1)
+		    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
+		       Try a moderate value.  */
+		    pwbuflen = 1024;
+		  pwtmpbuf = (char *) __alloca (pwbuflen);
+
+		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+			 != 0)
+		    {
+		      if (errno != ERANGE)
+			{
+			  p = NULL;
+			  break;
+			}
+		      pwbuflen *= 2;
+		      pwtmpbuf = (char *) __alloca (pwbuflen);
+		      __set_errno (save);
+		    }
+#   else
+		  p = getpwnam (name);
+#   endif
+		  if (p != NULL)
+		    home_dir = p->pw_dir;
+		}
+	    }
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    {
+	      if (flags & GLOB_TILDE_CHECK)
+		return GLOB_NOMATCH;
+	      else
+		home_dir = "~"; /* No luck.  */
+	    }
+#   endif /* VMS */
+#  endif /* WINDOWS32 */
+# endif
+	  /* Now construct the full directory.  */
+	  if (dirname[1] == '\0')
+	    dirname = home_dir;
+	  else
+	    {
+	      char *newp;
+	      size_t home_len = strlen (home_dir);
+	      newp = (char *) __alloca (home_len + dirlen);
+# ifdef HAVE_MEMPCPY
+	      mempcpy (mempcpy (newp, home_dir, home_len),
+		       &dirname[1], dirlen);
+# else
+	      memcpy (newp, home_dir, home_len);
+	      memcpy (&newp[home_len], &dirname[1], dirlen);
+# endif
+	      dirname = newp;
+	    }
+	}
+# if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
+      else
+	{
+	  char *end_name = strchr (dirname, '/');
+	  const char *user_name;
+	  const char *home_dir;
+
+	  if (end_name == NULL)
+	    user_name = dirname + 1;
+	  else
+	    {
+	      char *newp;
+	      newp = (char *) __alloca (end_name - dirname);
+# ifdef HAVE_MEMPCPY
+	      *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
+		= '\0';
+# else
+	      memcpy (newp, dirname + 1, end_name - dirname);
+	      newp[end_name - dirname - 1] = '\0';
+# endif
+	      user_name = newp;
+	    }
+
+	  /* Look up specific user's home directory.  */
+	  {
+	    struct passwd *p;
+#  if defined HAVE_GETPWNAM_R || defined _LIBC
+	    size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+	    char *pwtmpbuf;
+	    struct passwd pwbuf;
+	    int save = errno;
+
+	    if (buflen == -1)
+	      /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
+		 moderate value.  */
+	      buflen = 1024;
+	    pwtmpbuf = (char *) __alloca (buflen);
+
+	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+	      {
+		if (errno != ERANGE)
+		  {
+		    p = NULL;
+		    break;
+		  }
+		buflen *= 2;
+		pwtmpbuf = __alloca (buflen);
+		__set_errno (save);
+	      }
+#  else
+	    p = getpwnam (user_name);
+#  endif
+	    if (p != NULL)
+	      home_dir = p->pw_dir;
+	    else
+	      home_dir = NULL;
+	  }
+	  /* If we found a home directory use this.  */
+	  if (home_dir != NULL)
+	    {
+	      char *newp;
+	      size_t home_len = strlen (home_dir);
+	      size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+	      newp = (char *) __alloca (home_len + rest_len + 1);
+#  ifdef HAVE_MEMPCPY
+	      *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
+				  end_name, rest_len)) = '\0';
+#  else
+	      memcpy (newp, home_dir, home_len);
+	      memcpy (&newp[home_len], end_name, rest_len);
+	      newp[home_len + rest_len] = '\0';
+#  endif
+	      dirname = newp;
+	    }
+	  else
+	    if (flags & GLOB_TILDE_CHECK)
+	      /* We have to regard it as an error if we cannot find the
+		 home directory.  */
+	      return GLOB_NOMATCH;
+	}
+# endif	/* Not Amiga && not WINDOWS32 && not VMS.  */
+    }
+#endif	/* Not VMS.  */
+
+  /* Now test whether we looked for "~" or "~NAME".  In this case we
+     can give the answer now.  */
+  if (filename == NULL)
+    {
+      struct stat st;
+
+      /* Return the directory if we don't check for error or if it exists.  */
+      if ((flags & GLOB_NOCHECK)
+	  || (((flags & GLOB_ALTDIRFUNC)
+	       ? (*pglob->gl_stat) (dirname, &st)
+	       : __stat (dirname, &st)) == 0
+	      && S_ISDIR (st.st_mode)))
+	{
+	  pglob->gl_pathv
+	    = (char **) realloc (pglob->gl_pathv,
+				 (pglob->gl_pathc +
+				  ((flags & GLOB_DOOFFS) ?
+				   pglob->gl_offs : 0) +
+				  1 + 1) *
+				 sizeof (char *));
+	  if (pglob->gl_pathv == NULL)
+	    return GLOB_NOSPACE;
+
+	  if (flags & GLOB_DOOFFS)
+	    while (pglob->gl_pathc < pglob->gl_offs)
+	      pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+#if defined HAVE_STRDUP || defined _LIBC
+	  pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);
+#else
+	  {
+	    size_t len = strlen (dirname) + 1;
+	    char *dircopy = malloc (len);
+	    if (dircopy != NULL)
+	      pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
+							 len);
+	  }
+#endif
+	  if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
+	    {
+	      free (pglob->gl_pathv);
+	      return GLOB_NOSPACE;
+	    }
+	  pglob->gl_pathv[++pglob->gl_pathc] = NULL;
+	  pglob->gl_flags = flags;
+
+	  return 0;
+	}
+
+      /* Not found.  */
+      return GLOB_NOMATCH;
+    }
+
+  if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
+    {
+      /* The directory name contains metacharacters, so we
+	 have to glob for the directory, and then glob for
+	 the pattern in each directory found.  */
+      glob_t dirs;
+      register __size_t i; /* bird: correct type. */
+
+      status = glob (dirname,
+		     ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
+		      | GLOB_NOSORT | GLOB_ONLYDIR),
+		     errfunc, &dirs);
+      if (status != 0)
+	return status;
+
+      /* We have successfully globbed the preceding directory name.
+	 For each name we found, call glob_in_dir on it and FILENAME,
+	 appending the results to PGLOB.  */
+      for (i = 0; i < dirs.gl_pathc; ++i)
+	{
+	  int old_pathc;
+
+#ifdef	SHELL
+	  {
+	    /* Make globbing interruptible in the bash shell. */
+	    extern int interrupt_state;
+
+	    if (interrupt_state)
+	      {
+		globfree (&dirs);
+		globfree (&files);
+		return GLOB_ABORTED;
+	      }
+	  }
+#endif /* SHELL.  */
+
+	  old_pathc = pglob->gl_pathc;
+	  status = glob_in_dir (filename, dirs.gl_pathv[i],
+				((flags | GLOB_APPEND)
+				 & ~(GLOB_NOCHECK | GLOB_ERR)),
+				errfunc, pglob);
+	  if (status == GLOB_NOMATCH)
+	    /* No matches in this directory.  Try the next.  */
+	    continue;
+
+	  if (status != 0)
+	    {
+	      globfree (&dirs);
+	      globfree (pglob);
+	      return status;
+	    }
+
+	  /* Stick the directory on the front of each name.  */
+	  if (prefix_array (dirs.gl_pathv[i],
+			    &pglob->gl_pathv[old_pathc],
+			    pglob->gl_pathc - old_pathc))
+	    {
+	      globfree (&dirs);
+	      globfree (pglob);
+	      return GLOB_NOSPACE;
+	    }
+	}
+
+      flags |= GLOB_MAGCHAR;
+
+      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
+	 But if we have not found any matching entry and thie GLOB_NOCHECK
+	 flag was set we must return the list consisting of the disrectory
+	 names followed by the filename.  */
+      if (pglob->gl_pathc == oldcount)
+	{
+	  /* No matches.  */
+	  if (flags & GLOB_NOCHECK)
+	    {
+	      size_t filename_len = strlen (filename) + 1;
+	      char **new_pathv;
+	      struct stat st;
+
+	      /* This is an pessimistic guess about the size.  */
+	      pglob->gl_pathv
+		= (char **) realloc (pglob->gl_pathv,
+				     (pglob->gl_pathc +
+				      ((flags & GLOB_DOOFFS) ?
+				       pglob->gl_offs : 0) +
+				      dirs.gl_pathc + 1) *
+				     sizeof (char *));
+	      if (pglob->gl_pathv == NULL)
+		{
+		  globfree (&dirs);
+		  return GLOB_NOSPACE;
+		}
+
+	      if (flags & GLOB_DOOFFS)
+		while (pglob->gl_pathc < pglob->gl_offs)
+		  pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+	      for (i = 0; i < dirs.gl_pathc; ++i)
+		{
+		  const char *dir = dirs.gl_pathv[i];
+		  size_t dir_len = strlen (dir);
+
+		  /* First check whether this really is a directory.  */
+		  if (((flags & GLOB_ALTDIRFUNC)
+		       ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
+		      || !S_ISDIR (st.st_mode))
+		    /* No directory, ignore this entry.  */
+		    continue;
+
+		  pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1
+							     + filename_len);
+		  if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
+		    {
+		      globfree (&dirs);
+		      globfree (pglob);
+		      return GLOB_NOSPACE;
+		    }
+
+#ifdef HAVE_MEMPCPY
+		  mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
+					     dir, dir_len),
+				    "/", 1),
+			   filename, filename_len);
+#else
+		  memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
+		  pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
+		  memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
+			  filename, filename_len);
+#endif
+		  ++pglob->gl_pathc;
+		}
+
+	      pglob->gl_pathv[pglob->gl_pathc] = NULL;
+	      pglob->gl_flags = flags;
+
+	      /* Now we know how large the gl_pathv vector must be.  */
+	      new_pathv = (char **) realloc (pglob->gl_pathv,
+					     ((pglob->gl_pathc + 1)
+					      * sizeof (char *)));
+	      if (new_pathv != NULL)
+		pglob->gl_pathv = new_pathv;
+	    }
+	  else
+	    return GLOB_NOMATCH;
+	}
+
+      globfree (&dirs);
+    }
+  else
+    {
+      status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
+      if (status != 0)
+	return status;
+
+      if (dirlen > 0)
+	{
+	  /* Stick the directory on the front of each name.  */
+	  __size_t ignore = oldcount; /* bird: correct type. */
+
+	  if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)
+	    ignore = pglob->gl_offs;
+
+	  if (prefix_array (dirname,
+			    &pglob->gl_pathv[ignore],
+			    pglob->gl_pathc - ignore))
+	    {
+	      globfree (pglob);
+	      return GLOB_NOSPACE;
+	    }
+	}
+    }
+
+  if (flags & GLOB_MARK)
+    {
+      /* Append slashes to directory names.  */
+      __size_t i; /* bird: correct type. */
+      struct stat st;
+      for (i = oldcount; i < pglob->gl_pathc; ++i)
+	if (((flags & GLOB_ALTDIRFUNC)
+	     ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
+	     : __stat (pglob->gl_pathv[i], &st)) == 0
+	    && S_ISDIR (st.st_mode))
+	  {
+ 	    size_t len = strlen (pglob->gl_pathv[i]) + 2;
+	    char *new = realloc (pglob->gl_pathv[i], len);
+ 	    if (new == NULL)
+	      {
+		globfree (pglob);
+		return GLOB_NOSPACE;
+	      }
+	    strcpy (&new[len - 2], "/");
+	    pglob->gl_pathv[i] = new;
+	  }
+    }
+
+  if (!(flags & GLOB_NOSORT))
+    {
+      /* Sort the vector.  */
+      int non_sort = oldcount;
+
+      if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
+	non_sort = pglob->gl_offs;
+
+      qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
+	     pglob->gl_pathc - non_sort,
+	     sizeof (char *), collated_compare);
+    }
+
+  return 0;
+}
+
+
+/* Free storage allocated in PGLOB by a previous `glob' call.  */
+void
+globfree (pglob)
+     register glob_t *pglob;
+{
+  if (pglob->gl_pathv != NULL)
+    {
+      register __size_t i; /* bird: correct type */
+      for (i = 0; i < pglob->gl_pathc; ++i)
+	if (pglob->gl_pathv[i] != NULL)
+	  free ((__ptr_t) pglob->gl_pathv[i]);
+      free ((__ptr_t) pglob->gl_pathv);
+    }
+}
+
+
+/* Do a collated comparison of A and B.  */
+static int
+collated_compare (a, b)
+     const __ptr_t a;
+     const __ptr_t b;
+{
+  const char *const s1 = *(const char *const * const) a;
+  const char *const s2 = *(const char *const * const) b;
+
+  if (s1 == s2)
+    return 0;
+  if (s1 == NULL)
+    return 1;
+  if (s2 == NULL)
+    return -1;
+  return strcoll (s1, s2);
+}
+
+
+/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
+   elements in place.  Return nonzero if out of memory, zero if successful.
+   A slash is inserted between DIRNAME and each elt of ARRAY,
+   unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
+static int
+prefix_array (dirname, array, n)
+     const char *dirname;
+     char **array;
+     size_t n;
+{
+  register size_t i;
+  size_t dirlen = strlen (dirname);
+#if defined __MSDOS__ || defined WINDOWS32
+  int sep_char = '/';
+# define DIRSEP_CHAR sep_char
+#else
+# define DIRSEP_CHAR '/'
+#endif
+
+  if (dirlen == 1 && dirname[0] == '/')
+    /* DIRNAME is just "/", so normal prepending would get us "//foo".
+       We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
+    dirlen = 0;
+#if defined __MSDOS__ || defined WINDOWS32
+  else if (dirlen > 1)
+    {
+      if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
+	/* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
+	--dirlen;
+      else if (dirname[dirlen - 1] == ':')
+	{
+	  /* DIRNAME is "d:".  Use `:' instead of `/'.  */
+	  --dirlen;
+	  sep_char = ':';
+	}
+    }
+#endif
+
+  for (i = 0; i < n; ++i)
+    {
+      size_t eltlen = strlen (array[i]) + 1;
+      char *new = (char *) malloc (dirlen + 1 + eltlen);
+      if (new == NULL)
+	{
+	  while (i > 0)
+	    free ((__ptr_t) array[--i]);
+	  return 1;
+	}
+
+#ifdef HAVE_MEMPCPY
+      {
+	char *endp = (char *) mempcpy (new, dirname, dirlen);
+	*endp++ = DIRSEP_CHAR;
+	mempcpy (endp, array[i], eltlen);
+      }
+#else
+      memcpy (new, dirname, dirlen);
+      new[dirlen] = DIRSEP_CHAR;
+      memcpy (&new[dirlen + 1], array[i], eltlen);
+#endif
+      free ((__ptr_t) array[i]);
+      array[i] = new;
+    }
+
+  return 0;
+}
+
+
+/* We must not compile this function twice.  */
+#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
+/* Return nonzero if PATTERN contains any metacharacters.
+   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
+int
+__glob_pattern_p (pattern, quote)
+     const char *pattern;
+     int quote;
+{
+  register const char *p;
+  int open = 0;
+
+  for (p = pattern; *p != '\0'; ++p)
+    switch (*p)
+      {
+      case '?':
+      case '*':
+	return 1;
+
+      case '\\':
+	if (quote && p[1] != '\0')
+	  ++p;
+	break;
+
+      case '[':
+	open = 1;
+	break;
+
+      case ']':
+	if (open)
+	  return 1;
+	break;
+      }
+
+  return 0;
+}
+# ifdef _LIBC
+weak_alias (__glob_pattern_p, glob_pattern_p)
+# endif
+#endif
+
+
+/* Like `glob', but PATTERN is a final pathname component,
+   and matches are searched for in DIRECTORY.
+   The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
+   The GLOB_APPEND flag is assumed to be set (always appends).  */
+static int
+glob_in_dir (pattern, directory, flags, errfunc, pglob)
+     const char *pattern;
+     const char *directory;
+     int flags;
+     int (*errfunc) __P ((const char *, int));
+     glob_t *pglob;
+{
+  __ptr_t stream = NULL;
+
+  struct globlink
+    {
+      struct globlink *next;
+      char *name;
+    };
+  struct globlink *names = NULL;
+  size_t nfound;
+  int meta;
+  int save;
+
+#ifdef VMS
+  if (*directory == 0)
+    directory = "[]";
+#endif
+  meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
+  if (meta == 0)
+    {
+      if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
+	/* We need not do any tests.  The PATTERN contains no meta
+	   characters and we must not return an error therefore the
+	   result will always contain exactly one name.  */
+	flags |= GLOB_NOCHECK;
+      else
+	{
+	  /* Since we use the normal file functions we can also use stat()
+	     to verify the file is there.  */
+	  struct stat st;
+	  size_t patlen = strlen (pattern);
+	  size_t dirlen = strlen (directory);
+	  char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
+
+# ifdef HAVE_MEMPCPY
+	  mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
+			    "/", 1),
+		   pattern, patlen + 1);
+# else
+	  memcpy (fullname, directory, dirlen);
+	  fullname[dirlen] = '/';
+	  memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
+# endif
+	  if (((flags & GLOB_ALTDIRFUNC)
+	       ? (*pglob->gl_stat) (fullname, &st)
+	       : __stat (fullname, &st)) == 0)
+	    /* We found this file to be existing.  Now tell the rest
+	       of the function to copy this name into the result.  */
+	    flags |= GLOB_NOCHECK;
+	}
+
+      nfound = 0;
+    }
+  else
+    {
+      if (pattern[0] == '\0')
+	{
+	  /* This is a special case for matching directories like in
+	     "*a/".  */
+	  names = (struct globlink *) __alloca (sizeof (struct globlink));
+	  names->name = (char *) malloc (1);
+	  if (names->name == NULL)
+	    goto memory_error;
+	  names->name[0] = '\0';
+	  names->next = NULL;
+	  nfound = 1;
+	  meta = 0;
+	}
+      else
+	{
+	  stream = ((flags & GLOB_ALTDIRFUNC)
+		    ? (*pglob->gl_opendir) (directory)
+		    : (__ptr_t) opendir (directory));
+	  if (stream == NULL)
+	    {
+	      if (errno != ENOTDIR
+		  && ((errfunc != NULL && (*errfunc) (directory, errno))
+		      || (flags & GLOB_ERR)))
+		return GLOB_ABORTED;
+	      nfound = 0;
+	      meta = 0;
+	    }
+	  else
+	    {
+	      int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+			       | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
+#if defined HAVE_CASE_INSENSITIVE_FS
+				   | FNM_CASEFOLD
+#endif
+				   );
+	      nfound = 0;
+	      flags |= GLOB_MAGCHAR;
+
+	      while (1)
+		{
+		  const char *name;
+		  size_t len;
+		  struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
+				      ? (*pglob->gl_readdir) (stream)
+				      : readdir ((DIR *) stream));
+		  if (d == NULL)
+		    break;
+		  if (! REAL_DIR_ENTRY (d))
+		    continue;
+
+#ifdef HAVE_D_TYPE
+		  /* If we shall match only directories use the information
+		     provided by the dirent call if possible.  */
+		  if ((flags & GLOB_ONLYDIR)
+		      && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
+		    continue;
+#endif
+
+		  name = d->d_name;
+
+		  if (fnmatch (pattern, name, fnm_flags) == 0)
+		    {
+		      struct globlink *new = (struct globlink *)
+			__alloca (sizeof (struct globlink));
+		      len = NAMLEN (d);
+		      new->name = (char *) malloc (len + 1);
+		      if (new->name == NULL)
+			goto memory_error;
+#ifdef HAVE_MEMPCPY
+		      *((char *) mempcpy ((__ptr_t) new->name, name, len))
+			= '\0';
+#else
+		      memcpy ((__ptr_t) new->name, name, len);
+		      new->name[len] = '\0';
+#endif
+		      new->next = names;
+		      names = new;
+		      ++nfound;
+		    }
+		}
+	    }
+	}
+    }
+
+  if (nfound == 0 && (flags & GLOB_NOCHECK))
+    {
+      size_t len = strlen (pattern);
+      nfound = 1;
+      names = (struct globlink *) __alloca (sizeof (struct globlink));
+      names->next = NULL;
+      names->name = (char *) malloc (len + 1);
+      if (names->name == NULL)
+	goto memory_error;
+#ifdef HAVE_MEMPCPY
+      *((char *) mempcpy (names->name, pattern, len)) = '\0';
+#else
+      memcpy (names->name, pattern, len);
+      names->name[len] = '\0';
+#endif
+    }
+
+  if (nfound != 0)
+    {
+      pglob->gl_pathv
+	= (char **) realloc (pglob->gl_pathv,
+			     (pglob->gl_pathc +
+			      ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
+			      nfound + 1) *
+			     sizeof (char *));
+      if (pglob->gl_pathv == NULL)
+	goto memory_error;
+
+      if (flags & GLOB_DOOFFS)
+	while (pglob->gl_pathc < pglob->gl_offs)
+	  pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+      for (; names != NULL; names = names->next)
+	pglob->gl_pathv[pglob->gl_pathc++] = names->name;
+      pglob->gl_pathv[pglob->gl_pathc] = NULL;
+
+      pglob->gl_flags = flags;
+    }
+
+  save = errno;
+  if (stream != NULL)
+    {
+      if (flags & GLOB_ALTDIRFUNC)
+	(*pglob->gl_closedir) (stream);
+      else
+	closedir ((DIR *) stream);
+    }
+  __set_errno (save);
+
+  return nfound == 0 ? GLOB_NOMATCH : 0;
+
+ memory_error:
+  {
+    int save = errno;
+    if (flags & GLOB_ALTDIRFUNC)
+      (*pglob->gl_closedir) (stream);
+    else
+      closedir ((DIR *) stream);
+    __set_errno (save);
+  }
+  while (names != NULL)
+    {
+      if (names->name != NULL)
+	free ((__ptr_t) names->name);
+      names = names->next;
+    }
+  return GLOB_NOSPACE;
+}
+
+#endif	/* Not ELIDE_CODE.  */
Index: /tags/kBuild-0.1.4/src/kmk/glob/glob.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/glob/glob.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/glob/glob.h	(revision 1780)
@@ -0,0 +1,209 @@
+/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this library; see the file COPYING.LIB.  If not, write to the Free
+Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA.  */
+
+#ifndef	_GLOB_H
+#define	_GLOB_H	1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#undef	__ptr_t
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
+# if !defined __GLIBC__
+#  undef __P
+#  undef __PMT
+#  define __P(protos)	protos
+#  define __PMT(protos)	protos
+#  if !defined __GNUC__ || __GNUC__ < 2
+#   undef __const
+#   define __const const
+#  endif
+# endif
+# define __ptr_t	void *
+#else /* Not C++ or ANSI C.  */
+# undef	__P
+# undef __PMT
+# define __P(protos)	()
+# define __PMT(protos)	()
+# undef	__const
+# define __const
+# define __ptr_t	char *
+#endif /* C++ or ANSI C.  */
+
+/* We need `size_t' for the following definitions.  */
+#ifndef __size_t
+# if defined __FreeBSD__
+#  define __size_t size_t
+# else
+#  if defined __GNUC__ && __GNUC__ >= 2
+typedef __SIZE_TYPE__ __size_t;
+#  else
+/* This is a guess.  */
+/*hb
+ *	Conflicts with DECCs aready defined type __size_t.
+ *	Defining an own type with a name beginning with '__' is no good.
+ *	Anyway if DECC is used and __SIZE_T is defined then __size_t is
+ *	already defined (and I hope it's exactly the one we need here).
+ */
+#   if !(defined __DECC && defined __SIZE_T)
+typedef unsigned long int __size_t;
+#   endif
+#  endif
+# endif
+#else
+/* The GNU CC stddef.h version defines __size_t as empty.  We need a real
+   definition.  */
+# undef __size_t
+# define __size_t size_t
+#endif
+
+/* Bits set in the FLAGS argument to `glob'.  */
+#define	GLOB_ERR	(1 << 0)/* Return on read errors.  */
+#define	GLOB_MARK	(1 << 1)/* Append a slash to each name.  */
+#define	GLOB_NOSORT	(1 << 2)/* Don't sort the names.  */
+#define	GLOB_DOOFFS	(1 << 3)/* Insert PGLOB->gl_offs NULLs.  */
+#define	GLOB_NOCHECK	(1 << 4)/* If nothing matches, return the pattern.  */
+#define	GLOB_APPEND	(1 << 5)/* Append to results of a previous call.  */
+#define	GLOB_NOESCAPE	(1 << 6)/* Backslashes don't quote metacharacters.  */
+#define	GLOB_PERIOD	(1 << 7)/* Leading `.' can be matched by metachars.  */
+
+#if (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _BSD_SOURCE \
+     || defined _GNU_SOURCE)
+# define GLOB_MAGCHAR	 (1 << 8)/* Set in gl_flags if any metachars seen.  */
+# define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions.  */
+# define GLOB_BRACE	 (1 << 10)/* Expand "{a,b}" to "a" "b".  */
+# define GLOB_NOMAGIC	 (1 << 11)/* If no magic chars, return the pattern.  */
+# define GLOB_TILDE	 (1 << 12)/* Expand ~user and ~ to home directories. */
+# define GLOB_ONLYDIR	 (1 << 13)/* Match only directories.  */
+# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error
+				      if the user name is not available.  */
+# define __GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+			 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
+			 GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE|     \
+			 GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)
+#else
+# define __GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+			 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
+			 GLOB_PERIOD)
+#endif
+
+/* Error returns from `glob'.  */
+#define	GLOB_NOSPACE	1	/* Ran out of memory.  */
+#define	GLOB_ABORTED	2	/* Read error.  */
+#define	GLOB_NOMATCH	3	/* No matches found.  */
+#define GLOB_NOSYS	4	/* Not implemented.  */
+#ifdef _GNU_SOURCE
+/* Previous versions of this file defined GLOB_ABEND instead of
+   GLOB_ABORTED.  Provide a compatibility definition here.  */
+# define GLOB_ABEND GLOB_ABORTED
+#endif
+
+/* Structure describing a globbing run.  */
+#if !defined _AMIGA && !defined VMS /* Buggy compiler.   */
+struct stat;
+#endif
+typedef struct
+  {
+    __size_t gl_pathc;		/* Count of paths matched by the pattern.  */
+    char **gl_pathv;		/* List of matched pathnames.  */
+    __size_t gl_offs;		/* Slots to reserve in `gl_pathv'.  */
+    int gl_flags;		/* Set to FLAGS, maybe | GLOB_MAGCHAR.  */
+
+    /* If the GLOB_ALTDIRFUNC flag is set, the following functions
+       are used instead of the normal file access functions.  */
+    void (*gl_closedir) __PMT ((void *));
+    struct dirent *(*gl_readdir) __PMT ((void *));
+    __ptr_t (*gl_opendir) __PMT ((__const char *));
+    int (*gl_lstat) __PMT ((__const char *, struct stat *));
+#if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE)
+    int (*gl_stat) __PMT ((__const char *, struct stat *, ...));
+#else
+    int (*gl_stat) __PMT ((__const char *, struct stat *));
+#endif
+  } glob_t;
+
+#ifdef _LARGEFILE64_SOURCE
+struct stat64;
+typedef struct
+  {
+    __size_t gl_pathc;
+    char **gl_pathv;
+    __size_t gl_offs;
+    int gl_flags;
+
+    /* If the GLOB_ALTDIRFUNC flag is set, the following functions
+       are used instead of the normal file access functions.  */
+    void (*gl_closedir) __PMT ((void *));
+    struct dirent64 *(*gl_readdir) __PMT ((void *));
+    __ptr_t (*gl_opendir) __PMT ((__const char *));
+    int (*gl_lstat) __PMT ((__const char *, struct stat64 *));
+    int (*gl_stat) __PMT ((__const char *, struct stat64 *));
+  } glob64_t;
+#endif
+
+#if _FILE_OFFSET_BITS == 64 && __GNUC__ < 2
+# define glob glob64
+# define globfree globfree64
+#else
+# ifdef _LARGEFILE64_SOURCE
+extern int glob64 __P ((__const char *__pattern, int __flags,
+			int (*__errfunc) (__const char *, int),
+			glob64_t *__pglob));
+
+extern void globfree64 __P ((glob64_t *__pglob));
+# endif
+#endif
+
+/* Do glob searching for PATTERN, placing results in PGLOB.
+   The bits defined above may be set in FLAGS.
+   If a directory cannot be opened or read and ERRFUNC is not nil,
+   it is called with the pathname that caused the error, and the
+   `errno' value from the failing call; if it returns non-zero
+   `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
+   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+   Otherwise, `glob' returns zero.  */
+#if _FILE_OFFSET_BITS != 64 || __GNUC__ < 2
+extern int glob __P ((__const char *__pattern, int __flags,
+		      int (*__errfunc) (__const char *, int),
+		      glob_t *__pglob));
+
+/* Free storage allocated in PGLOB by a previous `glob' call.  */
+extern void globfree __P ((glob_t *__pglob));
+#else
+extern int glob __P ((__const char *__pattern, int __flags,
+		      int (*__errfunc) (__const char *, int),
+		      glob_t *__pglob)) __asm__ ("glob64");
+
+extern void globfree __P ((glob_t *__pglob)) __asm__ ("globfree64");
+#endif
+
+
+#ifdef _GNU_SOURCE
+/* Return nonzero if PATTERN contains any metacharacters.
+   Metacharacters can be quoted with backslashes if QUOTE is nonzero.
+
+   This function is not part of the interface specified by POSIX.2
+   but several programs want to use it.  */
+extern int glob_pattern_p __P ((__const char *__pattern, int __quote));
+#endif
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* glob.h  */
Index: /tags/kBuild-0.1.4/src/kmk/hash.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/hash.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/hash.c	(revision 1780)
@@ -0,0 +1,338 @@
+/* hash.c -- hash table maintenance
+   Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc.
+   Written by Greg McGary <gkm@gnu.org> <greg@mcgary.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, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "hash.h"
+
+#define	CALLOC(t, n) ((t *) calloc (sizeof (t), (n)))
+#define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n)))
+#define REALLOC(o, t, n) ((t *) xrealloc ((o), sizeof (t) * (n)))
+#define CLONE(o, t, n) ((t *) memcpy (MALLOC (t, (n)), (o), sizeof (t) * (n)))
+
+static void hash_rehash __P((struct hash_table* ht));
+static unsigned long round_up_2 __P((unsigned long rough));
+
+/* Implement double hashing with open addressing.  The table size is
+   always a power of two.  The secondary (`increment') hash function
+   is forced to return an odd-value, in order to be relatively prime
+   to the table size.  This guarantees that the increment can
+   potentially hit every slot in the table during collision
+   resolution.  */
+
+void *hash_deleted_item = &hash_deleted_item;
+
+/* Force the table size to be a power of two, possibly rounding up the
+   given size.  */
+
+void
+hash_init (struct hash_table *ht, unsigned long size,
+           hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp)
+{
+  ht->ht_size = round_up_2 (size);
+  ht->ht_empty_slots = ht->ht_size;
+  ht->ht_vec = (void**) CALLOC (struct token *, ht->ht_size);
+  if (ht->ht_vec == 0)
+    {
+      fprintf (stderr, _("can't allocate %ld bytes for hash table: memory exhausted"),
+	       ht->ht_size * sizeof(struct token *));
+      exit (1);
+    }
+
+  ht->ht_capacity = ht->ht_size - (ht->ht_size / 16); /* 93.75% loading factor */
+  ht->ht_fill = 0;
+  ht->ht_collisions = 0;
+  ht->ht_lookups = 0;
+  ht->ht_rehashes = 0;
+  ht->ht_hash_1 = hash_1;
+  ht->ht_hash_2 = hash_2;
+  ht->ht_compare = hash_cmp;
+}
+
+/* Load an array of items into `ht'.  */
+
+void
+hash_load (struct hash_table *ht, void *item_table,
+           unsigned long cardinality, unsigned long size)
+{
+  char *items = (char *) item_table;
+  while (cardinality--)
+    {
+      hash_insert (ht, items);
+      items += size;
+    }
+}
+
+/* Returns the address of the table slot matching `key'.  If `key' is
+   not found, return the address of an empty slot suitable for
+   inserting `key'.  The caller is responsible for incrementing
+   ht_fill on insertion.  */
+
+void **
+hash_find_slot (struct hash_table *ht, const void *key)
+{
+  void **slot;
+  void **deleted_slot = 0;
+  unsigned int hash_2 = 0;
+  unsigned int hash_1 = (*ht->ht_hash_1) (key);
+
+  ht->ht_lookups++;
+#ifdef CONFIG_WITH_MAKE_STATS
+  make_stats_ht_lookups++;
+#endif
+  for (;;)
+    {
+      hash_1 &= (ht->ht_size - 1);
+      slot = &ht->ht_vec[hash_1];
+
+      if (*slot == 0)
+	return (deleted_slot ? deleted_slot : slot);
+      if (*slot == hash_deleted_item)
+	{
+	  if (deleted_slot == 0)
+	    deleted_slot = slot;
+	}
+      else
+	{
+	  if (key == *slot)
+	    return slot;
+	  if ((*ht->ht_compare) (key, *slot) == 0)
+	    return slot;
+	  ht->ht_collisions++;
+#ifdef CONFIG_WITH_MAKE_STATS
+	  make_stats_ht_collisions++;
+#endif
+	}
+      if (!hash_2)
+	  hash_2 = (*ht->ht_hash_2) (key) | 1;
+      hash_1 += hash_2;
+    }
+}
+
+void *
+hash_find_item (struct hash_table *ht, const void *key)
+{
+  void **slot = hash_find_slot (ht, key);
+  return ((HASH_VACANT (*slot)) ? 0 : *slot);
+}
+
+void *
+hash_insert (struct hash_table *ht, const void *item)
+{
+  void **slot = hash_find_slot (ht, item);
+  const void *old_item = slot ? *slot : 0;
+  hash_insert_at (ht, item, slot);
+  return (void *)((HASH_VACANT (old_item)) ? 0 : old_item);
+}
+
+void *
+hash_insert_at (struct hash_table *ht, const void *item, const void *slot)
+{
+  const void *old_item = *(void **) slot;
+  if (HASH_VACANT (old_item))
+    {
+      ht->ht_fill++;
+      if (old_item == 0)
+	ht->ht_empty_slots--;
+      old_item = item;
+    }
+  *(void const **) slot = item;
+  if (ht->ht_empty_slots < ht->ht_size - ht->ht_capacity)
+    {
+      hash_rehash (ht);
+      return (void *) hash_find_slot (ht, item);
+    }
+  else
+    return (void *) slot;
+}
+
+void *
+hash_delete (struct hash_table *ht, const void *item)
+{
+  void **slot = hash_find_slot (ht, item);
+  return hash_delete_at (ht, slot);
+}
+
+void *
+hash_delete_at (struct hash_table *ht, const void *slot)
+{
+  void *item = *(void **) slot;
+  if (!HASH_VACANT (item))
+    {
+      *(void const **) slot = hash_deleted_item;
+      ht->ht_fill--;
+      return item;
+    }
+  else
+    return 0;
+}
+
+void
+hash_free_items (struct hash_table *ht)
+{
+  void **vec = ht->ht_vec;
+  void **end = &vec[ht->ht_size];
+  for (; vec < end; vec++)
+    {
+      void *item = *vec;
+      if (!HASH_VACANT (item))
+	free (item);
+      *vec = 0;
+    }
+  ht->ht_fill = 0;
+  ht->ht_empty_slots = ht->ht_size;
+}
+
+void
+hash_delete_items (struct hash_table *ht)
+{
+  void **vec = ht->ht_vec;
+  void **end = &vec[ht->ht_size];
+  for (; vec < end; vec++)
+    *vec = 0;
+  ht->ht_fill = 0;
+  ht->ht_collisions = 0;
+  ht->ht_lookups = 0;
+  ht->ht_rehashes = 0;
+  ht->ht_empty_slots = ht->ht_size;
+}
+
+void
+hash_free (struct hash_table *ht, int free_items)
+{
+  if (free_items)
+    hash_free_items (ht);
+  else
+    {
+      ht->ht_fill = 0;
+      ht->ht_empty_slots = ht->ht_size;
+    }
+  free (ht->ht_vec);
+  ht->ht_vec = 0;
+  ht->ht_capacity = 0;
+}
+
+void
+hash_map (struct hash_table *ht, hash_map_func_t map)
+{
+  void **slot;
+  void **end = &ht->ht_vec[ht->ht_size];
+
+  for (slot = ht->ht_vec; slot < end; slot++)
+    {
+      if (!HASH_VACANT (*slot))
+	(*map) (*slot);
+    }
+}
+
+void
+hash_map_arg (struct hash_table *ht, hash_map_arg_func_t map, void *arg)
+{
+  void **slot;
+  void **end = &ht->ht_vec[ht->ht_size];
+
+  for (slot = ht->ht_vec; slot < end; slot++)
+    {
+      if (!HASH_VACANT (*slot))
+	(*map) (*slot, arg);
+    }
+}
+
+/* Double the size of the hash table in the event of overflow... */
+
+static void
+hash_rehash (struct hash_table *ht)
+{
+  unsigned long old_ht_size = ht->ht_size;
+  void **old_vec = ht->ht_vec;
+  void **ovp;
+
+  if (ht->ht_fill >= ht->ht_capacity)
+    {
+      ht->ht_size *= 2;
+      ht->ht_capacity = ht->ht_size - (ht->ht_size >> 4);
+    }
+  ht->ht_rehashes++;
+  ht->ht_vec = (void **) CALLOC (struct token *, ht->ht_size);
+
+  for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++)
+    {
+      if (! HASH_VACANT (*ovp))
+	{
+	  void **slot = hash_find_slot (ht, *ovp);
+	  *slot = *ovp;
+	}
+    }
+  ht->ht_empty_slots = ht->ht_size - ht->ht_fill;
+  free (old_vec);
+}
+
+void
+hash_print_stats (struct hash_table *ht, FILE *out_FILE)
+{
+  /* GKM FIXME: honor NO_FLOAT */
+  fprintf (out_FILE, _("Load=%ld/%ld=%.0f%%, "), ht->ht_fill, ht->ht_size,
+	   100.0 * (double) ht->ht_fill / (double) ht->ht_size);
+  fprintf (out_FILE, _("Rehash=%d, "), ht->ht_rehashes);
+  fprintf (out_FILE, _("Collisions=%ld/%ld=%.0f%%"), ht->ht_collisions, ht->ht_lookups,
+	   (ht->ht_lookups
+	    ? (100.0 * (double) ht->ht_collisions / (double) ht->ht_lookups)
+	    : 0));
+}
+
+/* Dump all items into a NULL-terminated vector.  Use the
+   user-supplied vector, or malloc one.  */
+
+void **
+hash_dump (struct hash_table *ht, void **vector_0, qsort_cmp_t compare)
+{
+  void **vector;
+  void **slot;
+  void **end = &ht->ht_vec[ht->ht_size];
+
+  if (vector_0 == 0)
+    vector_0 = MALLOC (void *, ht->ht_fill + 1);
+  vector = vector_0;
+
+  for (slot = ht->ht_vec; slot < end; slot++)
+    if (!HASH_VACANT (*slot))
+      *vector++ = *slot;
+  *vector = 0;
+
+  if (compare)
+    qsort (vector_0, ht->ht_fill, sizeof (void *), compare);
+  return vector_0;
+}
+
+/* Round a given number up to the nearest power of 2. */
+
+static unsigned long
+round_up_2 (unsigned long n)
+{
+  n |= (n >> 1);
+  n |= (n >> 2);
+  n |= (n >> 4);
+  n |= (n >> 8);
+  n |= (n >> 16);
+
+#if !defined(HAVE_LIMITS_H) || ULONG_MAX > 4294967295
+  /* We only need this on systems where unsigned long is >32 bits.  */
+  n |= (n >> 32);
+#endif
+
+  return n + 1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/hash.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/hash.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/hash.h	(revision 1780)
@@ -0,0 +1,337 @@
+/* hash.h -- decls for hash table
+Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc.
+Written by Greg McGary <gkm@gnu.org> <greg@mcgary.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, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef _hash_h_
+#define _hash_h_
+
+#include <stdio.h>
+#include <ctype.h>
+
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
+# if !defined __GLIBC__ || !defined __P
+#  undef	__P
+#  define __P(protos)	protos
+# endif
+#else /* Not C++ or ANSI C.  */
+# undef	__P
+# define __P(protos)	()
+/* We can get away without defining `const' here only because in this file
+   it is used only inside the prototype for `fnmatch', which is elided in
+   non-ANSI C where `const' is problematical.  */
+#endif /* C++ or ANSI C.  */
+
+typedef unsigned long (*hash_func_t) __P((void const *key));
+typedef int (*hash_cmp_func_t) __P((void const *x, void const *y));
+typedef void (*hash_map_func_t) __P((void const *item));
+typedef void (*hash_map_arg_func_t) __P((void const *item, void *arg));
+
+struct hash_table
+{
+  void **ht_vec;
+  unsigned long ht_size;	/* total number of slots (power of 2) */
+  unsigned long ht_capacity;	/* usable slots, limited by loading-factor */
+  unsigned long ht_fill;	/* items in table */
+  unsigned long ht_empty_slots;	/* empty slots not including deleted slots */
+  unsigned long ht_collisions;	/* # of failed calls to comparison function */
+  unsigned long ht_lookups;	/* # of queries */
+  unsigned int ht_rehashes;	/* # of times we've expanded table */
+  hash_func_t ht_hash_1;	/* primary hash function */
+  hash_func_t ht_hash_2;	/* secondary hash function */
+  hash_cmp_func_t ht_compare;	/* comparison function */
+};
+
+typedef int (*qsort_cmp_t) __P((void const *, void const *));
+
+void hash_init __P((struct hash_table *ht, unsigned long size,
+		    hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp));
+void hash_load __P((struct hash_table *ht, void *item_table,
+		    unsigned long cardinality, unsigned long size));
+void **hash_find_slot __P((struct hash_table *ht, void const *key));
+void *hash_find_item __P((struct hash_table *ht, void const *key));
+void *hash_insert __P((struct hash_table *ht, const void *item));
+void *hash_insert_at __P((struct hash_table *ht, const void *item, void const *slot));
+void *hash_delete __P((struct hash_table *ht, void const *item));
+void *hash_delete_at __P((struct hash_table *ht, void const *slot));
+void hash_delete_items __P((struct hash_table *ht));
+void hash_free_items __P((struct hash_table *ht));
+void hash_free __P((struct hash_table *ht, int free_items));
+void hash_map __P((struct hash_table *ht, hash_map_func_t map));
+void hash_map_arg __P((struct hash_table *ht, hash_map_arg_func_t map, void *arg));
+void hash_print_stats __P((struct hash_table *ht, FILE *out_FILE));
+void **hash_dump __P((struct hash_table *ht, void **vector_0, qsort_cmp_t compare));
+
+extern void *hash_deleted_item;
+#define HASH_VACANT(item) ((item) == 0 || (void *) (item) == hash_deleted_item)
+
+
+
+/* hash and comparison macros for case-sensitive string keys. */
+
+#ifndef CONFIG_WITH_OPTIMIZATION_HACKS
+#define STRING_HASH_1(KEY, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
+  while (*++_key_) \
+    (RESULT) += (*_key_ << (_key_[1] & 0xf)); \
+} while (0)
+#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
+# define STRING_HASH_1(KEY, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY); \
+  unsigned int _ch_ = *_key_; \
+  while (_ch_) \
+    { \
+      unsigned char _ch2_ = *++_key_; \
+     (RESULT) += (_ch_ << (_ch2_ & 0xf)); \
+     _ch_ = _ch2_; \
+    } \
+} while (0)
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#define return_STRING_HASH_1(KEY) do { \
+  unsigned long _result_ = 0; \
+  STRING_HASH_1 ((KEY), _result_); \
+  return _result_; \
+} while (0)
+
+#ifndef CONFIG_WITH_OPTIMIZATION_HACKS
+#define STRING_HASH_2(KEY, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
+  while (*++_key_) \
+    (RESULT) += (*_key_ << (_key_[1] & 0x7)); \
+} while (0)
+#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
+# define STRING_HASH_2(KEY, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY); \
+  unsigned int _ch_ = *_key_; \
+  while (_ch_) \
+    { \
+      unsigned char _ch2_ = *++_key_; \
+     (RESULT) += (_ch_ << (_ch2_ & 0x7)); \
+     _ch_ = _ch2_; \
+    } \
+} while (0)
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#define return_STRING_HASH_2(KEY) do { \
+  unsigned long _result_ = 0; \
+  STRING_HASH_2 ((KEY), _result_); \
+  return _result_; \
+} while (0)
+
+#define STRING_COMPARE(X, Y, RESULT) do { \
+  RESULT = strcmp ((X), (Y)); \
+} while (0)
+#define return_STRING_COMPARE(X, Y) do { \
+  return strcmp ((X), (Y)); \
+} while (0)
+
+#ifndef CONFIG_WITH_OPTIMIZATION_HACKS
+#define STRING_N_HASH_1(KEY, N, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
+  int _n_ = (N); \
+  if (_n_) \
+    while (--_n_ && *++_key_) \
+      (RESULT) += (*_key_ << (_key_[1] & 0xf)); \
+  (RESULT) += *++_key_; \
+} while (0)
+#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
+# define STRING_N_HASH_1(KEY, N, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY); \
+  unsigned int _ch_ = *_key_; \
+  int _n_ = (N); \
+  if (_n_) \
+    { \
+      for (;;) \
+        { \
+          unsigned char _ch2_; \
+          if (!--_n_) \
+            { \
+              (RESULT) += _ch_; \
+              break; \
+            } \
+          _ch2_ = *++_key_; \
+          (RESULT) += (_ch_ << (_ch2_ & 0xf)); \
+          _ch_ = _ch2_; \
+          if (!_ch_) break; \
+        } \
+    } \
+  else \
+    (RESULT) += _ch_; \
+} while (0)
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#define return_STRING_N_HASH_1(KEY, N) do { \
+  unsigned long _result_ = 0; \
+  STRING_N_HASH_1 ((KEY), (N), _result_); \
+  return _result_; \
+} while (0)
+
+#ifndef CONFIG_WITH_OPTIMIZATION_HACKS
+#define STRING_N_HASH_2(KEY, N, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
+  int _n_ = (N); \
+  if (_n_) \
+    while (--_n_ && *++_key_) \
+      (RESULT) += (*_key_ << (_key_[1] & 0x7)); \
+  (RESULT) += *++_key_; \
+} while (0)
+#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
+# define STRING_N_HASH_2(KEY, N, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY); \
+  unsigned int _ch_ = *_key_; \
+  int _n_ = (N); \
+  if (_n_) \
+    { \
+      for (;;) \
+        { \
+          unsigned char _ch2_; \
+          if (!--_n_) \
+            { \
+              (RESULT) += _ch_; \
+              break; \
+            } \
+          _ch2_ = *++_key_; \
+          (RESULT) += (_ch_ << (_ch2_ & 0x7)); \
+          _ch_ = _ch2_; \
+          if (!_ch_) break; \
+        } \
+    } \
+  else \
+    (RESULT) += _ch_; \
+} while (0)
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#define return_STRING_N_HASH_2(KEY, N) do { \
+  unsigned long _result_ = 0; \
+  STRING_N_HASH_2 ((KEY), (N), _result_); \
+  return _result_; \
+} while (0)
+
+#define STRING_N_COMPARE(X, Y, N, RESULT) do { \
+  RESULT = strncmp ((X), (Y), (N)); \
+} while (0)
+#define return_STRING_N_COMPARE(X, Y, N) do { \
+  return strncmp ((X), (Y), (N)); \
+} while (0)
+
+#ifdef HAVE_CASE_INSENSITIVE_FS
+
+/* hash and comparison macros for case-insensitive string _key_s. */
+
+#if 1 /*ndef CONFIG_WITH_OPTIMIZATION_HACKS - testme */
+#define ISTRING_HASH_1(KEY, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
+  while (*++_key_) \
+    (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0xf)); \
+} while (0)
+#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#define ISTRING_HASH_1(KEY, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY); \
+  unsigned int _ch_ = *_key_;
+  while (_ch_) \
+    { \
+      unsigned _ch2_ = *++_key_; \
+      (RESULT) += ((isupper (_ch_) ? tolower (_ch_) : _ch_) << (_ch2_ & 0xf)); \
+      _ch_ = _ch2_; \
+    } \
+} while (0)
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#define return_ISTRING_HASH_1(KEY) do { \
+  unsigned long _result_ = 0; \
+  ISTRING_HASH_1 ((KEY), _result_); \
+  return _result_; \
+} while (0)
+
+#if 1 /* ndef CONFIG_WITH_OPTIMIZATION_HACKS - testme */
+#define ISTRING_HASH_2(KEY, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
+  while (*++_key_) \
+    (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0x7)); \
+} while (0)
+#else /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#define ISTRING_HASH_2(KEY, RESULT) do { \
+  unsigned char const *_key_ = (unsigned char const *) (KEY); \
+  unsigned int _ch_ = *_key_;
+  while (_ch_) \
+    { \
+      unsigned _ch2_ = *++_key_; \
+      (RESULT) += ((isupper (_ch_) ? tolower (_ch_) : _ch_) << (_ch2_ & 0x7)); \
+      _ch_ = _ch2_; \
+    } \
+} while (0)
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#define return_ISTRING_HASH_2(KEY) do { \
+  unsigned long _result_ = 0; \
+  ISTRING_HASH_2 ((KEY), _result_); \
+  return _result_; \
+} while (0)
+
+#define ISTRING_COMPARE(X, Y, RESULT) do { \
+  RESULT = strcasecmp ((X), (Y)); \
+} while (0)
+#define return_ISTRING_COMPARE(X, Y) do { \
+  return strcasecmp ((X), (Y)); \
+} while (0)
+
+#else
+
+#define ISTRING_HASH_1(KEY, RESULT) STRING_HASH_1 ((KEY), (RESULT))
+#define return_ISTRING_HASH_1(KEY) return_STRING_HASH_1 (KEY)
+
+#define ISTRING_HASH_2(KEY, RESULT) STRING_HASH_2 ((KEY), (RESULT))
+#define return_ISTRING_HASH_2(KEY) return_STRING_HASH_2 (KEY)
+
+#define ISTRING_COMPARE(X, Y, RESULT) STRING_COMPARE ((X), (Y), (RESULT))
+#define return_ISTRING_COMPARE(X, Y) return_STRING_COMPARE ((X), (Y))
+
+#endif
+
+/* hash and comparison macros for integer _key_s. */
+
+#define INTEGER_HASH_1(KEY, RESULT) do { \
+  (RESULT) += ((unsigned long)(KEY)); \
+} while (0)
+#define return_INTEGER_HASH_1(KEY) do { \
+  unsigned long _result_ = 0; \
+  INTEGER_HASH_1 ((KEY), _result_); \
+  return _result_; \
+} while (0)
+
+#define INTEGER_HASH_2(KEY, RESULT) do { \
+  (RESULT) += ~((unsigned long)(KEY)); \
+} while (0)
+#define return_INTEGER_HASH_2(KEY) do { \
+  unsigned long _result_ = 0; \
+  INTEGER_HASH_2 ((KEY), _result_); \
+  return _result_; \
+} while (0)
+
+#define INTEGER_COMPARE(X, Y, RESULT) do { \
+  (RESULT) = X - Y; \
+} while (0)
+#define return_INTEGER_COMPARE(X, Y) do { \
+  int _result_; \
+  INTEGER_COMPARE (X, Y, _result_); \
+  return _result_; \
+} while (0)
+
+/* hash and comparison macros for address keys. */
+
+#define ADDRESS_HASH_1(KEY, RESULT) INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3, (RESULT))
+#define ADDRESS_HASH_2(KEY, RESULT) INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3, (RESULT))
+#define ADDRESS_COMPARE(X, Y, RESULT) INTEGER_COMPARE ((X), (Y), (RESULT))
+#define return_ADDRESS_HASH_1(KEY) return_INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3)
+#define return_ADDRESS_HASH_2(KEY) return_INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3)
+#define return_ADDRESS_COMPARE(X, Y) return_INTEGER_COMPARE ((X), (Y))
+
+#endif /* not _hash_h_ */
Index: /tags/kBuild-0.1.4/src/kmk/implicit.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/implicit.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/implicit.c	(revision 1780)
@@ -0,0 +1,956 @@
+/* Implicit rule searching for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "filedef.h"
+#include "rule.h"
+#include "dep.h"
+#include "debug.h"
+#include "variable.h"
+#include "job.h"      /* struct child, used inside commands.h */
+#include "commands.h" /* set_file_variables */
+
+static int pattern_search (struct file *file, int archive,
+                           unsigned int depth, unsigned int recursions);
+
+
+/* For a FILE which has no commands specified, try to figure out some
+   from the implicit pattern rules.
+   Returns 1 if a suitable implicit rule was found,
+   after modifying FILE to contain the appropriate commands and deps,
+   or returns 0 if no implicit rule was found.  */
+
+int
+try_implicit_rule (struct file *file, unsigned int depth)
+{
+  DBF (DB_IMPLICIT, _("Looking for an implicit rule for `%s'.\n"));
+
+  /* The order of these searches was previously reversed.  My logic now is
+     that since the non-archive search uses more information in the target
+     (the archive search omits the archive name), it is more specific and
+     should come first.  */
+
+  if (pattern_search (file, 0, depth, 0))
+    return 1;
+
+#ifndef	NO_ARCHIVES
+  /* If this is an archive member reference, use just the
+     archive member name to search for implicit rules.  */
+  if (ar_name (file->name))
+    {
+      DBF (DB_IMPLICIT,
+           _("Looking for archive-member implicit rule for `%s'.\n"));
+      if (pattern_search (file, 1, depth, 0))
+	return 1;
+    }
+#endif
+
+  return 0;
+}
+
+
+
+/* Struct idep captures information about implicit prerequisites
+   that come from implicit rules. */
+struct idep
+{
+  struct idep *next;              /* struct dep -compatible interface */
+  const char *name;               /* name of the prerequisite */
+  struct file *intermediate_file; /* intermediate file, 0 otherwise */
+  const char *intermediate_pattern; /* pattern for intermediate file */
+  unsigned char had_stem;         /* had % substituted with stem */
+  unsigned char ignore_mtime;     /* ignore_mtime flag */
+};
+
+static void
+free_idep_chain (struct idep *p)
+{
+  struct idep *n;
+
+  for (; p != 0; p = n)
+    {
+      n = p->next;
+      free (p);
+    }
+}
+
+
+/* Scans the BUFFER for the next word with whitespace as a separator.
+   Returns the pointer to the beginning of the word. LENGTH hold the
+   length of the word.  */
+
+static char *
+get_next_word (const char *buffer, unsigned int *length)
+{
+  const char *p = buffer, *beg;
+  char c;
+
+  /* Skip any leading whitespace.  */
+  while (isblank ((unsigned char)*p))
+    ++p;
+
+  beg = p;
+  c = *(p++);
+
+  if (c == '\0')
+    return 0;
+
+
+  /* We already found the first value of "c", above.  */
+  while (1)
+    {
+      char closeparen;
+      int count;
+
+      switch (c)
+        {
+        case '\0':
+        case ' ':
+        case '\t':
+          goto done_word;
+
+        case '$':
+          c = *(p++);
+          if (c == '$')
+            break;
+
+          /* This is a variable reference, so read it to the matching
+             close paren.  */
+
+          if (c == '(')
+            closeparen = ')';
+          else if (c == '{')
+            closeparen = '}';
+          else
+            /* This is a single-letter variable reference.  */
+            break;
+
+          for (count = 0; *p != '\0'; ++p)
+            {
+              if (*p == c)
+                ++count;
+              else if (*p == closeparen && --count < 0)
+                {
+                  ++p;
+                  break;
+                }
+            }
+          break;
+
+        case '|':
+          goto done;
+
+        default:
+          break;
+        }
+
+      c = *(p++);
+    }
+ done_word:
+  --p;
+
+ done:
+  if (length)
+    *length = p - beg;
+
+  return (char *)beg;
+}
+
+/* Search the pattern rules for a rule with an existing dependency to make
+   FILE.  If a rule is found, the appropriate commands and deps are put in FILE
+   and 1 is returned.  If not, 0 is returned.
+
+   If ARCHIVE is nonzero, FILE->name is of the form "LIB(MEMBER)".  A rule for
+   "(MEMBER)" will be searched for, and "(MEMBER)" will not be chopped up into
+   directory and filename parts.
+
+   If an intermediate file is found by pattern search, the intermediate file
+   is set up as a target by the recursive call and is also made a dependency
+   of FILE.
+
+   DEPTH is used for debugging messages.  */
+
+static int
+pattern_search (struct file *file, int archive,
+                unsigned int depth, unsigned int recursions)
+{
+  /* Filename we are searching for a rule for.  */
+  const char *filename = archive ? strchr (file->name, '(') : file->name;
+
+  /* Length of FILENAME.  */
+  unsigned int namelen = strlen (filename);
+
+  /* The last slash in FILENAME (or nil if there is none).  */
+  char *lastslash;
+
+  /* This is a file-object used as an argument in
+     recursive calls.  It never contains any data
+     except during a recursive call.  */
+  struct file *intermediate_file = 0;
+
+  /* This linked list records all the prerequisites actually
+     found for a rule along with some other useful information
+     (see struct idep for details). */
+  struct idep* deps = 0;
+
+  /* 1 if we need to remove explicit prerequisites, 0 otherwise. */
+  unsigned int remove_explicit_deps = 0;
+
+  /* Names of possible dependencies are constructed in this buffer.  */
+  char *depname = alloca (namelen + max_pattern_dep_length);
+
+  /* The start and length of the stem of FILENAME for the current rule.  */
+  const char *stem = 0;
+  unsigned int stemlen = 0;
+  unsigned int fullstemlen = 0;
+
+  /* Buffer in which we store all the rules that are possibly applicable.  */
+  struct rule **tryrules = xmalloc (num_pattern_rules * max_pattern_targets
+                                    * sizeof (struct rule *));
+
+  /* Number of valid elements in TRYRULES.  */
+  unsigned int nrules;
+
+  /* The numbers of the rule targets of each rule
+     in TRYRULES that matched the target file.  */
+  unsigned int *matches = alloca (num_pattern_rules * sizeof (unsigned int));
+
+  /* Each element is nonzero if LASTSLASH was used in
+     matching the corresponding element of TRYRULES.  */
+  char *checked_lastslash = alloca (num_pattern_rules * sizeof (char));
+
+  /* The index in TRYRULES of the rule we found.  */
+  unsigned int foundrule;
+
+  /* Nonzero if should consider intermediate files as dependencies.  */
+  int intermed_ok;
+
+  /* Nonzero if we have matched a pattern-rule target
+     that is not just `%'.  */
+  int specific_rule_matched = 0;
+
+  unsigned int ri;  /* uninit checks OK */
+  struct rule *rule;
+  struct dep *dep, *expl_d;
+
+  struct idep *d;
+  struct idep **id_ptr;
+  struct dep **d_ptr;
+
+  PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */
+
+#ifndef	NO_ARCHIVES
+  if (archive || ar_name (filename))
+    lastslash = 0;
+  else
+#endif
+    {
+      /* Set LASTSLASH to point at the last slash in FILENAME
+	 but not counting any slash at the end.  (foo/bar/ counts as
+	 bar/ in directory foo/, not empty in directory foo/bar/.)  */
+#ifdef VMS
+      lastslash = strrchr (filename, ']');
+      if (lastslash == 0)
+	lastslash = strrchr (filename, ':');
+#else
+      lastslash = strrchr (filename, '/');
+#ifdef HAVE_DOS_PATHS
+      /* Handle backslashes (possibly mixed with forward slashes)
+	 and the case of "d:file".  */
+      {
+	char *bslash = strrchr (filename, '\\');
+	if (lastslash == 0 || bslash > lastslash)
+	  lastslash = bslash;
+	if (lastslash == 0 && filename[0] && filename[1] == ':')
+	  lastslash = (char *)filename + 1;
+      }
+#endif
+#endif
+      if (lastslash != 0 && lastslash[1] == '\0')
+	lastslash = 0;
+    }
+
+  /* First see which pattern rules match this target
+     and may be considered.  Put them in TRYRULES.  */
+
+  nrules = 0;
+  for (rule = pattern_rules; rule != 0; rule = rule->next)
+    {
+      unsigned int ti;
+
+      /* If the pattern rule has deps but no commands, ignore it.
+	 Users cancel built-in rules by redefining them without commands.  */
+      if (rule->deps != 0 && rule->cmds == 0)
+	continue;
+
+      /* If this rule is in use by a parent pattern_search,
+	 don't use it here.  */
+      if (rule->in_use)
+	{
+	  DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n")));
+	  continue;
+	}
+
+      for (ti = 0; ti < rule->num; ++ti)
+	{
+	  const char *target = rule->targets[ti];
+	  const char *suffix = rule->suffixes[ti];
+	  int check_lastslash;
+
+	  /* Rules that can match any filename and are not terminal
+	     are ignored if we're recursing, so that they cannot be
+	     intermediate files.  */
+	  if (recursions > 0 && target[1] == '\0' && !rule->terminal)
+	    continue;
+
+	  if (rule->lens[ti] > namelen)
+	    /* It can't possibly match.  */
+	    continue;
+
+	  /* From the lengths of the filename and the pattern parts,
+	     find the stem: the part of the filename that matches the %.  */
+	  stem = filename + (suffix - target - 1);
+	  stemlen = namelen - rule->lens[ti] + 1;
+
+	  /* Set CHECK_LASTSLASH if FILENAME contains a directory
+	     prefix and the target pattern does not contain a slash.  */
+
+          check_lastslash = 0;
+          if (lastslash)
+            {
+#ifdef VMS
+              check_lastslash = (strchr (target, ']') == 0
+                                 && strchr (target, ':') == 0);
+#else
+              check_lastslash = strchr (target, '/') == 0;
+#ifdef HAVE_DOS_PATHS
+              /* Didn't find it yet: check for DOS-type directories.  */
+              if (check_lastslash)
+                {
+                  char *b = strchr (target, '\\');
+                  check_lastslash = !(b || (target[0] && target[1] == ':'));
+                }
+#endif
+#endif
+            }
+	  if (check_lastslash)
+	    {
+	      /* If so, don't include the directory prefix in STEM here.  */
+	      unsigned int difference = lastslash - filename + 1;
+	      if (difference > stemlen)
+		continue;
+	      stemlen -= difference;
+	      stem += difference;
+	    }
+
+	  /* Check that the rule pattern matches the text before the stem.  */
+	  if (check_lastslash)
+	    {
+	      if (stem > (lastslash + 1)
+		  && !strneq (target, lastslash + 1, stem - lastslash - 1))
+		continue;
+	    }
+	  else if (stem > filename
+		   && !strneq (target, filename, stem - filename))
+	    continue;
+
+	  /* Check that the rule pattern matches the text after the stem.
+	     We could test simply use streq, but this way we compare the
+	     first two characters immediately.  This saves time in the very
+	     common case where the first character matches because it is a
+	     period.  */
+	  if (*suffix != stem[stemlen]
+	      || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1])))
+	    continue;
+
+	  /* Record if we match a rule that not all filenames will match.  */
+	  if (target[1] != '\0')
+	    specific_rule_matched = 1;
+
+	  /* A rule with no dependencies and no commands exists solely to set
+	     specific_rule_matched when it matches.  Don't try to use it.  */
+	  if (rule->deps == 0 && rule->cmds == 0)
+	    continue;
+
+	  /* Record this rule in TRYRULES and the index of the matching
+	     target in MATCHES.  If several targets of the same rule match,
+	     that rule will be in TRYRULES more than once.  */
+	  tryrules[nrules] = rule;
+	  matches[nrules] = ti;
+	  checked_lastslash[nrules] = check_lastslash;
+	  ++nrules;
+	}
+    }
+
+  /* If we have found a matching rule that won't match all filenames,
+     retroactively reject any non-"terminal" rules that do always match.  */
+  if (specific_rule_matched)
+    for (ri = 0; ri < nrules; ++ri)
+      if (!tryrules[ri]->terminal)
+	{
+	  unsigned int j;
+	  for (j = 0; j < tryrules[ri]->num; ++j)
+	    if (tryrules[ri]->targets[j][1] == '\0')
+              {
+                tryrules[ri] = 0;
+                break;
+              }
+	}
+
+  /* We are going to do second expansion so initialize file variables
+     for the rule. */
+  initialize_file_variables (file, 0);
+
+  /* Try each rule once without intermediate files, then once with them.  */
+  for (intermed_ok = 0; intermed_ok == !!intermed_ok; ++intermed_ok)
+    {
+      /* Try each pattern rule till we find one that applies.
+	 If it does, expand its dependencies (as substituted)
+	 and chain them in DEPS.  */
+
+      for (ri = 0; ri < nrules; ri++)
+	{
+          struct file *f;
+          unsigned int failed = 0;
+	  int check_lastslash;
+          int file_variables_set = 0;
+
+	  rule = tryrules[ri];
+
+          remove_explicit_deps = 0;
+
+	  /* RULE is nil when we discover that a rule,
+	     already placed in TRYRULES, should not be applied.  */
+	  if (rule == 0)
+	    continue;
+
+	  /* Reject any terminal rules if we're
+	     looking to make intermediate files.  */
+	  if (intermed_ok && rule->terminal)
+	    continue;
+
+	  /* Mark this rule as in use so a recursive
+	     pattern_search won't try to use it.  */
+	  rule->in_use = 1;
+
+	  /* From the lengths of the filename and the matching pattern parts,
+	     find the stem: the part of the filename that matches the %.  */
+	  stem = filename
+	    + (rule->suffixes[matches[ri]] - rule->targets[matches[ri]]) - 1;
+	  stemlen = namelen - rule->lens[matches[ri]] + 1;
+	  check_lastslash = checked_lastslash[ri];
+	  if (check_lastslash)
+	    {
+	      stem += lastslash - filename + 1;
+	      stemlen -= (lastslash - filename) + 1;
+	    }
+
+	  DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"),
+                             (int) stemlen, stem));
+
+          strncpy (stem_str, stem, stemlen);
+          stem_str[stemlen] = '\0';
+
+          /* Temporary assign STEM to file->stem (needed to set file
+             variables below).   */
+          file->stem = stem_str;
+
+	  /* Try each dependency; see if it "exists".  */
+
+	  for (dep = rule->deps; dep != 0; dep = dep->next)
+	    {
+              unsigned int len;
+              char *p;
+              char *p2;
+              unsigned int order_only = 0; /* Set if '|' was seen. */
+
+              /* In an ideal world we would take the dependency line,
+                 substitute the stem, re-expand the whole line and chop it
+                 into individual prerequisites. Unfortunately this won't work
+                 because of the "check_lastslash" twist.  Instead, we will
+                 have to go word by word, taking $()'s into account, for each
+                 word we will substitute the stem, re-expand, chop it up, and,
+                 if check_lastslash != 0, add the directory part to each
+                 resulting prerequisite.  */
+
+              p = get_next_word (dep->name, &len);
+
+              while (1)
+                {
+                  int add_dir = 0;
+                  int had_stem = 0;
+
+                  if (p == 0)
+                    break; /* No more words */
+
+                  /* Is there a pattern in this prerequisite?  */
+
+                  for (p2 = p; p2 < p + len && *p2 != '%'; ++p2)
+                    ;
+
+                  if (dep->need_2nd_expansion)
+                    {
+                      /* If the dependency name has %, substitute the stem.
+
+                         Watch out, we are going to do something tricky
+                         here. If we just replace % with the stem value,
+                         later, when we do the second expansion, we will
+                         re-expand this stem value once again. This is not
+                         good especially if you have certain characters in
+                         your stem (like $).
+
+                         Instead, we will replace % with $* and allow the
+                         second expansion to take care of it for us. This way
+                         (since $* is a simple variable) there won't be
+                         additional re-expansion of the stem.  */
+
+                      if (p2 < p + len)
+                        {
+                          unsigned int i = p2 - p;
+                          memcpy (depname, p, i);
+                          memcpy (depname + i, "$*", 2);
+                          memcpy (depname + i + 2, p2 + 1, len - i - 1);
+                          depname[len + 2 - 1] = '\0';
+
+                          if (check_lastslash)
+                            add_dir = 1;
+
+                          had_stem = 1;
+                        }
+                      else
+                        {
+                          memcpy (depname, p, len);
+                          depname[len] = '\0';
+                        }
+
+                      /* Set file variables. Note that we cannot do it once
+                         at the beginning of the function because of the stem
+                         value.  */
+                      if (!file_variables_set)
+                        {
+                          set_file_variables (file);
+                          file_variables_set = 1;
+                        }
+
+                      p2 = variable_expand_for_file (depname, file);
+                    }
+                  else
+                    {
+                       if (p2 < p + len)
+                        {
+                          unsigned int i = p2 - p;
+                          memcpy (depname, p, i);
+                          memcpy (depname + i, stem_str, stemlen);
+                          memcpy (depname + i + stemlen, p2 + 1, len - i - 1);
+                          depname[len + stemlen - 1] = '\0';
+
+                          if (check_lastslash)
+                            add_dir = 1;
+
+                          had_stem = 1;
+                        }
+                      else
+                        {
+                          memcpy (depname, p, len);
+                          depname[len] = '\0';
+                        }
+
+                       p2 = depname;
+                    }
+
+                  /* Parse the dependencies. */
+
+                  while (1)
+                    {
+                      id_ptr = &deps;
+
+                      for (; *id_ptr; id_ptr = &(*id_ptr)->next)
+                        ;
+
+                      *id_ptr = (struct idep *)
+                        multi_glob (
+                          parse_file_seq (&p2,
+                                          order_only ? '\0' : '|',
+                                          sizeof (struct idep),
+                                          1), sizeof (struct idep));
+
+                      /* @@ It would be nice to teach parse_file_seq or
+                         multi_glob to add prefix. This would save us some
+                         reallocations. */
+
+                      if (order_only || add_dir || had_stem)
+                        {
+                          unsigned long l = lastslash - filename + 1;
+
+                          for (d = *id_ptr; d != 0; d = d->next)
+                            {
+                              if (order_only)
+                                d->ignore_mtime = 1;
+
+                              if (add_dir)
+                                {
+                                  char *n = alloca (strlen (d->name) + l + 1);
+                                  memcpy (n, filename, l);
+                                  memcpy (n+l, d->name, strlen (d->name) + 1);
+                                  d->name = strcache_add (n);
+                                }
+
+                              if (had_stem)
+                                d->had_stem = 1;
+                            }
+                        }
+
+                      if (!order_only && *p2)
+                      {
+                        ++p2;
+                        order_only = 1;
+                        continue;
+                      }
+
+                      break;
+                    }
+
+                  p += len;
+                  p = get_next_word (p, &len);
+                }
+	    }
+
+          /* Reset the stem in FILE. */
+
+          file->stem = 0;
+
+          /* @@ This loop can be combined with the previous one. I do
+             it separately for now for transparency.*/
+
+          for (d = deps; d != 0; d = d->next)
+            {
+              const char *name = d->name;
+
+              if (file_impossible_p (name))
+                {
+                  /* If this dependency has already been ruled "impossible",
+                     then the rule fails and don't bother trying it on the
+                     second pass either since we know that will fail too.  */
+                  DBS (DB_IMPLICIT,
+                       (d->had_stem
+                        ? _("Rejecting impossible implicit prerequisite `%s'.\n")
+                        : _("Rejecting impossible rule prerequisite `%s'.\n"),
+                        name));
+                  tryrules[ri] = 0;
+
+                  failed = 1;
+                  break;
+                }
+
+              DBS (DB_IMPLICIT,
+                   (d->had_stem
+                    ? _("Trying implicit prerequisite `%s'.\n")
+                    : _("Trying rule prerequisite `%s'.\n"), name));
+
+              /* If this prerequisite also happened to be explicitly mentioned
+                 for FILE skip all the test below since it it has to be built
+                 anyway, no matter which implicit rule we choose. */
+
+              for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next)
+                if (streq (dep_name (expl_d), name))
+                  break;
+              if (expl_d != 0)
+                continue;
+
+              /* The DEP->changed flag says that this dependency resides in a
+                 nonexistent directory.  So we normally can skip looking for
+                 the file.  However, if CHECK_LASTSLASH is set, then the
+                 dependency file we are actually looking for is in a different
+                 directory (the one gotten by prepending FILENAME's directory),
+                 so it might actually exist.  */
+
+              /* @@ dep->changed check is disabled. */
+              if (((f = lookup_file (name)) != 0 && f->is_target)
+                  /*|| ((!dep->changed || check_lastslash) && */
+                  || file_exists_p (name))
+                continue;
+
+              /* This code, given FILENAME = "lib/foo.o", dependency name
+                 "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c".  */
+              {
+                const char *vname = vpath_search (name, 0);
+                if (vname)
+                  {
+                    DBS (DB_IMPLICIT,
+                         (_("Found prerequisite `%s' as VPATH `%s'\n"),
+                          name, vname));
+                    continue;
+                  }
+              }
+
+
+              /* We could not find the file in any place we should look.  Try
+                 to make this dependency as an intermediate file, but only on
+                 the second pass.  */
+
+              if (intermed_ok)
+                {
+                  if (intermediate_file == 0)
+                    intermediate_file = alloca (sizeof (struct file));
+
+                  DBS (DB_IMPLICIT,
+                       (_("Looking for a rule with intermediate file `%s'.\n"),
+                        name));
+
+                  memset (intermediate_file, '\0', sizeof (struct file));
+                  intermediate_file->name = name;
+                  if (pattern_search (intermediate_file,
+                                      0,
+                                      depth + 1,
+                                      recursions + 1))
+                    {
+                      d->intermediate_pattern = intermediate_file->name;
+                      intermediate_file->name = strcache_add (name);
+                      d->intermediate_file = intermediate_file;
+                      intermediate_file = 0;
+
+                      continue;
+                    }
+
+                  /* If we have tried to find P as an intermediate
+                     file and failed, mark that name as impossible
+                     so we won't go through the search again later.  */
+                  if (intermediate_file->variables)
+                    free_variable_set (intermediate_file->variables);
+                  file_impossible (name);
+                }
+
+              /* A dependency of this rule does not exist. Therefore,
+                 this rule fails.  */
+              failed = 1;
+              break;
+            }
+
+          /* This rule is no longer `in use' for recursive searches.  */
+	  rule->in_use = 0;
+
+          if (failed)
+            {
+              /* This pattern rule does not apply. If some of its
+                 dependencies succeeded, free the data structure
+                 describing them.  */
+              free_idep_chain (deps);
+              deps = 0;
+            }
+	  else
+	    /* This pattern rule does apply.  Stop looking for one.  */
+	    break;
+	}
+
+      /* If we found an applicable rule without
+	 intermediate files, don't try with them.  */
+      if (ri < nrules)
+	break;
+
+      rule = 0;
+    }
+
+  /* RULE is nil if the loop went all the way
+     through the list and everything failed.  */
+  if (rule == 0)
+    goto done;
+
+  foundrule = ri;
+
+  /* If we are recursing, store the pattern that matched
+     FILENAME in FILE->name for use in upper levels.  */
+
+  if (recursions > 0)
+    /* Kludge-o-matic */
+    file->name = rule->targets[matches[foundrule]];
+
+  /* FOUND_FILES lists the dependencies for the rule we found.
+     This includes the intermediate files, if any.
+     Convert them into entries on the deps-chain of FILE.  */
+
+  if (remove_explicit_deps)
+    {
+      /* Remove all the dependencies that didn't come from
+         this implicit rule. */
+
+      dep = file->deps;
+      while (dep != 0)
+        {
+          struct dep *next = dep->next;
+          free_dep (dep);
+          dep = next;
+        }
+      file->deps = 0;
+  }
+
+  expl_d = file->deps; /* We will add them at the end. */
+  d_ptr = &file->deps;
+
+  for (d = deps; d != 0; d = d->next)
+    {
+      const char *s;
+
+      if (d->intermediate_file != 0)
+	{
+	  /* If we need to use an intermediate file,
+	     make sure it is entered as a target, with the info that was
+	     found for it in the recursive pattern_search call.
+	     We know that the intermediate file did not already exist as
+	     a target; therefore we can assume that the deps and cmds
+	     of F below are null before we change them.  */
+
+	  struct file *imf = d->intermediate_file;
+	  register struct file *f = lookup_file (imf->name);
+
+          /* We don't want to delete an intermediate file that happened
+             to be a prerequisite of some (other) target. Mark it as
+             precious.  */
+          if (f != 0)
+            f->precious = 1;
+          else
+            f = enter_file (strcache_add (imf->name));
+
+	  f->deps = imf->deps;
+	  f->cmds = imf->cmds;
+	  f->stem = imf->stem;
+          f->also_make = imf->also_make;
+          f->is_target = 1;
+
+          if (!f->precious)
+            {
+              imf = lookup_file (d->intermediate_pattern);
+              if (imf != 0 && imf->precious)
+                f->precious = 1;
+            }
+
+	  f->intermediate = 1;
+	  f->tried_implicit = 1;
+	  for (dep = f->deps; dep != 0; dep = dep->next)
+	    {
+	      dep->file = enter_file (dep->name);
+	      dep->name = 0;
+	      dep->file->tried_implicit |= dep->changed;
+	    }
+	}
+
+      dep = alloc_dep ();
+      dep->ignore_mtime = d->ignore_mtime;
+      s = d->name; /* Hijacking the name. */
+      d->name = 0;
+      if (recursions == 0)
+	{
+	  dep->file = lookup_file (s);
+	  if (dep->file == 0)
+	    dep->file = enter_file (s);
+	}
+      else
+        dep->name = s;
+
+      if (d->intermediate_file == 0 && tryrules[foundrule]->terminal)
+	{
+	  /* If the file actually existed (was not an intermediate file),
+	     and the rule that found it was a terminal one, then we want
+	     to mark the found file so that it will not have implicit rule
+	     search done for it.  If we are not entering a `struct file' for
+	     it now, we indicate this with the `changed' flag.  */
+	  if (dep->file == 0)
+	    dep->changed = 1;
+	  else
+	    dep->file->tried_implicit = 1;
+	}
+
+      *d_ptr = dep;
+      d_ptr = &dep->next;
+    }
+
+  *d_ptr = expl_d;
+
+  if (!checked_lastslash[foundrule])
+    {
+      /* Always allocate new storage, since STEM might be
+         on the stack for an intermediate file.  */
+      file->stem = strcache_add_len (stem, stemlen);
+      fullstemlen = stemlen;
+    }
+  else
+    {
+      int dirlen = (lastslash + 1) - filename;
+      char *sp;
+
+      /* We want to prepend the directory from
+	 the original FILENAME onto the stem.  */
+      fullstemlen = dirlen + stemlen;
+      sp = alloca (fullstemlen + 1);
+      memcpy (sp, filename, dirlen);
+      memcpy (sp + dirlen, stem, stemlen);
+      sp[fullstemlen] = '\0';
+      file->stem = strcache_add (sp);
+    }
+
+  file->cmds = rule->cmds;
+  file->is_target = 1;
+
+  /* Set precious flag. */
+  {
+    struct file *f = lookup_file (rule->targets[matches[foundrule]]);
+    if (f && f->precious)
+      file->precious = 1;
+  }
+
+  /* If this rule builds other targets, too, put the others into FILE's
+     `also_make' member.  */
+
+  if (rule->num > 1)
+    for (ri = 0; ri < rule->num; ++ri)
+      if (ri != matches[foundrule])
+	{
+          char *p = alloca (rule->lens[ri] + fullstemlen + 1);
+	  struct file *f;
+	  struct dep *new = alloc_dep ();
+
+	  /* GKM FIMXE: handle '|' here too */
+	  memcpy (p, rule->targets[ri],
+                  rule->suffixes[ri] - rule->targets[ri] - 1);
+	  p += rule->suffixes[ri] - rule->targets[ri] - 1;
+	  memcpy (p, file->stem, fullstemlen);
+	  p += fullstemlen;
+	  memcpy (p, rule->suffixes[ri],
+                  rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1);
+          new->name = strcache_add (p);
+	  new->file = enter_file (new->name);
+	  new->next = file->also_make;
+
+	  /* Set precious flag. */
+	  f = lookup_file (rule->targets[ri]);
+	  if (f && f->precious)
+            new->file->precious = 1;
+
+          /* Set the is_target flag so that this file is not treated
+             as intermediate by the pattern rule search algorithm and
+             file_exists_p cannot pick it up yet.  */
+          new->file->is_target = 1;
+
+	  file->also_make = new;
+	}
+
+ done:
+  free_idep_chain (deps);
+  free (tryrules);
+
+  return rule != 0;
+}
Index: /tags/kBuild-0.1.4/src/kmk/job.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/job.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/job.c	(revision 1780)
@@ -0,0 +1,3409 @@
+/* Job execution and handling for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#include <assert.h>
+
+#include "job.h"
+#include "debug.h"
+#include "filedef.h"
+#include "commands.h"
+#include "variable.h"
+#include "debug.h"
+#ifdef CONFIG_WITH_KMK_BUILTIN
+# include "kmkbuiltin.h"
+#endif
+#ifdef KMK
+# include "kbuild.h"
+#endif
+
+
+#include <string.h>
+
+/* Default shell to use.  */
+#ifdef WINDOWS32
+#include <windows.h>
+
+char *default_shell = "sh.exe";
+int no_default_sh_exe = 1;
+int batch_mode_shell = 1;
+HANDLE main_thread;
+
+#elif defined (_AMIGA)
+
+char default_shell[] = "";
+extern int MyExecute (char **);
+int batch_mode_shell = 0;
+
+#elif defined (__MSDOS__)
+
+/* The default shell is a pointer so we can change it if Makefile
+   says so.  It is without an explicit path so we get a chance
+   to search the $PATH for it (since MSDOS doesn't have standard
+   directories we could trust).  */
+char *default_shell = "command.com";
+int batch_mode_shell = 0;
+
+#elif defined (__EMX__)
+
+char *default_shell = "sh.exe"; /* bird changed this from "/bin/sh" as that doesn't make sense on OS/2. */
+int batch_mode_shell = 0;
+
+#elif defined (VMS)
+
+# include <descrip.h>
+char default_shell[] = "";
+int batch_mode_shell = 0;
+
+#elif defined (__riscos__)
+
+char default_shell[] = "";
+int batch_mode_shell = 0;
+
+#else
+
+char default_shell[] = "/bin/sh";
+int batch_mode_shell = 0;
+
+#endif
+
+#ifdef __MSDOS__
+# include <process.h>
+static int execute_by_shell;
+static int dos_pid = 123;
+int dos_status;
+int dos_command_running;
+#endif /* __MSDOS__ */
+
+#ifdef _AMIGA
+# include <proto/dos.h>
+static int amiga_pid = 123;
+static int amiga_status;
+static char amiga_bname[32];
+static int amiga_batch_file;
+#endif /* Amiga.  */
+
+#ifdef VMS
+# ifndef __GNUC__
+#   include <processes.h>
+# endif
+# include <starlet.h>
+# include <lib$routines.h>
+static void vmsWaitForChildren (int *);
+#endif
+
+#ifdef WINDOWS32
+# include <windows.h>
+# include <io.h>
+# include <process.h>
+# include "sub_proc.h"
+# include "w32err.h"
+# include "pathstuff.h"
+#endif /* WINDOWS32 */
+
+#ifdef __EMX__
+# include <process.h>
+#endif
+
+#if defined (HAVE_SYS_WAIT_H) || defined (HAVE_UNION_WAIT)
+# include <sys/wait.h>
+#endif
+
+#ifdef HAVE_WAITPID
+# define WAIT_NOHANG(status)	waitpid (-1, (status), WNOHANG)
+#else	/* Don't have waitpid.  */
+# ifdef HAVE_WAIT3
+#  ifndef wait3
+extern int wait3 ();
+#  endif
+#  define WAIT_NOHANG(status)	wait3 ((status), WNOHANG, (struct rusage *) 0)
+# endif /* Have wait3.  */
+#endif /* Have waitpid.  */
+
+#if !defined (wait) && !defined (POSIX)
+int wait ();
+#endif
+
+#ifndef	HAVE_UNION_WAIT
+
+# define WAIT_T int
+
+# ifndef WTERMSIG
+#  define WTERMSIG(x) ((x) & 0x7f)
+# endif
+# ifndef WCOREDUMP
+#  define WCOREDUMP(x) ((x) & 0x80)
+# endif
+# ifndef WEXITSTATUS
+#  define WEXITSTATUS(x) (((x) >> 8) & 0xff)
+# endif
+# ifndef WIFSIGNALED
+#  define WIFSIGNALED(x) (WTERMSIG (x) != 0)
+# endif
+# ifndef WIFEXITED
+#  define WIFEXITED(x) (WTERMSIG (x) == 0)
+# endif
+
+#else	/* Have `union wait'.  */
+
+# define WAIT_T union wait
+# ifndef WTERMSIG
+#  define WTERMSIG(x) ((x).w_termsig)
+# endif
+# ifndef WCOREDUMP
+#  define WCOREDUMP(x) ((x).w_coredump)
+# endif
+# ifndef WEXITSTATUS
+#  define WEXITSTATUS(x) ((x).w_retcode)
+# endif
+# ifndef WIFSIGNALED
+#  define WIFSIGNALED(x) (WTERMSIG(x) != 0)
+# endif
+# ifndef WIFEXITED
+#  define WIFEXITED(x) (WTERMSIG(x) == 0)
+# endif
+
+#endif	/* Don't have `union wait'.  */
+
+#ifndef	HAVE_UNISTD_H
+# ifndef _MSC_VER /* bird */
+int dup2 ();
+int execve ();
+void _exit ();
+# endif /* bird */
+# ifndef VMS
+int geteuid ();
+int getegid ();
+int setgid ();
+int getgid ();
+# endif
+#endif
+
+int getloadavg (double loadavg[], int nelem);
+int start_remote_job (char **argv, char **envp, int stdin_fd, int *is_remote,
+                      int *id_ptr, int *used_stdin);
+int start_remote_job_p (int);
+int remote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr,
+                   int block);
+
+RETSIGTYPE child_handler (int);
+static void free_child (struct child *);
+static void start_job_command (struct child *child);
+static int load_too_high (void);
+static int job_next_command (struct child *);
+static int start_waiting_job (struct child *);
+
+
+/* Chain of all live (or recently deceased) children.  */
+
+struct child *children = 0;
+
+/* Number of children currently running.  */
+
+unsigned int job_slots_used = 0;
+
+/* Nonzero if the `good' standard input is in use.  */
+
+static int good_stdin_used = 0;
+
+/* Chain of children waiting to run until the load average goes down.  */
+
+static struct child *waiting_jobs = 0;
+
+/* Non-zero if we use a *real* shell (always so on Unix).  */
+
+int unixy_shell = 1;
+
+/* Number of jobs started in the current second.  */
+
+unsigned long job_counter = 0;
+
+/* Number of jobserver tokens this instance is currently using.  */
+
+unsigned int jobserver_tokens = 0;
+
+
+#ifdef WINDOWS32
+/*
+ * The macro which references this function is defined in make.h.
+ */
+int
+w32_kill(int pid, int sig)
+{
+  return ((process_kill((HANDLE)pid, sig) == TRUE) ? 0 : -1);
+}
+
+/* This function creates a temporary file name with an extension specified
+ * by the unixy arg.
+ * Return an xmalloc'ed string of a newly created temp file and its
+ * file descriptor, or die.  */
+static char *
+create_batch_file (char const *base, int unixy, int *fd)
+{
+  const char *const ext = unixy ? "sh" : "bat";
+  const char *error = NULL;
+  char temp_path[MAXPATHLEN]; /* need to know its length */
+  unsigned path_size = GetTempPath(sizeof temp_path, temp_path);
+  int path_is_dot = 0;
+  unsigned uniq = 1;
+  const unsigned sizemax = strlen (base) + strlen (ext) + 10;
+
+  if (path_size == 0)
+    {
+      path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
+      path_is_dot = 1;
+    }
+
+  while (path_size > 0 &&
+         path_size + sizemax < sizeof temp_path &&
+         uniq < 0x10000)
+    {
+      unsigned size = sprintf (temp_path + path_size,
+                               "%s%s-%x.%s",
+                               temp_path[path_size - 1] == '\\' ? "" : "\\",
+                               base, uniq, ext);
+      HANDLE h = CreateFile (temp_path,  /* file name */
+                             GENERIC_READ | GENERIC_WRITE, /* desired access */
+                             0,                            /* no share mode */
+                             NULL,                         /* default security attributes */
+                             CREATE_NEW,                   /* creation disposition */
+                             FILE_ATTRIBUTE_NORMAL |       /* flags and attributes */
+                             FILE_ATTRIBUTE_TEMPORARY,     /* we'll delete it */
+                             NULL);                        /* no template file */
+
+      if (h == INVALID_HANDLE_VALUE)
+        {
+          const DWORD er = GetLastError();
+
+          if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS)
+            ++uniq;
+
+          /* the temporary path is not guaranteed to exist */
+          else if (path_is_dot == 0)
+            {
+              path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
+              path_is_dot = 1;
+            }
+
+          else
+            {
+              error = map_windows32_error_to_string (er);
+              break;
+            }
+        }
+      else
+        {
+          const unsigned final_size = path_size + size + 1;
+          char *const path = xmalloc (final_size);
+          memcpy (path, temp_path, final_size);
+          *fd = _open_osfhandle ((long)h, 0);
+          if (unixy)
+            {
+              char *p;
+              int ch;
+              for (p = path; (ch = *p) != 0; ++p)
+                if (ch == '\\')
+                  *p = '/';
+            }
+          return path; /* good return */
+        }
+    }
+
+  *fd = -1;
+  if (error == NULL)
+    error = _("Cannot create a temporary file\n");
+  fatal (NILF, error);
+
+  /* not reached */
+  return NULL;
+}
+#endif /* WINDOWS32 */
+
+#ifdef __EMX__
+/* returns whether path is assumed to be a unix like shell. */
+int
+_is_unixy_shell (const char *path)
+{
+  /* list of non unix shells */
+  const char *known_os2shells[] = {
+    "cmd.exe",
+    "cmd",
+    "4os2.exe",
+    "4os2",
+    "4dos.exe",
+    "4dos",
+    "command.com",
+    "command",
+    NULL
+  };
+
+  /* find the rightmost '/' or '\\' */
+  const char *name = strrchr (path, '/');
+  const char *p = strrchr (path, '\\');
+  unsigned i;
+
+  if (name && p)    /* take the max */
+    name = (name > p) ? name : p;
+  else if (p)       /* name must be 0 */
+    name = p;
+  else if (!name)   /* name and p must be 0 */
+    name = path;
+
+  if (*name == '/' || *name == '\\') name++;
+
+  i = 0;
+  while (known_os2shells[i] != NULL) {
+    if (strcasecmp (name, known_os2shells[i]) == 0)
+      return 0; /* not a unix shell */
+    i++;
+  }
+
+  /* in doubt assume a unix like shell */
+  return 1;
+}
+#endif /* __EMX__ */
+
+
+
+/* Write an error message describing the exit status given in
+   EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.
+   Append "(ignored)" if IGNORED is nonzero.  */
+
+static void
+child_error (const char *target_name,
+             int exit_code, int exit_sig, int coredump, int ignored)
+{
+  if (ignored && silent_flag)
+    return;
+
+#ifdef VMS
+  if (!(exit_code & 1))
+      error (NILF,
+             (ignored ? _("*** [%s] Error 0x%x (ignored)")
+              : _("*** [%s] Error 0x%x")),
+             target_name, exit_code);
+#else
+  if (exit_sig == 0)
+    error (NILF, ignored ? _("[%s] Error %d (ignored)") :
+	   _("*** [%s] Error %d"),
+	   target_name, exit_code);
+  else
+    error (NILF, "*** [%s] %s%s",
+	   target_name, strsignal (exit_sig),
+	   coredump ? _(" (core dumped)") : "");
+#endif /* VMS */
+}
+
+
+
+/* Handle a dead child.  This handler may or may not ever be installed.
+
+   If we're using the jobserver feature, we need it.  First, installing it
+   ensures the read will interrupt on SIGCHLD.  Second, we close the dup'd
+   read FD to ensure we don't enter another blocking read without reaping all
+   the dead children.  In this case we don't need the dead_children count.
+
+   If we don't have either waitpid or wait3, then make is unreliable, but we
+   use the dead_children count to reap children as best we can.  */
+
+static unsigned int dead_children = 0;
+
+RETSIGTYPE
+child_handler (int sig UNUSED)
+{
+  ++dead_children;
+
+  if (job_rfd >= 0)
+    {
+      close (job_rfd);
+      job_rfd = -1;
+    }
+
+#if defined __EMX__ && !defined(__INNOTEK_LIBC__) /* bird */
+  /* The signal handler must called only once! */
+  signal (SIGCHLD, SIG_DFL);
+#endif
+
+  /* This causes problems if the SIGCHLD interrupts a printf().
+  DB (DB_JOBS, (_("Got a SIGCHLD; %u unreaped children.\n"), dead_children));
+  */
+}
+
+extern int shell_function_pid, shell_function_completed;
+
+/* Reap all dead children, storing the returned status and the new command
+   state (`cs_finished') in the `file' member of the `struct child' for the
+   dead child, and removing the child from the chain.  In addition, if BLOCK
+   nonzero, we block in this function until we've reaped at least one
+   complete child, waiting for it to die if necessary.  If ERR is nonzero,
+   print an error message first.  */
+
+void
+reap_children (int block, int err)
+{
+#ifndef WINDOWS32
+  WAIT_T status;
+  /* Initially, assume we have some.  */
+  int reap_more = 1;
+#endif
+
+#ifdef WAIT_NOHANG
+# define REAP_MORE reap_more
+#else
+# define REAP_MORE dead_children
+#endif
+
+  /* As long as:
+
+       We have at least one child outstanding OR a shell function in progress,
+         AND
+       We're blocking for a complete child OR there are more children to reap
+
+     we'll keep reaping children.  */
+
+  while ((children != 0 || shell_function_pid != 0)
+         && (block || REAP_MORE))
+    {
+      int remote = 0;
+      pid_t pid;
+      int exit_code, exit_sig, coredump;
+      register struct child *lastc, *c;
+      int child_failed;
+      int any_remote, any_local;
+      int dontcare;
+#ifdef CONFIG_WITH_KMK_BUILTIN
+      struct child *completed_child = NULL;
+#endif
+
+      if (err && block)
+	{
+          static int printed = 0;
+
+	  /* We might block for a while, so let the user know why.
+             Only print this message once no matter how many jobs are left.  */
+	  fflush (stdout);
+          if (!printed)
+            error (NILF, _("*** Waiting for unfinished jobs...."));
+          printed = 1;
+	}
+
+      /* We have one less dead child to reap.  As noted in
+	 child_handler() above, this count is completely unimportant for
+	 all modern, POSIX-y systems that support wait3() or waitpid().
+	 The rest of this comment below applies only to early, broken
+	 pre-POSIX systems.  We keep the count only because... it's there...
+
+	 The test and decrement are not atomic; if it is compiled into:
+		register = dead_children - 1;
+		dead_children = register;
+	 a SIGCHLD could come between the two instructions.
+	 child_handler increments dead_children.
+	 The second instruction here would lose that increment.  But the
+	 only effect of dead_children being wrong is that we might wait
+	 longer than necessary to reap a child, and lose some parallelism;
+	 and we might print the "Waiting for unfinished jobs" message above
+	 when not necessary.  */
+
+      if (dead_children > 0)
+	--dead_children;
+
+      any_remote = 0;
+      any_local = shell_function_pid != 0;
+      for (c = children; c != 0; c = c->next)
+	{
+	  any_remote |= c->remote;
+	  any_local |= ! c->remote;
+#ifdef CONFIG_WITH_KMK_BUILTIN
+          if (c->has_status)
+            {
+              completed_child = c;
+              DB (DB_JOBS, (_("builtin child 0x%08lx (%s) PID %ld %s Status %ld\n"),
+                            (unsigned long int) c, c->file->name,
+                            (long) c->pid, c->remote ? _(" (remote)") : "",
+                            (long) c->status));
+            }
+          else
+#endif
+	  DB (DB_JOBS, (_("Live child 0x%08lx (%s) PID %ld %s\n"),
+                        (unsigned long int) c, c->file->name,
+                        (long) c->pid, c->remote ? _(" (remote)") : ""));
+#ifdef VMS
+	  break;
+#endif
+	}
+
+      /* First, check for remote children.  */
+      if (any_remote)
+	pid = remote_status (&exit_code, &exit_sig, &coredump, 0);
+      else
+	pid = 0;
+
+      if (pid > 0)
+	/* We got a remote child.  */
+	remote = 1;
+      else if (pid < 0)
+	{
+          /* A remote status command failed miserably.  Punt.  */
+	remote_status_lose:
+	  pfatal_with_name ("remote_status");
+	}
+      else
+	{
+	  /* No remote children.  Check for local children.  */
+#ifdef CONFIG_WITH_KMK_BUILTIN
+          if (completed_child)
+            {
+              pid = completed_child->pid;
+# if defined(WINDOWS32)
+              exit_code = completed_child->status;
+              exit_sig = 0;
+              coredump = 0;
+# else
+              status = (WAIT_T)completed_child->status;
+# endif
+            }
+          else
+#endif /* CONFIG_WITH_KMK_BUILTIN */
+#if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32)
+	  if (any_local)
+	    {
+#ifdef VMS
+	      vmsWaitForChildren (&status);
+	      pid = c->pid;
+#else
+#ifdef WAIT_NOHANG
+	      if (!block)
+		pid = WAIT_NOHANG (&status);
+	      else
+#endif
+		pid = wait (&status);
+#endif /* !VMS */
+	    }
+	  else
+	    pid = 0;
+
+	  if (pid < 0)
+	    {
+              /* The wait*() failed miserably.  Punt.  */
+	      pfatal_with_name ("wait");
+	    }
+	  else if (pid > 0)
+	    {
+	      /* We got a child exit; chop the status word up.  */
+	      exit_code = WEXITSTATUS (status);
+	      exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;
+	      coredump = WCOREDUMP (status);
+
+              /* If we have started jobs in this second, remove one.  */
+              if (job_counter)
+                --job_counter;
+	    }
+	  else
+	    {
+	      /* No local children are dead.  */
+              reap_more = 0;
+
+	      if (!block || !any_remote)
+                break;
+
+              /* Now try a blocking wait for a remote child.  */
+              pid = remote_status (&exit_code, &exit_sig, &coredump, 1);
+              if (pid < 0)
+                goto remote_status_lose;
+              else if (pid == 0)
+                /* No remote children either.  Finally give up.  */
+                break;
+
+              /* We got a remote child.  */
+              remote = 1;
+	    }
+#endif /* !__MSDOS__, !Amiga, !WINDOWS32.  */
+
+#ifdef __MSDOS__
+	  /* Life is very different on MSDOS.  */
+	  pid = dos_pid - 1;
+	  status = dos_status;
+	  exit_code = WEXITSTATUS (status);
+	  if (exit_code == 0xff)
+	    exit_code = -1;
+	  exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;
+	  coredump = 0;
+#endif /* __MSDOS__ */
+#ifdef _AMIGA
+	  /* Same on Amiga */
+	  pid = amiga_pid - 1;
+	  status = amiga_status;
+	  exit_code = amiga_status;
+	  exit_sig = 0;
+	  coredump = 0;
+#endif /* _AMIGA */
+#ifdef WINDOWS32
+          {
+            HANDLE hPID;
+            int werr;
+            HANDLE hcTID, hcPID;
+            exit_code = 0;
+            exit_sig = 0;
+            coredump = 0;
+
+            /* Record the thread ID of the main process, so that we
+               could suspend it in the signal handler.  */
+            if (!main_thread)
+              {
+                hcTID = GetCurrentThread ();
+                hcPID = GetCurrentProcess ();
+                if (!DuplicateHandle (hcPID, hcTID, hcPID, &main_thread, 0,
+                                      FALSE, DUPLICATE_SAME_ACCESS))
+                  {
+                    DWORD e = GetLastError ();
+                    fprintf (stderr,
+                             "Determine main thread ID (Error %ld: %s)\n",
+                             e, map_windows32_error_to_string(e));
+                  }
+                else
+                  DB (DB_VERBOSE, ("Main thread handle = 0x%08lx\n",
+                                   (unsigned long)main_thread));
+              }
+
+            /* wait for anything to finish */
+            hPID = process_wait_for_any();
+            if (hPID)
+              {
+
+                /* was an error found on this process? */
+                werr = process_last_err(hPID);
+
+                /* get exit data */
+                exit_code = process_exit_code(hPID);
+
+                if (werr)
+                  fprintf(stderr, "make (e=%d): %s",
+                          exit_code, map_windows32_error_to_string(exit_code));
+
+                /* signal */
+                exit_sig = process_signal(hPID);
+
+                /* cleanup process */
+                process_cleanup(hPID);
+
+                coredump = 0;
+              }
+            else if (!process_used_slots())
+              {
+                /* The wait*() failed miserably.  Punt.  */
+                errno = ECHILD;
+                pfatal_with_name ("wait");
+              }
+
+            pid = (pid_t) hPID;
+          }
+#endif /* WINDOWS32 */
+	}
+
+      /* Check if this is the child of the `shell' function.  */
+      if (!remote && pid == shell_function_pid)
+	{
+	  /* It is.  Leave an indicator for the `shell' function.  */
+	  if (exit_sig == 0 && exit_code == 127)
+	    shell_function_completed = -1;
+	  else
+	    shell_function_completed = 1;
+	  break;
+	}
+
+      child_failed = exit_sig != 0 || exit_code != 0;
+
+      /* Search for a child matching the deceased one.  */
+      lastc = 0;
+      for (c = children; c != 0; lastc = c, c = c->next)
+	if (c->remote == remote && c->pid == pid)
+	  break;
+
+      if (c == 0)
+        /* An unknown child died.
+           Ignore it; it was inherited from our invoker.  */
+        continue;
+
+      DB (DB_JOBS, (child_failed
+                    ? _("Reaping losing child 0x%08lx PID %ld %s\n")
+                    : _("Reaping winning child 0x%08lx PID %ld %s\n"),
+                    (unsigned long int) c, (long) c->pid,
+                    c->remote ? _(" (remote)") : ""));
+
+      if (c->sh_batch_file) {
+        DB (DB_JOBS, (_("Cleaning up temp batch file %s\n"),
+                      c->sh_batch_file));
+
+        /* just try and remove, don't care if this fails */
+        remove (c->sh_batch_file);
+
+        /* all done with memory */
+        free (c->sh_batch_file);
+        c->sh_batch_file = NULL;
+      }
+
+      /* If this child had the good stdin, say it is now free.  */
+      if (c->good_stdin)
+        good_stdin_used = 0;
+
+      dontcare = c->dontcare;
+
+      if (child_failed && !c->noerror && !ignore_errors_flag)
+        {
+          /* The commands failed.  Write an error message,
+             delete non-precious targets, and abort.  */
+          static int delete_on_error = -1;
+
+          if (!dontcare)
+#ifdef KMK
+            {
+              child_error (c->file->name, exit_code, exit_sig, coredump, 0);
+              if ((  c->file->cmds->lines_flags[c->command_line - 1]
+                   & (COMMANDS_SILENT | COMMANDS_RECURSE))
+                  == COMMANDS_SILENT)
+                message (0, "The failing command:\n%s", c->file->cmds->command_lines[c->command_line - 1]);
+            }
+#else
+            child_error (c->file->name, exit_code, exit_sig, coredump, 0);
+#endif
+
+          c->file->update_status = 2;
+          if (delete_on_error == -1)
+            {
+              struct file *f = lookup_file (".DELETE_ON_ERROR");
+              delete_on_error = f != 0 && f->is_target;
+            }
+          if (exit_sig != 0 || delete_on_error)
+            delete_child_targets (c);
+        }
+      else
+        {
+          if (child_failed)
+            {
+              /* The commands failed, but we don't care.  */
+              child_error (c->file->name,
+                           exit_code, exit_sig, coredump, 1);
+              child_failed = 0;
+            }
+
+          /* If there are more commands to run, try to start them.  */
+          if (job_next_command (c))
+            {
+              if (handling_fatal_signal)
+                {
+                  /* Never start new commands while we are dying.
+                     Since there are more commands that wanted to be run,
+                     the target was not completely remade.  So we treat
+                     this as if a command had failed.  */
+                  c->file->update_status = 2;
+                }
+              else
+                {
+                  /* Check again whether to start remotely.
+                     Whether or not we want to changes over time.
+                     Also, start_remote_job may need state set up
+                     by start_remote_job_p.  */
+                  c->remote = start_remote_job_p (0);
+                  start_job_command (c);
+                  /* Fatal signals are left blocked in case we were
+                     about to put that child on the chain.  But it is
+                     already there, so it is safe for a fatal signal to
+                     arrive now; it will clean up this child's targets.  */
+                  unblock_sigs ();
+                  if (c->file->command_state == cs_running)
+                    /* We successfully started the new command.
+                       Loop to reap more children.  */
+                    continue;
+                }
+
+              if (c->file->update_status != 0)
+                /* We failed to start the commands.  */
+                delete_child_targets (c);
+            }
+          else
+            /* There are no more commands.  We got through them all
+               without an unignored error.  Now the target has been
+               successfully updated.  */
+            c->file->update_status = 0;
+        }
+
+      /* When we get here, all the commands for C->file are finished
+         (or aborted) and C->file->update_status contains 0 or 2.  But
+         C->file->command_state is still cs_running if all the commands
+         ran; notice_finish_file looks for cs_running to tell it that
+         it's interesting to check the file's modtime again now.  */
+
+      if (! handling_fatal_signal)
+        /* Notice if the target of the commands has been changed.
+           This also propagates its values for command_state and
+           update_status to its also_make files.  */
+        notice_finished_file (c->file);
+
+      DB (DB_JOBS, (_("Removing child 0x%08lx PID %ld%s from chain.\n"),
+                    (unsigned long int) c, (long) c->pid,
+                    c->remote ? _(" (remote)") : ""));
+
+      /* Block fatal signals while frobnicating the list, so that
+         children and job_slots_used are always consistent.  Otherwise
+         a fatal signal arriving after the child is off the chain and
+         before job_slots_used is decremented would believe a child was
+         live and call reap_children again.  */
+      block_sigs ();
+
+      /* There is now another slot open.  */
+      if (job_slots_used > 0)
+        --job_slots_used;
+
+      /* Remove the child from the chain and free it.  */
+      if (lastc == 0)
+        children = c->next;
+      else
+        lastc->next = c->next;
+
+      free_child (c);
+
+      unblock_sigs ();
+
+      /* If the job failed, and the -k flag was not given, die,
+         unless we are already in the process of dying.  */
+      if (!err && child_failed && !dontcare && !keep_going_flag &&
+          /* fatal_error_signal will die with the right signal.  */
+          !handling_fatal_signal)
+        die (2);
+
+      /* Only block for one child.  */
+      block = 0;
+    }
+
+  return;
+}
+
+
+/* Free the storage allocated for CHILD.  */
+
+static void
+free_child (struct child *child)
+{
+  if (!jobserver_tokens)
+    fatal (NILF, "INTERNAL: Freeing child 0x%08lx (%s) but no tokens left!\n",
+           (unsigned long int) child, child->file->name);
+
+  /* If we're using the jobserver and this child is not the only outstanding
+     job, put a token back into the pipe for it.  */
+
+  if (job_fds[1] >= 0 && jobserver_tokens > 1)
+    {
+      char token = '+';
+      int r;
+
+      /* Write a job token back to the pipe.  */
+
+      EINTRLOOP (r, write (job_fds[1], &token, 1));
+      if (r != 1)
+	pfatal_with_name (_("write jobserver"));
+
+      DB (DB_JOBS, (_("Released token for child 0x%08lx (%s).\n"),
+                    (unsigned long int) child, child->file->name));
+    }
+
+  --jobserver_tokens;
+
+  if (handling_fatal_signal) /* Don't bother free'ing if about to die.  */
+    return;
+
+  if (child->command_lines != 0)
+    {
+      register unsigned int i;
+      for (i = 0; i < child->file->cmds->ncommand_lines; ++i)
+	free (child->command_lines[i]);
+      free (child->command_lines);
+    }
+
+  if (child->environment != 0)
+    {
+      register char **ep = child->environment;
+      while (*ep != 0)
+	free (*ep++);
+      free (child->environment);
+    }
+
+  free (child);
+}
+
+
+#ifdef POSIX
+extern sigset_t fatal_signal_set;
+#endif
+
+void
+block_sigs (void)
+{
+#ifdef POSIX
+  (void) sigprocmask (SIG_BLOCK, &fatal_signal_set, (sigset_t *) 0);
+#else
+# ifdef HAVE_SIGSETMASK
+  (void) sigblock (fatal_signal_mask);
+# endif
+#endif
+}
+
+#ifdef POSIX
+void
+unblock_sigs (void)
+{
+  sigset_t empty;
+  sigemptyset (&empty);
+  sigprocmask (SIG_SETMASK, &empty, (sigset_t *) 0);
+}
+#endif
+
+#ifdef MAKE_JOBSERVER
+RETSIGTYPE
+job_noop (int sig UNUSED)
+{
+}
+/* Set the child handler action flags to FLAGS.  */
+static void
+set_child_handler_action_flags (int set_handler, int set_alarm)
+{
+  struct sigaction sa;
+
+#if defined(__EMX__) && !defined(__KLIBC__) /* bird */
+  /* The child handler must be turned off here.  */
+  signal (SIGCHLD, SIG_DFL);
+#endif
+
+  memset (&sa, '\0', sizeof sa);
+  sa.sa_handler = child_handler;
+  sa.sa_flags = set_handler ? 0 : SA_RESTART;
+#if defined SIGCHLD
+  sigaction (SIGCHLD, &sa, NULL);
+#endif
+#if defined SIGCLD && SIGCLD != SIGCHLD
+  sigaction (SIGCLD, &sa, NULL);
+#endif
+#if defined SIGALRM
+  if (set_alarm)
+    {
+      /* If we're about to enter the read(), set an alarm to wake up in a
+         second so we can check if the load has dropped and we can start more
+         work.  On the way out, turn off the alarm and set SIG_DFL.  */
+      alarm (set_handler ? 1 : 0);
+      sa.sa_handler = set_handler ? job_noop : SIG_DFL;
+      sa.sa_flags = 0;
+      sigaction (SIGALRM, &sa, NULL);
+    }
+#endif
+}
+#endif
+
+
+/* Start a job to run the commands specified in CHILD.
+   CHILD is updated to reflect the commands and ID of the child process.
+
+   NOTE: On return fatal signals are blocked!  The caller is responsible
+   for calling `unblock_sigs', once the new child is safely on the chain so
+   it can be cleaned up in the event of a fatal signal.  */
+
+static void
+start_job_command (struct child *child)
+{
+#if !defined(_AMIGA) && !defined(WINDOWS32)
+  static int bad_stdin = -1;
+#endif
+  register char *p;
+  int flags;
+#ifdef VMS
+  char *argv;
+#else
+  char **argv;
+#endif
+
+  /* If we have a completely empty commandset, stop now.  */
+  if (!child->command_ptr)
+    goto next_command;
+
+  /* Combine the flags parsed for the line itself with
+     the flags specified globally for this target.  */
+  flags = (child->file->command_flags
+	   | child->file->cmds->lines_flags[child->command_line - 1]);
+
+  p = child->command_ptr;
+  child->noerror = ((flags & COMMANDS_NOERROR) != 0);
+
+  while (*p != '\0')
+    {
+      if (*p == '@')
+	flags |= COMMANDS_SILENT;
+      else if (*p == '+')
+	flags |= COMMANDS_RECURSE;
+      else if (*p == '-')
+	child->noerror = 1;
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+      else if (*p == '%')
+        flags |= COMMAND_GETTER_SKIP_IT;
+#endif 
+      else if (!isblank ((unsigned char)*p))
+#ifndef CONFIG_WITH_KMK_BUILTIN
+        break;
+#else  /* CONFIG_WITH_KMK_BUILTIN */
+
+        {
+          if (   !(flags & COMMANDS_KMK_BUILTIN)
+              && !strncmp(p, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
+            flags |= COMMANDS_KMK_BUILTIN;
+          break;
+        }
+#endif /* CONFIG_WITH_KMK_BUILTIN */
+      ++p;
+    }
+
+  /* Update the file's command flags with any new ones we found.  We only
+     keep the COMMANDS_RECURSE setting.  Even this isn't 100% correct; we are
+     now marking more commands recursive than should be in the case of
+     multiline define/endef scripts where only one line is marked "+".  In
+     order to really fix this, we'll have to keep a lines_flags for every
+     actual line, after expansion.  */
+  child->file->cmds->lines_flags[child->command_line - 1]
+    |= flags & COMMANDS_RECURSE;
+
+  /* Figure out an argument list from this command line.  */
+
+  {
+    char *end = 0;
+#ifdef VMS
+    argv = p;
+#else
+    argv = construct_command_argv (p, &end, child->file, &child->sh_batch_file);
+#endif
+    if (end == NULL)
+      child->command_ptr = NULL;
+    else
+      {
+	*end++ = '\0';
+	child->command_ptr = end;
+      }
+  }
+
+  /* If -q was given, say that updating `failed' if there was any text on the
+     command line, or `succeeded' otherwise.  The exit status of 1 tells the
+     user that -q is saying `something to do'; the exit status for a random
+     error is 2.  */
+  if (argv != 0 && question_flag && !(flags & COMMANDS_RECURSE))
+    {
+#ifndef VMS
+      free (argv[0]);
+      free (argv);
+#endif
+      child->file->update_status = 1;
+      notice_finished_file (child->file);
+      return;
+    }
+
+  if (touch_flag && !(flags & COMMANDS_RECURSE))
+    {
+      /* Go on to the next command.  It might be the recursive one.
+	 We construct ARGV only to find the end of the command line.  */
+#ifndef VMS
+      if (argv)
+        {
+          free (argv[0]);
+          free (argv);
+        }
+#endif
+      argv = 0;
+    }
+
+  if (argv == 0)
+    {
+    next_command:
+#ifdef __MSDOS__
+      execute_by_shell = 0;   /* in case construct_command_argv sets it */
+#endif
+      /* This line has no commands.  Go to the next.  */
+      if (job_next_command (child))
+	start_job_command (child);
+      else
+	{
+	  /* No more commands.  Make sure we're "running"; we might not be if
+             (e.g.) all commands were skipped due to -n.  */
+          set_command_state (child->file, cs_running);
+	  child->file->update_status = 0;
+	  notice_finished_file (child->file);
+	}
+      return;
+    }
+
+  /* Print out the command.  If silent, we call `message' with null so it
+     can log the working directory before the command's own error messages
+     appear.  */
+#ifdef CONFIG_PRETTY_COMMAND_PRINTING
+  if (   pretty_command_printing
+      && (just_print_flag || (!(flags & COMMANDS_SILENT) && !silent_flag))
+      && argv[0][0] != '\0')
+    {
+      unsigned i;
+      for (i = 0; argv[i]; i++)
+        message (0, "%s'%s'%s", i ? "\t" : "> ", argv[i], argv[i + 1] ? " \\" : "");
+    }
+  else
+#endif /* CONFIG_PRETTY_COMMAND_PRINTING */
+    message (0, (just_print_flag || (!(flags & COMMANDS_SILENT) && !silent_flag))
+             ? "%s" : (char *) 0, p);
+
+  /* Tell update_goal_chain that a command has been started on behalf of
+     this target.  It is important that this happens here and not in
+     reap_children (where we used to do it), because reap_children might be
+     reaping children from a different target.  We want this increment to
+     guaranteedly indicate that a command was started for the dependency
+     chain (i.e., update_file recursion chain) we are processing.  */
+
+  ++commands_started;
+
+  /* Optimize an empty command.  People use this for timestamp rules,
+     so avoid forking a useless shell.  Do this after we increment
+     commands_started so make still treats this special case as if it
+     performed some action (makes a difference as to what messages are
+     printed, etc.  */
+
+#if !defined(VMS) && !defined(_AMIGA)
+  if (
+#if defined __MSDOS__ || defined (__EMX__)
+      unixy_shell	/* the test is complicated and we already did it */
+#else
+      (argv[0] && !strcmp (argv[0], "/bin/sh"))
+#endif
+      && (argv[1]
+          && argv[1][0] == '-' && argv[1][1] == 'c' && argv[1][2] == '\0')
+      && (argv[2] && argv[2][0] == ':' && argv[2][1] == '\0')
+      && argv[3] == NULL)
+    {
+      free (argv[0]);
+      free (argv);
+      goto next_command;
+    }
+#endif  /* !VMS && !_AMIGA */
+
+  /* If -n was given, recurse to get the next line in the sequence.  */
+
+  if (just_print_flag && !(flags & COMMANDS_RECURSE))
+    {
+#ifndef VMS
+      free (argv[0]);
+      free (argv);
+#endif
+      goto next_command;
+    }
+
+#ifdef CONFIG_WITH_KMK_BUILTIN
+  /* If builtin command then pass it on to the builtin shell interpreter. */
+
+  if ((flags & COMMANDS_KMK_BUILTIN) && !just_print_flag)
+    {
+      int    rc;
+      char **argv_spawn = NULL;
+      char **p2 = argv;
+      while (*p2 && strncmp (*p2, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
+        p2++;
+      assert (*p2);
+      set_command_state (child->file, cs_running);
+      child->pid = 0;
+      if (p2 != argv)
+        rc = kmk_builtin_command (*p2, &argv_spawn, &child->pid);
+      else
+        {
+          int argc = 1;
+          while (argv[argc])
+            argc++;
+          rc = kmk_builtin_command_parsed (argc, argv, &argv_spawn, &child->pid);
+        }
+
+#ifndef VMS
+      free (argv[0]);
+      free ((char *) argv);
+#endif
+
+      /* synchronous command execution? */
+      if (!rc && !argv_spawn)
+        goto next_command;
+
+      /* spawned a child? */
+      if (!rc && child->pid)
+        {
+          ++job_counter;
+          return;
+        }
+
+      /* failure? */
+      if (rc)
+        {
+          child->pid = (pid_t)42424242;
+          child->status = rc << 8;
+          child->has_status = 1;
+          unblock_sigs();
+          return;
+        }
+
+      /* conditional check == true; kicking off a child (not kmk_builtin_*). */
+      argv = argv_spawn;
+    }
+#endif /* CONFIG_WITH_KMK_BUILTIN */
+
+  /* Flush the output streams so they won't have things written twice.  */
+
+  fflush (stdout);
+  fflush (stderr);
+
+#ifndef VMS
+#if !defined(WINDOWS32) && !defined(_AMIGA) && !defined(__MSDOS__)
+
+  /* Set up a bad standard input that reads from a broken pipe.  */
+
+  if (bad_stdin == -1)
+    {
+      /* Make a file descriptor that is the read end of a broken pipe.
+	 This will be used for some children's standard inputs.  */
+      int pd[2];
+      if (pipe (pd) == 0)
+	{
+	  /* Close the write side.  */
+	  (void) close (pd[1]);
+	  /* Save the read side.  */
+	  bad_stdin = pd[0];
+
+	  /* Set the descriptor to close on exec, so it does not litter any
+	     child's descriptor table.  When it is dup2'd onto descriptor 0,
+	     that descriptor will not close on exec.  */
+	  CLOSE_ON_EXEC (bad_stdin);
+	}
+    }
+
+#endif /* !WINDOWS32 && !_AMIGA && !__MSDOS__ */
+
+  /* Decide whether to give this child the `good' standard input
+     (one that points to the terminal or whatever), or the `bad' one
+     that points to the read side of a broken pipe.  */
+
+  child->good_stdin = !good_stdin_used;
+  if (child->good_stdin)
+    good_stdin_used = 1;
+
+#endif /* !VMS */
+
+  child->deleted = 0;
+
+#ifndef _AMIGA
+  /* Set up the environment for the child.  */
+  if (child->environment == 0)
+    child->environment = target_environment (child->file);
+#endif
+
+#if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32)
+
+#ifndef VMS
+  /* start_waiting_job has set CHILD->remote if we can start a remote job.  */
+  if (child->remote)
+    {
+      int is_remote, id, used_stdin;
+      if (start_remote_job (argv, child->environment,
+			    child->good_stdin ? 0 : bad_stdin,
+			    &is_remote, &id, &used_stdin))
+        /* Don't give up; remote execution may fail for various reasons.  If
+           so, simply run the job locally.  */
+	goto run_local;
+      else
+	{
+	  if (child->good_stdin && !used_stdin)
+	    {
+	      child->good_stdin = 0;
+	      good_stdin_used = 0;
+	    }
+	  child->remote = is_remote;
+	  child->pid = id;
+	}
+    }
+  else
+#endif /* !VMS */
+    {
+      /* Fork the child process.  */
+
+      char **parent_environ;
+
+    run_local:
+      block_sigs ();
+
+      child->remote = 0;
+
+#ifdef VMS
+      if (!child_execute_job (argv, child)) {
+        /* Fork failed!  */
+        perror_with_name ("vfork", "");
+        goto error;
+      }
+
+#else
+
+      parent_environ = environ;
+
+# ifdef __EMX__
+      /* If we aren't running a recursive command and we have a jobserver
+         pipe, close it before exec'ing.  */
+      if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
+	{
+	  CLOSE_ON_EXEC (job_fds[0]);
+	  CLOSE_ON_EXEC (job_fds[1]);
+	}
+      if (job_rfd >= 0)
+	CLOSE_ON_EXEC (job_rfd);
+
+      /* Never use fork()/exec() here! Use spawn() instead in exec_command() */
+      child->pid = child_execute_job (child->good_stdin ? 0 : bad_stdin, 1,
+                                      argv, child->environment);
+      if (child->pid < 0)
+	{
+	  /* spawn failed!  */
+	  unblock_sigs ();
+	  perror_with_name ("spawn", "");
+	  goto error;
+	}
+
+      /* undo CLOSE_ON_EXEC() after the child process has been started */
+      if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
+	{
+	  fcntl (job_fds[0], F_SETFD, 0);
+	  fcntl (job_fds[1], F_SETFD, 0);
+	}
+      if (job_rfd >= 0)
+	fcntl (job_rfd, F_SETFD, 0);
+
+#else  /* !__EMX__ */
+
+      child->pid = vfork ();
+      environ = parent_environ;	/* Restore value child may have clobbered.  */
+      if (child->pid == 0)
+	{
+	  /* We are the child side.  */
+	  unblock_sigs ();
+
+          /* If we aren't running a recursive command and we have a jobserver
+             pipe, close it before exec'ing.  */
+          if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
+            {
+              close (job_fds[0]);
+              close (job_fds[1]);
+            }
+          if (job_rfd >= 0)
+            close (job_rfd);
+
+	  child_execute_job (child->good_stdin ? 0 : bad_stdin, 1,
+                             argv, child->environment);
+	}
+      else if (child->pid < 0)
+	{
+	  /* Fork failed!  */
+	  unblock_sigs ();
+	  perror_with_name ("vfork", "");
+	  goto error;
+	}
+# endif  /* !__EMX__ */
+#endif /* !VMS */
+    }
+
+#else	/* __MSDOS__ or Amiga or WINDOWS32 */
+#ifdef __MSDOS__
+  {
+    int proc_return;
+
+    block_sigs ();
+    dos_status = 0;
+
+    /* We call `system' to do the job of the SHELL, since stock DOS
+       shell is too dumb.  Our `system' knows how to handle long
+       command lines even if pipes/redirection is needed; it will only
+       call COMMAND.COM when its internal commands are used.  */
+    if (execute_by_shell)
+      {
+	char *cmdline = argv[0];
+	/* We don't have a way to pass environment to `system',
+	   so we need to save and restore ours, sigh...  */
+	char **parent_environ = environ;
+
+	environ = child->environment;
+
+	/* If we have a *real* shell, tell `system' to call
+	   it to do everything for us.  */
+	if (unixy_shell)
+	  {
+	    /* A *real* shell on MSDOS may not support long
+	       command lines the DJGPP way, so we must use `system'.  */
+	    cmdline = argv[2];	/* get past "shell -c" */
+	  }
+
+	dos_command_running = 1;
+	proc_return = system (cmdline);
+	environ = parent_environ;
+	execute_by_shell = 0;	/* for the next time */
+      }
+    else
+      {
+	dos_command_running = 1;
+	proc_return = spawnvpe (P_WAIT, argv[0], argv, child->environment);
+      }
+
+    /* Need to unblock signals before turning off
+       dos_command_running, so that child's signals
+       will be treated as such (see fatal_error_signal).  */
+    unblock_sigs ();
+    dos_command_running = 0;
+
+    /* If the child got a signal, dos_status has its
+       high 8 bits set, so be careful not to alter them.  */
+    if (proc_return == -1)
+      dos_status |= 0xff;
+    else
+      dos_status |= (proc_return & 0xff);
+    ++dead_children;
+    child->pid = dos_pid++;
+  }
+#endif /* __MSDOS__ */
+#ifdef _AMIGA
+  amiga_status = MyExecute (argv);
+
+  ++dead_children;
+  child->pid = amiga_pid++;
+  if (amiga_batch_file)
+  {
+     amiga_batch_file = 0;
+     DeleteFile (amiga_bname);        /* Ignore errors.  */
+  }
+#endif	/* Amiga */
+#ifdef WINDOWS32
+  {
+      HANDLE hPID;
+      char* arg0;
+
+      /* make UNC paths safe for CreateProcess -- backslash format */
+      arg0 = argv[0];
+      if (arg0 && arg0[0] == '/' && arg0[1] == '/')
+        for ( ; arg0 && *arg0; arg0++)
+          if (*arg0 == '/')
+            *arg0 = '\\';
+
+      /* make sure CreateProcess() has Path it needs */
+      sync_Path_environment();
+
+      hPID = process_easy(argv, child->environment);
+
+      if (hPID != INVALID_HANDLE_VALUE)
+        child->pid = (int) hPID;
+      else {
+        int i;
+        unblock_sigs();
+        fprintf(stderr,
+                _("process_easy() failed to launch process (e=%ld)\n"),
+                process_last_err(hPID));
+        for (i = 0; argv[i]; i++)
+          fprintf(stderr, "%s ", argv[i]);
+        fprintf(stderr, _("\nCounted %d args in failed launch\n"), i);
+        goto error;
+      }
+  }
+#endif /* WINDOWS32 */
+#endif	/* __MSDOS__ or Amiga or WINDOWS32 */
+
+  /* Bump the number of jobs started in this second.  */
+  ++job_counter;
+
+  /* We are the parent side.  Set the state to
+     say the commands are running and return.  */
+
+  set_command_state (child->file, cs_running);
+
+  /* Free the storage used by the child's argument list.  */
+#ifdef KMK /* leak */
+ cleanup_argv:
+#endif
+#ifndef VMS
+  free (argv[0]);
+  free (argv);
+#endif
+
+  return;
+
+ error:
+  child->file->update_status = 2;
+  notice_finished_file (child->file);
+#ifdef KMK /* fix leak */
+  goto cleanup_argv;
+#else
+  return;
+#endif
+}
+
+/* Try to start a child running.
+   Returns nonzero if the child was started (and maybe finished), or zero if
+   the load was too high and the child was put on the `waiting_jobs' chain.  */
+
+static int
+start_waiting_job (struct child *c)
+{
+  struct file *f = c->file;
+#ifdef DB_KMK
+  DB (DB_KMK, (_("start_waiting_job %p (`%s') command_flags=%#x slots=%d/%d\n"), c, c->file->name, c->file->command_flags, job_slots_used, job_slots));
+#endif
+
+  /* If we can start a job remotely, we always want to, and don't care about
+     the local load average.  We record that the job should be started
+     remotely in C->remote for start_job_command to test.  */
+
+  c->remote = start_remote_job_p (1);
+
+#ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL
+  if (c->file->command_flags & COMMANDS_NOTPARALLEL)
+    {
+      DB (DB_KMK, (_("not_parallel %d -> %d (file=%p `%s') [start_waiting_job]\n"),
+                   not_parallel, not_parallel + 1, c->file, c->file->name));
+      assert(not_parallel >= 0);
+      ++not_parallel;
+    }
+#endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+
+  /* If we are running at least one job already and the load average
+     is too high, make this one wait.  */
+  if (!c->remote
+#ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL
+      && ((job_slots_used > 0 && (not_parallel > 0 || load_too_high ()))
+#else
+      && ((job_slots_used > 0 && load_too_high ())
+#endif
+#ifdef WINDOWS32
+	  || (process_used_slots () >= MAXIMUM_WAIT_OBJECTS)
+#endif
+	  ))
+    {
+#ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL
+        /* Put this child on the chain of children waiting for the load average
+           to go down.  */
+        set_command_state (f, cs_running);
+        c->next = waiting_jobs;
+        waiting_jobs = c;
+
+#else  /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+
+      /* Put this child on the chain of children waiting for the load average
+         to go down. If not parallel, put it last.  */
+      set_command_state (f, cs_running);
+      c->next = waiting_jobs;
+      if (c->next && (c->file->command_flags & COMMANDS_NOTPARALLEL))
+        {
+          struct child *prev = waiting_jobs;
+          while (prev->next)
+            prev = prev->next;
+          c->next = 0;
+          prev->next = c;
+        }
+      else /* FIXME: insert after the last node with COMMANDS_NOTPARALLEL set */
+        waiting_jobs = c;
+      DB (DB_KMK, (_("queued child %p (`%s')\n"), c, c->file->name));
+#endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+      return 0;
+    }
+
+  /* Start the first command; reap_children will run later command lines.  */
+  start_job_command (c);
+
+  switch (f->command_state)
+    {
+    case cs_running:
+      c->next = children;
+      DB (DB_JOBS, (_("Putting child 0x%08lx (%s) PID %ld%s on the chain.\n"),
+                    (unsigned long int) c, c->file->name,
+                    (long) c->pid, c->remote ? _(" (remote)") : ""));
+      children = c;
+      /* One more job slot is in use.  */
+      ++job_slots_used;
+      unblock_sigs ();
+      break;
+
+    case cs_not_started:
+      /* All the command lines turned out to be empty.  */
+      f->update_status = 0;
+      /* FALLTHROUGH */
+
+    case cs_finished:
+      notice_finished_file (f);
+      free_child (c);
+      break;
+
+    default:
+      assert (f->command_state == cs_finished);
+      break;
+    }
+
+  return 1;
+}
+
+/* Create a `struct child' for FILE and start its commands running.  */
+
+void
+new_job (struct file *file)
+{
+  struct commands *cmds = file->cmds;
+  struct child *c;
+  char **lines;
+  unsigned int i;
+
+  /* Let any previously decided-upon jobs that are waiting
+     for the load to go down start before this new one.  */
+  start_waiting_jobs ();
+
+  /* Reap any children that might have finished recently.  */
+  reap_children (0, 0);
+
+  /* Chop the commands up into lines if they aren't already.  */
+  chop_commands (cmds);
+
+  /* Expand the command lines and store the results in LINES.  */
+  lines = xmalloc (cmds->ncommand_lines * sizeof (char *));
+  for (i = 0; i < cmds->ncommand_lines; ++i)
+    {
+      /* Collapse backslash-newline combinations that are inside variable
+	 or function references.  These are left alone by the parser so
+	 that they will appear in the echoing of commands (where they look
+	 nice); and collapsed by construct_command_argv when it tokenizes.
+	 But letting them survive inside function invocations loses because
+	 we don't want the functions to see them as part of the text.  */
+
+      char *in, *out, *ref;
+
+      /* IN points to where in the line we are scanning.
+	 OUT points to where in the line we are writing.
+	 When we collapse a backslash-newline combination,
+	 IN gets ahead of OUT.  */
+
+      in = out = cmds->command_lines[i];
+      while ((ref = strchr (in, '$')) != 0)
+	{
+	  ++ref;		/* Move past the $.  */
+
+	  if (out != in)
+	    /* Copy the text between the end of the last chunk
+	       we processed (where IN points) and the new chunk
+	       we are about to process (where REF points).  */
+	    memmove (out, in, ref - in);
+
+	  /* Move both pointers past the boring stuff.  */
+	  out += ref - in;
+	  in = ref;
+
+	  if (*ref == '(' || *ref == '{')
+	    {
+	      char openparen = *ref;
+	      char closeparen = openparen == '(' ? ')' : '}';
+	      int count;
+	      char *p;
+
+	      *out++ = *in++;	/* Copy OPENPAREN.  */
+	      /* IN now points past the opening paren or brace.
+		 Count parens or braces until it is matched.  */
+	      count = 0;
+	      while (*in != '\0')
+		{
+		  if (*in == closeparen && --count < 0)
+		    break;
+		  else if (*in == '\\' && in[1] == '\n')
+		    {
+		      /* We have found a backslash-newline inside a
+			 variable or function reference.  Eat it and
+			 any following whitespace.  */
+
+		      int quoted = 0;
+		      for (p = in - 1; p > ref && *p == '\\'; --p)
+			quoted = !quoted;
+
+		      if (quoted)
+			/* There were two or more backslashes, so this is
+			   not really a continuation line.  We don't collapse
+			   the quoting backslashes here as is done in
+			   collapse_continuations, because the line will
+			   be collapsed again after expansion.  */
+			*out++ = *in++;
+		      else
+			{
+			  /* Skip the backslash, newline and
+			     any following whitespace.  */
+			  in = next_token (in + 2);
+
+			  /* Discard any preceding whitespace that has
+			     already been written to the output.  */
+			  while (out > ref
+				 && isblank ((unsigned char)out[-1]))
+			    --out;
+
+			  /* Replace it all with a single space.  */
+			  *out++ = ' ';
+			}
+		    }
+		  else
+		    {
+		      if (*in == openparen)
+			++count;
+
+		      *out++ = *in++;
+		    }
+		}
+	    }
+	}
+
+      /* There are no more references in this line to worry about.
+	 Copy the remaining uninteresting text to the output.  */
+      if (out != in)
+	strcpy (out, in);
+
+      /* Finally, expand the line.  */
+      lines[i] = allocated_variable_expand_for_file (cmds->command_lines[i],
+						     file);
+    }
+
+  /* Start the command sequence, record it in a new
+     `struct child', and add that to the chain.  */
+
+  c = xmalloc (sizeof (struct child));
+  memset (c, '\0', sizeof (struct child));
+  c->file = file;
+  c->command_lines = lines;
+  c->sh_batch_file = NULL;
+
+  /* Cache dontcare flag because file->dontcare can be changed once we
+     return. Check dontcare inheritance mechanism for details.  */
+  c->dontcare = file->dontcare;
+
+  /* Fetch the first command line to be run.  */
+  job_next_command (c);
+
+  /* Wait for a job slot to be freed up.  If we allow an infinite number
+     don't bother; also job_slots will == 0 if we're using the jobserver.  */
+
+  if (job_slots != 0)
+    while (job_slots_used == job_slots)
+      reap_children (1, 0);
+
+#ifdef MAKE_JOBSERVER
+  /* If we are controlling multiple jobs make sure we have a token before
+     starting the child. */
+
+  /* This can be inefficient.  There's a decent chance that this job won't
+     actually have to run any subprocesses: the command script may be empty
+     or otherwise optimized away.  It would be nice if we could defer
+     obtaining a token until just before we need it, in start_job_command.
+     To do that we'd need to keep track of whether we'd already obtained a
+     token (since start_job_command is called for each line of the job, not
+     just once).  Also more thought needs to go into the entire algorithm;
+     this is where the old parallel job code waits, so...  */
+
+  else if (job_fds[0] >= 0)
+    while (1)
+      {
+        char token;
+	int got_token;
+	int saved_errno;
+
+        DB (DB_JOBS, ("Need a job token; we %shave children\n",
+                      children ? "" : "don't "));
+
+        /* If we don't already have a job started, use our "free" token.  */
+        if (!jobserver_tokens)
+          break;
+
+        /* Read a token.  As long as there's no token available we'll block.
+           We enable interruptible system calls before the read(2) so that if
+           we get a SIGCHLD while we're waiting, we'll return with EINTR and
+           we can process the death(s) and return tokens to the free pool.
+
+           Once we return from the read, we immediately reinstate restartable
+           system calls.  This allows us to not worry about checking for
+           EINTR on all the other system calls in the program.
+
+           There is one other twist: there is a span between the time
+           reap_children() does its last check for dead children and the time
+           the read(2) call is entered, below, where if a child dies we won't
+           notice.  This is extremely serious as it could cause us to
+           deadlock, given the right set of events.
+
+           To avoid this, we do the following: before we reap_children(), we
+           dup(2) the read FD on the jobserver pipe.  The read(2) call below
+           uses that new FD.  In the signal handler, we close that FD.  That
+           way, if a child dies during the section mentioned above, the
+           read(2) will be invoked with an invalid FD and will return
+           immediately with EBADF.  */
+
+        /* Make sure we have a dup'd FD.  */
+        if (job_rfd < 0)
+          {
+            DB (DB_JOBS, ("Duplicate the job FD\n"));
+            job_rfd = dup (job_fds[0]);
+          }
+
+        /* Reap anything that's currently waiting.  */
+        reap_children (0, 0);
+
+        /* Kick off any jobs we have waiting for an opportunity that
+           can run now (ie waiting for load). */
+        start_waiting_jobs ();
+
+        /* If our "free" slot has become available, use it; we don't need an
+           actual token.  */
+        if (!jobserver_tokens)
+          break;
+
+        /* There must be at least one child already, or we have no business
+           waiting for a token. */
+        if (!children)
+          fatal (NILF, "INTERNAL: no children as we go to sleep on read\n");
+
+        /* Set interruptible system calls, and read() for a job token.  */
+	set_child_handler_action_flags (1, waiting_jobs != NULL);
+	got_token = read (job_rfd, &token, 1);
+	saved_errno = errno;
+	set_child_handler_action_flags (0, waiting_jobs != NULL);
+
+        /* If we got one, we're done here.  */
+	if (got_token == 1)
+          {
+            DB (DB_JOBS, (_("Obtained token for child 0x%08lx (%s).\n"),
+                          (unsigned long int) c, c->file->name));
+            break;
+          }
+
+        /* If the error _wasn't_ expected (EINTR or EBADF), punt.  Otherwise,
+           go back and reap_children(), and try again.  */
+	errno = saved_errno;
+        if (errno != EINTR && errno != EBADF)
+          pfatal_with_name (_("read jobs pipe"));
+        if (errno == EBADF)
+          DB (DB_JOBS, ("Read returned EBADF.\n"));
+      }
+#endif
+
+  ++jobserver_tokens;
+
+  /* The job is now primed.  Start it running.
+     (This will notice if there are in fact no commands.)  */
+  if (cmds->fileinfo.filenm)
+    DB (DB_BASIC, (_("Invoking commands from %s:%lu to update target `%s'.\n"),
+                   cmds->fileinfo.filenm, cmds->fileinfo.lineno,
+                   c->file->name));
+  else
+    DB (DB_BASIC, (_("Invoking builtin commands to update target `%s'.\n"),
+                   c->file->name));
+
+
+  start_waiting_job (c);
+
+#ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL
+  if (job_slots == 1 || not_parallel)
+    /* Since there is only one job slot, make things run linearly.
+       Wait for the child to die, setting the state to `cs_finished'.  */
+    while (file->command_state == cs_running)
+      reap_children (1, 0);
+
+#else /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+
+  if (job_slots == 1 || not_parallel < 0)
+    {
+      /* Since there is only one job slot, make things run linearly.
+         Wait for the child to die, setting the state to `cs_finished'.  */
+      while (file->command_state == cs_running)
+        reap_children (1, 0);
+    }
+  else if (not_parallel > 0)
+    {
+      /* wait for all live children to finish and then continue
+         with the not-parallel child(s). FIXME: this loop could be better? */
+      while (file->command_state == cs_running
+          && (children != 0 || shell_function_pid != 0) /* reap_child condition */
+          && not_parallel > 0)
+        reap_children (1, 0);
+    }
+#endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+
+  return;
+}
+
+
+/* Move CHILD's pointers to the next command for it to execute.
+   Returns nonzero if there is another command.  */
+
+static int
+job_next_command (struct child *child)
+{
+  while (child->command_ptr == 0 || *child->command_ptr == '\0')
+    {
+      /* There are no more lines in the expansion of this line.  */
+      if (child->command_line == child->file->cmds->ncommand_lines)
+	{
+	  /* There are no more lines to be expanded.  */
+	  child->command_ptr = 0;
+	  return 0;
+	}
+      else
+	/* Get the next line to run.  */
+	child->command_ptr = child->command_lines[child->command_line++];
+    }
+  return 1;
+}
+
+/* Determine if the load average on the system is too high to start a new job.
+   The real system load average is only recomputed once a second.  However, a
+   very parallel make can easily start tens or even hundreds of jobs in a
+   second, which brings the system to its knees for a while until that first
+   batch of jobs clears out.
+
+   To avoid this we use a weighted algorithm to try to account for jobs which
+   have been started since the last second, and guess what the load average
+   would be now if it were computed.
+
+   This algorithm was provided by Thomas Riedl <thomas.riedl@siemens.com>,
+   who writes:
+
+!      calculate something load-oid and add to the observed sys.load,
+!      so that latter can catch up:
+!      - every job started increases jobctr;
+!      - every dying job decreases a positive jobctr;
+!      - the jobctr value gets zeroed every change of seconds,
+!        after its value*weight_b is stored into the 'backlog' value last_sec
+!      - weight_a times the sum of jobctr and last_sec gets
+!        added to the observed sys.load.
+!
+!      The two weights have been tried out on 24 and 48 proc. Sun Solaris-9
+!      machines, using a several-thousand-jobs-mix of cpp, cc, cxx and smallish
+!      sub-shelled commands (rm, echo, sed...) for tests.
+!      lowering the 'direct influence' factor weight_a (e.g. to 0.1)
+!      resulted in significant excession of the load limit, raising it
+!      (e.g. to 0.5) took bad to small, fast-executing jobs and didn't
+!      reach the limit in most test cases.
+!
+!      lowering the 'history influence' weight_b (e.g. to 0.1) resulted in
+!      exceeding the limit for longer-running stuff (compile jobs in
+!      the .5 to 1.5 sec. range),raising it (e.g. to 0.5) overrepresented
+!      small jobs' effects.
+
+ */
+
+#define LOAD_WEIGHT_A           0.25
+#define LOAD_WEIGHT_B           0.25
+
+static int
+load_too_high (void)
+{
+#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__)
+  return 1;
+#else
+  static double last_sec;
+  static time_t last_now;
+  double load, guess;
+  time_t now;
+
+#ifdef WINDOWS32
+  /* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS children */
+  if (process_used_slots () >= MAXIMUM_WAIT_OBJECTS)
+    return 1;
+#endif
+
+  if (max_load_average < 0)
+    return 0;
+
+  /* Find the real system load average.  */
+  make_access ();
+  if (getloadavg (&load, 1) != 1)
+    {
+      static int lossage = -1;
+      /* Complain only once for the same error.  */
+      if (lossage == -1 || errno != lossage)
+	{
+	  if (errno == 0)
+	    /* An errno value of zero means getloadavg is just unsupported.  */
+	    error (NILF,
+                   _("cannot enforce load limits on this operating system"));
+	  else
+	    perror_with_name (_("cannot enforce load limit: "), "getloadavg");
+	}
+      lossage = errno;
+      load = 0;
+    }
+  user_access ();
+
+  /* If we're in a new second zero the counter and correct the backlog
+     value.  Only keep the backlog for one extra second; after that it's 0.  */
+  now = time (NULL);
+  if (last_now < now)
+    {
+      if (last_now == now - 1)
+        last_sec = LOAD_WEIGHT_B * job_counter;
+      else
+        last_sec = 0.0;
+
+      job_counter = 0;
+      last_now = now;
+    }
+
+  /* Try to guess what the load would be right now.  */
+  guess = load + (LOAD_WEIGHT_A * (job_counter + last_sec));
+
+  DB (DB_JOBS, ("Estimated system load = %f (actual = %f) (max requested = %f)\n",
+                guess, load, max_load_average));
+
+  return guess >= max_load_average;
+#endif
+}
+
+/* Start jobs that are waiting for the load to be lower.  */
+
+void
+start_waiting_jobs (void)
+{
+  struct child *job;
+
+  if (waiting_jobs == 0)
+    return;
+
+  do
+    {
+      /* Check for recently deceased descendants.  */
+      reap_children (0, 0);
+
+      /* Take a job off the waiting list.  */
+      job = waiting_jobs;
+      waiting_jobs = job->next;
+
+#ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL
+      /* If it's a not-parallel job, we've already counted it once
+         when it was queued in start_waiting_job, so decrement
+         before sending it to  start_waiting_job again. */
+      if (job->file->command_flags & COMMANDS_NOTPARALLEL)
+        {
+          DB (DB_KMK, (_("not_parallel %d -> %d (file=%p `%s') [start_waiting_jobs]\n"),
+                       not_parallel, not_parallel - 1, job->file, job->file->name));
+          assert(not_parallel > 0);
+          --not_parallel;
+        }
+#endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+
+      /* Try to start that job.  We break out of the loop as soon
+	 as start_waiting_job puts one back on the waiting list.  */
+    }
+  while (start_waiting_job (job) && waiting_jobs != 0);
+
+  return;
+}
+
+
+#ifndef WINDOWS32
+
+/* EMX: Start a child process. This function returns the new pid.  */
+# if defined __MSDOS__ || defined __EMX__
+int
+child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp)
+{
+  int pid;
+  /* stdin_fd == 0 means: nothing to do for stdin;
+     stdout_fd == 1 means: nothing to do for stdout */
+  int save_stdin = (stdin_fd != 0) ? dup (0) : 0;
+  int save_stdout = (stdout_fd != 1) ? dup (1): 1;
+
+  /* < 0 only if dup() failed */
+  if (save_stdin < 0)
+    fatal (NILF, _("no more file handles: could not duplicate stdin\n"));
+  if (save_stdout < 0)
+    fatal (NILF, _("no more file handles: could not duplicate stdout\n"));
+
+  /* Close unnecessary file handles for the child.  */
+  if (save_stdin != 0)
+    CLOSE_ON_EXEC (save_stdin);
+  if (save_stdout != 1)
+    CLOSE_ON_EXEC (save_stdout);
+
+  /* Connect the pipes to the child process.  */
+  if (stdin_fd != 0)
+    (void) dup2 (stdin_fd, 0);
+  if (stdout_fd != 1)
+    (void) dup2 (stdout_fd, 1);
+
+  /* stdin_fd and stdout_fd must be closed on exit because we are
+     still in the parent process */
+  if (stdin_fd != 0)
+    CLOSE_ON_EXEC (stdin_fd);
+  if (stdout_fd != 1)
+    CLOSE_ON_EXEC (stdout_fd);
+
+  /* Run the command.  */
+  pid = exec_command (argv, envp);
+
+  /* Restore stdout/stdin of the parent and close temporary FDs.  */
+  if (stdin_fd != 0)
+    {
+      if (dup2 (save_stdin, 0) != 0)
+        fatal (NILF, _("Could not restore stdin\n"));
+      else
+        close (save_stdin);
+    }
+
+  if (stdout_fd != 1)
+    {
+      if (dup2 (save_stdout, 1) != 1)
+        fatal (NILF, _("Could not restore stdout\n"));
+      else
+        close (save_stdout);
+    }
+
+  return pid;
+}
+
+#elif !defined (_AMIGA) && !defined (__MSDOS__) && !defined (VMS)
+
+/* UNIX:
+   Replace the current process with one executing the command in ARGV.
+   STDIN_FD and STDOUT_FD are used as the process's stdin and stdout; ENVP is
+   the environment of the new program.  This function does not return.  */
+void
+child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp)
+{
+  if (stdin_fd != 0)
+    (void) dup2 (stdin_fd, 0);
+  if (stdout_fd != 1)
+    (void) dup2 (stdout_fd, 1);
+  if (stdin_fd != 0)
+    (void) close (stdin_fd);
+  if (stdout_fd != 1)
+    (void) close (stdout_fd);
+
+  /* Run the command.  */
+  exec_command (argv, envp);
+}
+#endif /* !AMIGA && !__MSDOS__ && !VMS */
+#endif /* !WINDOWS32 */
+
+
+#ifndef _AMIGA
+/* Replace the current process with one running the command in ARGV,
+   with environment ENVP.  This function does not return.  */
+
+/* EMX: This function returns the pid of the child process.  */
+# ifdef __EMX__
+int
+# else
+void
+# endif
+exec_command (char **argv, char **envp)
+{
+#ifdef VMS
+  /* to work around a problem with signals and execve: ignore them */
+#ifdef SIGCHLD
+  signal (SIGCHLD,SIG_IGN);
+#endif
+  /* Run the program.  */
+  execve (argv[0], argv, envp);
+  perror_with_name ("execve: ", argv[0]);
+  _exit (EXIT_FAILURE);
+#else
+#ifdef WINDOWS32
+  HANDLE hPID;
+  HANDLE hWaitPID;
+  int err = 0;
+  int exit_code = EXIT_FAILURE;
+
+  /* make sure CreateProcess() has Path it needs */
+  sync_Path_environment();
+
+  /* launch command */
+  hPID = process_easy(argv, envp);
+
+  /* make sure launch ok */
+  if (hPID == INVALID_HANDLE_VALUE)
+    {
+      int i;
+      fprintf(stderr,
+              _("process_easy() failed failed to launch process (e=%ld)\n"),
+              process_last_err(hPID));
+      for (i = 0; argv[i]; i++)
+          fprintf(stderr, "%s ", argv[i]);
+      fprintf(stderr, _("\nCounted %d args in failed launch\n"), i);
+      exit(EXIT_FAILURE);
+    }
+
+  /* wait and reap last child */
+  hWaitPID = process_wait_for_any();
+  while (hWaitPID)
+    {
+      /* was an error found on this process? */
+      err = process_last_err(hWaitPID);
+
+      /* get exit data */
+      exit_code = process_exit_code(hWaitPID);
+
+      if (err)
+          fprintf(stderr, "make (e=%d, rc=%d): %s",
+                  err, exit_code, map_windows32_error_to_string(err));
+
+      /* cleanup process */
+      process_cleanup(hWaitPID);
+
+      /* expect to find only last pid, warn about other pids reaped */
+      if (hWaitPID == hPID)
+          break;
+      else
+          fprintf(stderr,
+                  _("make reaped child pid %ld, still waiting for pid %ld\n"),
+                  (DWORD)hWaitPID, (DWORD)hPID);
+    }
+
+  /* return child's exit code as our exit code */
+  exit(exit_code);
+
+#else  /* !WINDOWS32 */
+
+# ifdef __EMX__
+  int pid;
+# endif
+
+  /* Be the user, permanently.  */
+  child_access ();
+
+# ifdef __EMX__
+
+  /* Run the program.  */
+  pid = spawnvpe (P_NOWAIT, argv[0], argv, envp);
+
+  if (pid >= 0)
+    return pid;
+
+  /* the file might have a strange shell extension */
+  if (errno == ENOENT)
+    errno = ENOEXEC;
+
+# else
+
+  /* Run the program.  */
+  environ = envp;
+  execvp (argv[0], argv);
+
+# endif /* !__EMX__ */
+
+  switch (errno)
+    {
+    case ENOENT:
+      error (NILF, _("%s: Command not found"), argv[0]);
+      break;
+    case ENOEXEC:
+      {
+	/* The file is not executable.  Try it as a shell script.  */
+	extern char *getenv ();
+	char *shell;
+	char **new_argv;
+	int argc;
+        int i=1;
+
+# ifdef __EMX__
+        /* Do not use $SHELL from the environment */
+	struct variable *p = lookup_variable ("SHELL", 5);
+	if (p)
+	  shell = p->value;
+        else
+          shell = 0;
+# else
+	shell = getenv ("SHELL");
+# endif
+	if (shell == 0)
+	  shell = default_shell;
+
+	argc = 1;
+	while (argv[argc] != 0)
+	  ++argc;
+
+# ifdef __EMX__
+        if (!unixy_shell)
+          ++argc;
+# endif
+
+	new_argv = alloca ((1 + argc + 1) * sizeof (char *));
+	new_argv[0] = shell;
+
+# ifdef __EMX__
+        if (!unixy_shell)
+          {
+            new_argv[1] = "/c";
+            ++i;
+            --argc;
+          }
+# endif
+
+        new_argv[i] = argv[0];
+	while (argc > 0)
+	  {
+	    new_argv[i + argc] = argv[argc];
+	    --argc;
+	  }
+
+# ifdef __EMX__
+	pid = spawnvpe (P_NOWAIT, shell, new_argv, envp);
+	if (pid >= 0)
+          break;
+# else
+	execvp (shell, new_argv);
+# endif
+	if (errno == ENOENT)
+	  error (NILF, _("%s: Shell program not found"), shell);
+	else
+	  perror_with_name ("execvp: ", shell);
+	break;
+      }
+
+# ifdef __EMX__
+    case EINVAL:
+      /* this nasty error was driving me nuts :-( */
+      error (NILF, _("spawnvpe: environment space might be exhausted"));
+      /* FALLTHROUGH */
+# endif
+
+    default:
+      perror_with_name ("execvp: ", argv[0]);
+      break;
+    }
+
+# ifdef __EMX__
+  return pid;
+# else
+  _exit (127);
+# endif
+#endif /* !WINDOWS32 */
+#endif /* !VMS */
+}
+#else /* On Amiga */
+void exec_command (char **argv)
+{
+  MyExecute (argv);
+}
+
+void clean_tmp (void)
+{
+  DeleteFile (amiga_bname);
+}
+
+#endif /* On Amiga */
+
+
+#ifndef VMS
+/* Figure out the argument list necessary to run LINE as a command.  Try to
+   avoid using a shell.  This routine handles only ' quoting, and " quoting
+   when no backslash, $ or ` characters are seen in the quotes.  Starting
+   quotes may be escaped with a backslash.  If any of the characters in
+   sh_chars[] is seen, or any of the builtin commands listed in sh_cmds[]
+   is the first word of a line, the shell is used.
+
+   If RESTP is not NULL, *RESTP is set to point to the first newline in LINE.
+   If *RESTP is NULL, newlines will be ignored.
+
+   SHELL is the shell to use, or nil to use the default shell.
+   IFS is the value of $IFS, or nil (meaning the default).  */
+
+static char **
+construct_command_argv_internal (char *line, char **restp, char *shell,
+                                 char *ifs, char **batch_filename_ptr)
+{
+#ifdef __MSDOS__
+  /* MSDOS supports both the stock DOS shell and ports of Unixy shells.
+     We call `system' for anything that requires ``slow'' processing,
+     because DOS shells are too dumb.  When $SHELL points to a real
+     (unix-style) shell, `system' just calls it to do everything.  When
+     $SHELL points to a DOS shell, `system' does most of the work
+     internally, calling the shell only for its internal commands.
+     However, it looks on the $PATH first, so you can e.g. have an
+     external command named `mkdir'.
+
+     Since we call `system', certain characters and commands below are
+     actually not specific to COMMAND.COM, but to the DJGPP implementation
+     of `system'.  In particular:
+
+       The shell wildcard characters are in DOS_CHARS because they will
+       not be expanded if we call the child via `spawnXX'.
+
+       The `;' is in DOS_CHARS, because our `system' knows how to run
+       multiple commands on a single line.
+
+       DOS_CHARS also include characters special to 4DOS/NDOS, so we
+       won't have to tell one from another and have one more set of
+       commands and special characters.  */
+  static char sh_chars_dos[] = "*?[];|<>%^&()";
+  static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls",
+				 "copy", "ctty", "date", "del", "dir", "echo",
+				 "erase", "exit", "for", "goto", "if", "md",
+				 "mkdir", "path", "pause", "prompt", "rd",
+				 "rmdir", "rem", "ren", "rename", "set",
+				 "shift", "time", "type", "ver", "verify",
+				 "vol", ":", 0 };
+
+  static char sh_chars_sh[]  = "#;\"*?[]&|<>(){}$`^";
+  static char *sh_cmds_sh[]  = { "cd", "echo", "eval", "exec", "exit", "login",
+				 "logout", "set", "umask", "wait", "while",
+				 "for", "case", "if", ":", ".", "break",
+				 "continue", "export", "read", "readonly",
+				 "shift", "times", "trap", "switch", "unset",
+                                 0 };
+
+  char *sh_chars;
+  char **sh_cmds;
+#elif defined (__EMX__)
+  static char sh_chars_dos[] = "*?[];|<>%^&()";
+  static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls",
+				 "copy", "ctty", "date", "del", "dir", "echo",
+				 "erase", "exit", "for", "goto", "if", "md",
+				 "mkdir", "path", "pause", "prompt", "rd",
+				 "rmdir", "rem", "ren", "rename", "set",
+				 "shift", "time", "type", "ver", "verify",
+				 "vol", ":", 0 };
+
+  static char sh_chars_os2[] = "*?[];|<>%^()\"'&";
+  static char *sh_cmds_os2[] = { "call", "cd", "chcp", "chdir", "cls", "copy",
+			     "date", "del", "detach", "dir", "echo",
+			     "endlocal", "erase", "exit", "for", "goto", "if",
+			     "keys", "md", "mkdir", "move", "path", "pause",
+			     "prompt", "rd", "rem", "ren", "rename", "rmdir",
+			     "set", "setlocal", "shift", "start", "time",
+                             "type", "ver", "verify", "vol", ":", 0 };
+
+  static char sh_chars_sh[]  = "#;\"*?[]&|<>(){}$`^~'";
+  static char *sh_cmds_sh[]  = { "echo", "cd", "eval", "exec", "exit", "login",
+				 "logout", "set", "umask", "wait", "while",
+				 "for", "case", "if", ":", ".", "break",
+				 "continue", "export", "read", "readonly",
+				 "shift", "times", "trap", "switch", "unset",
+                                 0 };
+  char *sh_chars;
+  char **sh_cmds;
+
+#elif defined (_AMIGA)
+  static char sh_chars[] = "#;\"|<>()?*$`";
+  static char *sh_cmds[] = { "cd", "eval", "if", "delete", "echo", "copy",
+			     "rename", "set", "setenv", "date", "makedir",
+			     "skip", "else", "endif", "path", "prompt",
+			     "unset", "unsetenv", "version",
+			     0 };
+#elif defined (WINDOWS32)
+  static char sh_chars_dos[] = "\"|&<>";
+  static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls",
+			     "copy", "ctty", "date", "del", "dir", "echo",
+			     "erase", "exit", "for", "goto", "if", "if", "md",
+			     "mkdir", "path", "pause", "prompt", "rd", "rem",
+                             "ren", "rename", "rmdir", "set", "shift", "time",
+                             "type", "ver", "verify", "vol", ":", 0 };
+  static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^";
+  static char *sh_cmds_sh[] = { "cd", "eval", "exec", "exit", "login",
+			     "logout", "set", "umask", "wait", "while", "for",
+			     "case", "if", ":", ".", "break", "continue",
+			     "export", "read", "readonly", "shift", "times",
+			     "trap", "switch", "test",
+#ifdef BATCH_MODE_ONLY_SHELL
+                 "echo",
+#endif
+                 0 };
+  char*  sh_chars;
+  char** sh_cmds;
+#elif defined(__riscos__)
+  static char sh_chars[] = "";
+  static char *sh_cmds[] = { 0 };
+#else  /* must be UNIX-ish */
+  static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^~!";                          /* kmk: +_sh */
+  static char *sh_cmds_sh[] = { ".", ":", "break", "case", "cd", "continue",    /* kmk: +_sh */
+                             "eval", "exec", "exit", "export", "for", "if",
+                             "login", "logout", "read", "readonly", "set",
+                             "shift", "switch", "test", "times", "trap",
+                             "umask", "wait", "while", 0 };
+# ifdef HAVE_DOS_PATHS
+  /* This is required if the MSYS/Cygwin ports (which do not define
+     WINDOWS32) are compiled with HAVE_DOS_PATHS defined, which uses
+     sh_chars_sh[] directly (see below).  */
+  static char *sh_chars_sh = sh_chars;
+# endif	 /* HAVE_DOS_PATHS */
+  char*  sh_chars = sh_chars_sh;                                                /* kmk: +_sh */
+  char** sh_cmds = sh_cmds_sh;                                                  /* kmk: +_sh */
+#endif
+#ifdef KMK
+  static char sh_chars_kash[] = "#;*?[]&|<>(){}$`^~!";                          /* note: no \" - good idea? */
+  static char *sh_cmds_kash[] = {
+      ".", ":", "break", "case", "cd", "continue",
+      "echo", "eval", "exec", "exit", "export", "for", "if",
+      "login", "logout", "read", "readonly", "set",
+      "shift", "switch", "test", "times", "trap",
+      "umask", "wait", "while", 0
+  };
+  int is_kmk_shell = 0;
+#endif
+  int i;
+  char *p;
+  char *ap;
+  char *end;
+  int instring, word_has_equals, seen_nonequals, last_argument_was_empty;
+  char **new_argv = 0;
+  char *argstr = 0;
+#ifdef WINDOWS32
+  int slow_flag = 0;
+
+  if (!unixy_shell) {
+    sh_cmds = sh_cmds_dos;
+    sh_chars = sh_chars_dos;
+  } else {
+    sh_cmds = sh_cmds_sh;
+    sh_chars = sh_chars_sh;
+  }
+#endif /* WINDOWS32 */
+
+  if (restp != NULL)
+    *restp = NULL;
+
+  /* Make sure not to bother processing an empty line.  */
+  while (isblank ((unsigned char)*line))
+    ++line;
+  if (*line == '\0')
+    return 0;
+
+  /* See if it is safe to parse commands internally.  */
+#ifdef KMK /* kmk_ash and kmk_kash are both fine, kmk_ash is the default btw. */
+  if (shell == 0)
+    {
+      is_kmk_shell = 1;
+      shell = (char *)get_default_kbuild_shell ();
+    }
+  else if (!strcmp (shell, get_default_kbuild_shell()))
+    is_kmk_shell = 1;
+  else
+    {
+      const char *psz = strstr (shell, "/kmk_ash");
+      if (psz)
+        psz += sizeof ("/kmk_ash") - 1;
+      else
+        {
+          psz = strstr (shell, "/kmk_kash");
+          if (psz)
+            psz += sizeof ("/kmk_kash") - 1;
+        }
+# if defined (__OS2__) || defined (_WIN32) || defined (WINDOWS32)
+      is_kmk_shell = psz && (*psz == '\0' || !stricmp (psz, ".exe"));
+# else
+      is_kmk_shell = psz && *psz == '\0';
+# endif
+    }
+  if (is_kmk_shell)
+    {
+      sh_chars = sh_chars_kash;
+      sh_cmds = sh_cmds_kash;
+    }
+#else /* !KMK */
+  if (shell == 0)
+    shell = default_shell;
+#endif /* !KMK */
+#ifdef WINDOWS32
+  else if (strcmp (shell, default_shell))
+  {
+    char *s1 = _fullpath (NULL, shell, 0);
+    char *s2 = _fullpath (NULL, default_shell, 0);
+
+    slow_flag = strcmp ((s1 ? s1 : ""), (s2 ? s2 : ""));
+
+    if (s1)
+      free (s1);
+    if (s2)
+      free (s2);
+  }
+  if (slow_flag)
+    goto slow;
+#else  /* not WINDOWS32 */
+#if defined (__MSDOS__) || defined (__EMX__)
+  else if (strcasecmp (shell, default_shell))
+    {
+      extern int _is_unixy_shell (const char *_path);
+
+      DB (DB_BASIC, (_("$SHELL changed (was `%s', now `%s')\n"),
+                     default_shell, shell));
+      unixy_shell = _is_unixy_shell (shell);
+      /* we must allocate a copy of shell: construct_command_argv() will free
+       * shell after this function returns.  */
+      default_shell = xstrdup (shell);
+    }
+  if (unixy_shell)
+    {
+      sh_chars = sh_chars_sh;
+      sh_cmds  = sh_cmds_sh;
+    }
+  else
+    {
+      sh_chars = sh_chars_dos;
+      sh_cmds  = sh_cmds_dos;
+# ifdef __EMX__
+      if (_osmode == OS2_MODE)
+        {
+          sh_chars = sh_chars_os2;
+          sh_cmds = sh_cmds_os2;
+        }
+# endif
+    }
+#else  /* !__MSDOS__ */
+  else if (strcmp (shell, default_shell))
+    goto slow;
+#endif /* !__MSDOS__ && !__EMX__ */
+#endif /* not WINDOWS32 */
+
+  if (ifs != 0)
+    for (ap = ifs; *ap != '\0'; ++ap)
+      if (*ap != ' ' && *ap != '\t' && *ap != '\n')
+	goto slow;
+
+  i = strlen (line) + 1;
+
+  /* More than 1 arg per character is impossible.  */
+  new_argv = xmalloc (i * sizeof (char *));
+
+  /* All the args can fit in a buffer as big as LINE is.   */
+  ap = new_argv[0] = argstr = xmalloc (i);
+  end = ap + i;
+
+  /* I is how many complete arguments have been found.  */
+  i = 0;
+  instring = word_has_equals = seen_nonequals = last_argument_was_empty = 0;
+  for (p = line; *p != '\0'; ++p)
+    {
+      assert (ap <= end);
+
+      if (instring)
+	{
+	  /* Inside a string, just copy any char except a closing quote
+	     or a backslash-newline combination.  */
+	  if (*p == instring)
+	    {
+	      instring = 0;
+	      if (ap == new_argv[0] || *(ap-1) == '\0')
+		last_argument_was_empty = 1;
+	    }
+	  else if (*p == '\\' && p[1] == '\n')
+            {
+              /* Backslash-newline is handled differently depending on what
+                 kind of string we're in: inside single-quoted strings you
+                 keep them; in double-quoted strings they disappear.
+	         For DOS/Windows/OS2, if we don't have a POSIX shell,
+		 we keep the pre-POSIX behavior of removing the
+		 backslash-newline.  */
+              if (instring == '"'
+#if defined (__MSDOS__) || defined (__EMX__) || defined (WINDOWS32)
+		  || !unixy_shell
+#endif
+		  )
+                ++p;
+              else
+                {
+                  *(ap++) = *(p++);
+                  *(ap++) = *p;
+                }
+              /* If there's a command prefix char here, skip it.  */
+              if (p[1] == cmd_prefix)
+                ++p;
+            }
+	  else if (*p == '\n' && restp != NULL)
+	    {
+	      /* End of the command line.  */
+	      *restp = p;
+	      goto end_of_line;
+	    }
+	  /* Backslash, $, and ` are special inside double quotes.
+	     If we see any of those, punt.
+	     But on MSDOS, if we use COMMAND.COM, double and single
+	     quotes have the same effect.  */
+	  else if (instring == '"' && strchr ("\\$`", *p) != 0 && unixy_shell)
+	    goto slow;
+	  else
+	    *ap++ = *p;
+	}
+      else if (strchr (sh_chars, *p) != 0)
+#ifdef KMK
+        {
+          /* Tilde is only special if at the start of a path spec,
+             i.e. don't get excited when we by 8.3 files on windows. */
+          if (   *p == '~'
+              && p > line
+              && !isspace (p[-1])
+              && p[-1] != '='
+              && p[-1] != ':'
+              && p[-1] != '"'
+              && p[-1] != '\'')
+            *ap++ = *p;
+          else
+            /* Not inside a string, but it's a special char.  */
+            goto slow;
+        }
+#else  /* !KMK */
+	/* Not inside a string, but it's a special char.  */
+	goto slow;
+#endif /* !KMK */
+#ifdef  __MSDOS__
+      else if (*p == '.' && p[1] == '.' && p[2] == '.' && p[3] != '.')
+	/* `...' is a wildcard in DJGPP.  */
+	goto slow;
+#endif
+      else
+	/* Not a special char.  */
+	switch (*p)
+	  {
+	  case '=':
+	    /* Equals is a special character in leading words before the
+	       first word with no equals sign in it.  This is not the case
+	       with sh -k, but we never get here when using nonstandard
+	       shell flags.  */
+	    if (! seen_nonequals && unixy_shell)
+	      goto slow;
+	    word_has_equals = 1;
+	    *ap++ = '=';
+	    break;
+
+	  case '\\':
+	    /* Backslash-newline has special case handling, ref POSIX.
+               We're in the fastpath, so emulate what the shell would do.  */
+	    if (p[1] == '\n')
+	      {
+		/* Throw out the backslash and newline.  */
+                ++p;
+
+		/* If there is a command prefix after a backslash-newline,
+		   remove it.  */
+		if (p[1] == cmd_prefix)
+                  ++p;
+
+                /* If there's nothing in this argument yet, skip any
+                   whitespace before the start of the next word.  */
+                if (ap == new_argv[i])
+                  p = next_token (p + 1) - 1;
+	      }
+	    else if (p[1] != '\0')
+              {
+#ifdef HAVE_DOS_PATHS
+                /* Only remove backslashes before characters special to Unixy
+                   shells.  All other backslashes are copied verbatim, since
+                   they are probably DOS-style directory separators.  This
+                   still leaves a small window for problems, but at least it
+                   should work for the vast majority of naive users.  */
+
+#ifdef __MSDOS__
+                /* A dot is only special as part of the "..."
+                   wildcard.  */
+                if (strneq (p + 1, ".\\.\\.", 5))
+                  {
+                    *ap++ = '.';
+                    *ap++ = '.';
+                    p += 4;
+                  }
+                else
+#endif
+                  if (p[1] != '\\' && p[1] != '\''
+                      && !isspace ((unsigned char)p[1])
+# ifdef KMK
+                      && strchr (sh_chars, p[1]) == 0 
+                      && (p[1] != '"' || !unixy_shell))
+# else
+                      && strchr (sh_chars_sh, p[1]) == 0)
+# endif 
+                    /* back up one notch, to copy the backslash */
+                    --p;
+#endif  /* HAVE_DOS_PATHS */
+
+                /* Copy and skip the following char.  */
+                *ap++ = *++p;
+              }
+	    break;
+
+	  case '\'':
+	  case '"':
+	    instring = *p;
+	    break;
+
+	  case '\n':
+	    if (restp != NULL)
+	      {
+		/* End of the command line.  */
+		*restp = p;
+		goto end_of_line;
+	      }
+	    else
+	      /* Newlines are not special.  */
+	      *ap++ = '\n';
+	    break;
+
+	  case ' ':
+	  case '\t':
+	    /* We have the end of an argument.
+	       Terminate the text of the argument.  */
+	    *ap++ = '\0';
+	    new_argv[++i] = ap;
+	    last_argument_was_empty = 0;
+
+	    /* Update SEEN_NONEQUALS, which tells us if every word
+	       heretofore has contained an `='.  */
+	    seen_nonequals |= ! word_has_equals;
+	    if (word_has_equals && ! seen_nonequals)
+	      /* An `=' in a word before the first
+		 word without one is magical.  */
+	      goto slow;
+	    word_has_equals = 0; /* Prepare for the next word.  */
+
+	    /* If this argument is the command name,
+	       see if it is a built-in shell command.
+	       If so, have the shell handle it.  */
+	    if (i == 1)
+	      {
+		register int j;
+		for (j = 0; sh_cmds[j] != 0; ++j)
+                  {
+                    if (streq (sh_cmds[j], new_argv[0]))
+                      goto slow;
+# ifdef __EMX__
+                    /* Non-Unix shells are case insensitive.  */
+                    if (!unixy_shell
+                        && strcasecmp (sh_cmds[j], new_argv[0]) == 0)
+                      goto slow;
+# endif
+                  }
+	      }
+
+	    /* Ignore multiple whitespace chars.  */
+	    p = next_token (p) - 1;
+	    break;
+
+	  default:
+	    *ap++ = *p;
+	    break;
+	  }
+    }
+ end_of_line:
+
+  if (instring)
+    /* Let the shell deal with an unterminated quote.  */
+    goto slow;
+
+  /* Terminate the last argument and the argument list.  */
+
+  *ap = '\0';
+  if (new_argv[i][0] != '\0' || last_argument_was_empty)
+    ++i;
+  new_argv[i] = 0;
+
+  if (i == 1)
+    {
+      register int j;
+      for (j = 0; sh_cmds[j] != 0; ++j)
+	if (streq (sh_cmds[j], new_argv[0]))
+	  goto slow;
+    }
+
+  if (new_argv[0] == 0)
+    {
+      /* Line was empty.  */
+      free (argstr);
+      free (new_argv);
+      return 0;
+    }
+
+  return new_argv;
+
+ slow:;
+  /* We must use the shell.  */
+
+  if (new_argv != 0)
+    {
+      /* Free the old argument list we were working on.  */
+      free (argstr);
+      free (new_argv);
+    }
+
+#ifdef __MSDOS__
+  execute_by_shell = 1;	/* actually, call `system' if shell isn't unixy */
+#endif
+
+#ifdef _AMIGA
+  {
+    char *ptr;
+    char *buffer;
+    char *dptr;
+
+    buffer = xmalloc (strlen (line)+1);
+
+    ptr = line;
+    for (dptr=buffer; *ptr; )
+    {
+      if (*ptr == '\\' && ptr[1] == '\n')
+	ptr += 2;
+      else if (*ptr == '@') /* Kludge: multiline commands */
+      {
+	ptr += 2;
+	*dptr++ = '\n';
+      }
+      else
+	*dptr++ = *ptr++;
+    }
+    *dptr = 0;
+
+    new_argv = xmalloc (2 * sizeof (char *));
+    new_argv[0] = buffer;
+    new_argv[1] = 0;
+  }
+#else	/* Not Amiga  */
+#ifdef WINDOWS32
+  /*
+   * Not eating this whitespace caused things like
+   *
+   *    sh -c "\n"
+   *
+   * which gave the shell fits. I think we have to eat
+   * whitespace here, but this code should be considered
+   * suspicious if things start failing....
+   */
+
+  /* Make sure not to bother processing an empty line.  */
+  while (isspace ((unsigned char)*line))
+    ++line;
+  if (*line == '\0')
+    return 0;
+#endif /* WINDOWS32 */
+  {
+    /* SHELL may be a multi-word command.  Construct a command line
+       "SHELL -c LINE", with all special chars in LINE escaped.
+       Then recurse, expanding this command line to get the final
+       argument list.  */
+
+    unsigned int shell_len = strlen (shell);
+#ifndef VMS
+    static char minus_c[] = " -c ";
+#else
+    static char minus_c[] = "";
+#endif
+    unsigned int line_len = strlen (line);
+
+    char *new_line = alloca (shell_len + (sizeof (minus_c)-1)
+                             + (line_len*2) + 1);
+    char *command_ptr = NULL; /* used for batch_mode_shell mode */
+
+# ifdef __EMX__ /* is this necessary? */
+    if (!unixy_shell)
+      minus_c[1] = '/'; /* " /c " */
+# endif
+
+    ap = new_line;
+    memcpy (ap, shell, shell_len);
+    ap += shell_len;
+    memcpy (ap, minus_c, sizeof (minus_c) - 1);
+    ap += sizeof (minus_c) - 1;
+    command_ptr = ap;
+    for (p = line; *p != '\0'; ++p)
+      {
+	if (restp != NULL && *p == '\n')
+	  {
+	    *restp = p;
+	    break;
+	  }
+	else if (*p == '\\' && p[1] == '\n')
+	  {
+	    /* POSIX says we keep the backslash-newline, but throw out
+               the next char if it's a TAB.  If we don't have a POSIX
+               shell on DOS/Windows/OS2, mimic the pre-POSIX behavior
+               and remove the backslash/newline.  */
+#if defined (__MSDOS__) || defined (__EMX__) || defined (WINDOWS32)
+# define PRESERVE_BSNL  unixy_shell
+#else
+# define PRESERVE_BSNL  1
+#endif
+	    if (PRESERVE_BSNL)
+	      {
+		*(ap++) = '\\';
+#ifdef KMK /* see test in Makefile.kmk, required on windows. */
+                if (!batch_mode_shell)
+#endif
+		*(ap++) = '\\';
+		*(ap++) = '\n';
+	      }
+
+	    ++p;
+	    if (p[1] == cmd_prefix)
+	      ++p;
+
+	    continue;
+	  }
+
+        /* DOS shells don't know about backslash-escaping.  */
+	if (unixy_shell && !batch_mode_shell &&
+            (*p == '\\' || *p == '\'' || *p == '"'
+             || isspace ((unsigned char)*p)
+             || strchr (sh_chars, *p) != 0))
+	  *ap++ = '\\';
+#ifdef __MSDOS__
+        else if (unixy_shell && strneq (p, "...", 3))
+          {
+            /* The case of `...' wildcard again.  */
+            strcpy (ap, "\\.\\.\\");
+            ap += 5;
+            p  += 2;
+          }
+#endif
+	*ap++ = *p;
+      }
+    if (ap == new_line + shell_len + sizeof (minus_c) - 1)
+      /* Line was empty.  */
+      return 0;
+    *ap = '\0';
+
+#ifdef WINDOWS32
+    /* Some shells do not work well when invoked as 'sh -c xxx' to run a
+       command line (e.g. Cygnus GNUWIN32 sh.exe on WIN32 systems).  In these
+       cases, run commands via a script file.  */
+    if (just_print_flag) {
+      /* Need to allocate new_argv, although it's unused, because
+        start_job_command will want to free it and its 0'th element.  */
+      new_argv = xmalloc(2 * sizeof (char *));
+      new_argv[0] = xstrdup ("");
+      new_argv[1] = NULL;
+    } else if ((no_default_sh_exe || batch_mode_shell) && batch_filename_ptr) {
+      int temp_fd;
+      FILE* batch = NULL;
+      int id = GetCurrentProcessId();
+      PATH_VAR(fbuf);
+
+      /* create a file name */
+      sprintf(fbuf, "make%d", id);
+      *batch_filename_ptr = create_batch_file (fbuf, unixy_shell, &temp_fd);
+
+# ifdef KMK
+      DB (DB_JOBS, (_("Creating temporary batch file %s\nCommand: %s\n"),
+                    *batch_filename_ptr, command_ptr));
+# else  /* !KMK */
+      DB (DB_JOBS, (_("Creating temporary batch file %s\n"),
+                    *batch_filename_ptr));
+# endif /* !KMK */
+
+      /* Create a FILE object for the batch file, and write to it the
+	 commands to be executed.  Put the batch file in TEXT mode.  */
+      _setmode (temp_fd, _O_TEXT);
+      batch = _fdopen (temp_fd, "wt");
+      if (!unixy_shell)
+        fputs ("@echo off\n", batch);
+      fputs (command_ptr, batch);
+      fputc ('\n', batch);
+      fclose (batch);
+
+      /* create argv */
+      new_argv = xmalloc(3 * sizeof (char *));
+      if (unixy_shell) {
+        new_argv[0] = xstrdup (shell);
+        new_argv[1] = *batch_filename_ptr; /* only argv[0] gets freed later */
+      } else {
+        new_argv[0] = xstrdup (*batch_filename_ptr);
+        new_argv[1] = NULL;
+      }
+      new_argv[2] = NULL;
+    } else
+#endif /* WINDOWS32 */
+    if (unixy_shell)
+      new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0);
+#ifdef __EMX__
+    else if (!unixy_shell)
+      {
+	/* new_line is local, must not be freed therefore
+           We use line here instead of new_line because we run the shell
+           manually.  */
+        size_t line_len = strlen (line);
+        char *p = new_line;
+        char *q = new_line;
+        memcpy (new_line, line, line_len + 1);
+        /* replace all backslash-newline combination and also following tabs */
+        while (*q != '\0')
+          {
+            if (q[0] == '\\' && q[1] == '\n')
+              {
+                q += 2; /* remove '\\' and '\n' */
+		/* Remove any command prefix in the next line */
+                if (q[0] == cmd_prefix)
+                  q++;
+              }
+            else
+              *p++ = *q++;
+          }
+        *p = '\0';
+
+# ifndef NO_CMD_DEFAULT
+        if (strnicmp (new_line, "echo", 4) == 0
+            && (new_line[4] == ' ' || new_line[4] == '\t'))
+          {
+            /* the builtin echo command: handle it separately */
+            size_t echo_len = line_len - 5;
+            char *echo_line = new_line + 5;
+
+            /* special case: echo 'x="y"'
+               cmd works this way: a string is printed as is, i.e., no quotes
+               are removed. But autoconf uses a command like echo 'x="y"' to
+               determine whether make works. autoconf expects the output x="y"
+               so we will do exactly that.
+               Note: if we do not allow cmd to be the default shell
+               we do not need this kind of voodoo */
+            if (echo_line[0] == '\''
+                && echo_line[echo_len - 1] == '\''
+                && strncmp (echo_line + 1, "ac_maketemp=",
+                            strlen ("ac_maketemp=")) == 0)
+              {
+                /* remove the enclosing quotes */
+                memmove (echo_line, echo_line + 1, echo_len - 2);
+                echo_line[echo_len - 2] = '\0';
+              }
+          }
+# endif
+
+        {
+          /* Let the shell decide what to do. Put the command line into the
+             2nd command line argument and hope for the best ;-)  */
+          size_t sh_len = strlen (shell);
+
+          /* exactly 3 arguments + NULL */
+          new_argv = xmalloc (4 * sizeof (char *));
+          /* Exactly strlen(shell) + strlen("/c") + strlen(line) + 3 times
+             the trailing '\0' */
+          new_argv[0] = xmalloc (sh_len + line_len + 5);
+          memcpy (new_argv[0], shell, sh_len + 1);
+          new_argv[1] = new_argv[0] + sh_len + 1;
+          memcpy (new_argv[1], "/c", 3);
+          new_argv[2] = new_argv[1] + 3;
+          memcpy (new_argv[2], new_line, line_len + 1);
+          new_argv[3] = NULL;
+        }
+      }
+#elif defined(__MSDOS__)
+    else
+      {
+        /* With MSDOS shells, we must construct the command line here
+           instead of recursively calling ourselves, because we
+           cannot backslash-escape the special characters (see above).  */
+        new_argv = xmalloc (sizeof (char *));
+        line_len = strlen (new_line) - shell_len - sizeof (minus_c) + 1;
+        new_argv[0] = xmalloc (line_len + 1);
+        strncpy (new_argv[0],
+                 new_line + shell_len + sizeof (minus_c) - 1, line_len);
+        new_argv[0][line_len] = '\0';
+      }
+#else
+    else
+      fatal (NILF, _("%s (line %d) Bad shell context (!unixy && !batch_mode_shell)\n"),
+            __FILE__, __LINE__);
+#endif
+  }
+#endif	/* ! AMIGA */
+
+  return new_argv;
+}
+#endif /* !VMS */
+
+/* Figure out the argument list necessary to run LINE as a command.  Try to
+   avoid using a shell.  This routine handles only ' quoting, and " quoting
+   when no backslash, $ or ` characters are seen in the quotes.  Starting
+   quotes may be escaped with a backslash.  If any of the characters in
+   sh_chars[] is seen, or any of the builtin commands listed in sh_cmds[]
+   is the first word of a line, the shell is used.
+
+   If RESTP is not NULL, *RESTP is set to point to the first newline in LINE.
+   If *RESTP is NULL, newlines will be ignored.
+
+   FILE is the target whose commands these are.  It is used for
+   variable expansion for $(SHELL) and $(IFS).  */
+
+char **
+construct_command_argv (char *line, char **restp, struct file *file,
+                        char **batch_filename_ptr)
+{
+  char *shell, *ifs;
+  char **argv;
+
+#ifdef VMS
+  char *cptr;
+  int argc;
+
+  argc = 0;
+  cptr = line;
+  for (;;)
+    {
+      while ((*cptr != 0)
+	     && (isspace ((unsigned char)*cptr)))
+	cptr++;
+      if (*cptr == 0)
+	break;
+      while ((*cptr != 0)
+	     && (!isspace((unsigned char)*cptr)))
+	cptr++;
+      argc++;
+    }
+
+  argv = xmalloc (argc * sizeof (char *));
+  if (argv == 0)
+    abort ();
+
+  cptr = line;
+  argc = 0;
+  for (;;)
+    {
+      while ((*cptr != 0)
+	     && (isspace ((unsigned char)*cptr)))
+	cptr++;
+      if (*cptr == 0)
+	break;
+      DB (DB_JOBS, ("argv[%d] = [%s]\n", argc, cptr));
+      argv[argc++] = cptr;
+      while ((*cptr != 0)
+	     && (!isspace((unsigned char)*cptr)))
+	cptr++;
+      if (*cptr != 0)
+	*cptr++ = 0;
+    }
+#else
+  {
+    /* Turn off --warn-undefined-variables while we expand SHELL and IFS.  */
+    int save = warn_undefined_variables_flag;
+    warn_undefined_variables_flag = 0;
+
+    shell = allocated_variable_expand_for_file ("$(SHELL)", file);
+#ifdef WINDOWS32
+    /*
+     * Convert to forward slashes so that construct_command_argv_internal()
+     * is not confused.
+     */
+    if (shell) {
+      char *p = w32ify (shell, 0);
+      strcpy (shell, p);
+    }
+#endif
+#ifdef __EMX__
+    {
+      static const char *unixroot = NULL;
+      static const char *last_shell = "";
+      static int init = 0;
+      if (init == 0)
+	{
+	  unixroot = getenv ("UNIXROOT");
+	  /* unixroot must be NULL or not empty */
+	  if (unixroot && unixroot[0] == '\0') unixroot = NULL;
+	  init = 1;
+	}
+
+      /* if we have an unixroot drive and if shell is not default_shell
+         (which means it's either cmd.exe or the test has already been
+         performed) and if shell is an absolute path without drive letter,
+         try whether it exists e.g.: if "/bin/sh" does not exist use
+         "$UNIXROOT/bin/sh" instead.  */
+      if (unixroot && shell && strcmp (shell, last_shell) != 0
+	  && (shell[0] == '/' || shell[0] == '\\'))
+	{
+	  /* trying a new shell, check whether it exists */
+	  size_t size = strlen (shell);
+	  char *buf = xmalloc (size + 7);
+	  memcpy (buf, shell, size);
+	  memcpy (buf + size, ".exe", 5); /* including the trailing '\0' */
+          if (access (shell, F_OK) != 0 && access (buf, F_OK) != 0)
+	    {
+	      /* try the same for the unixroot drive */
+	      memmove (buf + 2, buf, size + 5);
+	      buf[0] = unixroot[0];
+	      buf[1] = unixroot[1];
+	      if (access (buf, F_OK) == 0)
+		/* we have found a shell! */
+		/* free(shell); */
+		shell = buf;
+	      else
+		free (buf);
+	    }
+	  else
+            free (buf);
+	}
+    }
+#endif /* __EMX__ */
+
+    ifs = allocated_variable_expand_for_file ("$(IFS)", file);
+
+    warn_undefined_variables_flag = save;
+  }
+
+#ifdef CONFIG_WITH_KMK_BUILTIN
+  /* If it's a kmk_builtin command, make sure we're treated like a
+     unix shell and and don't get batch files. */
+  if (   (  !unixy_shell
+          || batch_mode_shell
+# ifdef WINDOWS32
+          || no_default_sh_exe
+# endif
+         )
+      && line
+      && !strncmp(line, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
+  {
+    int saved_batch_mode_shell = batch_mode_shell;
+    int saved_unixy_shell = unixy_shell;
+# ifdef WINDOWS32
+    int saved_no_default_sh_exe = no_default_sh_exe;
+    no_default_sh_exe = 0;
+# endif
+    unixy_shell = 1;
+    batch_mode_shell = 0;
+    argv = construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr);
+    batch_mode_shell = saved_batch_mode_shell;
+    unixy_shell = saved_unixy_shell;
+# ifdef WINDOWS32
+    no_default_sh_exe = saved_no_default_sh_exe;
+# endif
+  }
+  else
+#endif /* CONFIG_WITH_KMK_BUILTIN */
+  argv = construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr);
+
+  free (shell);
+  free (ifs);
+#endif /* !VMS */
+  return argv;
+}
+
+
+#if !defined(HAVE_DUP2) && !defined(_AMIGA)
+int
+dup2 (int old, int new)
+{
+  int fd;
+
+  (void) close (new);
+  fd = dup (old);
+  if (fd != new)
+    {
+      (void) close (fd);
+      errno = EMFILE;
+      return -1;
+    }
+
+  return fd;
+}
+#endif /* !HAPE_DUP2 && !_AMIGA */
+
+/* On VMS systems, include special VMS functions.  */
+
+#ifdef VMS
+#include "vmsjobs.c"
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/job.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/job.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/job.h	(revision 1780)
@@ -0,0 +1,109 @@
+/* Definitions for managing subprocesses in GNU Make.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef SEEN_JOB_H
+#define SEEN_JOB_H
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#else
+# include <sys/file.h>
+#endif
+
+/* How to set close-on-exec for a file descriptor.  */
+
+#if !defined F_SETFD
+# define CLOSE_ON_EXEC(_d)
+#else
+# ifndef FD_CLOEXEC
+#  define FD_CLOEXEC 1
+# endif
+# define CLOSE_ON_EXEC(_d) (void) fcntl ((_d), F_SETFD, FD_CLOEXEC)
+#endif
+
+/* Structure describing a running or dead child process.  */
+
+struct child
+  {
+    struct child *next;		/* Link in the chain.  */
+
+    struct file *file;		/* File being remade.  */
+
+    char **environment;		/* Environment for commands.  */
+
+    char **command_lines;	/* Array of variable-expanded cmd lines.  */
+    unsigned int command_line;	/* Index into above.  */
+    char *command_ptr;		/* Ptr into command_lines[command_line].  */
+
+    pid_t pid;			/* Child process's ID number.  */
+#ifdef VMS
+    int efn;			/* Completion event flag number */
+    int cstatus;		/* Completion status */
+#endif
+    char *sh_batch_file;        /* Script file for shell commands */
+#ifdef CONFIG_WITH_KMK_BUILTIN
+    int status;                 /* Status of the job. */
+    unsigned int has_status:1;  /* Nonzero if status is available. */
+#endif
+    unsigned int remote:1;	/* Nonzero if executing remotely.  */
+
+    unsigned int noerror:1;	/* Nonzero if commands contained a `-'.  */
+
+    unsigned int good_stdin:1;	/* Nonzero if this child has a good stdin.  */
+    unsigned int deleted:1;	/* Nonzero if targets have been deleted.  */
+    unsigned int dontcare:1;    /* Saved dontcare flag.  */
+  };
+
+extern struct child *children;
+
+void new_job (struct file *file);
+void reap_children (int block, int err);
+void start_waiting_jobs (void);
+
+char **construct_command_argv (char *line, char **restp, struct file *file, char** batch_file);
+#ifdef VMS
+int child_execute_job (char *argv, struct child *child);
+#elif defined(__EMX__)
+int child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp);
+#else
+void child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp);
+#endif
+#ifdef _AMIGA
+void exec_command (char **argv);
+#elif defined(__EMX__)
+int exec_command (char **argv, char **envp);
+#else
+void exec_command (char **argv, char **envp);
+#endif
+
+extern unsigned int job_slots_used;
+
+void block_sigs (void);
+#ifdef POSIX
+void unblock_sigs (void);
+#else
+#ifdef	HAVE_SIGSETMASK
+extern int fatal_signal_mask;
+#define	unblock_sigs()	sigsetmask (0)
+#else
+#define	unblock_sigs()
+#endif
+#endif
+
+extern unsigned int jobserver_tokens;
+
+#endif /* SEEN_JOB_H */
Index: /tags/kBuild-0.1.4/src/kmk/kbuild.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kbuild.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kbuild.c	(revision 1780)
@@ -0,0 +1,1843 @@
+/* $Id$ */
+/** @file
+ *
+ * kBuild specific make functionality.
+ *
+ * Copyright (c) 2006-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/* No GNU coding style here! */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "make.h"
+#include "filedef.h"
+#include "variable.h"
+#include "dep.h"
+#include "debug.h"
+#ifdef WINDOWS32
+# include "pathstuff.h"
+# include <Windows.h>
+#endif
+#if defined(__APPLE__)
+# include <mach-o/dyld.h>
+#endif
+
+#include "kbuild.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#ifndef va_copy
+# define va_copy(dst, src) do {(dst) = (src);} while (0)
+#endif
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The argv[0] passed to main. */
+static const char *g_pszExeName;
+/** The initial working directory. */
+static char *g_pszInitialCwd;
+
+
+/**
+ * Initialize kBuild stuff.
+ *
+ * @param   argc    Number of arguments to main().
+ * @param   argv    The main() argument vector.
+ */
+void init_kbuild(int argc, char **argv)
+{
+    int rc;
+    PATH_VAR(szTmp);
+
+    /*
+     * Get the initial cwd for use in my_abspath.
+     */
+#ifdef WINDOWS32
+    if (getcwd_fs(szTmp, GET_PATH_MAX) != 0)
+#else
+    if (getcwd(szTmp, GET_PATH_MAX) != 0)
+#endif
+        g_pszInitialCwd = xstrdup(szTmp);
+    else
+        fatal(NILF, _("getcwd failed"));
+
+    /*
+     * Determin the executable name.
+     */
+    rc = -1;
+#if defined(__APPLE__)
+    {
+        const char *pszImageName = _dyld_get_image_name(0);
+        if (pszImageName)
+        {
+            size_t cchImageName = strlen(pszImageName);
+            if (cchImageName < GET_PATH_MAX)
+            {
+                memcpy(szTmp, pszImageName, cchImageName + 1);
+                rc = 0;
+            }
+        }
+    }
+
+#elif defined(__FreeBSD__)
+    rc = readlink("/proc/curproc/file", szTmp, GET_PATH_MAX - 1);
+    if (rc < 0 || rc == GET_PATH_MAX - 1)
+        rc = -1;
+    else
+        szTmp[rc] = '\0';
+
+#elif defined(__gnu_linux__) /** @todo find proper define... */
+    rc = readlink("/proc/self/exe", szTmp, GET_PATH_MAX - 1);
+    if (rc < 0 || rc == GET_PATH_MAX - 1)
+        rc = -1;
+    else
+        szTmp[rc] = '\0';
+
+#elif defined(__OS2__)
+    _execname(szTmp, GET_PATH_MAX);
+    rc = 0;
+
+#elif defined(__sun__)
+    {
+        char szTmp2[64];
+        snprintf(szTmp2, sizeof(szTmp2), "/proc/%d/path/a.out", getpid());
+        rc = readlink(szTmp2, szTmp, GET_PATH_MAX - 1);
+        if (rc < 0 || rc == GET_PATH_MAX - 1)
+            rc = -1;
+        else
+            szTmp[rc] = '\0';
+    }
+
+#elif defined(WINDOWS32)
+    if (GetModuleFileName(GetModuleHandle(NULL), szTmp, GET_PATH_MAX))
+        rc = 0;
+
+#endif
+
+#if !defined(__OS2__) && !defined(WINDOWS32)
+    /* fallback, try use the path to locate the binary. */
+    if (   rc < 0
+        && access(argv[0], X_OK))
+    {
+        size_t cchArgv0 = strlen(argv[0]);
+        const char *pszPath = getenv("PATH");
+        char *pszCopy = xstrdup(pszPath ? pszPath : ".");
+        char *psz = pszCopy;
+        while (*psz)
+        {
+            size_t cch;
+            char *pszEnd = strchr(psz, PATH_SEPARATOR_CHAR);
+            if (!pszEnd)
+                pszEnd = strchr(psz, '\0');
+            cch = pszEnd - psz;
+            if (cch + cchArgv0 + 2 <= GET_PATH_MAX)
+            {
+                memcpy(szTmp, psz, cch);
+                szTmp[cch] = '/';
+                memcpy(&szTmp[cch + 1], argv[0], cchArgv0 + 1);
+                if (!access(szTmp, X_OK))
+                {
+                    rc = 0;
+                    break;
+                }
+            }
+
+            /* next */
+            psz = pszEnd;
+            while (*psz == PATH_SEPARATOR_CHAR)
+               psz++;
+        }
+        free(pszCopy);
+    }
+#endif
+
+    if (rc < 0)
+        g_pszExeName = argv[0];
+    else
+        g_pszExeName = xstrdup(szTmp);
+
+    (void)argc;
+}
+
+
+/**
+ * Wrapper that ensures correct starting_directory.
+ */
+static char *my_abspath(const char *pszIn, char *pszOut)
+{
+    char *pszSaved, *pszRet;
+
+    pszSaved = starting_directory;
+    starting_directory = g_pszInitialCwd;
+    pszRet = abspath(pszIn, pszOut);
+    starting_directory = pszSaved;
+
+    return pszRet;
+}
+
+
+/**
+ * Determin the KBUILD_PATH value.
+ *
+ * @returns Pointer to static a buffer containing the value (consider it read-only).
+ */
+const char *get_kbuild_path(void)
+{
+    static const char *s_pszPath = NULL;
+    if (!s_pszPath)
+    {
+        PATH_VAR(szTmpPath);
+        const char *pszEnvVar = getenv("KBUILD_PATH");
+        if (    !pszEnvVar
+            ||  !my_abspath(pszEnvVar, szTmpPath))
+        {
+            const char *pszEnvVar = getenv("PATH_KBUILD");
+            if (    !pszEnvVar
+                ||  !my_abspath(pszEnvVar, szTmpPath))
+            {
+#ifdef KBUILD_PATH
+                return s_pszPath = KBUILD_PATH;
+#else
+                /* $(abspath $(KBUILD_BIN_PATH)/../..)*/
+                size_t cch = strlen(get_kbuild_bin_path());
+                char *pszTmp2 = alloca(cch + sizeof("/../.."));
+                strcat(strcpy(pszTmp2, get_kbuild_bin_path()), "/../..");
+                if (!my_abspath(pszTmp2, szTmpPath))
+                    fatal(NILF, _("failed to determin KBUILD_PATH"));
+#endif
+            }
+        }
+        s_pszPath = xstrdup(szTmpPath);
+    }
+    return s_pszPath;
+}
+
+
+/**
+ * Determin the KBUILD_BIN_PATH value.
+ *
+ * @returns Pointer to static a buffer containing the value (consider it read-only).
+ */
+const char *get_kbuild_bin_path(void)
+{
+    static const char *s_pszPath = NULL;
+    if (!s_pszPath)
+    {
+        PATH_VAR(szTmpPath);
+
+        const char *pszEnvVar = getenv("KBUILD_BIN_PATH");
+        if (    !pszEnvVar
+            ||  !my_abspath(pszEnvVar, szTmpPath))
+        {
+            const char *pszEnvVar = getenv("PATH_KBUILD_BIN");
+            if (    !pszEnvVar
+                ||  !my_abspath(pszEnvVar, szTmpPath))
+            {
+#ifdef KBUILD_PATH
+                return s_pszPath = KBUILD_BIN_PATH;
+#else
+                /* $(abspath $(dir $(ARGV0)).) */
+                size_t cch = strlen(g_pszExeName);
+                char *pszTmp2 = alloca(cch + sizeof("."));
+                char *pszSep = pszTmp2 + cch - 1;
+                memcpy(pszTmp2, g_pszExeName, cch);
+# ifdef HAVE_DOS_PATHS
+                while (pszSep >= pszTmp2 && *pszSep != '/' && *pszSep != '\\' && *pszSep != ':')
+# else
+                while (pszSep >= pszTmp2 && *pszSep != '/')
+# endif
+                    pszSep--;
+                if (pszSep >= pszTmp2)
+                  strcpy(pszSep + 1, ".");
+                else
+                  strcpy(pszTmp2, ".");
+
+                if (!my_abspath(pszTmp2, szTmpPath))
+                    fatal(NILF, _("failed to determin KBUILD_BIN_PATH (pszTmp2=%s szTmpPath=%s)"), pszTmp2, szTmpPath);
+#endif /* !KBUILD_PATH */
+            }
+        }
+        s_pszPath = xstrdup(szTmpPath);
+    }
+    return s_pszPath;
+}
+
+
+/**
+ * Determin the location of default kBuild shell.
+ *
+ * @returns Pointer to static a buffer containing the location (consider it read-only).
+ */
+const char *get_default_kbuild_shell(void)
+{
+    static char *s_pszDefaultShell = NULL;
+    if (!s_pszDefaultShell)
+    {
+#if defined(__OS2__) || defined(_WIN32) || defined(WINDOWS32)
+        static const char s_szShellName[] = "/kmk_ash.exe";
+#else
+        static const char s_szShellName[] = "/kmk_ash";
+#endif
+        const char *pszBin = get_kbuild_bin_path();
+        size_t cchBin = strlen(pszBin);
+        s_pszDefaultShell = xmalloc(cchBin + sizeof(s_szShellName));
+        memcpy(s_pszDefaultShell, pszBin, cchBin);
+        memcpy(&s_pszDefaultShell[cchBin], s_szShellName, sizeof(s_szShellName));
+    }
+    return s_pszDefaultShell;
+}
+
+#ifdef KMK_HELPERS
+
+/**
+ * Applies the specified default path to any relative paths in *ppsz.
+ *
+ * @param   pDefPath        The default path.
+ * @param   ppsz            Pointer to the string pointer. If we expand anything, *ppsz
+ *                          will be replaced and the caller is responsible for calling free() on it.
+ * @param   pcch            IN: *pcch contains the current string length.
+ *                          OUT: *pcch contains the new string length.
+ * @param   pcchAlloc       *pcchAlloc contains the length allocated for the string. Can be NULL.
+ * @param   fCanFree        Whether *ppsz should be freed when we replace it.
+ */
+static void
+kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, int *pcch, int *pcchAlloc, int fCanFree)
+{
+    const char *pszIterator;
+    const char *pszInCur;
+    unsigned int cchInCur;
+    unsigned int cRelativePaths;
+
+    /*
+     * The first pass, count the relative paths.
+     */
+    cRelativePaths = 0;
+    pszIterator = *ppsz;
+    while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
+    {
+        /* is relative? */
+#ifdef HAVE_DOS_PATHS
+        if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':'))
+#else
+        if (pszInCur[0] != '/')
+#endif
+            cRelativePaths++;
+    }
+
+    /*
+     * The second pass construct the new string.
+     */
+    if (cRelativePaths)
+    {
+        const size_t cchOut = *pcch + cRelativePaths * (pDefPath->value_length + 1) + 1;
+        char *pszOut = xmalloc(cchOut);
+        char *pszOutCur = pszOut;
+        const char *pszInNextCopy = *ppsz;
+
+        cRelativePaths = 0;
+        pszIterator = *ppsz;
+        while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
+        {
+            /* is relative? */
+#ifdef HAVE_DOS_PATHS
+            if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':'))
+#else
+            if (pszInCur[0] != '/')
+#endif
+            {
+                PATH_VAR(szAbsPathIn);
+                PATH_VAR(szAbsPathOut);
+
+                if (pDefPath->value_length + cchInCur + 1 >= GET_PATH_MAX)
+                    continue;
+
+                /* Create the abspath input. */
+                memcpy(szAbsPathIn, pDefPath->value, pDefPath->value_length);
+                szAbsPathIn[pDefPath->value_length] = '/';
+                memcpy(&szAbsPathIn[pDefPath->value_length + 1], pszInCur, cchInCur);
+                szAbsPathIn[pDefPath->value_length + 1 + cchInCur] = '\0';
+
+                if (abspath(szAbsPathIn, szAbsPathOut) != NULL)
+                {
+                    const size_t cchAbsPathOut = strlen(szAbsPathOut);
+                    assert(cchAbsPathOut <= pDefPath->value_length + 1 + cchInCur);
+
+                    /* copy leading input */
+                    if (pszInCur != pszInNextCopy)
+                    {
+                        const size_t cchCopy = pszInCur - pszInNextCopy;
+                        memcpy(pszOutCur, pszInNextCopy, cchCopy);
+                        pszOutCur += cchCopy;
+                    }
+                    pszInNextCopy = pszInCur + cchInCur;
+
+                    /* copy out the abspath. */
+                    memcpy(pszOutCur, szAbsPathOut, cchAbsPathOut);
+                    pszOutCur += cchAbsPathOut;
+                }
+            }
+        }
+        /* the final copy (includes the nil). */
+        cchInCur = *ppsz + *pcch - pszInNextCopy;
+        memcpy(pszOutCur, pszInNextCopy, cchInCur);
+        pszOutCur += cchInCur;
+        *pszOutCur = '\0';
+        assert((size_t)(pszOutCur - pszOut) < cchOut);
+
+        /* set return values */
+        if (fCanFree)
+            free(*ppsz);
+        *ppsz = pszOut;
+        *pcch = pszOutCur - pszOut;
+        if (pcchAlloc)
+            *pcchAlloc = cchOut;
+    }
+}
+
+
+/**
+ * Gets a variable that must exist.
+ * Will cause a fatal failure if the variable doesn't exist.
+ *
+ * @returns Pointer to the variable.
+ * @param   pszName     The variable name.
+ */
+static struct variable *
+kbuild_get_variable(const char *pszName)
+{
+#ifndef NDEBUG
+    int i;
+#endif
+    struct variable *pVar = lookup_variable(pszName, strlen(pszName));
+    if (!pVar)
+        fatal(NILF, _("variable `%s' isn't defined!"), pszName);
+    if (pVar->recursive)
+        fatal(NILF, _("variable `%s' is defined as `recursive' instead of `simple'!"), pszName);
+#ifndef NDEBUG
+    i = strlen(pVar->value);
+    if (i != pVar->value_length)
+    {
+        printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
+# ifdef _MSC_VER
+        __debugbreak();
+# endif
+        assert(0);
+    }
+#endif
+    return pVar;
+}
+
+
+/**
+ * Gets a variable that must exist and can be recursive.
+ * Will cause a fatal failure if the variable doesn't exist.
+ *
+ * @returns Pointer to the variable.
+ * @param   pszName     The variable name.
+ */
+static struct variable *
+kbuild_get_recursive_variable(const char *pszName)
+{
+#ifndef NDEBUG
+    int i;
+#endif
+    struct variable *pVar = lookup_variable(pszName, strlen(pszName));
+    if (!pVar)
+        fatal(NILF, _("variable `%s' isn't defined!"), pszName);
+#ifndef NDEBUG
+    i = strlen(pVar->value);
+    if (i != pVar->value_length)
+    {
+        printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
+# ifdef _MSC_VER
+        __debugbreak();
+# endif
+        assert(0);
+    }
+#endif
+    return pVar;
+}
+
+
+/**
+ * Gets a variable that doesn't have to exit, but if it does can be recursive.
+ *
+ * @returns Pointer to the variable.
+ *          NULL if not found.
+ * @param   pszName     The variable name.
+ */
+static struct variable *
+kbuild_query_recursive_variable(const char *pszName)
+{
+#ifndef NDEBUG
+    int i;
+#endif
+    struct variable *pVar = lookup_variable(pszName, strlen(pszName));
+    if (pVar)
+    {
+#ifndef NDEBUG
+        i = strlen(pVar->value);
+        if (i != pVar->value_length)
+        {
+            printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
+# ifdef _MSC_VER
+            __debugbreak();
+# endif
+            assert(0);
+        }
+#endif
+    }
+    return pVar;
+}
+
+
+/**
+ * Converts the specified variable into a 'simple' one.
+ * @returns pVar.
+ * @param   pVar        The variable.
+ */
+static struct variable *
+kbuild_simplify_variable(struct variable *pVar)
+{
+    if (memchr(pVar->value, '$', pVar->value_length))
+    {
+        char *pszExpanded = allocated_variable_expand(pVar->value);
+        free(pVar->value);
+        pVar->value = pszExpanded;
+        pVar->value_length = strlen(pVar->value);
+        pVar->value_alloc_len = pVar->value_length + 1;
+    }
+    pVar->recursive = 0;
+    return pVar;
+}
+
+
+/**
+ * Looks up a variable.
+ * The value_length field is valid upon successful return.
+ *
+ * @returns Pointer to the variable. NULL if not found.
+ * @param   pszName     The variable name.
+ */
+static struct variable *
+kbuild_lookup_variable(const char *pszName)
+{
+    struct variable *pVar = lookup_variable(pszName, strlen(pszName));
+    if (pVar)
+    {
+#ifndef NDEBUG
+        int i = strlen(pVar->value);
+        if (i != pVar->value_length)
+        {
+            printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
+# ifdef _MSC_VER
+            __debugbreak();
+# endif
+            assert(0);
+        }
+#endif
+        /* Make sure the variable is simple, convert it if necessary. */
+        if (pVar->recursive)
+            kbuild_simplify_variable(pVar);
+    }
+    return pVar;
+}
+
+
+/**
+ * Looks up a variable and applies default a path to all relative paths.
+ * The value_length field is valid upon successful return.
+ *
+ * @returns Pointer to the variable. NULL if not found.
+ * @param   pDefPath    The default path.
+ * @param   pszName     The variable name.
+ */
+static struct variable *
+kbuild_lookup_variable_defpath(struct variable *pDefPath, const char *pszName)
+{
+    struct variable *pVar = kbuild_lookup_variable(pszName);
+    if (pVar && pDefPath)
+        kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1);
+    return pVar;
+}
+
+
+/** Same as kbuild_lookup_variable except that a '%s' in the name string
+ * will be substituted with the values of the variables in the va list. */
+static struct variable *
+kbuild_lookup_variable_fmt_va(struct variable *pDefPath, const char *pszNameFmt, va_list va)
+{
+    va_list va2;
+    size_t cchName;
+    const char *pszFmt;
+    char *pszName;
+    char *psz;
+
+    /* first pass, calc value name size and allocate stack buffer. */
+    va_copy(va2, va);
+
+    cchName = strlen(pszNameFmt) + 1;
+    pszFmt = strchr(pszNameFmt, '%');
+    while (pszFmt)
+    {
+        struct variable *pVar = va_arg(va, struct variable *);
+        if (pVar)
+            cchName += pVar->value_length;
+        pszFmt = strchr(pszFmt + 1, '%');
+    }
+    pszName = alloca(cchName);
+
+    /* second pass format it. */
+    pszFmt = pszNameFmt;
+    psz = pszName;
+    for (;;)
+    {
+        char ch = *pszFmt++;
+        if (ch != '%')
+        {
+            *psz++ = ch;
+            if (!ch)
+                break;
+        }
+        else
+        {
+            struct variable *pVar = va_arg(va2, struct variable *);
+            if (pVar)
+            {
+                memcpy(psz, pVar->value, pVar->value_length);
+                psz += pVar->value_length;
+            }
+        }
+    }
+    va_end(va2);
+
+    if (pDefPath)
+        return kbuild_lookup_variable_defpath(pDefPath, pszName);
+    return kbuild_lookup_variable(pszName);
+}
+
+
+/** Same as kbuild_lookup_variable except that a '%s' in the name string
+ * will be substituted with the values of the variables in the ellipsis.  */
+static struct variable *
+kbuild_lookup_variable_fmt(struct variable *pDefPath, const char *pszNameFmt, ...)
+{
+    struct variable *pVar;
+    va_list va;
+    va_start(va, pszNameFmt);
+    pVar = kbuild_lookup_variable_fmt_va(pDefPath, pszNameFmt, va);
+    va_end(va);
+    return pVar;
+}
+
+
+/**
+ * Gets the first defined property variable.
+ */
+static struct variable *
+kbuild_first_prop(struct variable *pTarget, struct variable *pSource,
+                  struct variable *pTool, struct variable *pType,
+                  struct variable *pBldTrg, struct variable *pBldTrgArch,
+                  const char *pszPropF1, const char *pszPropF2, const char *pszVarName)
+{
+    struct variable *pVar;
+    struct variable PropF1, PropF2;
+
+    PropF1.value = (char *)pszPropF1;
+    PropF1.value_length = strlen(pszPropF1);
+
+    PropF2.value = (char *)pszPropF2;
+    PropF2.value_length = strlen(pszPropF2);
+
+    if (    (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%.%.%",pTarget, pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%.%",  pTarget, pSource, pType, &PropF2, pBldTrg))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%",    pTarget, pSource, pType, &PropF2))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%.%.%", pTarget, pSource, &PropF2, pBldTrg, pBldTrgArch))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%.%",   pTarget, pSource, &PropF2, pBldTrg))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%",     pTarget, pSource, &PropF2))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%.%",  pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%",    pSource, pType, &PropF2, pBldTrg))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%",      pSource, pType, &PropF2))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%.%",   pSource, &PropF2, pBldTrg, pBldTrgArch))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%",     pSource, &PropF2, pBldTrg))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%",       pSource, &PropF2))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%.%",  pTarget, pType, &PropF2, pBldTrg, pBldTrgArch))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%",    pTarget, pType, &PropF2, pBldTrg))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%",      pTarget, pType, &PropF2))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%.%",   pTarget, &PropF2, pBldTrg, pBldTrgArch))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%",     pTarget, &PropF2, pBldTrg))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%_%",       pTarget, &PropF2))
+
+        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%.%",   pTool, pType, &PropF2, pBldTrg, pBldTrgArch)))
+        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%",     pTool, pType, &PropF2, pBldTrg)))
+        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%",       pTool, pType, &PropF2)))
+        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%.%",    pTool, &PropF2, pBldTrg, pBldTrgArch)))
+        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%",      pTool, &PropF2, pBldTrg)))
+        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%",        pTool, &PropF2)))
+
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%%.%.%",    pType, &PropF1, pBldTrg, pBldTrgArch))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%%.%",      pType, &PropF1, pBldTrg))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%%",        pType, &PropF1))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%.%.%",     &PropF1, pBldTrg, pBldTrgArch))
+        ||  (pVar = kbuild_lookup_variable_fmt(NULL, "%.%",       &PropF1, pBldTrg))
+        ||  (pVar = kbuild_lookup_variable(pszPropF1))
+       )
+    {
+        /* strip it */
+        char *psz = pVar->value;
+        char *pszEnd = psz + pVar->value_length;
+        while (isblank((unsigned char)*psz))
+            psz++;
+        while (pszEnd > psz && isblank((unsigned char)pszEnd[-1]))
+            pszEnd--;
+        if (pszEnd > psz)
+        {
+            char chSaved = *pszEnd;
+            *pszEnd = '\0';
+            pVar = define_variable_vl(pszVarName, strlen(pszVarName), psz, pszEnd - psz,
+                                      1 /* duplicate */, o_local, 0 /* !recursive */);
+            *pszEnd = chSaved;
+            if (pVar)
+                return pVar;
+        }
+    }
+    return NULL;
+}
+
+
+/*
+_SOURCE_TOOL = $(strip $(firstword \
+    $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
+    $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \
+    $($(target)_$(source)_$(type)TOOL) \
+    $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
+    $($(target)_$(source)_TOOL.$(bld_trg)) \
+    $($(target)_$(source)_TOOL) \
+    $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
+    $($(source)_$(type)TOOL.$(bld_trg)) \
+    $($(source)_$(type)TOOL) \
+    $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
+    $($(source)_TOOL.$(bld_trg)) \
+    $($(source)_TOOL) \
+    $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
+    $($(target)_$(type)TOOL.$(bld_trg)) \
+    $($(target)_$(type)TOOL) \
+    $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
+    $($(target)_TOOL.$(bld_trg)) \
+    $($(target)_TOOL) \
+    $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
+    $($(type)TOOL.$(bld_trg)) \
+    $($(type)TOOL) \
+    $(TOOL.$(bld_trg).$(bld_trg_arch)) \
+    $(TOOL.$(bld_trg)) \
+    $(TOOL) ))
+*/
+static struct variable *
+kbuild_get_source_tool(struct variable *pTarget, struct variable *pSource, struct variable *pType,
+                       struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
+{
+    struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch,
+                                              "TOOL", "TOOL", pszVarName);
+    if (!pVar)
+        fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value);
+    return pVar;
+}
+
+
+/* Implements _SOURCE_TOOL. */
+char *
+func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName)
+{
+    struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable("target"),
+                                                   kbuild_get_variable("source"),
+                                                   kbuild_get_variable("type"),
+                                                   kbuild_get_variable("bld_trg"),
+                                                   kbuild_get_variable("bld_trg_arch"),
+                                                   argv[0]);
+    if (pVar)
+         o = variable_buffer_output(o, pVar->value, pVar->value_length);
+    (void)pszFuncName;
+    return o;
+
+}
+
+
+/* This has been extended a bit, it's now identical to _SOURCE_TOOL.
+$(firstword \
+	$($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_$(source)_OBJSUFF.$(bld_trg))\
+	$($(target)_$(source)_OBJSUFF)\
+	$($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
+	$($(source)_OBJSUFF.$(bld_trg))\
+	$($(source)_OBJSUFF)\
+	$($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_OBJSUFF.$(bld_trg))\
+	$($(target)_OBJSUFF)\
+	$(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\
+	$(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\
+	$(TOOL_$(tool)_$(type)OBJSUFF)\
+	$(SUFF_OBJ))
+*/
+static struct variable *
+kbuild_get_object_suffix(struct variable *pTarget, struct variable *pSource,
+                         struct variable *pTool, struct variable *pType,
+                         struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
+{
+    struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch,
+                                              "SUFF_OBJ", "OBJSUFF", pszVarName);
+    if (!pVar)
+        fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value);
+    return pVar;
+}
+
+
+/*  */
+char *
+func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName)
+{
+    struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable("target"),
+                                                     kbuild_get_variable("source"),
+                                                     kbuild_get_variable("tool"),
+                                                     kbuild_get_variable("type"),
+                                                     kbuild_get_variable("bld_trg"),
+                                                     kbuild_get_variable("bld_trg_arch"),
+                                                     argv[0]);
+    if (pVar)
+         o = variable_buffer_output(o, pVar->value, pVar->value_length);
+    (void)pszFuncName;
+    return o;
+
+}
+
+
+/*
+## Figure out where to put object files.
+# @param    $1      source file
+# @param    $2      normalized main target
+# @remark There are two major hacks here:
+#           1. Source files in the output directory are translated into a gen/ subdir.
+#         	2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c.
+_OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \
+	$(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1)))))))
+*/
+static struct variable *
+kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName)
+{
+    struct variable *pPathTarget = kbuild_get_variable("PATH_TARGET");
+    struct variable *pPathRoot   = kbuild_get_variable("PATH_ROOT");
+    struct variable *pPathSubCur = kbuild_get_variable("PATH_SUB_CURRENT");
+    const char *pszSrcPrefix = NULL;
+    size_t      cchSrcPrefix = 0;
+    size_t      cchSrc = 0;
+    const char *pszSrcEnd;
+    char *pszSrc;
+    char *pszResult;
+    char *psz;
+    char *pszDot;
+    size_t cch;
+
+    /*
+     * Strip the source filename of any uncessary leading path and root specs.
+     */
+    /* */
+    if (    pSource->value_length > pPathTarget->value_length
+        &&  !strncmp(pSource->value, pPathTarget->value, pPathTarget->value_length))
+    {
+        pszSrc = pSource->value + pPathTarget->value_length;
+        pszSrcPrefix = "gen/";
+        cchSrcPrefix = sizeof("gen/") - 1;
+        if (    *pszSrc == '/'
+            &&  !strncmp(pszSrc + 1, pTarget->value, pTarget->value_length)
+            &&   (   pszSrc[pTarget->value_length + 1] == '/'
+                  || pszSrc[pTarget->value_length + 1] == '\0'))
+            pszSrc += 1 + pTarget->value_length;
+    }
+    else if (    pSource->value_length > pPathRoot->value_length
+             &&  !strncmp(pSource->value, pPathRoot->value, pPathRoot->value_length))
+    {
+        pszSrc = pSource->value + pPathRoot->value_length;
+        if (    *pszSrc == '/'
+            &&  !strncmp(pszSrc + 1, pPathSubCur->value, pPathSubCur->value_length)
+            &&   (   pszSrc[pPathSubCur->value_length + 1] == '/'
+                  || pszSrc[pPathSubCur->value_length + 1] == '\0'))
+            pszSrc += 1 + pPathSubCur->value_length;
+    }
+    else
+        pszSrc = pSource->value;
+
+    /* skip root specification */
+#ifdef HAVE_DOS_PATHS
+    if (isalpha(pszSrc[0]) && pszSrc[1] == ':')
+        pszSrc += 2;
+#endif
+    while (*pszSrc == '/'
+#ifdef HAVE_DOS_PATHS
+           || *pszSrc == '\\'
+#endif
+           )
+        pszSrc++;
+
+    /* drop the source extension. */
+    pszSrcEnd = pSource->value + pSource->value_length;
+    for (;;)
+    {
+        pszSrcEnd--;
+        if (    pszSrcEnd <= pszSrc
+            ||  *pszSrcEnd == '/'
+#ifdef HAVE_DOS_PATHS
+            ||  *pszSrcEnd == '\\'
+            ||  *pszSrcEnd == ':'
+#endif
+           )
+        {
+            pszSrcEnd = pSource->value + pSource->value_length;
+            break;
+        }
+        if (*pszSrcEnd == '.')
+            break;
+    }
+
+    /*
+     * Assemble the string on the heap and define the objbase variable
+     * which we then return.
+     */
+    cchSrc = pszSrcEnd - pszSrc;
+    cch = pPathTarget->value_length
+        + 1 /* slash */
+        + pTarget->value_length
+        + 1 /* slash */
+        + cchSrcPrefix
+        + cchSrc
+        + 1;
+    psz = pszResult = xmalloc(cch);
+
+    memcpy(psz, pPathTarget->value, pPathTarget->value_length); psz += pPathTarget->value_length;
+    *psz++ = '/';
+    memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
+    *psz++ = '/';
+    if (pszSrcPrefix)
+    {
+        memcpy(psz, pszSrcPrefix, cchSrcPrefix);
+        psz += cchSrcPrefix;
+    }
+    pszDot = psz;
+    memcpy(psz, pszSrc, cchSrc); psz += cchSrc;
+    *psz = '\0';
+
+    /* convert '..' path elements in the source to 'dt'. */
+    while ((pszDot = memchr(pszDot, '.', psz - pszDot)) != NULL)
+    {
+        if (    pszDot[1] == '.'
+            &&  (   pszDot == psz
+                 || pszDot[-1] == '/'
+#ifdef HAVE_DOS_PATHS
+                 || pszDot[-1] == '\\'
+                 || pszDot[-1] == ':'
+#endif
+                )
+            &&  (   !pszDot[2]
+                 || pszDot[2] == '/'
+#ifdef HAVE_DOS_PATHS
+                 || pszDot[2] == '\\'
+                 || pszDot[2] == ':'
+#endif
+                )
+            )
+        {
+            *pszDot++ = 'd';
+            *pszDot++ = 't';
+        }
+        else
+            pszDot++;
+    }
+
+    /*
+     * Define the variable in the current set and return it.
+     */
+    return define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cch - 1,
+                              0 /* use pszResult */, o_local, 0 /* !recursive */);
+}
+
+
+/* Implements _OBJECT_BASE. */
+char *
+func_kbuild_object_base(char *o, char **argv, const char *pszFuncName)
+{
+    struct variable *pVar = kbuild_get_object_base(kbuild_lookup_variable("target"),
+                                                   kbuild_lookup_variable("source"),
+                                                   argv[0]);
+    if (pVar)
+         o = variable_buffer_output(o, pVar->value, pVar->value_length);
+    (void)pszFuncName;
+    return o;
+
+}
+
+
+struct kbuild_sdks
+{
+    char *apsz[4];
+    struct variable *pa;
+    unsigned c;
+    unsigned iGlobal;
+    unsigned cGlobal;
+    unsigned iTarget;
+    unsigned cTarget;
+    unsigned iSource;
+    unsigned cSource;
+    unsigned iTargetSource;
+    unsigned cTargetSource;
+};
+
+
+/* Fills in the SDK struct (remember to free it). */
+static void
+kbuild_get_sdks(struct kbuild_sdks *pSdks, struct variable *pTarget, struct variable *pSource,
+                struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch)
+{
+    unsigned i;
+    unsigned j;
+    size_t cchTmp, cch;
+    char *pszTmp;
+    unsigned cchCur;
+    char *pszCur;
+    const char *pszIterator;
+
+    /* basic init. */
+    pSdks->pa = NULL;
+    pSdks->c = 0;
+    i = 0;
+
+    /* determin required tmp variable name space. */
+    cchTmp = sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)")
+           + (pTarget->value_length + pSource->value_length) * 5
+           + pBldType->value_length
+           + pBldTrg->value_length
+           + pBldTrgArch->value_length
+           + pBldTrg->value_length + pBldTrgArch->value_length;
+    pszTmp = alloca(cchTmp);
+
+    /* the global sdks. */
+    pSdks->iGlobal = i;
+    pSdks->cGlobal = 0;
+    sprintf(pszTmp, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)",
+            pBldType->value,
+            pBldTrg->value,
+            pBldTrgArch->value,
+            pBldTrg->value, pBldTrgArch->value);
+    pszIterator = pSdks->apsz[0] = allocated_variable_expand(pszTmp);
+    while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
+        pSdks->cGlobal++;
+    i += pSdks->cGlobal;
+
+    /* the target sdks.*/
+    pSdks->iTarget = i;
+    pSdks->cTarget = 0;
+    sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
+            pTarget->value,
+            pTarget->value, pBldType->value,
+            pTarget->value, pBldTrg->value,
+            pTarget->value, pBldTrgArch->value,
+            pTarget->value, pBldTrg->value, pBldTrgArch->value);
+    pszIterator = pSdks->apsz[1] = allocated_variable_expand(pszTmp);
+    while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
+        pSdks->cTarget++;
+    i += pSdks->cTarget;
+
+    /* the source sdks.*/
+    pSdks->iSource = i;
+    pSdks->cSource = 0;
+    sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
+            pSource->value,
+            pSource->value, pBldType->value,
+            pSource->value, pBldTrg->value,
+            pSource->value, pBldTrgArch->value,
+            pSource->value, pBldTrg->value, pBldTrgArch->value);
+    pszIterator = pSdks->apsz[2] = allocated_variable_expand(pszTmp);
+    while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
+        pSdks->cSource++;
+    i += pSdks->cSource;
+
+    /* the target + source sdks. */
+    pSdks->iTargetSource = i;
+    pSdks->cTargetSource = 0;
+    cch = sprintf(pszTmp, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)",
+                  pTarget->value, pSource->value,
+                  pTarget->value, pSource->value, pBldType->value,
+                  pTarget->value, pSource->value, pBldTrg->value,
+                  pTarget->value, pSource->value, pBldTrgArch->value,
+                  pTarget->value, pSource->value, pBldTrg->value, pBldTrgArch->value);
+    assert(cch < cchTmp); (void)cch;
+    pszIterator = pSdks->apsz[3] = allocated_variable_expand(pszTmp);
+    while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
+        pSdks->cTargetSource++;
+    i += pSdks->cTargetSource;
+
+    pSdks->c = i;
+    if (!i)
+        return;
+
+    /*
+     * Allocate the variable array and create the variables.
+     */
+    pSdks->pa = (struct variable *)xmalloc(sizeof(pSdks->pa[0]) * i);
+    memset(pSdks->pa, 0, sizeof(pSdks->pa[0]) * i);
+    for (i = j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
+    {
+        pszIterator = pSdks->apsz[j];
+        while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
+        {
+            pSdks->pa[i].value = pszCur;
+            pSdks->pa[i].value_length = cchCur;
+            i++;
+        }
+    }
+    assert(i == pSdks->c);
+
+    /* terminate them (find_next_token won't work if we terminate them in the previous loop). */
+    while (i-- > 0)
+        pSdks->pa[i].value[pSdks->pa[i].value_length] = '\0';
+}
+
+
+/* releases resources allocated in the kbuild_get_sdks. */
+static void
+kbuild_put_sdks(struct kbuild_sdks *pSdks)
+{
+    unsigned j;
+    for (j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
+        free(pSdks->apsz[j]);
+    free(pSdks->pa);
+}
+
+
+/* this kind of stuff:
+
+defs        := $(kb-src-exp defs)
+	$(TOOL_$(tool)_DEFS)\
+	$(TOOL_$(tool)_DEFS.$(bld_type))\
+	$(TOOL_$(tool)_DEFS.$(bld_trg))\
+	$(TOOL_$(tool)_DEFS.$(bld_trg_arch))\
+	$(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\
+	$(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\
+	$(TOOL_$(tool)_$(type)DEFS)\
+	$(TOOL_$(tool)_$(type)DEFS.$(bld_type))\
+	$(foreach sdk, $(SDKS.$(bld_trg)) \
+				   $(SDKS.$(bld_trg).$(bld_trg_arch)) \
+				   $(SDKS.$(bld_type)) \
+				   $(SDKS),\
+		$(SDK_$(sdk)_DEFS)\
+		$(SDK_$(sdk)_DEFS.$(bld_type))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
+		$(SDK_$(sdk)_$(type)DEFS)\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
+	$(DEFS)\
+	$(DEFS.$(bld_type))\
+	$(DEFS.$(bld_trg))\
+	$(DEFS.$(bld_trg_arch))\
+	$(DEFS.$(bld_trg).$(bld_trg_arch))\
+	$(DEFS.$(bld_trg_cpu))\
+	$($(type)DEFS)\
+	$($(type)DEFS.$(bld_type))\
+	$($(type)DEFS.$(bld_trg))\
+	$($(type)DEFS.$(bld_trg_arch))\
+	$($(type)DEFS.$(bld_trg).$(bld_trg_arch))\
+	$($(type)DEFS.$(bld_trg_cpu))\
+	$(foreach sdk, $($(target)_SDKS.$(bld_trg)) \
+				   $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
+				   $($(target)_SDKS.$(bld_type)) \
+				   $($(target)_SDKS),\
+		$(SDK_$(sdk)_DEFS)\
+		$(SDK_$(sdk)_DEFS.$(bld_type))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
+		$(SDK_$(sdk)_$(type)DEFS)\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
+	$($(target)_DEFS)\
+	$($(target)_DEFS.$(bld_type))\
+	$($(target)_DEFS.$(bld_trg))\
+	$($(target)_DEFS.$(bld_trg_arch))\
+	$($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_DEFS.$(bld_trg_cpu))\
+	$($(target)_$(type)DEFS)\
+	$($(target)_$(type)DEFS.$(bld_type))\
+	$($(target)_$(type)DEFS.$(bld_trg))\
+	$($(target)_$(type)DEFS.$(bld_trg_arch))\
+	$($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_$(type)DEFS.$(bld_trg_cpu))\
+	$(foreach sdk, $($(source)_SDKS.$(bld_trg)) \
+				   $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
+				   $($(source)_SDKS.$(bld_type)) \
+				   $($(source)_SDKS),\
+		$(SDK_$(sdk)_DEFS)\
+		$(SDK_$(sdk)_DEFS.$(bld_type))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
+		$(SDK_$(sdk)_$(type)DEFS)\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
+	$($(source)_DEFS)\
+	$($(source)_DEFS.$(bld_type))\
+	$($(source)_DEFS.$(bld_trg))\
+	$($(source)_DEFS.$(bld_trg_arch))\
+	$($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
+	$($(source)_DEFS.$(bld_trg_cpu))\
+	$($(source)_$(type)DEFS)\
+	$($(source)_$(type)DEFS.$(bld_type))\
+	$($(source)_$(type)DEFS.$(bld_trg))\
+	$($(source)_$(type)DEFS.$(bld_trg_arch))\
+	$($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
+	$($(source)_$(type)DEFS.$(bld_trg_cpu))\
+	$(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \
+				   $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
+				   $($(target)_$(source)_SDKS.$(bld_type)) \
+				   $($(target)_$(source)_SDKS),\
+		$(SDK_$(sdk)_DEFS)\
+		$(SDK_$(sdk)_DEFS.$(bld_type))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
+		$(SDK_$(sdk)_$(type)DEFS)\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
+		$(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
+	$($(target)_$(source)_DEFS)\
+	$($(target)_$(source)_DEFS.$(bld_type))\
+	$($(target)_$(source)_DEFS.$(bld_trg))\
+	$($(target)_$(source)_DEFS.$(bld_trg_arch))\
+	$($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_$(source)_DEFS.$(bld_trg_cpu))\
+	$($(target)_$(source)_$(type)DEFS)\
+	$($(target)_$(source)_$(type)DEFS.$(bld_type))\
+	$($(target)_$(source)_$(type)DEFS.$(bld_trg))\
+	$($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\
+	$($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
+	$($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu))
+*/
+static struct variable *
+kbuild_collect_source_prop(struct variable *pTarget, struct variable *pSource,
+                           struct variable *pTool, struct kbuild_sdks *pSdks,
+                           struct variable *pType, struct variable *pBldType,
+                           struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu,
+                           struct variable *pDefPath,
+                           const char *pszProp, const char *pszVarName, int iDirection)
+{
+    struct variable *pVar;
+    unsigned iSdk, iSdkEnd;
+    int cVars, iVar, iVarEnd;
+    size_t cchTotal;
+    char *pszResult, *psz;
+    struct
+    {
+        struct variable    *pVar;
+        int                 cchExp;
+        char               *pszExp;
+    } *paVars;
+
+    struct variable Prop = {0};
+    Prop.value = (char *)pszProp;
+    Prop.value_length = strlen(pszProp);
+
+    assert(iDirection == 1 || iDirection == -1);
+
+    /*
+     * Get the variables.
+     */
+    cVars = 12 * (pSdks->c + 5);
+    paVars = alloca(cVars * sizeof(paVars[0]));
+
+    iVar = 0;
+    /* the tool (lowest priority) */
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%",      pTool, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%",    pTool, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%",    pTool, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%",    pTool, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%.%",  pTool, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%",    pTool, &Prop, pBldTrgCpu);
+
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%",     pTool, pType, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%",   pTool, pType, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%",   pTool, pType, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%",   pTool, pType, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%.%", pTool, pType, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%",   pTool, pType, &Prop, pBldTrgCpu);
+
+    /* the global sdks */
+    iSdkEnd = iDirection == 1 ? pSdks->iGlobal + pSdks->cGlobal : pSdks->iGlobal - 1;
+    for (iSdk = iDirection == 1 ? pSdks->iGlobal : pSdks->iGlobal + pSdks->cGlobal - 1;
+         iSdk != iSdkEnd;
+         iSdk += iDirection)
+    {
+        struct variable *pSdk = &pSdks->pa[iSdk];
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%",      pSdk, &Prop);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldType);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrg);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%",  pSdk, &Prop, pBldTrg, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrgCpu);
+
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%",     pSdk, pType, &Prop);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldType);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrg);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrgCpu);
+    }
+
+    /* the globals */
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%",      &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%",    &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%",    &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%",    &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%.%",  &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%",    &Prop, pBldTrgCpu);
+
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%",     pType, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%",   pType, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%",   pType, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%",   pType, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%.%", pType, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%",   pType, &Prop, pBldTrgCpu);
+
+    /* the target sdks */
+    iSdkEnd = iDirection == 1 ? pSdks->iTarget + pSdks->cTarget : pSdks->iTarget - 1;
+    for (iSdk = iDirection == 1 ? pSdks->iTarget : pSdks->iTarget + pSdks->cTarget - 1;
+         iSdk != iSdkEnd;
+         iSdk += iDirection)
+    {
+        struct variable *pSdk = &pSdks->pa[iSdk];
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%",      pSdk, &Prop);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldType);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrg);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%",  pSdk, &Prop, pBldTrg, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrgCpu);
+
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%",     pSdk, pType, &Prop);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldType);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrg);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrgCpu);
+    }
+
+    /* the target */
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%",      pTarget, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%",    pTarget, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%",    pTarget, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%",    pTarget, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%.%",  pTarget, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%",    pTarget, &Prop, pBldTrgCpu);
+
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%",     pTarget, pType, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%",   pTarget, pType, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%",   pTarget, pType, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%",   pTarget, pType, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%.%", pTarget, pType, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%",   pTarget, pType, &Prop, pBldTrgCpu);
+
+    /* the source sdks */
+    iSdkEnd = iDirection == 1 ? pSdks->iSource + pSdks->cSource : pSdks->iSource - 1;
+    for (iSdk = iDirection == 1 ? pSdks->iSource : pSdks->iSource + pSdks->cSource - 1;
+         iSdk != iSdkEnd;
+         iSdk += iDirection)
+    {
+        struct variable *pSdk = &pSdks->pa[iSdk];
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%",      pSdk, &Prop);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldType);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrg);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%",  pSdk, &Prop, pBldTrg, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrgCpu);
+
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%",     pSdk, pType, &Prop);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldType);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrg);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrgCpu);
+    }
+
+    /* the source */
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%",      pSource, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%",    pSource, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%",    pSource, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%",    pSource, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%.%",  pSource, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%",    pSource, &Prop, pBldTrgCpu);
+
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%",     pSource, pType, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%",   pSource, pType, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%",   pSource, pType, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%",   pSource, pType, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%.%", pSource, pType, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%",   pSource, pType, &Prop, pBldTrgCpu);
+
+
+    /* the target + source sdks */
+    iSdkEnd = iDirection == 1 ? pSdks->iTargetSource + pSdks->cTargetSource : pSdks->iTargetSource - 1;
+    for (iSdk = iDirection == 1 ? pSdks->iTargetSource : pSdks->iTargetSource + pSdks->cTargetSource - 1;
+         iSdk != iSdkEnd;
+         iSdk += iDirection)
+    {
+        struct variable *pSdk = &pSdks->pa[iSdk];
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%",      pSdk, &Prop);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldType);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrg);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%",  pSdk, &Prop, pBldTrg, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%",    pSdk, &Prop, pBldTrgCpu);
+
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%",     pSdk, pType, &Prop);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldType);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrg);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
+        paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%",   pSdk, pType, &Prop, pBldTrgCpu);
+    }
+
+    /* the target + source */
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%",      pTarget, pSource, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%",    pTarget, pSource, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%",    pTarget, pSource, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%",    pTarget, pSource, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%.%",  pTarget, pSource, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%",    pTarget, pSource, &Prop, pBldTrgCpu);
+
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%",     pTarget, pSource, pType, &Prop);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%",   pTarget, pSource, pType, &Prop, pBldType);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%",   pTarget, pSource, pType, &Prop, pBldTrg);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%",   pTarget, pSource, pType, &Prop, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%.%", pTarget, pSource, pType, &Prop, pBldTrg, pBldTrgArch);
+    paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%",   pTarget, pSource, pType, &Prop, pBldTrgCpu);
+
+    assert(cVars == iVar);
+
+    /*
+     * Expand the variables and calculate the total length.
+     */
+    cchTotal = 0;
+    iVarEnd = iDirection == 1 ? cVars : 0;
+    for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
+    {
+        paVars[iVar].cchExp = 0;
+        if (!paVars[iVar].pVar)
+            continue;
+        if (    paVars[iVar].pVar->flavor == f_simple
+            ||  !strchr(paVars[iVar].pVar->value, '$'))
+        {
+            paVars[iVar].pszExp = paVars[iVar].pVar->value;
+            paVars[iVar].cchExp = paVars[iVar].pVar->value_length;
+        }
+        else
+        {
+            paVars[iVar].pszExp = allocated_variable_expand(paVars[iVar].pVar->value);
+            paVars[iVar].cchExp = strlen(paVars[iVar].pszExp);
+        }
+        if (pDefPath)
+            kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL,
+                                 paVars[iVar].pszExp != paVars[iVar].pVar->value);
+        cchTotal += paVars[iVar].cchExp + 1;
+    }
+
+    /*
+     * Construct the result value.
+     */
+    psz = pszResult = xmalloc(cchTotal + 1);
+    iVarEnd = iDirection == 1 ? cVars : 0;
+    for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
+    {
+        if (!paVars[iVar].cchExp)
+            continue;
+        memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
+        psz += paVars[iVar].cchExp;
+        *psz++ = ' ';
+        if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
+            free(paVars[iVar].pszExp);
+    }
+    if (psz != pszResult)
+        psz--;
+    *psz = '\0';
+    cchTotal = psz - pszResult;
+
+    pVar = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cchTotal,
+                              0 /* take pszResult */ , o_local, 0 /* !recursive */);
+    return pVar;
+}
+
+
+/* get a source property. */
+char *
+func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
+{
+    struct variable *pTarget = kbuild_get_variable("target");
+    struct variable *pSource = kbuild_get_variable("source");
+    struct variable *pDefPath = NULL;
+    struct variable *pType = kbuild_get_variable("type");
+    struct variable *pTool = kbuild_get_variable("tool");
+    struct variable *pBldType = kbuild_get_variable("bld_type");
+    struct variable *pBldTrg = kbuild_get_variable("bld_trg");
+    struct variable *pBldTrgArch = kbuild_get_variable("bld_trg_arch");
+    struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
+    struct variable *pVar;
+    struct kbuild_sdks Sdks;
+    int iDirection;
+    if (!strcmp(argv[2], "left-to-right"))
+        iDirection = 1;
+    else if (!strcmp(argv[2], "right-to-left"))
+        iDirection = -1;
+    else
+        fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]);
+    if (argv[3])
+    {
+        const char *psz = argv[3];
+        while (isspace(*psz))
+            psz++;
+        if (*psz)
+            pDefPath = kbuild_get_variable("defpath");
+    }
+
+    kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
+
+    pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType,
+                                      pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
+                                      pDefPath,
+                                      argv[0], argv[1], iDirection);
+    if (pVar)
+         o = variable_buffer_output(o, pVar->value, pVar->value_length);
+
+    kbuild_put_sdks(&Sdks);
+    (void)pszFuncName;
+    return o;
+}
+
+
+/*
+dep     := $(obj)$(SUFF_DEP)
+obj     := $(outbase)$(objsuff)
+dirdep  := $(call DIRDEP,$(dir $(outbase)))
+PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
+*/
+static struct variable *
+kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource,
+                                                                 struct variable *pOutBase, struct variable *pObjSuff,
+                                                                 const char *pszVarName, struct variable **ppDep,
+                                                                 struct variable **ppDirDep)
+{
+    struct variable *pDepSuff = kbuild_get_variable("SUFF_DEP");
+    struct variable *pObj;
+    size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
+    char *pszResult = alloca(cch);
+    char *pszName, *psz;
+
+    /*
+     * dep.
+     */
+    psz = pszResult;
+    memcpy(psz, pOutBase->value, pOutBase->value_length);   psz += pOutBase->value_length;
+    memcpy(psz, pObjSuff->value, pObjSuff->value_length);   psz += pObjSuff->value_length;
+    memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1);
+    *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_local, 0 /* !recursive */);
+
+    /*
+     * obj
+     */
+    *psz = '\0';
+    pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult,
+                              1/* dup */, o_local, 0 /* !recursive */);
+
+    /*
+     * PATH_$(target)_$(source) - this is global!
+     */
+    /* calc variable name. */
+    cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length;
+    psz = pszName = alloca(cch + 1);
+    memcpy(psz, "PATH_", sizeof("PATH_") - 1);          psz += sizeof("PATH_") - 1;
+    memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
+    *psz++ = '_';
+    memcpy(psz, pSource->value, pSource->value_length + 1);
+
+    /* strip off the filename. */
+    psz = pszResult + pOutBase->value_length;
+    for (;;)
+    {
+        psz--;
+        if (psz <= pszResult)
+            fatal(NULL, "whut!?! no path? result=`%s'", pszResult);
+#ifdef HAVE_DOS_PATHS
+        if (*psz == ':')
+        {
+            psz++;
+            break;
+        }
+#endif
+        if (    *psz == '/'
+#ifdef HAVE_DOS_PATHS
+            ||  *psz == '\\'
+#endif
+           )
+        {
+            while (     psz - 1 > pszResult
+                   &&   psz[-1] == '/'
+#ifdef HAVE_DOS_PATHS
+                   ||   psz[-1] == '\\'
+#endif
+                  )
+                psz--;
+#ifdef HAVE_DOS_PATHS
+            if (psz == pszResult + 2 && pszResult[1] == ':')
+                psz++;
+#endif
+            break;
+        }
+    }
+    *psz = '\0';
+
+    /* set global variable */
+    define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF);
+
+    /*
+     * dirdep
+     */
+    if (    psz[-1] != '/'
+#ifdef HAVE_DOS_PATHS
+        &&  psz[-1] != '\\'
+        &&  psz[-1] != ':'
+#endif
+       )
+    {
+        *psz++ = '/';
+        *psz = '\0';
+    }
+    *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_local, 0 /* !recursive */);
+
+    return pObj;
+}
+
+
+/* setup the base variables for def_target_source_c_cpp_asm_new:
+
+X := $(kb-src-tool tool)
+x := $(kb-obj-base outbase)
+x := $(kb-obj-suff objsuff)
+obj     := $(outbase)$(objsuff)
+PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
+
+x := $(kb-src-prop DEFS,defs,left-to-right)
+x := $(kb-src-prop INCS,incs,right-to-left)
+x := $(kb-src-prop FLAGS,flags,right-to-left)
+
+x := $(kb-src-prop DEPS,deps,left-to-right)
+dirdep  := $(call DIRDEP,$(dir $(outbase)))
+dep     := $(obj)$(SUFF_DEP)
+*/
+char *
+func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
+{
+    static int s_fNoCompileCmdsDepsDefined = -1;
+    struct variable *pTarget    = kbuild_get_variable("target");
+    struct variable *pSource    = kbuild_get_variable("source");
+    struct variable *pDefPath   = kbuild_get_variable("defpath");
+    struct variable *pType      = kbuild_get_variable("type");
+    struct variable *pBldType   = kbuild_get_variable("bld_type");
+    struct variable *pBldTrg    = kbuild_get_variable("bld_trg");
+    struct variable *pBldTrgArch= kbuild_get_variable("bld_trg_arch");
+    struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
+    struct variable *pTool      = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
+    struct variable *pOutBase   = kbuild_get_object_base(pTarget, pSource, "outbase");
+    struct variable *pObjSuff   = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
+    struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput, *pOutputMaybe;
+    struct variable *pObj       = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
+    char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
+    char *pszSavedVarBuf;
+    unsigned cchSavedVarBuf;
+    size_t cch;
+    struct kbuild_sdks Sdks;
+
+    /*
+     * Gather properties.
+     */
+    kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
+
+    if (pDefPath && !pDefPath->value_length)
+        pDefPath = NULL;
+    pDefs      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
+                                            "DEFS", "defs", 1/* left-to-right */);
+    pIncs      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
+                                            "INCS", "incs", -1/* right-to-left */);
+    pFlags     = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
+                                            "FLAGS", "flags", 1/* left-to-right */);
+    pDeps      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
+                                            "DEPS", "deps", 1/* left-to-right */);
+    pOrderDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
+                                            "ORDERDEPS", "orderdeps", 1/* left-to-right */);
+
+    /*
+     * If we've got a default path, we must expand the source now.
+     * If we do this too early, "<source>_property = stuff" won't work becuase
+     * our 'source' value isn't what the user expects.
+     */
+    if (pDefPath)
+        kbuild_apply_defpath(pDefPath, &pSource->value, &pSource->value_length, &pSource->value_alloc_len, 1 /* can free */);
+
+    /*
+    # dependencies
+    ifndef NO_COMPILE_CMDS_DEPS
+    _DEPFILES_INCLUDED += $(dep)
+    $(if $(wildcard $(dep)),$(eval include $(dep)))
+    endif
+     */
+    if (s_fNoCompileCmdsDepsDefined == -1)
+        s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable("NO_COMPILE_CMDS_DEPS") != NULL;
+    if (!s_fNoCompileCmdsDepsDefined)
+    {
+        do_variable_definition(NILF, "_DEPFILES_INCLUDED", pDep->value, o_file, f_append, 0 /* !target_var */);
+        eval_include_dep(pDep->value, NILF);
+    }
+
+    /*
+    # call the tool
+    $(target)_$(source)_CMDS_   := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
+    $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
+    $(target)_$(source)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT_MAYBE)
+    $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
+    $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
+    */
+    cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT_MAYBE");
+    psz = pszSrcVar = alloca(cch);
+    memcpy(psz, "TOOL_", sizeof("TOOL_") - 1);          psz += sizeof("TOOL_") - 1;
+    memcpy(psz, pTool->value, pTool->value_length);     psz += pTool->value_length;
+    memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1);  psz += sizeof("_COMPILE_") - 1;
+    memcpy(psz, pType->value, pType->value_length);     psz += pType->value_length;
+    pszSrc = psz;
+
+    cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_MAYBE_");
+    psz = pszDstVar = alloca(cch);
+    memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
+    *psz++ = '_';
+    memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length;
+    pszDst = psz;
+
+    memcpy(pszSrc, "_CMDS", sizeof("_CMDS"));
+    memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
+    pVar = kbuild_get_recursive_variable(pszSrcVar);
+    do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
+
+    memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
+    memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
+    pVar = kbuild_get_recursive_variable(pszSrcVar);
+    pOutput = do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
+
+    memcpy(pszSrc, "_OUTPUT_MAYBE", sizeof("_OUTPUT_MAYBE"));
+    memcpy(pszDst, "_OUTPUT_MAYBE_", sizeof("_OUTPUT_MAYBE_"));
+    pVar = kbuild_query_recursive_variable(pszSrcVar);
+    pOutputMaybe = do_variable_definition(NILF, pszDstVar, pVar ? pVar->value : "", o_file, f_simple, 0 /* !target_var */);
+
+    memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
+    memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
+    pVar = kbuild_get_recursive_variable(pszSrcVar);
+    psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1);
+    memcpy(psz, pVar->value, pVar->value_length);       psz += pVar->value_length;
+    *psz++ = ' ';
+    memcpy(psz, pDeps->value, pDeps->value_length);     psz += pDeps->value_length;
+    *psz++ = ' ';
+    memcpy(psz, pSource->value, pSource->value_length + 1);
+    do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
+    free(pszVal);
+
+    memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
+    memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
+    pVar = kbuild_get_recursive_variable(pszSrcVar);
+    psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length + 1);
+    memcpy(psz, pVar->value, pVar->value_length);       psz += pVar->value_length;
+    *psz++ = ' ';
+    memcpy(psz, pDirDep->value, pDirDep->value_length); psz += pDirDep->value_length;
+    *psz++ = ' ';
+    memcpy(psz, pOrderDeps->value, pOrderDeps->value_length + 1);
+    do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
+    free(pszVal);
+
+    /*
+    _OUT_FILES      += $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_)
+    */
+    pVar = kbuild_get_variable("_OUT_FILES");
+    psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length + 1);
+    memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
+    *psz++ = ' ';
+    memcpy(psz, pOutput->value, pOutput->value_length); psz += pOutput->value_length;
+    *psz++ = ' ';
+    memcpy(psz, pOutputMaybe->value, pOutputMaybe->value_length + 1);
+    do_variable_definition(NILF, "_OUT_FILES", pszVal, o_file, f_simple, 0 /* !target_var */);
+    free(pszVal);
+
+    /*
+    $(target)_OBJS_ += $(obj)
+    */
+    memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_"));
+    do_variable_definition(NILF, pszDstVar, pObj->value, o_file, f_append, 0 /* !target_var */);
+
+    /*
+    $(eval $(def_target_source_rule))
+    */
+    pVar = kbuild_get_recursive_variable("def_target_source_rule");
+    pszVal = allocated_variable_expand(pVar->value);
+
+    install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
+    eval_buffer(pszVal);
+    restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
+
+    free(pszVal);
+
+    kbuild_put_sdks(&Sdks);
+    (void)pszFuncName;
+    (void)argv;
+    return variable_buffer_output(o, "", 1);
+}
+
+
+#endif /* KMK_HELPERS */
+
Index: /tags/kBuild-0.1.4/src/kmk/kbuild.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kbuild.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kbuild.h	(revision 1780)
@@ -0,0 +1,41 @@
+/* $Id$ */
+/** @file
+ *
+ * kBuild specific make functionality.
+ *
+ * Copyright (c) 2006-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __kBuild_h__
+#define __kBuild_h__
+
+char *func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName);
+char *func_kbuild_object_base(char *o, char **argv, const char *pszFuncName);
+char *func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName);
+char *func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName);
+char *func_kbuild_source_one(char *o, char **argv, const char *pszFuncName);
+
+void init_kbuild(int argc, char **argv);
+const char *get_kbuild_path(void);
+const char *get_kbuild_bin_path(void);
+const char *get_default_kbuild_shell(void);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/kbuildprf.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kbuildprf.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kbuildprf.c	(revision 1780)
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <io.h>
+#include <errno.h>
+#include <Windows.h>
+
+__int64 prf_now(void)
+{
+    return GetTickCount();
+}
+
+#undef open
+int prf_open(const char *name, int of, int mask)
+{
+    int fd;
+//    int err;
+//    __int64 t = prf_now();
+    fd = _open(name, of, mask);
+//    err = errno;
+//    t = prf_now() - t;
+//    fprintf(stderr, "open(%s, %#x) -> %d/%d in %lu\n", name, of, fd, err, (long)t);
+//    errno = err;
+    return fd;
+}
+
+#undef close
+int prf_close(int fd)
+{
+    int rc;
+    rc = _close(fd);
+    return rc;
+}
+
+
+#undef read
+int prf_read(int fd, void *buf, long cb)
+{
+    int cbRead;
+    cbRead = _read(fd, buf, cb);
+    return cbRead;
+}
+
+#undef lseek
+long prf_lseek(int fd, long off, int whence)
+{
+    long rc;
+    rc = _lseek(fd, off, whence);
+    return rc;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin.c	(revision 1780)
@@ -0,0 +1,264 @@
+/* $Id$ */
+/** @file
+ *
+ * kMk Builtin command execution.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#ifdef _MSC_VER
+# include <io.h>
+#endif
+#include "kmkbuiltin/err.h"
+#include "kmkbuiltin.h"
+
+#ifndef _MSC_VER
+extern char **environ;
+#endif
+
+int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
+{
+    int         argc;
+    char      **argv;
+    int         rc;
+
+    /*
+     * Check and skip the prefix.
+     */
+    if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
+    {
+        printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
+        return 1;
+    }
+
+    /*
+     * Parse arguments.
+     */
+    argc = 0;
+    argv = NULL;
+    while (*pszCmd)
+    {
+        const char *pszEnd;
+        const char *pszNext;
+        int         fEscaped = 0;
+        size_t      cch;
+
+        /*
+         * Find start and end of the current command.
+         */
+        if (*pszCmd == '"' || *pszCmd == '\'')
+        {
+            pszEnd = pszCmd;
+            for (;;)
+            {
+                pszEnd = strchr(pszEnd + 1, *pszCmd);
+                if (!pszEnd)
+                {
+                    printf("kmk_builtin: Unbalanced quote in argument %d: %s\n", argc + 1, pszCmd);
+                    while (argc--)
+                        free(argv[argc]);
+                    free(argv);
+                    return 1;
+                }
+                /* two quotes -> escaped quote. */
+                if (pszEnd[0] != pszEnd[1])
+                    break;
+                fEscaped = 1;
+            }
+            pszNext = pszEnd + 1;
+            pszCmd++;
+        }
+        else
+        {
+            pszEnd = pszCmd;
+            while (!isspace(*pszEnd) && *pszEnd)
+                pszEnd++;
+            pszNext = pszEnd;
+        }
+
+        /*
+         * Make argument.
+         */
+        if (!(argc % 16))
+        {
+            void *pv = realloc(argv, sizeof(char *) * (argc + 17));
+            if (!pv)
+            {
+                printf("kmk_builtin: out of memory. argc=%d\n", argc);
+                break;
+            }
+            argv = (char **)pv;
+        }
+        cch = pszEnd - pszCmd;
+        argv[argc] = malloc(cch + 1);
+        if (!argv[argc])
+        {
+            printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, pszEnd - pszCmd + 1);
+            break;
+        }
+        memcpy(argv[argc], pszCmd, cch);
+        argv[argc][cch] = '\0';
+
+        /* unescape quotes? */
+        if (fEscaped)
+        {
+            char ch = pszCmd[-1];
+            char *pszW = argv[argc];
+            char *pszR = argv[argc];
+            while (*pszR)
+            {
+                if (*pszR == ch)
+                    pszR++;
+                *pszW++ = *pszR++;
+            }
+            *pszW = '\0';
+        }
+        /* commit it */
+        argv[++argc] = NULL;
+
+        /*
+         * Next
+         */
+        pszCmd = pszNext;
+        if (isspace(*pszCmd) && *pszCmd)
+            pszCmd++;
+    }
+
+    /*
+     * Execute the command if parsing was successful.
+     */
+    if (!*pszCmd)
+        rc = kmk_builtin_command_parsed(argc, argv, ppapszArgvToSpawn, pPidSpawned);
+    else
+        rc = 1;
+
+    /* clean up and return. */
+    while (argc--)
+        free(argv[argc]);
+    free(argv);
+    return rc;
+}
+
+
+int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
+{
+    const char *pszCmd = argv[0];
+    int         iumask;
+    int         rc;
+
+    /*
+     * Check and skip the prefix.
+     */
+    if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
+    {
+        printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
+        return 1;
+    }
+    pszCmd += sizeof("kmk_builtin_") - 1;
+
+    /*
+     * String switch on the command.
+     */
+    iumask = umask(0);
+    umask(iumask);
+    if (!strcmp(pszCmd, "append"))
+        rc = kmk_builtin_append(argc, argv, environ);
+    else if (!strcmp(pszCmd, "printf"))
+        rc = kmk_builtin_printf(argc, argv, environ);
+    else if (!strcmp(pszCmd, "echo"))
+        rc = kmk_builtin_echo(argc, argv, environ);
+    else if (!strcmp(pszCmd, "install"))
+        rc = kmk_builtin_install(argc, argv, environ);
+    else if (!strcmp(pszCmd, "kDepIDB"))
+        rc = kmk_builtin_kDepIDB(argc, argv, environ);
+    else if (!strcmp(pszCmd, "mkdir"))
+        rc = kmk_builtin_mkdir(argc, argv, environ);
+    else if (!strcmp(pszCmd, "mv"))
+        rc = kmk_builtin_mv(argc, argv, environ);
+    /*else if (!strcmp(pszCmd, "redirect"))
+        rc = kmk_builtin_redirect(argc, argv, environ, pPidSpawned);*/
+    else if (!strcmp(pszCmd, "rm"))
+        rc = kmk_builtin_rm(argc, argv, environ);
+    else if (!strcmp(pszCmd, "rmdir"))
+        rc = kmk_builtin_rmdir(argc, argv, environ);
+    else if (!strcmp(pszCmd, "test"))
+        rc = kmk_builtin_test(argc, argv, environ, ppapszArgvToSpawn);
+    /* rarely used commands: */
+    else if (!strcmp(pszCmd, "chmod"))
+        rc = kmk_builtin_chmod(argc, argv, environ);
+    else if (!strcmp(pszCmd, "cp"))
+        rc = kmk_builtin_cp(argc, argv, environ);
+    else if (!strcmp(pszCmd, "expr"))
+        rc = kmk_builtin_expr(argc, argv, environ);
+    else if (!strcmp(pszCmd, "ln"))
+        rc = kmk_builtin_ln(argc, argv, environ);
+    else if (!strcmp(pszCmd, "md5sum"))
+        rc = kmk_builtin_md5sum(argc, argv, environ);
+    else if (!strcmp(pszCmd, "cmp"))
+        rc = kmk_builtin_cmp(argc, argv, environ);
+    else if (!strcmp(pszCmd, "cat"))
+        rc = kmk_builtin_cat(argc, argv, environ);
+    else
+    {
+        printf("kmk_builtin: Unknown command '%s'!\n", pszCmd);
+        return 1;
+    }
+
+    /*
+     * Cleanup.
+     */
+    g_progname = "kmk";                 /* paranoia, make sure it's not pointing at a freed argv[0]. */
+    umask(iumask);
+
+
+    /*
+     * If we've executed a conditional test or something that wishes to execute
+     * some child process, check if the child is a kmk_builtin thing. We recurse
+     * here, both because I'm lazy and because it's easier to debug a problem then
+     * (the call stack shows what's been going on).
+     */
+    if (    !rc
+        &&  *ppapszArgvToSpawn
+        &&  !strncmp(**ppapszArgvToSpawn, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
+    {
+        char **argv_new = *ppapszArgvToSpawn;
+        int argc_new = 1;
+        while (argv_new[argc_new])
+          argc_new++;
+
+        assert(argv_new[0] != argv[0]);
+        assert(!*pPidSpawned);
+
+        *ppapszArgvToSpawn = NULL;
+        rc = kmk_builtin_command_parsed(argc_new, argv_new, ppapszArgvToSpawn, pPidSpawned);
+
+        free(argv_new[0]);
+        free(argv_new);
+    }
+
+    return rc;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin.h	(revision 1780)
@@ -0,0 +1,57 @@
+/* $Id$ */
+/** @file
+ *
+ * kMk Builtin command handling.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifdef _MSC_VER
+# ifndef pid_t /* see config.h.win */
+#  define pid_t int
+# endif
+#else
+# include <sys/types.h>
+#endif
+
+int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
+int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
+
+extern int kmk_builtin_append(int argc, char **argv, char **envp);
+extern int kmk_builtin_cp(int argc, char **argv, char **envp);
+extern int kmk_builtin_cat(int argc, char **argv, char **envp);
+extern int kmk_builtin_chmod(int argc, char **argv, char **envp);
+extern int kmk_builtin_cmp(int argc, char **argv, char **envp);
+extern int kmk_builtin_echo(int argc, char **argv, char **envp);
+extern int kmk_builtin_expr(int argc, char **argv, char **envp);
+extern int kmk_builtin_install(int argc, char **argv, char **envp);
+extern int kmk_builtin_ln(int argc, char **argv, char **envp);
+extern int kmk_builtin_md5sum(int argc, char **argv, char **envp);
+extern int kmk_builtin_mkdir(int argc, char **argv, char **envp);
+extern int kmk_builtin_mv(int argc, char **argv, char **envp);
+extern int kmk_builtin_printf(int argc, char **argv, char **envp);
+extern int kmk_builtin_rm(int argc, char **argv, char **envp);
+extern int kmk_builtin_rmdir(int argc, char **argv, char **envp);
+extern int kmk_builtin_test(int argc, char **argv, char **envp, char ***ppapszArgvSpawn);
+extern int kmk_builtin_kDepIDB(int argc, char **argv, char **envp);
+
+extern int kbuild_version(const char *argv0);
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/append.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/append.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/append.c	(revision 1780)
@@ -0,0 +1,242 @@
+/* $Id$ */
+/** @file
+ *
+ * kMk Builtin command - append text to file.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "err.h"
+#include "kmkbuiltin.h"
+#ifndef kmk_builtin_append
+# include "make.h"
+# include "filedef.h"
+# include "variable.h"
+#endif
+
+
+/**
+ * Prints the usage and return 1.
+ */
+static int usage(FILE *pf)
+{
+    fprintf(pf,
+            "usage: %s [-dcntv] file [string ...]\n"
+            "   or: %s --version\n"
+            "   or: %s --help\n"
+            "\n"
+            "Options:\n"
+            "  -d  Enclose the output in define ... endef, taking the name from\n"
+            "      the first argument following the file name.\n"
+            "  -c  Output the command for specified target(s). [builtin only]\n"
+            "  -n  Insert a new line between the strings.\n"
+            "  -t  Truncate the file instead of appending\n"
+            "  -v  Output the value(s) for specified variable(s). [builtin only]\n"
+            ,
+            g_progname, g_progname, g_progname);
+    return 1;
+}
+
+
+/**
+ * Appends text to a textfile, creating the textfile if necessary.
+ */
+int kmk_builtin_append(int argc, char **argv, char **envp)
+{
+    int i;
+    int fFirst;
+    int iFile;
+    FILE *pFile;
+    int fNewLine = 0;
+    int fTruncate = 0;
+    int fDefine = 0;
+    int fVariables = 0;
+    int fCommands = 0;
+
+    g_progname = argv[0];
+
+    /*
+     * Parse options.
+     */
+    i = 1;
+    while (i < argc
+       &&  argv[i][0] == '-'
+       &&  argv[i][1] != '\0' /* '-' is a file */
+       &&  strchr("-cdntv", argv[i][1]) /* valid option char */
+       )
+    {
+        char *psz = &argv[i][1];
+        if (*psz != '-')
+        {
+            do
+            {
+                switch (*psz)
+                {
+                    case 'c':
+                        if (fVariables)
+                        {
+                            errx(1, "Option '-c' clashes with '-v'.");
+                            return usage(stderr);
+                        }
+#ifndef kmk_builtin_append
+                        fCommands = 1;
+                        break;
+#else
+                        errx(1, "Option '-c' isn't supported in external mode.");
+                        return usage(stderr);
+#endif
+                    case 'd':
+                        if (fVariables)
+                        {
+                            errx(1, "Option '-d' must come before '-v'!");
+                            return usage(stderr);
+                        }
+                        fDefine = 1;
+                        break;
+                    case 'n':
+                        fNewLine = 1;
+                        break;
+                    case 't':
+                        fTruncate = 1;
+                        break;
+                    case 'v':
+                        if (fCommands)
+                        {
+                            errx(1, "Option '-v' clashes with '-c'.");
+                            return usage(stderr);
+                        }
+#ifndef kmk_builtin_append
+                        fVariables = 1;
+                        break;
+#else
+                        errx(1, "Option '-v' isn't supported in external mode.");
+                        return usage(stderr);
+#endif
+                    default:
+                        errx(1, "Invalid option '%c'! (%s)", *psz, argv[i]);
+                        return usage(stderr);
+                }
+            } while (*++psz);
+        }
+        else if (!strcmp(psz, "-help"))
+        {
+            usage(stdout);
+            return 0;
+        }
+        else if (!strcmp(psz, "-version"))
+            return kbuild_version(argv[0]);
+        else
+            break;
+        i++;
+    }
+
+    if (i + fDefine >= argc)
+    {
+        if (i <= argc)
+            errx(1, "missing filename!");
+        else
+            errx(1, "missing define name!");
+        return usage(stderr);
+    }
+
+    /*
+     * Open the output file.
+     */
+    iFile = i;
+    pFile = fopen(argv[i], fTruncate ? "w" : "a");
+    if (!pFile)
+        return err(1, "failed to open '%s'.", argv[i]);
+
+    /*
+     * Start define?
+     */
+    if (fDefine)
+    {
+        i++;
+        fprintf(pFile, "define %s\n", argv[i]);
+    }
+
+    /*
+     * Append the argument strings to the file
+     */
+    fFirst = 1;
+    for (i++; i < argc; i++)
+    {
+        const char *psz = argv[i];
+        size_t cch = strlen(psz);
+        if (!fFirst)
+            fputc(fNewLine ? '\n' : ' ', pFile);
+#ifndef kmk_builtin_append
+        if (fCommands)
+        {
+            char *pszOldBuf;
+            unsigned cchOldBuf;
+            char *pchEnd;
+
+            install_variable_buffer(&pszOldBuf, &cchOldBuf);
+
+            pchEnd = func_commands(variable_buffer, &argv[i], "commands");
+            fwrite(variable_buffer, 1, pchEnd - variable_buffer, pFile);
+
+            restore_variable_buffer(pszOldBuf, cchOldBuf);
+        }
+        else if (fVariables)
+        {
+            struct variable *pVar = lookup_variable(psz, cch);
+            if (!pVar)
+                continue;
+            if (    pVar->recursive
+                &&  memchr(pVar->value, '$', pVar->value_length))
+            {
+                char *pszExpanded = allocated_variable_expand(pVar->value);
+                fwrite(pszExpanded, 1, strlen(pszExpanded), pFile);
+                free(pszExpanded);
+            }
+            else
+                fwrite(pVar->value, 1, pVar->value_length, pFile);
+        }
+        else
+#endif
+            fwrite(psz, 1, cch, pFile);
+        fFirst = 0;
+    }
+
+    /* 
+     * Add the newline, closing the define if needed, and close the file.
+     */
+    if (    (  fDefine
+             ? fwrite(fFirst ?        "endef\n"      :        "\nendef\n", 
+                      1, 
+                      fFirst ? sizeof("endef\n") - 1 : sizeof("\nendef\n") - 1, 
+                      pFile) < sizeof("endef\n")
+             : fputc('\n', pFile) == EOF)
+        ||  ferror(pFile))
+    {
+        fclose(pFile);
+        return errx(1, "error writing to '%s'!", argv[iFile]);
+    }
+    if (fclose(pFile))
+        return err(1, "failed to fclose '%s'!", argv[iFile]);
+    return 0;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cat.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cat.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cat.c	(revision 1780)
@@ -0,0 +1,368 @@
+/*-
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kevin Fall.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cat.c	8.2 (Berkeley) 4/27/95";
+#endif
+#endif /* not lint */
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/cat/cat.c,v 1.32 2005/01/10 08:39:20 imp Exp $");
+#else
+#define NO_UDOM_SUPPORT /* kmk */
+#endif
+
+#ifndef _MSC_VER
+# include <sys/param.h>
+#endif
+#include <sys/stat.h>
+#ifndef NO_UDOM_SUPPORT
+# include <sys/socket.h>
+# include <sys/un.h>
+# include <errno.h>
+#endif
+
+#include <ctype.h>
+#include "err.h"
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stddef.h>
+#include "getopt.h"
+#ifdef __sun__
+# include "solfakes.h"
+#endif
+#ifdef _MSC_VER
+# include "mscfakes.h"
+#endif
+#include "kmkbuiltin.h"
+
+
+int bflag, eflag, nflag, sflag, tflag, vflag;
+/*int rval;*/
+const char *filename;
+
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { 0, 0,	0, 0 },
+};
+
+
+static int usage(FILE *);
+static int scanfiles(char *argv[], int cooked);
+static int cook_cat(FILE *);
+static int raw_cat(int);
+
+#ifndef NO_UDOM_SUPPORT
+static int udom_open(const char *path, int flags);
+#endif
+
+int
+kmk_builtin_cat(int argc, char *argv[], char **envp)
+{
+	int ch, rc;
+
+	/* kmk: reinitialize globals */
+	bflag = eflag = nflag = sflag = tflag = vflag = 0;
+	filename = NULL;
+
+	/* kmk: reset getopt and set progname */
+	g_progname = argv[0];
+	opterr = 1;
+	optarg = NULL;
+	optopt = 0;
+	optind = 0; /* init */
+
+#ifdef kmk_builtin_cat /* kmk did this already. */
+	setlocale(LC_CTYPE, "");
+#endif
+
+	while ((ch = getopt_long(argc, argv, "benstuv", long_options, NULL)) != -1)
+		switch (ch) {
+		case 'b':
+			bflag = nflag = 1;	/* -b implies -n */
+			break;
+		case 'e':
+			eflag = vflag = 1;	/* -e implies -v */
+			break;
+		case 'n':
+			nflag = 1;
+			break;
+		case 's':
+			sflag = 1;
+			break;
+		case 't':
+			tflag = vflag = 1;	/* -t implies -v */
+			break;
+		case 'u':
+			setbuf(stdout, NULL);
+			break;
+		case 'v':
+			vflag = 1;
+			break;
+		case 261:
+			usage(stdout);
+			return 0;
+		case 262:
+			return kbuild_version(argv[0]);
+		default:
+			return usage(stderr);
+		}
+	argv += optind;
+
+	if (bflag || eflag || nflag || sflag || tflag || vflag)
+		rc = scanfiles(argv, 1);
+	else
+		rc = scanfiles(argv, 0);
+#ifdef kmk_builtin_cat /* only in the external program. */
+	if (fclose(stdout))
+		return err(1, "stdout");
+#endif
+	return rc;
+}
+
+static int
+usage(FILE *fp)
+{
+	fprintf(fp, "usage: %s [-benstuv] [file ...]\n"
+	            "   or: %s --help\n"
+	            "   or: %s --version\n",
+	        g_progname, g_progname, g_progname);
+	return 1;
+}
+
+static int
+scanfiles(char *argv[], int cooked)
+{
+	int i = 0;
+	char *path;
+	FILE *fp;
+	int rc2 = 0;
+	int rc = 0;
+
+	while ((path = argv[i]) != NULL || i == 0) {
+		int fd;
+
+		if (path == NULL || strcmp(path, "-") == 0) {
+			filename = "stdin";
+			fd = STDIN_FILENO;
+		} else {
+			filename = path;
+			fd = open(path, O_RDONLY);
+#ifndef NO_UDOM_SUPPORT
+			if (fd < 0 && errno == EOPNOTSUPP)
+				fd = udom_open(path, O_RDONLY);
+#endif
+		}
+		if (fd < 0) {
+			warn("%s", path);
+			rc2 = 1; /* non fatal */
+		} else if (cooked) {
+			if (fd == STDIN_FILENO)
+				rc = cook_cat(stdin);
+			else {
+				fp = fdopen(fd, "r");
+				rc = cook_cat(fp);
+				fclose(fp);
+			}
+		} else {
+			rc = raw_cat(fd);
+			if (fd != STDIN_FILENO)
+				close(fd);
+		}
+		if (rc || path == NULL)
+			break;
+		++i;
+	}
+	return !rc ? rc2 : rc;
+}
+
+static int
+cook_cat(FILE *fp)
+{
+	int ch, gobble, line, prev;
+	int rc = 0;
+
+	/* Reset EOF condition on stdin. */
+	if (fp == stdin && feof(stdin))
+		clearerr(stdin);
+
+	line = gobble = 0;
+	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
+		if (prev == '\n') {
+			if (sflag) {
+				if (ch == '\n') {
+					if (gobble)
+						continue;
+					gobble = 1;
+				} else
+					gobble = 0;
+			}
+			if (nflag && (!bflag || ch != '\n')) {
+				(void)fprintf(stdout, "%6d\t", ++line);
+				if (ferror(stdout))
+					break;
+			}
+		}
+		if (ch == '\n') {
+			if (eflag && putchar('$') == EOF)
+				break;
+		} else if (ch == '\t') {
+			if (tflag) {
+				if (putchar('^') == EOF || putchar('I') == EOF)
+					break;
+				continue;
+			}
+		} else if (vflag) {
+			if (!isascii(ch) && !isprint(ch)) {
+				if (putchar('M') == EOF || putchar('-') == EOF)
+					break;
+				ch = toascii(ch);
+			}
+			if (iscntrl(ch)) {
+				if (putchar('^') == EOF ||
+				    putchar(ch == '\177' ? '?' :
+				    ch | 0100) == EOF)
+					break;
+				continue;
+			}
+		}
+		if (putchar(ch) == EOF)
+			break;
+	}
+	if (ferror(fp)) {
+		warn("%s", filename);
+		rc = 1;
+		clearerr(fp);
+	}
+	if (ferror(stdout))
+		return err(1, "stdout");
+	return rc;
+}
+
+static int
+raw_cat(int rfd)
+{
+	int off, wfd;
+	ssize_t nr, nw;
+	static size_t bsize;
+	static char *buf = NULL;
+	struct stat sbuf;
+
+	wfd = fileno(stdout);
+	if (buf == NULL) {
+		if (fstat(wfd, &sbuf))
+			return err(1, "%s", filename);
+#ifdef _MSC_VER
+		bsize = 1024;
+#else
+		bsize = MAX(sbuf.st_blksize, 1024);
+#endif
+		if ((buf = malloc(bsize)) == NULL)
+			return err(1, "buffer");
+	}
+	while ((nr = read(rfd, buf, bsize)) > 0)
+		for (off = 0; nr; nr -= nw, off += nw)
+			if ((nw = write(wfd, buf + off, (size_t)nr)) < 0)
+				return err(1, "stdout");
+	if (nr < 0) {
+		warn("%s", filename);
+		return 1;
+	}
+	return 0;
+}
+
+#ifndef NO_UDOM_SUPPORT
+
+static int
+udom_open(const char *path, int flags)
+{
+	struct sockaddr_un sou;
+	int fd;
+	unsigned int len;
+
+	bzero(&sou, sizeof(sou));
+
+	/*
+	 * Construct the unix domain socket address and attempt to connect
+	 */
+	fd = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (fd >= 0) {
+		sou.sun_family = AF_UNIX;
+		if ((len = strlcpy(sou.sun_path, path,
+		    sizeof(sou.sun_path))) >= sizeof(sou.sun_path)) {
+			errno = ENAMETOOLONG;
+			return (-1);
+		}
+		len = offsetof(struct sockaddr_un, sun_path[len+1]);
+
+		if (connect(fd, (void *)&sou, len) < 0) {
+			close(fd);
+			fd = -1;
+		}
+	}
+
+	/*
+	 * handle the open flags by shutting down appropriate directions
+	 */
+	if (fd >= 0) {
+		switch(flags & O_ACCMODE) {
+		case O_RDONLY:
+			if (shutdown(fd, SHUT_WR) == -1)
+				warn(NULL);
+			break;
+		case O_WRONLY:
+			if (shutdown(fd, SHUT_RD) == -1)
+				warn(NULL);
+			break;
+		default:
+			break;
+		}
+	}
+	return(fd);
+}
+
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/chmod.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/chmod.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/chmod.c	(revision 1780)
@@ -0,0 +1,263 @@
+/*-
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1989, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)chmod.c	8.8 (Berkeley) 4/1/94";
+#endif /* not lint */
+#endif
+/*#include <sys/cdefs.h> */
+/*__FBSDID("$FreeBSD: src/bin/chmod/chmod.c,v 1.33 2005/01/10 08:39:20 imp Exp $");*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "err.h"
+#include <errno.h>
+#include <fts.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _MSC_VER
+# include <unistd.h>
+#else
+# include "mscfakes.h"
+#endif
+#ifdef __sun__
+# include "solfakes.h"
+#endif
+#include "getopt.h"
+#include "kmkbuiltin.h"
+
+extern void * bsd_setmode(const char *p);
+extern mode_t bsd_getmode(const void *bbox, mode_t omode);
+extern void bsd_strmode(mode_t mode, char *p);
+
+#if defined(__APPLE__) && !defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)
+extern int lchmod(const char *, mode_t);
+#endif
+
+static int usage(FILE *);
+
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { 0, 0,	0, 0 },
+};
+
+
+int
+kmk_builtin_chmod(int argc, char *argv[], char **envp)
+{
+	FTS *ftsp;
+	FTSENT *p;
+	mode_t *set;
+	int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval;
+	int vflag;
+	char *mode;
+	mode_t newmode;
+	int (*change_mode)(const char *, mode_t);
+
+	/* kmk: reset getopt and set progname */
+	g_progname = argv[0];
+	opterr = 1;
+	optarg = NULL;
+	optopt = 0;
+	optind = 0; /* init */
+
+	set = NULL;
+	Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
+	while ((ch = getopt_long(argc, argv, "HLPRXfghorstuvwx", long_options, NULL)) != -1)
+		switch (ch) {
+		case 'H':
+			Hflag = 1;
+			Lflag = 0;
+			break;
+		case 'L':
+			Lflag = 1;
+			Hflag = 0;
+			break;
+		case 'P':
+			Hflag = Lflag = 0;
+			break;
+		case 'R':
+			Rflag = 1;
+			break;
+		case 'f':
+			fflag = 1;
+			break;
+		case 'h':
+			/*
+			 * In System V (and probably POSIX.2) the -h option
+			 * causes chmod to change the mode of the symbolic
+			 * link.  4.4BSD's symbolic links didn't have modes,
+			 * so it was an undocumented noop.  In FreeBSD 3.0,
+			 * lchmod(2) is introduced and this option does real
+			 * work.
+			 */
+			hflag = 1;
+			break;
+		/*
+		 * XXX
+		 * "-[rwx]" are valid mode commands.  If they are the entire
+		 * argument, getopt has moved past them, so decrement optind.
+		 * Regardless, we're done argument processing.
+		 */
+		case 'g': case 'o': case 'r': case 's':
+		case 't': case 'u': case 'w': case 'X': case 'x':
+			if (argv[optind - 1][0] == '-' &&
+			    argv[optind - 1][1] == ch &&
+			    argv[optind - 1][2] == '\0')
+				--optind;
+			goto done;
+		case 'v':
+			vflag++;
+			break;
+		case 261:
+			usage(stdout);
+			return 0;
+		case 262:
+			return kbuild_version(argv[0]);
+		case '?':
+		default:
+			return usage(stderr);
+		}
+done:	argv += optind;
+	argc -= optind;
+
+	if (argc < 2)
+		return usage(stderr);
+
+	if (Rflag) {
+		fts_options = FTS_PHYSICAL;
+		if (hflag)
+			return errx(1,
+		"the -R and -h options may not be specified together.");
+		if (Hflag)
+			fts_options |= FTS_COMFOLLOW;
+		if (Lflag) {
+			fts_options &= ~FTS_PHYSICAL;
+			fts_options |= FTS_LOGICAL;
+		}
+	} else
+		fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
+
+	if (hflag)
+		change_mode = lchmod;
+	else
+		change_mode = chmod;
+
+	mode = *argv;
+	if ((set = bsd_setmode(mode)) == NULL)
+		return errx(1, "invalid file mode: %s", mode);
+
+	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
+		return err(1, "fts_open");
+	for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
+		switch (p->fts_info) {
+		case FTS_D:			/* Change it at FTS_DP. */
+			if (!Rflag)
+				fts_set(ftsp, p, FTS_SKIP);
+			continue;
+		case FTS_DNR:			/* Warn, chmod, continue. */
+			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+			rval = 1;
+			break;
+		case FTS_ERR:			/* Warn, continue. */
+		case FTS_NS:
+			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+			rval = 1;
+			continue;
+		case FTS_SL:			/* Ignore. */
+		case FTS_SLNONE:
+			/*
+			 * The only symlinks that end up here are ones that
+			 * don't point to anything and ones that we found
+			 * doing a physical walk.
+			 */
+			if (!hflag)
+				continue;
+			/* else */
+			/* FALLTHROUGH */
+		default:
+			break;
+		}
+		newmode = bsd_getmode(set, p->fts_statp->st_mode);
+		if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
+			continue;
+		if ((*change_mode)(p->fts_accpath, newmode) && !fflag) {
+			warn("%s", p->fts_path);
+			rval = 1;
+		} else {
+			if (vflag) {
+				(void)printf("%s", p->fts_path);
+
+				if (vflag > 1) {
+					char m1[12], m2[12];
+
+					bsd_strmode(p->fts_statp->st_mode, m1);
+					bsd_strmode((p->fts_statp->st_mode &
+					    S_IFMT) | newmode, m2);
+
+					(void)printf(": 0%o [%s] -> 0%o [%s]",
+					    p->fts_statp->st_mode, m1,
+					    (p->fts_statp->st_mode & S_IFMT) |
+					    newmode, m2);
+				}
+				(void)printf("\n");
+			}
+
+		}
+	}
+	if (errno)
+		rval = err(1, "fts_read");
+	free(set);
+	fts_close(ftsp);
+	return rval;
+}
+
+int
+usage(FILE *out)
+{
+	(void)fprintf(out,
+	    "usage: %s [-fhv] [-R [-H | -L | -P]] mode file ...\n"
+	    "   or: %s --version\n"
+	    "   or: %s --help\n",
+	    g_progname, g_progname, g_progname);
+
+	return 1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp.c	(revision 1780)
@@ -0,0 +1,141 @@
+/*	$NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $	*/
+
+/*
+ * Copyright (c) 1987, 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*__COPYRIGHT("@(#) Copyright (c) 1987, 1990, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n");
+static char sccsid[] = "@(#)cmp.c	8.3 (Berkeley) 4/2/94";
+__RCSID("$NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $"); */
+
+#include <sys/types.h>
+#include "err.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#ifndef _MSC_VER
+# include <unistd.h>
+#else
+# define MSC_DO_64_BIT_IO /* for correct off_t */
+# include "mscfakes.h"
+#endif
+#include "getopt.h"
+#include "kmkbuiltin.h"
+#include "cmp_extern.h"
+
+
+static const struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { 0, 0,	0, 0 },
+};
+
+
+static int usage(FILE *);
+
+int
+kmk_builtin_cmp(int argc, char *argv[], char **envp)
+{
+    off_t skip1 = 0, skip2 = 0;
+    int lflag = 0, sflag = 0;
+    int ch;
+    char *file1, *file2;
+
+#ifdef kmk_builtin_cmp
+    setlocale(LC_ALL, "");
+#endif
+
+    /* reset getopt and set progname. */
+    g_progname = argv[0];
+    opterr = 1;
+    optarg = NULL;
+    optopt = 0;
+    optind = 0; /* init */
+
+    while ((ch = getopt_long(argc, argv, "ls", long_options, NULL)) != -1)
+    {
+        switch (ch)
+        {
+            case 'l':		/* print all differences */
+                lflag = 1;
+                break;
+            case 's':		/* silent run */
+                sflag = 1;
+                break;
+            case 261:
+                usage(stdout);
+                return 0;
+            case 262:
+                return kbuild_version(argv[0]);
+            case '?':
+            default:
+                return usage(stderr);
+        }
+    }
+    argv += optind;
+    argc -= optind;
+
+    if (argc < 2 || argc > 4)
+        return usage(stderr);
+
+    file1 = argv[0];
+    file2 = argv[1];
+
+    if (argc > 2)
+    {
+        char *ep;
+
+        errno = 0;
+        skip1 = strtoll(argv[2], &ep, 0);
+        if (errno || ep == argv[2])
+            return errx(ERR_EXIT, "strtoll(%s,,) failed", argv[2]);
+
+        if (argc == 4)
+        {
+            skip2 = strtoll(argv[3], &ep, 0);
+            if (errno || ep == argv[3])
+                return errx(ERR_EXIT, "strtoll(%s,,) failed", argv[3]);
+	}
+    }
+
+    return cmp_file_and_file_ex(file1, skip1, file2, skip2, sflag, lflag, 0);
+}
+
+static int
+usage(FILE *fp)
+{
+    fprintf(fp, "usage: %s [-l | -s] file1 file2 [skip1 [skip2]]\n"
+                "   or: %s --help\n"
+                "   or: %s --version\n",
+            g_progname, g_progname, g_progname);
+    return ERR_EXIT;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp_extern.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp_extern.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp_extern.h	(revision 1780)
@@ -0,0 +1,49 @@
+/*	$NetBSD: extern.h,v 1.7 2007/08/21 14:09:53 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)extern.h	8.3 (Berkeley) 4/2/94
+ */
+
+#define OK_EXIT		0
+#define DIFF_EXIT	1
+#define ERR_EXIT	2	/* error exit code */
+
+int cmp_file_and_file(const char *file1, const char *file2, int sflag, int lflag, int special);
+int cmp_file_and_file_ex(const char *file1, off_t skip1, 
+                         const char *file2, off_t skip2, int sflag, int lflag, int special);
+int cmp_fd_and_file(int fd1, const char *file1,
+                    const char *file2, int sflag, int lflag, int special);
+int cmp_fd_and_file_ex(int fd1, const char *file1, off_t skip1,
+                       const char *file2, off_t skip2, int sflag, int lflag, int special);
+int cmp_fd_and_fd(int fd1, const char *file1, 
+                  int fd2, const char *file2, int sflag, int lflag, int special);
+int cmp_fd_and_fd_ex(int fd1, const char *file1, off_t skip1,
+                     int fd2, const char *file2, off_t skip2,  int sflag, int lflag, int special);
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp_util.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp_util.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cmp_util.c	(revision 1780)
@@ -0,0 +1,559 @@
+/*	$NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $	*/
+/*	$NetBSD: misc.c,v 1.11 2007/08/22 16:59:19 christos Exp $	*/
+/*	$NetBSD: regular.c,v 1.20 2006/06/03 21:47:55 christos Exp $	*/
+/*	$NetBSD: special.c,v 1.12 2007/08/21 14:09:54 christos Exp $	*/
+
+/*
+ * Copyright (c) 1987, 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*__COPYRIGHT("@(#) Copyright (c) 1987, 1990, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n");*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(__FreeBSD__) || defined(__NetBSD__) /** @todo more mmap capable OSes. */
+# define CMP_USE_MMAP
+# include <sys/param.h>
+# include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _MSC_VER
+# include <unistd.h>
+# ifndef O_BINARY
+#  define O_BINARY 0
+# endif
+#else
+# define MSC_DO_64_BIT_IO
+# include "mscfakes.h"
+#endif
+#include "err.h"
+
+#include "cmp_extern.h"
+
+
+static int
+errmsg(const char *file, off_t byte, off_t line, int lflag)
+{
+    if (lflag)
+#ifdef _MSC_VER
+        return err(ERR_EXIT, "%s: char %I64d, line %lld", file, (__int64)byte, (long long)line);
+#else
+        return err(ERR_EXIT, "%s: char %lld, line %lld", file, (long long)byte, (long long)line);
+#endif
+    return err(ERR_EXIT, "%s", file);
+}
+
+
+static int
+eofmsg(const char *file, off_t byte, off_t line, int sflag, int lflag)
+{
+    if (!sflag)
+    {
+        if (!lflag)
+            warnx("EOF on %s", file);
+        else
+        {
+#ifdef _MSC_VER
+            if (line > 0)
+                warnx("EOF on %s: char %I64d, line %I64d", file, (__int64)byte, (__int64)line);
+            else
+                warnx("EOF on %s: char %I64d", file, (__int64)byte);
+#else
+            if (line > 0)
+                warnx("EOF on %s: char %lld, line %lld", file, (long long)byte, (long long)line);
+            else
+                warnx("EOF on %s: char %lld", file, (long long)byte);
+#endif
+        }
+    }
+    return DIFF_EXIT;
+}
+
+
+static int
+diffmsg(const char *file1, const char *file2, off_t byte, off_t line, int sflag)
+{
+    if (!sflag)
+#ifdef _MSC_VER
+        printf("%s %s differ: char %I64d, line %I64d\n",
+               file1, file2, (__int64)byte, (__int64)line);
+#else
+        printf("%s %s differ: char %lld, line %lld\n",
+               file1, file2, (long long)byte, (long long)line);
+#endif
+    return DIFF_EXIT;
+}
+
+
+/**
+ * Compares two files, where one or both are non-regular ones.
+ */
+static int
+c_special(int fd1, const char *file1, off_t skip1,
+          int fd2, const char *file2, off_t skip2,
+          int lflag, int sflag)
+{
+    int fd1dup, fd2dup;
+    FILE *fp1;
+    int rc;
+
+    /* duplicate because fdopen+fclose will otherwise close the handle. */
+    fd1dup = dup(fd1);
+    if (fd1 < 0)
+        return err(ERR_EXIT, "%s", file1);
+    fp1 = fdopen(fd1dup, "rb");
+    if (!fp1)
+        fp1 = fdopen(fd1dup, "r");
+    if (!fp1)
+    {
+        err(ERR_EXIT, "%s", file1);
+        close(fd1dup);
+        return ERR_EXIT;
+    }
+
+    fd2dup = dup(fd2);
+    if (fd2dup >= 0)
+    {
+        FILE *fp2 = fdopen(fd2dup, "rb");
+        if (!fp2)
+            fp2 = fdopen(fd2dup, "r");
+        if (fp2)
+        {
+            off_t byte;
+            off_t line;
+            int ch1 = 0;
+            int ch2 = 0;
+
+            /* skipping ahead */
+            rc = OK_EXIT;
+            for (byte = line = 1; skip1--; byte++)
+            {
+                ch1 = getc(fp1);
+                if (ch1 == EOF)
+                    break;
+                if (ch1 == '\n')
+                    line++;
+            }
+            for (byte = line = 1; skip2--; byte++)
+            {
+                ch2 = getc(fp2);
+                if (ch2 == EOF)
+                    break;
+                if (ch2 == '\n')
+                    line++;
+            }
+            if (ch2 != EOF && ch1 != EOF)
+            {
+                /* compare byte by byte */
+                for (byte = line = 1;; ++byte)
+                {
+                    ch1 = getc(fp1);
+                    ch2 = getc(fp2);
+                    if (ch1 == EOF || ch2 == EOF)
+                        break;
+                    if (ch1 != ch2)
+                    {
+                        if (!lflag)
+                        {
+                            rc = diffmsg(file1, file2, byte, line, sflag);
+                            break;
+                        }
+                        rc = DIFF_EXIT;
+#ifdef _MSC_VER
+                        printf("%6i64d %3o %3o\n", (__int64)byte, ch1, ch2);
+#else
+                        printf("%6lld %3o %3o\n", (long long)byte, ch1, ch2);
+#endif
+                    }
+                    if (ch1 == '\n')
+                        ++line;
+                }
+            }
+
+            /* Check for errors and length differences (EOF). */
+            if (ferror(fp1) && rc != ERR_EXIT)
+                rc = errmsg(file1, byte, line, lflag);
+            if (ferror(fp2) && rc != ERR_EXIT)
+                rc = errmsg(file2, byte, line, lflag);
+            if (rc == OK_EXIT)
+            {
+                if (feof(fp1))
+                {
+                    if (!feof(fp2))
+                        rc = eofmsg(file1, byte, line, sflag, lflag);
+                }
+                else if (feof(fp2))
+                    rc = eofmsg(file2, byte, line, sflag, lflag);
+            }
+
+            fclose(fp2);
+        }
+        else
+        {
+            rc = err(ERR_EXIT, "%s", file2);
+            close(fd2dup);
+        }
+    }
+    else
+        rc = err(ERR_EXIT, "%s", file2);
+
+    fclose(fp1);
+    return rc;
+}
+
+
+#ifdef CMP_USE_MMAP
+/**
+ * Compare two files using mmap.
+ */
+static int
+c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
+          int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag)
+{
+    unsigned char ch, *p1, *p2, *b1, *b2;
+    off_t byte, length, line;
+    int dfound;
+    size_t blk_sz, blk_cnt;
+
+    if (sflag && len1 != len2)
+        return DIFF_EXIT;
+
+    if (skip1 > len1)
+        return eofmsg(file1, len1 + 1, 0, sflag, lflag);
+    len1 -= skip1;
+    if (skip2 > len2)
+        return eofmsg(file2, len2 + 1, 0, sflag, lflag);
+    len2 -= skip2;
+
+    byte = line = 1;
+    dfound = 0;
+    length = len1 <= len2 ? len1 : len2;
+    for (blk_sz = 1024 * 1024; length != 0; length -= blk_sz)
+    {
+        if (blk_sz > length)
+            blk_sz = length;
+        b1 = p1 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd1, skip1);
+        if (p1 == MAP_FAILED)
+            goto l_mmap_failed;
+
+        b2 = p2 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd2, skip2);
+        if (p2 == MAP_FAILED)
+        {
+            munmap(p1, blk_sz);
+            goto l_mmap_failed;
+        }
+
+        blk_cnt = blk_sz;
+        for (; blk_cnt--; ++p1, ++p2, ++byte)
+        {
+            if ((ch = *p1) != *p2)
+            {
+                if (!lflag)
+                {
+                    munmap(b1, blk_sz);
+                    munmap(b2, blk_sz);
+                    return diffmsg(file1, file2, byte, line, sflag);
+                }
+                dfound = 1;
+#ifdef _MSC_VER
+                printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2);
+#else
+                printf("%6lld %3o %3o\n", (long long)byte, ch, *p2);
+#endif
+            }
+            if (ch == '\n')
+                ++line;
+        }
+        munmap(p1 - blk_sz, blk_sz);
+        munmap(p2 - blk_sz, blk_sz);
+        skip1 += blk_sz;
+        skip2 += blk_sz;
+    }
+
+    if (len1 != len2)
+        return eofmsg(len1 > len2 ? file2 : file1, byte, line, sflag, lflag);
+    if (dfound)
+        return DIFF_EXIT;
+    return OK_EXIT;
+
+l_mmap_failed:
+    return c_special(fd1, file1, skip1, fd2, file2, skip2, lflag, sflag);
+}
+
+#else /* non-mmap c_regular: */
+
+/**
+ * Compare two files without mmaping them.
+ */
+static int
+c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
+          int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag)
+{
+    unsigned char ch, *p1, *p2, *b1 = 0, *b2 = 0;
+    off_t byte, length, line, bytes_read;
+    int dfound;
+    size_t blk_sz, blk_cnt;
+
+    if (sflag && len1 != len2)
+        return DIFF_EXIT;
+
+    if (skip1 > len1)
+        return eofmsg(file1, len1 + 1, 0, sflag, lflag);
+    len1 -= skip1;
+    if (skip2 > len2)
+        return eofmsg(file2, len2 + 1, 0, sflag, lflag);
+    len2 -= skip2;
+
+    if (skip1 && lseek(fd1, skip1, SEEK_SET) < 0)
+        goto l_special;
+    if (skip2 && lseek(fd2, skip2, SEEK_SET) < 0)
+    {
+        if (skip1 && lseek(fd1, 0, SEEK_SET) < 0)
+            return err(1, "seek failed");
+        goto l_special;
+    }
+
+#define CMP_BUF_SIZE (128*1024)
+
+    b1 = malloc(CMP_BUF_SIZE);
+    b2 = malloc(CMP_BUF_SIZE);
+    if (!b1 || !b2)
+        goto l_malloc_failed;
+
+    byte = line = 1;
+    dfound = 0;
+    length = len1;
+    if (length > len2)
+        length = len2;
+    for (blk_sz = CMP_BUF_SIZE; length != 0; length -= blk_sz)
+    {
+        if ((off_t)blk_sz > length)
+            blk_sz = length;
+
+        bytes_read = read(fd1, b1, blk_sz);
+        if (bytes_read != blk_sz)
+            goto l_read_error;
+
+        bytes_read = read(fd2, b2, blk_sz);
+        if (bytes_read != blk_sz)
+            goto l_read_error;
+
+        blk_cnt = blk_sz;
+        p1 = b1;
+        p2 = b2;
+        for (; blk_cnt--; ++p1, ++p2, ++byte)
+        {
+            if ((ch = *p1) != *p2)
+            {
+                if (!lflag)
+                {
+                    free(b1);
+                    free(b2);
+                    return diffmsg(file1, file2, byte, line, sflag);
+                }
+                dfound = 1;
+#ifdef _MSC_VER
+                printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2);
+#else
+                printf("%6lld %3o %3o\n", (long long)byte, ch, *p2);
+#endif
+            }
+            if (ch == '\n')
+                ++line;
+        }
+        skip1 += blk_sz;
+        skip2 += blk_sz;
+    }
+
+    if (len1 != len2)
+        return eofmsg(len1 > len2 ? file2 : file1, byte, line, sflag, lflag);
+    if (dfound)
+        return DIFF_EXIT;
+    return OK_EXIT;
+
+l_read_error:
+    if (    lseek(fd1, 0, SEEK_SET) < 0
+        ||  lseek(fd2, 0, SEEK_SET) < 0)
+    {
+        err(1, "seek failed");
+        free(b1);
+        free(b2);
+        return 1;
+    }
+l_malloc_failed:
+    free(b1);
+    free(b2);
+l_special:
+    return c_special(fd1, file1, skip1, fd2, file2, skip2, lflag, sflag);
+}
+#endif  /* non-mmap c_regular */
+
+
+/**
+ * Compares two open files.
+ */
+int
+cmp_fd_and_fd_ex(int fd1, const char *file1, off_t skip1,
+                 int fd2, const char *file2, off_t skip2,
+                 int sflag, int lflag, int special)
+{
+    struct stat st1, st2;
+    int rc;
+
+    if (fstat(fd1, &st1))
+        return err(ERR_EXIT, "%s", file1);
+    if (fstat(fd2, &st2))
+        return err(ERR_EXIT, "%s", file2);
+
+    if (    !S_ISREG(st1.st_mode)
+        ||  !S_ISREG(st2.st_mode)
+        ||  special)
+        rc = c_special(fd1, file1, skip1,
+                       fd2, file2, skip2, sflag, lflag);
+    else
+        rc = c_regular(fd1, file1, skip1, st1.st_size,
+                       fd2, file2, skip2, st2.st_size, sflag, lflag);
+    return rc;
+}
+
+
+/**
+ * Compares two open files.
+ */
+int
+cmp_fd_and_fd(int fd1, const char *file1,
+              int fd2, const char *file2,
+              int sflag, int lflag, int special)
+{
+    return cmp_fd_and_fd_ex(fd1, file1, 0, fd2, file2, 0, sflag, lflag, special);
+}
+
+
+/**
+ * Compares an open file with another that isn't open yet.
+ */
+int
+cmp_fd_and_file_ex(int fd1, const char *file1, off_t skip1,
+                   const char *file2, off_t skip2,
+                   int sflag, int lflag, int special)
+{
+    int rc;
+    int fd2;
+
+    if (!strcmp(file2, "-"))
+    {
+        fd2 = 0 /* stdin */;
+        special = 1;
+        file2 = "stdin";
+    }
+    else
+        fd2 = open(file2, O_RDONLY | O_BINARY, 0);
+    if (fd2 >= 0)
+    {
+        rc = cmp_fd_and_fd_ex(fd1, file1, skip1,
+                              fd2, file2, skip2, sflag, lflag, special);
+        close(fd2);
+    }
+    else
+    {
+        if (!sflag)
+            warn("%s", file2);
+        rc = ERR_EXIT;
+    }
+    return rc;
+}
+
+
+/**
+ * Compares an open file with another that isn't open yet.
+ */
+int
+cmp_fd_and_file(int fd1, const char *file1,
+                const char *file2,
+                int sflag, int lflag, int special)
+{
+    return cmp_fd_and_file_ex(fd1, file1, 0,
+                                   file2, 0, sflag, lflag, special);
+}
+
+
+/**
+ * Opens and compare two files.
+ */
+int
+cmp_file_and_file_ex(const char *file1, off_t skip1,
+                     const char *file2, off_t skip2,
+                     int sflag, int lflag, int special)
+{
+    int fd1;
+    int rc;
+
+    if (lflag && sflag)
+        return errx(ERR_EXIT, "only one of -l and -s may be specified");
+
+    if (!strcmp(file1, "-"))
+    {
+        if (!strcmp(file2, "-"))
+            return errx(ERR_EXIT, "standard input may only be specified once");
+        file1 = "stdin";
+        fd1 = 1;
+        special = 1;
+    }
+    else
+        fd1 = open(file1, O_RDONLY | O_BINARY, 0);
+    if (fd1 >= 0)
+    {
+        rc = cmp_fd_and_file_ex(fd1, file1, skip1,
+                                     file2, skip2, sflag, lflag, special);
+        close(fd1);
+    }
+    else
+    {
+        if (!sflag)
+            warn("%s", file1);
+        rc = ERR_EXIT;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Opens and compare two files.
+ */
+int
+cmp_file_and_file(const char *file1, const char *file2, int sflag, int lflag, int special)
+{
+    return cmp_file_and_file_ex(file1, 0, file2, 0, sflag, lflag, special);
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp.c	(revision 1780)
@@ -0,0 +1,728 @@
+/*
+ * Copyright (c) 1988, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * David Hitz of Auspex Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1988, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)cp.c	8.2 (Berkeley) 4/1/94";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/cp/cp.c,v 1.50 2004/04/06 20:06:44 markm Exp $");
+#endif
+
+/*
+ * Cp copies source files to target files.
+ *
+ * The global PATH_T structure "to" always contains the path to the
+ * current target file.  Since fts(3) does not change directories,
+ * this path can be either absolute or dot-relative.
+ *
+ * The basic algorithm is to initialize "to" and use fts(3) to traverse
+ * the file hierarchy rooted in the argument list.  A trivial case is the
+ * case of 'cp file1 file2'.  The more interesting case is the case of
+ * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
+ * path (relative to the root of the traversal) is appended to dir (stored
+ * in "to") to form the final target path.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "err.h"
+#include <errno.h>
+#include <fts.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "getopt.h"
+#include "k/kDefs.h"
+#ifdef _MSC_VER
+# include "mscfakes.h"
+#endif
+#include "cp_extern.h"
+#include "kmkbuiltin.h"
+#include "kbuild_protection.h"
+
+
+#ifndef S_IFWHT
+#define S_IFWHT 0
+#define S_ISWHT(s) 0
+#define undelete(s) (-1)
+#endif
+
+#ifndef S_ISTXT
+#ifdef S_ISVTX
+#define S_ISTXT S_ISVTX
+#else
+#define S_ISTXT 0
+#endif
+#endif /* !S_ISTXT */
+
+#ifndef __unused
+# define __unused
+#endif
+
+#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+# define IS_SLASH(ch)   ((ch) == '/' || (ch) == '\\')
+#else
+# define IS_SLASH(ch)   ((ch) == '/')
+#endif
+
+#define	STRIP_TRAILING_SLASH(p) {					\
+        while ((p).p_end > (p).p_path + 1 && IS_SLASH((p).p_end[-1]))	\
+                *--(p).p_end = 0;					\
+}
+
+/* have wrappers for globals in cp_extern! */
+
+static KBUILDPROTECTION g_ProtData;
+const char *cp_argv0;
+static char emptystring[] = "";
+
+PATH_T to = { to.p_path, emptystring, "" };
+
+int fflag, iflag, nflag, pflag, vflag;
+static int Rflag, rflag;
+volatile sig_atomic_t info;
+static int cp_ignore_non_existing, cp_changed_only;
+
+enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
+
+enum cp_arg {
+    CP_OPT_HELP = 261,
+    CP_OPT_VERSION,
+    CP_OPT_IGNORE_NON_EXISTING,
+    CP_OPT_CHANGED,
+    CP_OPT_DISABLE_PROTECTION,
+    CP_OPT_ENABLE_PROTECTION,
+    CP_OPT_ENABLE_FULL_PROTECTION,
+    CP_OPT_DISABLE_FULL_PROTECTION,
+    CP_OPT_PROTECTION_DEPTH
+};
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, CP_OPT_HELP },
+    { "version",   					no_argument, 0, CP_OPT_VERSION },
+    { "ignore-non-existing",				no_argument, 0, CP_OPT_IGNORE_NON_EXISTING },
+    { "changed",					no_argument, 0, CP_OPT_CHANGED },
+    { "disable-protection",				no_argument, 0, CP_OPT_DISABLE_PROTECTION },
+    { "enable-protection",				no_argument, 0, CP_OPT_ENABLE_PROTECTION },
+    { "enable-full-protection",				no_argument, 0, CP_OPT_ENABLE_FULL_PROTECTION },
+    { "disable-full-protection",			no_argument, 0, CP_OPT_DISABLE_FULL_PROTECTION },
+    { "protection-depth",				required_argument, 0, CP_OPT_PROTECTION_DEPTH },
+    { 0, 0,	0, 0 },
+};
+
+
+static int copy(char *[], enum op, int);
+static int mastercmp(const FTSENT **, const FTSENT **);
+#ifdef SIGINFO
+static void siginfo(int __unused);
+#endif
+static int usage(FILE *);
+
+int
+kmk_builtin_cp(int argc, char *argv[], char **envp)
+{
+	struct stat to_stat, tmp_stat;
+	enum op type;
+	int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash, rc;
+	char *target;
+
+        /* init globals */
+        cp_argv0 = argv[0];
+        to.p_end = to.p_path;
+        to.target_end = emptystring;
+        memset(to.p_path, 0, sizeof(to.p_path));
+        fflag = iflag = nflag = pflag = vflag = Rflag = rflag = 0;
+        info = 0;
+	cp_ignore_non_existing = cp_changed_only = 0;
+	kBuildProtectionInit(&g_ProtData);
+
+        /* reset getopt and set progname. */
+        g_progname = argv[0];
+        opterr = 1;
+        optarg = NULL;
+        optopt = 0;
+        optind = 0; /* init */
+
+	Hflag = Lflag = Pflag = 0;
+	while ((ch = getopt_long(argc, argv, "HLPRfinprv", long_options, NULL)) != -1)
+		switch (ch) {
+		case 'H':
+			Hflag = 1;
+			Lflag = Pflag = 0;
+			break;
+		case 'L':
+			Lflag = 1;
+			Hflag = Pflag = 0;
+			break;
+		case 'P':
+			Pflag = 1;
+			Hflag = Lflag = 0;
+			break;
+		case 'R':
+			Rflag = 1;
+			break;
+		case 'f':
+			fflag = 1;
+			iflag = nflag = 0;
+			break;
+		case 'i':
+			iflag = 1;
+			fflag = nflag = 0;
+			break;
+		case 'n':
+			nflag = 1;
+			fflag = iflag = 0;
+			break;
+		case 'p':
+			pflag = 1;
+			break;
+#if 0 /* only one -R */
+		case 'r':
+			rflag = 1;
+			break;
+#endif
+		case 'v':
+			vflag = 1;
+			break;
+		case CP_OPT_HELP:
+			usage(stdout);
+			kBuildProtectionTerm(&g_ProtData);
+			return 0;
+		case CP_OPT_VERSION:
+			kBuildProtectionTerm(&g_ProtData);
+			return kbuild_version(argv[0]);
+		case CP_OPT_IGNORE_NON_EXISTING:
+			cp_ignore_non_existing = 1;
+			break;
+		case CP_OPT_CHANGED:
+			cp_changed_only = 1;
+			break;
+		case CP_OPT_DISABLE_PROTECTION:
+			kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
+			break;
+		case CP_OPT_ENABLE_PROTECTION:
+			kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
+			break;
+		case CP_OPT_ENABLE_FULL_PROTECTION:
+			kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
+			break;
+		case CP_OPT_DISABLE_FULL_PROTECTION:
+			kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
+			break;
+		case CP_OPT_PROTECTION_DEPTH:
+			if (kBuildProtectionSetDepth(&g_ProtData, optarg)) {
+				kBuildProtectionTerm(&g_ProtData);
+				return 1;
+			}
+			break;
+		default:
+			kBuildProtectionTerm(&g_ProtData);
+		        return usage(stderr);
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 2) {
+		kBuildProtectionTerm(&g_ProtData);
+		return usage(stderr);
+	}
+
+	fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
+	if (rflag) {
+		if (Rflag) {
+			kBuildProtectionTerm(&g_ProtData);
+			return errx(1,
+		    "the -R and -r options may not be specified together.");
+		}
+		if (Hflag || Lflag || Pflag)
+			errx(1,
+	"the -H, -L, and -P options may not be specified with the -r option.");
+		fts_options &= ~FTS_PHYSICAL;
+		fts_options |= FTS_LOGICAL;
+        }
+	if (Rflag) {
+		if (Hflag)
+			fts_options |= FTS_COMFOLLOW;
+		if (Lflag) {
+			fts_options &= ~FTS_PHYSICAL;
+			fts_options |= FTS_LOGICAL;
+		}
+	} else {
+		fts_options &= ~FTS_PHYSICAL;
+		fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
+	}
+#ifdef SIGINFO
+	(void)signal(SIGINFO, siginfo);
+#endif
+
+	/* Save the target base in "to". */
+	target = argv[--argc];
+	if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path)) {
+		kBuildProtectionTerm(&g_ProtData);
+		return errx(1, "%s: name too long", target);
+	}
+	to.p_end = to.p_path + strlen(to.p_path);
+        if (to.p_path == to.p_end) {
+		*to.p_end++ = '.';
+		*to.p_end = 0;
+	}
+	have_trailing_slash = IS_SLASH(to.p_end[-1]);
+	if (have_trailing_slash)
+		STRIP_TRAILING_SLASH(to);
+	to.target_end = to.p_end;
+
+	/* Set end of argument list for fts(3). */
+	argv[argc] = NULL;
+
+	/*
+	 * Cp has two distinct cases:
+	 *
+	 * cp [-R] source target
+	 * cp [-R] source1 ... sourceN directory
+	 *
+	 * In both cases, source can be either a file or a directory.
+	 *
+	 * In (1), the target becomes a copy of the source. That is, if the
+	 * source is a file, the target will be a file, and likewise for
+	 * directories.
+	 *
+	 * In (2), the real target is not directory, but "directory/source".
+	 */
+	r = stat(to.p_path, &to_stat);
+	if (r == -1 && errno != ENOENT) {
+		kBuildProtectionTerm(&g_ProtData);
+		return err(1, "%s", to.p_path);
+	}
+	if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
+		/*
+		 * Case (1).  Target is not a directory.
+		 */
+		if (argc > 1) {
+			kBuildProtectionTerm(&g_ProtData);
+			return usage(stderr);
+		}
+		/*
+		 * Need to detect the case:
+		 *	cp -R dir foo
+		 * Where dir is a directory and foo does not exist, where
+		 * we want pathname concatenations turned on but not for
+		 * the initial mkdir().
+		 */
+		if (r == -1) {
+			if (rflag || (Rflag && (Lflag || Hflag)))
+				stat(*argv, &tmp_stat);
+			else
+				lstat(*argv, &tmp_stat);
+
+			if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag))
+				type = DIR_TO_DNE;
+			else
+				type = FILE_TO_FILE;
+		} else
+			type = FILE_TO_FILE;
+
+		if (have_trailing_slash && type == FILE_TO_FILE) {
+			kBuildProtectionTerm(&g_ProtData);
+			if (r == -1)
+				return errx(1, "directory %s does not exist",
+				            to.p_path);
+			else
+				return errx(1, "%s is not a directory", to.p_path);
+		}
+	} else
+		/*
+		 * Case (2).  Target is a directory.
+		 */
+		type = FILE_TO_DIR;
+
+	/* Finally, check that the "to" directory isn't protected. */
+	rc = 1;
+	if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_CP_")
+	 && !kBuildProtectionEnforce(&g_ProtData,
+				     Rflag || rflag
+				     ? KBUILDPROTECTIONTYPE_RECURSIVE
+				     : KBUILDPROTECTIONTYPE_FULL,
+				     to.p_path)) {
+	    rc = copy(argv, type, fts_options);
+	}
+
+	kBuildProtectionTerm(&g_ProtData);
+	return rc;
+}
+
+static int
+copy(char *argv[], enum op type, int fts_options)
+{
+	struct stat to_stat;
+	FTS *ftsp;
+	FTSENT *curr;
+	int base = 0, dne, badcp, rval;
+	size_t nlen;
+	char *p, *target_mid;
+	mode_t mask, mode;
+
+	/*
+	 * Keep an inverted copy of the umask, for use in correcting
+	 * permissions on created directories when not using -p.
+	 */
+	mask = ~umask(0777);
+	umask(~mask);
+
+	if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
+		return err(1, "fts_open");
+	for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) {
+                int copied = 0;
+
+		switch (curr->fts_info) {
+		case FTS_NS:
+			if (   cp_ignore_non_existing
+			    && curr->fts_errno == ENOENT) {
+				if (vflag) {
+					warnx("%s: %s", curr->fts_path,
+					      strerror(curr->fts_errno));
+				}
+				continue;
+			}
+		case FTS_DNR:
+		case FTS_ERR:
+			warnx("%s: %s",
+			    curr->fts_path, strerror(curr->fts_errno));
+			badcp = rval = 1;
+			continue;
+		case FTS_DC:			/* Warn, continue. */
+			warnx("%s: directory causes a cycle", curr->fts_path);
+			badcp = rval = 1;
+			continue;
+		default:
+			;
+		}
+
+		/*
+		 * If we are in case (2) or (3) above, we need to append the
+                 * source name to the target name.
+                 */
+		if (type != FILE_TO_FILE) {
+			/*
+			 * Need to remember the roots of traversals to create
+			 * correct pathnames.  If there's a directory being
+			 * copied to a non-existent directory, e.g.
+			 *	cp -R a/dir noexist
+			 * the resulting path name should be noexist/foo, not
+			 * noexist/dir/foo (where foo is a file in dir), which
+			 * is the case where the target exists.
+			 *
+			 * Also, check for "..".  This is for correct path
+			 * concatenation for paths ending in "..", e.g.
+			 *	cp -R .. /tmp
+			 * Paths ending in ".." are changed to ".".  This is
+			 * tricky, but seems the easiest way to fix the problem.
+			 *
+			 * XXX
+			 * Since the first level MUST be FTS_ROOTLEVEL, base
+			 * is always initialized.
+			 */
+			if (curr->fts_level == FTS_ROOTLEVEL) {
+				if (type != DIR_TO_DNE) {
+					p = strrchr(curr->fts_path, '/');
+#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+                                        if (strrchr(curr->fts_path, '\\') > p)
+                                            p = strrchr(curr->fts_path, '\\');
+#endif
+					base = (p == NULL) ? 0 :
+					    (int)(p - curr->fts_path + 1);
+
+					if (!strcmp(&curr->fts_path[base],
+					    ".."))
+						base += 1;
+				} else
+					base = curr->fts_pathlen;
+			}
+
+			p = &curr->fts_path[base];
+			nlen = curr->fts_pathlen - base;
+			target_mid = to.target_end;
+			if (!IS_SLASH(*p) && !IS_SLASH(target_mid[-1]))
+				*target_mid++ = '/';
+			*target_mid = 0;
+			if (target_mid - to.p_path + nlen >= PATH_MAX) {
+				warnx("%s%s: name too long (not copied)",
+				    to.p_path, p);
+				badcp = rval = 1;
+				continue;
+			}
+			(void)strncat(target_mid, p, nlen);
+			to.p_end = target_mid + nlen;
+			*to.p_end = 0;
+			STRIP_TRAILING_SLASH(to);
+		}
+
+		if (curr->fts_info == FTS_DP) {
+			/*
+			 * We are nearly finished with this directory.  If we
+			 * didn't actually copy it, or otherwise don't need to
+			 * change its attributes, then we are done.
+			 */
+			if (!curr->fts_number)
+				continue;
+			/*
+			 * If -p is in effect, set all the attributes.
+			 * Otherwise, set the correct permissions, limited
+			 * by the umask.  Optimise by avoiding a chmod()
+			 * if possible (which is usually the case if we
+			 * made the directory).  Note that mkdir() does not
+			 * honour setuid, setgid and sticky bits, but we
+			 * normally want to preserve them on directories.
+			 */
+			if (pflag) {
+				if (setfile(curr->fts_statp, -1))
+				    rval = 1;
+			} else {
+				mode = curr->fts_statp->st_mode;
+				if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) ||
+				    ((mode | S_IRWXU) & mask) != (mode & mask))
+					if (chmod(to.p_path, mode & mask) != 0){
+						warn("chmod: %s", to.p_path);
+						rval = 1;
+					}
+			}
+			continue;
+		}
+
+		/* Not an error but need to remember it happened */
+		if (stat(to.p_path, &to_stat) == -1)
+			dne = 1;
+		else {
+			if (to_stat.st_dev == curr->fts_statp->st_dev &&
+			    to_stat.st_dev != 0 &&
+			    to_stat.st_ino == curr->fts_statp->st_ino &&
+			    to_stat.st_ino != 0) {
+				warnx("%s and %s are identical (not copied).",
+				    to.p_path, curr->fts_path);
+				badcp = rval = 1;
+				if (S_ISDIR(curr->fts_statp->st_mode))
+					(void)fts_set(ftsp, curr, FTS_SKIP);
+				continue;
+			}
+			if (!S_ISDIR(curr->fts_statp->st_mode) &&
+			    S_ISDIR(to_stat.st_mode)) {
+				warnx("cannot overwrite directory %s with "
+				    "non-directory %s",
+				    to.p_path, curr->fts_path);
+				badcp = rval = 1;
+				continue;
+			}
+			dne = 0;
+		}
+
+		switch (curr->fts_statp->st_mode & S_IFMT) {
+#ifdef S_IFLNK
+		case S_IFLNK:
+			/* Catch special case of a non-dangling symlink */
+			if ((fts_options & FTS_LOGICAL) ||
+			    ((fts_options & FTS_COMFOLLOW) &&
+			    curr->fts_level == 0)) {
+				if (copy_file(curr, dne, cp_changed_only, &copied))
+					badcp = rval = 1;
+			} else {
+				if (copy_link(curr, !dne))
+					badcp = rval = 1;
+			}
+			break;
+#endif
+		case S_IFDIR:
+			if (!Rflag && !rflag) {
+				warnx("%s is a directory (not copied).",
+				    curr->fts_path);
+				(void)fts_set(ftsp, curr, FTS_SKIP);
+				badcp = rval = 1;
+				break;
+			}
+			/*
+			 * If the directory doesn't exist, create the new
+			 * one with the from file mode plus owner RWX bits,
+			 * modified by the umask.  Trade-off between being
+			 * able to write the directory (if from directory is
+			 * 555) and not causing a permissions race.  If the
+			 * umask blocks owner writes, we fail..
+			 */
+			if (dne) {
+				if (mkdir(to.p_path,
+				    curr->fts_statp->st_mode | S_IRWXU) < 0)
+					return err(1, "%s", to.p_path);
+			} else if (!S_ISDIR(to_stat.st_mode)) {
+				errno = ENOTDIR;
+				return err(1, "%s", to.p_path);
+			}
+			/*
+			 * Arrange to correct directory attributes later
+			 * (in the post-order phase) if this is a new
+			 * directory, or if the -p flag is in effect.
+			 */
+			curr->fts_number = pflag || dne;
+			break;
+#ifdef S_IFBLK
+		case S_IFBLK:
+#endif
+		case S_IFCHR:
+			if (Rflag) {
+				if (copy_special(curr->fts_statp, !dne))
+					badcp = rval = 1;
+			} else {
+				if (copy_file(curr, dne, cp_changed_only, &copied))
+					badcp = rval = 1;
+			}
+			break;
+#ifdef S_IFIFO
+		case S_IFIFO:
+#endif
+			if (Rflag) {
+				if (copy_fifo(curr->fts_statp, !dne))
+					badcp = rval = 1;
+			} else {
+				if (copy_file(curr, dne, cp_changed_only, &copied))
+					badcp = rval = 1;
+			}
+			break;
+		default:
+			if (copy_file(curr, dne, cp_changed_only, &copied))
+				badcp = rval = 1;
+			break;
+		}
+		if (vflag && !badcp)
+			(void)printf(copied ? "%s -> %s\n" : "%s matches %s - not copied\n",
+				     curr->fts_path, to.p_path);
+	}
+	if (errno)
+		return err(1, "fts_read");
+	return (rval);
+}
+
+/*
+ * mastercmp --
+ *	The comparison function for the copy order.  The order is to copy
+ *	non-directory files before directory files.  The reason for this
+ *	is because files tend to be in the same cylinder group as their
+ *	parent directory, whereas directories tend not to be.  Copying the
+ *	files first reduces seeking.
+ */
+static int
+mastercmp(const FTSENT **a, const FTSENT **b)
+{
+	int a_info, b_info;
+
+	a_info = (*a)->fts_info;
+	if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR)
+		return (0);
+	b_info = (*b)->fts_info;
+	if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR)
+		return (0);
+	if (a_info == FTS_D)
+		return (-1);
+	if (b_info == FTS_D)
+		return (1);
+	return (0);
+}
+
+#ifdef SIGINFO
+static void
+siginfo(int sig __unused)
+{
+
+	info = 1;
+}
+#endif
+
+
+static int
+usage(FILE *fp)
+{
+	fprintf(fp,
+"usage: %s [options] src target\n"
+"   or: %s [options] src1 ... srcN directory\n"
+"   or: %s --help\n"
+"   or: %s --version\n"
+"\n"
+"Options:\n"
+"   -R  Recursive copy.\n"
+"   -H  Follow symbolic links on the commandline. Only valid with -R.\n"
+"   -L  Follow all symbolic links. Only valid with -R.\n"
+"   -P  Do not follow symbolic links. Default. Only valid with -R\n"
+"   -f  Force. Overrides -i and -n.\n"
+"   -i  Iteractive. Overrides -n and -f.\n"
+"   -n  Don't overwrite any files. Overrides -i and -f.\n"
+"   --ignore-non-existing\n"
+"       Don't fail if the specified source file doesn't exist.\n"
+"   --changed\n"
+"       Only copy if changed (i.e. compare first).\n"
+"   --disable-protection\n"
+"       Will disable the protection file protection applied with -R.\n"
+"   --enable-protection\n"
+"       Will enable the protection file protection applied with -R.\n"
+"   --enable-full-protection\n"
+"       Will enable the protection file protection for all operations.\n"
+"   --disable-full-protection\n"
+"       Will disable the protection file protection for all operations.\n"
+"   --protection-depth\n"
+"       Number or path indicating the file protection depth. Default: %d\n"
+"\n"
+"Environment:\n"
+"    KMK_CP_DISABLE_PROTECTION\n"
+"       Same as --disable-protection. Overrides command line.\n"
+"    KMK_CP_ENABLE_PROTECTION\n"
+"       Same as --enable-protection. Overrides everyone else.\n"
+"    KMK_CP_ENABLE_FULL_PROTECTION\n"
+"       Same as --enable-full-protection. Overrides everyone else.\n"
+"    KMK_CP_DISABLE_FULL_PROTECTION\n"
+"       Same as --disable-full-protection. Overrides command line.\n"
+"    KMK_CP_PROTECTION_DEPTH\n"
+"       Same as --protection-depth. Overrides command line.\n"
+"\n"
+"The file protection of the top %d layers of the file hierarchy is there\n"
+"to try prevent makefiles from doing bad things to your system. This\n"
+"protection is not bulletproof, but should help prevent you from shooting\n"
+"yourself in the foot.\n"
+		,
+	        g_progname, g_progname, g_progname, g_progname,
+	        kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth());
+	return 1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp_extern.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp_extern.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp_extern.h	(revision 1780)
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)extern.h	8.2 (Berkeley) 4/1/94
+ * $FreeBSD: src/bin/cp/extern.h,v 1.19 2004/04/06 20:06:44 markm Exp $
+ */
+
+typedef struct {
+	char	*p_end;			/* pointer to NULL at end of path */
+	char	*target_end;		/* pointer to end of target base */
+	char	p_path[PATH_MAX];	/* pointer to the start of a path */
+} PATH_T;
+
+#define argv0   cp_argv0
+#define to      cp_to
+#define fflag   cp_fflag
+#define iflag   cp_iflag
+#define nflag   cp_nflag
+#define pflag   cp_pflag
+#define vflag   cp_vflag
+#define info    cp_info
+#define usage   cp_usage
+#define setfile cp_setfile
+
+extern const char *argv0;
+extern PATH_T to;
+extern int fflag, iflag, nflag, pflag, vflag;
+extern volatile sig_atomic_t info;
+
+int	copy_fifo(struct stat *, int);
+int	copy_file(const FTSENT *, int, int, int *);
+int	copy_link(const FTSENT *, int);
+int	copy_special(struct stat *, int);
+int	setfile(struct stat *, int);
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp_utils.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp_utils.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/cp_utils.c	(revision 1780)
@@ -0,0 +1,378 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)utils.c	8.3 (Berkeley) 4/1/94";
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/cp/utils.c,v 1.43 2004/04/06 20:06:44 markm Exp $");
+#endif
+#endif /* not lint */
+
+#ifndef _MSC_VER
+# include <sys/param.h>
+#endif
+#include <sys/stat.h>
+#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
+# include <sys/mman.h>
+#endif
+
+#include "err.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sysexits.h>
+#include <unistd.h>
+#ifdef __sun__
+# include "solfakes.h"
+#endif
+#ifdef _MSC_VER
+# define MSC_DO_64_BIT_IO
+# include "mscfakes.h"
+#endif
+#include "cp_extern.h"
+#include "cmp_extern.h"
+
+#define	cp_pct(x,y)	(int)(100.0 * (double)(x) / (double)(y))
+
+#ifndef MAXBSIZE
+# define MAXBSIZE 0x20000
+#endif
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+#ifndef S_ISVTX
+# define S_ISVTX 0
+#endif
+
+
+int
+copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
+{
+	static char buf[MAXBSIZE];
+	struct stat *fs;
+	int ch, checkch, from_fd, rcount, rval, to_fd;
+	ssize_t wcount;
+	size_t wresid;
+	size_t wtotal;
+	char *bufp;
+#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
+	char *p;
+#endif
+
+	*pcopied = 0;
+
+	if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY, 0)) == -1) {
+		warn("%s", entp->fts_path);
+		return (1);
+	}
+
+	fs = entp->fts_statp;
+
+	/*
+	 * If the file exists and we're interactive, verify with the user.
+	 * If the file DNE, set the mode to be the from file, minus setuid
+	 * bits, modified by the umask; arguably wrong, but it makes copying
+	 * executables work right and it's been that way forever.  (The
+	 * other choice is 666 or'ed with the execute bits on the from file
+	 * modified by the umask.)
+	 */
+	if (!dne) {
+		/* compare the files first if requested */
+		if (changed_only) {
+                        if (cmp_fd_and_file(from_fd, entp->fts_path, to.p_path,
+					    1 /* silent */, 0 /* lflag */,
+					    0 /* special */) == OK_EXIT) {
+				close(from_fd);
+				return (0);
+			}
+			if (lseek(from_fd, 0, SEEK_SET) != 0) {
+    				close(from_fd);
+				if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY, 0)) == -1) {
+					warn("%s", entp->fts_path);
+					return (1);
+				}
+			}
+		}
+
+#define YESNO "(y/n [n]) "
+		if (nflag) {
+			if (vflag)
+				printf("%s not overwritten\n", to.p_path);
+			return (0);
+		} else if (iflag) {
+			(void)fprintf(stderr, "overwrite %s? %s",
+					to.p_path, YESNO);
+			checkch = ch = getchar();
+			while (ch != '\n' && ch != EOF)
+				ch = getchar();
+			if (checkch != 'y' && checkch != 'Y') {
+				(void)close(from_fd);
+				(void)fprintf(stderr, "not overwritten\n");
+				return (1);
+			}
+		}
+
+		if (fflag) {
+		    /* remove existing destination file name,
+		     * create a new file  */
+		    (void)unlink(to.p_path);
+		    to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY,
+				 fs->st_mode & ~(S_ISUID | S_ISGID));
+		} else
+		    /* overwrite existing destination file name */
+		    to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_BINARY, 0);
+	} else
+		to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY,
+		    fs->st_mode & ~(S_ISUID | S_ISGID));
+
+	if (to_fd == -1) {
+		warn("%s", to.p_path);
+		(void)close(from_fd);
+		return (1);
+	}
+
+	rval = 0;
+	*pcopied = 1;
+
+	/*
+	 * Mmap and write if less than 8M (the limit is so we don't totally
+	 * trash memory on big files.  This is really a minor hack, but it
+	 * wins some CPU back.
+	 */
+#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
+	if (S_ISREG(fs->st_mode) && fs->st_size > 0 &&
+	    fs->st_size <= 8 * 1048576) {
+		if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
+		    MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
+			warn("%s", entp->fts_path);
+			rval = 1;
+		} else {
+			wtotal = 0;
+			for (bufp = p, wresid = fs->st_size; ;
+			    bufp += wcount, wresid -= (size_t)wcount) {
+				wcount = write(to_fd, bufp, wresid);
+				wtotal += wcount;
+				if (info) {
+					info = 0;
+					(void)fprintf(stderr,
+						"%s -> %s %3d%%\n",
+						entp->fts_path, to.p_path,
+						cp_pct(wtotal, fs->st_size));
+
+				}
+				if (wcount >= (ssize_t)wresid || wcount <= 0)
+					break;
+			}
+			if (wcount != (ssize_t)wresid) {
+				warn("%s", to.p_path);
+				rval = 1;
+			}
+			/* Some systems don't unmap on close(2). */
+			if (munmap(p, fs->st_size) < 0) {
+				warn("%s", entp->fts_path);
+				rval = 1;
+			}
+		}
+	} else
+#endif
+	{
+		wtotal = 0;
+		while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
+			for (bufp = buf, wresid = rcount; ;
+			    bufp += wcount, wresid -= wcount) {
+				wcount = write(to_fd, bufp, wresid);
+				wtotal += wcount;
+				if (info) {
+					info = 0;
+					(void)fprintf(stderr,
+						"%s -> %s %3d%%\n",
+						entp->fts_path, to.p_path,
+						cp_pct(wtotal, fs->st_size));
+
+				}
+				if (wcount >= (ssize_t)wresid || wcount <= 0)
+					break;
+			}
+			if (wcount != (ssize_t)wresid) {
+				warn("%s", to.p_path);
+				rval = 1;
+				break;
+			}
+		}
+		if (rcount < 0) {
+			warn("%s", entp->fts_path);
+			rval = 1;
+		}
+	}
+
+	/*
+	 * Don't remove the target even after an error.  The target might
+	 * not be a regular file, or its attributes might be important,
+	 * or its contents might be irreplaceable.  It would only be safe
+	 * to remove it if we created it and its length is 0.
+	 */
+
+	if (pflag && setfile(fs, to_fd))
+		rval = 1;
+	(void)close(from_fd);
+	if (close(to_fd)) {
+		warn("%s", to.p_path);
+		rval = 1;
+	}
+	return (rval);
+}
+
+int
+copy_link(const FTSENT *p, int exists)
+{
+	int len;
+	char llink[PATH_MAX];
+
+	if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) {
+		warn("readlink: %s", p->fts_path);
+		return (1);
+	}
+	llink[len] = '\0';
+	if (exists && unlink(to.p_path)) {
+		warn("unlink: %s", to.p_path);
+		return (1);
+	}
+	if (symlink(llink, to.p_path)) {
+		warn("symlink: %s", llink);
+		return (1);
+	}
+	return (pflag ? setfile(p->fts_statp, -1) : 0);
+}
+
+int
+copy_fifo(struct stat *from_stat, int exists)
+{
+	if (exists && unlink(to.p_path)) {
+		warn("unlink: %s", to.p_path);
+		return (1);
+	}
+	if (mkfifo(to.p_path, from_stat->st_mode)) {
+		warn("mkfifo: %s", to.p_path);
+		return (1);
+	}
+	return (pflag ? setfile(from_stat, -1) : 0);
+}
+
+int
+copy_special(struct stat *from_stat, int exists)
+{
+	if (exists && unlink(to.p_path)) {
+		warn("unlink: %s", to.p_path);
+		return (1);
+	}
+	if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) {
+		warn("mknod: %s", to.p_path);
+		return (1);
+	}
+	return (pflag ? setfile(from_stat, -1) : 0);
+}
+
+int
+setfile(struct stat *fs, int fd)
+{
+	static struct timeval tv[2];
+	struct stat ts;
+	int rval, gotstat, islink, fdval;
+
+	rval = 0;
+	fdval = fd != -1;
+	islink = !fdval && S_ISLNK(fs->st_mode);
+	fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
+		       S_IRWXU | S_IRWXG | S_IRWXO;
+
+#ifdef HAVE_ST_TIMESPEC
+	TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
+	TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
+#else
+        tv[0].tv_sec = fs->st_atime;
+        tv[1].tv_sec = fs->st_mtime;
+        tv[0].tv_usec = tv[1].tv_usec = 0;
+#endif
+	if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
+		warn("%sutimes: %s", islink ? "l" : "", to.p_path);
+		rval = 1;
+	}
+	if (fdval ? fstat(fd, &ts) :
+	    (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
+		gotstat = 0;
+	else {
+		gotstat = 1;
+		ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
+			      S_IRWXU | S_IRWXG | S_IRWXO;
+	}
+	/*
+	 * Changing the ownership probably won't succeed, unless we're root
+	 * or POSIX_CHOWN_RESTRICTED is not set.  Set uid/gid before setting
+	 * the mode; current BSD behavior is to remove all setuid bits on
+	 * chown.  If chown fails, lose setuid/setgid bits.
+	 */
+	if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
+		if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
+		    (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
+		    chown(to.p_path, fs->st_uid, fs->st_gid))) {
+			if (errno != EPERM) {
+				warn("chown: %s", to.p_path);
+				rval = 1;
+			}
+			fs->st_mode &= ~(S_ISUID | S_ISGID);
+		}
+
+	if (!gotstat || fs->st_mode != ts.st_mode)
+		if (fdval ? fchmod(fd, fs->st_mode) :
+		    (islink ? lchmod(to.p_path, fs->st_mode) :
+		    chmod(to.p_path, fs->st_mode))) {
+			warn("chmod: %s", to.p_path);
+			rval = 1;
+		}
+
+#ifdef HAVE_ST_FLAGS
+	if (!gotstat || fs->st_flags != ts.st_flags)
+		if (fdval ?
+		    fchflags(fd, fs->st_flags) :
+		    (islink ? (errno = ENOSYS) :
+		    chflags(to.p_path, fs->st_flags))) {
+			warn("chflags: %s", to.p_path);
+			rval = 1;
+		}
+#endif
+
+	return (rval);
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/darwin.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/darwin.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/darwin.c	(revision 1780)
@@ -0,0 +1,51 @@
+/* $Id$ */
+/** @file
+ * Missing BSD functions on Darwin / Mac OS X.
+ */
+
+/*
+ * Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+
+int lchmod(const char *path, mode_t mode)
+{
+    struct stat st;
+    if (lstat(path, &st))
+        return -1;
+    if (S_ISLNK(st.st_mode))
+        return 0; /* pretend success */
+    return chmod(path, mode);
+}
+
+
+int lutimes(const char *path, const struct timeval *tvs)
+{
+    struct stat st;
+    if (lstat(path, &st))
+        return -1;
+    if (S_ISLNK(st.st_mode))
+        return 0; /* pretend success */
+    return utimes(path, tvs);
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/echo.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/echo.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/echo.c	(revision 1780)
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)echo.c	8.1 (Berkeley) 5/31/93";
+#endif /* not lint */
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.17 2004/04/06 20:06:46 markm Exp $");
+#endif
+
+#include <sys/types.h>
+#ifndef _MSC_VER
+#include <sys/uio.h>
+#endif 
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#else
+#include "mscfakes.h"
+#endif 
+
+#ifndef IOV_MAX
+#define IOV_MAX 1024
+#endif
+
+
+/*
+ * Report an error and exit.
+ * Use it instead of err(3) to avoid linking-in stdio.
+ */
+static void
+errexit(const char *prog, const char *reason)
+{
+	char *errstr = strerror(errno);
+	write(STDERR_FILENO, prog, strlen(prog));
+	write(STDERR_FILENO, ": ", 2);
+	write(STDERR_FILENO, reason, strlen(reason));
+	write(STDERR_FILENO, ": ", 2);
+	write(STDERR_FILENO, errstr, strlen(errstr));
+	write(STDERR_FILENO, "\n", 1);
+}
+	
+int
+kmk_builtin_echo(int argc, char *argv[])
+{
+	int nflag;	/* if not set, output a trailing newline. */
+	int veclen;	/* number of writev arguments. */
+	struct iovec *iov, *vp, *iovfree; /* Elements to write, current element. */
+	char space[] = " ";
+	char newline[] = "\n";
+	char *progname = argv[0];
+
+	/* This utility may NOT do getopt(3) option parsing. */
+	if (*++argv && !strcmp(*argv, "-n")) {
+		++argv;
+		--argc;
+		nflag = 1;
+	} else
+		nflag = 0;
+
+	veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;
+
+	if ((iovfree = vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) {
+		errexit(progname, "malloc");
+                exit(1);
+        }
+
+	while (argv[0] != NULL) {
+		size_t len;
+		
+		len = strlen(argv[0]);
+
+		/*
+		 * If the next argument is NULL then this is this
+		 * the last argument, therefore we need to check
+		 * for a trailing \c.
+		 */
+		if (argv[1] == NULL) {
+			/* is there room for a '\c' and is there one? */
+			if (len >= 2 &&
+			    argv[0][len - 2] == '\\' &&
+			    argv[0][len - 1] == 'c') {
+				/* chop it and set the no-newline flag. */
+				len -= 2;
+				nflag = 1;
+			}
+		}
+		vp->iov_base = *argv;
+		vp++->iov_len = len;
+		if (*++argv) {
+			vp->iov_base = space;
+			vp++->iov_len = 1;
+		}
+	}
+	if (!nflag) {
+		veclen++;
+		vp->iov_base = newline;
+		vp++->iov_len = 1;
+	}
+	/* assert(veclen == (vp - iov)); */
+	while (veclen) {
+		int nwrite;
+
+		nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;
+		if (writev(STDOUT_FILENO, iov, nwrite) == -1) {
+			 errexit(progname, "write");
+                         free(iovfree);
+                         return 1;
+                }
+		iov += nwrite;
+		veclen -= nwrite;
+	}
+	free(iovfree);
+	return 0;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/err.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/err.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/err.c	(revision 1780)
@@ -0,0 +1,85 @@
+/* $Id$ */
+/** @file
+ *
+ * Override err.h so we get the program name right.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include "err.h"
+
+
+/** The current program name. */
+const char *g_progname = "kmk";
+
+
+int err(int eval, const char *fmt, ...)
+{
+    va_list args;
+    int error = errno;
+    fprintf(stderr, "%s: ", g_progname);
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, ": %s\n", strerror(error));
+
+    return eval;
+}
+
+
+int errx(int eval, const char *fmt, ...)
+{
+    va_list args;
+    fprintf(stderr, "%s: ", g_progname);
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, "\n");
+
+    return eval;
+}
+
+void warn(const char *fmt, ...)
+{
+    int error = errno;
+    va_list args;
+    fprintf(stderr, "%s: ", g_progname);
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, ": %s\n", strerror(error));
+}
+
+void warnx(const char *fmt, ...)
+{
+    int err = errno;
+    va_list args;
+    fprintf(stderr, "%s: ", g_progname);
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, "\n");
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/err.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/err.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/err.h	(revision 1780)
@@ -0,0 +1,35 @@
+/* $Id$ */
+/** @file
+ *
+ * Override err.h stuff so we get the program names right.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+#ifndef ___err_h
+#define ___err_h
+
+extern const char *g_progname;
+int err(int eval, const char *fmt, ...);
+int errx(int eval, const char *fmt, ...);
+void warn(const char *fmt, ...);
+void warnx(const char *fmt, ...);
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/expr.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/expr.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/expr.c	(revision 1780)
@@ -0,0 +1,598 @@
+/*	$OpenBSD: expr.c,v 1.17 2006/06/21 18:28:24 deraadt Exp $	*/
+/*	$NetBSD: expr.c,v 1.3.6.1 1996/06/04 20:41:47 cgd Exp $	*/
+
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <ctype.h>
+#ifdef KMK_WITH_REGEX
+#include <regex.h>
+#endif
+#include <setjmp.h>
+#include <assert.h>
+#include "err.h"
+#include "getopt.h"
+#include "kmkbuiltin.h"
+
+static struct val	*make_int(int);
+static struct val	*make_str(char *);
+static void		 free_value(struct val *);
+static int		 is_integer(struct val *, int *);
+static int		 to_integer(struct val *);
+static void		 to_string(struct val *);
+static int		 is_zero_or_null(struct val *);
+static void		 nexttoken(int);
+static void	 	 error(void);
+static struct val	*eval6(void);
+static struct val	*eval5(void);
+static struct val	*eval4(void);
+static struct val	*eval3(void);
+static struct val	*eval2(void);
+static struct val	*eval1(void);
+static struct val	*eval0(void);
+
+enum token {
+	OR, AND, EQ, LT, GT, ADD, SUB, MUL, DIV, MOD, MATCH, RP, LP,
+	NE, LE, GE, OPERAND, EOI
+};
+
+struct val {
+	enum {
+		integer,
+		string
+	} type;
+
+	union {
+		char	       *s;
+		int		i;
+	} u;
+};
+
+static enum token	token;
+static struct val     *tokval;
+static char	      **av;
+static jmp_buf          g_expr_jmp;
+static void           **recorded_allocations;
+static int 		num_recorded_allocations;
+
+
+static void expr_mem_record_alloc(void *ptr)
+{
+	if (!(num_recorded_allocations & 31)) {
+    		void *newtab = realloc(recorded_allocations, (num_recorded_allocations + 33) * sizeof(void *));
+		if (!newtab)
+			longjmp(g_expr_jmp, err(3, NULL));
+		recorded_allocations = (void **)newtab;
+	}
+	recorded_allocations[num_recorded_allocations++] = ptr;
+}
+
+
+static void expr_mem_record_free(void *ptr)
+{
+	int i = num_recorded_allocations;
+	while (i-- > 0)
+		if (recorded_allocations[i] == ptr) {
+			num_recorded_allocations--;
+			recorded_allocations[i] = recorded_allocations[num_recorded_allocations];
+			return;
+		}
+	assert(i >= 0);
+}
+
+static void expr_mem_init(void)
+{
+	num_recorded_allocations = 0;
+	recorded_allocations = NULL;
+}
+
+static void expr_mem_cleanup(void)
+{
+	if (recorded_allocations) {
+		while (num_recorded_allocations-- > 0)
+			free(recorded_allocations[num_recorded_allocations]);
+		free(recorded_allocations);
+		recorded_allocations = NULL;
+	}
+}
+
+
+static struct val *
+make_int(int i)
+{
+	struct val     *vp;
+
+	vp = (struct val *) malloc(sizeof(*vp));
+	if (vp == NULL)
+		longjmp(g_expr_jmp, err(3, NULL));
+	expr_mem_record_alloc(vp);
+	vp->type = integer;
+	vp->u.i = i;
+	return vp;
+}
+
+
+static struct val *
+make_str(char *s)
+{
+	struct val     *vp;
+
+	vp = (struct val *) malloc(sizeof(*vp));
+	if (vp == NULL || ((vp->u.s = strdup(s)) == NULL))
+		longjmp(g_expr_jmp, err(3, NULL));
+	expr_mem_record_alloc(vp->u.s);
+	expr_mem_record_alloc(vp);
+	vp->type = string;
+	return vp;
+}
+
+
+static void
+free_value(struct val *vp)
+{
+	if (vp->type == string) {
+		expr_mem_record_free(vp->u.s);
+		free(vp->u.s);
+	}
+	free(vp);
+	expr_mem_record_free(vp);
+}
+
+
+/* determine if vp is an integer; if so, return it's value in *r */
+static int
+is_integer(struct val *vp, int *r)
+{
+	char	       *s;
+	int		neg;
+	int		i;
+
+	if (vp->type == integer) {
+		*r = vp->u.i;
+		return 1;
+	}
+
+	/*
+	 * POSIX.2 defines an "integer" as an optional unary minus
+	 * followed by digits.
+	 */
+	s = vp->u.s;
+	i = 0;
+
+	neg = (*s == '-');
+	if (neg)
+		s++;
+
+	while (*s) {
+		if (!isdigit(*s))
+			return 0;
+
+		i *= 10;
+		i += *s - '0';
+
+		s++;
+	}
+
+	if (neg)
+		i *= -1;
+
+	*r = i;
+	return 1;
+}
+
+
+/* coerce to vp to an integer */
+static int
+to_integer(struct val *vp)
+{
+	int		r;
+
+	if (vp->type == integer)
+		return 1;
+
+	if (is_integer(vp, &r)) {
+		expr_mem_record_free(vp->u.s);
+		free(vp->u.s);
+		vp->u.i = r;
+		vp->type = integer;
+		return 1;
+	}
+
+	return 0;
+}
+
+
+/* coerce to vp to an string */
+static void
+to_string(struct val *vp)
+{
+	char	       *tmp;
+
+	if (vp->type == string)
+		return;
+
+	if (asprintf(&tmp, "%d", vp->u.i) == -1)
+		longjmp(g_expr_jmp, err(3, NULL));
+	expr_mem_record_alloc(tmp);
+
+	vp->type = string;
+	vp->u.s = tmp;
+}
+
+static int
+is_zero_or_null(struct val *vp)
+{
+	if (vp->type == integer) {
+		return (vp->u.i == 0);
+	} else {
+		return (*vp->u.s == 0 || (to_integer(vp) && vp->u.i == 0));
+	}
+	/* NOTREACHED */
+}
+
+static void
+nexttoken(int pat)
+{
+	char	       *p;
+
+	if ((p = *av) == NULL) {
+		token = EOI;
+		return;
+	}
+	av++;
+
+
+	if (pat == 0 && p[0] != '\0') {
+		if (p[1] == '\0') {
+			const char     *x = "|&=<>+-*/%:()";
+			char	       *i;	/* index */
+
+			if ((i = strchr(x, *p)) != NULL) {
+				token = i - x;
+				return;
+			}
+		} else if (p[1] == '=' && p[2] == '\0') {
+			switch (*p) {
+			case '<':
+				token = LE;
+				return;
+			case '>':
+				token = GE;
+				return;
+			case '!':
+				token = NE;
+				return;
+			}
+		}
+	}
+	tokval = make_str(p);
+	token = OPERAND;
+	return;
+}
+
+static void
+error(void)
+{
+	longjmp(g_expr_jmp, errx(2, "syntax error"));
+	/* NOTREACHED */
+}
+
+static struct val *
+eval6(void)
+{
+	struct val     *v;
+
+	if (token == OPERAND) {
+		nexttoken(0);
+		return tokval;
+
+	} else if (token == RP) {
+		nexttoken(0);
+		v = eval0();
+
+		if (token != LP) {
+			error();
+			/* NOTREACHED */
+		}
+		nexttoken(0);
+		return v;
+	} else {
+		error();
+	}
+	/* NOTREACHED */
+}
+
+/* Parse and evaluate match (regex) expressions */
+static struct val *
+eval5(void)
+{
+#ifdef KMK_WITH_REGEX
+	regex_t		rp;
+	regmatch_t	rm[2];
+	char		errbuf[256];
+	int		eval;
+	struct val     *r;
+	struct val     *v;
+#endif
+	struct val     *l;
+
+	l = eval6();
+	while (token == MATCH) {
+#ifdef KMK_WITH_REGEX
+		nexttoken(1);
+		r = eval6();
+
+		/* coerce to both arguments to strings */
+		to_string(l);
+		to_string(r);
+
+		/* compile regular expression */
+		if ((eval = regcomp(&rp, r->u.s, 0)) != 0) {
+			regerror(eval, &rp, errbuf, sizeof(errbuf));
+			longjmp(g_expr_jmp, errx(2, "%s", errbuf));
+		}
+
+		/* compare string against pattern --  remember that patterns
+		   are anchored to the beginning of the line */
+		if (regexec(&rp, l->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) {
+			if (rm[1].rm_so >= 0) {
+				*(l->u.s + rm[1].rm_eo) = '\0';
+				v = make_str(l->u.s + rm[1].rm_so);
+
+			} else {
+				v = make_int((int)(rm[0].rm_eo - rm[0].rm_so));
+			}
+		} else {
+			if (rp.re_nsub == 0) {
+				v = make_int(0);
+			} else {
+				v = make_str("");
+			}
+		}
+
+		/* free arguments and pattern buffer */
+		free_value(l);
+		free_value(r);
+		regfree(&rp);
+
+		l = v;
+#else
+		longjmp(g_expr_jmp, errx(2, "regex not supported, sorry."));
+#endif
+	}
+
+	return l;
+}
+
+/* Parse and evaluate multiplication and division expressions */
+static struct val *
+eval4(void)
+{
+	struct val     *l, *r;
+	enum token	op;
+
+	l = eval5();
+	while ((op = token) == MUL || op == DIV || op == MOD) {
+		nexttoken(0);
+		r = eval5();
+
+		if (!to_integer(l) || !to_integer(r)) {
+			longjmp(g_expr_jmp, errx(2, "non-numeric argument"));
+		}
+
+		if (op == MUL) {
+			l->u.i *= r->u.i;
+		} else {
+			if (r->u.i == 0) {
+				longjmp(g_expr_jmp, errx(2, "division by zero"));
+			}
+			if (op == DIV) {
+				l->u.i /= r->u.i;
+			} else {
+				l->u.i %= r->u.i;
+			}
+		}
+
+		free_value(r);
+	}
+
+	return l;
+}
+
+/* Parse and evaluate addition and subtraction expressions */
+static struct val *
+eval3(void)
+{
+	struct val     *l, *r;
+	enum token	op;
+
+	l = eval4();
+	while ((op = token) == ADD || op == SUB) {
+		nexttoken(0);
+		r = eval4();
+
+		if (!to_integer(l) || !to_integer(r)) {
+			longjmp(g_expr_jmp, errx(2, "non-numeric argument"));
+		}
+
+		if (op == ADD) {
+			l->u.i += r->u.i;
+		} else {
+			l->u.i -= r->u.i;
+		}
+
+		free_value(r);
+	}
+
+	return l;
+}
+
+/* Parse and evaluate comparison expressions */
+static struct val *
+eval2(void)
+{
+	struct val     *l, *r;
+	enum token	op;
+	int		v = 0, li, ri;
+
+	l = eval3();
+	while ((op = token) == EQ || op == NE || op == LT || op == GT ||
+	    op == LE || op == GE) {
+		nexttoken(0);
+		r = eval3();
+
+		if (is_integer(l, &li) && is_integer(r, &ri)) {
+			switch (op) {
+			case GT:
+				v = (li >  ri);
+				break;
+			case GE:
+				v = (li >= ri);
+				break;
+			case LT:
+				v = (li <  ri);
+				break;
+			case LE:
+				v = (li <= ri);
+				break;
+			case EQ:
+				v = (li == ri);
+				break;
+			case NE:
+				v = (li != ri);
+				break;
+			default:
+				break;
+			}
+		} else {
+			to_string(l);
+			to_string(r);
+
+			switch (op) {
+			case GT:
+				v = (strcoll(l->u.s, r->u.s) > 0);
+				break;
+			case GE:
+				v = (strcoll(l->u.s, r->u.s) >= 0);
+				break;
+			case LT:
+				v = (strcoll(l->u.s, r->u.s) < 0);
+				break;
+			case LE:
+				v = (strcoll(l->u.s, r->u.s) <= 0);
+				break;
+			case EQ:
+				v = (strcoll(l->u.s, r->u.s) == 0);
+				break;
+			case NE:
+				v = (strcoll(l->u.s, r->u.s) != 0);
+				break;
+			default:
+				break;
+			}
+		}
+
+		free_value(l);
+		free_value(r);
+		l = make_int(v);
+	}
+
+	return l;
+}
+
+/* Parse and evaluate & expressions */
+static struct val *
+eval1(void)
+{
+	struct val     *l, *r;
+
+	l = eval2();
+	while (token == AND) {
+		nexttoken(0);
+		r = eval2();
+
+		if (is_zero_or_null(l) || is_zero_or_null(r)) {
+			free_value(l);
+			free_value(r);
+			l = make_int(0);
+		} else {
+			free_value(r);
+		}
+	}
+
+	return l;
+}
+
+/* Parse and evaluate | expressions */
+static struct val *
+eval0(void)
+{
+	struct val     *l, *r;
+
+	l = eval1();
+	while (token == OR) {
+		nexttoken(0);
+		r = eval1();
+
+		if (is_zero_or_null(l)) {
+			free_value(l);
+			l = r;
+		} else {
+			free_value(r);
+		}
+	}
+
+	return l;
+}
+
+
+int
+kmk_builtin_expr(int argc, char *argv[], char **envp)
+{
+	struct val     *vp;
+	int rval;
+
+	/* re-init globals */
+	token = 0;
+	tokval = 0;
+	av = 0;
+	expr_mem_init();
+
+#ifdef kmk_builtin_expr /* kmk already does this. */
+	(void) setlocale(LC_ALL, "");
+#endif
+
+	if (argc > 1 && !strcmp(argv[1], "--"))
+		argv++;
+
+	av = argv + 1;
+
+	rval = setjmp(g_expr_jmp);
+	if (!rval) {
+		nexttoken(0);
+		vp = eval0();
+
+		if (token != EOI) {
+			error();
+			/* NOTREACHED */
+		}
+
+		if (vp->type == integer)
+			printf("%d\n", vp->u.i);
+		else
+			printf("%s\n", vp->u.s);
+
+		rval = is_zero_or_null(vp);
+	}
+	/* else: longjmp */
+
+	/* cleanup */
+	expr_mem_cleanup();
+	return rval;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/fts.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/fts.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/fts.c	(revision 1780)
@@ -0,0 +1,1361 @@
+/*	$NetBSD: __fts13.c,v 1.44 2005/01/19 00:59:48 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+/*#include <sys/cdefs.h>*/
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)fts.c	8.6 (Berkeley) 8/14/94";
+#else
+__RCSID("$NetBSD: __fts13.c,v 1.44 2005/01/19 00:59:48 mycroft Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*#include "namespace.h"*/
+#ifndef _MSC_VER
+#include <sys/param.h>
+#endif
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "ftsfake.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __sun__
+# include "solfakes.h"
+# ifndef __XOPEN_OR_POSIX
+#  define dirfd(dir) ((dir)->dd_fd)
+#else
+#  define dirfd(dir) ((dir)->d_fd)
+#endif
+#endif
+#ifdef _MSC_VER
+# include "mscfakes.h"
+# define dirfd(dir) -1
+#endif
+
+#if ! HAVE_NBTOOL_CONFIG_H
+#ifndef __sun__
+#define HAVE_STRUCT_DIRENT_D_NAMLEN 1
+#endif
+#endif
+
+#if 0
+#ifdef __weak_alias
+#ifdef __LIBC12_SOURCE__
+__weak_alias(fts_children,_fts_children)
+__weak_alias(fts_close,_fts_close)
+__weak_alias(fts_open,_fts_open)
+__weak_alias(fts_read,_fts_read)
+__weak_alias(fts_set,_fts_set)
+#endif /* __LIBC12_SOURCE__ */
+#endif /* __weak_alias */
+#endif
+
+#ifdef __LIBC12_SOURCE__
+#define	STAT	stat12
+#else
+#define	STAT	stat
+#endif
+
+#ifdef __LIBC12_SOURCE__
+__warn_references(fts_children,
+    "warning: reference to compatibility fts_children();"
+    " include <fts.h> for correct reference")
+__warn_references(fts_close,
+    "warning: reference to compatibility fts_close();"
+    " include <fts.h> for correct reference")
+__warn_references(fts_open,
+    "warning: reference to compatibility fts_open();"
+    " include <fts.h> for correct reference")
+__warn_references(fts_read,
+    "warning: reference to compatibility fts_read();"
+    " include <fts.h> for correct reference")
+__warn_references(fts_set,
+    "warning: reference to compatibility fts_set();"
+    " include <fts.h> for correct reference")
+#endif
+
+static FTSENT	*fts_alloc(FTS *, const char *, size_t);
+static FTSENT	*fts_build(FTS *, int);
+static void	 fts_lfree(FTSENT *);
+static void	 fts_load(FTS *, FTSENT *);
+static size_t	 fts_maxarglen(char * const *);
+static size_t	 fts_pow2(size_t);
+static int	 fts_palloc(FTS *, size_t);
+static void	 fts_padjust(FTS *, FTSENT *);
+static FTSENT	*fts_sort(FTS *, FTSENT *, size_t);
+static u_short	 fts_stat(FTS *, FTSENT *, int);
+static int	 fts_safe_changedir(const FTS *, const FTSENT *, int,
+    const char *);
+
+#ifdef _MSC_VER
+#undef HAVE_STRUCT_DIRENT_D_NAMLEN
+#undef HAVE_FCHDIR
+#endif
+
+#if defined(__EMX__) || defined(_MSC_VER)
+# define NEED_STRRSLASH
+# define IS_SLASH(ch)   ( (ch) == '/' || (ch) == '\\' )
+#else
+# define HAVE_FCHDIR
+# define IS_SLASH(ch)   ( (ch) == '/' )
+#endif
+
+#define	ISDOT(a)	(a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+#define	CLR(opt)	(sp->fts_options &= ~(opt))
+#define	ISSET(opt)	(sp->fts_options & (opt))
+#define	SET(opt)	(sp->fts_options |= (opt))
+
+#define	CHDIR(sp, path)	(!ISSET(FTS_NOCHDIR) && chdir(path))
+#ifdef HAVE_FCHDIR
+#define	FCHDIR(sp, fd)	(!ISSET(FTS_NOCHDIR) && fchdir(fd))
+#else
+#define	FCHDIR(sp, rdir) CHDIR(sp, rdir)
+#endif
+
+
+/* fts_build flags */
+#define	BCHILD		1		/* fts_children */
+#define	BNAMES		2		/* fts_children, names only */
+#define	BREAD		3		/* fts_read */
+
+#ifndef DTF_HIDEW
+#undef FTS_WHITEOUT
+#endif
+
+#ifndef _DIAGASSERT
+#define _DIAGASSERT assert
+#endif
+
+
+FTS *
+fts_open(argv, options, compar)
+	char * const *argv;
+	int options;
+	int (*compar)(const FTSENT **, const FTSENT **);
+{
+	FTS *sp;
+	FTSENT *p, *root;
+	size_t nitems;
+	FTSENT *parent, *tmp = NULL;	/* pacify gcc */
+	size_t len;
+
+	_DIAGASSERT(argv != NULL);
+
+	/* Options check. */
+	if (options & ~FTS_OPTIONMASK) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/* Allocate/initialize the stream */
+	if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
+		return (NULL);
+	memset(sp, 0, sizeof(FTS));
+	sp->fts_compar = compar;
+	sp->fts_options = options;
+
+	/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+	if (ISSET(FTS_LOGICAL))
+		SET(FTS_NOCHDIR);
+
+	/*
+	 * Start out with 1K of path space, and enough, in any case,
+	 * to hold the user's paths.
+	 */
+	if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+		goto mem1;
+
+	/* Allocate/initialize root's parent. */
+	if ((parent = fts_alloc(sp, "", 0)) == NULL)
+		goto mem2;
+	parent->fts_level = FTS_ROOTPARENTLEVEL;
+
+	/* Allocate/initialize root(s). */
+	for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
+		/* Don't allow zero-length paths. */
+		if ((len = strlen(*argv)) == 0) {
+			errno = ENOENT;
+			goto mem3;
+		}
+
+		if ((p = fts_alloc(sp, *argv, len)) == NULL)
+			goto mem3;
+		p->fts_level = FTS_ROOTLEVEL;
+		p->fts_parent = parent;
+		p->fts_accpath = p->fts_name;
+		p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+
+		/* Command-line "." and ".." are real directories. */
+		if (p->fts_info == FTS_DOT)
+			p->fts_info = FTS_D;
+
+		/*
+		 * If comparison routine supplied, traverse in sorted
+		 * order; otherwise traverse in the order specified.
+		 */
+		if (compar) {
+			p->fts_link = root;
+			root = p;
+		} else {
+			p->fts_link = NULL;
+			if (root == NULL)
+				tmp = root = p;
+			else {
+				tmp->fts_link = p;
+				tmp = p;
+			}
+		}
+	}
+	if (compar && nitems > 1)
+		root = fts_sort(sp, root, nitems);
+
+	/*
+	 * Allocate a dummy pointer and make fts_read think that we've just
+	 * finished the node before the root(s); set p->fts_info to FTS_INIT
+	 * so that everything about the "current" node is ignored.
+	 */
+	if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+		goto mem3;
+	sp->fts_cur->fts_link = root;
+	sp->fts_cur->fts_info = FTS_INIT;
+
+	/*
+	 * If using chdir(2), grab a file descriptor pointing to dot to insure
+	 * that we can get back here; this could be avoided for some paths,
+	 * but almost certainly not worth the effort.  Slashes, symbolic links,
+	 * and ".." are all fairly nasty problems.  Note, if we can't get the
+	 * descriptor we run anyway, just more slowly.
+	 */
+	if (!ISSET(FTS_NOCHDIR)) {
+#ifdef HAVE_FCHDIR
+		if ((sp->fts_rfd = open(".", O_RDONLY, 0)) == -1)
+			SET(FTS_NOCHDIR);
+		else if (fcntl(sp->fts_rfd, F_SETFD, FD_CLOEXEC) == -1) {
+			close(sp->fts_rfd);
+			SET(FTS_NOCHDIR);
+		}
+#else
+		if ((sp->fts_rdir = getcwd(NULL, 0)) != NULL)
+			SET(FTS_NOCHDIR);
+#endif
+	}
+
+	return (sp);
+
+mem3:	fts_lfree(root);
+	free(parent);
+mem2:	free(sp->fts_path);
+mem1:	free(sp);
+	return (NULL);
+}
+
+#ifdef NEED_STRRSLASH
+static char *strrslash(register char *psz)
+{
+    register char ch;
+    char *pszLast = NULL;
+    for (; (ch = *psz); psz++)
+        switch (ch)
+        {
+            case '/':
+            case '\\':
+            case ':':
+                pszLast = psz;
+                break;
+        }
+    return pszLast;
+}
+#endif
+
+static void
+fts_load(sp, p)
+	FTS *sp;
+	FTSENT *p;
+{
+	size_t len;
+	char *cp;
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(p != NULL);
+
+	/*
+	 * Load the stream structure for the next traversal.  Since we don't
+	 * actually enter the directory until after the preorder visit, set
+	 * the fts_accpath field specially so the chdir gets done to the right
+	 * place and the user can access the first node.  From fts_open it's
+	 * known that the path will fit.
+	 */
+	len = p->fts_pathlen = p->fts_namelen;
+	memmove(sp->fts_path, p->fts_name, len + 1);
+#ifdef NEED_STRRSLASH
+	if ((cp = strrslash(p->fts_name)) && (cp != p->fts_name || cp[1])) {
+#else
+	if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+#endif
+		len = strlen(++cp);
+		memmove(p->fts_name, cp, len + 1);
+		p->fts_namelen = len;
+	}
+	p->fts_accpath = p->fts_path = sp->fts_path;
+	sp->fts_dev = p->fts_dev;
+}
+
+int
+fts_close(sp)
+	FTS *sp;
+{
+	FTSENT *freep, *p;
+	int saved_errno = 0;
+
+	_DIAGASSERT(sp != NULL);
+
+	/*
+	 * This still works if we haven't read anything -- the dummy structure
+	 * points to the root list, so we step through to the end of the root
+	 * list which has a valid parent pointer.
+	 */
+	if (sp->fts_cur) {
+#ifndef _MSC_VER
+		if (ISSET(FTS_SYMFOLLOW))
+			(void)close(sp->fts_cur->fts_symfd);
+#endif
+		for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+			freep = p;
+			p = p->fts_link ? p->fts_link : p->fts_parent;
+			free(freep);
+		}
+		free(p);
+	}
+
+	/* Free up child linked list, sort array, path buffer. */
+	if (sp->fts_child)
+		fts_lfree(sp->fts_child);
+	if (sp->fts_array)
+		free(sp->fts_array);
+	free(sp->fts_path);
+
+	/* Return to original directory, save errno if necessary. */
+	if (!ISSET(FTS_NOCHDIR)) {
+#ifdef HAVE_FCHDIR
+		if (fchdir(sp->fts_rfd))
+			saved_errno = errno;
+		(void)close(sp->fts_rfd);
+#else
+		if (chdir(sp->fts_rdir))
+			saved_errno =  errno;
+        free(sp->fts_rdir);
+		sp->fts_rdir = NULL;
+#endif
+	}
+
+	/* Free up the stream pointer. */
+	free(sp);
+	/* ISSET() is illegal after this, since the macro touches sp */
+
+	/* Set errno and return. */
+	if (saved_errno) {
+		errno = saved_errno;
+		return (-1);
+	}
+	return (0);
+}
+
+/*
+ * Special case a root of "/" so that slashes aren't appended which would
+ * cause paths to be written as "//foo".
+ */
+#define	NAPPEND(p)							\
+	(p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 &&	\
+	    IS_SLASH(p->fts_path[0]) ? 0 : p->fts_pathlen)
+
+FTSENT *
+fts_read(sp)
+	FTS *sp;
+{
+	FTSENT *p, *tmp;
+	int instr;
+	char *t;
+	int saved_errno;
+
+	_DIAGASSERT(sp != NULL);
+
+	/* If finished or unrecoverable error, return NULL. */
+	if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+		return (NULL);
+
+	/* Set current node pointer. */
+	p = sp->fts_cur;
+
+	/* Save and zero out user instructions. */
+	instr = p->fts_instr;
+	p->fts_instr = FTS_NOINSTR;
+
+	/* Any type of file may be re-visited; re-stat and re-turn. */
+	if (instr == FTS_AGAIN) {
+		p->fts_info = fts_stat(sp, p, 0);
+		return (p);
+	}
+
+	/*
+	 * Following a symlink -- SLNONE test allows application to see
+	 * SLNONE and recover.  If indirecting through a symlink, have
+	 * keep a pointer to current location.  If unable to get that
+	 * pointer, follow fails.
+	 */
+	if (instr == FTS_FOLLOW &&
+	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+		p->fts_info = fts_stat(sp, p, 1);
+		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+#ifdef HAVE_FCHDIR
+			if ((p->fts_symfd = open(".", O_RDONLY, 0)) == -1) {
+				p->fts_errno = errno;
+				p->fts_info = FTS_ERR;
+			} else if (fcntl(p->fts_symfd, F_SETFD, FD_CLOEXEC) == -1) {
+				p->fts_errno = errno;
+				p->fts_info = FTS_ERR;
+				close(p->fts_symfd);
+			} else
+				p->fts_flags |= FTS_SYMFOLLOW;
+#endif
+		}
+		return (p);
+	}
+
+	/* Directory in pre-order. */
+	if (p->fts_info == FTS_D) {
+		/* If skipped or crossed mount point, do post-order visit. */
+		if (instr == FTS_SKIP ||
+		    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
+#ifdef HAVE_FCHDIR
+			if (p->fts_flags & FTS_SYMFOLLOW)
+				(void)close(p->fts_symfd);
+#endif
+			if (sp->fts_child) {
+				fts_lfree(sp->fts_child);
+				sp->fts_child = NULL;
+			}
+			p->fts_info = FTS_DP;
+			return (p);
+		}
+
+		/* Rebuild if only read the names and now traversing. */
+		if (sp->fts_child && ISSET(FTS_NAMEONLY)) {
+			CLR(FTS_NAMEONLY);
+			fts_lfree(sp->fts_child);
+			sp->fts_child = NULL;
+		}
+
+		/*
+		 * Cd to the subdirectory.
+		 *
+		 * If have already read and now fail to chdir, whack the list
+		 * to make the names come out right, and set the parent errno
+		 * so the application will eventually get an error condition.
+		 * Set the FTS_DONTCHDIR flag so that when we logically change
+		 * directories back to the parent we don't do a chdir.
+		 *
+		 * If haven't read do so.  If the read fails, fts_build sets
+		 * FTS_STOP or the fts_info field of the node.
+		 */
+		if (sp->fts_child) {
+			if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+				p->fts_errno = errno;
+				p->fts_flags |= FTS_DONTCHDIR;
+				for (p = sp->fts_child; p; p = p->fts_link)
+					p->fts_accpath =
+					    p->fts_parent->fts_accpath;
+			}
+		} else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+			if (ISSET(FTS_STOP))
+				return (NULL);
+			return (p);
+		}
+		p = sp->fts_child;
+		sp->fts_child = NULL;
+		goto name;
+	}
+
+	/* Move to the next node on this level. */
+next:	tmp = p;
+	if ((p = p->fts_link) != NULL) {
+		free(tmp);
+
+		/*
+		 * If reached the top, return to the original directory, and
+		 * load the paths for the next root.
+		 */
+		if (p->fts_level == FTS_ROOTLEVEL) {
+#ifdef HAVE_FCHDIR
+			if (FCHDIR(sp, sp->fts_rfd)) {
+#else
+			if (CHDIR(sp, sp->fts_rdir)) {
+#endif
+				SET(FTS_STOP);
+				return (NULL);
+			}
+			fts_load(sp, p);
+			return (sp->fts_cur = p);
+		}
+
+		/*
+		 * User may have called fts_set on the node.  If skipped,
+		 * ignore.  If followed, get a file descriptor so we can
+		 * get back if necessary.
+		 */
+		if (p->fts_instr == FTS_SKIP)
+			goto next;
+		if (p->fts_instr == FTS_FOLLOW) {
+			p->fts_info = fts_stat(sp, p, 1);
+			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+#ifdef HAVE_FCHDIR
+				if ((p->fts_symfd =
+				    open(".", O_RDONLY, 0)) == -1) {
+					p->fts_errno = errno;
+					p->fts_info = FTS_ERR;
+				} else if (fcntl(p->fts_symfd, F_SETFD, FD_CLOEXEC) == -1) {
+					p->fts_errno = errno;
+					p->fts_info = FTS_ERR;
+					close(p->fts_symfd);
+				} else
+					p->fts_flags |= FTS_SYMFOLLOW;
+#endif
+			}
+			p->fts_instr = FTS_NOINSTR;
+		}
+
+name:		t = sp->fts_path + NAPPEND(p->fts_parent);
+		*t++ = '/';
+		memmove(t, p->fts_name, (size_t)(p->fts_namelen + 1));
+		return (sp->fts_cur = p);
+	}
+
+	/* Move up to the parent node. */
+	p = tmp->fts_parent;
+	free(tmp);
+
+	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+		/*
+		 * Done; free everything up and set errno to 0 so the user
+		 * can distinguish between error and EOF.
+		 */
+		free(p);
+		errno = 0;
+		return (sp->fts_cur = NULL);
+	}
+
+	/* Nul terminate the pathname. */
+	sp->fts_path[p->fts_pathlen] = '\0';
+
+	/*
+	 * Return to the parent directory.  If at a root node or came through
+	 * a symlink, go back through the file descriptor.  Otherwise, cd up
+	 * one directory.
+	 */
+	if (p->fts_level == FTS_ROOTLEVEL) {
+#ifdef HAVE_FCHDIR
+		if (FCHDIR(sp, sp->fts_rfd)) {
+#else
+		if (CHDIR(sp, sp->fts_rdir)) {
+#endif
+			SET(FTS_STOP);
+			return (NULL);
+		}
+#ifdef HAVE_FCHDIR
+	} else if (p->fts_flags & FTS_SYMFOLLOW) {
+		if (FCHDIR(sp, p->fts_symfd)) {
+			saved_errno = errno;
+			(void)close(p->fts_symfd);
+			errno = saved_errno;
+			SET(FTS_STOP);
+			return (NULL);
+		}
+		(void)close(p->fts_symfd);
+#else
+        (void)saved_errno;
+#endif
+	} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+	    fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+		SET(FTS_STOP);
+		return (NULL);
+	}
+	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+	return (sp->fts_cur = p);
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set.  An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+fts_set(sp, p, instr)
+	FTS *sp;
+	FTSENT *p;
+	int instr;
+{
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(p != NULL);
+
+	if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
+		errno = EINVAL;
+		return (1);
+	}
+	p->fts_instr = instr;
+	return (0);
+}
+
+FTSENT *
+fts_children(sp, instr)
+	FTS *sp;
+	int instr;
+{
+	FTSENT *p;
+#ifdef HAVE_FCHDIR
+	int fd;
+#else
+	char *pszRoot;
+	int rc;
+#endif
+
+	_DIAGASSERT(sp != NULL);
+
+	if (instr && instr != FTS_NAMEONLY) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/* Set current node pointer. */
+	p = sp->fts_cur;
+
+	/*
+	 * Errno set to 0 so user can distinguish empty directory from
+	 * an error.
+	 */
+	errno = 0;
+
+	/* Fatal errors stop here. */
+	if (ISSET(FTS_STOP))
+		return (NULL);
+
+	/* Return logical hierarchy of user's arguments. */
+	if (p->fts_info == FTS_INIT)
+		return (p->fts_link);
+
+	/*
+	 * If not a directory being visited in pre-order, stop here.  Could
+	 * allow FTS_DNR, assuming the user has fixed the problem, but the
+	 * same effect is available with FTS_AGAIN.
+	 */
+	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+		return (NULL);
+
+	/* Free up any previous child list. */
+	if (sp->fts_child)
+		fts_lfree(sp->fts_child);
+
+	if (instr == FTS_NAMEONLY) {
+		SET(FTS_NAMEONLY);
+		instr = BNAMES;
+	} else
+		instr = BCHILD;
+
+	/*
+	 * If using chdir on a relative path and called BEFORE fts_read does
+	 * its chdir to the root of a traversal, we can lose -- we need to
+	 * chdir into the subdirectory, and we don't know where the current
+	 * directory is, so we can't get back so that the upcoming chdir by
+	 * fts_read will work.
+	 */
+	if (p->fts_level != FTS_ROOTLEVEL || IS_SLASH(p->fts_accpath[0]) ||
+	    ISSET(FTS_NOCHDIR))
+		return (sp->fts_child = fts_build(sp, instr));
+
+#ifdef HAVE_FCHDIR
+	if ((fd = open(".", O_RDONLY, 0)) == -1)
+#else
+	if ((pszRoot = getcwd(NULL, 0)) == NULL)
+#endif
+		return (sp->fts_child = NULL);
+	sp->fts_child = fts_build(sp, instr);
+#ifdef HAVE_FCHDIR
+	if (fchdir(fd)) {
+		(void)close(fd);
+		return (NULL);
+	}
+	(void)close(fd);
+#else
+	rc = chdir(pszRoot);
+	free(pszRoot);
+	if (rc)
+		return (NULL);
+#endif
+
+	return (sp->fts_child);
+}
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here.  The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read.  There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly.  First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry.  Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls.  The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT *
+fts_build(sp, type)
+	FTS *sp;
+	int type;
+{
+	struct dirent *dp;
+	FTSENT *p, *head;
+	size_t nitems;
+	FTSENT *cur, *tail;
+	DIR *dirp;
+	int adjust, cderrno, descend, len, level, nlinks, saved_errno, nostat;
+	size_t maxlen;
+#ifdef FTS_WHITEOUT
+	int oflag;
+#endif
+	char *cp = NULL;	/* pacify gcc */
+
+	_DIAGASSERT(sp != NULL);
+
+	/* Set current node pointer. */
+	cur = sp->fts_cur;
+
+	/*
+	 * Open the directory for reading.  If this fails, we're done.
+	 * If being called from fts_read, set the fts_info field.
+	 */
+#ifdef FTS_WHITEOUT
+	if (ISSET(FTS_WHITEOUT))
+		oflag = DTF_NODUP|DTF_REWIND;
+	else
+		oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
+#else
+#define __opendir2(path, flag) opendir(path)
+#endif
+	if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
+		if (type == BREAD) {
+			cur->fts_info = FTS_DNR;
+			cur->fts_errno = errno;
+		}
+		return (NULL);
+	}
+
+	/*
+	 * Nlinks is the number of possible entries of type directory in the
+	 * directory if we're cheating on stat calls, 0 if we're not doing
+	 * any stat calls at all, -1 if we're doing stats on everything.
+	 */
+	if (type == BNAMES) {
+		nlinks = 0;
+		nostat = 1;
+	} else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+		nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+		nostat = 1;
+	} else {
+		nlinks = -1;
+		nostat = 0;
+	}
+
+#ifdef notdef
+	(void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
+	(void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
+	    ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
+#endif
+	/*
+	 * If we're going to need to stat anything or we want to descend
+	 * and stay in the directory, chdir.  If this fails we keep going,
+	 * but set a flag so we don't chdir after the post-order visit.
+	 * We won't be able to stat anything, but we can still return the
+	 * names themselves.  Note, that since fts_read won't be able to
+	 * chdir into the directory, it will have to return different path
+	 * names than before, i.e. "a/b" instead of "b".  Since the node
+	 * has already been visited in pre-order, have to wait until the
+	 * post-order visit to return the error.  There is a special case
+	 * here, if there was nothing to stat then it's not an error to
+	 * not be able to stat.  This is all fairly nasty.  If a program
+	 * needed sorted entries or stat information, they had better be
+	 * checking FTS_NS on the returned nodes.
+	 */
+	cderrno = 0;
+	if (nlinks || type == BREAD) {
+#ifdef HAVE_FCHDIR
+		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
+#else
+		if (fts_safe_changedir(sp, cur, dirfd(dirp), cur->fts_accpath)) {
+#endif
+			if (nlinks && type == BREAD)
+				cur->fts_errno = errno;
+			cur->fts_flags |= FTS_DONTCHDIR;
+			descend = 0;
+			cderrno = errno;
+		} else
+			descend = 1;
+	} else
+		descend = 0;
+
+	/*
+	 * Figure out the max file name length that can be stored in the
+	 * current path -- the inner loop allocates more path as necessary.
+	 * We really wouldn't have to do the maxlen calculations here, we
+	 * could do them in fts_read before returning the path, but it's a
+	 * lot easier here since the length is part of the dirent structure.
+	 *
+	 * If not changing directories set a pointer so that can just append
+	 * each new name into the path.
+	 */
+	len = NAPPEND(cur);
+	if (ISSET(FTS_NOCHDIR)) {
+		cp = sp->fts_path + len;
+		*cp++ = '/';
+	}
+	len++;
+	maxlen = sp->fts_pathlen - len;
+
+	level = cur->fts_level + 1;
+
+	/* Read the directory, attaching each entry to the `link' pointer. */
+	adjust = 0;
+	for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)) != NULL;) {
+		size_t dlen;
+
+		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+			continue;
+
+#if HAVE_STRUCT_DIRENT_D_NAMLEN
+		dlen = dp->d_namlen;
+#else
+		dlen = strlen(dp->d_name);
+#endif
+		if ((p = fts_alloc(sp, dp->d_name, dlen)) == NULL)
+			goto mem1;
+		if (dlen >= maxlen) {	/* include space for NUL */
+			if (fts_palloc(sp, len + dlen + 1)) {
+				/*
+				 * No more memory for path or structures.  Save
+				 * errno, free up the current structure and the
+				 * structures already allocated.
+				 */
+mem1:				saved_errno = errno;
+				if (p)
+					free(p);
+				fts_lfree(head);
+				(void)closedir(dirp);
+				errno = saved_errno;
+				cur->fts_info = FTS_ERR;
+				SET(FTS_STOP);
+				return (NULL);
+			}
+			adjust = 1;
+			if (ISSET(FTS_NOCHDIR))
+				cp = sp->fts_path + len;
+			maxlen = sp->fts_pathlen - len;
+		}
+
+		p->fts_pathlen = len + dlen;
+		p->fts_parent = sp->fts_cur;
+		p->fts_level = level;
+
+#ifdef FTS_WHITEOUT
+		if (dp->d_type == DT_WHT)
+			p->fts_flags |= FTS_ISW;
+#endif
+
+		if (cderrno) {
+			if (nlinks) {
+				p->fts_info = FTS_NS;
+				p->fts_errno = cderrno;
+			} else
+				p->fts_info = FTS_NSOK;
+			p->fts_accpath = cur->fts_accpath;
+		} else if (nlinks == 0
+#ifdef DT_DIR
+		    || (nostat &&
+		    dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+#endif
+		    ) {
+			p->fts_accpath =
+			    ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
+			p->fts_info = FTS_NSOK;
+		} else {
+			/* Build a file name for fts_stat to stat. */
+			if (ISSET(FTS_NOCHDIR)) {
+				p->fts_accpath = p->fts_path;
+				memmove(cp, p->fts_name,
+				        (size_t)(p->fts_namelen + 1));
+			} else
+				p->fts_accpath = p->fts_name;
+			/* Stat it. */
+			p->fts_info = fts_stat(sp, p, 0);
+
+			/* Decrement link count if applicable. */
+			if (nlinks > 0 && (p->fts_info == FTS_D ||
+			    p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+				--nlinks;
+		}
+
+		/* We walk in directory order so "ls -f" doesn't get upset. */
+		p->fts_link = NULL;
+		if (head == NULL)
+			head = tail = p;
+		else {
+			tail->fts_link = p;
+			tail = p;
+		}
+		++nitems;
+	}
+	(void)closedir(dirp);
+
+	/*
+	 * If had to realloc the path, adjust the addresses for the rest
+	 * of the tree.
+	 */
+	if (adjust)
+		fts_padjust(sp, head);
+
+	/*
+	 * If not changing directories, reset the path back to original
+	 * state.
+	 */
+	if (ISSET(FTS_NOCHDIR)) {
+		if (cp - 1 > sp->fts_path)
+			--cp;
+		*cp = '\0';
+	}
+
+	/*
+	 * If descended after called from fts_children or after called from
+	 * fts_read and nothing found, get back.  At the root level we use
+	 * the saved fd; if one of fts_open()'s arguments is a relative path
+	 * to an empty directory, we wind up here with no other way back.  If
+	 * can't get back, we're done.
+	 */
+	if (descend && (type == BCHILD || !nitems) &&
+	    (cur->fts_level == FTS_ROOTLEVEL ?
+#ifdef HAVE_FCHDIR
+	    FCHDIR(sp, sp->fts_rfd) :
+#else
+	    CHDIR(sp, sp->fts_rdir) :
+#endif
+	    fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+		cur->fts_info = FTS_ERR;
+		SET(FTS_STOP);
+		return (NULL);
+	}
+
+	/* If didn't find anything, return NULL. */
+	if (!nitems) {
+		if (type == BREAD)
+			cur->fts_info = FTS_DP;
+		return (NULL);
+	}
+
+	/* Sort the entries. */
+	if (sp->fts_compar && nitems > 1)
+		head = fts_sort(sp, head, nitems);
+	return (head);
+}
+
+static u_short
+fts_stat(sp, p, follow)
+	FTS *sp;
+	FTSENT *p;
+	int follow;
+{
+	FTSENT *t;
+	dev_t dev;
+	ino_t ino;
+	struct STAT *sbp, sb;
+	int saved_errno;
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(p != NULL);
+
+	/* If user needs stat info, stat buffer already allocated. */
+	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+#ifdef FTS_WHITEOUT
+	/* check for whiteout */
+	if (p->fts_flags & FTS_ISW) {
+		if (sbp != &sb) {
+			memset(sbp, '\0', sizeof (*sbp));
+			sbp->st_mode = S_IFWHT;
+		}
+		return (FTS_W);
+	}
+#endif
+
+	/*
+	 * If doing a logical walk, or application requested FTS_FOLLOW, do
+	 * a stat(2).  If that fails, check for a non-existent symlink.  If
+	 * fail, set the errno from the stat call.
+	 */
+	if (ISSET(FTS_LOGICAL) || follow) {
+		if (stat(p->fts_accpath, sbp)) {
+			saved_errno = errno;
+			if (!lstat(p->fts_accpath, sbp)) {
+				errno = 0;
+				return (FTS_SLNONE);
+			}
+			p->fts_errno = saved_errno;
+			goto err;
+		}
+	} else if (lstat(p->fts_accpath, sbp)) {
+		p->fts_errno = errno;
+err:		memset(sbp, 0, sizeof(struct STAT));
+		return (FTS_NS);
+	}
+
+	if (S_ISDIR(sbp->st_mode)) {
+		/*
+		 * Set the device/inode.  Used to find cycles and check for
+		 * crossing mount points.  Also remember the link count, used
+		 * in fts_build to limit the number of stat calls.  It is
+		 * understood that these fields are only referenced if fts_info
+		 * is set to FTS_D.
+		 */
+		dev = p->fts_dev = sbp->st_dev;
+		ino = p->fts_ino = sbp->st_ino;
+		p->fts_nlink = sbp->st_nlink;
+
+		if (ISDOT(p->fts_name))
+			return (FTS_DOT);
+
+		/*
+		 * Cycle detection is done by brute force when the directory
+		 * is first encountered.  If the tree gets deep enough or the
+		 * number of symbolic links to directories is high enough,
+		 * something faster might be worthwhile.
+		 */
+
+#ifdef _MSC_VER
+		if (ino && dev) /** @todo ino emulation on windows... */
+#endif
+		for (t = p->fts_parent;
+		    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+			if (ino == t->fts_ino && dev == t->fts_dev) {
+				p->fts_cycle = t;
+				return (FTS_DC);
+			}
+		return (FTS_D);
+	}
+	if (S_ISLNK(sbp->st_mode))
+		return (FTS_SL);
+	if (S_ISREG(sbp->st_mode))
+		return (FTS_F);
+	return (FTS_DEFAULT);
+}
+
+static FTSENT *
+fts_sort(sp, head, nitems)
+	FTS *sp;
+	FTSENT *head;
+	size_t nitems;
+{
+	FTSENT **ap, *p;
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(head != NULL);
+
+	/*
+	 * Construct an array of pointers to the structures and call qsort(3).
+	 * Reassemble the array in the order returned by qsort.  If unable to
+	 * sort for memory reasons, return the directory entries in their
+	 * current order.  Allocate enough space for the current needs plus
+	 * 40 so don't realloc one entry at a time.
+	 */
+	if (nitems > sp->fts_nitems) {
+		FTSENT **new;
+
+		new = realloc(sp->fts_array, sizeof(FTSENT *) * (nitems + 40));
+		if (new == 0)
+			return (head);
+		sp->fts_array = new;
+		sp->fts_nitems = nitems + 40;
+	}
+	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+		*ap++ = p;
+	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *),
+		(int (*)(const void *, const void *))sp->fts_compar);
+	for (head = *(ap = sp->fts_array); --nitems; ++ap)
+		ap[0]->fts_link = ap[1];
+	ap[0]->fts_link = NULL;
+	return (head);
+}
+
+static FTSENT *
+fts_alloc(sp, name, namelen)
+	FTS *sp;
+	const char *name;
+	size_t namelen;
+{
+	FTSENT *p;
+	size_t len;
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(name != NULL);
+
+#if defined(ALIGNBYTES) && defined(ALIGN)
+	/*
+	 * The file name is a variable length array and no stat structure is
+	 * necessary if the user has set the nostat bit.  Allocate the FTSENT
+	 * structure, the file name and the stat structure in one chunk, but
+	 * be careful that the stat structure is reasonably aligned.  Since the
+	 * fts_name field is declared to be of size 1, the fts_name pointer is
+	 * namelen + 2 before the first possible address of the stat structure.
+	 */
+	len = sizeof(FTSENT) + namelen;
+	if (!ISSET(FTS_NOSTAT))
+		len += sizeof(struct STAT) + ALIGNBYTES;
+	if ((p = malloc(len)) == NULL)
+		return (NULL);
+
+	if (!ISSET(FTS_NOSTAT))
+		p->fts_statp =
+		    (struct STAT *)ALIGN((u_long)(p->fts_name + namelen + 2));
+#else
+	(void)len;
+	if ((p = malloc(sizeof(FTSENT) + namelen)) == NULL)
+		return (NULL);
+
+	if (!ISSET(FTS_NOSTAT))
+		if ((p->fts_statp = malloc(sizeof(struct STAT))) == NULL) {
+			free(p);
+			return (NULL);
+		}
+#endif
+
+	/* Copy the name plus the trailing NULL. */
+	memmove(p->fts_name, name, namelen + 1);
+
+	p->fts_namelen = namelen;
+	p->fts_path = sp->fts_path;
+	p->fts_errno = 0;
+	p->fts_flags = 0;
+	p->fts_instr = FTS_NOINSTR;
+	p->fts_number = 0;
+	p->fts_pointer = NULL;
+	return (p);
+}
+
+static void
+fts_lfree(head)
+	FTSENT *head;
+{
+	FTSENT *p;
+
+	/* XXX: head may be NULL ? */
+
+	/* Free a linked list of structures. */
+	while ((p = head) != NULL) {
+		head = head->fts_link;
+
+#if !defined(ALIGNBYTES) || !defined(ALIGN)
+		if (p->fts_statp)
+			free(p->fts_statp);
+#endif
+		free(p);
+	}
+}
+
+static size_t
+fts_pow2(x)
+	size_t x;
+{
+
+	x--;
+	x |= x>>1;
+	x |= x>>2;
+	x |= x>>4;
+	x |= x>>8;
+	x |= x>>16;
+#if LONG_BIT > 32
+	x |= x>>32;
+#endif
+#if LONG_BIT > 64
+	x |= x>>64;
+#endif
+	x++;
+	return (x);
+}
+
+/*
+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * though the kernel won't resolve them.  Round up the new size to a power of 2,
+ * so we don't realloc the path 2 bytes at a time.
+ */
+static int
+fts_palloc(sp, size)
+	FTS *sp;
+	size_t size;
+{
+	char *new;
+
+	_DIAGASSERT(sp != NULL);
+
+#if 1
+	/* Protect against fts_pathlen overflow. */
+	if (size > USHRT_MAX + 1) {
+		errno = ENOMEM;
+		return (1);
+	}
+#endif
+	size = fts_pow2(size);
+	new = realloc(sp->fts_path, size);
+	if (new == 0)
+		return (1);
+	sp->fts_path = new;
+	sp->fts_pathlen = size;
+	return (0);
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+fts_padjust(sp, head)
+	FTS *sp;
+	FTSENT *head;
+{
+	FTSENT *p;
+	char *addr;
+
+	_DIAGASSERT(sp != NULL);
+
+#define	ADJUST(p) do {							\
+	if ((p)->fts_accpath != (p)->fts_name)				\
+		(p)->fts_accpath =					\
+		    addr + ((p)->fts_accpath - (p)->fts_path);		\
+	(p)->fts_path = addr;						\
+} while (/*CONSTCOND*/0)
+
+	addr = sp->fts_path;
+
+	/* Adjust the current set of children. */
+	for (p = sp->fts_child; p; p = p->fts_link)
+		ADJUST(p);
+
+	/* Adjust the rest of the tree, including the current level. */
+	for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+		ADJUST(p);
+		p = p->fts_link ? p->fts_link : p->fts_parent;
+	}
+}
+
+static size_t
+fts_maxarglen(argv)
+	char * const *argv;
+{
+	size_t len, max;
+
+	_DIAGASSERT(argv != NULL);
+
+	for (max = 0; *argv; ++argv)
+		if ((len = strlen(*argv)) > max)
+			max = len;
+	return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+fts_safe_changedir(sp, p, fd, path)
+	const FTS *sp;
+	const FTSENT *p;
+	int fd;
+	const char *path;
+{
+	int oldfd = fd, ret = -1;
+	struct STAT sb;
+
+	if (ISSET(FTS_NOCHDIR))
+		return 0;
+
+#ifdef HAVE_FCHDIR
+	if (oldfd < 0 && (fd = open(path, O_RDONLY)) == -1)
+		return -1;
+
+	if (fstat(fd, &sb) == -1)
+		goto bail;
+#else
+	if (stat(path, &sb))
+		goto bail;
+#endif
+
+	if (sb.st_ino != p->fts_ino || sb.st_dev != p->fts_dev) {
+		errno = ENOENT;
+		goto bail;
+	}
+
+#ifdef HAVE_FCHDIR
+	ret = fchdir(fd);
+#else
+	ret = chdir(path);
+#endif
+
+bail:
+#ifdef HAVE_FCHDIR
+	if (oldfd < 0) {
+		int save_errno = errno;
+		(void)close(fd);
+		errno = save_errno;
+	}
+#endif
+	return ret;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/ftsfake.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/ftsfake.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/ftsfake.h	(revision 1780)
@@ -0,0 +1,176 @@
+/*	$NetBSD: fts.h,v 1.12 2005/02/03 04:39:32 perry Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)fts.h	8.3 (Berkeley) 8/14/94
+ */
+
+#ifndef	_FTS_H_
+#define	_FTS_H_
+
+#ifdef _MSC_VER
+# include "kmkbuiltin/mscfakes.h"
+#endif
+
+typedef struct {
+	struct _ftsent *fts_cur;	/* current node */
+	struct _ftsent *fts_child;	/* linked list of children */
+	struct _ftsent **fts_array;	/* sort array */
+	dev_t fts_dev;			/* starting device # */
+	char *fts_path;			/* path for this descent */
+#ifdef _MSC_VER
+	char *fts_rdir;		        /* path of root */
+#else
+	int fts_rfd;			/* fd for root */
+#endif
+	u_int fts_pathlen;		/* sizeof(path) */
+	u_int fts_nitems;		/* elements in the sort array */
+	int (*fts_compar)		/* compare function */
+		(const struct _ftsent **, const struct _ftsent **);
+
+#define	FTS_COMFOLLOW	0x001		/* follow command line symlinks */
+#define	FTS_LOGICAL	0x002		/* logical walk */
+#define	FTS_NOCHDIR	0x004		/* don't change directories */
+#define	FTS_NOSTAT	0x008		/* don't get stat info */
+#define	FTS_PHYSICAL	0x010		/* physical walk */
+#define	FTS_SEEDOT	0x020		/* return dot and dot-dot */
+#define	FTS_XDEV	0x040		/* don't cross devices */
+#ifndef _MSC_VER
+#define	FTS_WHITEOUT	0x080		/* return whiteout information */
+#endif
+#define	FTS_OPTIONMASK	0x0ff		/* valid user option mask */
+
+#define	FTS_NAMEONLY	0x100		/* (private) child names only */
+#define	FTS_STOP	0x200		/* (private) unrecoverable error */
+	int fts_options;		/* fts_open options, global flags */
+} FTS;
+
+typedef struct _ftsent {
+	struct _ftsent *fts_cycle;	/* cycle node */
+	struct _ftsent *fts_parent;	/* parent directory */
+	struct _ftsent *fts_link;	/* next file in directory */
+	long fts_number;	        /* local numeric value */
+	void *fts_pointer;	        /* local address value */
+	char *fts_accpath;		/* access path */
+	char *fts_path;			/* root path */
+	int fts_errno;			/* errno for this node */
+#ifndef _MSC_VER
+	int fts_symfd;			/* fd for symlink */
+#endif
+	u_short fts_pathlen;		/* strlen(fts_path) */
+	u_short fts_namelen;		/* strlen(fts_name) */
+
+	ino_t fts_ino;			/* inode */
+	dev_t fts_dev;			/* device */
+#ifdef __LIBC12_SOURCE__
+	u_int16_t fts_nlink;		/* link count */
+#else
+#ifndef _MSC_VER
+	nlink_t fts_nlink;		/* link count */
+#else
+	int fts_nlink;		/* link count */
+#endif
+#endif
+
+#define	FTS_ROOTPARENTLEVEL	-1
+#define	FTS_ROOTLEVEL		 0
+	short fts_level;		/* depth (-1 to N) */
+
+#define	FTS_D		 1		/* preorder directory */
+#define	FTS_DC		 2		/* directory that causes cycles */
+#define	FTS_DEFAULT	 3		/* none of the above */
+#define	FTS_DNR		 4		/* unreadable directory */
+#define	FTS_DOT		 5		/* dot or dot-dot */
+#define	FTS_DP		 6		/* postorder directory */
+#define	FTS_ERR		 7		/* error; errno is set */
+#define	FTS_F		 8		/* regular file */
+#define	FTS_INIT	 9		/* initialized only */
+#define	FTS_NS		10		/* stat(2) failed */
+#define	FTS_NSOK	11		/* no stat(2) requested */
+#define	FTS_SL		12		/* symbolic link */
+#define	FTS_SLNONE	13		/* symbolic link without target */
+#ifndef _MSC_VER
+#define	FTS_W		14		/* whiteout object */
+#endif
+	u_short fts_info;		/* user flags for FTSENT structure */
+
+#define	FTS_DONTCHDIR	 0x01		/* don't chdir .. to the parent */
+#define	FTS_SYMFOLLOW	 0x02		/* followed a symlink to get here */
+#ifndef _MSC_VER
+#define	FTS_ISW		 0x04		/* this is a whiteout object */
+#endif
+	u_short fts_flags;		/* private flags for FTSENT structure */
+
+#define	FTS_AGAIN	 1		/* read node again */
+#define	FTS_FOLLOW	 2		/* follow symbolic link */
+#define	FTS_NOINSTR	 3		/* no instructions */
+#define	FTS_SKIP	 4		/* discard node */
+	u_short fts_instr;		/* fts_set() instructions */
+
+#ifdef __LIBC12_SOURCE__
+	struct stat12 *fts_statp;	/* stat(2) information */
+#else
+	struct stat *fts_statp;		/* stat(2) information */
+#endif
+	char fts_name[1];		/* file name */
+} FTSENT;
+
+#ifndef __sun__
+#ifndef _MSC_VER
+#include <sys/cdefs.h>
+__BEGIN_DECLS
+#else
+#define __RENAME(a)
+#endif
+#endif
+
+#if defined(__LIBC12_SOURCE__) || defined(__sun__)
+FTSENT	*fts_children(FTS *, int);
+int	 fts_close(FTS *);
+FTS	*fts_open(char * const *, int,
+	    int (*)(const FTSENT **, const FTSENT **));
+FTSENT	*fts_read(FTS *);
+int	 fts_set(FTS *, FTSENT *, int);
+#else
+FTSENT	*fts_children(FTS *, int)		__RENAME(__fts_children13);
+int	 fts_close(FTS *)			__RENAME(__fts_close13);
+FTS	*fts_open(char * const *, int,
+	    int (*)(const FTSENT **, const FTSENT **))
+						__RENAME(__fts_open13);
+FTSENT	*fts_read(FTS *)			__RENAME(__fts_read13);
+int	 fts_set(FTS *, FTSENT *, int)	__RENAME(__fts_set13);
+#endif
+
+#ifndef __sun__
+#ifndef _MSC_VER
+__END_DECLS
+#endif
+#endif
+
+#endif /* !_FTS_H_ */
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/install.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/install.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/install.c	(revision 1780)
@@ -0,0 +1,1033 @@
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1987, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)xinstall.c	8.1 (Berkeley) 7/21/93";
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/xinstall/xinstall.c,v 1.66 2005/01/25 14:34:57 ssouhlal Exp $");
+#endif
+
+#ifndef _MSC_VER
+# include <sys/param.h>
+# ifdef USE_MMAP
+#  include <sys/mman.h>
+# endif
+# include <sys/mount.h>
+# include <sys/wait.h>
+# include <sys/time.h>
+#endif /* !_MSC_VER */
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include "err.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#if defined(__EMX__) || defined(_MSC_VER)
+# include <process.h>
+#endif
+#include "getopt.h"
+#ifdef __sun__
+# include "solfakes.h"
+#endif
+#ifdef _MSC_VER
+# include "mscfakes.h"
+#endif
+#include "kmkbuiltin.h"
+
+
+extern void * bsd_setmode(const char *p);
+extern mode_t bsd_getmode(const void *bbox, mode_t omode);
+
+#ifndef __unused
+# define __unused
+#endif
+
+#ifndef MAXBSIZE
+# define MAXBSIZE 0x20000
+#endif
+
+/* Bootstrap aid - this doesn't exist in most older releases */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)	/* from <sys/mman.h> */
+#endif
+
+#define MAX_CMP_SIZE	(16 * 1024 * 1024)
+
+#define	DIRECTORY	0x01		/* Tell install it's a directory. */
+#define	SETFLAGS	0x02		/* Tell install to set flags. */
+#define	NOCHANGEBITS	(UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
+#define	BACKUP_SUFFIX	".old"
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+#ifndef EFTYPE
+# define EFTYPE EINVAL
+#endif
+
+#if defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+# define IS_SLASH(ch)   ((ch) == '/' || (ch) == '\\')
+#else
+# define IS_SLASH(ch)   ((ch) == '/')
+#endif
+
+static gid_t gid;
+static uid_t uid;
+static int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose;
+static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+static const char *suffix = BACKUP_SUFFIX;
+static int ignore_perm_errors;
+
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { "ignore-perm-errors",   				no_argument, 0, 263 },
+    { "no-ignore-perm-errors",				no_argument, 0, 264 },
+    { 0, 0,	0, 0 },
+};
+
+
+static int	copy(int, const char *, int, const char *, off_t);
+static int	compare(int, const char *, size_t, int, const char *, size_t);
+static int	create_newfile(const char *, int, struct stat *);
+static int	create_tempfile(const char *, char *, size_t);
+static int	install(const char *, const char *, u_long, u_int);
+static int	install_dir(char *);
+static u_long	numeric_id(const char *, const char *);
+static int	strip(const char *);
+#ifdef USE_MMAP
+static int	trymmap(int);
+#endif
+static int	usage(FILE *);
+static char    *last_slash(const char *);
+
+int
+kmk_builtin_install(int argc, char *argv[], char ** envp)
+{
+	struct stat from_sb, to_sb;
+	mode_t *set;
+	u_long fset = 0;
+	int ch, no_target;
+	u_int iflags;
+	char *flags;
+	const char *group, *owner, *to_name;
+	(void)envp;
+
+        /* reinitialize globals */
+        mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+        suffix = BACKUP_SUFFIX;
+        gid = 0;
+        uid = 0;
+        dobackup = docompare = dodir = dopreserve = dostrip = nommap = safecopy = verbose = 0;
+	ignore_perm_errors = geteuid() != 0;
+
+        /* reset getopt and set progname. */
+        g_progname = argv[0];
+        opterr = 1;
+        optarg = NULL;
+        optopt = 0;
+        optind = 0; /* init */
+
+	iflags = 0;
+	group = owner = NULL;
+	while ((ch = getopt_long(argc, argv, "B:bCcdf:g:Mm:o:pSsv", long_options, NULL)) != -1)
+		switch(ch) {
+		case 'B':
+			suffix = optarg;
+			/* FALLTHROUGH */
+		case 'b':
+			dobackup = 1;
+			break;
+		case 'C':
+			docompare = 1;
+			break;
+		case 'c':
+			/* For backwards compatibility. */
+			break;
+		case 'd':
+			dodir = 1;
+			break;
+		case 'f':
+#ifdef UF_IMMUTABLE
+			flags = optarg;
+			if (strtofflags(&flags, &fset, NULL))
+				return errx(EX_USAGE, "%s: invalid flag", flags);
+			iflags |= SETFLAGS;
+#else
+			(void)flags;
+#endif
+			break;
+		case 'g':
+			group = optarg;
+			break;
+		case 'M':
+			nommap = 1;
+			break;
+                case 'm':
+			if (!(set = bsd_setmode(optarg)))
+				return errx(EX_USAGE, "invalid file mode: %s",
+				            optarg);
+			mode = bsd_getmode(set, 0);
+			free(set);
+			break;
+		case 'o':
+			owner = optarg;
+			break;
+		case 'p':
+			docompare = dopreserve = 1;
+			break;
+		case 'S':
+			safecopy = 1;
+			break;
+		case 's':
+			dostrip = 1;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 261:
+			usage(stdout);
+			return 0;
+		case 262:
+			return kbuild_version(argv[0]);
+		case 263:
+			ignore_perm_errors = 1;
+			break;
+		case 264:
+			ignore_perm_errors = 0;
+			break;
+		case '?':
+		default:
+			return usage(stderr);
+		}
+	argc -= optind;
+	argv += optind;
+
+	/* some options make no sense when creating directories */
+	if (dostrip && dodir) {
+		warnx("-d and -s may not be specified together");
+		return usage(stderr);
+	}
+
+	/* must have at least two arguments, except when creating directories */
+	if (argc == 0 || (argc == 1 && !dodir))
+		return usage(stderr);
+
+	/* need to make a temp copy so we can compare stripped version */
+	if (docompare && dostrip)
+		safecopy = 1;
+
+	/* get group and owner id's */
+	if (group != NULL) {
+#ifndef _MSC_VER
+		struct group *gp;
+		if ((gp = getgrnam(group)) != NULL)
+			gid = gp->gr_gid;
+		else
+#endif
+		{
+			gid = (gid_t)numeric_id(group, "group");
+			if (gid == (gid_t)-1)
+				return 1;
+		}
+	} else
+		gid = (gid_t)-1;
+
+	if (owner != NULL) {
+#ifndef _MSC_VER
+                struct passwd *pp;
+		if ((pp = getpwnam(owner)) != NULL)
+			uid = pp->pw_uid;
+		else
+#endif
+		{
+			uid = (uid_t)numeric_id(owner, "user");
+			if (uid == (uid_t)-1)
+				return 1;
+		}
+	} else
+		uid = (uid_t)-1;
+
+	if (dodir) {
+		for (; *argv != NULL; ++argv) {
+			int rc = install_dir(*argv);
+			if (rc)
+				return rc;
+		}
+		return EX_OK;
+		/* NOTREACHED */
+	}
+
+	no_target = stat(to_name = argv[argc - 1], &to_sb);
+	if (!no_target && S_ISDIR(to_sb.st_mode)) {
+		for (; *argv != to_name; ++argv) {
+			int rc = install(*argv, to_name, fset, iflags | DIRECTORY);
+			if (rc)
+				return rc;
+		}
+		return EX_OK;
+	}
+
+	/* can't do file1 file2 directory/file */
+	if (argc != 2) {
+		warnx("wrong number or types of arguments");
+		return usage(stderr);
+	}
+
+	if (!no_target) {
+		if (stat(*argv, &from_sb))
+			return err(EX_OSERR, "%s", *argv);
+		if (!S_ISREG(to_sb.st_mode)) {
+			errno = EFTYPE;
+			return err(EX_OSERR, "%s", to_name);
+		}
+		if (to_sb.st_dev == from_sb.st_dev &&
+                    to_sb.st_dev != 0 &&
+		    to_sb.st_ino == from_sb.st_ino &&
+		    to_sb.st_ino != 0)
+			return errx(EX_USAGE,
+			            "%s and %s are the same file", *argv, to_name);
+	}
+	return install(*argv, to_name, fset, iflags);
+}
+
+static u_long
+numeric_id(const char *name, const char *type)
+{
+	u_long val;
+	char *ep;
+
+	/*
+	 * XXX
+	 * We know that uid_t's and gid_t's are unsigned longs.
+	 */
+	errno = 0;
+	val = strtoul(name, &ep, 10);
+	if (errno)
+		return err(-1, "%s", name);
+	if (*ep != '\0')
+		return errx(-1, "unknown %s %s", type, name);
+	return (val);
+}
+
+/*
+ * install --
+ *	build a path name and install the file
+ */
+static int
+install(const char *from_name, const char *to_name, u_long fset, u_int flags)
+{
+	struct stat from_sb, temp_sb, to_sb;
+	struct timeval tvb[2];
+	int devnull, files_match, from_fd, serrno, target;
+	int tempcopy, temp_fd, to_fd;
+	char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
+	int rc = EX_OK;
+
+	files_match = 0;
+	from_fd = -1;
+	to_fd = -1;
+	temp_fd = -1;
+
+	/* If try to install NULL file to a directory, fails. */
+	if (flags & DIRECTORY
+#if defined(__EMX__) || defined(_MSC_VER)
+	    || (   stricmp(from_name, _PATH_DEVNULL)
+		&& stricmp(from_name, "nul")
+#ifdef __EMX__
+		&& stricmp(from_name, "/dev/nul")
+#endif
+	       )
+#else
+	    || strcmp(from_name, _PATH_DEVNULL)
+#endif
+	    ) {
+		if (stat(from_name, &from_sb))
+			return err(EX_OSERR, "%s", from_name);
+		if (!S_ISREG(from_sb.st_mode)) {
+			errno = EFTYPE;
+			return err(EX_OSERR, "%s", from_name);
+		}
+		/* Build the target path. */
+		if (flags & DIRECTORY) {
+			(void)snprintf(pathbuf, sizeof(pathbuf), "%s/%s",
+			    to_name,
+			    (p = last_slash(from_name)) ? ++p : from_name);
+			to_name = pathbuf;
+		}
+		devnull = 0;
+	} else {
+		devnull = 1;
+	}
+
+	target = stat(to_name, &to_sb) == 0;
+
+	/* Only install to regular files. */
+	if (target && !S_ISREG(to_sb.st_mode)) {
+		errno = EFTYPE;
+		warn("%s", to_name);
+		return EX_OK;
+	}
+
+	/* Only copy safe if the target exists. */
+	tempcopy = safecopy && target;
+
+	if (!devnull && (from_fd = open(from_name, O_RDONLY | O_BINARY, 0)) < 0)
+		return err(EX_OSERR, "%s", from_name);
+
+	/* If we don't strip, we can compare first. */
+	if (docompare && !dostrip && target) {
+		if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) {
+			rc = err(EX_OSERR, "%s", to_name);
+			goto l_done;
+		}
+		if (devnull)
+			files_match = to_sb.st_size == 0;
+		else
+			files_match = !(compare(from_fd, from_name,
+			    (size_t)from_sb.st_size, to_fd,
+			    to_name, (size_t)to_sb.st_size));
+
+		/* Close "to" file unless we match. */
+		if (!files_match) {
+			(void)close(to_fd);
+			to_fd = -1;
+		}
+	}
+
+	if (!files_match) {
+		if (tempcopy) {
+			to_fd = create_tempfile(to_name, tempfile,
+			    sizeof(tempfile));
+			if (to_fd < 0) {
+				rc = err(EX_OSERR, "%s", tempfile);
+				goto l_done;
+			}
+		} else {
+			if ((to_fd = create_newfile(to_name, target,
+			    &to_sb)) < 0) {
+				rc = err(EX_OSERR, "%s", to_name);
+				goto l_done;
+			}
+			if (verbose)
+				(void)printf("install: %s -> %s\n",
+				    from_name, to_name);
+		}
+		if (!devnull) {
+			rc = copy(from_fd, from_name, to_fd,
+			          tempcopy ? tempfile : to_name, from_sb.st_size);
+			if (rc)
+    				goto l_done;
+		}
+	}
+
+	if (dostrip) {
+#if defined(__EMX__) || defined(_MSC_VER)
+		/* close before we strip. */
+		close(to_fd);
+		to_fd = -1;
+#endif
+		rc = strip(tempcopy ? tempfile : to_name);
+		if (rc)
+			goto l_done;
+
+		/*
+		 * Re-open our fd on the target, in case we used a strip
+		 * that does not work in-place -- like GNU binutils strip.
+		 */
+#if !defined(__EMX__) && !defined(_MSC_VER)
+		close(to_fd);
+#endif
+		to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY | O_BINARY, 0);
+		if (to_fd < 0) {
+			rc = err(EX_OSERR, "stripping %s", to_name);
+			goto l_done;
+		}
+	}
+
+	/*
+	 * Compare the stripped temp file with the target.
+	 */
+	if (docompare && dostrip && target) {
+		temp_fd = to_fd;
+
+		/* Re-open to_fd using the real target name. */
+		if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) {
+			rc = err(EX_OSERR, "%s", to_name);
+			goto l_done;
+		}
+
+		if (fstat(temp_fd, &temp_sb)) {
+			serrno = errno;
+			(void)unlink(tempfile);
+			errno = serrno;
+			rc = err(EX_OSERR, "%s", tempfile);
+			goto l_done;
+		}
+
+		if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd,
+			    to_name, (size_t)to_sb.st_size) == 0) {
+			/*
+			 * If target has more than one link we need to
+			 * replace it in order to snap the extra links.
+			 * Need to preserve target file times, though.
+			 */
+#if !defined(_MSC_VER) && !defined(__EMX__)
+			if (to_sb.st_nlink != 1) {
+				tvb[0].tv_sec = to_sb.st_atime;
+				tvb[0].tv_usec = 0;
+				tvb[1].tv_sec = to_sb.st_mtime;
+				tvb[1].tv_usec = 0;
+				(void)utimes(tempfile, tvb);
+			} else
+#endif
+                        {
+
+				files_match = 1;
+				(void)unlink(tempfile);
+			}
+			(void) close(temp_fd);
+			temp_fd = -1;
+		}
+	}
+
+	/*
+	 * Move the new file into place if doing a safe copy
+	 * and the files are different (or just not compared).
+	 */
+	if (tempcopy && !files_match) {
+#ifdef UF_IMMUTABLE
+		/* Try to turn off the immutable bits. */
+		if (to_sb.st_flags & NOCHANGEBITS)
+			(void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS);
+#endif
+		if (dobackup) {
+			if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name,
+			    suffix) != strlen(to_name) + strlen(suffix)) {
+				unlink(tempfile);
+				rc = errx(EX_OSERR, "%s: backup filename too long",
+				          to_name);
+				goto l_done;
+			}
+			if (verbose)
+				(void)printf("install: %s -> %s\n", to_name, backup);
+			if (rename(to_name, backup) < 0) {
+				serrno = errno;
+				unlink(tempfile);
+				errno = serrno;
+				rc = err(EX_OSERR, "rename: %s to %s", to_name,
+				         backup);
+				goto l_done;
+			}
+		}
+		if (verbose)
+			(void)printf("install: %s -> %s\n", from_name, to_name);
+		if (rename(tempfile, to_name) < 0) {
+			serrno = errno;
+			unlink(tempfile);
+			errno = serrno;
+			rc = err(EX_OSERR, "rename: %s to %s",
+			         tempfile, to_name);
+			goto l_done;
+		}
+
+		/* Re-open to_fd so we aren't hosed by the rename(2). */
+		(void) close(to_fd);
+		if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) {
+			rc = err(EX_OSERR, "%s", to_name);
+			goto l_done;
+		}
+	}
+
+	/*
+	 * Preserve the timestamp of the source file if necessary.
+	 */
+	if (dopreserve && !files_match && !devnull) {
+		tvb[0].tv_sec = from_sb.st_atime;
+		tvb[0].tv_usec = 0;
+		tvb[1].tv_sec = from_sb.st_mtime;
+		tvb[1].tv_usec = 0;
+		(void)utimes(to_name, tvb);
+	}
+
+	if (fstat(to_fd, &to_sb) == -1) {
+		serrno = errno;
+		(void)unlink(to_name);
+		errno = serrno;
+		rc = err(EX_OSERR, "%s", to_name);
+		goto l_done;
+	}
+
+	/*
+	 * Set owner, group, mode for target; do the chown first,
+	 * chown may lose the setuid bits.
+	 */
+#ifdef UF_IMMUTABLE
+	if ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
+	    (uid != (uid_t)-1 && uid != to_sb.st_uid) ||
+	    (mode != (to_sb.st_mode & ALLPERMS))) {
+		/* Try to turn off the immutable bits. */
+		if (to_sb.st_flags & NOCHANGEBITS)
+			(void)fchflags(to_fd, to_sb.st_flags & ~NOCHANGEBITS);
+	}
+#endif
+
+	if ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
+	    (uid != (uid_t)-1 && uid != to_sb.st_uid))
+		if (fchown(to_fd, uid, gid) == -1) {
+    			if (errno == EPERM && ignore_perm_errors) {
+				warn("%s: ignoring chown uid=%d gid=%d failure", to_name, (int)uid, (int)gid);
+			} else {
+				serrno = errno;
+				(void)unlink(to_name);
+				errno = serrno;
+				rc = err(EX_OSERR,"%s: chown/chgrp", to_name);
+				goto l_done;
+			}
+		}
+
+	if (mode != (to_sb.st_mode & ALLPERMS))
+		if (fchmod(to_fd, mode)) {
+			serrno = errno;
+			if (serrno == EPERM && ignore_perm_errors) {
+				fchmod(to_fd, mode & (ALLPERMS & ~0007000));
+				errno = errno;
+				warn("%s: ignoring chmod 0%o failure", to_name, (int)(mode & ALLPERMS));
+			} else  {
+				serrno = errno;
+				(void)unlink(to_name);
+				errno = serrno;
+				rc = err(EX_OSERR, "%s: chmod", to_name);
+				goto l_done;
+			}
+		}
+
+	/*
+	 * If provided a set of flags, set them, otherwise, preserve the
+	 * flags, except for the dump flag.
+	 * NFS does not support flags.  Ignore EOPNOTSUPP flags if we're just
+	 * trying to turn off UF_NODUMP.  If we're trying to set real flags,
+	 * then warn if the the fs doesn't support it, otherwise fail.
+	 */
+#ifdef UF_IMMUTABLE
+	if (!devnull && (flags & SETFLAGS ||
+	    (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) &&
+	    fchflags(to_fd,
+	    flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) {
+		if (flags & SETFLAGS) {
+			if (errno == EOPNOTSUPP)
+				warn("%s: chflags", to_name);
+			else {
+				serrno = errno;
+				(void)unlink(to_name);
+				errno = serrno;
+				rc = err(EX_OSERR, "%s: chflags", to_name);
+				goto l_done;
+			}
+		}
+	}
+#endif
+
+l_done:
+	if (to_fd >= 0)
+		(void)close(to_fd);
+	if (temp_fd >= 0)
+		(void)close(temp_fd);
+	if (!devnull)
+		(void)close(from_fd);
+	return rc;
+}
+
+/*
+ * compare --
+ *	compare two files; non-zero means files differ
+ */
+static int
+compare(int from_fd, const char *from_name __unused, size_t from_len,
+	int to_fd, const char *to_name __unused, size_t to_len)
+{
+	char *p, *q;
+	int rv;
+	int done_compare;
+
+	rv = 0;
+	if (from_len != to_len)
+		return 1;
+
+	if (from_len <= MAX_CMP_SIZE) {
+#ifdef USE_MMAP
+		done_compare = 0;
+		if (trymmap(from_fd) && trymmap(to_fd)) {
+			p = mmap(NULL, from_len, PROT_READ, MAP_SHARED, from_fd, (off_t)0);
+			if (p == (char *)MAP_FAILED)
+				goto out;
+			q = mmap(NULL, from_len, PROT_READ, MAP_SHARED, to_fd, (off_t)0);
+			if (q == (char *)MAP_FAILED) {
+				munmap(p, from_len);
+				goto out;
+			}
+
+			rv = memcmp(p, q, from_len);
+			munmap(p, from_len);
+			munmap(q, from_len);
+			done_compare = 1;
+		}
+	out:
+#else
+	(void)p; (void)q;
+	done_compare = 0;
+#endif
+		if (!done_compare) {
+			char buf1[MAXBSIZE];
+			char buf2[MAXBSIZE];
+			int n1, n2;
+
+			rv = 0;
+			lseek(from_fd, 0, SEEK_SET);
+			lseek(to_fd, 0, SEEK_SET);
+			while (rv == 0) {
+				n1 = read(from_fd, buf1, sizeof(buf1));
+				if (n1 == 0)
+					break;		/* EOF */
+				else if (n1 > 0) {
+					n2 = read(to_fd, buf2, n1);
+					if (n2 == n1)
+						rv = memcmp(buf1, buf2, n1);
+					else
+						rv = 1;	/* out of sync */
+				} else
+					rv = 1;		/* read failure */
+			}
+			lseek(from_fd, 0, SEEK_SET);
+			lseek(to_fd, 0, SEEK_SET);
+		}
+	} else
+		rv = 1;	/* don't bother in this case */
+
+	return rv;
+}
+
+/*
+ * create_tempfile --
+ *	create a temporary file based on path and open it
+ */
+int
+create_tempfile(const char *path, char *temp, size_t tsize)
+{
+	char *p;
+
+	(void)strncpy(temp, path, tsize);
+	temp[tsize - 1] = '\0';
+	if ((p = last_slash(temp)) != NULL)
+		p++;
+	else
+		p = temp;
+	(void)strncpy(p, "INS@XXXX", &temp[tsize - 1] - p);
+	temp[tsize - 1] = '\0';
+	return (mkstemp(temp));
+}
+
+/*
+ * create_newfile --
+ *	create a new file, overwriting an existing one if necessary
+ */
+int
+create_newfile(const char *path, int target, struct stat *sbp)
+{
+	char backup[MAXPATHLEN];
+	int saved_errno = 0;
+	int newfd;
+
+	if (target) {
+		/*
+		 * Unlink now... avoid ETXTBSY errors later.  Try to turn
+		 * off the append/immutable bits -- if we fail, go ahead,
+		 * it might work.
+		 */
+#ifdef UF_IMMUTABLE
+		if (sbp->st_flags & NOCHANGEBITS)
+			(void)chflags(path, sbp->st_flags & ~NOCHANGEBITS);
+#endif
+
+		if (dobackup) {
+			if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s",
+			    path, suffix) != strlen(path) + strlen(suffix)) {
+				errx(EX_OSERR, "%s: backup filename too long",
+				     path);
+				errno = ENAMETOOLONG;
+				return -1;
+			}
+			(void)snprintf(backup, MAXPATHLEN, "%s%s",
+			    path, suffix);
+			if (verbose)
+				(void)printf("install: %s -> %s\n",
+				    path, backup);
+			if (rename(path, backup) < 0) {
+				err(EX_OSERR, "rename: %s to %s", path, backup);
+				return -1;
+			}
+		} else
+			if (unlink(path) < 0)
+				saved_errno = errno;
+	}
+
+	newfd = open(path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
+	if (newfd < 0 && saved_errno != 0)
+		errno = saved_errno;
+	return newfd;
+}
+
+/*
+ * copy --
+ *	copy from one file to another
+ */
+static int
+copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
+    off_t size)
+{
+	int nr, nw;
+	int serrno;
+	char *p, buf[MAXBSIZE];
+	int done_copy;
+
+	/* Rewind file descriptors. */
+	if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1)
+		return err(EX_OSERR, "lseek: %s", from_name);
+	if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1)
+		return err(EX_OSERR, "lseek: %s", to_name);
+
+	/*
+	 * Mmap and write if less than 8M (the limit is so we don't totally
+	 * trash memory on big files.  This is really a minor hack, but it
+	 * wins some CPU back.
+	 */
+	done_copy = 0;
+#ifdef USE_MMAP
+	if (size <= 8 * 1048576 && trymmap(from_fd) &&
+	    (p = mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED,
+		    from_fd, (off_t)0)) != (char *)MAP_FAILED) {
+		if ((nw = write(to_fd, p, size)) != size) {
+			serrno = errno;
+			(void)unlink(to_name);
+			errno = nw > 0 ? EIO : serrno;
+			err(EX_OSERR, "%s", to_name);
+		}
+		done_copy = 1;
+	}
+#else
+	(void)p; (void)size;
+#endif
+	if (!done_copy) {
+		while ((nr = read(from_fd, buf, sizeof(buf))) > 0)
+			if ((nw = write(to_fd, buf, nr)) != nr) {
+				serrno = errno;
+				(void)unlink(to_name);
+				errno = nw > 0 ? EIO : serrno;
+				return err(EX_OSERR, "%s", to_name);
+			}
+		if (nr != 0) {
+			serrno = errno;
+			(void)unlink(to_name);
+			errno = serrno;
+			return err(EX_OSERR, "%s", from_name);
+		}
+	}
+	return EX_OK;
+}
+
+/*
+ * strip --
+ *	use strip(1) to strip the target file
+ */
+static int
+strip(const char *to_name)
+{
+#if defined(__EMX__) || defined(_MSC_VER)
+	const char *stripbin = getenv("STRIPBIN");
+	if (stripbin == NULL)
+		stripbin = "strip";
+	return spawnlp(P_WAIT, stripbin, stripbin, to_name, NULL);
+#else
+	const char *stripbin;
+	int serrno, status;
+        pid_t pid;
+
+        pid = fork();
+	switch (pid) {
+	case -1:
+		serrno = errno;
+		(void)unlink(to_name);
+		errno = serrno;
+		return err(EX_TEMPFAIL, "fork");
+	case 0:
+		stripbin = getenv("STRIPBIN");
+		if (stripbin == NULL)
+			stripbin = "strip";
+		execlp(stripbin, stripbin, to_name, (char *)NULL);
+		err(EX_OSERR, "exec(%s)", stripbin);
+                exit(EX_OSERR);
+	default:
+		if (waitpid(pid, &status, 0) == -1 || status) {
+			serrno = errno;
+			(void)unlink(to_name);
+                        errno = serrno;
+			return err(EX_SOFTWARE, "waitpid");
+			/* NOTREACHED */
+		}
+	}
+        return 0;
+#endif
+}
+
+/*
+ * install_dir --
+ *	build directory heirarchy
+ */
+static int
+install_dir(char *path)
+{
+	char *p;
+	struct stat sb;
+	int ch;
+
+	for (p = path;; ++p)
+		if (!*p || (p != path && IS_SLASH(*p))) {
+			ch = *p;
+			*p = '\0';
+			if (stat(path, &sb)) {
+				if (errno != ENOENT || mkdir(path, 0755) < 0) {
+					return err(EX_OSERR, "mkdir %s", path);
+					/* NOTREACHED */
+				} else if (verbose)
+					(void)printf("install: mkdir %s\n",
+						     path);
+			} else if (!S_ISDIR(sb.st_mode))
+				return errx(EX_OSERR, "%s exists but is not a directory", path);
+			if (!(*p = ch))
+				break;
+ 		}
+
+	if ((gid != (gid_t)-1 || uid != (uid_t)-1) && chown(path, uid, gid))
+		warn("chown %u:%u %s", uid, gid, path);
+	if (chmod(path, mode))
+		warn("chmod %o %s", mode, path);
+	return EX_OK;
+}
+
+/*
+ * usage --
+ *	print a usage message and die
+ */
+static int
+usage(FILE *pf)
+{
+	fprintf(pf,
+"usage: %s [-bCcpSsv] [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n"
+"            [-g group] [-m mode] [-o owner] file1 file2\n"
+"   or: %s [-bCcpSsv] [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n"
+"            [-g group] [-m mode] [-o owner] file1 ... fileN directory\n"
+"   or: %s -d [-v] [-g group] [-m mode] [-o owner] directory ...\n"
+"   or: %s --help\n"
+"   or: %s --version\n",
+			g_progname, g_progname, g_progname, g_progname, g_progname);
+	return EX_USAGE;
+}
+
+#ifdef USE_MMAP
+/*
+ * trymmap --
+ *	return true (1) if mmap should be tried, false (0) if not.
+ */
+static int
+trymmap(int fd)
+{
+/*
+ * The ifdef is for bootstrapping - f_fstypename doesn't exist in
+ * pre-Lite2-merge systems.
+ */
+#ifdef MFSNAMELEN
+	struct statfs stfs;
+
+	if (nommap || fstatfs(fd, &stfs) != 0)
+		return (0);
+	if (strcmp(stfs.f_fstypename, "ufs") == 0 ||
+	    strcmp(stfs.f_fstypename, "cd9660") == 0)
+		return (1);
+#endif
+	return (0);
+}
+#endif
+
+/* figures out where the last slash or colon is. */
+static char *
+last_slash(const char *path)
+{
+#if defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__)
+    char *p = (char *)strrchr(path, '/');
+    if (p)
+    {
+        char *p2 = strrchr(p, '\\');
+        if (p2)
+            p = p2;
+    }
+    else
+    {
+        p = (char *)strrchr(path, '\\');
+        if (!p && isalpha(path[0]) && path[1] == ':')
+            p = (char *)&path[1];
+    }
+    return p;
+#else
+    return strrchr(path, '/');
+#endif
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kDepIDB.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kDepIDB.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kDepIDB.c	(revision 1780)
@@ -0,0 +1,1001 @@
+/* $Id$ */
+/** @file
+ *
+ * kDepIDB - Extract dependency information from a MS Visual C++ .idb file.
+ *
+ * Copyright (c) 2006-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#if !defined(_MSC_VER)
+# include <stdint.h>
+#else
+# define USE_WIN_MMAP
+# include <io.h>
+# include <Windows.h>
+ typedef unsigned char  uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int   uint32_t;
+#endif
+/*#include "kDep.h"*/
+#include "../../lib/kDep.h"
+#include "kmkbuiltin.h"
+
+#define OFFSETOF(type, member)  ( (int)(size_t)(void *)&( ((type *)(void *)0)->member) )
+
+/*#define DEBUG*/
+#ifdef DEBUG
+# define dprintf(a)             printf a
+# define dump(pb, cb, offBase)  hexdump(pb,cb,offBase)
+#else
+# define dprintf(a)             do {} while (0)
+# define dump(pb, cb, offBase)  do {} while (0)
+#endif
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** the executable name. */
+static const char *argv0 = "";
+
+#ifdef DEBUG
+/**
+ * Performs a hexdump.
+ */
+static void hexdump(const uint8_t *pb, size_t cb, size_t offBase)
+{
+    static const char   szHex[16] = "0123456789abcdef";
+
+    const unsigned      cchWidth = 16;
+    size_t              off = 0;
+    while (off < cb)
+    {
+        unsigned i;
+        printf("%s%0*x %04x:", off ? "\n" : "", sizeof(pb) * 2, offBase + off, off);
+        for (i = 0; i < cchWidth && off + i < cb ; i++)
+            printf(off + i < cb ? !(i & 7) && i ? "-%02x" : " %02x" : "   ", pb[i]);
+
+        while (i++ < cchWidth)
+                printf("   ");
+        printf(" ");
+
+        for (i = 0; i < cchWidth && off + i < cb; i++)
+        {
+            const uint8_t u8 = pb[i];
+            printf("%c", u8 < 127 && u8 >= 32 ? u8 : '.', 1);
+        }
+        off += cchWidth;
+        pb  += cchWidth;
+    }
+    printf("\n");
+}
+#endif
+
+/**
+ * Scans a stream (chunk of data really) for dependencies.
+ *
+ * @returns 0 on success.
+ * @returns !0 on failure.
+ * @param   pbStream        The stream bits.
+ * @param   cbStream        The size of the stream.
+ * @param   pszPrefix       The dependency prefix.
+ * @param   cchPrefix       The size of the prefix.
+ */
+static int ScanStream(uint8_t *pbStream, size_t cbStream, const char *pszPrefix, size_t cchPrefix)
+{
+    const uint8_t  *pbCur = pbStream;
+    size_t          cbLeft = cbStream;
+    register char   chFirst = *pszPrefix;
+    while (cbLeft > cchPrefix + 2)
+    {
+        if (    *pbCur != chFirst
+            ||  memcmp(pbCur, pszPrefix, cchPrefix))
+        {
+            pbCur++;
+            cbLeft--;
+        }
+        else
+        {
+            size_t cchDep;
+            pbCur += cchPrefix;
+            cchDep = strlen((const char *)pbCur);
+            depAdd((const char *)pbCur, cchDep);
+            dprintf(("%05x: '%s'\n", pbCur - pbStream, pbCur));
+
+            pbCur += cchDep;
+            cbLeft -= cchDep + cchPrefix;
+        }
+    }
+
+    return 0;
+}
+
+
+#ifdef USE_WIN_MMAP
+/** Handle to the current file mapping object. */
+static HANDLE g_hMapObj = NULL;
+#endif
+
+
+/**
+ * Reads the file specified by the pInput file stream into memory.
+ * The size of the file is returned in *pcbFile if specified.
+ * The returned pointer should be freed by FreeFileMemory().
+ */
+void *ReadFileIntoMemory(FILE *pInput, size_t *pcbFile)
+{
+    void       *pvFile;
+    long        cbFile;
+    int         rc = 0;
+
+    /*
+     * Figure out file size.
+     */
+#if defined(_MSC_VER)
+    cbFile = _filelength(fileno(pInput));
+    if (cbFile < 0)
+#else
+    if (    fseek(pInput, 0, SEEK_END) < 0
+        ||  (cbFile = ftell(pInput)) < 0
+        ||  fseek(pInput, 0, SEEK_SET))
+#endif
+    {
+        fprintf(stderr, "%s: error: Failed to determin file size.\n", argv0);
+        return NULL;
+    }
+    if (pcbFile)
+        *pcbFile = cbFile;
+
+    /*
+     * Try mmap first.
+     */
+#ifdef USE_WIN_MMAP
+    {
+        HANDLE hMapObj = CreateFileMapping((HANDLE)_get_osfhandle(fileno(pInput)),
+                                           NULL, PAGE_READONLY, 0, cbFile, NULL);
+        if (hMapObj != NULL)
+        {
+            pvFile = MapViewOfFile(hMapObj, FILE_MAP_READ, 0, 0, cbFile);
+            if (pvFile)
+            {
+                g_hMapObj = hMapObj;
+                return pvFile;
+            }
+            fprintf(stderr, "%s: warning: MapViewOfFile failed, %d.\n", argv0, GetLastError());
+            CloseHandle(hMapObj);
+        }
+        else
+            fprintf(stderr, "%s: warning: CreateFileMapping failed, %d.\n", argv0, GetLastError());
+    }
+
+#endif
+
+    /*
+     * Allocate memory and read the file.
+     */
+    pvFile = malloc(cbFile + 1);
+    if (pvFile)
+    {
+        if (fread(pvFile, cbFile, 1, pInput))
+        {
+            ((uint8_t *)pvFile)[cbFile] = '\0';
+            return pvFile;
+        }
+        fprintf(stderr, "%s: error: Failed to read %ld bytes.\n", argv0, cbFile);
+        free(pvFile);
+    }
+    else
+        fprintf(stderr, "%s: error: Failed to allocate %ld bytes (file mapping).\n", argv0, cbFile);
+    return NULL;
+}
+
+
+static void FreeFileMemory(void *pvFile)
+{
+#if defined(USE_WIN_MMAP)
+    if (g_hMapObj)
+    {
+        UnmapViewOfFile(pvFile);
+        CloseHandle(g_hMapObj);
+        return;
+    }
+#endif
+    free(pvFile);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//
+//  P D B   7 . 0
+//
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/** A PDB 7.0 Page number. */
+typedef uint32_t PDB70PAGE;
+/** Pointer to a PDB 7.0 Page number. */
+typedef PDB70PAGE *PPDB70PAGE;
+
+/**
+ * A PDB 7.0 stream.
+ */
+typedef struct PDB70STREAM
+{
+    /** The size of the stream. */
+    uint32_t    cbStream;
+} PDB70STREAM, *PPDB70STREAM;
+
+
+/** The PDB 7.00 signature. */
+#define PDB_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\x1A" "DS\0\0"
+/**
+ * The PDB 7.0 header.
+ */
+typedef struct PDB70HDR
+{
+    /** The signature string. */
+    uint8_t     szSignature[sizeof(PDB_SIGNATURE_700)];
+    /** The page size. */
+    uint32_t    cbPage;
+    /** The start page. */
+    PDB70PAGE   iStartPage;
+    /** The number of pages in the file. */
+    PDB70PAGE   cPages;
+    /** The root stream directory. */
+    uint32_t    cbRoot;
+    /** Unknown function, always 0. */
+    uint32_t    u32Reserved;
+    /** The page index of the root page table. */
+    PDB70PAGE   iRootPages;
+} PDB70HDR, *PPDB70HDR;
+
+/**
+ * The PDB 7.0 root directory.
+ */
+typedef struct PDB70ROOT
+{
+    /** The number of streams */
+    uint32_t    cStreams;
+    /** Array of streams. */
+    PDB70STREAM aStreams[1];
+    /* uint32_t aiPages[] */
+} PDB70ROOT, *PPDB70ROOT;
+
+/**
+ * The PDB 7.0 name stream (#1) header.
+ */
+typedef struct PDB70NAMES
+{
+    /** The structure version. */
+    uint32_t        Version;
+    /** Timestamp.  */
+    uint32_t        TimeStamp;
+    /** Unknown. */
+    uint32_t        Unknown1;
+    /** GUID. */
+    uint32_t        u32Guid[4];
+    /** The size of the following name table. */
+    uint32_t        cbNames;
+    /** The name table. */
+    char            szzNames[1];
+} PDB70NAMES, *PPDB70NAMES;
+
+/** The version / magic of the names structure. */
+#define PDB70NAMES_VERSION  20000404
+
+
+static int Pdb70ValidateHeader(PPDB70HDR pHdr, size_t cbFile)
+{
+    if (pHdr->cbPage * pHdr->cPages != cbFile)
+    {
+        fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0);
+        return 1;
+    }
+    if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0)
+    {
+        fprintf(stderr, "%s: error: Bad PDB 2.0 header - iStartPage=%u cPages=%u.\n", argv0,
+                pHdr->iStartPage, pHdr->cPages);
+        return 1;
+    }
+    if (pHdr->iRootPages >= pHdr->cPages && pHdr->iRootPages <= 0)
+    {
+        fprintf(stderr, "%s: error: Bad PDB 2.0 header - iRootPages=%u cPage=%u.\n", argv0,
+                pHdr->iStartPage, pHdr->cPages);
+        return 1;
+    }
+    return 0;
+}
+
+static size_t Pdb70Align(PPDB70HDR pHdr, size_t cb)
+{
+    if (cb == ~(uint32_t)0 || !cb)
+        return 0;
+    return ((cb + pHdr->cbPage - 1) / pHdr->cbPage) * pHdr->cbPage;
+}
+
+static size_t Pdb70Pages(PPDB70HDR pHdr, size_t cb)
+{
+    if (cb == ~(uint32_t)0 || !cb)
+        return 0;
+    return (cb + pHdr->cbPage - 1) / pHdr->cbPage;
+}
+
+static void *Pdb70AllocAndRead(PPDB70HDR pHdr, size_t cb, PPDB70PAGE paiPageMap)
+{
+    const size_t    cbPage = pHdr->cbPage;
+    size_t          cPages = Pdb70Pages(pHdr, cb);
+    uint8_t *pbBuf = malloc(cPages * cbPage + 1);
+    if (pbBuf)
+    {
+        size_t iPage = 0;
+        while (iPage < cPages)
+        {
+            size_t off = paiPageMap[iPage];
+            if (off < pHdr->cPages)
+            {
+                off *= cbPage;
+                memcpy(pbBuf + iPage * cbPage, (uint8_t *)pHdr + off, cbPage);
+                dump(pbBuf + iPage * cbPage, iPage + 1 < cPages ? cbPage : cb % cbPage, off);
+            }
+            else
+            {
+                fprintf(stderr, "%s: warning: Invalid page index %u (max %u)!\n", argv0,
+                        (unsigned)off, pHdr->cPages);
+                memset(pbBuf + iPage * cbPage, 0, cbPage);
+            }
+
+            iPage++;
+        }
+        pbBuf[cPages * cbPage] = '\0';
+    }
+    else
+        fprintf(stderr, "%s: error: failed to allocate %u bytes\n", argv0, cPages * cbPage + 1);
+    return pbBuf;
+}
+
+static PPDB70ROOT Pdb70AllocAndReadRoot(PPDB70HDR pHdr)
+{
+    /*
+     * The tricky bit here is to find the right length. Really?
+     * (Todo: Check if we can just use the stream #0 size..)
+     */
+    PPDB70PAGE piPageMap = (uint32_t *)((uint8_t *)pHdr + pHdr->iRootPages * pHdr->cbPage);
+    PPDB70ROOT pRoot = Pdb70AllocAndRead(pHdr, pHdr->cbRoot, piPageMap);
+    if (pRoot)
+    {
+#if 1
+        /* This stuff is probably unnecessary: */
+        /* size = stream header + array of stream. */
+        size_t cb = OFFSETOF(PDB70ROOT, aStreams[pRoot->cStreams]);
+        free(pRoot);
+        pRoot = Pdb70AllocAndRead(pHdr, cb, piPageMap);
+        if (pRoot)
+        {
+            /* size += page tables. */
+            unsigned iStream = pRoot->cStreams;
+            while (iStream-- > 0)
+                if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
+                    cb += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB70PAGE);
+            free(pRoot);
+            pRoot = Pdb70AllocAndRead(pHdr, cb, piPageMap);
+            if (pRoot)
+            {
+                /* validate? */
+                return pRoot;
+            }
+        }
+#else
+        /* validate? */
+        return pRoot;
+#endif
+    }
+    return NULL;
+}
+
+static void *Pdb70AllocAndReadStream(PPDB70HDR pHdr, PPDB70ROOT pRoot, unsigned iStream, size_t *pcbStream)
+{
+    const size_t    cbStream = pRoot->aStreams[iStream].cbStream;
+    PPDB70PAGE      paiPageMap;
+    if (    iStream >= pRoot->cStreams
+        ||  cbStream == ~(uint32_t)0)
+    {
+        fprintf(stderr, "%s: error: Invalid stream %d\n", iStream);
+        return NULL;
+    }
+
+    paiPageMap = (PPDB70PAGE)&pRoot->aStreams[pRoot->cStreams];
+    while (iStream-- > 0)
+        if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
+            paiPageMap += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream);
+
+    if (pcbStream)
+        *pcbStream = cbStream;
+    return Pdb70AllocAndRead(pHdr, cbStream, paiPageMap);
+}
+
+static int Pdb70Process(uint8_t *pbFile, size_t cbFile)
+{
+    PPDB70HDR   pHdr = (PPDB70HDR)pbFile;
+    PPDB70ROOT  pRoot;
+    PPDB70NAMES pNames;
+    size_t      cbStream;
+    unsigned    fDone = 0;
+    unsigned    iStream;
+    int         rc = 0;
+    dprintf(("pdb70\n"));
+
+    /*
+     * Validate the header and read the root stream.
+     */
+    if (Pdb70ValidateHeader(pHdr, cbFile))
+        return 1;
+    pRoot = Pdb70AllocAndReadRoot(pHdr);
+    if (!pRoot)
+        return 1;
+
+    /*
+     * The names we want are usually all found in the 'Names' stream, that is #1.
+     */
+    dprintf(("Reading the names stream....\n"));
+    pNames = Pdb70AllocAndReadStream(pHdr, pRoot, 1, &cbStream);
+    if (pNames)
+    {
+        dprintf(("Names: Version=%u cbNames=%u (%#x)\n", pNames->Version, pNames->cbNames, pNames->cbNames));
+        if (    pNames->Version == PDB70NAMES_VERSION
+            &&  pNames->cbNames > 32
+            &&  pNames->cbNames + offsetof(PDB70NAMES, szzNames) <= pRoot->aStreams[1].cbStream)
+        {
+            /*
+             * Iterate the names and add the /mr/inversedeps/ ones to the dependency list.
+             */
+            const char *psz = &pNames->szzNames[0];
+            size_t cb = pNames->cbNames;
+            size_t off = 0;
+            dprintf(("0x0000 #0: %6d bytes  [root / toc]\n", pRoot->aStreams[0].cbStream));
+            for (iStream = 1; cb > 0; iStream++)
+            {
+                int fAdded = 0;
+                size_t cch = strlen(psz);
+                if (   cch >= sizeof("/mr/inversedeps/")
+                    && !memcmp(psz, "/mr/inversedeps/", sizeof("/mr/inversedeps/") - 1))
+                {
+                    depAdd(psz + sizeof("/mr/inversedeps/") - 1, cch - (sizeof("/mr/inversedeps/") - 1));
+                    fAdded = 1;
+                }
+                dprintf(("%#06x #%d: %6d bytes  %s%s\n", off, iStream,
+                         iStream < pRoot->cStreams ? pRoot->aStreams[iStream].cbStream : -1,
+                         psz, fAdded ? "  [dep]" : ""));
+                (void)fAdded;
+
+                /* next */
+                if (cch >= cb)
+                {
+                    dprintf(("warning! cch=%d cb=%d\n", cch, cb));
+                    cch = cb - 1;
+                }
+                cb  -= cch + 1;
+                psz += cch + 1;
+                off += cch + 1;
+            }
+            rc = 0;
+            fDone = 1;
+        }
+        else
+            dprintf(("Unknown version or bad size: Version=%u cbNames=%d cbStream=%d\n",
+                     pNames->Version, pNames->cbNames, cbStream));
+        free(pNames);
+    }
+
+    if (!fDone)
+    {
+        /*
+         * Iterate the streams in the root and scan their content for
+         * dependencies.
+         */
+        rc = 0;
+        for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++)
+        {
+            uint8_t *pbStream;
+            if (    pRoot->aStreams[iStream].cbStream == ~(uint32_t)0
+                ||  !pRoot->aStreams[iStream].cbStream)
+                continue;
+            dprintf(("Stream #%d: %#x bytes (%#x aligned)\n", iStream, pRoot->aStreams[iStream].cbStream,
+                     Pdb70Align(pHdr, pRoot->aStreams[iStream].cbStream)));
+            pbStream = (uint8_t *)Pdb70AllocAndReadStream(pHdr, pRoot, iStream, &cbStream);
+            if (pbStream)
+            {
+                rc = ScanStream(pbStream, cbStream, "/mr/inversedeps/", sizeof("/mr/inversedeps/") - 1);
+                free(pbStream);
+            }
+            else
+                rc = 1;
+        }
+    }
+
+    free(pRoot);
+    return rc;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//
+//  P D B   2 . 0
+//
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+/** A PDB 2.0 Page number. */
+typedef uint16_t PDB20PAGE;
+/** Pointer to a PDB 2.0 Page number. */
+typedef PDB20PAGE *PPDB20PAGE;
+
+/**
+ * A PDB 2.0 stream.
+ */
+typedef struct PDB20STREAM
+{
+    /** The size of the stream. */
+    uint32_t    cbStream;
+    /** Some unknown value. */
+    uint32_t    u32Unknown;
+} PDB20STREAM, *PPDB20STREAM;
+
+/** The PDB 2.00 signature. */
+#define PDB_SIGNATURE_200 "Microsoft C/C++ program database 2.00\r\n\x1A" "JG\0"
+/**
+ * The PDB 2.0 header.
+ */
+typedef struct PDB20HDR
+{
+    /** The signature string. */
+    uint8_t     szSignature[sizeof(PDB_SIGNATURE_200)];
+    /** The page size. */
+    uint32_t    cbPage;
+    /** The start page - whatever that is... */
+    PDB20PAGE   iStartPage;
+    /** The number of pages in the file. */
+    PDB20PAGE   cPages;
+    /** The root stream directory. */
+    PDB20STREAM RootStream;
+    /** The root page table. */
+    PDB20PAGE   aiRootPageMap[1];
+} PDB20HDR, *PPDB20HDR;
+
+/**
+ * The PDB 2.0 root directory.
+ */
+typedef struct PDB20ROOT
+{
+    /** The number of streams */
+    uint16_t    cStreams;
+    /** Reserved or high part of cStreams. */
+    uint16_t    u16Reserved;
+    /** Array of streams. */
+    PDB20STREAM aStreams[1];
+} PDB20ROOT, *PPDB20ROOT;
+
+
+static int Pdb20ValidateHeader(PPDB20HDR pHdr, size_t cbFile)
+{
+    if (pHdr->cbPage * pHdr->cPages != cbFile)
+    {
+        fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0);
+        return 1;
+    }
+    if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0)
+    {
+        fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0);
+        return 1;
+    }
+    return 0;
+}
+
+static size_t Pdb20Pages(PPDB20HDR pHdr, size_t cb)
+{
+    if (cb == ~(uint32_t)0 || !cb)
+        return 0;
+    return (cb + pHdr->cbPage - 1) / pHdr->cbPage;
+}
+
+static void *Pdb20AllocAndRead(PPDB20HDR pHdr, size_t cb, PPDB20PAGE paiPageMap)
+{
+    size_t cPages = Pdb20Pages(pHdr, cb);
+    uint8_t *pbBuf = malloc(cPages * pHdr->cbPage + 1);
+    if (pbBuf)
+    {
+        size_t iPage = 0;
+        while (iPage < cPages)
+        {
+            size_t off = paiPageMap[iPage];
+            off *= pHdr->cbPage;
+            memcpy(pbBuf + iPage * pHdr->cbPage, (uint8_t *)pHdr + off, pHdr->cbPage);
+            iPage++;
+        }
+        pbBuf[cPages * pHdr->cbPage] = '\0';
+    }
+    else
+        fprintf(stderr, "%s: error: failed to allocate %d bytes\n", argv0, cPages * pHdr->cbPage + 1);
+    return pbBuf;
+}
+
+static PPDB20ROOT Pdb20AllocAndReadRoot(PPDB20HDR pHdr)
+{
+    /*
+     * The tricky bit here is to find the right length.
+     * (Todo: Check if we can just use the stream size..)
+     */
+    PPDB20ROOT pRoot = Pdb20AllocAndRead(pHdr, sizeof(*pRoot), &pHdr->aiRootPageMap[0]);
+    if (pRoot)
+    {
+        /* size = stream header + array of stream. */
+        size_t cb = OFFSETOF(PDB20ROOT, aStreams[pRoot->cStreams]);
+        free(pRoot);
+        pRoot = Pdb20AllocAndRead(pHdr, cb, &pHdr->aiRootPageMap[0]);
+        if (pRoot)
+        {
+            /* size += page tables. */
+            unsigned iStream = pRoot->cStreams;
+            while (iStream-- > 0)
+                if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
+                    cb += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB20PAGE);
+            free(pRoot);
+            pRoot = Pdb20AllocAndRead(pHdr, cb, &pHdr->aiRootPageMap[0]);
+            if (pRoot)
+            {
+                /* validate? */
+                return pRoot;
+            }
+        }
+    }
+    return NULL;
+
+}
+
+static void *Pdb20AllocAndReadStream(PPDB20HDR pHdr, PPDB20ROOT pRoot, unsigned iStream, size_t *pcbStream)
+{
+    size_t      cbStream = pRoot->aStreams[iStream].cbStream;
+    PPDB20PAGE  paiPageMap;
+    if (    iStream >= pRoot->cStreams
+        ||  cbStream == ~(uint32_t)0)
+    {
+        fprintf(stderr, "%s: error: Invalid stream %d\n", iStream);
+        return NULL;
+    }
+
+    paiPageMap = (PPDB20PAGE)&pRoot->aStreams[pRoot->cStreams];
+    while (iStream-- > 0)
+        if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
+            paiPageMap += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream);
+
+    if (pcbStream)
+        *pcbStream = cbStream;
+    return Pdb20AllocAndRead(pHdr, cbStream, paiPageMap);
+}
+
+static int Pdb20Process(uint8_t *pbFile, size_t cbFile)
+{
+    PPDB20HDR   pHdr = (PPDB20HDR)pbFile;
+    PPDB20ROOT  pRoot;
+    unsigned    iStream;
+    int         rc = 0;
+
+    /*
+     * Validate the header and read the root stream.
+     */
+    if (Pdb20ValidateHeader(pHdr, cbFile))
+        return 1;
+    pRoot = Pdb20AllocAndReadRoot(pHdr);
+    if (!pRoot)
+        return 1;
+
+    /*
+     * Iterate the streams in the root and scan their content for
+     * dependencies.
+     */
+    rc = 0;
+    for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++)
+    {
+        uint8_t *pbStream;
+        if (pRoot->aStreams[iStream].cbStream == ~(uint32_t)0)
+            continue;
+        pbStream = (uint8_t *)Pdb20AllocAndReadStream(pHdr, pRoot, iStream, NULL);
+        if (pbStream)
+        {
+            rc = ScanStream(pbStream, pRoot->aStreams[iStream].cbStream, "/ipm/header/", sizeof("/ipm/header/") - 1);
+            free(pbStream);
+        }
+        else
+            rc = 1;
+    }
+
+    free(pRoot);
+    return rc;
+}
+
+
+/**
+ * Make an attempt at parsing a Visual C++ IDB file.
+ */
+static int ProcessIDB(FILE *pInput)
+{
+    size_t      cbFile;
+    uint8_t    *pbFile;
+    int         rc = 0;
+
+    /*
+     * Read the file into memory.
+     */
+    pbFile = (uint8_t *)ReadFileIntoMemory(pInput, &cbFile);
+    if (!pbFile)
+        return 1;
+
+    /*
+     * Figure out which parser to use.
+     */
+    if (!memcmp(pbFile, PDB_SIGNATURE_700, sizeof(PDB_SIGNATURE_700)))
+        rc = Pdb70Process(pbFile, cbFile);
+    else if (!memcmp(pbFile, PDB_SIGNATURE_200, sizeof(PDB_SIGNATURE_200)))
+        rc = Pdb20Process(pbFile, cbFile);
+    else
+    {
+        fprintf(stderr, "%s: error: Doesn't recognize the header of the Visual C++ IDB file.\n", argv0);
+        rc = 1;
+    }
+
+    FreeFileMemory(pbFile);
+    return rc;
+}
+
+
+static void usage(const char *argv0)
+{
+    printf("usage: %s -o <output> -t <target> [-f] [-s] <vc idb-file>\n"
+           "   or: %s --help\n"
+           "   or: %s --version\n",
+           argv0, argv0, argv0);
+}
+
+
+int kmk_builtin_kDepIDB(int argc, char *argv[], char **envp)
+{
+    int         i;
+
+    /* Arguments. */
+    FILE       *pOutput = NULL;
+    const char *pszOutput = NULL;
+    FILE       *pInput = NULL;
+    const char *pszTarget = NULL;
+    int         fStubs = 0;
+    int         fFixCase = 0;
+    /* Argument parsing. */
+    int         fInput = 0;             /* set when we've found input argument. */
+
+    argv0 = argv[0];
+
+    /*
+     * Parse arguments.
+     */
+    if (argc <= 1)
+    {
+        usage(argv[0]);
+        return 1;
+    }
+    for (i = 1; i < argc; i++)
+    {
+        if (argv[i][0] == '-')
+        {
+            const char *psz = &argv[i][1];
+            if (*psz == '-')
+            {
+                if (!strcmp(psz, "-help"))
+                    psz = "?";
+                else if (!strcmp(psz, "-version"))
+                    psz = "v";
+            }
+
+            switch (*psz)
+            {
+                /*
+                 * Output file.
+                 */
+                case 'o':
+                {
+                    pszOutput = &argv[i][2];
+                    if (pOutput)
+                    {
+                        fprintf(stderr, "%s: syntax error: only one output file!\n", argv[0]);
+                        return 1;
+                    }
+                    if (!*pszOutput)
+                    {
+                        if (++i >= argc)
+                        {
+                            fprintf(stderr, "%s: syntax error: The '-o' argument is missing the filename.\n", argv[0]);
+                            return 1;
+                        }
+                        pszOutput = argv[i];
+                    }
+                    if (pszOutput[0] == '-' && !pszOutput[1])
+                        pOutput = stdout;
+                    else
+                        pOutput = fopen(pszOutput, "w");
+                    if (!pOutput)
+                    {
+                        fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", argv[0], pszOutput);
+                        return 1;
+                    }
+                    break;
+                }
+
+                /*
+                 * Target name.
+                 */
+                case 't':
+                {
+                    if (pszTarget)
+                    {
+                        fprintf(stderr, "%s: syntax error: only one target!\n", argv[0]);
+                        return 1;
+                    }
+                    pszTarget = &argv[i][2];
+                    if (!*pszTarget)
+                    {
+                        if (++i >= argc)
+                        {
+                            fprintf(stderr, "%s: syntax error: The '-t' argument is missing the target name.\n", argv[0]);
+                            return 1;
+                        }
+                        pszTarget = argv[i];
+                    }
+                    break;
+                }
+
+                /*
+                 * Fix case.
+                 */
+                case 'f':
+                {
+                    fFixCase = 1;
+                    break;
+                }
+
+                /*
+                 * Generate stubs.
+                 */
+                case 's':
+                {
+                    fStubs = 1;
+                    break;
+                }
+
+                /*
+                 * The mandatory version & help.
+                 */
+                case '?':
+                    usage(argv[0]);
+                    return 0;
+                case 'v':
+                    return kbuild_version(argv[0]);
+
+                /*
+                 * Invalid argument.
+                 */
+                default:
+                    fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]);
+                    usage(argv[0]);
+                    return 1;
+            }
+        }
+        else
+        {
+            pInput = fopen(argv[i], "rb");
+            if (!pInput)
+            {
+                fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]);
+                return 1;
+            }
+            fInput = 1;
+        }
+
+        /*
+         * End of the line?
+         */
+        if (fInput)
+        {
+            if (++i < argc)
+            {
+                fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", argv[0]);
+                return 1;
+            }
+            break;
+        }
+    }
+
+    /*
+     * Got all we require?
+     */
+    if (!pInput)
+    {
+        fprintf(stderr, "%s: syntax error: No input!\n", argv[0]);
+        return 1;
+    }
+    if (!pOutput)
+    {
+        fprintf(stderr, "%s: syntax error: No output!\n", argv[0]);
+        return 1;
+    }
+    if (!pszTarget)
+    {
+        fprintf(stderr, "%s: syntax error: No target!\n", argv[0]);
+        return 1;
+    }
+
+    /*
+     * Do the parsing.
+     */
+    i = ProcessIDB(pInput);
+    fclose(pInput);
+
+    /*
+     * Write the dependecy file.
+     */
+    if (!i)
+    {
+        depOptimize(fFixCase);
+        fprintf(pOutput, "%s:", pszTarget);
+        depPrint(pOutput);
+        if (fStubs)
+            depPrintStubs(pOutput);
+    }
+
+    /*
+     * Close the output, delete output on failure.
+     */
+    if (!i && ferror(pOutput))
+    {
+        i = 1;
+        fprintf(stderr, "%s: error: Error writing to '%s'.\n", argv[0], pszOutput);
+    }
+    fclose(pOutput);
+    if (i)
+    {
+        if (unlink(pszOutput))
+            fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", argv[0], pszOutput);
+    }
+
+    depCleanup();
+    return i;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_protection.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_protection.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_protection.c	(revision 1780)
@@ -0,0 +1,373 @@
+/* $Id$ */
+/** @file
+ * Simple File Protection.
+ */
+
+/*
+ * Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#if defined(_MSC_VER) || defined(__OS2__)
+# include <limits.h>
+# include <direct.h>
+#endif 
+#include "kbuild_protection.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#define KBUILD_PROTECTION_MAGIC     0x00111100
+
+#if defined(__EMX__) || defined(_MSC_VER)
+# define IS_SLASH(ch)               ( (ch) == '/' || (ch) == '\\' )
+# define DEFAULT_PROTECTION_DEPTH   1
+#else
+# define IS_SLASH(ch)               ( (ch) == '/' )
+# define DEFAULT_PROTECTION_DEPTH   2
+#endif
+
+
+
+/**
+ * Counts the components in the specified sub path.
+ * This is a helper for count_path_components.
+ *
+ * etc = 1
+ * etc/ = 1
+ * etc/x11 = 2
+ * and so and and so forth.
+ */
+static int countSubPathComponents(const char *pszPath, int cDepth)
+{
+    for (;;)
+    {
+        const char *pszEnd;
+        size_t cch;
+
+        /* skip slashes. */
+        while (IS_SLASH(*pszPath))
+            pszPath++;
+        if (!*pszPath)
+            break;
+
+        /* find end of component. */
+        pszEnd = pszPath;
+        while (!IS_SLASH(*pszEnd) && *pszEnd)
+            pszEnd++;
+
+        /* count it, checking for '..' and '.'. */
+        cch = pszEnd - pszPath;
+        if (cch == 2 && pszPath[0] == '.' && pszPath[1] == '.')
+        {
+            if (cDepth > 0)
+                cDepth--;
+        }
+        else if (cch != 1 || pszPath[0] != '.')
+            cDepth++;
+
+        /* advance */
+        if (!*pszEnd)
+            break;
+        pszPath = pszEnd + 1;
+    }
+    return cDepth;
+}
+
+
+/**
+ * Parses the specified path counting the number of components
+ * relative to root.
+ *
+ * We don't check symbolic links and such, just some simple and cheap
+ * path parsing.
+ *
+ * @param   pszPath     The path to process.
+ *
+ * @returns 0 or higher on success.
+ *          On failure an error is printed, eval is set and -1 is returned.
+ */
+static int countPathComponents(const char *pszPath)
+{
+    int cComponents = 0;
+
+    /*
+     * Deal with root, UNC, drive letter.
+ */
+#if defined(_MSC_VER) || defined(__OS2__)
+    if (IS_SLASH(pszPath[0]) && IS_SLASH(pszPath[1]) && !IS_SLASH(pszPath[2]))
+    {
+        /* skip the root - UNC */
+        pszPath += 3;
+        while (!IS_SLASH(*pszPath) && *pszPath) /* server name */
+            pszPath++;
+        while (IS_SLASH(*pszPath))
+            pszPath++;
+        while (!IS_SLASH(*pszPath) && *pszPath) /* share name */
+            pszPath++;
+        while (IS_SLASH(*pszPath))
+            pszPath++;
+    }
+    else
+    {
+        unsigned uDriveLetter = (unsigned)toupper(pszPath[0]) - (unsigned)'A';
+        if (uDriveLetter <= (unsigned)('Z' - 'A') && pszPath[1] == ':')
+            uDriveLetter++; /* A == 1 */
+        else
+            uDriveLetter = 0; /* 0 == default */
+
+        if (!IS_SLASH(pszPath[uDriveLetter ? 2 : 0]))
+        {
+            /*
+             * Relative path, must count cwd depth first.
+             */
+#ifdef __OS2__ /** @todo remove when ticket 194 has been fixed */
+            char *pszCwd = _getdcwd(uDriveLetter, NULL, PATH_MAX);
+#else
+            char *pszCwd = _getdcwd(uDriveLetter, NULL, 0);
+#endif
+            char *pszTmp = pszCwd;
+            if (!pszTmp)
+            {
+                err(1, "_getdcwd");
+                return -1;
+            }
+
+            if (IS_SLASH(pszTmp[0]) && IS_SLASH(pszTmp[1]))
+            {
+                /* skip the root - UNC */
+                pszTmp += 2;
+                while (!IS_SLASH(*pszTmp) && *pszTmp) /* server name */
+                    pszTmp++;
+                while (IS_SLASH(*pszTmp))
+                    pszTmp++;
+                while (!IS_SLASH(*pszTmp) && *pszTmp) /* share name */
+                    pszTmp++;
+            }
+            else
+            {
+                /* skip the drive letter and while we're at it, the root slash too. */
+                pszTmp += 1 + (pszTmp[1] == ':');
+            }
+            cComponents = countSubPathComponents(pszTmp, 0);
+            free(pszCwd);
+        }
+        else
+        {
+            /* skip the drive letter and while we're at it, the root slash too. */
+            pszPath += uDriveLetter ? 3 : 1;
+        }
+    }
+#else
+    if (!IS_SLASH(pszPath[0]))
+    {
+        /*
+         * Relative path, must count cwd depth first.
+         */
+        char szCwd[4096];
+        if (!getcwd(szCwd, sizeof(szCwd)))
+        {
+            err(1, "getcwd");
+            return -1;
+        }
+        cComponents = countSubPathComponents(szCwd, 0);
+    }
+#endif
+
+    /*
+     * We're now past any UNC or drive letter crap, possibly positioned
+     * at the root slash or at the start of a path component at the
+     * given depth. Count the remainder.
+     */
+    return countSubPathComponents(pszPath, cComponents);
+}
+
+
+/**
+ * Initializes the instance data.
+ *
+ * @param   pThis   Pointer to the instance data.
+ */
+void kBuildProtectionInit(PKBUILDPROTECTION pThis)
+{
+    pThis->uMagic = KBUILD_PROTECTION_MAGIC;
+    pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] = 0;
+    pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] = 1;
+    pThis->cProtectionDepth = DEFAULT_PROTECTION_DEPTH;
+}
+
+
+/**
+ * Destroys the instance data.
+ *
+ * @param   pThis   Pointer to the instance data.
+ */
+void kBuildProtectionTerm(PKBUILDPROTECTION pThis)
+{
+    pThis->uMagic = 0;
+}
+
+
+void kBuildProtectionEnable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType)
+{
+    assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC);
+    assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST);
+    pThis->afTypes[enmType] |= 1;
+}
+
+
+void kBuildProtectionDisable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType)
+{
+    assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC);
+    assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST);
+    pThis->afTypes[enmType] &= ~1U;
+}
+
+
+/**
+ * Sets the protection depth according to the option argument.
+ *
+ * @param   pszValue    The value.
+ *
+ * @returns 0 on success, -1 and errx on failure.
+ */
+int  kBuildProtectionSetDepth(PKBUILDPROTECTION pThis, const char *pszValue)
+{
+    /* skip leading blanks, they don't count either way. */
+    while (isspace(*pszValue))
+        pszValue++;
+
+    /* number or path? */
+    if (!isdigit(*pszValue) || strpbrk(pszValue, ":/\\"))
+        pThis->cProtectionDepth = countPathComponents(pszValue);
+    else
+    {
+        char *pszMore = 0;
+        pThis->cProtectionDepth = strtol(pszValue, &pszMore, 0);
+        if (pThis->cProtectionDepth != 0 && pszMore)
+        {
+            /* trailing space is harmless. */
+            while (isspace(*pszMore))
+                pszMore++;
+        }
+        if (!pThis->cProtectionDepth || pszValue == pszMore || *pszMore)
+            return errx(1, "bogus protection depth: %s", pszValue);
+    }
+
+    if (pThis->cProtectionDepth < 1)
+        return  errx(1, "bogus protection depth: %s", pszValue);
+    return 0;
+}
+
+
+/**
+ * Scans the environment for option overrides.
+ *
+ * @param   pThis       Pointer to the instance data.
+ * @param   papszEnv    The environment array.
+ * @param   pszPrefix   The variable prefix.
+ *
+ * @returns 0 on success, -1 and err*() on failure.
+ */
+int  kBuildProtectionScanEnv(PKBUILDPROTECTION pThis, char **papszEnv, const char *pszPrefix)
+{
+    unsigned i;
+    const size_t cchPrefix = strlen(pszPrefix);
+
+    for (i = 0; papszEnv[i]; i++)
+    {
+        const char *pszVar = papszEnv[i];
+        if (!strncmp(pszVar, pszPrefix, cchPrefix))
+        {
+            pszVar += cchPrefix;
+            if (!strncmp(pszVar, "PROTECTION_DEPTH=", sizeof("PROTECTION_DEPTH=") - 1))
+            {
+                const char *pszVal = pszVar + sizeof("PROTECTION_DEPTH=") - 1;
+                if (kBuildProtectionSetDepth(pThis, pszVal))
+                    return -1;
+            }
+            else if (!strncmp(pszVar, "DISABLE_PROTECTION=", sizeof("DISABLE_PROTECTION=") - 1))
+                pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] &= ~1U;
+            else if (!strncmp(pszVar, "ENABLE_PROTECTION=", sizeof("ENABLE_PROTECTION=") - 1))
+                pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] |= 3;
+            else if (!strncmp(pszVar, "DISABLE_FULL_PROTECTION=", sizeof("DISABLE_FULL_PROTECTION=") - 1))
+                pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] &= ~1U;
+            else if (!strncmp(pszVar, "ENABLE_FULL_PROTECTION=", sizeof("ENABLE_FULL_PROTECTION=") - 1))
+                pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] |= 3;
+        }
+    }
+    return 0;
+}
+
+
+/**
+ * Protect the upper layers of the file system against accidental
+ * or malicious deletetion attempt from within a makefile.
+ *
+ * @param   pszPath             The path to check.
+ * @param   required_depth      The minimum number of components in the
+ *                              path counting from the root.
+ *
+ * @returns 0 on success.
+ *          On failure an error is printed and -1 is returned.
+ */
+int  kBuildProtectionEnforce(PCKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType, const char *pszPath)
+{
+    assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC);
+    assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST);
+
+    if (   (pThis->afTypes[enmType] & 3)
+        || (pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] & 3))
+    {
+        /*
+         * Count the path and compare it with the required depth.
+         */
+        int cComponents = countPathComponents(pszPath);
+        if (cComponents < 0)
+            return -1;
+        if (cComponents <= pThis->cProtectionDepth)
+        {
+            errx(1, "%s: protected", pszPath);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+
+/**
+ * Retrieve the default path protection depth.
+ *
+ * @returns the default value.
+ */
+int  kBuildProtectionDefaultDepth(void)
+{
+    return DEFAULT_PROTECTION_DEPTH;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_protection.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_protection.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_protection.h	(revision 1780)
@@ -0,0 +1,66 @@
+/* $Id$ */
+/** @file
+ * Simple File Protection.
+ */
+
+/*
+ * Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef ___kbuild_protection_h___
+#define ___kbuild_protection_h___
+
+/**
+ * The different protection types.
+ */
+typedef enum
+{
+    KBUILDPROTECTIONTYPE_FIRST = 0,
+    KBUILDPROTECTIONTYPE_RECURSIVE = KBUILDPROTECTIONTYPE_FIRST,
+    KBUILDPROTECTIONTYPE_FULL,
+    KBUILDPROTECTIONTYPE_MAX
+} KBUILDPROTECTIONTYPE;
+
+
+/**
+ * The instance data.
+ * Don't touch.
+ */
+typedef struct KBUILDPROTECTION
+{
+    unsigned        uMagic;
+    unsigned        cProtectionDepth;
+    unsigned char   afTypes[KBUILDPROTECTIONTYPE_MAX];
+} KBUILDPROTECTION;
+typedef KBUILDPROTECTION  *PKBUILDPROTECTION;
+typedef const KBUILDPROTECTION *PCKBUILDPROTECTION;
+
+
+void kBuildProtectionInit(PKBUILDPROTECTION pThis);
+void kBuildProtectionTerm(PKBUILDPROTECTION pThis);
+int  kBuildProtectionScanEnv(PKBUILDPROTECTION pThis, char **papszEnv, const char *pszPrefix);
+void kBuildProtectionEnable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType);
+void kBuildProtectionDisable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType);
+int  kBuildProtectionSetDepth(PKBUILDPROTECTION pThis, const char *pszValue);
+int  kBuildProtectionEnforce(PCKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType, const char *pszPath);
+int  kBuildProtectionDefaultDepth(void);
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_version.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_version.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/kbuild_version.c	(revision 1780)
@@ -0,0 +1,56 @@
+/* $Id$ */
+/** @file
+ * kbuild_version(), helper function.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "kmkbuiltin.h"
+#include <string.h>
+#include <stdio.h>
+
+/**
+ * Prints the kBuild version message and returns 0.
+ *
+ * @returns 0
+ * @param   argv0       The argv0.
+ */
+int kbuild_version(const char *argv0)
+{
+    const char *tmp;
+
+    /* skip the path */
+    for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:"))
+        argv0 = tmp + 1;
+
+    /* find the end, ignoring extenions */
+    tmp = strrchr(argv0, '.');
+    if (!tmp)
+        tmp = strchr(argv0, '\0');
+
+    printf("%.*s - kBuild version %d.%d.%d (r%u)\n",
+           tmp - argv0, argv0,
+           KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, 
+           KBUILD_SVN_REV);
+    return 0;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/ln.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/ln.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/ln.c	(revision 1780)
@@ -0,0 +1,265 @@
+/*-
+ * Copyright (c) 1987, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1987, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ln.c	8.2 (Berkeley) 3/31/94";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/ln/ln.c,v 1.33 2005/02/09 17:37:37 ru Exp $");
+#endif /* no $id */
+
+#ifndef _MSC_VER
+# include <sys/param.h>
+#endif
+#include <sys/stat.h>
+
+#include "err.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "getopt.h"
+#ifdef _MSC_VER
+# include "mscfakes.h"
+#endif
+#include "kmkbuiltin.h"
+
+static int	fflag;				/* Unlink existing files. */
+static int	hflag;				/* Check new name for symlink first. */
+static int	iflag;				/* Interactive mode. */
+static int	sflag;				/* Symbolic, not hard, link. */
+static int	vflag;				/* Verbose output. */
+					/* System link call. */
+static int (*linkf)(const char *, const char *);
+static char	linkch;
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { 0, 0,	0, 0 },
+};
+
+
+static int	linkit(const char *, const char *, int);
+static int	usage(FILE *);
+
+
+int
+kmk_builtin_ln(int argc, char *argv[], char **envp)
+{
+	struct stat sb;
+	char *sourcedir;
+	int ch, exitval;
+
+	/* initialize globals. */
+	fflag = hflag = iflag = sflag = vflag = 0;
+	linkch = 0;
+	linkf = NULL;
+
+	/* kmk: reset getopt() and set program name. */
+	g_progname = argv[0];
+	opterr = 1;
+	optarg = NULL;
+	optopt = 0;
+	optind = 0; /* init */
+
+	while ((ch = getopt_long(argc, argv, "fhinsv", long_options, NULL)) != -1)
+		switch (ch) {
+		case 'f':
+			fflag = 1;
+			iflag = 0;
+			break;
+		case 'h':
+		case 'n':
+			hflag = 1;
+			break;
+		case 'i':
+			iflag = 1;
+			fflag = 0;
+			break;
+		case 's':
+			sflag = 1;
+			break;
+		case 'v':
+			vflag = 1;
+			break;
+		case 261:
+			usage(stdout);
+			return 0;
+		case 262:
+			return kbuild_version(argv[0]);
+		case '?':
+		default:
+			return usage(stderr);
+		}
+
+	argv += optind;
+	argc -= optind;
+
+	linkf = sflag ? symlink : link;
+	linkch = sflag ? '-' : '=';
+
+	switch(argc) {
+	case 0:
+		return usage(stderr);
+		/* NOTREACHED */
+	case 1:				/* ln target */
+		return linkit(argv[0], ".", 1);
+	case 2:				/* ln target source */
+		return linkit(argv[0], argv[1], 0);
+	default:
+		;
+	}
+					/* ln target1 target2 directory */
+	sourcedir = argv[argc - 1];
+	if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
+		/*
+		 * We were asked not to follow symlinks, but found one at
+		 * the target--simulate "not a directory" error
+		 */
+		errno = ENOTDIR;
+		return err(1, "%s", sourcedir);
+	}
+	if (stat(sourcedir, &sb))
+		return err(1, "%s", sourcedir);
+	if (!S_ISDIR(sb.st_mode))
+		return usage(stderr);
+	for (exitval = 0; *argv != sourcedir; ++argv)
+		exitval |= linkit(*argv, sourcedir, 1);
+	return exitval;
+}
+
+static int
+linkit(const char *target, const char *source, int isdir)
+{
+	struct stat sb;
+	const char *p;
+	int ch, exists, first;
+	char path[PATH_MAX];
+
+	if (!sflag) {
+		/* If target doesn't exist, quit now. */
+		if (stat(target, &sb)) {
+			warn("%s", target);
+			return (1);
+		}
+		/* Only symbolic links to directories. */
+		if (S_ISDIR(sb.st_mode)) {
+			errno = EISDIR;
+			warn("%s", target);
+			return (1);
+		}
+	}
+
+	/*
+	 * If the source is a directory (and not a symlink if hflag),
+	 * append the target's name.
+	 */
+	if (isdir ||
+	    (lstat(source, &sb) == 0 && S_ISDIR(sb.st_mode)) ||
+	    (!hflag && stat(source, &sb) == 0 && S_ISDIR(sb.st_mode))) {
+#ifdef _MSC_VER || defined(__OS2__)
+		char *p2 = strrchr(target, '\\');
+		p = strrchr(target, '/');
+		if (p2 != NULL && (p == NULL || p2 > p))
+			p = p2;
+		if (p == NULL)
+#else
+		if ((p = strrchr(target, '/')) == NULL)
+#endif
+			p = target;
+		else
+			++p;
+		if (snprintf(path, sizeof(path), "%s/%s", source, p) >=
+		    (ssize_t)sizeof(path)) {
+			errno = ENAMETOOLONG;
+			warn("%s", target);
+			return (1);
+		}
+		source = path;
+	}
+
+	exists = !lstat(source, &sb);
+	/*
+	 * If the file exists, then unlink it forcibly if -f was specified
+	 * and interactively if -i was specified.
+	 */
+	if (fflag && exists) {
+		if (unlink(source)) {
+			warn("%s", source);
+			return (1);
+		}
+	} else if (iflag && exists) {
+		fflush(stdout);
+		fprintf(stderr, "replace %s? ", source);
+
+		first = ch = getchar();
+		while(ch != '\n' && ch != EOF)
+			ch = getchar();
+		if (first != 'y' && first != 'Y') {
+			fprintf(stderr, "not replaced\n");
+			return (1);
+		}
+
+		if (unlink(source)) {
+			warn("%s", source);
+			return (1);
+		}
+	}
+
+	/* Attempt the link. */
+	if ((*linkf)(target, source)) {
+		warn("%s", source);
+		return (1);
+	}
+	if (vflag)
+		(void)printf("%s %c> %s\n", source, linkch, target);
+	return (0);
+}
+
+static int
+usage(FILE *pf)
+{
+	fprintf(pf, "usage: %s [-fhinsv] source_file [target_file]\n"
+				"   or: %s [-fhinsv] source_file ... target_dir\n"
+                "   or: %s source_file target_file\n"
+				"   or: %s --help\n"
+				"   or: %s --version\n",
+                g_progname, g_progname, g_progname, g_progname, g_progname);
+	return 1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/md5sum.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/md5sum.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/md5sum.c	(revision 1780)
@@ -0,0 +1,809 @@
+/* $Id$ */
+/** @file
+ * md5sum.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef _MSC_VER
+# include <io.h>
+#else
+# include <unistd.h>
+#endif
+#include <sys/stat.h>
+#include "err.h"
+#include "kmkbuiltin.h"
+#include "../../lib/md5.h"
+
+/*#define MD5SUM_USE_STDIO*/
+
+
+/**
+ * Prints the usage and return 1.
+ */
+static int usage(FILE *pOut)
+{
+    fprintf(pOut,
+            "usage: md5sum [-bt] [-o list-file] file(s)\n"
+            "   or: md5sum [-btwq] -c list-file(s)\n"
+            "   or: md5sum [-btq] -C MD5 file\n"
+            "\n"
+            " -c, --check       Check MD5 and files found in the specified list file(s).\n"
+            "                   The default is to compute MD5 sums of the specified files\n"
+            "                   and print them to stdout in list form.\n"
+            " -C, --check-file  This is followed by an MD5 sum and the file to check.\n"
+            " -b, --binary      Read files in binary mode. (default)\n"
+            " -t, --text        Read files in text mode.\n"
+            " -p, --progress    Show progress indicator on large files.\n"
+            " -o, --output      Name of the output list file. Useful with -p.\n"
+            " -q, --status      Be quiet.\n"
+            " -w, --warn        Ignored. Always warn, unless quiet.\n"
+            " -h, --help        This usage info.\n"
+            " -v, --version     Show version information and exit.\n"
+            );
+    return 1;
+}
+
+
+/**
+ * Makes a string out of the given digest.
+ *
+ * @param   pDigest     The MD5 digest.
+ * @param   pszDigest   Where to put the digest string. Must be able to
+ *                      hold at least 33 bytes.
+ */
+static void digest_to_string(unsigned char pDigest[16], char *pszDigest)
+{
+    unsigned i;
+    for (i = 0; i < 16; i++)
+    {
+        static char s_achDigits[17] = "0123456789abcdef";
+        pszDigest[i*2]     = s_achDigits[(pDigest[i] >> 4)];
+        pszDigest[i*2 + 1] = s_achDigits[(pDigest[i] & 0xf)];
+    }
+    pszDigest[i*2] = '\0';
+}
+
+
+/**
+ * Attempts to convert a string to a MD5 digest.
+ *
+ * @returns 0 on success, 1-based position of the failure first error.
+ * @param   pszDigest   The string to interpret.
+ * @param   pDigest     Where to put the MD5 digest.
+ */
+static int string_to_digest(const char *pszDigest, unsigned char pDigest[16])
+{
+    unsigned i;
+    unsigned iBase = 1;
+
+    /* skip blanks */
+    while (     *pszDigest == ' '
+           ||   *pszDigest == '\t'
+           ||   *pszDigest == '\n'
+           ||   *pszDigest == '\r')
+        pszDigest++, iBase++;
+
+    /* convert the digits. */
+    memset(pDigest, 0, 16);
+    for (i = 0; i < 32; i++, pszDigest++)
+    {
+        int iDigit;
+        if (*pszDigest >= '0' && *pszDigest <= '9')
+            iDigit = *pszDigest - '0';
+        else if (*pszDigest >= 'a' && *pszDigest <= 'f')
+            iDigit = *pszDigest - 'a' + 10;
+        else if (*pszDigest >= 'A' && *pszDigest <= 'F')
+            iDigit = *pszDigest - 'A' + 10;
+        else
+            return i + iBase;
+        if (i & 1)
+            pDigest[i >> 1] |= iDigit;
+        else
+            pDigest[i >> 1] |= iDigit << 4;
+    }
+
+    /* the rest of the string must now be blanks. */
+    while (     *pszDigest == ' '
+           ||   *pszDigest == '\t'
+           ||   *pszDigest == '\n'
+           ||   *pszDigest == '\r')
+        pszDigest++, i++;
+
+    return *pszDigest ? i + iBase : 0;
+}
+
+
+/**
+ * Opens the specified file for md5 sum calculation.
+ *
+ * @returns Opaque pointer on success, NULL and errno on failure.
+ * @param   pszFilename     The filename.
+ * @param   fText           Whether text or binary mode should be used.
+ */
+static void *open_file(const char *pszFilename, unsigned fText)
+{
+#if defined(MD5SUM_USE_STDIO)
+    FILE *pFile;
+
+    errno = 0;
+    pFile = fopen(pszFilename, fText ? "r" : "rb");
+    if (!pFile && errno == EINVAL && !fText)
+        pFile = fopen(pszFilename, "r");
+    return pFile;
+
+#else
+    int fd;
+    int fFlags;
+
+    /* figure out the appropriate flags. */
+    fFlags = O_RDONLY;
+#ifdef O_SEQUENTIAL
+    fFlags |= _O_SEQUENTIAL;
+#elif defined(_O_SEQUENTIAL)
+    fFlags |= _O_SEQUENTIAL;
+#endif
+#ifdef _O_BINARY
+    if (!fText)     fFlags |= _O_BINARY;
+#elif defined(_O_BINARY)
+    if (!fText)     fFlags |= _O_BINARY;
+#endif
+#ifdef O_TEXT
+    if (fText)      fFlags |= O_TEXT;
+#elif defined(O_TEXT)
+    if (fText)      fFlags |= _O_TEXT;
+#endif
+
+    errno = 0;
+    fd = open(pszFilename, fFlags, 0755);
+    if (fd >= 0)
+    {
+        int *pFd = malloc(sizeof(*pFd));
+        if (pFd)
+        {
+            *pFd = fd;
+            return pFd;
+        }
+        close(fd);
+        errno = ENOMEM;
+    }
+
+    return NULL;
+#endif
+}
+
+
+/**
+ * Closes a file opened by open_file.
+ *
+ * @param   pvFile          The opaque pointer returned by open_file.
+ */
+static void close_file(void *pvFile)
+{
+#if defined(MD5SUM_USE_STDIO)
+    fclose((FILE *)pvFile);
+#else
+    close(*(int *)pvFile);
+    free(pvFile);
+#endif
+}
+
+
+/**
+ * Reads from a file opened by open_file.
+ *
+ * @returns Number of bytes read on success.
+ *          0 on EOF.
+ *          Negated errno on read error.
+ * @param   pvFile          The opaque pointer returned by open_file.
+ * @param   pvBuf           Where to put the number of read bytes.
+ * @param   cbBuf           The max number of bytes to read.
+ *                          Must be less than a INT_MAX.
+ */
+static int read_file(void *pvFile, void *pvBuf, size_t cbBuf)
+{
+#if defined(MD5SUM_USE_STDIO)
+    int cb;
+
+    errno = 0;
+    cb = (int)fread(pvBuf, 1, cbBuf, (FILE *)pvFile);
+    if (cb >= 0)
+        return (int)cb;
+    if (!errno)
+        return -EINVAL;
+    return -errno;
+#else
+    int cb;
+
+    errno = 0;
+    cb = (int)read(*(int *)pvFile, pvBuf, (int)cbBuf);
+    if (cb >= 0)
+        return (int)cb;
+    if (!errno)
+        return -EINVAL;
+    return -errno;
+#endif
+}
+
+
+/**
+ * Gets the size of the file.
+ * This is informational and not necessarily 100% accurate.
+ *
+ * @returns File size.
+ * @param   pvFile          The opaque pointer returned by open_file
+ */
+static double size_file(void *pvFile)
+{
+#if defined(_MSC_VER)
+    __int64 cb;
+# if defined(MD5SUM_USE_STDIO)
+    cb = _filelengthi64(fileno((FILE *)pvFile));
+# else
+    cb = _filelengthi64(*(int *)pvFile);
+# endif
+    if (cb >= 0)
+        return (double)cb;
+
+#elif defined(MD5SUM_USE_STDIO)
+    struct stat st;
+    if (!fstat(fileno((FILE *)pvFile), &st))
+        return st.st_size;
+
+#else
+    struct stat st;
+    if (!fstat(*(int *)pvFile, &st))
+        return st.st_size;
+#endif
+    return 1024;
+}
+
+
+/**
+ * Calculates the md5sum of the sepecified file stream.
+ *
+ * @returns errno on failure, 0 on success.
+ * @param   pvFile      The file stream.
+ * @param   pDigest     Where to store the MD5 digest.
+ * @param   fProgress   Whether to show a progress bar.
+ */
+static int calc_md5sum(void *pvFile, unsigned char pDigest[16], unsigned fProgress)
+{
+    int cb;
+    int rc = 0;
+    char abBuf[32*1024];
+    struct MD5Context Ctx;
+    unsigned uPercent = 0;
+    double cbFile = 0.0;
+    double off = 0.0;
+
+    if (fProgress)
+    {
+        cbFile = size_file(pvFile);
+        if (cbFile < 1024*1024)
+            fProgress = 0;
+    }
+
+    MD5Init(&Ctx);
+    for (;;)
+    {
+        /* process a chunk. */
+        cb = read_file(pvFile, abBuf, sizeof(abBuf));
+        if (cb > 0)
+            MD5Update(&Ctx, (unsigned char *)&abBuf[0], cb);
+        else if (!cb)
+            break;
+        else
+        {
+            rc = -cb;
+            break;
+        }
+
+        /* update the progress indicator. */
+        if (fProgress)
+        {
+            unsigned uNewPercent;
+            off += cb;
+            uNewPercent = (unsigned)((off / cbFile) * 100);
+            if (uNewPercent != uPercent)
+            {
+                if (uPercent)
+                    printf("\b\b\b\b");
+                printf("%3d%%", uNewPercent);
+                fflush(stdout);
+                uPercent = uNewPercent;
+            }
+        }
+    }
+    MD5Final(pDigest, &Ctx);
+
+    if (fProgress)
+        printf("\b\b\b\b    \b\b\b\b");
+
+    return rc;
+}
+
+
+/**
+ * Checks the if the specified digest matches the digest of the file stream.
+ *
+ * @returns 0 on match, -1 on mismatch, errno value (positive) on failure.
+ * @param   pvFile      The file stream.
+ * @param   Digest      The MD5 digest.
+ * @param   fProgress   Whether to show an progress indicator on large files.
+ */
+static int check_md5sum(void *pvFile, unsigned char Digest[16], unsigned fProgress)
+{
+    unsigned char DigestFile[16];
+    int rc;
+
+    rc = calc_md5sum(pvFile, DigestFile, fProgress);
+    if (!rc)
+        rc = memcmp(Digest, DigestFile, 16) ? -1 : 0;
+    return rc;
+}
+
+
+/**
+ * Checks if the specified file matches the given MD5 digest.
+ *
+ * @returns 0 if it matches, 1 if it doesn't or an error occurs.
+ * @param   pszFilename The name of the file to check.
+ * @param   pszDigest   The MD5 digest string.
+ * @param   fText       Whether to open the file in text or binary mode.
+ * @param   fQuiet      Whether to go about this in a quiet fashion or not.
+ * @param   fProgress   Whether to show an progress indicator on large files.
+ */
+static int check_one_file(const char *pszFilename, const char *pszDigest, unsigned fText, unsigned fQuiet, unsigned fProgress)
+{
+    unsigned char Digest[16];
+    int rc;
+
+    rc = string_to_digest(pszDigest, Digest);
+    if (!rc)
+    {
+        void *pvFile;
+
+        pvFile = open_file(pszFilename, fText);
+        if (pvFile)
+        {
+            if (!fQuiet)
+                fprintf(stdout, "%s: ", pszFilename);
+            rc = check_md5sum(pvFile, Digest, fProgress);
+            close_file(pvFile);
+            if (!fQuiet)
+            {
+                fprintf(stdout, "%s\n", !rc ? "OK" : rc < 0 ? "FAILURE" : "ERROR");
+                fflush(stdout);
+                if (rc > 0)
+                    errx(1, "Error reading '%s': %s", pszFilename, strerror(rc));
+            }
+            if (rc)
+                rc = 1;
+        }
+        else
+        {
+            if (!fQuiet)
+                errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno));
+            rc = 1;
+        }
+    }
+    else
+    {
+        errx(1, "Malformed MD5 digest '%s'!", pszDigest);
+        errx(1, "                      %*s^", rc - 1, "");
+        rc = 1;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Checks the specified md5.lst file.
+ *
+ * @returns 0 if all checks out file, 1 if one or more fails or there are read errors.
+ * @param   pszFilename     The name of the file.
+ * @param   fText           The default mode, text or binary. Only used when fBinaryTextOpt is true.
+ * @param   fBinaryTextOpt  Whether a -b or -t option was specified and should be used.
+ * @param   fQuiet          Whether to be quiet.
+ * @param   fProgress   Whether to show an progress indicator on large files.
+ */
+static int check_files(const char *pszFilename, int fText, int fBinaryTextOpt, int fQuiet, unsigned fProgress)
+{
+    int rc = 0;
+    FILE *pFile;
+
+    /*
+     * Try open the md5.lst file and process it line by line.
+     */
+    pFile = fopen(pszFilename, "r");
+    if (pFile)
+    {
+        int iLine = 0;
+        char szLine[8192];
+        while (fgets(szLine, sizeof(szLine), pFile))
+        {
+            const char *pszDigest;
+            int fLineText;
+            char *psz;
+            int rc2;
+
+            iLine++;
+            psz = szLine;
+
+            /* leading blanks */
+            while (*psz == ' ' || *psz == '\t' || *psz == '\n')
+                psz++;
+
+            /* skip blank or comment lines. */
+            if (!*psz || *psz == '#' || *psz == ';' || *psz == '/')
+                continue;
+
+            /* remove the trailing newline. */
+            rc2 = (int)strlen(psz);
+            if (psz[rc2 - 1] == '\n')
+                psz[rc2 - (rc2 >= 2 && psz[rc2 - 2] == '\r' ? 2 : 1)] = '\0';
+
+            /* skip to the end of the digest and terminate it. */
+            pszDigest = psz;
+            while (*psz != ' ' && *psz != '\t' && *psz)
+                psz++;
+            if (*psz)
+            {
+                *psz++ = '\0';
+
+                /* blanks */
+                while (*psz == ' ' || *psz == '\t' || *psz == '\n')
+                    psz++;
+
+                /* check for binary asterix */
+                if (*psz != '*')
+                    fLineText = fBinaryTextOpt ? fText : 0;
+                else
+                {
+                    fLineText = 0;
+                    psz++;
+                }
+                if (*psz)
+                {
+                    unsigned char Digest[16];
+
+                    /* the rest is filename. */
+                    pszFilename = psz;
+
+                    /*
+                     * Do the job.
+                     */
+                    rc2 = string_to_digest(pszDigest, Digest);
+                    if (!rc2)
+                    {
+                        void *pvFile = open_file(pszFilename, fLineText);
+                        if (pvFile)
+                        {
+                            if (!fQuiet)
+                                fprintf(stdout, "%s: ", pszFilename);
+                            rc2 = check_md5sum(pvFile, Digest, fProgress);
+                            close_file(pvFile);
+                            if (!fQuiet)
+                            {
+                                fprintf(stdout, "%s\n", !rc2 ? "OK" : rc2 < 0 ? "FAILURE" : "ERROR");
+                                fflush(stdout);
+                                if (rc2 > 0)
+                                    errx(1, "Error reading '%s': %s", pszFilename, strerror(rc2));
+                            }
+                            if (rc2)
+                                rc = 1;
+                        }
+                        else
+                        {
+                            if (!fQuiet)
+                                errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno));
+                            rc = 1;
+                        }
+                    }
+                    else if (!fQuiet)
+                    {
+                        errx(1, "%s (%d): Ignoring malformed digest '%s' (digest)", pszFilename, iLine, pszDigest);
+                        errx(1, "%s (%d):                            %*s^", pszFilename, iLine, rc2 - 1, "");
+                    }
+                }
+                else if (!fQuiet)
+                    errx(1, "%s (%d): Ignoring malformed line!", pszFilename, iLine);
+            }
+            else if (!fQuiet)
+                errx(1, "%s (%d): Ignoring malformed line!", pszFilename, iLine);
+        } /* while more lines */
+
+        fclose(pFile);
+    }
+    else
+    {
+        errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno));
+        rc = 1;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Calculates the MD5 sum for one file and prints it.
+ *
+ * @returns 0 on success, 1 on any kind of failure.
+ * @param   pszFilename     The file to process.
+ * @param   fText           The mode to open the file in.
+ * @param   fQuiet          Whether to be quiet or verbose about errors.
+ * @param   fProgress       Whether to show an progress indicator on large files.
+ * @param   pOutput         Where to write the list. Progress is always written to stdout. 
+ */
+static int md5sum_file(const char *pszFilename, unsigned fText, unsigned fQuiet, unsigned fProgress, FILE *pOutput)
+{
+    int rc;
+    void *pvFile;
+
+    /*
+     * Calcuate and print the MD5 sum for one file.
+     */
+    pvFile = open_file(pszFilename, fText);
+    if (pvFile)
+    {
+        unsigned char Digest[16];
+
+        if (fProgress && pOutput)
+            fprintf(stdout, "%s: ", pszFilename);
+
+        rc = calc_md5sum(pvFile, Digest, fProgress);
+        close_file(pvFile);
+
+        if (fProgress && pOutput)
+        {
+            size_t cch = strlen(pszFilename) + 2;
+            while (cch-- > 0)
+                fputc('\b', stdout);
+        }
+
+        if (!rc)
+        {
+            char szDigest[36];
+            digest_to_string(Digest, szDigest);
+            if (pOutput)
+            {
+                fprintf(pOutput, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename);
+                fflush(pOutput);
+            }
+            fprintf(stdout, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename);
+            fflush(stdout);
+        }
+        else
+        {
+            if (!fQuiet)
+                errx(1, "Failed to open '%s': %s", pszFilename, strerror(rc));
+            rc = 1;
+        }
+    }
+    else
+    {
+        if (!fQuiet)
+            errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno));
+        rc = 1;
+    }
+    return rc;
+}
+
+
+
+/**
+ * md5sum, calculates and checks the md5sum of files.
+ * Somewhat similar to the GNU coreutil md5sum command.
+ */
+int kmk_builtin_md5sum(int argc, char **argv, char **envp)
+{
+    int i;
+    int rc = 0;
+    int fText = 0;
+    int fBinaryTextOpt = 0;
+    int fQuiet = 0;
+    int fNewLine = 0;
+    int fChecking = 0;
+    int fProgress = 0;
+    int fNoMoreOptions = 0;
+    const char *pszOutput = NULL;
+    FILE *pOutput = NULL;
+
+    g_progname = argv[0];
+
+    /*
+     * Print usage if no arguments.
+     */
+    if (argc <= 1)
+        return usage(stderr);
+
+    /*
+     * Process the arguments, FIFO style.
+     */
+    i = 1;
+    while (i < argc)
+    {
+        char *psz = argv[i];
+        if (!fNoMoreOptions && psz[0] == '-' && psz[1] == '-' && !psz[2])
+            fNoMoreOptions = 1;
+        else if (*psz == '-' && !fNoMoreOptions)
+        {
+            psz++;
+
+            /* convert long options for gnu just for fun */
+            if (*psz == '-')
+            {
+                if (!strcmp(psz, "-binary"))
+                    psz = "b";
+                else if (!strcmp(psz, "-text"))
+                    psz = "t";
+                else if (!strcmp(psz, "-check"))
+                    psz = "c";
+                else if (!strcmp(psz, "-check-file"))
+                    psz = "C";
+                else if (!strcmp(psz, "-output"))
+                    psz = "o";
+                else if (!strcmp(psz, "-progress"))
+                    psz = "p";
+                else if (!strcmp(psz, "-status"))
+                    psz = "q";
+                else if (!strcmp(psz, "-warn"))
+                    psz = "w";
+                else if (!strcmp(psz, "-help"))
+                    psz = "h";
+                else if (!strcmp(psz, "-version"))
+                    psz = "v";
+            }
+
+            /* short options */
+            do
+            {
+                switch (*psz)
+                {
+                    case 'c':
+                        fChecking = 1;
+                        break;
+
+                    case 'b':
+                        fText = 0;
+                        fBinaryTextOpt = 1;
+                        break;
+
+                    case 't':
+                        fText = 1;
+                        fBinaryTextOpt = 1;
+                        break;
+
+                    case 'p':
+                        fProgress = 1;
+                        break;
+
+                    case 'q':
+                        fQuiet = 1;
+                        break;
+
+                    case 'w':
+                        /* ignored */
+                        break;
+
+                    case 'h':
+                        usage(stdout);
+                        return 0;
+
+                    case 'v':
+                        return kbuild_version(argv[0]);
+
+                    /*
+                     * -C md5 file
+                     */
+                    case 'C':
+                    {
+                        const char *pszFilename;
+                        const char *pszDigest;
+
+                        if (psz[1])
+                            pszDigest = &psz[1];
+                        else if (i + 1 < argc)
+                            pszDigest = argv[++i];
+                        else
+                        {
+                            errx(1, "'-C' is missing the MD5 sum!");
+                            return 1;
+                        }
+                        if (i + 1 < argc)
+                            pszFilename = argv[++i];
+                        else
+                        {
+                            errx(1, "'-C' is missing the filename!");
+                            return 1;
+                        }
+
+                        rc |= check_one_file(pszFilename, pszDigest, fText, fQuiet, fProgress && !fQuiet);
+                        psz = "\0";
+                        break;
+                    }
+
+                    /*
+                     * Output file.
+                     */
+                    case 'o':
+                    {
+                        if (fChecking)
+                        {
+                            errx(1, "'-o' cannot be used with -c or -C!");
+                            return 1;
+                        }
+
+                        if (psz[1])
+                            pszOutput = &psz[1];
+                        else if (i + 1 < argc)
+                            pszOutput = argv[++i];
+                        else
+                        {
+                            errx(1, "'-o' is missing the file name!");
+                            return 1;
+                        }
+
+                        psz = "\0";
+                        break;
+                    }
+
+                    default:
+                        errx(1, "Invalid option '%c'! (%s)", *psz, argv[i]);
+                        return usage(stderr);
+                }
+            } while (*++psz);
+        }
+        else if (fChecking)
+            rc |= check_files(argv[i], fText, fBinaryTextOpt, fQuiet, fProgress && !fQuiet);
+        else
+        {
+            /* lazily open the output if specified. */
+            if (pszOutput)
+            {
+                if (pOutput)
+                    fclose(pOutput);
+                pOutput = fopen(pszOutput, "w");
+                if (!pOutput)
+                {
+                    rc = err(1, "fopen(\"%s\", \"w\") failed", pszOutput);
+                    break;
+                }
+                pszOutput = NULL;
+            }
+
+            rc |= md5sum_file(argv[i], fText, fQuiet, fProgress && !fQuiet, pOutput);
+        }
+        i++;
+    }
+
+    if (pOutput)
+        fclose(pOutput);
+    return rc;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mkdir.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mkdir.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mkdir.c	(revision 1780)
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 1983, 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1983, 1992, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkdir.c	8.2 (Berkeley) 1/25/94";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/mkdir/mkdir.c,v 1.28 2004/04/06 20:06:48 markm Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "err.h"
+#include <errno.h>
+#ifndef _MSC_VER
+# include <libgen.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include "getopt.h"
+#ifdef _MSC_VER
+# include <malloc.h>
+# include "mscfakes.h"
+#endif
+#include "kmkbuiltin.h"
+
+
+static int vflag;
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { 0, 0,	0, 0 },
+};
+
+
+extern void * bsd_setmode(const char *p);
+extern mode_t bsd_getmode(const void *bbox, mode_t omode);
+
+static int	build(char *, mode_t);
+static int	usage(FILE *);
+
+
+int
+kmk_builtin_mkdir(int argc, char *argv[], char **envp)
+{
+	int ch, exitval, success, pflag;
+	mode_t omode, *set = (mode_t *)NULL;
+	char *mode;
+
+	omode = pflag = 0;
+	mode = NULL;
+
+	/* reinitialize globals */
+	vflag = 0;
+
+	/* kmk: reset getopt and set progname */
+	g_progname = argv[0];
+	opterr = 1;
+	optarg = NULL;
+	optopt = 0;
+	optind = 0; /* init */
+	while ((ch = getopt_long(argc, argv, "m:pv", long_options, NULL)) != -1)
+		switch(ch) {
+		case 'm':
+			mode = optarg;
+			break;
+		case 'p':
+			pflag = 1;
+			break;
+		case 'v':
+			vflag = 1;
+			break;
+		case 261:
+			usage(stdout);
+			return 0;
+		case 262:
+			return kbuild_version(argv[0]);
+		case '?':
+			default:
+			return usage(stderr);
+		}
+
+	argc -= optind;
+	argv += optind;
+	if (argv[0] == NULL)
+		return usage(stderr);
+
+	if (mode == NULL) {
+		omode = S_IRWXU | S_IRWXG | S_IRWXO;
+	} else {
+		if ((set = bsd_setmode(mode)) == NULL)
+                        return errx(1, "invalid file mode: %s", mode);
+		omode = bsd_getmode(set, S_IRWXU | S_IRWXG | S_IRWXO);
+		free(set);
+	}
+
+	for (exitval = 0; *argv != NULL; ++argv) {
+		success = 1;
+		if (pflag) {
+			if (build(*argv, omode))
+				success = 0;
+		} else if (mkdir(*argv, omode) < 0) {
+			if (errno == ENOTDIR || errno == ENOENT)
+				warn("%s", dirname(*argv));
+			else
+                                warn("%s", *argv);
+			success = 0;
+		} else if (vflag)
+			(void)printf("%s\n", *argv);
+
+		if (!success)
+			exitval = 1;
+		/*
+		 * The mkdir() and umask() calls both honor only the low
+		 * nine bits, so if you try to set a mode including the
+		 * sticky, setuid, setgid bits you lose them.  Don't do
+		 * this unless the user has specifically requested a mode,
+		 * as chmod will (obviously) ignore the umask.
+		 */
+		if (success && mode != NULL && chmod(*argv, omode) == -1) {
+			warn("%s", *argv);
+			exitval = 1;
+		}
+	}
+	return exitval;
+}
+
+static int
+build(char *path, mode_t omode)
+{
+	struct stat sb;
+	mode_t numask, oumask;
+	int first, last, retval;
+	char *p;
+
+	const size_t len = strlen(path);
+	p = alloca(len + 1);
+	path = memcpy(p, path, len + 1);
+
+#if defined(_MSC_VER) || defined(__EMX__)
+	/* correct slashes. */
+	p = strchr(path, '\\');
+	while (p) {
+		*p++ = '/';
+		p = strchr(p, '\\');
+	}
+#endif
+
+	p = path;
+	oumask = 0;
+	retval = 0;
+#if defined(_MSC_VER) || defined(__EMX__)
+	if (    (    (p[0] >= 'A' && p[0] <= 'Z')
+	         ||  (p[0] >= 'a' && p[0] <= 'z'))
+	    && p[1] == ':')
+		p += 2; /* skip the drive letter */
+	else if (   p[0] == '/'
+	         && p[1] == '/'
+	         && p[2] != '/')
+	{
+		/* UNC */
+		p += 2;
+		while (*p && *p != '/') /* server */
+			p++;
+		while (*p == '/')
+			p++;
+		while (*p && *p != '/') /* share */
+			p++;
+	}
+#endif
+	if (p[0] == '/')		/* Skip leading '/'. */
+		++p;
+	for (first = 1, last = 0; !last ; ++p) {
+		if (p[0] == '\0')
+			last = 1;
+		else if (p[0] != '/')
+			continue;
+		*p = '\0';
+		if (!last && p[1] == '\0')
+			last = 1;
+		if (first) {
+			/*
+			 * POSIX 1003.2:
+			 * For each dir operand that does not name an existing
+			 * directory, effects equivalent to those cased by the
+			 * following command shall occcur:
+			 *
+			 * mkdir -p -m $(umask -S),u+wx $(dirname dir) &&
+			 *    mkdir [-m mode] dir
+			 *
+			 * We change the user's umask and then restore it,
+			 * instead of doing chmod's.
+			 */
+			oumask = umask(0);
+			numask = oumask & ~(S_IWUSR | S_IXUSR);
+			(void)umask(numask);
+			first = 0;
+		}
+		if (last)
+			(void)umask(oumask);
+		if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
+			if (errno == EEXIST || errno == EISDIR || errno == ENOSYS /* (solaris crap) */) {
+				if (stat(path, &sb) < 0) {
+					warn("%s", path);
+					retval = 1;
+					break;
+				} else if (!S_ISDIR(sb.st_mode)) {
+					if (last)
+						errno = EEXIST;
+					else
+						errno = ENOTDIR;
+					warn("%s", path);
+					retval = 1;
+					break;
+				}
+			} else {
+				warn("%s", path);
+				retval = 1;
+				break;
+			}
+		} else if (vflag)
+			printf("%s\n", path);
+		if (!last)
+		    *p = '/';
+	}
+	if (!first && !last)
+		(void)umask(oumask);
+	return (retval);
+}
+
+static int
+usage(FILE *pf)
+{
+	fprintf(pf, "usage: %s [-pv] [-m mode] directory ...\n"
+	            "   or: %s --help\n"
+	            "   or: %s --version\n",
+	        g_progname, g_progname, g_progname);
+	return EX_USAGE;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mscfakes.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mscfakes.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mscfakes.c	(revision 1780)
@@ -0,0 +1,541 @@
+/* $Id$ */
+/** @file
+ *
+ * Fake Unix stuff for MSC.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "err.h"
+#include "mscfakes.h"
+
+#define timeval windows_timeval
+#include <Windows.h>
+#undef timeval
+
+
+/**
+ * Makes corrections to a directory path that ends with a trailing slash.
+ *
+ * @returns temporary buffer to free.
+ * @param   ppszPath    The path pointer. This is updated when necessary.
+ * @param   pfMustBeDir This is set if it must be a directory, otherwise it's cleared.
+ */
+static char *
+msc_fix_path(const char **ppszPath, int *pfMustBeDir)
+{
+    const char *pszPath = *ppszPath;
+    const char *psz;
+    char *pszNew;
+    *pfMustBeDir = 0;
+
+    /*
+     * Skip any compusory trailing slashes
+     */
+    if (pszPath[0] == '/' || pszPath[0] == '\\')
+    {
+        if (   (pszPath[1] == '/' || pszPath[1] == '\\')
+            &&  pszPath[2] != '/'
+            &&  pszPath[2] != '\\')
+            /* unc */
+            pszPath += 2;
+        else
+            /* root slash(es) */
+            pszPath++;
+    }
+    else if (   isalpha(pszPath[0])
+             && pszPath[1] == ':')
+    {
+        if (pszPath[2] == '/' || pszPath[2] == '\\')
+            /* drive w/ slash */
+            pszPath += 3;
+        else
+            /* drive relative path. */
+            pszPath += 2;
+    }
+    /* else: relative path, no skipping necessary. */
+
+    /*
+     * Any trailing slashes to drop off?
+     */
+    psz = strchr(pszPath, '\0');
+    if (pszPath <= psz)
+        return NULL;
+    if (   psz[-1] != '/'
+        || psz[-1] != '\\')
+        return NULL;
+
+    /* figure how many, make a copy and strip them off. */
+    while (     psz > pszPath
+           &&   (   psz[-1] == '/'
+                 || psz[-1] == '\\'))
+        psz--;
+    pszNew = strdup(pszPath);
+    pszNew[psz - pszPath] = '\0';
+
+    *pfMustBeDir = 1;
+    *ppszPath = pszNew; /* use this one */
+    return pszNew;
+}
+
+
+static int
+msc_set_errno(DWORD dwErr)
+{
+    switch (dwErr)
+    {
+        default:
+        case ERROR_INVALID_FUNCTION:        errno = EINVAL; break;
+        case ERROR_FILE_NOT_FOUND:          errno = ENOENT; break;
+        case ERROR_PATH_NOT_FOUND:          errno = ENOENT; break;
+        case ERROR_TOO_MANY_OPEN_FILES:     errno = EMFILE; break;
+        case ERROR_ACCESS_DENIED:           errno = EACCES; break;
+        case ERROR_INVALID_HANDLE:          errno = EBADF; break;
+        case ERROR_ARENA_TRASHED:           errno = ENOMEM; break;
+        case ERROR_NOT_ENOUGH_MEMORY:       errno = ENOMEM; break;
+        case ERROR_INVALID_BLOCK:           errno = ENOMEM; break;
+        case ERROR_BAD_ENVIRONMENT:         errno = E2BIG; break;
+        case ERROR_BAD_FORMAT:              errno = ENOEXEC; break;
+        case ERROR_INVALID_ACCESS:          errno = EINVAL; break;
+        case ERROR_INVALID_DATA:            errno = EINVAL; break;
+        case ERROR_INVALID_DRIVE:           errno = ENOENT; break;
+        case ERROR_CURRENT_DIRECTORY:       errno = EACCES; break;
+        case ERROR_NOT_SAME_DEVICE:         errno = EXDEV; break;
+        case ERROR_NO_MORE_FILES:           errno = ENOENT; break;
+        case ERROR_LOCK_VIOLATION:          errno = EACCES; break;
+        case ERROR_BAD_NETPATH:             errno = ENOENT; break;
+        case ERROR_NETWORK_ACCESS_DENIED:   errno = EACCES; break;
+        case ERROR_BAD_NET_NAME:            errno = ENOENT; break;
+        case ERROR_FILE_EXISTS:             errno = EEXIST; break;
+        case ERROR_CANNOT_MAKE:             errno = EACCES; break;
+        case ERROR_FAIL_I24:                errno = EACCES; break;
+        case ERROR_INVALID_PARAMETER:       errno = EINVAL; break;
+        case ERROR_NO_PROC_SLOTS:           errno = EAGAIN; break;
+        case ERROR_DRIVE_LOCKED:            errno = EACCES; break;
+        case ERROR_BROKEN_PIPE:             errno = EPIPE; break;
+        case ERROR_DISK_FULL:               errno = ENOSPC; break;
+        case ERROR_INVALID_TARGET_HANDLE:   errno = EBADF; break;
+        case ERROR_WAIT_NO_CHILDREN:        errno = ECHILD; break;
+        case ERROR_CHILD_NOT_COMPLETE:      errno = ECHILD; break;
+        case ERROR_DIRECT_ACCESS_HANDLE:    errno = EBADF; break;
+        case ERROR_NEGATIVE_SEEK:           errno = EINVAL; break;
+        case ERROR_SEEK_ON_DEVICE:          errno = EACCES; break;
+        case ERROR_DIR_NOT_EMPTY:           errno = ENOTEMPTY; break;
+        case ERROR_NOT_LOCKED:              errno = EACCES; break;
+        case ERROR_BAD_PATHNAME:            errno = ENOENT; break;
+        case ERROR_MAX_THRDS_REACHED:       errno = EAGAIN; break;
+        case ERROR_LOCK_FAILED:             errno = EACCES; break;
+        case ERROR_ALREADY_EXISTS:          errno = EEXIST; break;
+        case ERROR_FILENAME_EXCED_RANGE:    errno = ENOENT; break;
+        case ERROR_NESTING_NOT_ALLOWED:     errno = EAGAIN; break;
+    }
+
+    return -1;
+}
+
+char *dirname(char *path)
+{
+    /** @todo later */
+    return path;
+}
+
+
+int lchmod(const char *pszPath, mode_t mode)
+{
+    int rc = 0;
+    int fMustBeDir;
+    char *pszPathFree = msc_fix_path(&pszPath, &fMustBeDir);
+
+    /*
+     * Get the current attributes
+     */
+    DWORD fAttr = GetFileAttributes(pszPath);
+    if (fAttr == INVALID_FILE_ATTRIBUTES)
+        rc = msc_set_errno(GetLastError());
+    else if (fMustBeDir & !(fAttr & FILE_ATTRIBUTE_DIRECTORY))
+    {
+        errno = ENOTDIR;
+        rc = -1;
+    }
+    else
+    {
+        /*
+         * Modify the attributes and try set them.
+         */
+        if (mode & _S_IWRITE)
+            fAttr &= ~FILE_ATTRIBUTE_READONLY;
+        else
+            fAttr |= FILE_ATTRIBUTE_READONLY;
+        if (!SetFileAttributes(pszPath, fAttr))
+            rc = msc_set_errno(GetLastError());
+    }
+
+    if (pszPathFree)
+    {
+        int saved_errno = errno;
+        free(pszPathFree);
+        errno = saved_errno;
+    }
+    return rc;
+}
+
+
+int msc_chmod(const char *pszPath, mode_t mode)
+{
+    int rc = 0;
+    int saved_errno;
+    int fMustBeDir;
+    char *pszPathFree = msc_fix_path(&pszPath, &fMustBeDir);
+
+    /*
+     * Get the current attributes.
+     */
+    DWORD fAttr = GetFileAttributes(pszPath);
+    if (fAttr == INVALID_FILE_ATTRIBUTES)
+        rc = msc_set_errno(GetLastError());
+    else if (fMustBeDir & !(fAttr & FILE_ATTRIBUTE_DIRECTORY))
+    {
+        errno = ENOTDIR;
+        rc = -1;
+    }
+    else if (fAttr & FILE_ATTRIBUTE_REPARSE_POINT)
+    {
+        errno = ENOSYS; /** @todo resolve symbolic link / rewrite to NtSetInformationFile. */
+        rc = -1;
+    }
+    else
+    {
+        /*
+         * Modify the attributes and try set them.
+         */
+        if (mode & _S_IWRITE)
+            fAttr &= ~FILE_ATTRIBUTE_READONLY;
+        else
+            fAttr |= FILE_ATTRIBUTE_READONLY;
+        if (!SetFileAttributes(pszPath, fAttr))
+            rc = msc_set_errno(GetLastError());
+    }
+
+    if (pszPathFree)
+    {
+        int saved_errno = errno;
+        free(pszPathFree);
+        errno = saved_errno;
+    }
+    return rc;
+}
+
+
+int link(const char *pszDst, const char *pszLink)
+{
+    errno = ENOSYS;
+    err(1, "link() is not implemented on windows!");
+    return -1;
+}
+
+
+int mkdir_msc(const char *path, mode_t mode)
+{
+    int rc = (mkdir)(path);
+    if (rc)
+    {
+        size_t len = strlen(path);
+        if (len > 0 && (path[len - 1] == '/' || path[len - 1] == '\\'))
+        {
+            char *str = strdup(path);
+            while (len > 0 && (str[len - 1] == '/' || str[len - 1] == '\\'))
+                str[--len] = '\0';
+            rc = (mkdir)(str);
+            free(str);
+        }
+    }
+    return rc;
+}
+
+int rmdir_msc(const char *path)
+{
+    int rc = (rmdir)(path);
+    if (rc)
+    {
+        size_t len = strlen(path);
+        if (len > 0 && (path[len - 1] == '/' || path[len - 1] == '\\'))
+        {
+            char *str = strdup(path);
+            while (len > 0 && (str[len - 1] == '/' || str[len - 1] == '\\'))
+                str[--len] = '\0';
+            rc = (rmdir)(str);
+            free(str);
+        }
+    }
+    return rc;
+}
+
+
+static int doname(char *pszX, char *pszEnd)
+{
+    static char s_szChars[] = "Xabcdefghijklmnopqrstuwvxyz1234567890";
+    int rc = 0;
+    do
+    {
+        char ch;
+
+        pszEnd++;
+        ch = *(strchr(s_szChars, *pszEnd) + 1);
+        if (ch)
+        {
+            *pszEnd = ch;
+            return 0;
+        }
+        *pszEnd = 'a';
+    } while (pszEnd != pszX);
+    return 1;
+}
+
+
+int mkstemp(char *temp)
+{
+    char *pszX = strchr(temp, 'X');
+    char *pszEnd = strchr(pszX, '\0');
+    int cTries = 1000;
+    while (--cTries > 0)
+    {
+        int fd;
+        if (doname(pszX, pszEnd))
+            return -1;
+        fd = open(temp, _O_EXCL | _O_CREAT | _O_BINARY | _O_RDWR, 0777);
+        if (fd >= 0)
+            return fd;
+    }
+    return -1;
+}
+
+
+/** Unix to DOS. */
+static char *fix_slashes(char *psz)
+{
+    char *pszRet = psz;
+    for (; *psz; psz++)
+        if (*psz == '/')
+            *psz = '\\';
+    return pszRet;
+}
+
+
+/** Calcs the SYMBOLIC_LINK_FLAG_DIRECTORY flag for CreatesymbolcLink.  */
+static DWORD is_directory(const char *pszPath, const char *pszRelativeTo)
+{
+    size_t cchPath = strlen(pszPath);
+    struct stat st;
+    if (cchPath > 0 && pszPath[cchPath - 1] == '\\' || pszPath[cchPath - 1] == '/')
+        return 1; /* SYMBOLIC_LINK_FLAG_DIRECTORY */
+
+    if (stat(pszPath, &st))
+    {
+        size_t cchRelativeTo = strlen(pszRelativeTo);
+        char *psz = malloc(cchPath + cchRelativeTo + 4);
+        memcpy(psz, pszRelativeTo, cchRelativeTo);
+        memcpy(psz + cchRelativeTo, "\\", 1);
+        memcpy(psz + cchRelativeTo + 1, pszPath, cchPath + 1);
+        if (stat(pszPath, &st))
+            st.st_mode = _S_IFREG;
+        free(psz);
+    }
+
+    return (st.st_mode & _S_IFMT) == _S_IFDIR ? 1 : 0;
+}
+
+
+int symlink(const char *pszDst, const char *pszLink)
+{
+    static BOOLEAN (WINAPI *s_pfnCreateSymbolicLinkA)(LPCSTR, LPCSTR, DWORD) = 0;
+    static BOOL s_fTried = FALSE;
+
+    if (!s_fTried)
+    {
+        HMODULE hmod = LoadLibrary("KERNEL32.DLL");
+        if (hmod)
+            *(FARPROC *)&s_pfnCreateSymbolicLinkA = GetProcAddress(hmod, "CreateSymbolicLinkA");
+        s_fTried = TRUE;
+    }
+
+    if (s_pfnCreateSymbolicLinkA)
+    {
+        char *pszDstCopy = fix_slashes(strdup(pszDst));
+        char *pszLinkCopy = fix_slashes(strdup(pszLink));
+        BOOLEAN fRc = s_pfnCreateSymbolicLinkA(pszLinkCopy, pszDstCopy,
+                                               is_directory(pszDstCopy, pszLinkCopy));
+        DWORD err = GetLastError();
+        free(pszDstCopy);
+        free(pszLinkCopy);
+        if (fRc)
+            return 0;
+        switch (err)
+        {
+            case ERROR_NOT_SUPPORTED:       errno = ENOSYS; break;
+            case ERROR_ALREADY_EXISTS:
+            case ERROR_FILE_EXISTS:         errno = EEXIST; break;
+            case ERROR_DIRECTORY:           errno = ENOTDIR; break;
+            case ERROR_ACCESS_DENIED:
+            case ERROR_PRIVILEGE_NOT_HELD:  errno = EPERM; break;
+            default:                        errno = EINVAL; break;
+        }
+        return -1;
+    }
+
+    errno = ENOSYS;
+    err(1, "symlink() is not implemented on windows!");
+    return -1;
+}
+
+
+#if _MSC_VER < 1400
+int snprintf(char *buf, size_t size, const char *fmt, ...)
+{
+    int cch;
+    va_list args;
+    va_start(args, fmt);
+    cch = vsprintf(buf, fmt, args);
+    va_end(args);
+    return cch;
+}
+#endif
+
+
+int utimes(const char *pszPath, const struct timeval *paTimes)
+{
+    /** @todo implement me! */
+    return 0;
+}
+
+
+int writev(int fd, const struct iovec *vector, int count)
+{
+    int size = 0;
+    int i;
+    for (i = 0; i < count; i++)
+    {
+        int cb = (int)write(fd, vector[i].iov_base, (int)vector[i].iov_len);
+        if (cb < 0)
+            return -1;
+        size += cb;
+    }
+    return size;
+}
+
+
+intmax_t strtoimax(const char *nptr, char **endptr, int base)
+{
+    return strtol(nptr, endptr, base); /** @todo fix this. */
+}
+
+
+uintmax_t strtoumax(const char *nptr, char **endptr, int base)
+{
+    return strtoul(nptr, endptr, base); /** @todo fix this. */
+}
+
+
+int asprintf(char **strp, const char *fmt, ...)
+{
+    int rc;
+    va_list va;
+    va_start(va, fmt);
+    rc = vasprintf(strp, fmt, va);
+    va_end(va);
+    return rc;
+}
+
+
+int vasprintf(char **strp, const char *fmt, va_list va)
+{
+    int rc;
+    char *psz;
+    size_t cb = 1024;
+
+    *strp = NULL;
+    for (;;)
+    {
+        va_list va2;
+
+        psz = malloc(cb);
+        if (!psz)
+            return -1;
+
+#ifdef va_copy
+        va_copy(va2, va);
+        rc = snprintf(psz, cb, fmt, va2);
+        va_end(vaCopy);
+#else
+        va2 = va;
+        rc = snprintf(psz, cb, fmt, va2);
+#endif
+        if (rc < 0 || (size_t)rc < cb)
+            break;
+        cb *= 2;
+        free(psz);
+    }
+
+    *strp = psz;
+    return rc;
+}
+
+
+#undef stat
+/*
+ * Workaround for directory names with trailing slashes.
+ * Added by bird reasons stated.
+ */
+int
+my_other_stat(const char *path, struct stat *st)
+{
+    int rc = stat(path, st);
+    if (    rc != 0
+        &&  errno == ENOENT
+        &&  *path != '\0')
+    {
+        char *slash = strchr(path, '\0') - 1;
+        if (*slash == '/' || *slash == '\\')
+        {
+            size_t len_path = slash - path + 1;
+            char *tmp = alloca(len_path + 4);
+            memcpy(tmp, path, len_path);
+            tmp[len_path] = '.';
+            tmp[len_path + 1] = '\0';
+            errno = 0;
+            rc = stat(tmp, st);
+            if (    rc == 0
+                &&  !S_ISDIR(st->st_mode))
+            {
+                errno = ENOTDIR;
+                rc = -1;
+            }
+        }
+    }
+    return rc;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mscfakes.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mscfakes.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mscfakes.h	(revision 1780)
@@ -0,0 +1,158 @@
+/* $Id$ */
+/** @file
+ *
+ * Unix fakes for MSC.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+#ifndef __mscfakes_h__
+#define __mscfakes_h__
+#ifdef _MSC_VER
+
+#include <io.h>
+#include <direct.h>
+#include <time.h>
+#include <stdarg.h>
+#include <malloc.h>
+#include "getopt.h"
+
+#if defined(MSC_DO_64_BIT_IO) && _MSC_VER >= 1400 /* We want 64-bit file lengths here when possible. */
+# define off_t __int64
+# define stat  _stat64
+# define fstat _fstat64
+# define lseek _lseeki64
+#else
+# undef stat
+# define stat(_path, _st) my_other_stat(_path, _st)
+extern int my_other_stat(const char *, struct stat *);
+#endif
+
+
+
+#define S_ISDIR(m)  (((m) & _S_IFMT) == _S_IFDIR)
+#define S_ISREG(m)  (((m) & _S_IFMT) == _S_IFREG)
+#define S_ISLNK(m)  0
+#define	S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC)
+#define	S_IXUSR _S_IEXEC
+#define	S_IWUSR _S_IWRITE
+#define	S_IRUSR _S_IREAD
+#define S_IRWXG 0000070
+#define S_IRGRP	0000040
+#define S_IWGRP	0000020
+#define S_IXGRP 0000010
+#define S_IRWXO 0000007
+#define S_IROTH	0000004
+#define S_IWOTH	0000002
+#define S_IXOTH 0000001
+#define	S_ISUID 0004000
+#define	S_ISGID 0002000
+#define ALLPERMS 0000777
+
+#define PATH_MAX _MAX_PATH
+#define MAXPATHLEN _MAX_PATH
+
+#define EX_OK 0
+#define EX_OSERR 1
+#define EX_NOUSER 1
+#define EX_USAGE 1
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+#define F_OK 0
+#define X_OK 1
+#define W_OK 2
+#define R_OK 4
+
+#define EFTYPE EINVAL
+
+#define _PATH_DEVNULL "/dev/null"
+
+#define MAX(a,b) ((a) >= (b) ? (a) : (b))
+
+typedef int mode_t;
+typedef unsigned short nlink_t;
+typedef unsigned short uid_t;
+typedef unsigned short gid_t;
+typedef long ssize_t;
+typedef unsigned long u_long;
+typedef unsigned int u_int;
+typedef unsigned short u_short;
+
+#ifndef timerisset
+struct timeval
+{
+    long tv_sec;
+    long tv_usec;
+};
+#endif
+
+struct iovec
+{
+    char *iov_base;
+    size_t iov_len;
+};
+
+typedef __int64 intmax_t;
+typedef unsigned __int64 uintmax_t;
+
+#define chown(path, uid, gid) 0         /** @todo implement fchmod! */
+char *dirname(char *path);
+#define fsync(fd)  0
+#define fchown(fd,uid,gid) 0
+#define fchmod(fd, mode) 0              /** @todo implement fchmod! */
+#define geteuid()  0
+#define getegid()  0
+#define lstat(path, s) stat(path, s)
+int lchmod(const char *path, mode_t mode);
+int msc_chmod(const char *path, mode_t mode);
+#define chmod msc_chmod
+#define lchown(path, uid, gid) chown(path, uid, gid)
+#define lutimes(path, tvs) utimes(path, tvs)
+int link(const char *pszDst, const char *pszLink);
+int mkdir_msc(const char *path, mode_t mode);
+#define mkdir(path, mode) mkdir_msc(path, mode)
+#define mkfifo(path, mode) -1
+#define mknod(path, mode, devno) -1
+int mkstemp(char *temp);
+#define readlink(link, buf, size) -1
+#define reallocf(old, size) realloc(old, size)
+int rmdir_msc(const char *path);
+#define rmdir(path) rmdir_msc(path)
+intmax_t strtoimax(const char *nptr, char **endptr, int base);
+uintmax_t strtoumax(const char *nptr, char **endptr, int base);
+#define strtoll(a,b,c) strtoimax(a,b,c)
+#define strtoull(a,b,c) strtoumax(a,b,c)
+int asprintf(char **strp, const char *fmt, ...);
+int vasprintf(char **strp, const char *fmt, va_list ap);
+#if _MSC_VER < 1400
+int snprintf(char *buf, size_t size, const char *fmt, ...);
+#else
+#define snprintf _snprintf
+#endif
+size_t strlcpy(char *, const char *, size_t);
+int symlink(const char *pszDst, const char *pszLink);
+int utimes(const char *pszPath, const struct timeval *paTimes);
+int writev(int fd, const struct iovec *vector, int count);
+
+#endif /* _MSC_VER */
+#endif
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mv.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mv.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/mv.c	(revision 1780)
@@ -0,0 +1,503 @@
+/*-
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ken Smith of The State University of New York at Buffalo.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1989, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mv.c	8.2 (Berkeley) 4/2/94";
+#endif /* not lint */
+#endif
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/mv/mv.c,v 1.46 2005/09/05 04:36:08 csjp Exp $");
+#endif
+
+#include <sys/types.h>
+#ifndef _MSC_VER
+# ifndef __OS2__
+#  include <sys/acl.h>
+# endif
+# include <sys/param.h>
+# include <sys/time.h>
+# include <sys/wait.h>
+# include <sys/mount.h>
+#endif
+#include <sys/stat.h>
+
+#include "err.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <limits.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include "getopt.h"
+#ifdef __sun__
+# include "solfakes.h"
+#endif
+#ifdef _MSC_VER
+# include "mscfakes.h"
+#endif
+#include "kmkbuiltin.h"
+
+
+static int fflg, iflg, nflg, vflg;
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { 0, 0,	0, 0 },
+};
+
+
+static int	do_move(char *, char *);
+#ifdef CROSS_DEVICE_MOVE
+static int	fastcopy(char *, char *, struct stat *);
+static int	copy(char *, char *);
+#endif
+static int	usage(FILE *);
+
+extern void bsd_strmode(mode_t mode, char *p);
+
+#if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__DragonFly__)
+# ifdef __OS2__
+static
+# endif
+const char *user_from_uid(uid_t id, int x)
+{
+	static char s_buf[64];
+	sprintf(s_buf, "%ld", id);
+	return s_buf;
+}
+# ifdef __OS2__
+static
+# endif
+const char *group_from_gid(gid_t id, int x)
+{
+	static char s_buf[64];
+	sprintf(s_buf, "%ld", id);
+	return s_buf;
+}
+#endif /* 'not in libc' */
+
+
+int
+kmk_builtin_mv(int argc, char *argv[], char **envp)
+{
+	size_t baselen, len;
+	int rval;
+	char *p, *endp;
+	struct stat sb;
+	int ch;
+	char path[PATH_MAX];
+
+	/* kmk: reinitialize globals */
+	fflg = iflg = nflg = vflg = 0;
+
+	/* kmk: reset getopt and set progname */
+	g_progname = argv[0];
+	opterr = 1;
+	optarg = NULL;
+	optopt = 0;
+	optind = 0; /* init */
+
+	while ((ch = getopt_long(argc, argv, "finv", long_options, NULL)) != -1)
+		switch (ch) {
+		case 'i':
+			iflg = 1;
+			fflg = nflg = 0;
+			break;
+		case 'f':
+			fflg = 1;
+			iflg = nflg = 0;
+			break;
+		case 'n':
+			nflg = 1;
+			fflg = iflg = 0;
+			break;
+		case 'v':
+			vflg = 1;
+			break;
+		case 261:
+			usage(stdout);
+			return 0;
+		case 262:
+			return kbuild_version(argv[0]);
+		default:
+			return usage(stderr);
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 2)
+		return usage(stderr);
+
+	/*
+	 * If the stat on the target fails or the target isn't a directory,
+	 * try the move.  More than 2 arguments is an error in this case.
+	 */
+	if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) {
+		if (argc > 2)
+			return usage(stderr);
+		return do_move(argv[0], argv[1]);
+	}
+
+	/* It's a directory, move each file into it. */
+	if (strlen(argv[argc - 1]) > sizeof(path) - 1)
+		return errx(1, "%s: destination pathname too long", *argv);
+	(void)strcpy(path, argv[argc - 1]);
+	baselen = strlen(path);
+	endp = &path[baselen];
+#if defined(_MSC_VER) || defined(__EMX__)
+	if (!baselen || (*(endp - 1) != '/' && *(endp - 1) != '\\' && *(endp - 1) != ':')) {
+#else
+	if (!baselen || *(endp - 1) != '/') {
+#endif
+		*endp++ = '/';
+		++baselen;
+	}
+	for (rval = 0; --argc; ++argv) {
+		/*
+		 * Find the last component of the source pathname.  It
+		 * may have trailing slashes.
+		 */
+		p = *argv + strlen(*argv);
+#if defined(_MSC_VER) || defined(__EMX__)
+		while (p != *argv && (p[-1] == '/' || p[-1] == '\\'))
+			--p;
+		while (p != *argv && p[-1] != '/' && p[-1] != '/' && p[-1] != ':')
+			--p;
+#else
+		while (p != *argv && p[-1] == '/')
+			--p;
+		while (p != *argv && p[-1] != '/')
+			--p;
+#endif
+
+		if ((baselen + (len = strlen(p))) >= PATH_MAX) {
+			warnx("%s: destination pathname too long", *argv);
+			rval = 1;
+		} else {
+			memmove(endp, p, (size_t)len + 1);
+			if (do_move(*argv, path))
+				rval = 1;
+		}
+	}
+	return rval;
+}
+
+static int
+do_move(char *from, char *to)
+{
+	struct stat sb;
+	int ask, ch, first;
+	char modep[15];
+
+	/*
+	 * Check access.  If interactive and file exists, ask user if it
+	 * should be replaced.  Otherwise if file exists but isn't writable
+	 * make sure the user wants to clobber it.
+	 */
+	if (!fflg && !access(to, F_OK)) {
+
+		/* prompt only if source exist */
+		if (lstat(from, &sb) == -1) {
+			warn("%s", from);
+			return (1);
+		}
+
+#define YESNO "(y/n [n]) "
+		ask = 0;
+		if (nflg) {
+			if (vflg)
+				printf("%s not overwritten\n", to);
+			return (0);
+		} else if (iflg) {
+			(void)fprintf(stderr, "overwrite %s? %s", to, YESNO);
+			ask = 1;
+		} else if (access(to, W_OK) && !stat(to, &sb)) {
+			bsd_strmode(sb.st_mode, modep);
+			(void)fprintf(stderr, "override %s%s%s/%s for %s? %s",
+			    modep + 1, modep[9] == ' ' ? "" : " ",
+			    user_from_uid((unsigned long)sb.st_uid, 0),
+			    group_from_gid((unsigned long)sb.st_gid, 0), to, YESNO);
+			ask = 1;
+		}
+		if (ask) {
+			first = ch = getchar();
+			while (ch != '\n' && ch != EOF)
+				ch = getchar();
+			if (first != 'y' && first != 'Y') {
+				(void)fprintf(stderr, "not overwritten\n");
+				return (0);
+			}
+		}
+	}
+	if (!rename(from, to)) {
+		if (vflg)
+			printf("%s -> %s\n", from, to);
+		return (0);
+	}
+#ifdef _MSC_VER
+	if (errno == EEXIST) {
+		remove(to);
+		if (!rename(from, to)) {
+			if (vflg)
+				printf("%s -> %s\n", from, to);
+			return (0);
+		}
+	}
+#endif
+
+	if (errno == EXDEV) {
+#ifndef CROSS_DEVICE_MOVE
+		warnx("cannot move `%s' to a different device: `%s'", from, to);
+		return (1);
+#else
+		struct statfs sfs;
+		char path[PATH_MAX];
+
+		/*
+		 * If the source is a symbolic link and is on another
+		 * filesystem, it can be recreated at the destination.
+		 */
+		if (lstat(from, &sb) == -1) {
+			warn("%s", from);
+			return (1);
+		}
+		if (!S_ISLNK(sb.st_mode)) {
+			/* Can't mv(1) a mount point. */
+			if (realpath(from, path) == NULL) {
+				warnx("cannot resolve %s: %s", from, path);
+				return (1);
+			}
+			if (!statfs(path, &sfs) &&
+			    !strcmp(path, sfs.f_mntonname)) {
+				warnx("cannot rename a mount point");
+				return (1);
+			}
+		}
+#endif
+	} else {
+		warn("rename %s to %s", from, to);
+		return (1);
+	}
+
+#ifdef CROSS_DEVICE_MOVE
+	/*
+	 * If rename fails because we're trying to cross devices, and
+	 * it's a regular file, do the copy internally; otherwise, use
+	 * cp and rm.
+	 */
+	if (lstat(from, &sb)) {
+		warn("%s", from);
+		return (1);
+	}
+	return (S_ISREG(sb.st_mode) ?
+	    fastcopy(from, to, &sb) : copy(from, to));
+#endif
+}
+
+#ifdef CROSS_DEVICE_MOVE
+int
+static fastcopy(char *from, char *to, struct stat *sbp)
+{
+	struct timeval tval[2];
+	static u_int blen;
+	static char *bp;
+	mode_t oldmode;
+	int nread, from_fd, to_fd;
+	acl_t acl;
+
+	if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
+		warn("%s", from);
+		return (1);
+	}
+	if (blen < sbp->st_blksize) {
+		if (bp != NULL)
+			free(bp);
+		if ((bp = malloc((size_t)sbp->st_blksize)) == NULL) {
+			blen = 0;
+			warnx("malloc failed");
+			return (1);
+		}
+		blen = sbp->st_blksize;
+	}
+	while ((to_fd =
+	    open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) {
+		if (errno == EEXIST && unlink(to) == 0)
+			continue;
+		warn("%s", to);
+		(void)close(from_fd);
+		return (1);
+	}
+	while ((nread = read(from_fd, bp, (size_t)blen)) > 0)
+		if (write(to_fd, bp, (size_t)nread) != nread) {
+			warn("%s", to);
+			goto err;
+		}
+	if (nread < 0) {
+		warn("%s", from);
+err:		if (unlink(to))
+			warn("%s: remove", to);
+		(void)close(from_fd);
+		(void)close(to_fd);
+		return (1);
+	}
+
+	oldmode = sbp->st_mode & ALLPERMS;
+	if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) {
+		warn("%s: set owner/group (was: %lu/%lu)", to,
+		    (u_long)sbp->st_uid, (u_long)sbp->st_gid);
+		if (oldmode & (S_ISUID | S_ISGID)) {
+			warnx(
+"%s: owner/group changed; clearing suid/sgid (mode was 0%03o)",
+			    to, oldmode);
+			sbp->st_mode &= ~(S_ISUID | S_ISGID);
+		}
+	}
+	/*
+	 * POSIX 1003.2c states that if _POSIX_ACL_EXTENDED is in effect
+	 * for dest_file, then it's ACLs shall reflect the ACLs of the
+	 * source_file.
+	 */
+	if (fpathconf(to_fd, _PC_ACL_EXTENDED) == 1 &&
+	    fpathconf(from_fd, _PC_ACL_EXTENDED) == 1) {
+		acl = acl_get_fd(from_fd);
+		if (acl == NULL)
+			warn("failed to get acl entries while setting %s",
+			    from);
+		else if (acl_set_fd(to_fd, acl) < 0)
+			warn("failed to set acl entries for %s", to);
+	}
+	(void)close(from_fd);
+	if (fchmod(to_fd, sbp->st_mode))
+		warn("%s: set mode (was: 0%03o)", to, oldmode);
+	/*
+	 * XXX
+	 * NFS doesn't support chflags; ignore errors unless there's reason
+	 * to believe we're losing bits.  (Note, this still won't be right
+	 * if the server supports flags and we were trying to *remove* flags
+	 * on a file that we copied, i.e., that we didn't create.)
+	 */
+	errno = 0;
+	if (fchflags(to_fd, (u_long)sbp->st_flags))
+		if (errno != EOPNOTSUPP || sbp->st_flags != 0)
+			warn("%s: set flags (was: 0%07o)", to, sbp->st_flags);
+
+	tval[0].tv_sec = sbp->st_atime;
+	tval[1].tv_sec = sbp->st_mtime;
+	tval[0].tv_usec = tval[1].tv_usec = 0;
+	if (utimes(to, tval))
+		warn("%s: set times", to);
+
+	if (close(to_fd)) {
+		warn("%s", to);
+		return (1);
+	}
+
+	if (unlink(from)) {
+		warn("%s: remove", from);
+		return (1);
+	}
+	if (vflg)
+		printf("%s -> %s\n", from, to);
+	return (0);
+}
+
+int
+copy(char *from, char *to)
+{
+	int pid, status;
+
+	if ((pid = fork()) == 0) {
+		execl(_PATH_CP, "mv", vflg ? "-PRpv" : "-PRp", "--", from, to,
+		    (char *)NULL);
+		warn("%s", _PATH_CP);
+		_exit(1);
+	}
+	if (waitpid(pid, &status, 0) == -1) {
+		warn("%s: waitpid", _PATH_CP);
+		return (1);
+	}
+	if (!WIFEXITED(status)) {
+		warnx("%s: did not terminate normally", _PATH_CP);
+		return (1);
+	}
+	if (WEXITSTATUS(status)) {
+		warnx("%s: terminated with %d (non-zero) status",
+		    _PATH_CP, WEXITSTATUS(status));
+		return (1);
+	}
+	if (!(pid = vfork())) {
+		execl(_PATH_RM, "mv", "-rf", "--", from, (char *)NULL);
+		warn("%s", _PATH_RM);
+		_exit(1);
+	}
+	if (waitpid(pid, &status, 0) == -1) {
+		warn("%s: waitpid", _PATH_RM);
+		return (1);
+	}
+	if (!WIFEXITED(status)) {
+		warnx("%s: did not terminate normally", _PATH_RM);
+		return (1);
+	}
+	if (WEXITSTATUS(status)) {
+		warnx("%s: terminated with %d (non-zero) status",
+		    _PATH_RM, WEXITSTATUS(status));
+		return (1);
+	}
+	return (0);
+}
+#endif /* CROSS_DEVICE_MOVE */
+
+
+static int
+usage(FILE *pf)
+{
+	fprintf(pf, "usage: %s [-f | -i | -n] [-v] source target\n"
+	            "   or: %s [-f | -i | -n] [-v] source ... directory\n"
+	            "   or: %s --help\n"
+	            "   or: %s --version\n",
+	        g_progname, g_progname, g_progname, g_progname);
+	return EX_USAGE;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/osdep.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/osdep.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/osdep.c	(revision 1780)
@@ -0,0 +1,43 @@
+/* $Id$ */
+/** @file
+ *
+ * Include all the OS dependent bits when bootstrapping.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+/** @todo replace this by proper configure.in tests. */
+
+#if defined(_MSC_VER)
+# include "mscfakes.c"
+# include "fts.c"
+
+#elif defined(__sun__)
+# include "solfakes.c"
+# include "fts.c"
+
+#elif defined(__APPLE__)
+# include "darwin.c"
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/printf.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/printf.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/printf.c	(revision 1780)
@@ -0,0 +1,699 @@
+/*	$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>
+#ifndef lint
+#if !defined(BUILTIN) && !defined(SHELL)
+__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n");
+#endif
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)printf.c	8.2 (Berkeley) 3/22/95";
+#else
+__RCSID("$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $");
+#endif
+#endif*/ /* not lint */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include "err.h"
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "getopt.h"
+#ifdef __sun__
+# include "solfakes.h"
+#endif
+#ifdef _MSC_VER
+# include "mscfakes.h"
+#endif
+
+#include "kmkbuiltin.h"
+
+
+#ifdef __GNUC__
+#define ESCAPE '\e'
+#else
+#define ESCAPE 033
+#endif
+
+
+static size_t	b_length;
+static char	*b_fmt;
+static int	rval;
+static char  **gargv;
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { 0, 0,	0, 0 },
+};
+
+
+static void	 conv_escape_str(char *, void (*)(int));
+static char	*conv_escape(char *, char *);
+static char	*conv_expand(const char *);
+static int	 getchr(void);
+static double	 getdouble(void);
+static int	 getwidth(void);
+static intmax_t	 getintmax(void);
+static uintmax_t getuintmax(void);
+static char	*getstr(void);
+static char	*mklong(const char *, int);
+static void      check_conversion(const char *, const char *);
+static int	 usage(FILE *);
+
+static void	b_count(int);
+static void	b_output(int);
+
+#ifdef BUILTIN		/* csh builtin */
+#define kmk_builtin_printf progprintf
+#endif
+
+#ifdef SHELL		/* sh (aka ash) builtin */
+#define kmk_builtin_printf printfcmd
+#include "../../bin/sh/bltin/bltin.h"
+#endif /* SHELL */
+
+#define PF(f, func) { \
+	if (fieldwidth != -1) { \
+		if (precision != -1) \
+			(void)printf(f, fieldwidth, precision, func); \
+		else \
+			(void)printf(f, fieldwidth, func); \
+	} else if (precision != -1) \
+		(void)printf(f, precision, func); \
+	else \
+		(void)printf(f, func); \
+}
+
+#define APF(cpp, f, func) { \
+	if (fieldwidth != -1) { \
+		if (precision != -1) \
+			(void)asprintf(cpp, f, fieldwidth, precision, func); \
+		else \
+			(void)asprintf(cpp, f, fieldwidth, func); \
+	} else if (precision != -1) \
+		(void)asprintf(cpp, f, precision, func); \
+	else \
+		(void)asprintf(cpp, f, func); \
+}
+
+int kmk_builtin_printf(int argc, char *argv[], char **envp)
+{
+	char *fmt, *start;
+	int fieldwidth, precision;
+	char nextch;
+	char *format;
+	int ch;
+
+	/* kmk: reinitialize globals */
+	b_length = 0;
+	b_fmt = NULL;
+	rval = 0;
+	gargv = NULL;
+
+	/* kmk: reset getopt and set progname */
+	g_progname = argv[0];
+	opterr = 1;
+	optarg = NULL;
+	optopt = 0;
+	optind = 0; /* init */
+
+#if !defined(SHELL) && !defined(BUILTIN) && !defined(kmk_builtin_printf) /* kmk did this already. */
+	(void)setlocale (LC_ALL, "");
+#endif
+
+	while ((ch = getopt_long(argc, argv, "", long_options, NULL)) != -1) {
+		switch (ch) {
+		case 261:
+			usage(stdout);
+			return 0;
+		case 262:
+			return kbuild_version(argv[0]);
+		case '?':
+		default:
+			return usage(stderr);
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1) {
+		return usage(stderr);
+	}
+
+	format = *argv;
+	gargv = ++argv;
+
+#define SKIP1	"#-+ 0"
+#define SKIP2	"*0123456789"
+	do {
+		/*
+		 * Basic algorithm is to scan the format string for conversion
+		 * specifications -- once one is found, find out if the field
+		 * width or precision is a '*'; if it is, gather up value.
+		 * Note, format strings are reused as necessary to use up the
+		 * provided arguments, arguments of zero/null string are
+		 * provided to use up the format string.
+		 */
+
+		/* find next format specification */
+		for (fmt = format; (ch = *fmt++) != '\0';) {
+			if (ch == '\\') {
+				char c_ch;
+				fmt = conv_escape(fmt, &c_ch);
+				putchar(c_ch);
+				continue;
+			}
+			if (ch != '%' || (*fmt == '%' && ++fmt)) {
+				(void)putchar(ch);
+				continue;
+			}
+
+			/* Ok - we've found a format specification,
+			   Save its address for a later printf(). */
+			start = fmt - 1;
+
+			/* skip to field width */
+			fmt += strspn(fmt, SKIP1);
+			fieldwidth = *fmt == '*' ? getwidth() : -1;
+
+			/* skip to possible '.', get following precision */
+			fmt += strspn(fmt, SKIP2);
+			if (*fmt == '.')
+				++fmt;
+			precision = *fmt == '*' ? getwidth() : -1;
+
+			fmt += strspn(fmt, SKIP2);
+
+			ch = *fmt;
+			if (!ch) {
+				warnx("missing format character");
+				return (1);
+			}
+			/* null terminate format string to we can use it
+			   as an argument to printf. */
+			nextch = fmt[1];
+			fmt[1] = 0;
+			switch (ch) {
+
+			case 'B': {
+				const char *p = conv_expand(getstr());
+				*fmt = 's';
+				PF(start, p);
+				break;
+			}
+			case 'b': {
+				/* There has to be a better way to do this,
+				 * but the string we generate might have
+				 * embedded nulls. */
+				static char *a, *t;
+				char *cp = getstr();
+				/* Free on entry in case shell longjumped out */
+				if (a != NULL)
+					free(a);
+				a = NULL;
+				if (t != NULL)
+					free(t);
+				t = NULL;
+				/* Count number of bytes we want to output */
+				b_length = 0;
+				conv_escape_str(cp, b_count);
+				t = malloc(b_length + 1);
+				if (t == NULL)
+					break;
+				memset(t, 'x', b_length);
+				t[b_length] = 0;
+				/* Get printf to calculate the lengths */
+				*fmt = 's';
+				APF(&a, start, t);
+				b_fmt = a;
+				/* Output leading spaces and data bytes */
+				conv_escape_str(cp, b_output);
+				/* Add any trailing spaces */
+				printf("%s", b_fmt);
+				break;
+			}
+			case 'c': {
+				char p = getchr();
+				PF(start, p);
+				break;
+			}
+			case 's': {
+				char *p = getstr();
+				PF(start, p);
+				break;
+			}
+			case 'd':
+			case 'i': {
+				intmax_t p = getintmax();
+				char *f = mklong(start, ch);
+				PF(f, p);
+				break;
+			}
+			case 'o':
+			case 'u':
+			case 'x':
+			case 'X': {
+				uintmax_t p = getuintmax();
+				char *f = mklong(start, ch);
+				PF(f, p);
+				break;
+			}
+			case 'e':
+			case 'E':
+			case 'f':
+			case 'g':
+			case 'G': {
+				double p = getdouble();
+				PF(start, p);
+				break;
+			}
+			default:
+				warnx("%s: invalid directive", start);
+				return 1;
+			}
+			*fmt++ = ch;
+			*fmt = nextch;
+			/* escape if a \c was encountered */
+			if (rval & 0x100)
+				return rval & ~0x100;
+		}
+	} while (gargv != argv && *gargv);
+
+	return rval;
+}
+
+/* helper functions for conv_escape_str */
+
+static void
+/*ARGSUSED*/
+b_count(int ch)
+{
+	b_length++;
+}
+
+/* Output one converted character for every 'x' in the 'format' */
+
+static void
+b_output(int ch)
+{
+	for (;;) {
+		switch (*b_fmt++) {
+		case 0:
+			b_fmt--;
+			return;
+		case ' ':
+			putchar(' ');
+			break;
+		default:
+			putchar(ch);
+			return;
+		}
+	}
+}
+
+
+/*
+ * Print SysV echo(1) style escape string
+ *	Halts processing string if a \c escape is encountered.
+ */
+static void
+conv_escape_str(char *str, void (*do_putchar)(int))
+{
+	int value;
+	int ch;
+	char c;
+
+	while ((ch = *str++) != '\0') {
+		if (ch != '\\') {
+			do_putchar(ch);
+			continue;
+		}
+
+		ch = *str++;
+		if (ch == 'c') {
+			/* \c as in SYSV echo - abort all processing.... */
+			rval |= 0x100;
+			break;
+		}
+
+		/*
+		 * %b string octal constants are not like those in C.
+		 * They start with a \0, and are followed by 0, 1, 2,
+		 * or 3 octal digits.
+		 */
+		if (ch == '0') {
+			int octnum = 0, i;
+			for (i = 0; i < 3; i++) {
+				if (!isdigit((unsigned char)*str) || *str > '7')
+					break;
+				octnum = (octnum << 3) | (*str++ - '0');
+			}
+			do_putchar(octnum);
+			continue;
+		}
+
+		/* \[M][^|-]C as defined by vis(3) */
+		if (ch == 'M' && *str == '-') {
+			do_putchar(0200 | str[1]);
+			str += 2;
+			continue;
+		}
+		if (ch == 'M' && *str == '^') {
+			str++;
+			value = 0200;
+			ch = '^';
+		} else
+			value = 0;
+		if (ch == '^') {
+			ch = *str++;
+			if (ch == '?')
+				value |= 0177;
+			else
+				value |= ch & 037;
+			do_putchar(value);
+			continue;
+		}
+
+		/* Finally test for sequences valid in the format string */
+		str = conv_escape(str - 1, &c);
+		do_putchar(c);
+	}
+}
+
+/*
+ * Print "standard" escape characters
+ */
+static char *
+conv_escape(char *str, char *conv_ch)
+{
+	int value;
+	int ch;
+	char num_buf[4], *num_end;
+
+	ch = *str++;
+
+	switch (ch) {
+	case '0': case '1': case '2': case '3':
+	case '4': case '5': case '6': case '7':
+		num_buf[0] = ch;
+		ch = str[0];
+		num_buf[1] = ch;
+		num_buf[2] = ch ? str[1] : 0;
+		num_buf[3] = 0;
+		value = strtoul(num_buf, &num_end, 8);
+		str += num_end  - (num_buf + 1);
+		break;
+
+	case 'x':
+		/* Hexadecimal character constants are not required to be
+		   supported (by SuS v1) because there is no consistent
+		   way to detect the end of the constant.
+		   Supporting 2 byte constants is a compromise. */
+		ch = str[0];
+		num_buf[0] = ch;
+		num_buf[1] = ch ? str[1] : 0;
+		num_buf[2] = 0;
+		value = strtoul(num_buf, &num_end, 16);
+		str += num_end - num_buf;
+		break;
+
+	case '\\':	value = '\\';	break;	/* backslash */
+	case '\'':	value = '\'';	break;	/* single quote */
+	case '"':	value = '"';	break;	/* double quote */
+	case 'a':	value = '\a';	break;	/* alert */
+	case 'b':	value = '\b';	break;	/* backspace */
+	case 'e':	value = ESCAPE;	break;	/* escape */
+	case 'f':	value = '\f';	break;	/* form-feed */
+	case 'n':	value = '\n';	break;	/* newline */
+	case 'r':	value = '\r';	break;	/* carriage-return */
+	case 't':	value = '\t';	break;	/* tab */
+	case 'v':	value = '\v';	break;	/* vertical-tab */
+
+	default:
+		warnx("unknown escape sequence `\\%c'", ch);
+		rval = 1;
+		value = ch;
+		break;
+	}
+
+	*conv_ch = value;
+	return str;
+}
+
+/* expand a string so that everything is printable */
+
+static char *
+conv_expand(const char *str)
+{
+	static char *conv_str;
+	static char no_memory[] = "<no memory>";
+	char *cp;
+	int ch;
+
+	if (conv_str)
+		free(conv_str);
+	/* get a buffer that is definitely large enough.... */
+	conv_str = malloc(4 * strlen(str) + 1);
+	if (!conv_str)
+		return no_memory;
+	cp = conv_str;
+
+	while ((ch = *(const unsigned char *)str++) != '\0') {
+		switch (ch) {
+		/* Use C escapes for expected control characters */
+		case '\\':	ch = '\\';	break;	/* backslash */
+		case '\'':	ch = '\'';	break;	/* single quote */
+		case '"':	ch = '"';	break;	/* double quote */
+		case '\a':	ch = 'a';	break;	/* alert */
+		case '\b':	ch = 'b';	break;	/* backspace */
+		case ESCAPE:	ch = 'e';	break;	/* escape */
+		case '\f':	ch = 'f';	break;	/* form-feed */
+		case '\n':	ch = 'n';	break;	/* newline */
+		case '\r':	ch = 'r';	break;	/* carriage-return */
+		case '\t':	ch = 't';	break;	/* tab */
+		case '\v':	ch = 'v';	break;	/* vertical-tab */
+		default:
+			/* Copy anything printable */
+			if (isprint(ch)) {
+				*cp++ = ch;
+				continue;
+			}
+			/* Use vis(3) encodings for the rest */
+			*cp++ = '\\';
+			if (ch & 0200) {
+				*cp++ = 'M';
+				ch &= ~0200;
+			}
+			if (ch == 0177) {
+				*cp++ = '^';
+				*cp++ = '?';
+				continue;
+			}
+			if (ch < 040) {
+				*cp++ = '^';
+				*cp++ = ch | 0100;
+				continue;
+			}
+			*cp++ = '-';
+			*cp++ = ch;
+			continue;
+		}
+		*cp++ = '\\';
+		*cp++ = ch;
+	}
+
+	*cp = 0;
+	return conv_str;
+}
+
+static char *
+mklong(const char *str, int ch)
+{
+	static char copy[64];
+	size_t len;
+
+	len = strlen(str) + 2;
+	if (len > sizeof copy) {
+		warnx("format %s too complex\n", str);
+		len = 4;
+	}
+	(void)memmove(copy, str, len - 3);
+	copy[len - 3] = 'j';
+	copy[len - 2] = ch;
+	copy[len - 1] = '\0';
+	return copy;
+}
+
+static int
+getchr(void)
+{
+	if (!*gargv)
+		return 0;
+	return (int)**gargv++;
+}
+
+static char *
+getstr(void)
+{
+	static char empty[] = "";
+	if (!*gargv)
+		return empty;
+	return *gargv++;
+}
+
+static int
+getwidth(void)
+{
+	long val;
+	char *s, *ep;
+
+	s = *gargv;
+	if (!*gargv)
+		return (0);
+	gargv++;
+
+	errno = 0;
+	val = strtoul(s, &ep, 0);
+	check_conversion(s, ep);
+
+	/* Arbitrarily 'restrict' field widths to 1Mbyte */
+	if (val < 0 || val > 1 << 20) {
+		warnx("%s: invalid field width", s);
+		return 0;
+	}
+
+	return val;
+}
+
+static intmax_t
+getintmax(void)
+{
+	intmax_t val;
+	char *cp, *ep;
+
+	cp = *gargv;
+	if (cp == NULL)
+		return 0;
+	gargv++;
+
+	if (*cp == '\"' || *cp == '\'')
+		return *(cp+1);
+
+	errno = 0;
+	val = strtoimax(cp, &ep, 0);
+	check_conversion(cp, ep);
+	return val;
+}
+
+static uintmax_t
+getuintmax(void)
+{
+	uintmax_t val;
+	char *cp, *ep;
+
+	cp = *gargv;
+	if (cp == NULL)
+		return 0;
+	gargv++;
+
+	if (*cp == '\"' || *cp == '\'')
+		return *(cp + 1);
+
+	/* strtoumax won't error -ve values */
+	while (isspace(*(unsigned char *)cp))
+		cp++;
+	if (*cp == '-') {
+		warnx("%s: expected positive numeric value", cp);
+		rval = 1;
+		return 0;
+	}
+
+	errno = 0;
+	val = strtoumax(cp, &ep, 0);
+	check_conversion(cp, ep);
+	return val;
+}
+
+static double
+getdouble(void)
+{
+	double val;
+	char *ep;
+
+	if (!*gargv)
+		return (0.0);
+
+	if (**gargv == '\"' || **gargv == '\'')
+		return (double) *((*gargv++)+1);
+
+	errno = 0;
+	val = strtod(*gargv, &ep);
+	check_conversion(*gargv++, ep);
+	return val;
+}
+
+static void
+check_conversion(const char *s, const char *ep)
+{
+	if (*ep) {
+		if (ep == s)
+			warnx("%s: expected numeric value", s);
+		else
+			warnx("%s: not completely converted", s);
+		rval = 1;
+	} else if (errno == ERANGE) {
+		warnx("%s: %s", s, strerror(ERANGE));
+		rval = 1;
+	}
+}
+
+static int
+usage(FILE *pf)
+{
+	fprintf(pf, "usage: %s format [arg ...]\n"
+				"   or: %s --help\n"
+				"   or: %s --version\n",
+			g_progname, g_progname, g_progname);
+	return 1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/redirect.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/redirect.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/redirect.c	(revision 1780)
@@ -0,0 +1,507 @@
+/* $Id$ */
+/** @file
+ * kmk_redirect - Do simple program <-> file redirection (++).
+ */
+
+/*
+ * Copyright (c) 2007-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#if defined(_MSC_VER)
+# include <io.h>
+# include <direct.h>
+# include <process.h>
+#else
+# include <unistd.h>
+#endif
+
+#ifdef __OS2__
+# define INCL_BASE
+# include <os2.h>
+# ifndef LIBPATHSTRICT
+#  define LIBPATHSTRICT 3
+# endif
+#endif
+
+
+static const char *name(const char *pszName)
+{
+    const char *psz = strrchr(pszName, '/');
+#if defined(_MSC_VER) || defined(__OS2__)
+    const char *psz2 = strrchr(pszName, '\\');
+    if (!psz2)
+        psz2 = strrchr(pszName, ':');
+    if (psz2 && (!psz || psz2 > psz))
+        psz = psz2;
+#endif
+    return psz ? psz + 1 : pszName;
+}
+
+
+static int usage(FILE *pOut,  const char *argv0)
+{
+    fprintf(pOut,
+            "usage: %s [-[rwa+tb]<fd> <file>] [-E <var=val>] [-C <dir>] -- <program> [args]\n"
+            "   or: %s --help\n"
+            "   or: %s --version\n"
+            "\n"
+            "The rwa+tb is like for fopen, if not specified it defaults to w+.\n"
+            "The <fd> is either a number or an alias for the standard handles:\n"
+            "   i = stdin\n"
+            "   o = stdout\n"
+            "   e = stderr\n"
+            "\n"
+            "The -E switch is for making changes to the environment in a putenv\n"
+            "fashion.\n"
+            "\n"
+            "The -C switch is for changing the current directory. This takes immediate\n"
+            "effect, so be careful where you put it.\n"
+            "\n"
+            "This command is really just a quick hack to avoid invoking the shell\n"
+            "on Windows (cygwin) where forking is very expensive and has exhibited\n"
+            "stability issues on SMP machines. This tool may be retired when kBuild\n"
+            "starts using the kmk_kash shell.\n"
+            ,
+            argv0, argv0, argv0);
+    return 1;
+}
+
+
+int main(int argc, char **argv)
+{
+    int i;
+#if defined(_MSC_VER)
+    intptr_t rc;
+#endif
+    FILE *pStdErr = stderr;
+    FILE *pStdOut = stdout;
+
+    /*
+     * Parse arguments.
+     */
+    if (argc <= 1)
+        return usage(pStdErr, name(argv[0]));
+    for (i = 1; i < argc; i++)
+    {
+        if (argv[i][0] == '-')
+        {
+            int fd;
+            int fdOpened;
+            int fOpen;
+            char *psz = &argv[i][1];
+            if (*psz == '-')
+            {
+                /* '--' ? */
+                if (!psz[1])
+                {
+                    i++;
+                    break;
+                }
+
+                /* convert to short. */
+                if (!strcmp(psz, "-help"))
+                    psz = "h";
+                else if (!strcmp(psz, "-version"))
+                    psz = "V";
+                else if (!strcmp(psz, "-env"))
+                    psz = "E";
+                else if (!strcmp(psz, "-chdir"))
+                    psz = "C";
+            }
+
+            /*
+             * Deal with the obligatory help and version switches first.
+             */
+            if (*psz == 'h')
+            {
+                usage(pStdOut, name(argv[0]));
+                return 0;
+            }
+            if (*psz == 'V')
+            {
+                printf("kmk_redirect - kBuild version %d.%d.%d (r%u)\n"
+                       "Copyright (C) 2007-2008 Knut St. Osmundsen\n",
+                       KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH,
+                       KBUILD_SVN_REV);
+                return 0;
+            }
+
+            /*
+             * Environment switch?
+             */
+            if (*psz == 'E')
+            {
+                psz++;
+                if (*psz == ':' || *psz == '=')
+                    psz++;
+                else
+                {
+                    if (i + 1 >= argc)
+                    {
+                        fprintf(pStdErr, "%s: syntax error: no argument for %s\n", name(argv[0]), argv[i]);
+                        return 1;
+                    }
+                    psz = argv[++i];
+                }
+#ifdef __OS2__
+                if (    !strncmp(psz, "BEGINLIBPATH=",  sizeof("BEGINLIBPATH=") - 1)
+                    ||  !strncmp(psz, "ENDLIBPATH=",    sizeof("ENDLIBPATH=") - 1)
+                    ||  !strncmp(psz, "LIBPATHSTRICT=", sizeof("LIBPATHSTRICT=") - 1))
+                {
+                    ULONG ulVar = *psz == 'B' ? BEGIN_LIBPATH
+                                : *psz == 'E' ? END_LIBPATH
+                                :               LIBPATHSTRICT;
+                    const char *pszVal = strchr(psz, '=') + 1;
+                    APIRET rc = DosSetExtLIBPATH(pszVal, ulVar);
+                    if (rc)
+                    {
+                        fprintf(pStdErr, "%s: error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu\n",
+                                name(argv[0]), pszVal, pszVal - psz - 1, psz, ulVar, rc);
+                        return 1;
+                    }
+                }
+                else
+#endif /* __OS2__ */
+                if (putenv(psz))
+                {
+                    fprintf(pStdErr, "%s: error: putenv(\"%s\"): %s\n", name(argv[0]), psz, strerror(errno));
+                    return 1;
+                }
+                continue;
+            }
+
+            /*
+             * Change directory switch?
+             */
+            if (*psz == 'C')
+            {
+                psz++;
+                if (*psz == ':' || *psz == '=')
+                    psz++;
+                else
+                {
+                    if (i + 1 >= argc)
+                    {
+                        fprintf(pStdErr, "%s: syntax error: no argument for %s\n", name(argv[0]), argv[i]);
+                        return 1;
+                    }
+                    psz = argv[++i];
+                }
+                if (!chdir(psz))
+                    continue;
+#ifdef _MSC_VER
+                {
+                    /* drop trailing slash if any. */
+                    size_t cch = strlen(psz);
+                    if (    cch > 2
+                        &&  (psz[cch - 1] == '/' || psz[cch - 1] == '\\')
+                        &&  psz[cch - 1] != ':')
+                    {
+                        int rc2;
+                        char *pszCopy = strdup(psz);
+                        do  pszCopy[--cch] = '\0';
+                        while (    cch > 2
+                               &&  (pszCopy[cch - 1] == '/' || pszCopy[cch - 1] == '\\')
+                               &&  pszCopy[cch - 1] != ':');
+                        rc2 = chdir(pszCopy);
+                        free(pszCopy);
+                        if (!rc2)
+                            continue;
+                    }
+                }
+#endif
+                fprintf(pStdErr, "%s: error: chdir(\"%s\"): %s\n", name(argv[0]), psz, strerror(errno));
+                return 1;
+            }
+
+            /*
+             * Parse a file descriptor argument.
+             */
+
+            /* mode */
+            switch (*psz)
+            {
+                case 'r':
+                    psz++;
+                    if (*psz == '+')
+                    {
+                        fOpen = O_RDWR;
+                        psz++;
+                    }
+                    else
+                        fOpen = O_RDONLY;
+                    break;
+
+                case 'w':
+                    psz++;
+                    if (*psz == '+')
+                    {
+                        psz++;
+                        fOpen = O_RDWR | O_CREAT | O_TRUNC;
+                    }
+                    else
+                        fOpen = O_WRONLY | O_CREAT | O_TRUNC;
+                    break;
+
+                case 'a':
+                    psz++;
+                    if (*psz == '+')
+                    {
+                        psz++;
+                        fOpen = O_RDWR | O_CREAT | O_APPEND;
+                    }
+                    else
+                        fOpen = O_WRONLY | O_CREAT | O_APPEND;
+                    break;
+
+                case 'i': /* make sure stdin is read-only. */
+                    fOpen = O_RDONLY;
+                    break;
+
+                case '+':
+                    fprintf(pStdErr, "%s: syntax error: Unexpected '+' in '%s'\n", name(argv[0]), argv[i]);
+                    return 1;
+
+                default:
+                    fOpen = O_RDWR | O_CREAT | O_TRUNC;
+                    break;
+            }
+
+            /* binary / text modifiers */
+            switch (*psz)
+            {
+                case 'b':
+#ifdef O_BINARY
+                    fOpen |= O_BINARY;
+#endif
+                    psz++;
+                    break;
+
+                case 't':
+#ifdef O_TEXT
+                    fOpen |= O_TEXT;
+#endif
+                    psz++;
+                    break;
+
+                default:
+#ifdef O_BINARY
+                    fOpen |= O_BINARY;
+#endif
+                    break;
+
+            }
+
+            /* convert to file descriptor number */
+            switch (*psz)
+            {
+                case 'i':
+                    fd = 0;
+                    psz++;
+                    break;
+
+                case 'o':
+                    fd = 1;
+                    psz++;
+                    break;
+
+                case 'e':
+                    fd = 2;
+                    psz++;
+                    break;
+
+                case '0':
+                    if (!psz[1])
+                    {
+                        fd = 0;
+                        psz++;
+                        break;
+                    }
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                    fd = (int)strtol(psz, &psz, 0);
+                    if (!fd)
+                    {
+                        fprintf(pStdErr, "%s: error: failed to convert '%s' to a number\n", name(argv[0]), argv[i]);
+                        return 1;
+
+                    }
+                    if (fd < 0)
+                    {
+                        fprintf(pStdErr, "%s: error: negative fd %d (%s)\n", name(argv[0]), fd, argv[i]);
+                        return 1;
+                    }
+                    break;
+
+                /*
+                 * Invalid argument.
+                 */
+                default:
+                    fprintf(pStdErr, "%s: error: failed to convert '%s' ('%s') to a file descriptor\n", name(argv[0]), psz, argv[i]);
+                    return 1;
+            }
+
+            /*
+             * Check for the filename.
+             */
+            if (*psz)
+            {
+                if (*psz != ':' && *psz != '=')
+                {
+                    fprintf(pStdErr, "%s: syntax error: characters following the file descriptor: '%s' ('%s')\n", name(argv[0]), psz, argv[i]);
+                    return 1;
+                }
+                psz++;
+            }
+            else
+            {
+                i++;
+                if (i >= argc)
+                {
+                    fprintf(pStdErr, "%s: syntax error: missing filename argument.\n", name(argv[0]));
+                    return 1;
+                }
+                psz = argv[i];
+            }
+
+            /*
+             * Setup the redirection.
+             */
+            if (fd == fileno(pStdErr))
+            {
+                /*
+                 * Move stderr to a new location, making it close on exec.
+                 * If pStdOut has already teamed up with pStdErr, update it too.
+                 */
+                FILE *pNew;
+                fdOpened = dup(fileno(pStdErr));
+                if (fdOpened == -1)
+                {
+                    fprintf(pStdErr, "%s: error: failed to dup stderr (%d): %s\n", name(argv[0]), fileno(pStdErr), strerror(errno));
+                    return 1;
+                }
+#ifdef _MSC_VER
+                /** @todo figure out how to make the handle close-on-exec. We'll simply close it for now.
+                 * SetHandleInformation + set FNOINHERIT in CRT.
+                 */
+#else
+                if (fcntl(fdOpened, F_SETFD, FD_CLOEXEC) == -1)
+                {
+                    fprintf(pStdErr, "%s: error: failed to make stderr (%d) close-on-exec: %s\n", name(argv[0]), fdOpened, strerror(errno));
+                    return 1;
+                }
+#endif
+
+                pNew = fdopen(fdOpened, "w");
+                if (!pNew)
+                {
+                    fprintf(pStdErr, "%s: error: failed to fdopen the new stderr (%d): %s\n", name(argv[0]), fdOpened, strerror(errno));
+                    return 1;
+                }
+                if (pStdOut == pStdErr)
+                    pStdOut = pNew;
+                pStdErr = pNew;
+            }
+            else if (fd == 1 && pStdOut != pStdErr)
+                pStdOut = pStdErr;
+
+            /*
+             * Close and open the new file descriptor.
+             */
+            close(fd);
+#if defined(_MSC_VER)
+            if (!strcmp(psz, "/dev/null"))
+                psz = (char *)"nul";
+#endif
+            fdOpened = open(psz, fOpen, 0666);
+            if (fdOpened == -1)
+            {
+                fprintf(pStdErr, "%s: error: failed to open '%s' as %d: %s\n", name(argv[0]), psz, fd, strerror(errno));
+                return 1;
+            }
+            if (fdOpened != fd)
+            {
+                /* move it (dup2 returns 0 on MSC). */
+                if (dup2(fdOpened, fd) == -1)
+                {
+                    fprintf(pStdErr, "%s: error: failed to dup '%s' as %d: %s\n", name(argv[0]), psz, fd, strerror(errno));
+                    return 1;
+                }
+                close(fdOpened);
+            }
+        }
+        else
+        {
+            fprintf(pStdErr, "%s: syntax error: Invalid argument '%s'.\n", name(argv[0]), argv[i]);
+            return usage(pStdErr, name(argv[0]));
+        }
+    }
+
+    /*
+     * Make sure there's something to execute.
+     */
+    if (i >= argc)
+    {
+        fprintf(pStdErr, "%s: syntax error: nothing to execute!\n", name(argv[0]));
+        return usage(pStdErr, name(argv[0]));
+    }
+
+#if defined(_MSC_VER)
+    if (fileno(pStdErr) != 2) /* no close-on-exec flag on windows */
+    {
+        fclose(pStdErr);
+        pStdErr = NULL;
+    }
+
+    /** @todo
+     * We'll have to find the '--' in the commandline and pass that
+     * on to CreateProcess or spawn. Otherwise, the argument qouting
+     * is gonna be messed up.
+     */
+    rc = _spawnvp(_P_WAIT, argv[i], &argv[i]);
+    if (rc == -1 && pStdErr)
+    {
+        fprintf(pStdErr, "%s: error: _spawnvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno));
+        rc = 1;
+    }
+    return rc;
+#else
+    execvp(argv[i], &argv[i]);
+    fprintf(pStdErr, "%s: error: _execvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno));
+    return 1;
+#endif
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/rm.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/rm.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/rm.c	(revision 1780)
@@ -0,0 +1,731 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1990, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rm.c	8.5 (Berkeley) 4/18/94";
+#endif /* not lint */
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.47 2004/04/06 20:06:50 markm Exp $");
+#endif
+
+#include <sys/stat.h>
+#ifndef _MSC_VER
+# include <sys/param.h>
+# include <sys/mount.h>
+#endif
+
+#include "err.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "getopt.h"
+#ifdef _MSC_VER
+# include "mscfakes.h"
+#endif
+#if defined(__OS2__) || defined(_MSC_VER)
+# include <direct.h>
+# include <limits.h>
+#endif
+#include "kmkbuiltin.h"
+#include "kbuild_protection.h"
+
+#if defined(__EMX__) || defined(_MSC_VER)
+# define IS_SLASH(ch)   ( (ch) == '/' || (ch) == '\\' )
+# define HAVE_DOS_PATHS 1
+# define DEFAULT_PROTECTION_DEPTH 1
+#else
+# define IS_SLASH(ch)   ( (ch) == '/' )
+# undef HAVE_DOS_PATHS
+# define DEFAULT_PROTECTION_DEPTH 2
+#endif
+
+#ifdef __EMX__
+#undef S_IFWHT
+#undef S_ISWHT
+#endif
+#ifndef S_IFWHT
+#define S_IFWHT 0
+#define S_ISWHT(s) 0
+#define undelete(s) (-1)
+#endif
+
+extern void bsd_strmode(mode_t mode, char *p);
+
+static int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
+static uid_t uid;
+
+static char *argv0;
+static KBUILDPROTECTION g_ProtData;
+
+static struct option long_options[] =
+{
+    { "help",   					no_argument, 0, 261 },
+    { "version",   					no_argument, 0, 262 },
+    { "disable-protection",				no_argument, 0, 263 },
+    { "enable-protection",				no_argument, 0, 264 },
+    { "enable-full-protection",				no_argument, 0, 265 },
+    { "disable-full-protection",			no_argument, 0, 266 },
+    { "protection-depth",				required_argument, 0, 267 },
+    { 0, 0,	0, 0 },
+};
+
+
+static int	check(char *, char *, struct stat *);
+static void	checkdot(char **);
+static int	rm_file(char **);
+static int	rm_overwrite(char *, struct stat *);
+static int	rm_tree(char **);
+static int	count_path_components(const char *);
+static int	usage(FILE *);
+
+
+
+/*
+ * rm --
+ *	This rm is different from historic rm's, but is expected to match
+ *	POSIX 1003.2 behavior.  The most visible difference is that -f
+ *	has two specific effects now, ignore non-existent files and force
+ * 	file removal.
+ */
+int
+kmk_builtin_rm(int argc, char *argv[], char **envp)
+{
+	int ch, rflag;
+
+	/* reinitialize globals */
+	argv0 = argv[0];
+	dflag = eval = fflag = iflag = Pflag = vflag = Wflag = stdin_ok = 0;
+	uid = 0;
+	kBuildProtectionInit(&g_ProtData);
+
+	/* kmk: reset getopt and set program name. */
+	g_progname = argv[0];
+	opterr = 1;
+	optarg = NULL;
+	optopt = 0;
+	optind = 0; /* init */
+
+	Pflag = rflag = 0;
+	while ((ch = getopt_long(argc, argv, "dfiPRvW", long_options, NULL)) != -1)
+		switch(ch) {
+		case 'd':
+			dflag = 1;
+			break;
+		case 'f':
+			fflag = 1;
+			iflag = 0;
+			break;
+		case 'i':
+			fflag = 0;
+			iflag = 1;
+			break;
+		case 'P':
+			Pflag = 1;
+			break;
+		case 'R':
+#if 0
+		case 'r':			/* Compatibility. */
+#endif
+			rflag = 1;
+			break;
+		case 'v':
+			vflag = 1;
+			break;
+#ifdef FTS_WHITEOUT
+		case 'W':
+			Wflag = 1;
+			break;
+#endif
+		case 261:
+			kBuildProtectionTerm(&g_ProtData);
+			usage(stdout);
+			return 0;
+		case 262:
+			kBuildProtectionTerm(&g_ProtData);
+			return kbuild_version(argv[0]);
+		case 263:
+			kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
+			break;
+		case 264:
+			kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
+			break;
+		case 265:
+			kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
+			break;
+		case 266:
+			kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
+			break;
+		case 267:
+			if (kBuildProtectionSetDepth(&g_ProtData, optarg)) {
+			    kBuildProtectionTerm(&g_ProtData);
+			    return 1;
+			}
+			break;
+		case '?':
+		default:
+			kBuildProtectionTerm(&g_ProtData);
+			return usage(stderr);
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1) {
+		kBuildProtectionTerm(&g_ProtData);
+		if (fflag)
+			return (0);
+		return usage(stderr);
+	}
+
+	if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_RM_")) {
+		checkdot(argv);
+		uid = geteuid();
+
+		if (*argv) {
+			stdin_ok = isatty(STDIN_FILENO);
+			if (rflag)
+				eval |= rm_tree(argv);
+			else
+				eval |= rm_file(argv);
+		}
+	} else {
+		eval = 1;
+	}
+
+	kBuildProtectionTerm(&g_ProtData);
+	return eval;
+}
+
+static int
+rm_tree(char **argv)
+{
+	FTS *fts;
+	FTSENT *p;
+	int needstat;
+	int flags;
+	int rval;
+
+	/*
+	 * Check up front before anything is deleted. This will not catch
+	 * everything, but we'll check the individual items later.
+	 */
+	int i;
+	for (i = 0; argv[i]; i++) {
+		if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) {
+			return 1;
+		}
+	}
+
+	/*
+	 * Remove a file hierarchy.  If forcing removal (-f), or interactive
+	 * (-i) or can't ask anyway (stdin_ok), don't stat the file.
+	 */
+	needstat = !uid || (!fflag && !iflag && stdin_ok);
+
+	/*
+	 * If the -i option is specified, the user can skip on the pre-order
+	 * visit.  The fts_number field flags skipped directories.
+	 */
+#define	SKIPPED	1
+
+	flags = FTS_PHYSICAL;
+	if (!needstat)
+		flags |= FTS_NOSTAT;
+#ifdef FTS_WHITEOUT
+	if (Wflag)
+		flags |= FTS_WHITEOUT;
+#endif
+	if (!(fts = fts_open(argv, flags, NULL))) {
+		return err(1, "fts_open");
+	}
+	while ((p = fts_read(fts)) != NULL) {
+		switch (p->fts_info) {
+		case FTS_DNR:
+			if (!fflag || p->fts_errno != ENOENT) {
+				fprintf(stderr, "%s: %s: %s\n",
+				        argv0, p->fts_path, strerror(p->fts_errno));
+				eval = 1;
+			}
+			continue;
+		case FTS_ERR:
+			fts_close(fts);
+			return errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
+		case FTS_NS:
+			/*
+			 * Assume that since fts_read() couldn't stat the
+			 * file, it can't be unlinked.
+			 */
+			if (!needstat)
+				break;
+			if (!fflag || p->fts_errno != ENOENT) {
+				fprintf(stderr, "%s: %s: %s\n",
+				        argv0, p->fts_path, strerror(p->fts_errno));
+				eval = 1;
+			}
+			continue;
+		case FTS_D:
+			/* Pre-order: give user chance to skip. */
+			if (!fflag && !check(p->fts_path, p->fts_accpath,
+			    p->fts_statp)) {
+				(void)fts_set(fts, p, FTS_SKIP);
+				p->fts_number = SKIPPED;
+			}
+#ifdef UF_APPEND
+			else if (!uid &&
+				 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+				 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+				 chflags(p->fts_accpath,
+					 p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
+				goto err;
+#endif
+			continue;
+		case FTS_DP:
+			/* Post-order: see if user skipped. */
+			if (p->fts_number == SKIPPED)
+				continue;
+			break;
+		default:
+			if (!fflag &&
+			    !check(p->fts_path, p->fts_accpath, p->fts_statp))
+				continue;
+		}
+
+		/*
+		 * Protect against deleting root files and directories.
+		 */
+		if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) {
+			fts_close(fts);
+			return 1;
+		}
+
+		rval = 0;
+#ifdef UF_APPEND
+		if (!uid &&
+		    (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+		    !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
+			rval = chflags(p->fts_accpath,
+				       p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
+#endif
+		if (rval == 0) {
+			/*
+			 * If we can't read or search the directory, may still be
+			 * able to remove it.  Don't print out the un{read,search}able
+			 * message unless the remove fails.
+			 */
+			switch (p->fts_info) {
+			case FTS_DP:
+			case FTS_DNR:
+				rval = rmdir(p->fts_accpath);
+				if (rval == 0 || (fflag && errno == ENOENT)) {
+					if (rval == 0 && vflag)
+						(void)printf("%s\n",
+						    p->fts_path);
+					continue;
+				}
+				break;
+
+#ifdef FTS_W
+			case FTS_W:
+				rval = undelete(p->fts_accpath);
+				if (rval == 0 && (fflag && errno == ENOENT)) {
+					if (vflag)
+						(void)printf("%s\n",
+						    p->fts_path);
+					continue;
+				}
+				break;
+#endif
+
+			case FTS_NS:
+				/*
+				 * Assume that since fts_read() couldn't stat
+				 * the file, it can't be unlinked.
+				 */
+				if (fflag)
+					continue;
+				/* FALLTHROUGH */
+			default:
+				if (Pflag)
+					if (!rm_overwrite(p->fts_accpath, NULL))
+						continue;
+				rval = unlink(p->fts_accpath);
+#ifdef _MSC_VER
+				if (rval != 0) {
+    					chmod(p->fts_accpath, 0777);
+					rval = unlink(p->fts_accpath);
+				}
+#endif
+
+				if (rval == 0 || (fflag && errno == ENOENT)) {
+					if (rval == 0 && vflag)
+						(void)printf("%s\n",
+						    p->fts_path);
+					continue;
+				}
+			}
+		}
+#ifdef UF_APPEND
+err:
+#endif
+		fprintf(stderr, "%s: %s: %s\n", argv0, p->fts_path, strerror(errno));
+		eval = 1;
+	}
+	if (errno) {
+		fprintf(stderr, "%s: fts_read: %s\n", argv0, strerror(errno));
+		eval = 1;
+	}
+	fts_close(fts);
+	return eval;
+}
+
+static int
+rm_file(char **argv)
+{
+	struct stat sb;
+	int rval;
+	char *f;
+
+	/*
+	 * Check up front before anything is deleted.
+	 */
+	int i;
+	for (i = 0; argv[i]; i++) {
+		if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_FULL, argv[i]))
+			return 1;
+	}
+
+	/*
+	 * Remove a file.  POSIX 1003.2 states that, by default, attempting
+	 * to remove a directory is an error, so must always stat the file.
+	 */
+	while ((f = *argv++) != NULL) {
+		/* Assume if can't stat the file, can't unlink it. */
+		if (lstat(f, &sb)) {
+#ifdef FTS_WHITEOUT
+			if (Wflag) {
+				sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
+			} else {
+#else
+			{
+#endif
+				if (!fflag || errno != ENOENT) {
+					fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(errno));
+					eval = 1;
+				}
+				continue;
+			}
+#ifdef FTS_WHITEOUT
+		} else if (Wflag) {
+			fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(EEXIST));
+			eval = 1;
+			continue;
+#endif
+		}
+
+		if (S_ISDIR(sb.st_mode) && !dflag) {
+			fprintf(stderr, "%s: %s: is a directory\n", argv0, f);
+			eval = 1;
+			continue;
+		}
+		if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
+			continue;
+		rval = 0;
+#ifdef UF_APPEND
+		if (!uid &&
+		    (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+		    !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
+			rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
+#endif
+		if (rval == 0) {
+			if (S_ISWHT(sb.st_mode))
+				rval = undelete(f);
+			else if (S_ISDIR(sb.st_mode))
+				rval = rmdir(f);
+			else {
+				if (Pflag)
+					if (!rm_overwrite(f, &sb))
+						continue;
+				rval = unlink(f);
+#ifdef _MSC_VER
+				if (rval != 0) {
+					chmod(f, 0777);
+					rval = unlink(f);
+				}
+#endif
+			}
+		}
+		if (rval && (!fflag || errno != ENOENT)) {
+			fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(errno));
+			eval = 1;
+		}
+		if (vflag && rval == 0)
+			(void)printf("%s\n", f);
+	}
+	return eval;
+}
+
+/*
+ * rm_overwrite --
+ *	Overwrite the file 3 times with varying bit patterns.
+ *
+ * XXX
+ * This is a cheap way to *really* delete files.  Note that only regular
+ * files are deleted, directories (and therefore names) will remain.
+ * Also, this assumes a fixed-block file system (like FFS, or a V7 or a
+ * System V file system).  In a logging file system, you'll have to have
+ * kernel support.
+ */
+static int
+rm_overwrite(char *file, struct stat *sbp)
+{
+	struct stat sb;
+#ifdef HAVE_FSTATFS
+	struct statfs fsb;
+#endif
+	off_t len;
+	int bsize, fd, wlen;
+	char *buf = NULL;
+
+	fd = -1;
+	if (sbp == NULL) {
+		if (lstat(file, &sb))
+			goto err;
+		sbp = &sb;
+	}
+	if (!S_ISREG(sbp->st_mode))
+		return (1);
+	if ((fd = open(file, O_WRONLY, 0)) == -1)
+		goto err;
+#ifdef HAVE_FSTATFS
+	if (fstatfs(fd, &fsb) == -1)
+		goto err;
+	bsize = MAX(fsb.f_iosize, 1024);
+#elif defined(HAVE_ST_BLKSIZE)
+	bsize = MAX(sb.st_blksize, 1024);
+#else
+	bsize = 1024;
+#endif
+	if ((buf = malloc(bsize)) == NULL)
+		exit(err(1, "%s: malloc", file));
+
+#define	PASS(byte) {							\
+	memset(buf, byte, bsize);					\
+	for (len = sbp->st_size; len > 0; len -= wlen) {		\
+		wlen = len < bsize ? len : bsize;			\
+		if (write(fd, buf, wlen) != wlen)			\
+			goto err;					\
+	}								\
+}
+	PASS(0xff);
+	if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
+		goto err;
+	PASS(0x00);
+	if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
+		goto err;
+	PASS(0xff);
+	if (!fsync(fd) && !close(fd)) {
+		free(buf);
+		return (1);
+	}
+
+err:	eval = 1;
+	if (buf)
+		free(buf);
+	if (fd != -1)
+		close(fd);
+	fprintf(stderr, "%s: %s: %s\n", argv0, file, strerror(errno));
+	return (0);
+}
+
+
+static int
+check(char *path, char *name, struct stat *sp)
+{
+	int ch, first;
+	char modep[15], *flagsp;
+
+	/* Check -i first. */
+	if (iflag)
+		(void)fprintf(stderr, "remove %s? ", path);
+	else {
+		/*
+		 * If it's not a symbolic link and it's unwritable and we're
+		 * talking to a terminal, ask.  Symbolic links are excluded
+		 * because their permissions are meaningless.  Check stdin_ok
+		 * first because we may not have stat'ed the file.
+		 * Also skip this check if the -P option was specified because
+		 * we will not be able to overwrite file contents and will
+		 * barf later.
+		 */
+		if (!stdin_ok || S_ISLNK(sp->st_mode) || Pflag ||
+		    (!access(name, W_OK) &&
+#ifdef SF_APPEND
+		    !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+		    (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid))
+#else
+                    1)
+#endif
+                    )
+			return (1);
+		bsd_strmode(sp->st_mode, modep);
+#ifdef SF_APPEND
+		if ((flagsp = fflagstostr(sp->st_flags)) == NULL)
+			exit(err(1, "fflagstostr"));
+		(void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
+		              modep + 1, modep[9] == ' ' ? "" : " ",
+		              user_from_uid(sp->st_uid, 0),
+		              group_from_gid(sp->st_gid, 0),
+		              *flagsp ? flagsp : "", *flagsp ? " " : "",
+		              path);
+		free(flagsp);
+#else
+		(void)flagsp;
+		(void)fprintf(stderr, "override %s%s %d/%d for %s? ",
+		              modep + 1, modep[9] == ' ' ? "" : " ",
+		              sp->st_uid, sp->st_gid, path);
+#endif
+	}
+	(void)fflush(stderr);
+
+	first = ch = getchar();
+	while (ch != '\n' && ch != EOF)
+		ch = getchar();
+	return (first == 'y' || first == 'Y');
+}
+
+#define ISDOT(a)	((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
+static void
+checkdot(char **argv)
+{
+	char *p, **save, **t;
+	int complained;
+
+	complained = 0;
+	for (t = argv; *t;) {
+#ifdef HAVE_DOS_PATHS
+		const char *tmp = p = *t;
+		while (*tmp) {
+			switch (*tmp) {
+			case '/':
+			case '\\':
+			case ':':
+				p = (char *)tmp + 1;
+				break;
+			}
+			tmp++;
+		}
+#else
+		if ((p = strrchr(*t, '/')) != NULL)
+			++p;
+		else
+			p = *t;
+#endif
+		if (ISDOT(p)) {
+			if (!complained++)
+				fprintf(stderr, "%s: \".\" and \"..\" may not be removed\n", argv0);
+			eval = 1;
+			for (save = t; (t[0] = t[1]) != NULL; ++t)
+				continue;
+			t = save;
+		} else
+			++t;
+	}
+}
+
+static int
+usage(FILE *pf)
+{
+	fprintf(pf,
+		"usage: %s [options] file ...\n"
+		"   or: %s --help\n"
+		"   or: %s --version\n"
+		"\n"
+		"Options:\n"
+		"   -f\n"
+		"       Attempt to remove files without prompting, regardless of the file\n"
+		"       permission. Ignore non-existing files. Overrides previous -i's.\n"
+		"   -i\n"
+		"       Prompt for each file. Always.\n"
+		"   -d\n"
+		"       Attempt to remove directories as well as other kinds of files.\n"
+		"   -P\n"
+		"       Overwrite regular files before deleting; three passes: ff,0,ff\n"
+		"   -R\n"
+		"       Attempt to remove the file hierachy rooted in each file argument.\n"
+		"       This option implies -d and file protection.\n"
+		"   -v\n"
+		"       Be verbose, show files as they are removed.\n"
+		"   -W\n"
+		"       Undelete without files.\n"
+		"   --disable-protection\n"
+		"       Will disable the protection file protection applied with -R.\n"
+		"   --enable-protection\n"
+		"       Will enable the protection file protection applied with -R.\n"
+		"   --enable-full-protection\n"
+		"       Will enable the protection file protection for all operations.\n"
+		"   --disable-full-protection\n"
+		"       Will disable the protection file protection for all operations.\n"
+		"   --protection-depth\n"
+		"       Number or path indicating the file protection depth. Default: %d\n"
+		"\n"
+		"Environment:\n"
+		"    KMK_RM_DISABLE_PROTECTION\n"
+		"       Same as --disable-protection. Overrides command line.\n"
+		"    KMK_RM_ENABLE_PROTECTION\n"
+		"       Same as --enable-protection. Overrides everyone else.\n"
+		"    KMK_RM_ENABLE_FULL_PROTECTION\n"
+		"       Same as --enable-full-protection. Overrides everyone else.\n"
+		"    KMK_RM_DISABLE_FULL_PROTECTION\n"
+		"       Same as --disable-full-protection. Overrides command line.\n"
+		"    KMK_RM_PROTECTION_DEPTH\n"
+		"       Same as --protection-depth. Overrides command line.\n"
+		"\n"
+		"The file protection of the top %d layers of the file hierarchy is there\n"
+		"to try prevent makefiles from doing bad things to your system. This\n"
+		"protection is not bulletproof, but should help prevent you from shooting\n"
+		"yourself in the foot.\n"
+		,
+		g_progname, g_progname, g_progname,
+		kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth());
+	return EX_USAGE;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/rmdir.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/rmdir.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/rmdir.c	(revision 1780)
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rmdir.c	8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+#endif
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/rmdir/rmdir.c,v 1.20 2005/01/26 06:51:28 ssouhlal Exp $");
+#endif
+
+#include "err.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include "getopt.h"
+#include "kmkbuiltin.h"
+
+#ifdef _MSC_VER
+# include "mscfakes.h"
+#endif
+
+static int rm_path(char *);
+static int usage(FILE *);
+
+static int pflag;
+static int vflag;
+static int ignore_fail_on_non_empty;
+static int ignore_fail_on_not_exist;
+
+static struct option long_options[] =
+{
+    { "help",                       no_argument, 0, 262 },
+    { "ignore-fail-on-non-empty",   no_argument, 0, 260 },
+    { "ignore-fail-on-not-exist",   no_argument, 0, 261 },
+    { "parents",                    no_argument, 0, 'p' },
+    { "verbose",                    no_argument, 0, 'v' },
+    { "version",                    no_argument, 0, 263 },
+    { 0, 0,	0, 0 },
+};
+
+
+int
+kmk_builtin_rmdir(int argc, char *argv[], char **envp)
+{
+	int ch, errors;
+
+	/* reinitialize globals */
+	ignore_fail_on_not_exist = ignore_fail_on_non_empty = vflag = pflag = 0;
+
+	/* kmk: reset getopt and set progname */
+	g_progname = argv[0];
+	opterr = 1;
+	optarg = NULL;
+	optopt = 0;
+	optind = 0; /* init */
+	while ((ch = getopt_long(argc, argv, "pv", long_options, NULL)) != -1)
+		switch(ch) {
+		case 'p':
+			pflag = 1;
+			break;
+		case 'v':
+			vflag = 1;
+			break;
+		case 260:
+			ignore_fail_on_non_empty = 1;
+			break;
+		case 261:
+			ignore_fail_on_not_exist = 1;
+			break;
+		case 262:
+			usage(stdout);
+			return 0;
+		case 263:
+			return kbuild_version(argv[0]);
+		case '?':
+		default:
+			return usage(stderr);
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc == 0)
+		return /*usage(stderr)*/0;
+
+	for (errors = 0; *argv; argv++) {
+		if (rmdir(*argv) < 0) {
+			if (	(!ignore_fail_on_non_empty || (errno != ENOTEMPTY && errno != EPERM && errno != EACCES && errno != EINVAL && errno != EEXIST))
+			    &&	(!ignore_fail_on_not_exist || errno != ENOENT)) {
+				warn("%s", *argv);
+				errors = 1;
+				continue;
+			}
+			if (!ignore_fail_on_not_exist || errno != ENOENT)
+				continue;
+			/* (only ignored doesn't exist errors fall thru) */
+		} else if (vflag) {
+			printf("%s\n", *argv);
+		}
+		if (pflag)
+			errors |= rm_path(*argv);
+	}
+
+	return errors;
+}
+
+static int
+rm_path(char *path)
+{
+	char *p;
+	const size_t len = strlen(path);
+	p = alloca(len + 1);
+	path = memcpy(p, path, len + 1);
+
+#if defined(_MSC_VER) || defined(__EMX__)
+	p = strchr(path, '\\');
+	while (p) {
+		*p++ = '/';
+		p = strchr(p, '\\');
+	}
+#endif
+
+	p = path + len;
+	while (--p > path && *p == '/')
+		;
+	*++p = '\0';
+	while ((p = strrchr(path, '/')) != NULL) {
+		/* Delete trailing slashes. */
+		while (--p >= path && *p == '/')
+			;
+		*++p = '\0';
+		if (p == path)
+			break;
+#if defined(_MSC_VER) || defined(__EMX__)
+		if (p[-1] == ':' && p - 2 == path)
+			break;
+#endif
+
+		if (rmdir(path) < 0) {
+			if (ignore_fail_on_non_empty && (errno == ENOTEMPTY || errno == EPERM || errno == EACCES || errno == EINVAL || errno == EEXIST))
+				break;
+			if (!ignore_fail_on_not_exist || errno != ENOENT) {
+				warn("%s", path);
+				return (1);
+			}
+		}
+		if (vflag)
+			printf("%s\n", path);
+	}
+
+	return (0);
+}
+
+static int
+usage(FILE *pf)
+{
+	(void)fprintf(pf, "usage: %s [-pv --ignore-fail-on-non-empty --ignore-fail-on-not-exist] directory ...\n"
+	                  "   or: %s --help\n"
+	                  "   or: %s --version\n",
+	              g_progname, g_progname, g_progname);
+	return 1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/setmode.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/setmode.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/setmode.c	(revision 1780)
@@ -0,0 +1,501 @@
+/*	$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Dave Borman at Cray Research, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>*/
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)setmode.c	8.2 (Berkeley) 3/25/94";
+#else
+__RCSID("$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*#include "namespace.h"*/
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#else
+#include "mscfakes.h"
+#endif
+
+#ifdef SETMODE_DEBUG
+#include <stdio.h>
+#endif
+
+/*#ifdef __weak_alias
+__weak_alias(getmode,_getmode)
+__weak_alias(setmode,_setmode)
+#endif*/
+
+#define	SET_LEN	6		/* initial # of bitcmd struct to malloc */
+#define	SET_LEN_INCR 4		/* # of bitcmd structs to add as needed */
+
+typedef struct bitcmd {
+	char	cmd;
+	char	cmd2;
+	mode_t	bits;
+} BITCMD;
+
+#define	CMD2_CLR	0x01
+#define	CMD2_SET	0x02
+#define	CMD2_GBITS	0x04
+#define	CMD2_OBITS	0x08
+#define	CMD2_UBITS	0x10
+
+static BITCMD	*addcmd(BITCMD *, int, int, int, u_int);
+static void	 compress_mode(BITCMD *);
+#ifdef SETMODE_DEBUG
+static void	 dumpmode(BITCMD *);
+#endif
+
+#ifndef _DIAGASSERT
+# define _DIAGASSERT assert
+#endif
+
+#ifndef S_ISTXT
+# ifdef S_ISVTX
+#  define S_ISTXT S_ISVTX
+# else
+#  define S_ISTXT 0
+# endif
+#endif /* !S_ISTXT */
+
+/*
+ * Given the old mode and an array of bitcmd structures, apply the operations
+ * described in the bitcmd structures to the old mode, and return the new mode.
+ * Note that there is no '=' command; a strict assignment is just a '-' (clear
+ * bits) followed by a '+' (set bits).
+ */
+mode_t
+bsd_getmode(bbox, omode)
+	const void *bbox;
+	mode_t omode;
+{
+	const BITCMD *set;
+	mode_t clrval, newmode, value;
+
+	_DIAGASSERT(bbox != NULL);
+
+	set = (const BITCMD *)bbox;
+	newmode = omode;
+	for (value = 0;; set++)
+		switch(set->cmd) {
+		/*
+		 * When copying the user, group or other bits around, we "know"
+		 * where the bits are in the mode so that we can do shifts to
+		 * copy them around.  If we don't use shifts, it gets real
+		 * grundgy with lots of single bit checks and bit sets.
+		 */
+		case 'u':
+			value = (newmode & S_IRWXU) >> 6;
+			goto common;
+
+		case 'g':
+			value = (newmode & S_IRWXG) >> 3;
+			goto common;
+
+		case 'o':
+			value = newmode & S_IRWXO;
+common:			if (set->cmd2 & CMD2_CLR) {
+				clrval =
+				    (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
+				if (set->cmd2 & CMD2_UBITS)
+					newmode &= ~((clrval<<6) & set->bits);
+				if (set->cmd2 & CMD2_GBITS)
+					newmode &= ~((clrval<<3) & set->bits);
+				if (set->cmd2 & CMD2_OBITS)
+					newmode &= ~(clrval & set->bits);
+			}
+			if (set->cmd2 & CMD2_SET) {
+				if (set->cmd2 & CMD2_UBITS)
+					newmode |= (value<<6) & set->bits;
+				if (set->cmd2 & CMD2_GBITS)
+					newmode |= (value<<3) & set->bits;
+				if (set->cmd2 & CMD2_OBITS)
+					newmode |= value & set->bits;
+			}
+			break;
+
+		case '+':
+			newmode |= set->bits;
+			break;
+
+		case '-':
+			newmode &= ~set->bits;
+			break;
+
+		case 'X':
+			if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
+				newmode |= set->bits;
+			break;
+
+		case '\0':
+		default:
+#ifdef SETMODE_DEBUG
+			(void)printf("getmode:%04o -> %04o\n", omode, newmode);
+#endif
+			return (newmode);
+		}
+}
+
+#define	ADDCMD(a, b, c, d) do {						\
+	if (set >= endset) {						\
+		BITCMD *newset;						\
+		setlen += SET_LEN_INCR;					\
+		newset = realloc(saveset, sizeof(BITCMD) * setlen);	\
+		if (newset == NULL) {					\
+			free(saveset);					\
+			return (NULL);					\
+		}							\
+		set = newset + (set - saveset);				\
+		saveset = newset;					\
+		endset = newset + (setlen - 2);				\
+	}								\
+	set = addcmd(set, (a), (b), (c), (d));				\
+} while (/*CONSTCOND*/0)
+
+#define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+
+void *
+bsd_setmode(p)
+	const char *p;
+{
+	int perm, who;
+	char op, *ep;
+	BITCMD *set, *saveset, *endset;
+#ifndef _MSC_VER
+	sigset_t signset, sigoset;
+#endif
+	mode_t mask;
+	int equalopdone = 0;	/* pacify gcc */
+	int permXbits, setlen;
+
+	if (!*p)
+		return (NULL);
+
+	/*
+	 * Get a copy of the mask for the permissions that are mask relative.
+	 * Flip the bits, we want what's not set.  Since it's possible that
+	 * the caller is opening files inside a signal handler, protect them
+	 * as best we can.
+	 */
+#ifndef _MSC_VER
+	sigfillset(&signset);
+	(void)sigprocmask(SIG_BLOCK, &signset, &sigoset);
+#endif
+	(void)umask(mask = umask(0));
+	mask = ~mask;
+#ifndef _MSC_VER
+	(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
+#endif
+
+	setlen = SET_LEN + 2;
+
+	if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
+		return (NULL);
+	saveset = set;
+	endset = set + (setlen - 2);
+
+	/*
+	 * If an absolute number, get it and return; disallow non-octal digits
+	 * or illegal bits.
+	 */
+	if (isdigit((unsigned char)*p)) {
+		perm = (mode_t)strtol(p, &ep, 8);
+		if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
+			free(saveset);
+			return (NULL);
+		}
+		ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
+		set->cmd = 0;
+		return (saveset);
+	}
+
+	/*
+	 * Build list of structures to set/clear/copy bits as described by
+	 * each clause of the symbolic mode.
+	 */
+	for (;;) {
+		/* First, find out which bits might be modified. */
+		for (who = 0;; ++p) {
+			switch (*p) {
+			case 'a':
+				who |= STANDARD_BITS;
+				break;
+			case 'u':
+				who |= S_ISUID|S_IRWXU;
+				break;
+			case 'g':
+				who |= S_ISGID|S_IRWXG;
+				break;
+			case 'o':
+				who |= S_IRWXO;
+				break;
+			default:
+				goto getop;
+			}
+		}
+
+getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
+			free(saveset);
+			return (NULL);
+		}
+		if (op == '=')
+			equalopdone = 0;
+
+		who &= ~S_ISTXT;
+		for (perm = 0, permXbits = 0;; ++p) {
+			switch (*p) {
+			case 'r':
+				perm |= S_IRUSR|S_IRGRP|S_IROTH;
+				break;
+			case 's':
+				/*
+				 * If specific bits where requested and
+				 * only "other" bits ignore set-id.
+				 */
+				if (who == 0 || (who & ~S_IRWXO))
+					perm |= S_ISUID|S_ISGID;
+				break;
+			case 't':
+				/*
+				 * If specific bits where requested and
+				 * only "other" bits ignore set-id.
+				 */
+				if (who == 0 || (who & ~S_IRWXO)) {
+					who |= S_ISTXT;
+					perm |= S_ISTXT;
+				}
+				break;
+			case 'w':
+				perm |= S_IWUSR|S_IWGRP|S_IWOTH;
+				break;
+			case 'X':
+				permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
+				break;
+			case 'x':
+				perm |= S_IXUSR|S_IXGRP|S_IXOTH;
+				break;
+			case 'u':
+			case 'g':
+			case 'o':
+				/*
+				 * When ever we hit 'u', 'g', or 'o', we have
+				 * to flush out any partial mode that we have,
+				 * and then do the copying of the mode bits.
+				 */
+				if (perm) {
+					ADDCMD(op, who, perm, mask);
+					perm = 0;
+				}
+				if (op == '=')
+					equalopdone = 1;
+				if (op == '+' && permXbits) {
+					ADDCMD('X', who, permXbits, mask);
+					permXbits = 0;
+				}
+				ADDCMD(*p, who, op, mask);
+				break;
+
+			default:
+				/*
+				 * Add any permissions that we haven't already
+				 * done.
+				 */
+				if (perm || (op == '=' && !equalopdone)) {
+					if (op == '=')
+						equalopdone = 1;
+					ADDCMD(op, who, perm, mask);
+					perm = 0;
+				}
+				if (permXbits) {
+					ADDCMD('X', who, permXbits, mask);
+					permXbits = 0;
+				}
+				goto apply;
+			}
+		}
+
+apply:		if (!*p)
+			break;
+		if (*p != ',')
+			goto getop;
+		++p;
+	}
+	set->cmd = 0;
+#ifdef SETMODE_DEBUG
+	(void)printf("Before compress_mode()\n");
+	dumpmode(saveset);
+#endif
+	compress_mode(saveset);
+#ifdef SETMODE_DEBUG
+	(void)printf("After compress_mode()\n");
+	dumpmode(saveset);
+#endif
+	return (saveset);
+}
+
+static BITCMD *
+addcmd(set, op, who, oparg, mask)
+	BITCMD *set;
+	int oparg, who;
+	int op;
+	u_int mask;
+{
+
+	_DIAGASSERT(set != NULL);
+
+	switch (op) {
+	case '=':
+		set->cmd = '-';
+		set->bits = who ? who : STANDARD_BITS;
+		set++;
+
+		op = '+';
+		/* FALLTHROUGH */
+	case '+':
+	case '-':
+	case 'X':
+		set->cmd = op;
+		set->bits = (who ? who : mask) & oparg;
+		break;
+
+	case 'u':
+	case 'g':
+	case 'o':
+		set->cmd = op;
+		if (who) {
+			set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
+				    ((who & S_IRGRP) ? CMD2_GBITS : 0) |
+				    ((who & S_IROTH) ? CMD2_OBITS : 0);
+			set->bits = (mode_t)~0;
+		} else {
+			set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
+			set->bits = mask;
+		}
+
+		if (oparg == '+')
+			set->cmd2 |= CMD2_SET;
+		else if (oparg == '-')
+			set->cmd2 |= CMD2_CLR;
+		else if (oparg == '=')
+			set->cmd2 |= CMD2_SET|CMD2_CLR;
+		break;
+	}
+	return (set + 1);
+}
+
+#ifdef SETMODE_DEBUG
+static void
+dumpmode(set)
+	BITCMD *set;
+{
+
+	_DIAGASSERT(set != NULL);
+
+	for (; set->cmd; ++set)
+		(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
+		    set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
+		    set->cmd2 & CMD2_CLR ? " CLR" : "",
+		    set->cmd2 & CMD2_SET ? " SET" : "",
+		    set->cmd2 & CMD2_UBITS ? " UBITS" : "",
+		    set->cmd2 & CMD2_GBITS ? " GBITS" : "",
+		    set->cmd2 & CMD2_OBITS ? " OBITS" : "");
+}
+#endif
+
+/*
+ * Given an array of bitcmd structures, compress by compacting consecutive
+ * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
+ * 'g' and 'o' commands continue to be separate.  They could probably be
+ * compacted, but it's not worth the effort.
+ */
+static void
+compress_mode(set)
+	BITCMD *set;
+{
+	BITCMD *nset;
+	int setbits, clrbits, Xbits, op;
+
+	_DIAGASSERT(set != NULL);
+
+	for (nset = set;;) {
+		/* Copy over any 'u', 'g' and 'o' commands. */
+		while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
+			*set++ = *nset++;
+			if (!op)
+				return;
+		}
+
+		for (setbits = clrbits = Xbits = 0;; nset++) {
+			if ((op = nset->cmd) == '-') {
+				clrbits |= nset->bits;
+				setbits &= ~nset->bits;
+				Xbits &= ~nset->bits;
+			} else if (op == '+') {
+				setbits |= nset->bits;
+				clrbits &= ~nset->bits;
+				Xbits &= ~nset->bits;
+			} else if (op == 'X')
+				Xbits |= nset->bits & ~setbits;
+			else
+				break;
+		}
+		if (clrbits) {
+			set->cmd = '-';
+			set->cmd2 = 0;
+			set->bits = clrbits;
+			set++;
+		}
+		if (setbits) {
+			set->cmd = '+';
+			set->cmd2 = 0;
+			set->bits = setbits;
+			set++;
+		}
+		if (Xbits) {
+			set->cmd = 'X';
+			set->cmd2 = 0;
+			set->bits = Xbits;
+			set++;
+		}
+	}
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/solfakes.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/solfakes.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/solfakes.c	(revision 1780)
@@ -0,0 +1,95 @@
+/* $Id: $ */
+/** @file
+ *
+ * Fake Unix stuff for Solaris.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include "solfakes.h"
+
+
+int asprintf(char **strp, const char *fmt, ...)
+{
+    int rc;
+    va_list va;
+    va_start(va, fmt);
+    rc = vasprintf(strp, fmt, va);
+    va_end(va);
+    return rc;
+}
+
+
+int vasprintf(char **strp, const char *fmt, va_list va)
+{
+    int rc;
+    char *psz;
+    size_t cb = 1024;
+
+    *strp = NULL;
+    for (;;)
+    {
+        va_list va2;
+
+        psz = malloc(cb);
+        if (!psz)
+            return -1;
+
+#ifdef va_copy
+        va_copy(va2, va);
+        rc = snprintf(psz, cb, fmt, va2);
+        va_end(va2);
+#else
+        va2 = va;
+        rc = snprintf(psz, cb, fmt, va2);
+#endif
+        if (rc < 0 || (size_t)rc < cb)
+            break;
+        cb *= 2;
+        free(psz);
+    }
+
+    *strp = psz;
+    return rc;
+}
+
+
+
+int sol_lchmod(const char *pszPath, mode_t mode)
+{
+    /*
+     * Weed out symbolic links.
+     */
+    struct stat s;
+    if (    !lstat(pszPath, &s)
+        &&  S_ISLNK(s.st_mode))
+    {
+        errno = -ENOSYS;
+        return -1;
+    }
+
+    return chmod(pszPath, mode);
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/solfakes.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/solfakes.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/solfakes.h	(revision 1780)
@@ -0,0 +1,47 @@
+/* $Id: mscfakes.h 805 2007-01-25 00:56:27Z bird $ */
+/** @file
+ *
+ * Unix fakes for Solaris.
+ *
+ * Copyright (c) 2005-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * 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
+ *
+ */
+
+#ifndef __solfakes_h__
+#define __solfakes_h__
+#ifdef __sun__
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include "getopt.h"
+#define _PATH_DEVNULL "/dev/null"
+#define ALLPERMS 0000777
+#define lutimes(path, tvs) utimes(path, tvs)
+#define lchmod sol_lchmod
+#define MAX(a,b) ((a) >= (b) ? (a) : (b))
+#ifndef USHRT_MAX
+# define USHRT_MAX 65535
+#endif
+
+int vasprintf(char **strp, const char *fmt, va_list va);
+int asprintf(char **strp, const char *fmt, ...);
+int sol_lchmod(const char *pszPath, mode_t mode);
+
+#endif /* __sun__ */
+#endif /* __solfakes_h__ */
+
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/strlcpy.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/strlcpy.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/strlcpy.c	(revision 1780)
@@ -0,0 +1,70 @@
+/*	$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $");
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.7 2003/05/01 19:03:14 nectar Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t strlcpy(dst, src, siz)
+	char *dst;
+	const char *src;
+	size_t siz;
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/strmode.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/strmode.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/strmode.c	(revision 1780)
@@ -0,0 +1,196 @@
+/*	$NetBSD: strmode.c,v 1.16 2004/06/20 22:20:15 jmc Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#include <sys/cdefs.h>*/
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)strmode.c	8.3 (Berkeley) 8/15/94";
+#else
+__RCSID("$NetBSD: strmode.c,v 1.16 2004/06/20 22:20:15 jmc Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*#include "namespace.h"*/
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#else
+#include "mscfakes.h"
+#endif
+
+#ifndef _DIAGASSERT
+#define _DIAGASSERT assert
+#endif
+
+void
+bsd_strmode(mode, p)
+	mode_t mode;
+	char *p;
+{
+
+	_DIAGASSERT(p != NULL);
+
+	 /* print type */
+	switch (mode & S_IFMT) {
+	case S_IFDIR:			/* directory */
+		*p++ = 'd';
+		break;
+	case S_IFCHR:			/* character special */
+		*p++ = 'c';
+		break;
+#ifdef S_IFBLK
+	case S_IFBLK:			/* block special */
+		*p++ = 'b';
+		break;
+#endif
+	case S_IFREG:			/* regular */
+#ifdef S_ARCH2
+		if ((mode & S_ARCH2) != 0) {
+			*p++ = 'A';
+		} else if ((mode & S_ARCH1) != 0) {
+			*p++ = 'a';
+		} else {
+#endif
+			*p++ = '-';
+#ifdef S_ARCH2
+		}
+#endif
+		break;
+#ifdef S_IFLNK
+	case S_IFLNK:			/* symbolic link */
+		*p++ = 'l';
+		break;
+#endif
+#ifdef S_IFSOCK
+	case S_IFSOCK:			/* socket */
+		*p++ = 's';
+		break;
+#endif
+#ifdef S_IFIFO
+	case S_IFIFO:			/* fifo */
+		*p++ = 'p';
+		break;
+#endif
+#ifdef S_IFWHT
+	case S_IFWHT:			/* whiteout */
+		*p++ = 'w';
+		break;
+#endif
+#ifdef S_IFDOOR
+	case S_IFDOOR:			/* door */
+		*p++ = 'D';
+		break;
+#endif
+	default:			/* unknown */
+		*p++ = '?';
+		break;
+	}
+	/* usr */
+	if (mode & S_IRUSR)
+		*p++ = 'r';
+	else
+		*p++ = '-';
+	if (mode & S_IWUSR)
+		*p++ = 'w';
+	else
+		*p++ = '-';
+	switch (mode & (S_IXUSR | S_ISUID)) {
+	case 0:
+		*p++ = '-';
+		break;
+	case S_IXUSR:
+		*p++ = 'x';
+		break;
+	case S_ISUID:
+		*p++ = 'S';
+		break;
+	case S_IXUSR | S_ISUID:
+		*p++ = 's';
+		break;
+	}
+	/* group */
+	if (mode & S_IRGRP)
+		*p++ = 'r';
+	else
+		*p++ = '-';
+	if (mode & S_IWGRP)
+		*p++ = 'w';
+	else
+		*p++ = '-';
+	switch (mode & (S_IXGRP | S_ISGID)) {
+	case 0:
+		*p++ = '-';
+		break;
+	case S_IXGRP:
+		*p++ = 'x';
+		break;
+	case S_ISGID:
+		*p++ = 'S';
+		break;
+	case S_IXGRP | S_ISGID:
+		*p++ = 's';
+		break;
+	}
+	/* other */
+	if (mode & S_IROTH)
+		*p++ = 'r';
+	else
+		*p++ = '-';
+	if (mode & S_IWOTH)
+		*p++ = 'w';
+	else
+		*p++ = '-';
+#ifdef S_ISVTX
+	switch (mode & (S_IXOTH | S_ISVTX)) {
+#else
+	switch (mode & (S_IXOTH)) {
+#endif
+	case 0:
+		*p++ = '-';
+		break;
+	case S_IXOTH:
+		*p++ = 'x';
+		break;
+#ifdef S_ISVTX
+	case S_ISVTX:
+		*p++ = 'T';
+		break;
+	case S_IXOTH | S_ISVTX:
+		*p++ = 't';
+		break;
+#endif
+	}
+	*p++ = ' ';		/* will be a '+' if ACL's implemented */
+	*p = '\0';
+}
Index: /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/test.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/test.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/kmkbuiltin/test.c	(revision 1780)
@@ -0,0 +1,824 @@
+/* $NetBSD: test.c,v 1.33 2007/06/24 18:54:58 christos Exp $ */
+
+/*
+ * test(1); version 7-like  --  author Erik Baalbergen
+ * modified by Eric Gisin to be used as built-in.
+ * modified by Arnold Robbins to add SVR3 compatibility
+ * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
+ * modified by J.T. Conklin for NetBSD.
+ *
+ * This program is in the Public Domain.
+ */
+
+/*#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: test.c,v 1.33 2007/06/24 18:54:58 christos Exp $");
+#endif*/
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include "err.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <io.h>
+# include <process.h>
+# include "mscfakes.h"
+#else
+# include <unistd.h>
+#endif
+#include <stdarg.h>
+#include <sys/stat.h>
+
+#include "kmkbuiltin.h"
+
+#ifndef __arraycount
+# define __arraycount(a) 	( sizeof(a) / sizeof(a[0]) )
+#endif
+
+
+/* test(1) accepts the following grammar:
+	oexpr	::= aexpr | aexpr "-o" oexpr ;
+	aexpr	::= nexpr | nexpr "-a" aexpr ;
+	nexpr	::= primary | "!" primary
+	primary	::= unary-operator operand
+		| operand binary-operator operand
+		| operand
+		| "(" oexpr ")"
+		;
+	unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
+		"-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
+
+	binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
+			"-nt"|"-ot"|"-ef";
+	operand ::= <any legal UNIX file name>
+*/
+
+enum token {
+	EOI,
+	FILRD,
+	FILWR,
+	FILEX,
+	FILEXIST,
+	FILREG,
+	FILDIR,
+	FILCDEV,
+	FILBDEV,
+	FILFIFO,
+	FILSOCK,
+	FILSYM,
+	FILGZ,
+	FILTT,
+	FILSUID,
+	FILSGID,
+	FILSTCK,
+	FILNT,
+	FILOT,
+	FILEQ,
+	FILUID,
+	FILGID,
+	STREZ,
+	STRNZ,
+	STREQ,
+	STRNE,
+	STRLT,
+	STRGT,
+	INTEQ,
+	INTNE,
+	INTGE,
+	INTGT,
+	INTLE,
+	INTLT,
+	UNOT,
+	BAND,
+	BOR,
+	LPAREN,
+	RPAREN,
+	OPERAND
+};
+
+enum token_types {
+	UNOP,
+	BINOP,
+	BUNOP,
+	BBINOP,
+	PAREN
+};
+
+struct t_op {
+	const char *op_text;
+	short op_num, op_type;
+};
+
+static const struct t_op cop[] = {
+	{"!",	UNOT,	BUNOP},
+	{"(",	LPAREN,	PAREN},
+	{")",	RPAREN,	PAREN},
+	{"<",	STRLT,	BINOP},
+	{"=",	STREQ,	BINOP},
+	{">",	STRGT,	BINOP},
+};
+
+static const struct t_op cop2[] = {
+	{"!=",	STRNE,	BINOP},
+};
+
+static const struct t_op mop3[] = {
+	{"ef",	FILEQ,	BINOP},
+	{"eq",	INTEQ,	BINOP},
+	{"ge",	INTGE,	BINOP},
+	{"gt",	INTGT,	BINOP},
+	{"le",	INTLE,	BINOP},
+	{"lt",	INTLT,	BINOP},
+	{"ne",	INTNE,	BINOP},
+	{"nt",	FILNT,	BINOP},
+	{"ot",	FILOT,	BINOP},
+};
+
+static const struct t_op mop2[] = {
+	{"G",	FILGID,	UNOP},
+	{"L",	FILSYM,	UNOP},
+	{"O",	FILUID,	UNOP},
+	{"S",	FILSOCK,UNOP},
+	{"a",	BAND,	BBINOP},
+	{"b",	FILBDEV,UNOP},
+	{"c",	FILCDEV,UNOP},
+	{"d",	FILDIR,	UNOP},
+	{"e",	FILEXIST,UNOP},
+	{"f",	FILREG,	UNOP},
+	{"g",	FILSGID,UNOP},
+	{"h",	FILSYM,	UNOP},		/* for backwards compat */
+	{"k",	FILSTCK,UNOP},
+	{"n",	STRNZ,	UNOP},
+	{"o",	BOR,	BBINOP},
+	{"p",	FILFIFO,UNOP},
+	{"r",	FILRD,	UNOP},
+	{"s",	FILGZ,	UNOP},
+	{"t",	FILTT,	UNOP},
+	{"u",	FILSUID,UNOP},
+	{"w",	FILWR,	UNOP},
+	{"x",	FILEX,	UNOP},
+	{"z",	STREZ,	UNOP},
+};
+
+static char **t_wp;
+static struct t_op const *t_wp_op;
+
+static int syntax(const char *, const char *);
+static int oexpr(enum token);
+static int aexpr(enum token);
+static int nexpr(enum token);
+static int primary(enum token);
+static int binop(void);
+static int test_access(struct stat *, mode_t);
+static int filstat(char *, enum token);
+static enum token t_lex(char *);
+static int isoperand(void);
+static int getn(const char *);
+static int newerf(const char *, const char *);
+static int olderf(const char *, const char *);
+static int equalf(const char *, const char *);
+static int usage(const char *);
+
+#if !defined(kmk_builtin_test) || defined(ELECTRIC_HEAP)
+extern void *xmalloc(unsigned int);
+#else
+extern void *xmalloc(unsigned int sz)
+{
+    void *p = malloc(sz);
+    if (!p) {
+	    fprintf(stderr, "%s: malloc(%u) failed\n", g_progname, sz);
+	    exit(1);
+    }
+    return p;
+}
+#endif
+
+int kmk_builtin_test(int argc, char **argv, char **envp, char ***ppapszArgvSpawn)
+{
+	int res;
+	char **argv_spawn;
+	int i;
+
+	g_progname = argv[0];
+
+	/* look for the '--', '--help' and '--version'. */
+	argv_spawn = NULL;
+	for (i = 1; i < argc; i++) {
+		if (   argv[i][0] == '-'
+		    && argv[i][1] == '-') {
+    			if (argv[i][2] == '\0') {
+				argc = i;
+				argv[i] = NULL;
+
+                                /* skip blank arguments (happens inside kmk) */
+                                while (argv[++i]) {
+                                        const char *psz = argv[i];
+                                        while (isspace(*psz))
+                                                psz++;
+                                        if (*psz)
+                                                break;
+                                }
+				argv_spawn = &argv[i];
+				break;
+			}
+			if (!strcmp(argv[i], "--help"))
+				return usage(argv[0]);
+			if (!strcmp(argv[i], "--version"))
+				return kbuild_version(argv[0]);
+		}
+	}
+
+	/* are we '['? then check for ']'. */
+	if (strcmp(g_progname, "[") == 0) { /** @todo should skip the path in g_progname */
+		if (strcmp(argv[--argc], "]"))
+			return errx(1, "missing ]");
+		argv[argc] = NULL;
+	}
+
+	/* evaluate the expression */
+	if (argc < 2)
+		res = 1;
+	else {
+		t_wp = &argv[1];
+		res = oexpr(t_lex(*t_wp));
+		if (res != -42 && *t_wp != NULL && *++t_wp != NULL)
+			res = syntax(*t_wp, "unexpected operator");
+		if (res == -42)
+			return 1; /* don't mix syntax errors with the argv_spawn ignore */
+		res = !res;
+	}
+
+	/* anything to execute on success? */
+	if (argv_spawn) {
+		if (res != 0 || !argv_spawn[0])
+			res = 0; /* ignored */
+		else {
+#ifdef kmk_builtin_test
+			/* try exec the specified process */
+# if defined(_MSC_VER)
+			res = _spawnvp(_P_WAIT, argv_spawn[0], argv_spawn);
+			if (res == -1)
+			    res = err(1, "_spawnvp(_P_WAIT,%s,..)", argv_spawn[i]);
+# else
+			execvp(argv_spawn[i], &argv_spawn[i]);
+			res = err(1, "execvp(%s,..)", argv_spawn[i]);
+# endif
+#else /* in kmk */
+			/* let job.c spawn the process, make a job.c style argv_spawn copy. */
+			char *buf, *cur, **argv_new;
+			size_t sz = 0;
+			int argc_new = 0;
+			while (argv_spawn[argc_new]) {
+    				size_t len = strlen(argv_spawn[argc_new]) + 1;
+				sz += (len + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
+				argc_new++;
+			}
+
+			argv_new = xmalloc((argc_new + 1) * sizeof(char *));
+			buf = cur = xmalloc(sz);
+			for (i = 0; i < argc_new; i++) {
+				size_t len = strlen(argv_spawn[i]) + 1;
+				argv_new[i] = memcpy(cur, argv_spawn[i], len);
+				cur += (len + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
+			}
+			argv_new[i] = NULL;
+
+			*ppapszArgvSpawn = argv_new;
+			res = 0;
+#endif /* in kmk */
+		}
+	}
+
+	return res;
+}
+
+static int
+syntax(const char *op, const char *msg)
+{
+
+	if (op && *op)
+		errx(1, "%s: %s", op, msg);
+	else
+		errx(1, "%s", msg);
+	return -42;
+}
+
+static int
+oexpr(enum token n)
+{
+	int res;
+
+	res = aexpr(n);
+	if (res == -42 || *t_wp == NULL)
+		return res;
+	if (t_lex(*++t_wp) == BOR) {
+		int res2 = oexpr(t_lex(*++t_wp));
+		return res2 != -42 ? res2 || res : res2;
+	}
+	t_wp--;
+	return res;
+}
+
+static int
+aexpr(enum token n)
+{
+	int res;
+
+	res = nexpr(n);
+	if (res == -42 || *t_wp == NULL)
+		return res;
+	if (t_lex(*++t_wp) == BAND) {
+		int res2 = aexpr(t_lex(*++t_wp));
+		return res2 != -42 ? res2 && res : res2;
+	}
+	t_wp--;
+	return res;
+}
+
+static int
+nexpr(enum token n)
+{
+	if (n == UNOT) {
+		int res = nexpr(t_lex(*++t_wp));
+		return res != -42 ? !res : res;
+	}
+	return primary(n);
+}
+
+static int
+primary(enum token n)
+{
+	enum token nn;
+	int res;
+
+	if (n == EOI)
+		return 0;		/* missing expression */
+	if (n == LPAREN) {
+		if ((nn = t_lex(*++t_wp)) == RPAREN)
+			return 0;	/* missing expression */
+		res = oexpr(nn);
+		if (res != -42 && t_lex(*++t_wp) != RPAREN)
+			return syntax(NULL, "closing paren expected");
+		return res;
+	}
+	if (t_wp_op && t_wp_op->op_type == UNOP) {
+		/* unary expression */
+		if (*++t_wp == NULL)
+			return syntax(t_wp_op->op_text, "argument expected");
+		switch (n) {
+		case STREZ:
+			return strlen(*t_wp) == 0;
+		case STRNZ:
+			return strlen(*t_wp) != 0;
+		case FILTT:
+			return isatty(getn(*t_wp));
+		default:
+			return filstat(*t_wp, n);
+		}
+	}
+
+	if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
+		return binop();
+	}
+
+	return strlen(*t_wp) > 0;
+}
+
+static int
+binop(void)
+{
+	const char *opnd1, *opnd2;
+	struct t_op const *op;
+
+	opnd1 = *t_wp;
+	(void) t_lex(*++t_wp);
+	op = t_wp_op;
+
+	if ((opnd2 = *++t_wp) == NULL)
+		return syntax(op->op_text, "argument expected");
+
+	switch (op->op_num) {
+	case STREQ:
+		return strcmp(opnd1, opnd2) == 0;
+	case STRNE:
+		return strcmp(opnd1, opnd2) != 0;
+	case STRLT:
+		return strcmp(opnd1, opnd2) < 0;
+	case STRGT:
+		return strcmp(opnd1, opnd2) > 0;
+	case INTEQ:
+		return getn(opnd1) == getn(opnd2);
+	case INTNE:
+		return getn(opnd1) != getn(opnd2);
+	case INTGE:
+		return getn(opnd1) >= getn(opnd2);
+	case INTGT:
+		return getn(opnd1) > getn(opnd2);
+	case INTLE:
+		return getn(opnd1) <= getn(opnd2);
+	case INTLT:
+		return getn(opnd1) < getn(opnd2);
+	case FILNT:
+		return newerf(opnd1, opnd2);
+	case FILOT:
+		return olderf(opnd1, opnd2);
+	case FILEQ:
+		return equalf(opnd1, opnd2);
+	default:
+		abort();
+		/* NOTREACHED */
+#ifdef _MSC_VER
+		return -42;
+#endif
+	}
+}
+
+/*
+ * The manual, and IEEE POSIX 1003.2, suggests this should check the mode bits,
+ * not use access():
+ *
+ *	True shall indicate only that the write flag is on.  The file is not
+ *	writable on a read-only file system even if this test indicates true.
+ *
+ * Unfortunately IEEE POSIX 1003.1-2001, as quoted in SuSv3, says only:
+ *
+ *	True shall indicate that permission to read from file will be granted,
+ *	as defined in "File Read, Write, and Creation".
+ *
+ * and that section says:
+ *
+ *	When a file is to be read or written, the file shall be opened with an
+ *	access mode corresponding to the operation to be performed.  If file
+ *	access permissions deny access, the requested operation shall fail.
+ *
+ * and of course access permissions are described as one might expect:
+ *
+ *     * If a process has the appropriate privilege:
+ *
+ *        * If read, write, or directory search permission is requested,
+ *          access shall be granted.
+ *
+ *        * If execute permission is requested, access shall be granted if
+ *          execute permission is granted to at least one user by the file
+ *          permission bits or by an alternate access control mechanism;
+ *          otherwise, access shall be denied.
+ *
+ *   * Otherwise:
+ *
+ *        * The file permission bits of a file contain read, write, and
+ *          execute/search permissions for the file owner class, file group
+ *          class, and file other class.
+ *
+ *        * Access shall be granted if an alternate access control mechanism
+ *          is not enabled and the requested access permission bit is set for
+ *          the class (file owner class, file group class, or file other class)
+ *          to which the process belongs, or if an alternate access control
+ *          mechanism is enabled and it allows the requested access; otherwise,
+ *          access shall be denied.
+ *
+ * and when I first read this I thought:  surely we can't go about using
+ * open(O_WRONLY) to try this test!  However the POSIX 1003.1-2001 Rationale
+ * section for test does in fact say:
+ *
+ *	On historical BSD systems, test -w directory always returned false
+ *	because test tried to open the directory for writing, which always
+ *	fails.
+ *
+ * and indeed this is in fact true for Seventh Edition UNIX, UNIX 32V, and UNIX
+ * System III, and thus presumably also for BSD up to and including 4.3.
+ *
+ * Secondly I remembered why using open() and/or access() are bogus.  They
+ * don't work right for detecting read and write permissions bits when called
+ * by root.
+ *
+ * Interestingly the 'test' in 4.4BSD was closer to correct (as per
+ * 1003.2-1992) and it was implemented efficiently with stat() instead of
+ * open().
+ *
+ * This was apparently broken in NetBSD around about 1994/06/30 when the old
+ * 4.4BSD implementation was replaced with a (arguably much better coded)
+ * implementation derived from pdksh.
+ *
+ * Note that modern pdksh is yet different again, but still not correct, at
+ * least not w.r.t. 1003.2-1992.
+ *
+ * As I think more about it and read more of the related IEEE docs I don't like
+ * that wording about 'test -r' and 'test -w' in 1003.1-2001 at all.  I very
+ * much prefer the original wording in 1003.2-1992.  It is much more useful,
+ * and so that's what I've implemented.
+ *
+ * (Note that a strictly conforming implementation of 1003.1-2001 is in fact
+ * totally useless for the case in question since its 'test -w' and 'test -r'
+ * can never fail for root for any existing files, i.e. files for which 'test
+ * -e' succeeds.)
+ *
+ * The rationale for 1003.1-2001 suggests that the wording was "clarified" in
+ * 1003.1-2001 to align with the 1003.2b draft.  1003.2b Draft 12 (July 1999),
+ * which is the latest copy I have, does carry the same suggested wording as is
+ * in 1003.1-2001, with its rationale saying:
+ *
+ * 	This change is a clarification and is the result of interpretation
+ * 	request PASC 1003.2-92 #23 submitted for IEEE Std 1003.2-1992.
+ *
+ * That interpretation can be found here:
+ *
+ *   http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-23.html
+ *
+ * Not terribly helpful, unfortunately.  I wonder who that fence sitter was.
+ *
+ * Worse, IMVNSHO, I think the authors of 1003.2b-D12 have mis-interpreted the
+ * PASC interpretation and appear to be gone against at least one widely used
+ * implementation (namely 4.4BSD).  The problem is that for file access by root
+ * this means that if test '-r' and '-w' are to behave as if open() were called
+ * then there's no way for a shell script running as root to check if a file
+ * has certain access bits set other than by the grotty means of interpreting
+ * the output of 'ls -l'.  This was widely considered to be a bug in V7's
+ * "test" and is, I believe, one of the reasons why direct use of access() was
+ * avoided in some more recent implementations!
+ *
+ * I have always interpreted '-r' to match '-w' and '-x' as per the original
+ * wording in 1003.2-1992, not the other way around.  I think 1003.2b goes much
+ * too far the wrong way without any valid rationale and that it's best if we
+ * stick with 1003.2-1992 and test the flags, and not mimic the behaviour of
+ * open() since we already know very well how it will work -- existance of the
+ * file is all that matters to open() for root.
+ *
+ * Unfortunately the SVID is no help at all (which is, I guess, partly why
+ * we're in this mess in the first place :-).
+ *
+ * The SysV implementation (at least in the 'test' builtin in /bin/sh) does use
+ * access(name, 2) even though it also goes to much greater lengths for '-x'
+ * matching the 1003.2-1992 definition (which is no doubt where that definition
+ * came from).
+ *
+ * The ksh93 implementation uses access() for '-r' and '-w' if
+ * (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root.
+ * i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b).
+ */
+static int
+test_access(struct stat *sp, mode_t stmode)
+{
+#ifdef _MSC_VER
+	/* just pretend to be root for now. */
+	stmode = (stmode << 6) | (stmode << 3) | stmode;
+	return !!(sp->st_mode & stmode);
+#else
+	gid_t *groups;
+	register int n;
+	uid_t euid;
+	int maxgroups;
+
+	/*
+	 * I suppose we could use access() if not running as root and if we are
+	 * running with ((euid == uid) && (egid == gid)), but we've already
+	 * done the stat() so we might as well just test the permissions
+	 * directly instead of asking the kernel to do it....
+	 */
+	euid = geteuid();
+	if (euid == 0)				/* any bit is good enough */
+		stmode = (stmode << 6) | (stmode << 3) | stmode;
+ 	else if (sp->st_uid == euid)
+		stmode <<= 6;
+	else if (sp->st_gid == getegid())
+		stmode <<= 3;
+	else {
+		/* XXX stolen almost verbatim from ksh93.... */
+		/* on some systems you can be in several groups */
+		if ((maxgroups = getgroups(0, NULL)) <= 0)
+			maxgroups = NGROUPS_MAX;	/* pre-POSIX system? */
+		groups = xmalloc((maxgroups + 1) * sizeof(gid_t));
+		n = getgroups(maxgroups, groups);
+		while (--n >= 0) {
+			if (groups[n] == sp->st_gid) {
+				stmode <<= 3;
+				break;
+			}
+		}
+		free(groups);
+	}
+
+	return !!(sp->st_mode & stmode);
+#endif
+}
+
+static int
+filstat(char *nm, enum token mode)
+{
+	struct stat s;
+
+	if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s))
+		return 0;
+
+	switch (mode) {
+	case FILRD:
+		return test_access(&s, S_IROTH);
+	case FILWR:
+		return test_access(&s, S_IWOTH);
+	case FILEX:
+		return test_access(&s, S_IXOTH);
+	case FILEXIST:
+		return 1; /* the successful lstat()/stat() is good enough */
+	case FILREG:
+		return S_ISREG(s.st_mode);
+	case FILDIR:
+		return S_ISDIR(s.st_mode);
+	case FILCDEV:
+#ifdef S_ISCHR
+		return S_ISCHR(s.st_mode);
+#else
+		return 0;
+#endif
+	case FILBDEV:
+#ifdef S_ISBLK
+		return S_ISBLK(s.st_mode);
+#else
+		return 0;
+#endif
+	case FILFIFO:
+#ifdef S_ISFIFO
+		return S_ISFIFO(s.st_mode);
+#else
+		return 0;
+#endif
+	case FILSOCK:
+#ifdef S_ISSOCK
+		return S_ISSOCK(s.st_mode);
+#else
+		return 0;
+#endif
+	case FILSYM:
+#ifdef S_ISLNK
+		return S_ISLNK(s.st_mode);
+#else
+		return 0;
+#endif
+	case FILSUID:
+		return (s.st_mode & S_ISUID) != 0;
+	case FILSGID:
+		return (s.st_mode & S_ISGID) != 0;
+	case FILSTCK:
+#ifdef S_ISVTX
+		return (s.st_mode & S_ISVTX) != 0;
+#else
+		return 0;
+#endif
+	case FILGZ:
+		return s.st_size > (off_t)0;
+	case FILUID:
+		return s.st_uid == geteuid();
+	case FILGID:
+		return s.st_gid == getegid();
+	default:
+		return 1;
+	}
+}
+
+#define VTOC(x)	(const unsigned char *)((const struct t_op *)x)->op_text
+
+static int
+compare1(const void *va, const void *vb)
+{
+	const unsigned char *a = va;
+	const unsigned char *b = VTOC(vb);
+
+	return a[0] - b[0];
+}
+
+static int
+compare2(const void *va, const void *vb)
+{
+	const unsigned char *a = va;
+	const unsigned char *b = VTOC(vb);
+	int z = a[0] - b[0];
+
+	return z ? z : (a[1] - b[1]);
+}
+
+static struct t_op const *
+findop(const char *s)
+{
+	if (s[0] == '-') {
+		if (s[1] == '\0')
+			return NULL;
+		if (s[2] == '\0')
+			return bsearch(s + 1, mop2, __arraycount(mop2),
+			    sizeof(*mop2), compare1);
+		else if (s[3] != '\0')
+			return NULL;
+		else
+			return bsearch(s + 1, mop3, __arraycount(mop3),
+			    sizeof(*mop3), compare2);
+	} else {
+		if (s[1] == '\0')
+			return bsearch(s, cop, __arraycount(cop), sizeof(*cop),
+			    compare1);
+		else if (strcmp(s, cop2[0].op_text) == 0)
+			return cop2;
+		else
+			return NULL;
+	}
+}
+
+static enum token
+t_lex(char *s)
+{
+	struct t_op const *op;
+
+	if (s == NULL) {
+		t_wp_op = NULL;
+		return EOI;
+	}
+
+	if ((op = findop(s)) != NULL) {
+		if (!((op->op_type == UNOP && isoperand()) ||
+		    (op->op_num == LPAREN && *(t_wp+1) == 0))) {
+			t_wp_op = op;
+			return op->op_num;
+		}
+	}
+	t_wp_op = NULL;
+	return OPERAND;
+}
+
+static int
+isoperand(void)
+{
+	struct t_op const *op;
+	char *s, *t;
+
+	if ((s  = *(t_wp+1)) == 0)
+		return 1;
+	if ((t = *(t_wp+2)) == 0)
+		return 0;
+	if ((op = findop(s)) != NULL)
+		return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0');
+	return 0;
+}
+
+/* atoi with error detection */
+static int
+getn(const char *s)
+{
+	char *p;
+	long r;
+
+	errno = 0;
+	r = strtol(s, &p, 10);
+
+	if (errno != 0)
+	      return errx(-42, "%s: out of range", s);
+
+	while (isspace((unsigned char)*p))
+	      p++;
+
+	if (*p)
+	      return errx(-42, "%s: bad number", s);
+
+	return (int) r;
+}
+
+static int
+newerf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+		stat(f2, &b2) == 0 &&
+		b1.st_mtime > b2.st_mtime);
+}
+
+static int
+olderf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+		stat(f2, &b2) == 0 &&
+		b1.st_mtime < b2.st_mtime);
+}
+
+static int
+equalf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+		stat(f2, &b2) == 0 &&
+		b1.st_dev == b2.st_dev &&
+		b1.st_ino == b2.st_ino);
+}
+
+static int
+usage(const char *argv0)
+{
+	fprintf(stdout,
+	        "usage: %s expression [-- <prog> [args]]\n", argv0);
+	return 0; /* only used in --help. */
+}
Index: /tags/kBuild-0.1.4/src/kmk/main.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/main.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/main.c	(revision 1780)
@@ -0,0 +1,3746 @@
+/* Argument parsing and main program of GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "dep.h"
+#include "filedef.h"
+#include "variable.h"
+#include "job.h"
+#include "commands.h"
+#include "rule.h"
+#include "debug.h"
+#include "getopt.h"
+#ifdef KMK
+# include "kbuild.h"
+#endif
+
+#include <assert.h>
+#ifdef _AMIGA
+# include <dos/dos.h>
+# include <proto/dos.h>
+#endif
+#ifdef WINDOWS32
+#include <windows.h>
+#include <io.h>
+#include "pathstuff.h"
+#endif
+#ifdef __EMX__
+# include <sys/types.h>
+# include <sys/wait.h>
+#endif
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef KMK /* for get_online_cpu_count */
+# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#  include <sys/sysctl.h>
+# endif
+# ifdef __OS2__
+#  define INCL_BASE
+#  include <os2.h>
+# endif 
+#endif /* KMK*/
+
+#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
+# define SET_STACK_SIZE
+#endif
+
+#ifdef SET_STACK_SIZE
+# include <sys/resource.h>
+#endif
+
+#ifdef _AMIGA
+int __stack = 20000; /* Make sure we have 20K of stack space */
+#endif
+
+void init_dir (void);
+void remote_setup (void);
+void remote_cleanup (void);
+RETSIGTYPE fatal_error_signal (int sig);
+
+void print_variable_data_base (void);
+void print_dir_data_base (void);
+void print_rule_data_base (void);
+void print_file_data_base (void);
+void print_vpath_data_base (void);
+
+void verify_file_data_base (void);
+
+#if defined HAVE_WAITPID || defined HAVE_WAIT3
+# define HAVE_WAIT_NOHANG
+#endif
+
+#if !defined(HAVE_UNISTD_H) && !defined(_MSC_VER) /* bird */
+int chdir ();
+#endif
+#ifndef	STDC_HEADERS
+# ifndef sun			/* Sun has an incorrect decl in a header.  */
+void exit (int) __attribute__ ((noreturn));
+# endif
+double atof ();
+#endif
+
+static void clean_jobserver (int status);
+static void print_data_base (void);
+static void print_version (void);
+static void decode_switches (int argc, char **argv, int env);
+static void decode_env_switches (char *envar, unsigned int len);
+static void define_makeflags (int all, int makefile);
+static char *quote_for_env (char *out, const char *in);
+static void initialize_global_hash_tables (void);
+
+
+
+/* The structure that describes an accepted command switch.  */
+
+struct command_switch
+  {
+    int c;			/* The switch character.  */
+
+    enum			/* Type of the value.  */
+      {
+	flag,			/* Turn int flag on.  */
+	flag_off,		/* Turn int flag off.  */
+	string,			/* One string per switch.  */
+	filename,		/* A string containing a file name.  */
+	positive_int,		/* A positive integer.  */
+	floating,		/* A floating-point number (double).  */
+	ignore			/* Ignored.  */
+      } type;
+
+    void *value_ptr;	/* Pointer to the value-holding variable.  */
+
+    unsigned int env:1;		/* Can come from MAKEFLAGS.  */
+    unsigned int toenv:1;	/* Should be put in MAKEFLAGS.  */
+    unsigned int no_makefile:1;	/* Don't propagate when remaking makefiles.  */
+
+    const void *noarg_value;	/* Pointer to value used if no arg given.  */
+    const void *default_value;	/* Pointer to default value.  */
+
+    char *long_name;		/* Long option name.  */
+  };
+
+/* True if C is a switch value that corresponds to a short option.  */
+
+#define short_option(c) ((c) <= CHAR_MAX)
+
+/* The structure used to hold the list of strings given
+   in command switches of a type that takes string arguments.  */
+
+struct stringlist
+  {
+    const char **list;	/* Nil-terminated list of strings.  */
+    unsigned int idx;	/* Index into above.  */
+    unsigned int max;	/* Number of pointers allocated.  */
+  };
+
+
+/* The recognized command switches.  */
+
+/* Nonzero means do not print commands to be executed (-s).  */
+
+int silent_flag;
+
+/* Nonzero means just touch the files
+   that would appear to need remaking (-t)  */
+
+int touch_flag;
+
+/* Nonzero means just print what commands would need to be executed,
+   don't actually execute them (-n).  */
+
+int just_print_flag;
+
+#ifdef CONFIG_PRETTY_COMMAND_PRINTING
+/* Nonzero means to print commands argument for argument skipping blanks. */
+
+int pretty_command_printing;
+#endif
+
+/* Print debugging info (--debug).  */
+
+static struct stringlist *db_flags;
+static int debug_flag = 0;
+
+int db_level = 0;
+
+/* Output level (--verbosity).  */
+
+static struct stringlist *verbosity_flags;
+
+#ifdef WINDOWS32
+/* Suspend make in main for a short time to allow debugger to attach */
+
+int suspend_flag = 0;
+#endif
+
+/* Environment variables override makefile definitions.  */
+
+int env_overrides = 0;
+
+/* Nonzero means ignore status codes returned by commands
+   executed to remake files.  Just treat them all as successful (-i).  */
+
+int ignore_errors_flag = 0;
+
+/* Nonzero means don't remake anything, just print the data base
+   that results from reading the makefile (-p).  */
+
+int print_data_base_flag = 0;
+
+/* Nonzero means don't remake anything; just return a nonzero status
+   if the specified targets are not up to date (-q).  */
+
+int question_flag = 0;
+
+/* Nonzero means do not use any of the builtin rules (-r) / variables (-R).  */
+
+int no_builtin_rules_flag = 0;
+int no_builtin_variables_flag = 0;
+
+/* Nonzero means keep going even if remaking some file fails (-k).  */
+
+int keep_going_flag;
+int default_keep_going_flag = 0;
+
+/* Nonzero means check symlink mtimes.  */
+
+int check_symlink_flag = 0;
+
+/* Nonzero means print directory before starting and when done (-w).  */
+
+int print_directory_flag = 0;
+
+/* Nonzero means ignore print_directory_flag and never print the directory.
+   This is necessary because print_directory_flag is set implicitly.  */
+
+int inhibit_print_directory_flag = 0;
+
+/* Nonzero means print version information.  */
+
+int print_version_flag = 0;
+
+/* List of makefiles given with -f switches.  */
+
+static struct stringlist *makefiles = 0;
+
+/* Number of job slots (commands that can be run at once).  */
+
+unsigned int job_slots = 1;
+unsigned int default_job_slots = 1;
+static unsigned int master_job_slots = 0;
+
+/* Value of job_slots that means no limit.  */
+
+static unsigned int inf_jobs = 0;
+
+/* File descriptors for the jobs pipe.  */
+
+static struct stringlist *jobserver_fds = 0;
+
+int job_fds[2] = { -1, -1 };
+int job_rfd = -1;
+
+/* Maximum load average at which multiple jobs will be run.
+   Negative values mean unlimited, while zero means limit to
+   zero load (which could be useful to start infinite jobs remotely
+   but one at a time locally).  */
+#ifndef NO_FLOAT
+double max_load_average = -1.0;
+double default_load_average = -1.0;
+#else
+int max_load_average = -1;
+int default_load_average = -1;
+#endif
+
+/* List of directories given with -C switches.  */
+
+static struct stringlist *directories = 0;
+
+/* List of include directories given with -I switches.  */
+
+static struct stringlist *include_directories = 0;
+
+/* List of files given with -o switches.  */
+
+static struct stringlist *old_files = 0;
+
+/* List of files given with -W switches.  */
+
+static struct stringlist *new_files = 0;
+
+/* If nonzero, we should just print usage and exit.  */
+
+static int print_usage_flag = 0;
+
+/* If nonzero, we should print a warning message
+   for each reference to an undefined variable.  */
+
+int warn_undefined_variables_flag;
+
+/* If nonzero, always build all targets, regardless of whether
+   they appear out of date or not.  */
+
+static int always_make_set = 0;
+int always_make_flag = 0;
+
+/* If nonzero, we're in the "try to rebuild makefiles" phase.  */
+
+int rebuilding_makefiles = 0;
+
+/* Remember the original value of the SHELL variable, from the environment.  */
+
+struct variable shell_var;
+
+/* This character introduces a command: it's the first char on the line.  */
+
+char cmd_prefix = '\t';
+
+#ifdef KMK
+/* Process priority.
+    0 = no change;
+    1 = idle / max nice;
+    2 = below normal / nice 10;
+    3 = normal / nice 0;
+    4 = high / nice -10;
+    5 = realtime / nice -19; */
+
+int process_priority = 0;
+
+/* Process affinity mask; 0 means any CPU. */
+
+int process_affinity = 0;
+#endif /* KMK */
+
+#ifdef CONFIG_WITH_MAKE_STATS
+/* When set, we'll gather expensive statistics like for the heap. */
+
+int make_expensive_statistics = 0;
+#endif
+
+
+
+/* The usage output.  We write it this way to make life easier for the
+   translators, especially those trying to translate to right-to-left
+   languages like Hebrew.  */
+
+static const char *const usage[] =
+  {
+    N_("Options:\n"),
+    N_("\
+  -b, -m                      Ignored for compatibility.\n"),
+    N_("\
+  -B, --always-make           Unconditionally make all targets.\n"),
+    N_("\
+  -C DIRECTORY, --directory=DIRECTORY\n\
+                              Change to DIRECTORY before doing anything.\n"),
+    N_("\
+  -d                          Print lots of debugging information.\n"),
+    N_("\
+  --debug[=FLAGS]             Print various types of debugging information.\n"),
+    N_("\
+  -e, --environment-overrides\n\
+                              Environment variables override makefiles.\n"),
+    N_("\
+  -f FILE, --file=FILE, --makefile=FILE\n\
+                              Read FILE as a makefile.\n"),
+    N_("\
+  -h, --help                  Print this message and exit.\n"),
+    N_("\
+  -i, --ignore-errors         Ignore errors from commands.\n"),
+    N_("\
+  -I DIRECTORY, --include-dir=DIRECTORY\n\
+                              Search DIRECTORY for included makefiles.\n"),
+#ifdef KMK
+    N_("\
+  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg.\n\
+                              The default is the number of active CPUs.\n"),
+#else
+    N_("\
+  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg.\n"),
+#endif 
+    N_("\
+  -k, --keep-going            Keep going when some targets can't be made.\n"),
+    N_("\
+  -l [N], --load-average[=N], --max-load[=N]\n\
+                              Don't start multiple jobs unless load is below N.\n"),
+    N_("\
+  -L, --check-symlink-times   Use the latest mtime between symlinks and target.\n"),
+    N_("\
+  -n, --just-print, --dry-run, --recon\n\
+                              Don't actually run any commands; just print them.\n"),
+    N_("\
+  -o FILE, --old-file=FILE, --assume-old=FILE\n\
+                              Consider FILE to be very old and don't remake it.\n"),
+    N_("\
+  -p, --print-data-base       Print make's internal database.\n"),
+    N_("\
+  -q, --question              Run no commands; exit status says if up to date.\n"),
+    N_("\
+  -r, --no-builtin-rules      Disable the built-in implicit rules.\n"),
+    N_("\
+  -R, --no-builtin-variables  Disable the built-in variable settings.\n"),
+    N_("\
+  -s, --silent, --quiet       Don't echo commands.\n"),
+    N_("\
+  -S, --no-keep-going, --stop\n\
+                              Turns off -k.\n"),
+    N_("\
+  -t, --touch                 Touch targets instead of remaking them.\n"),
+    N_("\
+  -v, --version               Print the version number of make and exit.\n"),
+    N_("\
+  -w, --print-directory       Print the current directory.\n"),
+    N_("\
+  --no-print-directory        Turn off -w, even if it was turned on implicitly.\n"),
+    N_("\
+  -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE\n\
+                              Consider FILE to be infinitely new.\n"),
+    N_("\
+  --warn-undefined-variables  Warn when an undefined variable is referenced.\n"),
+#ifdef KMK
+    N_("\
+  --affinity=mask             Sets the CPU affinity on some hosts.\n"),
+    N_("\
+  --priority=1-5              Sets the process priority / nice level:\n\
+                                1 = idle / max nice;\n\
+                                2 = below normal / nice 10;\n\
+                                3 = normal / nice 0;\n\
+                                4 = high / nice -10;\n\
+                                5 = realtime / nice -19;\n"),
+#endif /* KMK */
+#ifdef CONFIG_PRETTY_COMMAND_PRINTING
+    N_("\
+  --pretty-command-printing   Makes the command echo easier to read.\n"),
+#endif
+#ifdef CONFIG_WITH_MAKE_STATS
+    N_("\
+  --statistics                Gather extra statistics for $(make-stats ).\n"),
+#endif
+    NULL
+  };
+
+/* The table of command switches.  */
+
+static const struct command_switch switches[] =
+  {
+    { 'b', ignore, 0, 0, 0, 0, 0, 0, 0 },
+    { 'B', flag, &always_make_set, 1, 1, 0, 0, 0, "always-make" },
+    { 'C', filename, &directories, 0, 0, 0, 0, 0, "directory" },
+    { 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0 },
+    { CHAR_MAX+1, string, &db_flags, 1, 1, 0, "basic", 0, "debug" },
+#ifdef WINDOWS32
+    { 'D', flag, &suspend_flag, 1, 1, 0, 0, 0, "suspend-for-debug" },
+#endif
+    { 'e', flag, &env_overrides, 1, 1, 0, 0, 0, "environment-overrides", },
+    { 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file" },
+    { 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, "help" },
+    { 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, "ignore-errors" },
+    { 'I', filename, &include_directories, 1, 1, 0, 0, 0,
+      "include-dir" },
+    { 'j', positive_int, &job_slots, 1, 1, 0, &inf_jobs, &default_job_slots,
+      "jobs" },
+    { CHAR_MAX+2, string, &jobserver_fds, 1, 1, 0, 0, 0, "jobserver-fds" },
+    { 'k', flag, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag,
+      "keep-going" },
+#ifndef NO_FLOAT
+    { 'l', floating, &max_load_average, 1, 1, 0, &default_load_average,
+      &default_load_average, "load-average" },
+#else
+    { 'l', positive_int, &max_load_average, 1, 1, 0, &default_load_average,
+      &default_load_average, "load-average" },
+#endif
+    { 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, "check-symlink-times" },
+    { 'm', ignore, 0, 0, 0, 0, 0, 0, 0 },
+    { 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, "just-print" },
+    { 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" },
+    { 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, "print-data-base" },
+#ifdef CONFIG_PRETTY_COMMAND_PRINTING
+    { CHAR_MAX+10, flag, (char *) &pretty_command_printing, 1, 1, 1, 0, 0,
+       "pretty-command-printing" },
+#endif
+#ifdef KMK
+    { CHAR_MAX+11, positive_int, (char *) &process_priority, 1, 1, 0,
+      (char *) &process_priority, (char *) &process_priority, "priority" },
+    { CHAR_MAX+12, positive_int, (char *) &process_affinity, 1, 1, 0,
+      (char *) &process_affinity, (char *) &process_affinity, "affinity" },
+#endif
+    { 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question" },
+    { 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules" },
+    { 'R', flag, &no_builtin_variables_flag, 1, 1, 0, 0, 0,
+      "no-builtin-variables" },
+    { 's', flag, &silent_flag, 1, 1, 0, 0, 0, "silent" },
+    { 'S', flag_off, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag,
+      "no-keep-going" },
+#ifdef KMK
+    { CHAR_MAX+14, flag, (char *) &make_expensive_statistics, 1, 1, 1, 0, 0,
+       "statistics" },
+#endif
+    { 't', flag, &touch_flag, 1, 1, 1, 0, 0, "touch" },
+    { 'v', flag, &print_version_flag, 1, 1, 0, 0, 0, "version" },
+    { CHAR_MAX+3, string, &verbosity_flags, 1, 1, 0, 0, 0,
+      "verbosity" },
+    { 'w', flag, &print_directory_flag, 1, 1, 0, 0, 0, "print-directory" },
+    { CHAR_MAX+4, flag, &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
+      "no-print-directory" },
+    { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" },
+    { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
+      "warn-undefined-variables" },
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+  };
+
+/* Secondary long names for options.  */
+
+static struct option long_option_aliases[] =
+  {
+    { "quiet",		no_argument,		0, 's' },
+    { "stop",		no_argument,		0, 'S' },
+    { "new-file",	required_argument,	0, 'W' },
+    { "assume-new",	required_argument,	0, 'W' },
+    { "assume-old",	required_argument,	0, 'o' },
+    { "max-load",	optional_argument,	0, 'l' },
+    { "dry-run",	no_argument,		0, 'n' },
+    { "recon",		no_argument,		0, 'n' },
+    { "makefile",	required_argument,	0, 'f' },
+  };
+
+/* List of goal targets.  */
+
+static struct dep *goals, *lastgoal;
+
+/* List of variables which were defined on the command line
+   (or, equivalently, in MAKEFLAGS).  */
+
+struct command_variable
+  {
+    struct command_variable *next;
+    struct variable *variable;
+  };
+static struct command_variable *command_variables;
+
+
+/* The name we were invoked with.  */
+
+char *program;
+
+/* Our current directory before processing any -C options.  */
+
+char *directory_before_chdir;
+
+/* Our current directory after processing all -C options.  */
+
+char *starting_directory;
+
+/* Value of the MAKELEVEL variable at startup (or 0).  */
+
+unsigned int makelevel;
+
+/* First file defined in the makefile whose name does not
+   start with `.'.  This is the default to remake if the
+   command line does not specify.  */
+
+struct file *default_goal_file;
+
+/* Pointer to the value of the .DEFAULT_GOAL special
+   variable.  */
+char ** default_goal_name;
+
+/* Pointer to structure for the file .DEFAULT
+   whose commands are used for any file that has none of its own.
+   This is zero if the makefiles do not define .DEFAULT.  */
+
+struct file *default_file;
+
+/* Nonzero if we have seen the magic `.POSIX' target.
+   This turns on pedantic compliance with POSIX.2.  */
+
+int posix_pedantic;
+
+/* Nonzero if we have seen the '.SECONDEXPANSION' target.
+   This turns on secondary expansion of prerequisites.  */
+
+int second_expansion;
+
+#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
+/* Nonzero if we have seen the '.SECONDTARGETEXPANSION' target.
+   This turns on secondary expansion of targets.  */
+
+int second_target_expansion;
+#endif
+
+#ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL
+/* Nonzero if we have seen the `.NOTPARALLEL' target.
+   This turns off parallel builds for this invocation of make.  */
+
+#else  /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+
+/* Negative if we have seen the `.NOTPARALLEL' target with an
+   empty dependency list.
+
+   Zero if no `.NOTPARALLEL' or no file in the dependency list
+   is being executed.
+
+   Positive when a file in the `.NOTPARALLEL' dependency list
+   is in progress, the value is the number of notparallel files
+   in progress (running or queued for running).
+
+   In short, any nonzero value means no more parallel builing. */
+#endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */
+
+int not_parallel;
+
+/* Nonzero if some rule detected clock skew; we keep track so (a) we only
+   print one warning about it during the run, and (b) we can print a final
+   warning at the end of the run. */
+
+int clock_skew_detected;
+
+
+/* Mask of signals that are being caught with fatal_error_signal.  */
+
+#ifdef	POSIX
+sigset_t fatal_signal_set;
+#else
+# ifdef	HAVE_SIGSETMASK
+int fatal_signal_mask;
+# endif
+#endif
+
+#if !defined HAVE_BSD_SIGNAL && !defined bsd_signal
+# if !defined HAVE_SIGACTION
+#  define bsd_signal signal
+# else
+typedef RETSIGTYPE (*bsd_signal_ret_t) ();
+
+static bsd_signal_ret_t
+bsd_signal (int sig, bsd_signal_ret_t func)
+{
+  struct sigaction act, oact;
+  act.sa_handler = func;
+  act.sa_flags = SA_RESTART;
+  sigemptyset (&act.sa_mask);
+  sigaddset (&act.sa_mask, sig);
+  if (sigaction (sig, &act, &oact) != 0)
+    return SIG_ERR;
+  return oact.sa_handler;
+}
+# endif
+#endif
+
+static void
+initialize_global_hash_tables (void)
+{
+  init_hash_global_variable_set ();
+  strcache_init ();
+  init_hash_files ();
+  hash_init_directories ();
+  hash_init_function_table ();
+}
+
+static const char *
+expand_command_line_file (char *name)
+{
+  const char *cp;
+  char *expanded = 0;
+
+  if (name[0] == '\0')
+    fatal (NILF, _("empty string invalid as file name"));
+
+  if (name[0] == '~')
+    {
+      expanded = tilde_expand (name);
+      if (expanded != 0)
+	name = expanded;
+    }
+
+  /* This is also done in parse_file_seq, so this is redundant
+     for names read from makefiles.  It is here for names passed
+     on the command line.  */
+  while (name[0] == '.' && name[1] == '/' && name[2] != '\0')
+    {
+      name += 2;
+      while (*name == '/')
+	/* Skip following slashes: ".//foo" is "foo", not "/foo".  */
+	++name;
+    }
+
+  if (*name == '\0')
+    {
+      /* It was all slashes!  Move back to the dot and truncate
+	 it after the first slash, so it becomes just "./".  */
+      do
+	--name;
+      while (name[0] != '.');
+      name[2] = '\0';
+    }
+
+  cp = strcache_add (name);
+
+  if (expanded)
+    free (expanded);
+
+  return cp;
+}
+
+/* Toggle -d on receipt of SIGUSR1.  */
+
+#ifdef SIGUSR1
+static RETSIGTYPE
+debug_signal_handler (int sig UNUSED)
+{
+  db_level = db_level ? DB_NONE : DB_BASIC;
+}
+#endif
+
+static void
+decode_debug_flags (void)
+{
+  const char **pp;
+
+  if (debug_flag)
+    db_level = DB_ALL;
+
+  if (!db_flags)
+    return;
+
+  for (pp=db_flags->list; *pp; ++pp)
+    {
+      const char *p = *pp;
+
+      while (1)
+        {
+          switch (tolower (p[0]))
+            {
+            case 'a':
+              db_level |= DB_ALL;
+              break;
+            case 'b':
+              db_level |= DB_BASIC;
+              break;
+            case 'i':
+              db_level |= DB_BASIC | DB_IMPLICIT;
+              break;
+            case 'j':
+              db_level |= DB_JOBS;
+              break;
+            case 'm':
+              db_level |= DB_BASIC | DB_MAKEFILES;
+              break;
+            case 'v':
+              db_level |= DB_BASIC | DB_VERBOSE;
+              break;
+#ifdef DB_KMK
+            case 'k':
+              db_level |= DB_KMK;
+              break;
+#endif
+            default:
+              fatal (NILF, _("unknown debug level specification `%s'"), p);
+            }
+
+          while (*(++p) != '\0')
+            if (*p == ',' || *p == ' ')
+              break;
+
+          if (*p == '\0')
+            break;
+
+          ++p;
+        }
+    }
+}
+
+
+#ifdef KMK
+static void
+set_make_priority_and_affinity (void)
+{
+#ifdef WINDOWS32
+  DWORD dwPriority;
+  if (process_affinity)
+    if (!SetProcessAffinityMask (GetCurrentProcess (), process_affinity))
+      fprintf (stderr, "warning: SetPriorityClass (,%#x) failed with last error %d\n",
+               process_affinity, GetLastError());
+
+  switch (process_priority)
+    {
+      case 0:     return;
+      case 1:     dwPriority = IDLE_PRIORITY_CLASS; break;
+      case 2:     dwPriority = BELOW_NORMAL_PRIORITY_CLASS; break;
+      case 3:     dwPriority = NORMAL_PRIORITY_CLASS; break;
+      case 4:     dwPriority = HIGH_PRIORITY_CLASS; break;
+      case 5:     dwPriority = REALTIME_PRIORITY_CLASS; break;
+      default:    fatal(NILF, _("invalid priority %d\n"), process_priority);
+    }
+  if (!SetPriorityClass (GetCurrentProcess (), dwPriority))
+    fprintf (stderr, "warning: SetPriorityClass (,%#x) failed with last error %d\n",
+             dwPriority, GetLastError ());
+
+#else /*#elif HAVE_NICE */
+  int nice_level = 0;
+  switch (process_priority)
+    {
+      case 0:     return;
+      case 1:     nice_level = 19; break;
+      case 2:     nice_level = 10; break;
+      case 3:     nice_level = 0; break;
+      case 4:     nice_level = -10; break;
+      case 5:     nice_level = -19; break;
+      default:    fatal(NILF, _("invalid priority %d\n"), process_priority);
+    }
+  errno = 0;
+  if (nice (nice_level) == -1 && errno != 0)
+    fprintf (stderr, "warning: nice (%d) failed: %s\n", nice, strerror (errno));
+#endif
+}
+#endif
+
+
+#ifdef WINDOWS32
+/*
+ * HANDLE runtime exceptions by avoiding a requestor on the GUI. Capture
+ * exception and print it to stderr instead.
+ *
+ * If ! DB_VERBOSE, just print a simple message and exit.
+ * If DB_VERBOSE, print a more verbose message.
+ * If compiled for DEBUG, let exception pass through to GUI so that
+ *   debuggers can attach.
+ */
+LONG WINAPI
+handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo )
+{
+  PEXCEPTION_RECORD exrec = exinfo->ExceptionRecord;
+  LPSTR cmdline = GetCommandLine();
+  LPSTR prg = strtok(cmdline, " ");
+  CHAR errmsg[1024];
+#ifdef USE_EVENT_LOG
+  HANDLE hEventSource;
+  LPTSTR lpszStrings[1];
+#endif
+
+  if (! ISDB (DB_VERBOSE))
+    {
+      sprintf(errmsg,
+              _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%lx)\n"),
+              prg, exrec->ExceptionCode, (DWORD)exrec->ExceptionAddress);
+      fprintf(stderr, errmsg);
+      exit(255);
+    }
+
+  sprintf(errmsg,
+          _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = %lx\n"),
+          prg, exrec->ExceptionCode, exrec->ExceptionFlags,
+          (DWORD)exrec->ExceptionAddress);
+
+  if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
+      && exrec->NumberParameters >= 2)
+    sprintf(&errmsg[strlen(errmsg)],
+            (exrec->ExceptionInformation[0]
+             ? _("Access violation: write operation at address %lx\n")
+             : _("Access violation: read operation at address %lx\n")),
+            exrec->ExceptionInformation[1]);
+
+  /* turn this on if we want to put stuff in the event log too */
+#ifdef USE_EVENT_LOG
+  hEventSource = RegisterEventSource(NULL, "GNU Make");
+  lpszStrings[0] = errmsg;
+
+  if (hEventSource != NULL)
+    {
+      ReportEvent(hEventSource,         /* handle of event source */
+                  EVENTLOG_ERROR_TYPE,  /* event type */
+                  0,                    /* event category */
+                  0,                    /* event ID */
+                  NULL,                 /* current user's SID */
+                  1,                    /* strings in lpszStrings */
+                  0,                    /* no bytes of raw data */
+                  lpszStrings,          /* array of error strings */
+                  NULL);                /* no raw data */
+
+      (VOID) DeregisterEventSource(hEventSource);
+    }
+#endif
+
+  /* Write the error to stderr too */
+  fprintf(stderr, errmsg);
+
+#ifdef DEBUG
+  return EXCEPTION_CONTINUE_SEARCH;
+#else
+  exit(255);
+  return (255); /* not reached */
+#endif
+}
+
+/*
+ * On WIN32 systems we don't have the luxury of a /bin directory that
+ * is mapped globally to every drive mounted to the system. Since make could
+ * be invoked from any drive, and we don't want to propogate /bin/sh
+ * to every single drive. Allow ourselves a chance to search for
+ * a value for default shell here (if the default path does not exist).
+ */
+
+int
+find_and_set_default_shell (const char *token)
+{
+  int sh_found = 0;
+  char *atoken = 0;
+  char *search_token;
+  char *tokend;
+  PATH_VAR(sh_path);
+  extern char *default_shell;
+
+  if (!token)
+    search_token = default_shell;
+  else
+    atoken = search_token = xstrdup (token);
+
+  /* If the user explicitly requests the DOS cmd shell, obey that request.
+     However, make sure that's what they really want by requiring the value
+     of SHELL either equal, or have a final path element of, "cmd" or
+     "cmd.exe" case-insensitive.  */
+  tokend = search_token + strlen (search_token) - 3;
+  if (((tokend == search_token
+        || (tokend > search_token
+            && (tokend[-1] == '/' || tokend[-1] == '\\')))
+       && !strcasecmp (tokend, "cmd"))
+      || ((tokend - 4 == search_token
+           || (tokend - 4 > search_token
+               && (tokend[-5] == '/' || tokend[-5] == '\\')))
+          && !strcasecmp (tokend - 4, "cmd.exe"))) {
+    batch_mode_shell = 1;
+    unixy_shell = 0;
+    sprintf (sh_path, "%s", search_token);
+    default_shell = xstrdup (w32ify (sh_path, 0));
+    DB (DB_VERBOSE,
+        (_("find_and_set_shell setting default_shell = %s\n"), default_shell));
+    sh_found = 1;
+  } else if (!no_default_sh_exe &&
+             (token == NULL || !strcmp (search_token, default_shell))) {
+    /* no new information, path already set or known */
+    sh_found = 1;
+  } else if (file_exists_p (search_token)) {
+    /* search token path was found */
+    sprintf (sh_path, "%s", search_token);
+    default_shell = xstrdup (w32ify (sh_path, 0));
+    DB (DB_VERBOSE,
+        (_("find_and_set_shell setting default_shell = %s\n"), default_shell));
+    sh_found = 1;
+  } else {
+    char *p;
+    struct variable *v = lookup_variable (STRING_SIZE_TUPLE ("PATH"));
+
+    /* Search Path for shell */
+    if (v && v->value) {
+      char *ep;
+
+      p  = v->value;
+      ep = strchr (p, PATH_SEPARATOR_CHAR);
+
+      while (ep && *ep) {
+        *ep = '\0';
+
+        if (dir_file_exists_p (p, search_token)) {
+          sprintf (sh_path, "%s/%s", p, search_token);
+          default_shell = xstrdup (w32ify (sh_path, 0));
+          sh_found = 1;
+          *ep = PATH_SEPARATOR_CHAR;
+
+          /* terminate loop */
+          p += strlen (p);
+        } else {
+          *ep = PATH_SEPARATOR_CHAR;
+           p = ++ep;
+        }
+
+        ep = strchr (p, PATH_SEPARATOR_CHAR);
+      }
+
+      /* be sure to check last element of Path */
+      if (p && *p && dir_file_exists_p (p, search_token)) {
+          sprintf (sh_path, "%s/%s", p, search_token);
+          default_shell = xstrdup (w32ify (sh_path, 0));
+          sh_found = 1;
+      }
+
+      if (sh_found)
+        DB (DB_VERBOSE,
+            (_("find_and_set_shell path search set default_shell = %s\n"),
+             default_shell));
+    }
+  }
+
+#if 0/* def KMK - has been fixed in sub_proc.c */
+  /* WORKAROUND:
+    With GNU Make 3.81, this kludge was necessary to get double quotes
+    working correctly again (worked fine with the 3.81beta1 code).
+    beta1 was forcing batch_mode_shell I think, so let's enforce that
+    for the kBuild shell. */
+  if (sh_found && strstr(default_shell, "kmk_ash")) {
+      unixy_shell = 1;
+      batch_mode_shell = 1;
+  } else
+#endif
+  /* naive test */
+  if (!unixy_shell && sh_found &&
+      (strstr (default_shell, "sh") || strstr (default_shell, "SH"))) {
+    unixy_shell = 1;
+    batch_mode_shell = 0;
+  }
+
+#ifdef BATCH_MODE_ONLY_SHELL
+  batch_mode_shell = 1;
+#endif
+
+  if (atoken)
+    free (atoken);
+
+  return (sh_found);
+}
+
+/* bird: */
+#ifdef CONFIG_NEW_WIN32_CTRL_EVENT
+#include <process.h>
+static UINT g_tidMainThread = 0;
+static int volatile g_sigPending = 0; /* lazy bird */
+# ifndef _M_IX86
+static LONG volatile g_lTriggered = 0;
+static CONTEXT g_Ctx;
+# endif
+
+# ifdef _M_IX86
+static __declspec(naked) void dispatch_stub(void)
+{
+    __asm  {
+        pushfd
+        pushad
+        cld
+    }
+    fflush(stdout);
+    /*fprintf(stderr, "dbg: raising %s on the main thread (%d)\n", g_sigPending == SIGINT ? "SIGINT" : "SIGBREAK", _getpid());*/
+    raise(g_sigPending);
+    __asm  {
+        popad
+        popfd
+        ret
+    }
+}
+# else /* !_M_IX86 */
+static void dispatch_stub(void)
+{
+    fflush(stdout);
+    /*fprintf(stderr, "dbg: raising %s on the main thread (%d)\n", g_sigPending == SIGINT ? "SIGINT" : "SIGBREAK", _getpid());*/
+    raise(g_sigPending);
+
+    SetThreadContext(GetCurrentThread(), &g_Ctx);
+    fprintf(stderr, "fatal error: SetThreadContext failed with last error %d\n", GetLastError());
+    for (;;)
+        exit(131);
+}
+# endif /* !_M_IX86 */
+
+static BOOL WINAPI ctrl_event(DWORD CtrlType)
+{
+    int sig = (CtrlType == CTRL_C_EVENT) ? SIGINT : SIGBREAK;
+    HANDLE hThread;
+    CONTEXT Ctx;
+
+#ifndef _M_IX86
+    /* only once. */
+    if (InterlockedExchange(&g_lTriggered, 1))
+    {
+        Sleep(1);
+        return TRUE;
+    }
+#endif
+
+    /* open the main thread and suspend it. */
+    hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, g_tidMainThread);
+    SuspendThread(hThread);
+
+    /* Get the thread context and if we've get a valid Esp, dispatch
+       it on the main thread otherwise raise the signal in the
+       ctrl-event thread (this). */
+    memset(&Ctx, 0, sizeof(Ctx));
+    Ctx.ContextFlags = CONTEXT_FULL;
+    if (GetThreadContext(hThread, &Ctx)
+#ifdef _M_IX86
+        && Ctx.Esp >= 0x1000
+#else
+        && Ctx.Rsp >= 0x1000
+#endif
+       )
+    {
+#ifdef _M_IX86
+        ((uintptr_t *)Ctx.Esp)[-1] = Ctx.Eip;
+        Ctx.Esp -= sizeof(uintptr_t);
+        Ctx.Eip = (uintptr_t)&dispatch_stub;
+#else
+        g_Ctx = Ctx;
+        Ctx.Rsp -= 0x20;
+        Ctx.Rsp &= ~(uintptr_t)0xf;
+        Ctx.Rip = (uintptr_t)&dispatch_stub;
+#endif
+
+        SetThreadContext(hThread, &Ctx);
+        g_sigPending = sig;
+        ResumeThread(hThread);
+        CloseHandle(hThread);
+    }
+    else
+    {
+        fprintf(stderr, "dbg: raising %s on the ctrl-event thread (%d)\n", sig == SIGINT ? "SIGINT" : "SIGBREAK", _getpid());
+        raise(sig);
+        ResumeThread(hThread);
+        CloseHandle(hThread);
+        exit(130);
+    }
+
+    Sleep(1);
+    return TRUE;
+}
+#endif /* CONFIG_NEW_WIN32_CTRL_EVENT */
+
+#endif  /* WINDOWS32 */
+
+#ifdef KMK
+/* Determins the number of CPUs that are currently online.
+   This is used to setup the default number of job slots. */
+static int 
+get_online_cpu_count(void)
+{
+# ifdef WINDOWS32
+    /* Windows: Count the active CPUs. */
+    int cpus, i;
+    SYSTEM_INFO si;
+    GetSystemInfo(&si);
+    for (i = cpus = 0; i < sizeof(si.dwActiveProcessorMask) * 8; i++)
+      {
+        if (si.dwActiveProcessorMask & 1)
+          cpus++;
+        si.dwActiveProcessorMask >>= 1;
+      }
+    return cpus ? cpus : 1;
+
+# elif defined(__OS2__)
+    /* OS/2: Count the active CPUs. */
+    int cpus, i, j;
+    MPAFFINITY mp;
+    if (DosQueryThreadAffinity(AFNTY_SYSTEM, &mp))
+      return 1;
+    for (j = cpus = 0; j < sizeof(mp.mask) / sizeof(mp.mask[0]); j++)
+      for (i = 0; i < 32; i++)
+        if (mp.mask[j] & (1UL << i))
+          cpus++;
+    return cpus ? cpus : 1;
+
+# else 
+  /* UNIX like systems, try sysconf and sysctl. */
+  int cpus = -1;
+#  if defined(CTL_HW)
+  int mib[2];
+  size_t sz;
+#  endif 
+
+#  ifdef _SC_NPROCESSORS_ONLN
+  cpus = sysconf(_SC_NPROCESSORS_ONLN);
+  if (cpus >= 1)
+      return cpus;
+  cpus = -1;
+#  endif
+
+#  if defined(CTL_HW)
+#   ifdef HW_AVAILCPU
+  sz = sizeof(cpus);
+  mib[0] = CTL_HW;
+  mib[1] = HW_AVAILCPU;
+  if (!sysctl(mib, 2, &cpus, &sz, NULL, 0)
+      && cpus >= 1)
+    return cpus;
+  cpus = -1;
+#   endif /* HW_AVAILCPU */
+
+  sz = sizeof(cpus);
+  mib[0] = CTL_HW;
+  mib[1] = HW_NCPU;
+  if (!sysctl(mib, 2, &cpus, &sz, NULL, 0)
+      && cpus >= 1)
+    return cpus;
+  cpus = -1;
+#  endif /* CTL_HW */
+
+  /* no idea / failure, just return 1. */
+  return 1;
+# endif
+}
+#endif /* KMK */
+
+#ifdef __MSDOS__
+static void
+msdos_return_to_initial_directory (void)
+{
+  if (directory_before_chdir)
+    chdir (directory_before_chdir);
+}
+#endif  /* __MSDOS__ */
+
+#ifndef _MSC_VER /* bird */
+char *mktemp (char *template);
+#endif
+int mkstemp (char *template);
+
+FILE *
+open_tmpfile(char **name, const char *template)
+{
+#ifdef HAVE_FDOPEN
+  int fd;
+#endif
+
+#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
+# define TEMPLATE_LEN   strlen (template)
+#else
+# define TEMPLATE_LEN   L_tmpnam
+#endif
+  *name = xmalloc (TEMPLATE_LEN + 1);
+  strcpy (*name, template);
+
+#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
+  /* It's safest to use mkstemp(), if we can.  */
+  fd = mkstemp (*name);
+  if (fd == -1)
+    return 0;
+  return fdopen (fd, "w");
+#else
+# ifdef HAVE_MKTEMP
+  (void) mktemp (*name);
+# else
+  (void) tmpnam (*name);
+# endif
+
+# ifdef HAVE_FDOPEN
+  /* Can't use mkstemp(), but guard against a race condition.  */
+  fd = open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600);
+  if (fd == -1)
+    return 0;
+  return fdopen (fd, "w");
+# else
+  /* Not secure, but what can we do?  */
+  return fopen (*name, "w");
+# endif
+#endif
+}
+
+
+#ifdef _AMIGA
+int
+main (int argc, char **argv)
+#else
+int
+main (int argc, char **argv, char **envp)
+#endif
+{
+  static char *stdin_nm = 0;
+  int makefile_status = MAKE_SUCCESS;
+  struct dep *read_makefiles;
+  PATH_VAR (current_directory);
+  unsigned int restarts = 0;
+#ifdef WINDOWS32
+  char *unix_path = NULL;
+  char *windows32_path = NULL;
+
+#ifndef ELECTRIC_HEAP /* Drop this because it prevent JIT debugging. */
+  SetUnhandledExceptionFilter(handle_runtime_exceptions);
+#endif /* !ELECTRICT_HEAP */
+
+  /* start off assuming we have no shell */
+  unixy_shell = 0;
+  no_default_sh_exe = 1;
+#endif
+
+#ifdef SET_STACK_SIZE
+ /* Get rid of any avoidable limit on stack size.  */
+  {
+    struct rlimit rlim;
+
+    /* Set the stack limit huge so that alloca does not fail.  */
+    if (getrlimit (RLIMIT_STACK, &rlim) == 0)
+      {
+        rlim.rlim_cur = rlim.rlim_max;
+        setrlimit (RLIMIT_STACK, &rlim);
+      }
+  }
+#endif
+
+#ifdef HAVE_ATEXIT
+  atexit (close_stdout);
+#endif
+
+  /* Needed for OS/2 */
+  initialize_main(&argc, &argv);
+
+#ifdef KMK
+  init_kbuild (argc, argv);
+#endif
+
+  default_goal_file = 0;
+  reading_file = 0;
+
+#if defined (__MSDOS__) && !defined (_POSIX_SOURCE)
+  /* Request the most powerful version of `system', to
+     make up for the dumb default shell.  */
+  __system_flags = (__system_redirect
+		    | __system_use_shell
+		    | __system_allow_multiple_cmds
+		    | __system_allow_long_cmds
+		    | __system_handle_null_commands
+		    | __system_emulate_chdir);
+
+#endif
+
+  /* Set up gettext/internationalization support.  */
+  setlocale (LC_ALL, "");
+#ifdef LOCALEDIR /* bird */
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+#endif
+
+#ifdef	POSIX
+  sigemptyset (&fatal_signal_set);
+#define	ADD_SIG(sig)	sigaddset (&fatal_signal_set, sig)
+#else
+#ifdef	HAVE_SIGSETMASK
+  fatal_signal_mask = 0;
+#define	ADD_SIG(sig)	fatal_signal_mask |= sigmask (sig)
+#else
+#define	ADD_SIG(sig)
+#endif
+#endif
+
+#define	FATAL_SIG(sig)							      \
+  if (bsd_signal (sig, fatal_error_signal) == SIG_IGN)			      \
+    bsd_signal (sig, SIG_IGN);						      \
+  else									      \
+    ADD_SIG (sig);
+
+#ifdef SIGHUP
+  FATAL_SIG (SIGHUP);
+#endif
+#ifdef SIGQUIT
+  FATAL_SIG (SIGQUIT);
+#endif
+  FATAL_SIG (SIGINT);
+  FATAL_SIG (SIGTERM);
+
+#ifdef __MSDOS__
+  /* Windows 9X delivers FP exceptions in child programs to their
+     parent!  We don't want Make to die when a child divides by zero,
+     so we work around that lossage by catching SIGFPE.  */
+  FATAL_SIG (SIGFPE);
+#endif
+
+#ifdef	SIGDANGER
+  FATAL_SIG (SIGDANGER);
+#endif
+#ifdef SIGXCPU
+  FATAL_SIG (SIGXCPU);
+#endif
+#ifdef SIGXFSZ
+  FATAL_SIG (SIGXFSZ);
+#endif
+
+#ifdef CONFIG_NEW_WIN32_CTRL_EVENT
+  /* bird: dispatch signals in our own way to try avoid deadlocks. */
+  g_tidMainThread = GetCurrentThreadId ();
+  SetConsoleCtrlHandler (ctrl_event, TRUE);
+#endif /* CONFIG_NEW_WIN32_CTRL_EVENT */
+
+#undef	FATAL_SIG
+
+  /* Do not ignore the child-death signal.  This must be done before
+     any children could possibly be created; otherwise, the wait
+     functions won't work on systems with the SVR4 ECHILD brain
+     damage, if our invoker is ignoring this signal.  */
+
+#ifdef HAVE_WAIT_NOHANG
+# if defined SIGCHLD
+  (void) bsd_signal (SIGCHLD, SIG_DFL);
+# endif
+# if defined SIGCLD && SIGCLD != SIGCHLD
+  (void) bsd_signal (SIGCLD, SIG_DFL);
+# endif
+#endif
+
+  /* Make sure stdout is line-buffered.  */
+
+#ifdef HAVE_SETVBUF
+# ifdef SETVBUF_REVERSED
+  setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
+# else	/* setvbuf not reversed.  */
+  /* Some buggy systems lose if we pass 0 instead of allocating ourselves.  */
+  setvbuf (stdout, 0, _IOLBF, BUFSIZ);
+# endif	/* setvbuf reversed.  */
+#elif HAVE_SETLINEBUF
+  setlinebuf (stdout);
+#endif	/* setlinebuf missing.  */
+
+  /* Figure out where this program lives.  */
+
+  if (argv[0] == 0)
+    argv[0] = "";
+  if (argv[0][0] == '\0')
+#ifdef KMK
+    program = "kmk";
+#else
+    program = "make";
+#endif
+  else
+    {
+#ifdef VMS
+      program = strrchr (argv[0], ']');
+#else
+      program = strrchr (argv[0], '/');
+#endif
+#if defined(__MSDOS__) || defined(__EMX__)
+      if (program == 0)
+	program = strrchr (argv[0], '\\');
+      else
+	{
+	  /* Some weird environments might pass us argv[0] with
+	     both kinds of slashes; we must find the rightmost.  */
+	  char *p = strrchr (argv[0], '\\');
+	  if (p && p > program)
+	    program = p;
+	}
+      if (program == 0 && argv[0][1] == ':')
+	program = argv[0] + 1;
+#endif
+#ifdef WINDOWS32
+      if (program == 0)
+        {
+          /* Extract program from full path */
+          int argv0_len;
+          program = strrchr (argv[0], '\\');
+          if (program)
+            {
+              argv0_len = strlen(program);
+              if (argv0_len > 4 && streq (&program[argv0_len - 4], ".exe"))
+                /* Remove .exe extension */
+                program[argv0_len - 4] = '\0';
+            }
+        }
+#endif
+      if (program == 0)
+	program = argv[0];
+      else
+	++program;
+    }
+
+  /* Set up to access user data (files).  */
+  user_access ();
+
+  initialize_global_hash_tables ();
+
+  /* Figure out where we are.  */
+
+#ifdef WINDOWS32
+  if (getcwd_fs (current_directory, GET_PATH_MAX) == 0)
+#else
+  if (getcwd (current_directory, GET_PATH_MAX) == 0)
+#endif
+    {
+#ifdef	HAVE_GETCWD
+      perror_with_name ("getcwd", "");
+#else
+      error (NILF, "getwd: %s", current_directory);
+#endif
+      current_directory[0] = '\0';
+      directory_before_chdir = 0;
+    }
+  else
+    directory_before_chdir = xstrdup (current_directory);
+#ifdef  __MSDOS__
+  /* Make sure we will return to the initial directory, come what may.  */
+  atexit (msdos_return_to_initial_directory);
+#endif
+
+  /* Initialize the special variables.  */
+  define_variable (".VARIABLES", 10, "", o_default, 0)->special = 1;
+  /* define_variable (".TARGETS", 8, "", o_default, 0)->special = 1; */
+
+  /* Set up .FEATURES */
+  define_variable (".FEATURES", 9,
+                   "target-specific order-only second-expansion else-if",
+                   o_default, 0);
+#ifndef NO_ARCHIVES
+  do_variable_definition (NILF, ".FEATURES", "archives",
+                          o_default, f_append, 0);
+#endif
+#ifdef MAKE_JOBSERVER
+  do_variable_definition (NILF, ".FEATURES", "jobserver",
+                          o_default, f_append, 0);
+#endif
+#ifdef MAKE_SYMLINKS
+  do_variable_definition (NILF, ".FEATURES", "check-symlink",
+                          o_default, f_append, 0);
+#endif
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  do_variable_definition (NILF, ".FEATURES", "explicit-multitarget",
+                          o_default, f_append, 0);
+#endif
+#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+  do_variable_definition (NILF, ".FEATURES", "prepend-assignment",
+                          o_default, f_append, 0);
+#endif
+
+#ifdef KMK
+  /* Initialize the default number of jobs to the cpu/core/smt count. */
+  default_job_slots = job_slots = get_online_cpu_count ();
+#endif /* KMK */
+
+  /* Read in variables from the environment.  It is important that this be
+     done before $(MAKE) is figured out so its definitions will not be
+     from the environment.  */
+
+#ifndef _AMIGA
+  {
+    unsigned int i;
+
+    for (i = 0; envp[i] != 0; ++i)
+      {
+        int do_not_define = 0;
+        char *ep = envp[i];
+
+        while (*ep != '\0' && *ep != '=')
+          ++ep;
+#ifdef WINDOWS32
+        if (!unix_path && strneq(envp[i], "PATH=", 5))
+          unix_path = ep+1;
+        else if (!strnicmp(envp[i], "Path=", 5)) {
+          do_not_define = 1; /* it gets defined after loop exits */
+          if (!windows32_path)
+            windows32_path = ep+1;
+        }
+#endif
+        /* The result of pointer arithmetic is cast to unsigned int for
+           machines where ptrdiff_t is a different size that doesn't widen
+           the same.  */
+        if (!do_not_define)
+          {
+            struct variable *v;
+
+            v = define_variable (envp[i], (unsigned int) (ep - envp[i]),
+                                 ep + 1, o_env, 1);
+            /* Force exportation of every variable culled from the
+               environment.  We used to rely on target_environment's
+               v_default code to do this.  But that does not work for the
+               case where an environment variable is redefined in a makefile
+               with `override'; it should then still be exported, because it
+               was originally in the environment.  */
+            v->export = v_export;
+
+            /* Another wrinkle is that POSIX says the value of SHELL set in
+               the makefile won't change the value of SHELL given to
+               subprocesses.  */
+            if (streq (v->name, "SHELL"))
+              {
+#ifndef __MSDOS__
+                v->export = v_noexport;
+#endif
+                shell_var.name = "SHELL";
+                shell_var.value = xstrdup (ep + 1);
+              }
+
+            /* If MAKE_RESTARTS is set, remember it but don't export it.  */
+            if (streq (v->name, "MAKE_RESTARTS"))
+              {
+                v->export = v_noexport;
+                restarts = (unsigned int) atoi (ep + 1);
+              }
+          }
+      }
+  }
+#ifdef WINDOWS32
+    /* If we didn't find a correctly spelled PATH we define PATH as
+     * either the first mispelled value or an empty string
+     */
+    if (!unix_path)
+      define_variable("PATH", 4,
+                      windows32_path ? windows32_path : "",
+                      o_env, 1)->export = v_export;
+#endif
+#else /* For Amiga, read the ENV: device, ignoring all dirs */
+    {
+	BPTR env, file, old;
+	char buffer[1024];
+	int len;
+	__aligned struct FileInfoBlock fib;
+
+	env = Lock ("ENV:", ACCESS_READ);
+	if (env)
+	{
+	    old = CurrentDir (DupLock(env));
+	    Examine (env, &fib);
+
+	    while (ExNext (env, &fib))
+	    {
+		if (fib.fib_DirEntryType < 0) /* File */
+		{
+		    /* Define an empty variable. It will be filled in
+			variable_lookup(). Makes startup quite a bit
+			faster. */
+			define_variable (fib.fib_FileName,
+			    strlen (fib.fib_FileName),
+			"", o_env, 1)->export = v_export;
+		}
+	    }
+	    UnLock (env);
+	    UnLock(CurrentDir(old));
+	}
+    }
+#endif
+
+  /* Decode the switches.  */
+
+#ifdef KMK
+  decode_env_switches (STRING_SIZE_TUPLE ("KMK_FLAGS"));
+#else /* !KMK */
+  decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
+#if 0
+  /* People write things like:
+        MFLAGS="CC=gcc -pipe" "CFLAGS=-g"
+     and we set the -p, -i and -e switches.  Doesn't seem quite right.  */
+  decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
+#endif
+#endif /* !KMK */
+  decode_switches (argc, argv, 0);
+#ifdef WINDOWS32
+  if (suspend_flag) {
+        fprintf(stderr, "%s (pid = %ld)\n", argv[0], GetCurrentProcessId());
+        fprintf(stderr, _("%s is suspending for 30 seconds..."), argv[0]);
+        Sleep(30 * 1000);
+        fprintf(stderr, _("done sleep(30). Continuing.\n"));
+  }
+#endif
+
+  decode_debug_flags ();
+
+#ifdef KMK
+  set_make_priority_and_affinity ();
+#endif
+
+  /* Set always_make_flag if -B was given and we've not restarted already.  */
+  always_make_flag = always_make_set && (restarts == 0);
+
+  /* Print version information.  */
+  if (print_version_flag || print_data_base_flag || db_level)
+    {
+      print_version ();
+
+      /* `make --version' is supposed to just print the version and exit.  */
+      if (print_version_flag)
+        die (0);
+    }
+
+#ifndef VMS
+  /* Set the "MAKE_COMMAND" variable to the name we were invoked with.
+     (If it is a relative pathname with a slash, prepend our directory name
+     so the result will run the same program regardless of the current dir.
+     If it is a name with no slash, we can only hope that PATH did not
+     find it in the current directory.)  */
+#ifdef WINDOWS32
+  /*
+   * Convert from backslashes to forward slashes for
+   * programs like sh which don't like them. Shouldn't
+   * matter if the path is one way or the other for
+   * CreateProcess().
+   */
+  if (strpbrk(argv[0], "/:\\") ||
+      strstr(argv[0], "..") ||
+      strneq(argv[0], "//", 2))
+    argv[0] = xstrdup(w32ify(argv[0],1));
+#else /* WINDOWS32 */
+#if defined (__MSDOS__) || defined (__EMX__)
+  if (strchr (argv[0], '\\'))
+    {
+      char *p;
+
+      argv[0] = xstrdup (argv[0]);
+      for (p = argv[0]; *p; p++)
+	if (*p == '\\')
+	  *p = '/';
+    }
+  /* If argv[0] is not in absolute form, prepend the current
+     directory.  This can happen when Make is invoked by another DJGPP
+     program that uses a non-absolute name.  */
+  if (current_directory[0] != '\0'
+      && argv[0] != 0
+      && (argv[0][0] != '/' && (argv[0][0] == '\0' || argv[0][1] != ':'))
+# ifdef __EMX__
+      /* do not prepend cwd if argv[0] contains no '/', e.g. "make" */
+      && (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\') != 0)
+# endif
+      )
+    argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
+#else  /* !__MSDOS__ */
+  if (current_directory[0] != '\0'
+      && argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0
+#ifdef HAVE_DOS_PATHS
+      && (argv[0][0] != '\\' && (!argv[0][0] || argv[0][1] != ':'))
+      && strchr (argv[0], '\\') != 0
+#endif
+      )
+    argv[0] = xstrdup (concat (current_directory, "/", argv[0]));
+#endif /* !__MSDOS__ */
+#endif /* WINDOWS32 */
+#endif
+
+  /* The extra indirection through $(MAKE_COMMAND) is done
+     for hysterical raisins.  */
+  (void) define_variable ("MAKE_COMMAND", 12, argv[0], o_default, 0);
+  (void) define_variable ("MAKE", 4, "$(MAKE_COMMAND)", o_default, 1);
+#ifdef KMK
+  (void) define_variable ("KMK", 3, argv[0], o_default, 1);
+#endif
+
+  if (command_variables != 0)
+    {
+      struct command_variable *cv;
+      struct variable *v;
+      unsigned int len = 0;
+      char *value, *p;
+
+      /* Figure out how much space will be taken up by the command-line
+	 variable definitions.  */
+      for (cv = command_variables; cv != 0; cv = cv->next)
+	{
+	  v = cv->variable;
+	  len += 2 * strlen (v->name);
+	  if (! v->recursive)
+	    ++len;
+	  ++len;
+	  len += 2 * strlen (v->value);
+	  ++len;
+	}
+
+      /* Now allocate a buffer big enough and fill it.  */
+      p = value = alloca (len);
+      for (cv = command_variables; cv != 0; cv = cv->next)
+	{
+	  v = cv->variable;
+	  p = quote_for_env (p, v->name);
+	  if (! v->recursive)
+	    *p++ = ':';
+	  *p++ = '=';
+	  p = quote_for_env (p, v->value);
+	  *p++ = ' ';
+	}
+      p[-1] = '\0';		/* Kill the final space and terminate.  */
+
+      /* Define an unchangeable variable with a name that no POSIX.2
+	 makefile could validly use for its own variable.  */
+      (void) define_variable ("-*-command-variables-*-", 23,
+			      value, o_automatic, 0);
+
+      /* Define the variable; this will not override any user definition.
+         Normally a reference to this variable is written into the value of
+         MAKEFLAGS, allowing the user to override this value to affect the
+         exported value of MAKEFLAGS.  In POSIX-pedantic mode, we cannot
+         allow the user's setting of MAKEOVERRIDES to affect MAKEFLAGS, so
+         a reference to this hidden variable is written instead. */
+#ifdef KMK
+      (void) define_variable ("KMK_OVERRIDES", 13,
+			      "${-*-command-variables-*-}", o_env, 1);
+#else
+      (void) define_variable ("MAKEOVERRIDES", 13,
+			      "${-*-command-variables-*-}", o_env, 1);
+#endif
+    }
+
+  /* If there were -C flags, move ourselves about.  */
+  if (directories != 0)
+    {
+      unsigned int i;
+      for (i = 0; directories->list[i] != 0; ++i)
+        {
+          const char *dir = directories->list[i];
+#ifdef WINDOWS32
+          /* WINDOWS32 chdir() doesn't work if the directory has a trailing '/'
+             But allow -C/ just in case someone wants that.  */
+          {
+            char *p = (char *)dir + strlen (dir) - 1;
+            while (p > dir && (p[0] == '/' || p[0] == '\\'))
+              --p;
+            p[1] = '\0';
+          }
+#endif
+          if (chdir (dir) < 0)
+            pfatal_with_name (dir);
+        }
+    }
+
+#ifdef KMK
+  /* Check for [Mm]akefile.kup and change directory when found.
+     Makefile.kmk overrides Makefile.kup but not plain Makefile.
+     If no -C arguments were given, fake one to indicate chdir. */
+  if (makefiles == 0)
+    {
+      struct stat st;
+      if ((   stat ("Makefile.kup", &st) == 0
+           && S_ISREG (st.st_mode) )
+       || (   stat ("makefile.kup", &st) == 0
+           && S_ISREG (st.st_mode) )
+       && stat ("Makefile.kmk", &st) < 0
+       && stat ("makefile.kmk", &st) < 0)
+        {
+          static char fake_path[3*16 + 32] = "..";
+          char *cur = &fake_path[2];
+          int   up_levels = 1;
+          while (up_levels < 16)
+            {
+              /* File with higher precedence.s */
+              strcpy (cur, "/Makefile.kmk");
+              if (stat (fake_path, &st) == 0)
+                break;
+              strcpy (cur, "/makefile.kmk");
+              if (stat (fake_path, &st) == 0)
+                break;
+
+              /* the .kup files */
+              strcpy (cur, "/Makefile.kup");
+              if (   stat (fake_path, &st) != 0
+                  || !S_ISREG (st.st_mode))
+                {
+                  strcpy (cur, "/makefile.kup");
+                  if (   stat (fake_path, &st) != 0
+                      || !S_ISREG (st.st_mode))
+                    break;
+                }
+
+              /* ok */
+              strcpy (cur, "/..");
+              cur += 3;
+              up_levels++;
+            }
+
+          if (up_levels >= 16)
+            fatal (NILF, _("Makefile.kup recursion is too deep."));
+
+          /* attempt to change to the directory. */
+          *cur = '\0';
+          if (chdir (fake_path) < 0)
+            pfatal_with_name (fake_path);
+
+          /* add the string to the directories. */
+          if (!directories)
+            {
+              directories = xmalloc (sizeof(*directories));
+              directories->list = xmalloc (5 * sizeof (char *));
+              directories->max = 5;
+              directories->idx = 0;
+            }
+          else if (directories->idx == directories->max - 1)
+            {
+              directories->max += 5;
+              directories->list = xrealloc ((void *)directories->list,
+                                   directories->max * sizeof (char *));
+            }
+          directories->list[directories->idx++] = fake_path;
+        }
+    }
+#endif /* KMK */
+
+#ifdef WINDOWS32
+  /*
+   * THIS BLOCK OF CODE MUST COME AFTER chdir() CALL ABOVE IN ORDER
+   * TO NOT CONFUSE THE DEPENDENCY CHECKING CODE IN implicit.c.
+   *
+   * The functions in dir.c can incorrectly cache information for "."
+   * before we have changed directory and this can cause file
+   * lookups to fail because the current directory (.) was pointing
+   * at the wrong place when it was first evaluated.
+   */
+#ifdef KMK /* this is really a candidate for all platforms... */
+  {
+    extern char *default_shell;
+    const char *bin = get_kbuild_bin_path();
+    size_t len = strlen (bin);
+    default_shell = xmalloc (len + sizeof("/kmk_ash.exe"));
+    memcpy (default_shell, bin, len);
+    strcpy (default_shell + len, "/kmk_ash.exe");
+    no_default_sh_exe = 0;
+    batch_mode_shell = 1;
+  }
+#else /* !KMK */
+   no_default_sh_exe = !find_and_set_default_shell(NULL);
+#endif /* !KMK */
+#endif /* WINDOWS32 */
+  /* Figure out the level of recursion.  */
+  {
+    struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME));
+    if (v != 0 && v->value[0] != '\0' && v->value[0] != '-')
+      makelevel = (unsigned int) atoi (v->value);
+    else
+      makelevel = 0;
+  }
+
+  /* Except under -s, always do -w in sub-makes and under -C.  */
+  if (!silent_flag && (directories != 0 || makelevel > 0))
+    print_directory_flag = 1;
+
+  /* Let the user disable that with --no-print-directory.  */
+  if (inhibit_print_directory_flag)
+    print_directory_flag = 0;
+
+  /* If -R was given, set -r too (doesn't make sense otherwise!)  */
+  if (no_builtin_variables_flag)
+    no_builtin_rules_flag = 1;
+
+  /* Construct the list of include directories to search.  */
+
+  construct_include_path (include_directories == 0
+                          ? 0 : include_directories->list);
+
+  /* Figure out where we are now, after chdir'ing.  */
+  if (directories == 0)
+    /* We didn't move, so we're still in the same place.  */
+    starting_directory = current_directory;
+  else
+    {
+#ifdef WINDOWS32
+      if (getcwd_fs (current_directory, GET_PATH_MAX) == 0)
+#else
+      if (getcwd (current_directory, GET_PATH_MAX) == 0)
+#endif
+	{
+#ifdef	HAVE_GETCWD
+	  perror_with_name ("getcwd", "");
+#else
+	  error (NILF, "getwd: %s", current_directory);
+#endif
+	  starting_directory = 0;
+	}
+      else
+	starting_directory = current_directory;
+    }
+
+  (void) define_variable ("CURDIR", 6, current_directory, o_file, 0);
+
+  /* Read any stdin makefiles into temporary files.  */
+
+  if (makefiles != 0)
+    {
+      unsigned int i;
+      for (i = 0; i < makefiles->idx; ++i)
+	if (makefiles->list[i][0] == '-' && makefiles->list[i][1] == '\0')
+	  {
+	    /* This makefile is standard input.  Since we may re-exec
+	       and thus re-read the makefiles, we read standard input
+	       into a temporary file and read from that.  */
+	    FILE *outfile;
+            char *template, *tmpdir;
+
+            if (stdin_nm)
+              fatal (NILF, _("Makefile from standard input specified twice."));
+
+#ifdef VMS
+# define DEFAULT_TMPDIR     "sys$scratch:"
+#else
+# ifdef P_tmpdir
+#  define DEFAULT_TMPDIR    P_tmpdir
+# else
+#  define DEFAULT_TMPDIR    "/tmp"
+# endif
+#endif
+#define DEFAULT_TMPFILE     "GmXXXXXX"
+
+	    if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0')
+#if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__)
+                /* These are also used commonly on these platforms.  */
+                && ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0')
+                && ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0')
+#endif
+               )
+	      tmpdir = DEFAULT_TMPDIR;
+
+            template = alloca (strlen (tmpdir) + sizeof (DEFAULT_TMPFILE) + 1);
+	    strcpy (template, tmpdir);
+
+#ifdef HAVE_DOS_PATHS
+	    if (strchr ("/\\", template[strlen (template) - 1]) == NULL)
+	      strcat (template, "/");
+#else
+# ifndef VMS
+	    if (template[strlen (template) - 1] != '/')
+	      strcat (template, "/");
+# endif /* !VMS */
+#endif /* !HAVE_DOS_PATHS */
+
+	    strcat (template, DEFAULT_TMPFILE);
+	    outfile = open_tmpfile (&stdin_nm, template);
+	    if (outfile == 0)
+	      pfatal_with_name (_("fopen (temporary file)"));
+	    while (!feof (stdin) && ! ferror (stdin))
+	      {
+		char buf[2048];
+		unsigned int n = fread (buf, 1, sizeof (buf), stdin);
+		if (n > 0 && fwrite (buf, 1, n, outfile) != n)
+		  pfatal_with_name (_("fwrite (temporary file)"));
+	      }
+	    fclose (outfile);
+
+	    /* Replace the name that read_all_makefiles will
+	       see with the name of the temporary file.  */
+            makefiles->list[i] = strcache_add (stdin_nm);
+
+	    /* Make sure the temporary file will not be remade.  */
+            {
+              struct file *f = enter_file (strcache_add (stdin_nm));
+              f->updated = 1;
+              f->update_status = 0;
+              f->command_state = cs_finished;
+              /* Can't be intermediate, or it'll be removed too early for
+                 make re-exec.  */
+              f->intermediate = 0;
+              f->dontcare = 0;
+            }
+	  }
+    }
+
+#if !defined(__EMX__) || defined(__KLIBC__) /* Don't use a SIGCHLD handler for good old EMX (bird) */
+#if defined(MAKE_JOBSERVER) || !defined(HAVE_WAIT_NOHANG)
+  /* Set up to handle children dying.  This must be done before
+     reading in the makefiles so that `shell' function calls will work.
+
+     If we don't have a hanging wait we have to fall back to old, broken
+     functionality here and rely on the signal handler and counting
+     children.
+
+     If we're using the jobs pipe we need a signal handler so that
+     SIGCHLD is not ignored; we need it to interrupt the read(2) of the
+     jobserver pipe in job.c if we're waiting for a token.
+
+     If none of these are true, we don't need a signal handler at all.  */
+  {
+    RETSIGTYPE child_handler (int sig);
+# if defined SIGCHLD
+    bsd_signal (SIGCHLD, child_handler);
+# endif
+# if defined SIGCLD && SIGCLD != SIGCHLD
+    bsd_signal (SIGCLD, child_handler);
+# endif
+  }
+#endif
+#endif
+
+  /* Let the user send us SIGUSR1 to toggle the -d flag during the run.  */
+#ifdef SIGUSR1
+  bsd_signal (SIGUSR1, debug_signal_handler);
+#endif
+
+  /* Define the initial list of suffixes for old-style rules.  */
+
+  set_default_suffixes ();
+
+  /* Define the file rules for the built-in suffix rules.  These will later
+     be converted into pattern rules.  We used to do this in
+     install_default_implicit_rules, but since that happens after reading
+     makefiles, it results in the built-in pattern rules taking precedence
+     over makefile-specified suffix rules, which is wrong.  */
+
+  install_default_suffix_rules ();
+
+  /* Define some internal and special variables.  */
+
+  define_automatic_variables ();
+
+  /* Set up the MAKEFLAGS and MFLAGS variables
+     so makefiles can look at them.  */
+
+  define_makeflags (0, 0);
+
+  /* Define the default variables.  */
+  define_default_variables ();
+
+  default_file = enter_file (strcache_add (".DEFAULT"));
+
+  {
+    struct variable *v = define_variable (".DEFAULT_GOAL", 13, "", o_file, 0);
+    default_goal_name = &v->value;
+  }
+
+  /* Read all the makefiles.  */
+
+  read_makefiles
+    = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list);
+
+#ifdef WINDOWS32
+  /* look one last time after reading all Makefiles */
+  if (no_default_sh_exe)
+    no_default_sh_exe = !find_and_set_default_shell(NULL);
+#endif /* WINDOWS32 */
+
+#if defined (__MSDOS__) || defined (__EMX__)
+  /* We need to know what kind of shell we will be using.  */
+  {
+    extern int _is_unixy_shell (const char *_path);
+    struct variable *shv = lookup_variable (STRING_SIZE_TUPLE ("SHELL"));
+    extern int unixy_shell;
+    extern char *default_shell;
+
+    if (shv && *shv->value)
+      {
+	char *shell_path = recursively_expand(shv);
+
+	if (shell_path && _is_unixy_shell (shell_path))
+	  unixy_shell = 1;
+	else
+	  unixy_shell = 0;
+	if (shell_path)
+	  default_shell = shell_path;
+      }
+  }
+#endif /* __MSDOS__ || __EMX__ */
+
+  /* Decode switches again, in case the variables were set by the makefile.  */
+#ifdef KMK
+  decode_env_switches (STRING_SIZE_TUPLE ("KMK_FLAGS"));
+#else /* !KMK */
+  decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
+#if 0
+  decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
+#endif
+#endif /* !KMK */
+
+#if defined (__MSDOS__) || defined (__EMX__)
+  if (job_slots != 1
+# ifdef __EMX__
+      && _osmode != OS2_MODE /* turn off -j if we are in DOS mode */
+# endif
+      )
+    {
+      error (NILF,
+             _("Parallel jobs (-j) are not supported on this platform."));
+      error (NILF, _("Resetting to single job (-j1) mode."));
+      job_slots = 1;
+    }
+#endif
+
+#ifdef MAKE_JOBSERVER
+  /* If the jobserver-fds option is seen, make sure that -j is reasonable.  */
+
+  if (jobserver_fds)
+  {
+    const char *cp;
+    unsigned int ui;
+
+    for (ui=1; ui < jobserver_fds->idx; ++ui)
+      if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui]))
+        fatal (NILF, _("internal error: multiple --jobserver-fds options"));
+
+    /* Now parse the fds string and make sure it has the proper format.  */
+
+    cp = jobserver_fds->list[0];
+
+    if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
+      fatal (NILF,
+             _("internal error: invalid --jobserver-fds string `%s'"), cp);
+
+    DB (DB_JOBS,
+	(_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
+
+    /* The combination of a pipe + !job_slots means we're using the
+       jobserver.  If !job_slots and we don't have a pipe, we can start
+       infinite jobs.  If we see both a pipe and job_slots >0 that means the
+       user set -j explicitly.  This is broken; in this case obey the user
+       (ignore the jobserver pipe for this make) but print a message.  */
+
+    if (job_slots > 0)
+      error (NILF,
+             _("warning: -jN forced in submake: disabling jobserver mode."));
+
+    /* Create a duplicate pipe, that will be closed in the SIGCHLD
+       handler.  If this fails with EBADF, the parent has closed the pipe
+       on us because it didn't think we were a submake.  If so, print a
+       warning then default to -j1.  */
+
+    else if ((job_rfd = dup (job_fds[0])) < 0)
+      {
+        if (errno != EBADF)
+          pfatal_with_name (_("dup jobserver"));
+
+        error (NILF,
+               _("warning: jobserver unavailable: using -j1.  Add `+' to parent make rule."));
+        job_slots = 1;
+      }
+
+    if (job_slots > 0)
+      {
+        close (job_fds[0]);
+        close (job_fds[1]);
+        job_fds[0] = job_fds[1] = -1;
+        free (jobserver_fds->list);
+        free (jobserver_fds);
+        jobserver_fds = 0;
+      }
+  }
+
+  /* If we have >1 slot but no jobserver-fds, then we're a top-level make.
+     Set up the pipe and install the fds option for our children.  */
+
+  if (job_slots > 1)
+    {
+      char *cp;
+      char c = '+';
+
+      if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0)
+	pfatal_with_name (_("creating jobs pipe"));
+
+      /* Every make assumes that it always has one job it can run.  For the
+         submakes it's the token they were given by their parent.  For the
+         top make, we just subtract one from the number the user wants.  We
+         want job_slots to be 0 to indicate we're using the jobserver.  */
+
+      master_job_slots = job_slots;
+
+      while (--job_slots)
+        {
+          int r;
+
+          EINTRLOOP (r, write (job_fds[1], &c, 1));
+          if (r != 1)
+            pfatal_with_name (_("init jobserver pipe"));
+        }
+
+      /* Fill in the jobserver_fds struct for our children.  */
+
+      cp = xmalloc ((sizeof ("1024")*2)+1);
+      sprintf (cp, "%d,%d", job_fds[0], job_fds[1]);
+
+      jobserver_fds = (struct stringlist *)
+                        xmalloc (sizeof (struct stringlist));
+      jobserver_fds->list = xmalloc (sizeof (char *));
+      jobserver_fds->list[0] = cp;
+      jobserver_fds->idx = 1;
+      jobserver_fds->max = 1;
+    }
+#endif
+
+#ifndef MAKE_SYMLINKS
+  if (check_symlink_flag)
+    {
+      error (NILF, _("Symbolic links not supported: disabling -L."));
+      check_symlink_flag = 0;
+    }
+#endif
+
+  /* Set up MAKEFLAGS and MFLAGS again, so they will be right.  */
+
+  define_makeflags (1, 0);
+
+  /* Make each `struct dep' point at the `struct file' for the file
+     depended on.  Also do magic for special targets.  */
+
+  snap_deps ();
+
+  /* Convert old-style suffix rules to pattern rules.  It is important to
+     do this before installing the built-in pattern rules below, so that
+     makefile-specified suffix rules take precedence over built-in pattern
+     rules.  */
+
+  convert_to_pattern ();
+
+  /* Install the default implicit pattern rules.
+     This used to be done before reading the makefiles.
+     But in that case, built-in pattern rules were in the chain
+     before user-defined ones, so they matched first.  */
+
+  install_default_implicit_rules ();
+
+  /* Compute implicit rule limits.  */
+
+  count_implicit_rule_limits ();
+
+  /* Construct the listings of directories in VPATH lists.  */
+
+  build_vpath_lists ();
+
+  /* Mark files given with -o flags as very old and as having been updated
+     already, and files given with -W flags as brand new (time-stamp as far
+     as possible into the future).  If restarts is set we'll do -W later.  */
+
+  if (old_files != 0)
+    {
+      const char **p;
+      for (p = old_files->list; *p != 0; ++p)
+        {
+          struct file *f = enter_file (*p);
+          f->last_mtime = f->mtime_before_update = OLD_MTIME;
+          f->updated = 1;
+          f->update_status = 0;
+          f->command_state = cs_finished;
+        }
+    }
+
+  if (!restarts && new_files != 0)
+    {
+      const char **p;
+      for (p = new_files->list; *p != 0; ++p)
+	{
+	  struct file *f = enter_file (*p);
+	  f->last_mtime = f->mtime_before_update = NEW_MTIME;
+	}
+    }
+
+  /* Initialize the remote job module.  */
+  remote_setup ();
+
+  if (read_makefiles != 0)
+    {
+      /* Update any makefiles if necessary.  */
+
+      FILE_TIMESTAMP *makefile_mtimes = 0;
+      unsigned int mm_idx = 0;
+      char **nargv = argv;
+      int nargc = argc;
+      int orig_db_level = db_level;
+      int status;
+
+      if (! ISDB (DB_MAKEFILES))
+        db_level = DB_NONE;
+
+      DB (DB_BASIC, (_("Updating makefiles....\n")));
+
+      /* Remove any makefiles we don't want to try to update.
+	 Also record the current modtimes so we can compare them later.  */
+      {
+	register struct dep *d, *last;
+	last = 0;
+	d = read_makefiles;
+	while (d != 0)
+	  {
+	    struct file *f = d->file;
+	    if (f->double_colon)
+	      for (f = f->double_colon; f != NULL; f = f->prev)
+		{
+		  if (f->deps == 0 && f->cmds != 0)
+		    {
+		      /* This makefile is a :: target with commands, but
+			 no dependencies.  So, it will always be remade.
+			 This might well cause an infinite loop, so don't
+			 try to remake it.  (This will only happen if
+			 your makefiles are written exceptionally
+			 stupidly; but if you work for Athena, that's how
+			 you write your makefiles.)  */
+
+		      DB (DB_VERBOSE,
+                          (_("Makefile `%s' might loop; not remaking it.\n"),
+                           f->name));
+
+		      if (last == 0)
+			read_makefiles = d->next;
+		      else
+			last->next = d->next;
+
+		      /* Free the storage.  */
+                      free_dep (d);
+
+		      d = last == 0 ? read_makefiles : last->next;
+
+		      break;
+		    }
+		}
+	    if (f == NULL || !f->double_colon)
+	      {
+                makefile_mtimes = xrealloc (makefile_mtimes,
+                                            (mm_idx+1)
+                                            * sizeof (FILE_TIMESTAMP));
+		makefile_mtimes[mm_idx++] = file_mtime_no_search (d->file);
+		last = d;
+		d = d->next;
+	      }
+	  }
+      }
+
+      /* Set up `MAKEFLAGS' specially while remaking makefiles.  */
+      define_makeflags (1, 1);
+
+      rebuilding_makefiles = 1;
+      status = update_goal_chain (read_makefiles);
+      rebuilding_makefiles = 0;
+
+      switch (status)
+	{
+	case 1:
+          /* The only way this can happen is if the user specified -q and asked
+           * for one of the makefiles to be remade as a target on the command
+           * line.  Since we're not actually updating anything with -q we can
+           * treat this as "did nothing".
+           */
+
+	case -1:
+	  /* Did nothing.  */
+	  break;
+
+	case 2:
+	  /* Failed to update.  Figure out if we care.  */
+	  {
+	    /* Nonzero if any makefile was successfully remade.  */
+	    int any_remade = 0;
+	    /* Nonzero if any makefile we care about failed
+	       in updating or could not be found at all.  */
+	    int any_failed = 0;
+	    unsigned int i;
+            struct dep *d;
+
+	    for (i = 0, d = read_makefiles; d != 0; ++i, d = d->next)
+              {
+                /* Reset the considered flag; we may need to look at the file
+                   again to print an error.  */
+                d->file->considered = 0;
+
+                if (d->file->updated)
+                  {
+                    /* This makefile was updated.  */
+                    if (d->file->update_status == 0)
+                      {
+                        /* It was successfully updated.  */
+                        any_remade |= (file_mtime_no_search (d->file)
+                                       != makefile_mtimes[i]);
+                      }
+                    else if (! (d->changed & RM_DONTCARE))
+                      {
+                        FILE_TIMESTAMP mtime;
+                        /* The update failed and this makefile was not
+                           from the MAKEFILES variable, so we care.  */
+                        error (NILF, _("Failed to remake makefile `%s'."),
+                               d->file->name);
+                        mtime = file_mtime_no_search (d->file);
+                        any_remade |= (mtime != NONEXISTENT_MTIME
+                                       && mtime != makefile_mtimes[i]);
+                        makefile_status = MAKE_FAILURE;
+                      }
+                  }
+                else
+                  /* This makefile was not found at all.  */
+                  if (! (d->changed & RM_DONTCARE))
+                    {
+                      /* This is a makefile we care about.  See how much.  */
+                      if (d->changed & RM_INCLUDED)
+                        /* An included makefile.  We don't need
+                           to die, but we do want to complain.  */
+                        error (NILF,
+                               _("Included makefile `%s' was not found."),
+                               dep_name (d));
+                      else
+                        {
+                          /* A normal makefile.  We must die later.  */
+                          error (NILF, _("Makefile `%s' was not found"),
+                                 dep_name (d));
+                          any_failed = 1;
+                        }
+                    }
+              }
+            /* Reset this to empty so we get the right error message below.  */
+            read_makefiles = 0;
+
+	    if (any_remade)
+	      goto re_exec;
+	    if (any_failed)
+	      die (2);
+            break;
+	  }
+
+	case 0:
+	re_exec:
+	  /* Updated successfully.  Re-exec ourselves.  */
+
+	  remove_intermediates (0);
+
+	  if (print_data_base_flag)
+	    print_data_base ();
+
+	  log_working_directory (0);
+
+          clean_jobserver (0);
+
+	  if (makefiles != 0)
+	    {
+	      /* These names might have changed.  */
+	      int i, j = 0;
+	      for (i = 1; i < argc; ++i)
+		if (strneq (argv[i], "-f", 2)) /* XXX */
+		  {
+		    char *p = &argv[i][2];
+		    if (*p == '\0')
+                      /* This cast is OK since we never modify argv.  */
+		      argv[++i] = (char *) makefiles->list[j];
+		    else
+		      argv[i] = xstrdup (concat ("-f", makefiles->list[j], ""));
+		    ++j;
+		  }
+	    }
+
+          /* Add -o option for the stdin temporary file, if necessary.  */
+          if (stdin_nm)
+            {
+              nargv = xmalloc ((nargc + 2) * sizeof (char *));
+              memcpy (nargv, argv, argc * sizeof (char *));
+              nargv[nargc++] = xstrdup (concat ("-o", stdin_nm, ""));
+              nargv[nargc] = 0;
+            }
+
+	  if (directories != 0 && directories->idx > 0)
+	    {
+	      int bad = 1;
+	      if (directory_before_chdir != 0)
+		{
+		  if (chdir (directory_before_chdir) < 0)
+		      perror_with_name ("chdir", "");
+		  else
+		    bad = 0;
+		}
+	      if (bad)
+		fatal (NILF, _("Couldn't change back to original directory."));
+	    }
+
+          ++restarts;
+
+	  if (ISDB (DB_BASIC))
+	    {
+	      char **p;
+	      printf (_("Re-executing[%u]:"), restarts);
+	      for (p = nargv; *p != 0; ++p)
+		printf (" %s", *p);
+	      putchar ('\n');
+	    }
+
+#ifndef _AMIGA
+          {
+            char **p;
+            for (p = environ; *p != 0; ++p)
+              {
+                if (strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH)
+                    && (*p)[MAKELEVEL_LENGTH] == '=')
+                  {
+                    *p = alloca (40);
+                    sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel);
+                  }
+                if (strneq (*p, "MAKE_RESTARTS=", 14))
+                  {
+                    *p = alloca (40);
+                    sprintf (*p, "MAKE_RESTARTS=%u", restarts);
+                    restarts = 0;
+                  }
+              }
+          }
+#else /* AMIGA */
+	  {
+	    char buffer[256];
+
+            sprintf (buffer, "%u", makelevel);
+            SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY);
+
+            sprintf (buffer, "%u", restarts);
+            SetVar ("MAKE_RESTARTS", buffer, -1, GVF_GLOBAL_ONLY);
+            restarts = 0;
+	  }
+#endif
+
+          /* If we didn't set the restarts variable yet, add it.  */
+          if (restarts)
+            {
+              char *b = alloca (40);
+              sprintf (b, "MAKE_RESTARTS=%u", restarts);
+              putenv (b);
+            }
+
+	  fflush (stdout);
+	  fflush (stderr);
+
+          /* Close the dup'd jobserver pipe if we opened one.  */
+          if (job_rfd >= 0)
+            close (job_rfd);
+
+#ifdef _AMIGA
+	  exec_command (nargv);
+	  exit (0);
+#elif defined (__EMX__)
+	  {
+	    /* It is not possible to use execve() here because this
+	       would cause the parent process to be terminated with
+	       exit code 0 before the child process has been terminated.
+	       Therefore it may be the best solution simply to spawn the
+	       child process including all file handles and to wait for its
+	       termination. */
+	    int pid;
+	    int status;
+	    pid = child_execute_job (0, 1, nargv, environ);
+
+	    /* is this loop really necessary? */
+	    do {
+	      pid = wait (&status);
+	    } while (pid <= 0);
+	    /* use the exit code of the child process */
+	    exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
+	  }
+#else
+	  exec_command (nargv, environ);
+#endif
+	  /* NOTREACHED */
+
+	default:
+#define BOGUS_UPDATE_STATUS 0
+	  assert (BOGUS_UPDATE_STATUS);
+	  break;
+	}
+
+      db_level = orig_db_level;
+
+      /* Free the makefile mtimes (if we allocated any).  */
+      if (makefile_mtimes)
+        free (makefile_mtimes);
+    }
+
+  /* Set up `MAKEFLAGS' again for the normal targets.  */
+  define_makeflags (1, 0);
+
+  /* Set always_make_flag if -B was given.  */
+  always_make_flag = always_make_set;
+
+  /* If restarts is set we haven't set up -W files yet, so do that now.  */
+  if (restarts && new_files != 0)
+    {
+      const char **p;
+      for (p = new_files->list; *p != 0; ++p)
+	{
+	  struct file *f = enter_file (*p);
+	  f->last_mtime = f->mtime_before_update = NEW_MTIME;
+	}
+    }
+
+  /* If there is a temp file from reading a makefile from stdin, get rid of
+     it now.  */
+  if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT)
+    perror_with_name (_("unlink (temporary file): "), stdin_nm);
+
+  {
+    int status;
+
+    /* If there were no command-line goals, use the default.  */
+    if (goals == 0)
+      {
+        if (**default_goal_name != '\0')
+          {
+            if (default_goal_file == 0 ||
+                strcmp (*default_goal_name, default_goal_file->name) != 0)
+              {
+                default_goal_file = lookup_file (*default_goal_name);
+
+                /* In case user set .DEFAULT_GOAL to a non-existent target
+                   name let's just enter this name into the table and let
+                   the standard logic sort it out. */
+                if (default_goal_file == 0)
+                  {
+                    struct nameseq *ns;
+                    char *p = *default_goal_name;
+
+                    ns = multi_glob (
+                      parse_file_seq (&p, '\0', sizeof (struct nameseq), 1),
+                      sizeof (struct nameseq));
+
+                    /* .DEFAULT_GOAL should contain one target. */
+                    if (ns->next != 0)
+                      fatal (NILF, _(".DEFAULT_GOAL contains more than one target"));
+
+                    default_goal_file = enter_file (strcache_add (ns->name));
+
+                    ns->name = 0; /* It was reused by enter_file(). */
+                    free_ns_chain (ns);
+                  }
+              }
+
+            goals = alloc_dep ();
+            goals->file = default_goal_file;
+          }
+      }
+    else
+      lastgoal->next = 0;
+
+
+    if (!goals)
+      {
+        if (read_makefiles == 0)
+          fatal (NILF, _("No targets specified and no makefile found"));
+
+        fatal (NILF, _("No targets"));
+      }
+
+    /* Update the goals.  */
+
+    DB (DB_BASIC, (_("Updating goal targets....\n")));
+
+    switch (update_goal_chain (goals))
+    {
+      case -1:
+        /* Nothing happened.  */
+      case 0:
+        /* Updated successfully.  */
+        status = makefile_status;
+        break;
+      case 1:
+        /* We are under -q and would run some commands.  */
+        status = MAKE_TROUBLE;
+        break;
+      case 2:
+        /* Updating failed.  POSIX.2 specifies exit status >1 for this;
+           but in VMS, there is only success and failure.  */
+        status = MAKE_FAILURE;
+        break;
+      default:
+        abort ();
+    }
+
+    /* If we detected some clock skew, generate one last warning */
+    if (clock_skew_detected)
+      error (NILF,
+             _("warning:  Clock skew detected.  Your build may be incomplete."));
+
+    /* Exit.  */
+    die (status);
+  }
+
+  /* NOTREACHED */
+  return 0;
+}
+
+
+/* Parsing of arguments, decoding of switches.  */
+
+static char options[1 + sizeof (switches) / sizeof (switches[0]) * 3];
+static struct option long_options[(sizeof (switches) / sizeof (switches[0])) +
+				  (sizeof (long_option_aliases) /
+				   sizeof (long_option_aliases[0]))];
+
+/* Fill in the string and vector for getopt.  */
+static void
+init_switches (void)
+{
+  char *p;
+  unsigned int c;
+  unsigned int i;
+
+  if (options[0] != '\0')
+    /* Already done.  */
+    return;
+
+  p = options;
+
+  /* Return switch and non-switch args in order, regardless of
+     POSIXLY_CORRECT.  Non-switch args are returned as option 1.  */
+  *p++ = '-';
+
+  for (i = 0; switches[i].c != '\0'; ++i)
+    {
+      long_options[i].name = (switches[i].long_name == 0 ? "" :
+			      switches[i].long_name);
+      long_options[i].flag = 0;
+      long_options[i].val = switches[i].c;
+      if (short_option (switches[i].c))
+	*p++ = switches[i].c;
+      switch (switches[i].type)
+	{
+	case flag:
+	case flag_off:
+	case ignore:
+	  long_options[i].has_arg = no_argument;
+	  break;
+
+	case string:
+        case filename:
+	case positive_int:
+	case floating:
+	  if (short_option (switches[i].c))
+	    *p++ = ':';
+	  if (switches[i].noarg_value != 0)
+	    {
+	      if (short_option (switches[i].c))
+		*p++ = ':';
+	      long_options[i].has_arg = optional_argument;
+	    }
+	  else
+	    long_options[i].has_arg = required_argument;
+	  break;
+	}
+    }
+  *p = '\0';
+  for (c = 0; c < (sizeof (long_option_aliases) /
+		   sizeof (long_option_aliases[0]));
+       ++c)
+    long_options[i++] = long_option_aliases[c];
+  long_options[i].name = 0;
+}
+
+static void
+handle_non_switch_argument (char *arg, int env)
+{
+  /* Non-option argument.  It might be a variable definition.  */
+  struct variable *v;
+  if (arg[0] == '-' && arg[1] == '\0')
+    /* Ignore plain `-' for compatibility.  */
+    return;
+  v = try_variable_definition (0, arg, o_command, 0);
+  if (v != 0)
+    {
+      /* It is indeed a variable definition.  If we don't already have this
+	 one, record a pointer to the variable for later use in
+	 define_makeflags.  */
+      struct command_variable *cv;
+
+      for (cv = command_variables; cv != 0; cv = cv->next)
+        if (cv->variable == v)
+          break;
+
+      if (! cv) {
+        cv = xmalloc (sizeof (*cv));
+        cv->variable = v;
+        cv->next = command_variables;
+        command_variables = cv;
+      }
+    }
+  else if (! env)
+    {
+      /* Not an option or variable definition; it must be a goal
+	 target!  Enter it as a file and add it to the dep chain of
+	 goals.  */
+      struct file *f = enter_file (strcache_add (expand_command_line_file (arg)));
+      f->cmd_target = 1;
+
+      if (goals == 0)
+	{
+	  goals = alloc_dep ();
+	  lastgoal = goals;
+	}
+      else
+	{
+	  lastgoal->next = alloc_dep ();
+	  lastgoal = lastgoal->next;
+	}
+
+      lastgoal->file = f;
+
+      {
+        /* Add this target name to the MAKECMDGOALS variable. */
+        struct variable *gv;
+        const char *value;
+
+        gv = lookup_variable (STRING_SIZE_TUPLE ("MAKECMDGOALS"));
+        if (gv == 0)
+          value = f->name;
+        else
+          {
+            /* Paste the old and new values together */
+            unsigned int oldlen, newlen;
+            char *vp;
+
+            oldlen = strlen (gv->value);
+            newlen = strlen (f->name);
+            vp = alloca (oldlen + 1 + newlen + 1);
+            memcpy (vp, gv->value, oldlen);
+            vp[oldlen] = ' ';
+            memcpy (&vp[oldlen + 1], f->name, newlen + 1);
+            value = vp;
+          }
+        define_variable ("MAKECMDGOALS", 12, value, o_default, 0);
+      }
+    }
+}
+
+/* Print a nice usage method.  */
+
+static void
+print_usage (int bad)
+{
+  const char *const *cpp;
+  FILE *usageto;
+
+  if (print_version_flag)
+    print_version ();
+
+  usageto = bad ? stderr : stdout;
+
+  fprintf (usageto, _("Usage: %s [options] [target] ...\n"), program);
+
+  for (cpp = usage; *cpp; ++cpp)
+    fputs (_(*cpp), usageto);
+
+#ifdef KMK
+  if (!remote_description || *remote_description == '\0')
+    printf (_("\nThis program is built for %s/%s/%s [" __DATE__ " " __TIME__ "]\n"),
+            KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU, remote_description);
+  else
+    printf (_("\nThis program is built for %s/%s/%s (%s) [" __DATE__ " " __TIME__ "]\n"),
+            KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU, remote_description);
+#else  /* !KMK */
+  if (!remote_description || *remote_description == '\0')
+    fprintf (usageto, _("\nThis program built for %s\n"), make_host);
+  else
+    fprintf (usageto, _("\nThis program built for %s (%s)\n"),
+             make_host, remote_description);
+#endif /* !KMK */
+
+  fprintf (usageto, _("Report bugs to <bug-make@gnu.org>\n"));
+}
+
+/* Decode switches from ARGC and ARGV.
+   They came from the environment if ENV is nonzero.  */
+
+static void
+decode_switches (int argc, char **argv, int env)
+{
+  int bad = 0;
+  register const struct command_switch *cs;
+  register struct stringlist *sl;
+  register int c;
+
+  /* getopt does most of the parsing for us.
+     First, get its vectors set up.  */
+
+  init_switches ();
+
+  /* Let getopt produce error messages for the command line,
+     but not for options from the environment.  */
+  opterr = !env;
+  /* Reset getopt's state.  */
+  optind = 0;
+
+  while (optind < argc)
+    {
+      /* Parse the next argument.  */
+      c = getopt_long (argc, argv, options, long_options, (int *) 0);
+      if (c == EOF)
+	/* End of arguments, or "--" marker seen.  */
+	break;
+      else if (c == 1)
+	/* An argument not starting with a dash.  */
+	handle_non_switch_argument (optarg, env);
+      else if (c == '?')
+	/* Bad option.  We will print a usage message and die later.
+	   But continue to parse the other options so the user can
+	   see all he did wrong.  */
+	bad = 1;
+      else
+	for (cs = switches; cs->c != '\0'; ++cs)
+	  if (cs->c == c)
+	    {
+	      /* Whether or not we will actually do anything with
+		 this switch.  We test this individually inside the
+		 switch below rather than just once outside it, so that
+		 options which are to be ignored still consume args.  */
+	      int doit = !env || cs->env;
+
+	      switch (cs->type)
+		{
+		default:
+		  abort ();
+
+		case ignore:
+		  break;
+
+		case flag:
+		case flag_off:
+		  if (doit)
+		    *(int *) cs->value_ptr = cs->type == flag;
+		  break;
+
+		case string:
+		case filename:
+		  if (!doit)
+		    break;
+
+		  if (optarg == 0)
+		    optarg = xstrdup (cs->noarg_value);
+                  else if (*optarg == '\0')
+                    {
+                      error (NILF, _("the `-%c' option requires a non-empty string argument"),
+                             cs->c);
+                      bad = 1;
+                    }
+
+		  sl = *(struct stringlist **) cs->value_ptr;
+		  if (sl == 0)
+		    {
+		      sl = (struct stringlist *)
+			xmalloc (sizeof (struct stringlist));
+		      sl->max = 5;
+		      sl->idx = 0;
+		      sl->list = xmalloc (5 * sizeof (char *));
+		      *(struct stringlist **) cs->value_ptr = sl;
+		    }
+		  else if (sl->idx == sl->max - 1)
+		    {
+		      sl->max += 5;
+		      sl->list = xrealloc ((void *)sl->list, /* bird */
+                                           sl->max * sizeof (char *));
+		    }
+                  if (cs->type == filename)
+                    sl->list[sl->idx++] = expand_command_line_file (optarg);
+                  else
+                    sl->list[sl->idx++] = optarg;
+		  sl->list[sl->idx] = 0;
+		  break;
+
+		case positive_int:
+                  /* See if we have an option argument; if we do require that
+                     it's all digits, not something like "10foo".  */
+		  if (optarg == 0 && argc > optind)
+                    {
+                      const char *cp;
+                      for (cp=argv[optind]; ISDIGIT (cp[0]); ++cp)
+                        ;
+                      if (cp[0] == '\0')
+                        optarg = argv[optind++];
+                    }
+
+		  if (!doit)
+		    break;
+
+		  if (optarg != 0)
+		    {
+		      int i = atoi (optarg);
+                      const char *cp;
+
+                      /* Yes, I realize we're repeating this in some cases.  */
+                      for (cp = optarg; ISDIGIT (cp[0]); ++cp)
+                        ;
+
+		      if (i < 1 || cp[0] != '\0')
+			{
+                          error (NILF, _("the `-%c' option requires a positive integral argument"),
+                                 cs->c);
+			  bad = 1;
+			}
+		      else
+			*(unsigned int *) cs->value_ptr = i;
+		    }
+		  else
+		    *(unsigned int *) cs->value_ptr
+		      = *(unsigned int *) cs->noarg_value;
+		  break;
+
+#ifndef NO_FLOAT
+		case floating:
+		  if (optarg == 0 && optind < argc
+		      && (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.'))
+		    optarg = argv[optind++];
+
+		  if (doit)
+		    *(double *) cs->value_ptr
+		      = (optarg != 0 ? atof (optarg)
+			 : *(double *) cs->noarg_value);
+
+		  break;
+#endif
+		}
+
+	      /* We've found the switch.  Stop looking.  */
+	      break;
+	    }
+    }
+
+  /* There are no more options according to getting getopt, but there may
+     be some arguments left.  Since we have asked for non-option arguments
+     to be returned in order, this only happens when there is a "--"
+     argument to prevent later arguments from being options.  */
+  while (optind < argc)
+    handle_non_switch_argument (argv[optind++], env);
+
+
+  if (!env && (bad || print_usage_flag))
+    {
+      print_usage (bad);
+      die (bad ? 2 : 0);
+    }
+}
+
+/* Decode switches from environment variable ENVAR (which is LEN chars long).
+   We do this by chopping the value into a vector of words, prepending a
+   dash to the first word if it lacks one, and passing the vector to
+   decode_switches.  */
+
+static void
+decode_env_switches (char *envar, unsigned int len)
+{
+  char *varref = alloca (2 + len + 2);
+  char *value, *p;
+  int argc;
+  char **argv;
+
+  /* Get the variable's value.  */
+  varref[0] = '$';
+  varref[1] = '(';
+  memcpy (&varref[2], envar, len);
+  varref[2 + len] = ')';
+  varref[2 + len + 1] = '\0';
+  value = variable_expand (varref);
+
+  /* Skip whitespace, and check for an empty value.  */
+  value = next_token (value);
+  len = strlen (value);
+  if (len == 0)
+    return;
+
+  /* Allocate a vector that is definitely big enough.  */
+  argv = alloca ((1 + len + 1) * sizeof (char *));
+
+  /* Allocate a buffer to copy the value into while we split it into words
+     and unquote it.  We must use permanent storage for this because
+     decode_switches may store pointers into the passed argument words.  */
+  p = xmalloc (2 * len);
+
+  /* getopt will look at the arguments starting at ARGV[1].
+     Prepend a spacer word.  */
+  argv[0] = 0;
+  argc = 1;
+  argv[argc] = p;
+  while (*value != '\0')
+    {
+      if (*value == '\\' && value[1] != '\0')
+	++value;		/* Skip the backslash.  */
+      else if (isblank ((unsigned char)*value))
+	{
+	  /* End of the word.  */
+	  *p++ = '\0';
+	  argv[++argc] = p;
+	  do
+	    ++value;
+	  while (isblank ((unsigned char)*value));
+	  continue;
+	}
+      *p++ = *value++;
+    }
+  *p = '\0';
+  argv[++argc] = 0;
+
+  if (argv[1][0] != '-' && strchr (argv[1], '=') == 0)
+    /* The first word doesn't start with a dash and isn't a variable
+       definition.  Add a dash and pass it along to decode_switches.  We
+       need permanent storage for this in case decode_switches saves
+       pointers into the value.  */
+    argv[1] = xstrdup (concat ("-", argv[1], ""));
+
+  /* Parse those words.  */
+  decode_switches (argc, argv, 1);
+}
+
+
+/* Quote the string IN so that it will be interpreted as a single word with
+   no magic by decode_env_switches; also double dollar signs to avoid
+   variable expansion in make itself.  Write the result into OUT, returning
+   the address of the next character to be written.
+   Allocating space for OUT twice the length of IN is always sufficient.  */
+
+static char *
+quote_for_env (char *out, const char *in)
+{
+  while (*in != '\0')
+    {
+      if (*in == '$')
+	*out++ = '$';
+      else if (isblank ((unsigned char)*in) || *in == '\\')
+        *out++ = '\\';
+      *out++ = *in++;
+    }
+
+  return out;
+}
+
+/* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the
+   command switches.  Include options with args if ALL is nonzero.
+   Don't include options with the `no_makefile' flag set if MAKEFILE.  */
+
+static void
+define_makeflags (int all, int makefile)
+{
+#ifdef KMK
+  static const char ref[] = "$(KMK_OVERRIDES)";
+#else
+  static const char ref[] = "$(MAKEOVERRIDES)";
+#endif
+  static const char posixref[] = "$(-*-command-variables-*-)";
+  register const struct command_switch *cs;
+  char *flagstring;
+  register char *p;
+  unsigned int words;
+  struct variable *v;
+
+  /* We will construct a linked list of `struct flag's describing
+     all the flags which need to go in MAKEFLAGS.  Then, once we
+     know how many there are and their lengths, we can put them all
+     together in a string.  */
+
+  struct flag
+    {
+      struct flag *next;
+      const struct command_switch *cs;
+      const char *arg;
+    };
+  struct flag *flags = 0;
+  unsigned int flagslen = 0;
+#define	ADD_FLAG(ARG, LEN) \
+  do {									      \
+    struct flag *new = alloca (sizeof (struct flag));                         \
+    new->cs = cs;							      \
+    new->arg = (ARG);							      \
+    new->next = flags;							      \
+    flags = new;							      \
+    if (new->arg == 0)							      \
+      ++flagslen;		/* Just a single flag letter.  */	      \
+    else								      \
+      flagslen += 1 + 1 + 1 + 1 + 3 * (LEN); /* " -x foo" */		      \
+    if (!short_option (cs->c))						      \
+      /* This switch has no single-letter version, so we use the long.  */    \
+      flagslen += 2 + strlen (cs->long_name);				      \
+  } while (0)
+
+  for (cs = switches; cs->c != '\0'; ++cs)
+    if (cs->toenv && (!makefile || !cs->no_makefile))
+      switch (cs->type)
+	{
+	case ignore:
+	  break;
+
+	case flag:
+	case flag_off:
+	  if (!*(int *) cs->value_ptr == (cs->type == flag_off)
+	      && (cs->default_value == 0
+		  || *(int *) cs->value_ptr != *(int *) cs->default_value))
+	    ADD_FLAG (0, 0);
+	  break;
+
+	case positive_int:
+	  if (all)
+	    {
+	      if ((cs->default_value != 0
+		   && (*(unsigned int *) cs->value_ptr
+		       == *(unsigned int *) cs->default_value)))
+		break;
+	      else if (cs->noarg_value != 0
+		       && (*(unsigned int *) cs->value_ptr ==
+			   *(unsigned int *) cs->noarg_value))
+		ADD_FLAG ("", 0); /* Optional value omitted; see below.  */
+#if !defined(KMK) || !defined(WINDOWS32) /* jobserver stuff doesn't work on windows???. */
+	      else if (cs->c == 'j')
+		/* Special case for `-j'.  */
+		ADD_FLAG ("1", 1);
+#endif
+	      else
+		{
+		  char *buf = alloca (30);
+		  sprintf (buf, "%u", *(unsigned int *) cs->value_ptr);
+		  ADD_FLAG (buf, strlen (buf));
+		}
+	    }
+	  break;
+
+#ifndef NO_FLOAT
+	case floating:
+	  if (all)
+	    {
+	      if (cs->default_value != 0
+		  && (*(double *) cs->value_ptr
+		      == *(double *) cs->default_value))
+		break;
+	      else if (cs->noarg_value != 0
+		       && (*(double *) cs->value_ptr
+			   == *(double *) cs->noarg_value))
+		ADD_FLAG ("", 0); /* Optional value omitted; see below.  */
+	      else
+		{
+		  char *buf = alloca (100);
+		  sprintf (buf, "%g", *(double *) cs->value_ptr);
+		  ADD_FLAG (buf, strlen (buf));
+		}
+	    }
+	  break;
+#endif
+
+	case filename:
+	case string:
+	  if (all)
+	    {
+	      struct stringlist *sl = *(struct stringlist **) cs->value_ptr;
+	      if (sl != 0)
+		{
+		  /* Add the elements in reverse order, because all the flags
+		     get reversed below; and the order matters for some
+		     switches (like -I).  */
+		  unsigned int i = sl->idx;
+		  while (i-- > 0)
+		    ADD_FLAG (sl->list[i], strlen (sl->list[i]));
+		}
+	    }
+	  break;
+
+	default:
+	  abort ();
+	}
+
+  flagslen += 4 + sizeof posixref; /* Four more for the possible " -- ".  */
+
+#undef	ADD_FLAG
+
+  /* Construct the value in FLAGSTRING.
+     We allocate enough space for a preceding dash and trailing null.  */
+  flagstring = alloca (1 + flagslen + 1);
+  memset (flagstring, '\0', 1 + flagslen + 1);
+  p = flagstring;
+  words = 1;
+  *p++ = '-';
+  while (flags != 0)
+    {
+      /* Add the flag letter or name to the string.  */
+      if (short_option (flags->cs->c))
+	*p++ = flags->cs->c;
+      else
+	{
+          if (*p != '-')
+            {
+              *p++ = ' ';
+              *p++ = '-';
+            }
+	  *p++ = '-';
+	  strcpy (p, flags->cs->long_name);
+	  p += strlen (p);
+	}
+      if (flags->arg != 0)
+	{
+	  /* A flag that takes an optional argument which in this case is
+	     omitted is specified by ARG being "".  We must distinguish
+	     because a following flag appended without an intervening " -"
+	     is considered the arg for the first.  */
+	  if (flags->arg[0] != '\0')
+	    {
+	      /* Add its argument too.  */
+	      *p++ = !short_option (flags->cs->c) ? '=' : ' ';
+	      p = quote_for_env (p, flags->arg);
+	    }
+	  ++words;
+	  /* Write a following space and dash, for the next flag.  */
+	  *p++ = ' ';
+	  *p++ = '-';
+	}
+      else if (!short_option (flags->cs->c))
+	{
+	  ++words;
+	  /* Long options must each go in their own word,
+	     so we write the following space and dash.  */
+	  *p++ = ' ';
+	  *p++ = '-';
+	}
+      flags = flags->next;
+    }
+
+  /* Define MFLAGS before appending variable definitions.  */
+
+  if (p == &flagstring[1])
+    /* No flags.  */
+    flagstring[0] = '\0';
+  else if (p[-1] == '-')
+    {
+      /* Kill the final space and dash.  */
+      p -= 2;
+      *p = '\0';
+    }
+  else
+    /* Terminate the string.  */
+    *p = '\0';
+
+#ifdef KMK
+  /* Since MFLAGS is not parsed for flags, there is no reason to
+     override any makefile redefinition.  */
+  (void) define_variable ("MFLAGS", 6, flagstring, o_env, 1);
+#endif /* !KMK */
+
+  if (all && command_variables != 0)
+    {
+      /* Now write a reference to $(MAKEOVERRIDES), which contains all the
+	 command-line variable definitions.  */
+
+      if (p == &flagstring[1])
+	/* No flags written, so elide the leading dash already written.  */
+	p = flagstring;
+      else
+	{
+	  /* Separate the variables from the switches with a "--" arg.  */
+	  if (p[-1] != '-')
+	    {
+	      /* We did not already write a trailing " -".  */
+	      *p++ = ' ';
+	      *p++ = '-';
+	    }
+	  /* There is a trailing " -"; fill it out to " -- ".  */
+	  *p++ = '-';
+	  *p++ = ' ';
+	}
+
+      /* Copy in the string.  */
+      if (posix_pedantic)
+	{
+	  memcpy (p, posixref, sizeof posixref - 1);
+	  p += sizeof posixref - 1;
+	}
+      else
+	{
+	  memcpy (p, ref, sizeof ref - 1);
+	  p += sizeof ref - 1;
+	}
+    }
+  else if (p == &flagstring[1])
+    {
+      words = 0;
+      --p;
+    }
+  else if (p[-1] == '-')
+    /* Kill the final space and dash.  */
+    p -= 2;
+  /* Terminate the string.  */
+  *p = '\0';
+
+#ifdef KMK
+  v = define_variable ("KMK_FLAGS", 9,
+                       /* If there are switches, omit the leading dash
+                          unless it is a single long option with two
+                          leading dashes.  */
+                       &flagstring[(flagstring[0] == '-'
+                                    && flagstring[1] != '-')
+                                   ? 1 : 0],
+                       /* This used to use o_env, but that lost when a
+                          makefile defined MAKEFLAGS.  Makefiles set
+                          MAKEFLAGS to add switches, but we still want
+                          to redefine its value with the full set of
+                          switches.  Of course, an override or command
+                          definition will still take precedence.  */
+                       o_file, 1);
+#else
+  v = define_variable ("MAKEFLAGS", 9,
+		       /* If there are switches, omit the leading dash
+			  unless it is a single long option with two
+			  leading dashes.  */
+		       &flagstring[(flagstring[0] == '-'
+				    && flagstring[1] != '-')
+				   ? 1 : 0],
+		       /* This used to use o_env, but that lost when a
+			  makefile defined MAKEFLAGS.  Makefiles set
+			  MAKEFLAGS to add switches, but we still want
+			  to redefine its value with the full set of
+			  switches.  Of course, an override or command
+			  definition will still take precedence.  */
+		       o_file, 1);
+#endif
+  if (! all)
+    /* The first time we are called, set MAKEFLAGS to always be exported.
+       We should not do this again on the second call, because that is
+       after reading makefiles which might have done `unexport MAKEFLAGS'. */
+    v->export = v_export;
+
+#ifdef KMK
+  /* Provide simple access to some of the options. */
+  {
+    char val[32];
+    sprintf (val, "%u", job_slots);
+    define_variable ("KMK_OPTS_JOBS", sizeof("KMK_OPTS_JOBS") - 1,
+                     val, o_default, 1);
+    define_variable ("KMK_OPTS_KEEP_GOING", sizeof("KMK_OPTS_KEEP_GOING") - 1,
+                     keep_going_flag ? "1" : "0", o_default, 1);
+    define_variable ("KMK_OPTS_JUST_PRINT", sizeof("KMK_OPTS_JUST_PRINT") - 1,
+                     just_print_flag ? "1" : "0", o_default, 1);
+    define_variable ("KMK_OPTS_PRETTY_COMMAND_PRINTING", sizeof("KMK_OPTS_PRETTY_COMMAND_PRINTING") - 1,
+                     pretty_command_printing ? "1" : "0", o_default, 1);
+    sprintf (val, "%u", process_priority);
+    define_variable ("KMK_OPTS_PRORITY", sizeof("KMK_OPTS_PRORITY") - 1,
+                     val, o_default, 1);
+    sprintf (val, "%u", process_affinity);
+    define_variable ("KMK_OPTS_AFFINITY", sizeof("KMK_OPTS_AFFINITY") - 1,
+                     val, o_default, 1);
+    define_variable ("KMK_OPTS_STATISTICS", sizeof("KMK_OPTS_STATISTICS") - 1,
+                     make_expensive_statistics ? "1" : "0", o_default, 1);
+  }
+#endif
+}
+
+
+/* Print version information.  */
+
+static void
+print_version (void)
+{
+  static int printed_version = 0;
+
+  char *precede = print_data_base_flag ? "# " : "";
+
+  if (printed_version)
+    /* Do it only once.  */
+    return;
+
+  /* Print this untranslated.  The coding standards recommend translating the
+     (C) to the copyright symbol, but this string is going to change every
+     year, and none of the rest of it should be translated (including the
+     word "Copyright", so it hardly seems worth it.  */
+
+#ifdef KMK
+  printf ("%skmk - kBuild version %d.%d.%d (r%u)\n\
+\n\
+%sBased on GNU Make %s:\n\
+%s Copyright (C) 2006  Free Software Foundation, Inc.\n\
+\n\
+%skBuild modifications:\n\
+%s Copyright (C) 2005-2008  Knut St. Osmundsen.\n\
+\n\
+%skmkbuiltin commands derived from *BSD sources:\n\
+%s Copyright (c) 1983 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994\n\
+%s  The Regents of the University of California. All rights reserved.\n\
+%s Copyright (c) 1998  Todd C. Miller <Todd.Miller@courtesan.com>\n\
+%s\n",
+          precede, KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR,
+          KBUILD_VERSION_PATCH, KBUILD_SVN_REV,
+          precede, version_string,
+          precede, precede, precede, precede, precede, precede,
+          precede, precede);
+#else
+  printf ("%sGNU Make %s\n\
+%sCopyright (C) 2006  Free Software Foundation, Inc.\n",
+          precede, version_string, precede);
+#endif
+
+  printf (_("%sThis is free software; see the source for copying conditions.\n\
+%sThere is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
+%sPARTICULAR PURPOSE.\n"),
+            precede, precede, precede);
+
+#ifdef KMK
+# ifdef KBUILD_PATH
+  printf (_("%s\n\
+%sKBUILD_PATH:     '%s' (default '%s')\n\
+%sKBUILD_BIN_PATH: '%s' (default '%s')\n"),
+          precede,
+          precede, get_kbuild_path(), KBUILD_PATH,
+          precede, get_kbuild_bin_path(), KBUILD_BIN_PATH);
+# else  /* !KBUILD_PATH */
+  printf (_("%s\n\
+%sKBUILD_PATH:     '%s'\n\
+%sKBUILD_BIN_PATH: '%s'\n"),
+          precede,
+          precede, get_kbuild_path(),
+          precede, get_kbuild_bin_path());
+# endif /* !KBUILD_PATH */
+  if (!remote_description || *remote_description == '\0')
+    printf (_("\n%sThis program is built for %s/%s/%s [" __DATE__ " " __TIME__ "]\n"),
+            precede, KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU, remote_description);
+  else
+    printf (_("\n%sThis program is built for %s/%s/%s (%s) [" __DATE__ " " __TIME__ "]\n"),
+            precede, KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU, remote_description);
+#else
+  if (!remote_description || *remote_description == '\0')
+    printf (_("\n%sThis program built for %s\n"), precede, make_host);
+  else
+    printf (_("\n%sThis program built for %s (%s)\n"),
+            precede, make_host, remote_description);
+#endif
+
+  printed_version = 1;
+
+  /* Flush stdout so the user doesn't have to wait to see the
+     version information while things are thought about.  */
+  fflush (stdout);
+}
+
+/* Print a bunch of information about this and that.  */
+
+static void
+print_data_base ()
+{
+  time_t when;
+
+  when = time ((time_t *) 0);
+  printf (_("\n# Make data base, printed on %s"), ctime (&when));
+
+  print_variable_data_base ();
+  print_dir_data_base ();
+  print_rule_data_base ();
+  print_file_data_base ();
+  print_vpath_data_base ();
+  strcache_print_stats ("#");
+
+  when = time ((time_t *) 0);
+  printf (_("\n# Finished Make data base on %s\n"), ctime (&when));
+}
+
+static void
+clean_jobserver (int status)
+{
+  char token = '+';
+
+  /* Sanity: have we written all our jobserver tokens back?  If our
+     exit status is 2 that means some kind of syntax error; we might not
+     have written all our tokens so do that now.  If tokens are left
+     after any other error code, that's bad.  */
+
+  if (job_fds[0] != -1 && jobserver_tokens)
+    {
+      if (status != 2)
+        error (NILF,
+               "INTERNAL: Exiting with %u jobserver tokens (should be 0)!",
+               jobserver_tokens);
+      else
+        while (jobserver_tokens--)
+          {
+            int r;
+
+            EINTRLOOP (r, write (job_fds[1], &token, 1));
+            if (r != 1)
+              perror_with_name ("write", "");
+          }
+    }
+
+
+  /* Sanity: If we're the master, were all the tokens written back?  */
+
+  if (master_job_slots)
+    {
+      /* We didn't write one for ourself, so start at 1.  */
+      unsigned int tcnt = 1;
+
+      /* Close the write side, so the read() won't hang.  */
+      close (job_fds[1]);
+
+      while (read (job_fds[0], &token, 1) == 1)
+        ++tcnt;
+
+      if (tcnt != master_job_slots)
+        error (NILF,
+               "INTERNAL: Exiting with %u jobserver tokens available; should be %u!",
+               tcnt, master_job_slots);
+
+      close (job_fds[0]);
+    }
+}
+
+
+/* Exit with STATUS, cleaning up as necessary.  */
+
+void
+die (int status)
+{
+  static char dying = 0;
+
+  if (!dying)
+    {
+      int err;
+
+      dying = 1;
+
+      if (print_version_flag)
+	print_version ();
+
+      /* Wait for children to die.  */
+      err = (status != 0);
+      while (job_slots_used > 0)
+	reap_children (1, err);
+
+      /* Let the remote job module clean up its state.  */
+      remote_cleanup ();
+
+      /* Remove the intermediate files.  */
+      remove_intermediates (0);
+
+      if (print_data_base_flag)
+	print_data_base ();
+
+      verify_file_data_base ();
+
+      clean_jobserver (status);
+
+      /* Try to move back to the original directory.  This is essential on
+	 MS-DOS (where there is really only one process), and on Unix it
+	 puts core files in the original directory instead of the -C
+	 directory.  Must wait until after remove_intermediates(), or unlinks
+         of relative pathnames fail.  */
+      if (directory_before_chdir != 0)
+	chdir (directory_before_chdir);
+
+      log_working_directory (0);
+    }
+
+  exit (status);
+}
+
+
+/* Write a message indicating that we've just entered or
+   left (according to ENTERING) the current directory.  */
+
+void
+log_working_directory (int entering)
+{
+  static int entered = 0;
+
+  /* Print nothing without the flag.  Don't print the entering message
+     again if we already have.  Don't print the leaving message if we
+     haven't printed the entering message.  */
+  if (! print_directory_flag || entering == entered)
+    return;
+
+  entered = entering;
+
+  if (print_data_base_flag)
+    fputs ("# ", stdout);
+
+  /* Use entire sentences to give the translators a fighting chance.  */
+
+  if (makelevel == 0)
+    if (starting_directory == 0)
+      if (entering)
+        printf (_("%s: Entering an unknown directory\n"), program);
+      else
+        printf (_("%s: Leaving an unknown directory\n"), program);
+    else
+      if (entering)
+        printf (_("%s: Entering directory `%s'\n"),
+                program, starting_directory);
+      else
+        printf (_("%s: Leaving directory `%s'\n"),
+                program, starting_directory);
+  else
+    if (starting_directory == 0)
+      if (entering)
+        printf (_("%s[%u]: Entering an unknown directory\n"),
+                program, makelevel);
+      else
+        printf (_("%s[%u]: Leaving an unknown directory\n"),
+                program, makelevel);
+    else
+      if (entering)
+        printf (_("%s[%u]: Entering directory `%s'\n"),
+                program, makelevel, starting_directory);
+      else
+        printf (_("%s[%u]: Leaving directory `%s'\n"),
+                program, makelevel, starting_directory);
+
+  /* Flush stdout to be sure this comes before any stderr output.  */
+  fflush (stdout);
+}
Index: /tags/kBuild-0.1.4/src/kmk/maintMakefile
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/maintMakefile	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/maintMakefile	(revision 1780)
@@ -0,0 +1,282 @@
+# Maintainer-only makefile segment.  This contains things that are relevant
+# only if you have the full copy of the GNU make sources from the CVS
+# tree, not a dist copy.
+
+# We like mondo-warnings!
+AM_CFLAGS += -Wall -Wextra -Wdeclaration-after-statement -Wshadow -Wpointer-arith -Wbad-function-cast
+
+# I want this one but I have to wait for the const cleanup!
+# -Wwrite-strings
+
+# Find the glob source files... this might be dangerous, but we're maintainers!
+globsrc := $(wildcard glob/*.c)
+globhdr := $(wildcard glob/*.h)
+
+TEMPLATES = README README.DOS README.W32 README.OS2 \
+	    config.ami configh.dos config.h.W32 config.h-vms
+MTEMPLATES = Makefile.DOS SMakefile
+
+# These are built as a side-effect of the dist rule
+#all-am: $(TEMPLATES) $(MTEMPLATES) build.sh.in
+
+# General rule for turning a .template into a regular file.
+#
+$(TEMPLATES) : % : %.template Makefile
+	rm -f $@
+	sed -e 's@%VERSION%@$(VERSION)@g' \
+	    -e 's@%PACKAGE%@$(PACKAGE)@g' \
+	  $< > $@
+	chmod a-w $@
+
+# Construct Makefiles by adding on dependencies, etc.
+#
+$(MTEMPLATES) : % : %.template .dep_segment Makefile
+	rm -f $@
+	sed -e 's@%VERSION%@$(VERSION)@g' \
+	    -e 's@%PROGRAMS%@$(bin_PROGRAMS)@g' \
+	    -e 's@%SOURCES%@$(filter-out remote-%,$(make_SOURCES)) remote-$$(REMOTE).c@g' \
+	    -e 's@%OBJECTS%@$(filter-out remote-%,$(make_OBJECTS)) remote-$$(REMOTE).o@g' \
+	    -e 's@%GLOB_SOURCES%@$(globsrc) $(globhdr)@g' \
+	    -e 's@%GLOB_OBJECTS%@$(globsrc:glob/%.c=%.o)@g' \
+	  $< > $@
+	echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \
+	  cat $(word 2,$^) >>$@
+	chmod a-w $@
+
+NMakefile: NMakefile.template .dep_segment Makefile
+	rm -f $@
+	cp $< $@
+	echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \
+	  sed 's/^\([^ ]*\)\.o:/$$(OUTDIR)\/\1.obj:/' $(word 2,$^) >>$@
+	chmod a-w $@
+
+# Construct build.sh.in
+#
+build.sh.in: build.template Makefile
+	rm -f $@
+	sed -e 's@%objs%@$(patsubst %.o,%.$${OBJEXT},$(filter-out remote-%,$(make_OBJECTS)))@g' \
+	    -e 's@%globobjs%@$(patsubst %.c,%.$${OBJEXT},$(globsrc))@g' \
+	  $< > $@
+	chmod a-w+x $@
+
+
+# Use automake to build a dependency list file, for "foreign" makefiles like
+# Makefile.DOS.
+#
+# Automake used to have a --generate-deps flag, but it's gone now, so we have
+# to do it ourselves.
+#
+DEP_FILES := $(wildcard $(DEPDIR)/*.Po)
+.dep_segment: Makefile.am maintMakefile $(DEP_FILES)
+	rm -f $@
+	(for f in $(DEPDIR)/*.Po; do \
+	   echo ""; \
+	   echo "# $$f"; \
+	   sed	-e '/^[^:]*\.[ch] *:/d' \
+		-e 's, /usr/[^ ]*,,g' \
+		-e 's, $(srcdir)/, ,g' \
+		-e '/^ *\\$$/d' \
+		-e '/^ *$$/d' \
+		< $$f; \
+	 done) > $@
+
+# Get rid of everything "else".
+#
+maintFILES = configure aclocal.m4 config.h.in Makefile.in stamp-h.in
+
+CVS-CLEAN-FILES +=	$(maintFILES) $(TEMPLATES) $(MTEMPLATES) NMakefile \
+			build.sh.in .deps .dep_segment ABOUT-NLS \
+			ansi2knr.*
+
+# This rule tries to clean the tree right down to how it looks when you do a
+# virgin CVS checkout.
+
+# This target is potentially dangerous since it removes _ANY FILE_ that
+# is not in CVS.  Including files you might mean to add to CVS but
+# haven't yet...  I only use this in subdirectories where it's unlikely
+# we have any new files.  Still... be careful!!
+
+cvsclean = $(PERL) -e '$$k{CVS} = 1; open(E,"< CVS/Entries") || die "CVS/Entries: $$!\n"; while (defined ($$_ = <E>)) { m%^/([^/]*)% or next; $$k{$$1} = 1; } close(E) || die "CVS/Entries: $$!\n"; opendir(D, ".") || die ".: $$!\n"; while (defined ($$_ = readdir(D))) { -f $$_ && ! exists $$k{$$_} && unlink($$_); } closedir(D) || die ".: $$!\n";'
+
+.PHONY: cvs-clean
+cvs-clean: maintainer-clean
+	-rm -rf *~ $(CVS-CLEAN-FILES)
+	-cd config && $(cvsclean)
+	-cd po     && $(cvsclean)
+	-cd doc    && $(cvsclean)
+	-cd glob   && $(cvsclean)
+
+
+# ----------------------------------------------------------------------
+#
+# The sections below were stolen from the Makefile.maint used by fileutils,
+# sh-utils, textutils, CPPI, Bison, and Autoconf.
+
+
+## ---------------- ##
+## Updating files.  ##
+## ---------------- ##
+
+WGET = wget --passive-ftp -nv
+ftp-gnu = ftp://ftp.gnu.org/gnu
+
+move_if_change =  if test -r $(target) && cmp -s $(target).t $(target); then \
+		    echo $(target) is unchanged; rm -f $(target).t; \
+		  else \
+		    mv $(target).t $(target); \
+		  fi
+
+# ------------------- #
+# Updating PO files.  #
+# ------------------- #
+
+# PO archive mirrors --- Be careful; some might not be fully populated!
+#   ftp://ftp.unex.es/pub/gnu-i18n/po/maint/
+#   http://translation.sf.net/maint/
+#   ftp://tiger.informatik.hu-berlin.de/pub/po/maint/
+
+po_repo = http://www.iro.umontreal.ca/translation/maint/$(PACKAGE)
+.PHONY: do-po-update po-update
+do-po-update:
+	tmppo="/tmp/po-$(PACKAGE)-$(VERSION).$$$$" \
+	  && rm -rf "$$tmppo" \
+	  && mkdir "$$tmppo" \
+	  && (cd "$$tmppo" \
+		&& $(WGET) -r -l1 -nd --no-parent -A '*.po' $(po_repo)) \
+	  && cp "$$tmppo"/*.po po && rm -rf "$$tmppo"
+	cd po && $(MAKE) update-po
+	$(MAKE) po-check
+
+po-update:
+	if test -d "po"; then \
+	  $(MAKE) do-po-update; \
+	fi
+
+# -------------------------- #
+# Updating GNU build files.  #
+# -------------------------- #
+
+# The following pseudo table associates a local directory and a URL
+# with each of the files that belongs to some other package and is
+# regularly updated from the specified URL.
+
+savannah-url = http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~
+target = $(patsubst get-%,%,$@)
+
+config-url = $(savannah-url)/config/config/$(patsubst get-config/%,%,$@)
+get-config/config.guess get-config/config.sub:
+	@echo $(WGET) $(config-url) -O $(target) \
+	  && $(WGET) $(config-url) -O $(target).t \
+	  && $(move_if_change)
+
+gnulib-url = $(savannah-url)/gnulib/gnulib/build-aux/$(patsubst get-config/%,%,$@)
+get-config/texinfo.tex:
+	@echo $(WGET) $(gnulib-url) -O $(target) \
+	  && $(WGET) $(gnulib-url) -O $(target).t \
+	  && $(move_if_change)
+
+gnustandards-url = $(savannah-url)/gnustandards/gnustandards/$(patsubst get-doc/%,%,$@)
+get-doc/make-stds.texi get-doc/fdl.texi:
+	@echo $(WGET) $(gnustandards-url) -O $(target) \
+	  && $(WGET) $(gnustandards-url) -O $(target).t \
+	  && $(move_if_change)
+
+.PHONY: cvs-update
+cvs-update: get-config/texinfo.tex get-config/config.guess get-config/config.sub get-doc/make-stds.texi get-doc/fdl.texi
+
+
+# --------------------- #
+# Updating everything.  #
+# --------------------- #
+
+.PHONY: update
+update: po-update cvs-update
+
+
+## --------------- ##
+## Sanity checks.  ##
+## --------------- ##
+
+# Checks that don't require cvs.  Run `changelog-check' last as
+# previous test may reveal problems requiring new ChangeLog entries.
+local-check: po-check changelog-check
+
+# copyright-check writable-files
+
+changelog-check:
+	if head ChangeLog | grep 'Version $(VERSION)' >/dev/null; then \
+	  :; \
+	else \
+	  echo "$(VERSION) not in ChangeLog" 1>&2; \
+	  exit 1; \
+	fi
+
+# Verify that all source files using _() are listed in po/POTFILES.in.
+# Ignore make.h; it defines _().
+po-check:
+	if test -f po/POTFILES.in; then \
+	  grep '^[^#]' po/POTFILES.in | sort > $@-1; \
+	  $(PERL) -wn -e 'if (/\b_\(/) { $$ARGV eq "make.h" || print "$$ARGV\n" and close ARGV }' *.c *.h | sort > $@-2; \
+	  diff -u $@-1 $@-2 || exit 1; \
+	  rm -f $@-1 $@-2; \
+	fi
+
+## ------------------------- ##
+## GNU FTP upload artifacts. ##
+## ------------------------- ##
+
+# This target creates the upload artifacts.
+# Sign it with my key.  If you don't have my key/passphrase then sorry,
+# you're SOL! :)
+
+GPG = gpg
+GPGFLAGS = -u 6338B6D4
+
+DIST_ARCHIVES_SIG = $(addsuffix .sig,$(DIST_ARCHIVES))
+DIST_ARCHIVES_DIRECTIVE = $(addsuffix .directive.asc,$(DIST_ARCHIVES))
+
+# A simple rule to test signing, etc.
+.PHONY: distsign
+distsign: $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
+
+%.sig : %
+	@echo "Signing file '$<':"
+	$(GPG) $(GPGFLAGS) -o "$@" -b "$<"
+
+%.directive.asc: %
+	@echo "Creating directive file '$@':"
+	@( \
+	   echo 'verstion: 1.1'; \
+	   echo 'directory: make'; \
+	   echo 'filename: $*'; \
+	   echo 'comment: Official upload of GNU make version $(VERSION)'; \
+	 ) > "$*.directive"
+	$(GPG) $(GPGFLAGS) -o "$@" --clearsign "$*.directive"
+	@rm -f "$*.directive"
+
+# Upload the artifacts
+
+FTPPUT = ncftpput
+gnu-url = ftp-upload.gnu.org /incoming
+
+UPLOADS = upload-alpha upload-ftp
+.PHONY: $(UPLOADS)
+$(UPLOADS): $(DIST_ARCHIVES) $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE)
+	$(FTPPUT) "$(gnu-url)/$(@:upload-%=%)" $^
+
+
+# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+# 2007 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/make.1
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/make.1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/make.1	(revision 1780)
@@ -0,0 +1,365 @@
+.TH MAKE 1 "22 August 1989" "GNU" "LOCAL USER COMMANDS"
+.SH NAME
+make \- GNU make utility to maintain groups of programs
+.SH SYNOPSIS
+.B "make "
+[
+.B \-f
+.I makefile
+] [ options ] ... [ targets ] ...
+.SH WARNING
+This man page is an extract of the documentation of GNU
+.IR make .
+It is updated only occasionally, because the GNU project does not use nroff.
+For complete, current documentation, refer to the Info file
+.B make.info
+which is made from the Texinfo source file
+.BR make.texi .
+.SH DESCRIPTION
+.LP
+The purpose of the
+.I make
+utility is to determine automatically which
+pieces of a large program need to be recompiled, and issue the commands to
+recompile them.
+The manual describes the GNU implementation of
+.IR make ,
+which was written by Richard Stallman and Roland McGrath, and is
+currently maintained by Paul Smith.
+Our examples show C programs, since they are most common, but you can use
+.I make
+with any programming language whose compiler can be run with a
+shell command.
+In fact,
+.I make
+is not limited to programs.
+You can use it to describe any task where some files must be
+updated automatically from others whenever the others change.
+.LP
+To prepare to use
+.IR make ,
+you must write a file called the
+.I makefile
+that describes the relationships among files in your program, and the
+states the commands for updating each file.
+In a program, typically the executable file is updated from object
+files, which are in turn made by compiling source files.
+.LP
+Once a suitable makefile exists, each time you change some source files,
+this simple shell command:
+.sp 1
+.RS
+.B make
+.RE
+.sp 1
+suffices to perform all necessary recompilations.
+The
+.I make
+program uses the makefile data base and the last-modification times
+of the files to decide which of the files need to be updated.
+For each of those files, it issues the commands recorded in the data base.
+.LP
+.I make
+executes commands in the
+.I makefile
+to update
+one or more target
+.IR names ,
+where
+.I name
+is typically a program.
+If no
+.B \-f
+option is present,
+.I make
+will look for the makefiles
+.IR GNUmakefile ,
+.IR makefile ,
+and
+.IR Makefile ,
+in that order.
+.LP
+Normally you should call your makefile either
+.I makefile
+or
+.IR Makefile .
+(We recommend
+.I Makefile
+because it appears prominently near the beginning of a directory
+listing, right near other important files such as
+.IR  README .)
+The first name checked,
+.IR GNUmakefile ,
+is not recommended for most makefiles.
+You should use this name if you have a makefile that is specific to GNU
+.IR make ,
+and will not be understood by other versions of
+.IR make .
+If
+.I makefile
+is `\-', the standard input is read.
+.LP
+.I make
+updates a target if it depends on prerequisite files
+that have been modified since the target was last modified,
+or if the target does not exist.
+.SH OPTIONS
+.sp 1
+.TP 0.5i
+.BR \-b , " \-m"
+These options are ignored for compatibility with other versions of
+.IR make .
+.TP 0.5i
+.BR \-B , " \-\-always\-make"
+Unconditionally make all targets.
+.TP 0.5i
+\fB\-C\fR \fIdir\fR, \fB\-\-directory\fR=\fIdir\fR
+Change to directory
+.I dir
+before reading the makefiles or doing anything else.
+If multiple
+.B \-C
+options are specified, each is interpreted relative to the
+previous one:
+.BR "\-C " /
+.BR "\-C " etc
+is equivalent to
+.BR "\-C " /etc.
+This is typically used with recursive invocations of
+.IR make .
+.TP 0.5i
+.B \-d
+Print debugging information in addition to normal processing.
+The debugging information says which files are being considered for
+remaking, which file-times are being compared and with what results,
+which files actually need to be remade, which implicit rules are
+considered and which are applied---everything interesting about how
+.I make
+decides what to do.
+.TP 0.5i
+.BI \-\-debug "[=FLAGS]"
+Print debugging information in addition to normal processing.
+If the
+.I FLAGS
+are omitted, then the behavior is the same as if
+.B \-d
+was specified.
+.I FLAGS
+may be
+.I a
+for all debugging output (same as using
+.BR \-d ),
+.I b
+for basic debugging,
+.I v
+for more verbose basic debugging,
+.I i
+for showing implicit rules,
+.I j
+for details on invocation of commands, and
+.I m
+for debugging while remaking makefiles.
+.TP 0.5i
+.BR \-e , " \-\-environment\-overrides"
+Give variables taken from the environment precedence
+over variables from makefiles.
+.TP 0.5i
+\fB\-f\fR \fIfile\fR, \fB\-\-file\fR=\fIfile\fR, \fB\-\-makefile\fR=\fIFILE\fR
+Use
+.I file
+as a makefile.
+.TP 0.5i
+.BR \-i , " \-\-ignore\-errors"
+Ignore all errors in commands executed to remake files.
+.TP 0.5i
+\fB\-I\fR \fIdir\fR, \fB\-\-include\-dir\fR=\fIdir\fR
+Specifies a directory
+.I dir
+to search for included makefiles.
+If several
+.B \-I
+options are used to specify several directories, the directories are
+searched in the order specified.
+Unlike the arguments to other flags of
+.IR make ,
+directories given with
+.B \-I
+flags may come directly after the flag:
+.BI \-I dir
+is allowed, as well as
+.BI "\-I " dir.
+This syntax is allowed for compatibility with the C
+preprocessor's
+.B \-I
+flag.
+.TP 0.5i
+\fB\-j\fR [\fIjobs\fR], \fB\-\-jobs\fR[=\fIjobs\fR]
+Specifies the number of
+.I jobs
+(commands) to run simultaneously.
+If there is more than one
+.B \-j
+option, the last one is effective.
+If the
+.B \-j
+option is given without an argument,
+.IR make
+will not limit the number of jobs that can run simultaneously.
+.TP 0.5i
+.BR \-k , " \-\-keep\-going"
+Continue as much as possible after an error.
+While the target that failed, and those that depend on it, cannot
+be remade, the other dependencies of these targets can be processed
+all the same.
+.TP 0.5i
+\fB\-l\fR [\fIload\fR], \fB\-\-load\-average\fR[=\fIload\fR]
+Specifies that no new jobs (commands) should be started if there are
+others jobs running and the load average is at least
+.I load
+(a floating-point number).
+With no argument, removes a previous load limit.
+.TP 0.5i
+.BR \-L , " \-\-check\-symlink\-times"
+Use the latest mtime between symlinks and target.
+.TP 0.5i
+.BR \-n , " \-\-just\-print" , " \-\-dry\-run" , " \-\-recon"
+Print the commands that would be executed, but do not execute them.
+.TP 0.5i
+\fB\-o\fR \fIfile\fR, \fB\-\-old\-file\fR=\fIfile\fR, \fB\-\-assume\-old\fR=\fIfile\fR
+Do not remake the file
+.I file
+even if it is older than its dependencies, and do not remake anything
+on account of changes in
+.IR file .
+Essentially the file is treated as very old and its rules are ignored.
+.TP 0.5i
+.BR \-p , " \-\-print\-data\-base"
+Print the data base (rules and variable values) that results from
+reading the makefiles; then execute as usual or as otherwise
+specified.
+This also prints the version information given by the
+.B \-v
+switch (see below).
+To print the data base without trying to remake any files, use
+.B make
+.B \-p
+.BI \-f /dev/null.
+.TP 0.5i
+.BR \-q , " \-\-question"
+``Question mode''.
+Do not run any commands, or print anything; just return an exit status
+that is zero if the specified targets are already up to date, nonzero
+otherwise.
+.TP 0.5i
+.BR \-r , " \-\-no\-builtin\-rules"
+Eliminate use of the built\-in implicit rules.
+Also clear out the default list of suffixes for suffix rules.
+.TP 0.5i
+.BR \-R , " \-\-no\-builtin\-variables"
+Don't define any built\-in variables.
+.TP 0.5i
+.BR \-s , " \-\-silent" , " \-\-quiet"
+Silent operation; do not print the commands as they are executed.
+.TP 0.5i
+.BR \-S , " \-\-no\-keep\-going" , " \-\-stop"
+Cancel the effect of the
+.B \-k
+option.
+This is never necessary except in a recursive
+.I make
+where
+.B \-k
+might be inherited from the top-level
+.I make
+via MAKEFLAGS or if you set
+.B \-k
+in MAKEFLAGS in your environment.
+.TP 0.5i
+.BR \-t , " \-\-touch"
+Touch files (mark them up to date without really changing them)
+instead of running their commands.
+This is used to pretend that the commands were done, in order to fool
+future invocations of
+.IR make .
+.TP 0.5i
+.BR \-v , " \-\-version"
+Print the version of the
+.I make
+program plus a copyright, a list of authors and a notice that there
+is no warranty.
+.TP 0.5i
+.BR \-w , " \-\-print\-directory"
+Print a message containing the working directory
+before and after other processing.
+This may be useful for tracking down errors from complicated nests of
+recursive
+.I make
+commands.
+.TP 0.5i
+.B \-\-no\-print\-directory
+Turn off
+.BR \-w ,
+even if it was turned on implicitly.
+.TP 0.5i
+\fB\-W\fR \fIfile\fR, \fB\-\-what\-if\fR=\fIfile\fR, \fB\-\-new\-file\fR=\fIfile\fR, \fB\-\-assume\-new\fR=\fIfile\fR
+Pretend that the target
+.I file
+has just been modified.
+When used with the
+.B \-n
+flag, this shows you what would happen if you were to modify that file.
+Without
+.BR \-n ,
+it is almost the same as running a
+.I touch
+command on the given file before running
+.IR make ,
+except that the modification time is changed only in the imagination of
+.IR make .
+.TP 0.5i
+.B \-\-warn\-undefined\-variables
+Warn when an undefined variable is referenced.
+.SH "EXIT STATUS"
+GNU
+.I make
+exits with a status of zero if all makefiles were successfully parsed
+and no targets that were built failed.  A status of one will be returned
+if the
+.B \-q
+flag was used and
+.I make
+determines that a target needs to be rebuilt.  A status of two will be
+returned if any errors were encountered.
+.SH "SEE ALSO"
+.I "The GNU Make Manual"
+.SH BUGS
+See the chapter `Problems and Bugs' in
+.IR "The GNU Make Manual" .
+.SH AUTHOR
+This manual page contributed by Dennis Morse of Stanford University.
+It has been reworked by Roland McGrath.  Further updates contributed by
+Mike Frysinger.
+.SH "COPYRIGHT"
+Copyright (C) 1992, 1993, 1996, 1999 Free Software Foundation, Inc.
+This file is part of GNU
+.IR make .
+.LP
+GNU
+.I make
+is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+.LP
+GNU
+.I make
+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.
+.LP
+You should have received a copy of the GNU General Public License
+along with GNU
+.IR make ;
+see the file COPYING.  If not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
Index: /tags/kBuild-0.1.4/src/kmk/make.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/make.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/make.h	(revision 1780)
@@ -0,0 +1,738 @@
+/* Miscellaneous global declarations and portability cruft for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* We use <config.h> instead of "config.h" so that a compilation
+   using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
+   (which it would do because make.h was found in $srcdir).  */
+#include <config.h>
+#undef  HAVE_CONFIG_H
+#define HAVE_CONFIG_H 1
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+
+/* Specify we want GNU source code.  This must be defined before any
+   system headers are included.  */
+
+#define _GNU_SOURCE 1
+
+
+#ifdef  CRAY
+/* This must happen before #include <signal.h> so
+   that the declaration therein is changed.  */
+# define signal bsdsignal
+#endif
+
+/* If we're compiling for the dmalloc debugger, turn off string inlining.  */
+#if defined(HAVE_DMALLOC_H) && defined(__GNUC__)
+# define __NO_STRING_INLINES
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_TIMEB_H
+/* SCO 3.2 "devsys 4.2" has a prototype for `ftime' in <time.h> that bombs
+   unless <sys/timeb.h> has been included first.  Does every system have a
+   <sys/timeb.h>?  If any does not, configure should check for it.  */
+# include <sys/timeb.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+#ifndef isblank
+# define isblank(c)     ((c) == ' ' || (c) == '\t')
+#endif
+
+#ifdef  HAVE_UNISTD_H
+# include <unistd.h>
+/* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get
+   POSIX.1 behavior with `cc -YPOSIX', which predefines POSIX itself!  */
+# if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS)
+#  define POSIX 1
+# endif
+#endif
+
+/* Some systems define _POSIX_VERSION but are not really POSIX.1.  */
+#if (defined (butterfly) || defined (__arm) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386)))
+# undef POSIX
+#endif
+
+#if !defined (POSIX) && defined (_AIX) && defined (_POSIX_SOURCE)
+# define POSIX 1
+#endif
+
+#ifndef RETSIGTYPE
+# define RETSIGTYPE     void
+#endif
+
+#ifndef sigmask
+# define sigmask(sig)   (1 << ((sig) - 1))
+#endif
+
+#ifndef HAVE_SA_RESTART
+# define SA_RESTART 0
+#endif
+
+#ifdef  HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifdef  HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#ifndef PATH_MAX
+# ifndef POSIX
+#  define PATH_MAX      MAXPATHLEN
+# endif
+#endif
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
+#endif
+
+#ifdef  PATH_MAX
+# define GET_PATH_MAX   PATH_MAX
+# define PATH_VAR(var)  char var[PATH_MAX]
+#else
+# define NEED_GET_PATH_MAX 1
+# define GET_PATH_MAX   (get_path_max ())
+# define PATH_VAR(var)  char *var = alloca (GET_PATH_MAX)
+unsigned int get_path_max (void);
+#endif
+
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+/* Nonzero if the integer type T is signed.  */
+#define INTEGER_TYPE_SIGNED(t) ((t) -1 < 0)
+
+/* The minimum and maximum values for the integer type T.
+   Use ~ (t) 0, not -1, for portability to 1's complement hosts.  */
+#define INTEGER_TYPE_MINIMUM(t) \
+  (! INTEGER_TYPE_SIGNED (t) ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))
+#define INTEGER_TYPE_MAXIMUM(t) (~ (t) 0 - INTEGER_TYPE_MINIMUM (t))
+
+#ifndef CHAR_MAX
+# define CHAR_MAX INTEGER_TYPE_MAXIMUM (char)
+#endif
+
+#ifdef STAT_MACROS_BROKEN
+# ifdef S_ISREG
+#  undef S_ISREG
+# endif
+# ifdef S_ISDIR
+#  undef S_ISDIR
+# endif
+#endif  /* STAT_MACROS_BROKEN.  */
+
+#ifndef S_ISREG
+# define S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
+#endif
+#ifndef S_ISDIR
+# define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
+#endif
+
+#ifdef VMS
+# include <types.h>
+# include <unixlib.h>
+# include <unixio.h>
+# include <perror.h>
+/* Needed to use alloca on VMS.  */
+# include <builtins.h>
+#endif
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+#  define __attribute__(x)
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+   are accepted by gcc versions 2.6.4 (effectively 2.7) and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#  define __format__ format
+#  define __printf__ printf
+# endif
+#endif
+#define UNUSED  __attribute__ ((unused))
+
+#if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)
+# include <stdlib.h>
+# include <string.h>
+# define ANSI_STRING 1
+#else   /* No standard headers.  */
+# ifdef HAVE_STRING_H
+#  include <string.h>
+#  define ANSI_STRING 1
+# else
+#  include <strings.h>
+# endif
+# ifdef HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# else
+void *malloc (int);
+void *realloc (void *, int);
+void free (void *);
+
+void abort (void) __attribute__ ((noreturn));
+void exit (int) __attribute__ ((noreturn));
+# endif /* HAVE_STDLIB_H.  */
+
+#endif /* Standard headers.  */
+
+/* These should be in stdlib.h.  Make sure we have them.  */
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+#ifndef  ANSI_STRING
+
+/* SCO Xenix has a buggy macro definition in <string.h>.  */
+#undef  strerror
+#if !defined(__DECC)
+char *strerror (int errnum);
+#endif
+
+#endif  /* !ANSI_STRING.  */
+#undef  ANSI_STRING
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#define FILE_TIMESTAMP uintmax_t
+
+#if !defined(HAVE_STRSIGNAL)
+char *strsignal (int signum);
+#endif
+
+/* ISDIGIT offers the following features:
+   - Its arg may be any int or unsigned int; it need not be an unsigned char.
+   - It's guaranteed to evaluate its argument exactly once.
+      NOTE!  Make relies on this behavior, don't change it!
+   - It's typically faster.
+   POSIX 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
+   only '0' through '9' are digits.  Prefer ISDIGIT to isdigit() unless
+   it's important to use the locale's definition of `digit' even when the
+   host does not conform to POSIX.  */
+#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
+
+#ifndef iAPX286
+# define streq(a, b) \
+   ((a) == (b) || \
+    (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1))))
+# ifdef HAVE_CASE_INSENSITIVE_FS
+#  define strieq(a, b) \
+    ((a) == (b) \
+     || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \
+         && (*(a) == '\0' || !strcasecmp ((a) + 1, (b) + 1))))
+# else
+#  define strieq(a, b) streq(a, b)
+# endif
+#else
+/* Buggy compiler can't handle this.  */
+# define streq(a, b) (strcmp ((a), (b)) == 0)
+# define strieq(a, b) (strcmp ((a), (b)) == 0)
+#endif
+#define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0)
+
+#if defined(__GNUC__) || defined(ENUM_BITFIELDS)
+# define ENUM_BITFIELD(bits)    :bits
+#else
+# define ENUM_BITFIELD(bits)
+#endif
+
+/* Handle gettext and locales.  */
+
+#if HAVE_LOCALE_H
+# include <locale.h>
+#else
+# define setlocale(category, locale)
+#endif
+
+#include <gettext.h>
+
+#define _(msgid)            gettext (msgid)
+#define N_(msgid)           gettext_noop (msgid)
+#define S_(msg1,msg2,num)   ngettext (msg1,msg2,num)
+
+/* Handle other OSs.  */
+#ifndef PATH_SEPARATOR_CHAR
+# if defined(HAVE_DOS_PATHS)
+#  define PATH_SEPARATOR_CHAR ';'
+# elif defined(VMS)
+#  define PATH_SEPARATOR_CHAR ','
+# else
+#  define PATH_SEPARATOR_CHAR ':'
+# endif
+#endif
+
+/* This is needed for getcwd() and chdir(), on some W32 systems.  */
+#if defined(HAVE_DIRECT_H)
+# include <direct.h>
+#endif
+
+#ifdef WINDOWS32
+# include <fcntl.h>
+# include <malloc.h>
+# define pipe(_p)        _pipe((_p), 512, O_BINARY)
+# define kill(_pid,_sig) w32_kill((_pid),(_sig))
+
+void sync_Path_environment (void);
+int w32_kill (int pid, int sig); /* bird kill -> w32_kill - macro acquired () on the args. */
+char *end_of_token_w32 (const char *s, char stopchar);
+int find_and_set_default_shell (const char *token);
+
+/* indicates whether or not we have Bourne shell */
+extern int no_default_sh_exe;
+
+/* is default_shell unixy? */
+extern int unixy_shell;
+#endif  /* WINDOWS32 */
+
+struct floc
+  {
+    const char *filenm;
+    unsigned long lineno;
+  };
+#define NILF ((struct floc *)0)
+
+#define STRING_SIZE_TUPLE(_s) (_s), (sizeof (_s)-1)
+
+
+
+/* We have to have stdarg.h or varargs.h AND v*printf or doprnt to use
+   variadic versions of these functions.  */
+
+#if HAVE_STDARG_H || HAVE_VARARGS_H
+# if HAVE_VPRINTF || HAVE_DOPRNT
+#  define USE_VARIADIC 1
+# endif
+#endif
+
+#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
+void message (int prefix, const char *fmt, ...)
+              __attribute__ ((__format__ (__printf__, 2, 3)));
+void error (const struct floc *flocp, const char *fmt, ...)
+            __attribute__ ((__format__ (__printf__, 2, 3)));
+void fatal (const struct floc *flocp, const char *fmt, ...)
+                   __attribute__ ((noreturn, __format__ (__printf__, 2, 3)));
+#else
+void message ();
+void error ();
+void fatal ();
+#endif
+
+void die (int) __attribute__ ((noreturn));
+void log_working_directory (int);
+void pfatal_with_name (const char *) __attribute__ ((noreturn));
+void perror_with_name (const char *, const char *);
+char *savestring (const char *, unsigned int);
+char *concat (const char *, const char *, const char *);
+void *xmalloc (unsigned int);
+void *xrealloc (void *, unsigned int);
+char *xstrdup (const char *);
+char *find_next_token (const char **, unsigned int *);
+char *next_token (const char *);
+char *end_of_token (const char *);
+void collapse_continuations (char *);
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS /* memchr is usually compiler intrinsic, thus faster. */
+# define lindex(s, limit, c) ((char *)memchr((s), (c), (limit) - (s)))
+#else
+char *lindex (const char *, const char *, int);
+#endif
+int alpha_compare (const void *, const void *);
+void print_spaces (unsigned int);
+char *find_percent (char *);
+const char *find_percent_cached (const char **);
+FILE *open_tmpfile (char **, const char *);
+
+#ifndef NO_ARCHIVES
+int ar_name (const char *);
+void ar_parse_name (const char *, char **, char **);
+int ar_touch (const char *);
+time_t ar_member_date (const char *);
+
+typedef long int (*ar_member_func_t) (int desc, const char *mem, int truncated,
+				      long int hdrpos, long int datapos,
+				      long int size, long int date, int uid,
+				      int gid, int mode, const void *arg);
+
+long int ar_scan (const char *archive, ar_member_func_t function, const void *arg);
+int ar_name_equal (const char *name, const char *mem, int truncated);
+#ifndef VMS
+int ar_member_touch (const char *arname, const char *memname);
+#endif
+#endif
+
+int dir_file_exists_p (const char *, const char *);
+int file_exists_p (const char *);
+int file_impossible_p (const char *);
+void file_impossible (const char *);
+const char *dir_name (const char *);
+void hash_init_directories (void);
+
+void define_default_variables (void);
+void set_default_suffixes (void);
+void install_default_suffix_rules (void);
+void install_default_implicit_rules (void);
+
+void build_vpath_lists (void);
+void construct_vpath_list (char *pattern, char *dirpath);
+const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr);
+int gpath_search (const char *file, unsigned int len);
+
+void construct_include_path (const char **arg_dirs);
+
+void user_access (void);
+void make_access (void);
+void child_access (void);
+
+void close_stdout (void);
+
+char *strip_whitespace (const char **begpp, const char **endpp);
+
+/* String caching  */
+void strcache_init (void);
+void strcache_print_stats (const char *prefix);
+int strcache_iscached (const char *str);
+const char *strcache_add (const char *str);
+const char *strcache_add_len (const char *str, int len);
+int strcache_setbufsize (int size);
+
+#ifdef  HAVE_VFORK_H
+# include <vfork.h>
+#endif
+
+/* We omit these declarations on non-POSIX systems which define _POSIX_VERSION,
+   because such systems often declare them in header files anyway.  */
+
+#if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32)
+
+long int atol ();
+# ifndef VMS
+long int lseek ();
+# endif
+
+#endif  /* Not GNU C library or POSIX.  */
+
+#ifdef  HAVE_GETCWD
+# if !defined(VMS) && !defined(__DECC) && !defined(_MSC_VER) /* bird: MSC */
+char *getcwd ();
+# endif
+#else
+char *getwd ();
+# define getcwd(buf, len)       getwd (buf)
+#endif
+
+#if !HAVE_STRCASECMP
+# if HAVE_STRICMP
+#  define strcasecmp stricmp
+# elif HAVE_STRCMPI
+#  define strcasecmp strcmpi
+# else
+/* Create our own, in misc.c */
+int strcasecmp (const char *s1, const char *s2);
+# endif
+#endif
+
+extern const struct floc *reading_file;
+extern const struct floc **expanding_var;
+
+#if !defined(_MSC_VER) /* bird */
+extern char **environ;
+#endif
+
+extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag;
+extern int print_data_base_flag, question_flag, touch_flag, always_make_flag;
+extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
+extern int print_version_flag, print_directory_flag, check_symlink_flag;
+extern int warn_undefined_variables_flag, posix_pedantic, not_parallel;
+extern int second_expansion, clock_skew_detected, rebuilding_makefiles;
+#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
+extern int second_target_expansion;
+#endif
+#ifdef CONFIG_PRETTY_COMMAND_PRINTING
+extern int pretty_command_printing;
+#endif
+#ifdef CONFIG_WITH_MAKE_STATS
+extern int make_expensive_statistics;
+#endif
+
+
+/* can we run commands via 'sh -c xxx' or must we use batch files? */
+extern int batch_mode_shell;
+
+extern char cmd_prefix;
+
+extern unsigned int job_slots;
+extern int job_fds[2];
+extern int job_rfd;
+#ifndef NO_FLOAT
+extern double max_load_average;
+#else
+extern int max_load_average;
+#endif
+
+extern char *program;
+extern char *starting_directory;
+extern unsigned int makelevel;
+extern char *version_string, *remote_description, *make_host;
+
+extern unsigned int commands_started;
+
+extern int handling_fatal_signal;
+
+
+#ifndef MIN
+#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
+#endif
+#ifndef MAX
+#define MAX(_a,_b) ((_a)>(_b)?(_a):(_b))
+#endif
+
+#ifdef VMS
+#  define MAKE_SUCCESS 1
+#  define MAKE_TROUBLE 2
+#  define MAKE_FAILURE 3
+#else
+#  define MAKE_SUCCESS 0
+#  define MAKE_TROUBLE 1
+#  define MAKE_FAILURE 2
+#endif
+
+/* Set up heap debugging library dmalloc.  */
+
+#ifdef HAVE_DMALLOC_H
+#include <dmalloc.h>
+#endif
+
+#ifndef initialize_main
+# ifdef __EMX__
+#  define initialize_main(pargc, pargv) \
+                          { _wildcard(pargc, pargv); _response(pargc, pargv); }
+# else
+#  define initialize_main(pargc, pargv)
+# endif
+#endif
+
+#ifdef __EMX__
+# if !defined chdir
+#  define chdir _chdir2
+# endif
+# if !defined getcwd
+#  define getcwd _getcwd2
+# endif
+
+/* NO_CHDIR2 causes make not to use _chdir2() and _getcwd2() instead of
+   chdir() and getcwd(). This avoids some error messages for the
+   make testsuite but restricts the drive letter support. */
+# ifdef NO_CHDIR2
+#  warning NO_CHDIR2: usage of drive letters restricted
+#  undef chdir
+#  undef getcwd
+# endif
+#endif
+
+#ifndef initialize_main
+# define initialize_main(pargc, pargv)
+#endif
+
+
+/* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag
+   properly according to POSIX.  So, we try to wrap common system calls with
+   checks for EINTR.  Note that there are still plenty of system calls that
+   can fail with EINTR but this, reportedly, gets the vast majority of
+   failure cases.  If you still experience failures you'll need to either get
+   a system where SA_RESTART works, or you need to avoid -j.  */
+
+#define EINTRLOOP(_v,_c)   while (((_v)=_c)==-1 && errno==EINTR)
+
+/* While system calls that return integers are pretty consistent about
+   returning -1 on failure and setting errno in that case, functions that
+   return pointers are not always so well behaved.  Sometimes they return
+   NULL for expected behavior: one good example is readdir() which returns
+   NULL at the end of the directory--and _doesn't_ reset errno.  So, we have
+   to do it ourselves here.  */
+
+#define ENULLLOOP(_v,_c)   do { errno = 0; (_v) = _c; } \
+                           while((_v)==0 && errno==EINTR)
+
+
+#if defined(__EMX__) && defined(CONFIG_WITH_OPTIMIZATION_HACKS) /* bird: saves 40-100ms on libc. */
+static inline void *__my_rawmemchr (const void *__s, int __c);
+#undef strchr
+#define strchr(s, c) \
+  (__extension__ (__builtin_constant_p (c)				      \
+		  ? ((c) == '\0'					      \
+		     ? (char *) __my_rawmemchr ((s), (c))			      \
+		     : __my_strchr_c ((s), ((c) & 0xff) << 8))		      \
+		  : __my_strchr_g ((s), (c))))
+static inline char *__my_strchr_c (const char *__s, int __c)
+{
+  register unsigned long int __d0;
+  register char *__res;
+  __asm__ __volatile__
+    ("1:\n\t"
+     "movb	(%0),%%al\n\t"
+     "cmpb	%%ah,%%al\n\t"
+     "je	2f\n\t"
+     "leal	1(%0),%0\n\t"
+     "testb	%%al,%%al\n\t"
+     "jne	1b\n\t"
+     "xorl	%0,%0\n"
+     "2:"
+     : "=r" (__res), "=&a" (__d0)
+     : "0" (__s), "1" (__c),
+       "m" ( *(struct { char __x[0xfffffff]; } *)__s)
+     : "cc");
+  return __res;
+}
+
+static inline char *__my_strchr_g (__const char *__s, int __c)
+{
+  register unsigned long int __d0;
+  register char *__res;
+  __asm__ __volatile__
+    ("movb	%%al,%%ah\n"
+     "1:\n\t"
+     "movb	(%0),%%al\n\t"
+     "cmpb	%%ah,%%al\n\t"
+     "je	2f\n\t"
+     "leal	1(%0),%0\n\t"
+     "testb	%%al,%%al\n\t"
+     "jne	1b\n\t"
+     "xorl	%0,%0\n"
+     "2:"
+     : "=r" (__res), "=&a" (__d0)
+     : "0" (__s), "1" (__c),
+       "m" ( *(struct { char __x[0xfffffff]; } *)__s)
+     : "cc");
+  return __res;
+}
+
+static inline void *__my_rawmemchr (const void *__s, int __c)
+{
+  register unsigned long int __d0;
+  register unsigned char *__res;
+  __asm__ __volatile__
+    ("cld\n\t"
+     "repne; scasb\n\t"
+     : "=D" (__res), "=&c" (__d0)
+     : "a" (__c), "0" (__s), "1" (0xffffffff),
+       "m" ( *(struct { char __x[0xfffffff]; } *)__s)
+     : "cc");
+  return __res - 1;
+}
+
+#undef memchr
+#define memchr(a,b,c) __my_memchr((a),(b),(c))
+static inline void *__my_memchr (__const void *__s, int __c, size_t __n)
+{
+  register unsigned long int __d0;
+  register unsigned char *__res;
+  if (__n == 0)
+    return NULL;
+  __asm__ __volatile__
+    ("repne; scasb\n\t"
+     "je	1f\n\t"
+     "movl	$1,%0\n"
+     "1:"
+     : "=D" (__res), "=&c" (__d0)
+     : "a" (__c), "0" (__s), "1" (__n),
+       "m" ( *(struct { __extension__ char __x[__n]; } *)__s)
+     : "cc");
+  return __res - 1;
+}
+
+#endif /* __EMX__ (bird) */
+
+#ifdef CONFIG_WITH_MAKE_STATS
+extern unsigned long make_stats_allocations;
+extern unsigned long make_stats_allocated;
+extern unsigned long make_stats_allocated_sum;
+extern unsigned long make_stats_ht_lookups;
+extern unsigned long make_stats_ht_collisions;
+
+# ifdef __APPLE__
+#  include <malloc/malloc.h>
+#  define SIZE_OF_HEAP_BLOCK(ptr)   malloc_size(ptr)
+
+# elif defined(__linux__) /* glibc */
+#  include <malloc.h>
+#  define SIZE_OF_HEAP_BLOCK(ptr)   malloc_usable_size(ptr)
+
+# elif defined(_MSC_VER) || defined(__OS2__)
+#  define SIZE_OF_HEAP_BLOCK(ptr)   _msize(ptr)
+
+# else
+#  include <stdlib.h>
+#  define SIZE_OF_HEAP_BLOCK(ptr)   0
+#endif
+
+# if defined(CONFIG_WITH_MAKE_STATS) && !defined(ELECTRIC_HEAP)
+#  define free xfree
+extern void xfree (void *);
+# endif
+
+#endif
+
+#ifdef CONFIG_WITH_IF_CONDITIONALS
+extern int expr_eval_if_conditionals(char *line, const struct floc *flocp);
+extern char *expr_eval_to_string(char *o, char *expr);
+#endif
+
+#ifdef KMK
+extern char *abspath(const char *name, char *apath);
+extern char *func_breakpoint(char *o, char **argv, const char *funcname);
+#endif 
Index: /tags/kBuild-0.1.4/src/kmk/make.lnk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/make.lnk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/make.lnk	(revision 1780)
@@ -0,0 +1,5 @@
+FROM LIB:cres.o "commands.o"+"job.o"+"dir.o"+"file.o"+"misc.o"+"main.o"+"read.o"+"remake.o"+"rule.o"+"implicit.o"+"default.o"+"variable.o"+"expand.o"+"function.o"+"vpath.o"+"version.o"+"ar.o"+"arscan.o"+"signame.o"+"remote-stub.o"+"getopt.o"+"getopt1.o"+"alloca.o"+"amiga.o"+"hash.o"+"strcache.o"
+TO "make.new"
+LIB glob/glob.lib LIB:sc.lib LIB:amiga.lib
+QUIET
+
Index: /tags/kBuild-0.1.4/src/kmk/make_msvc_net2003.sln
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/make_msvc_net2003.sln	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/make_msvc_net2003.sln	(revision 1780)
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_msvc.net2003", "make_msvc_net2003.vcproj", "{E96B5060-3240-4723-91C9-E64F1C877A04}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{E96B5060-3240-4723-91C9-E64F1C877A04}.Debug.ActiveCfg = Debug|Win32
+		{E96B5060-3240-4723-91C9-E64F1C877A04}.Debug.Build.0 = Debug|Win32
+		{E96B5060-3240-4723-91C9-E64F1C877A04}.Release.ActiveCfg = Release|Win32
+		{E96B5060-3240-4723-91C9-E64F1C877A04}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
Index: /tags/kBuild-0.1.4/src/kmk/make_msvc_net2003.vcproj
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/make_msvc_net2003.vcproj	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/make_msvc_net2003.vcproj	(revision 1780)
@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="make_msvc.net2003"
+	ProjectGUID="{E96B5060-3240-4723-91C9-E64F1C877A04}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".;w32/include;glob"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;HAVE_CONFIG_H=1;WINDOWS32=1"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				ForceConformanceInForLoopScope="TRUE"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				SuppressStartupBanner="TRUE"
+				Detect64BitPortabilityProblems="FALSE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/make_msvc.net2003.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/make_msvc.net2003.pdb"
+				SubSystem="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"
+				Description="Copying config.h.W32 to config.h"
+				CommandLine="if not exist config.h copy config.h.W32 config.h"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".;w32/include;glob"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;HAVE_CONFIG_H=1;WINDOWS32=1"
+				RuntimeLibrary="0"
+				ForceConformanceInForLoopScope="TRUE"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="FALSE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/make_msvc.net2003.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="TRUE"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"
+				Description="Copying config.h.W32 to config.h"
+				CommandLine="if not exist config.h copy config.h.W32 config.h"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="src"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\ar.c">
+			</File>
+			<File
+				RelativePath=".\arscan.c">
+			</File>
+			<File
+				RelativePath=".\commands.c">
+			</File>
+			<File
+				RelativePath=".\default.c">
+			</File>
+			<File
+				RelativePath=".\dir.c">
+			</File>
+			<File
+				RelativePath=".\expand.c">
+			</File>
+			<File
+				RelativePath=".\file.c">
+			</File>
+			<File
+				RelativePath=".\function.c">
+			</File>
+			<File
+				RelativePath=".\getloadavg.c">
+			</File>
+			<File
+				RelativePath=".\getopt.c">
+			</File>
+			<File
+				RelativePath=".\getopt1.c">
+			</File>
+			<File
+				RelativePath=".\hash.c">
+			</File>
+			<File
+				RelativePath=".\strcache.c">
+			</File>
+			<File
+				RelativePath=".\implicit.c">
+			</File>
+			<File
+				RelativePath=".\job.c">
+			</File>
+			<File
+				RelativePath=".\main.c">
+			</File>
+			<File
+				RelativePath=".\misc.c">
+			</File>
+			<File
+				RelativePath=".\read.c">
+			</File>
+			<File
+				RelativePath=".\remake.c">
+			</File>
+			<File
+				RelativePath=".\remote-stub.c">
+			</File>
+			<File
+				RelativePath=".\rule.c">
+			</File>
+			<File
+				RelativePath=".\signame.c">
+			</File>
+			<File
+				RelativePath=".\variable.c">
+			</File>
+			<File
+				RelativePath=".\version.c">
+			</File>
+			<File
+				RelativePath=".\vpath.c">
+			</File>
+			<Filter
+				Name="w32"
+				Filter="">
+				<File
+					RelativePath=".\w32\compat\dirent.c">
+				</File>
+				<File
+					RelativePath=".\w32\subproc\misc.c">
+					<FileConfiguration
+						Name="Debug|Win32">
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32">
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath=".\w32\pathstuff.c">
+				</File>
+				<File
+					RelativePath=".\w32\subproc\sub_proc.c">
+				</File>
+				<File
+					RelativePath=".\w32\subproc\w32err.c">
+				</File>
+			</Filter>
+			<Filter
+				Name="glob"
+				Filter="">
+				<File
+					RelativePath=".\glob\fnmatch.c">
+				</File>
+				<File
+					RelativePath=".\glob\glob.c">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="include"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\commands.h">
+			</File>
+			<File
+				RelativePath=".\config.h">
+			</File>
+			<File
+				RelativePath=".\debug.h">
+			</File>
+			<File
+				RelativePath=".\dep.h">
+			</File>
+			<File
+				RelativePath=".\filedef.h">
+			</File>
+			<File
+				RelativePath=".\getopt.h">
+			</File>
+			<File
+				RelativePath=".\gettext.h">
+			</File>
+			<File
+				RelativePath=".\hash.h">
+			</File>
+			<File
+				RelativePath=".\job.h">
+			</File>
+			<File
+				RelativePath=".\make.h">
+			</File>
+			<File
+				RelativePath=".\rule.h">
+			</File>
+			<File
+				RelativePath=".\variable.h">
+			</File>
+			<File
+				RelativePath=".\vmsdir.h">
+			</File>
+			<Filter
+				Name="w32"
+				Filter="">
+				<File
+					RelativePath=".\w32\include\dirent.h">
+				</File>
+				<File
+					RelativePath=".\w32\include\pathstuff.h">
+				</File>
+				<File
+					RelativePath=".\w32\subproc\proc.h">
+				</File>
+				<File
+					RelativePath=".\w32\include\sub_proc.h">
+				</File>
+				<File
+					RelativePath=".\w32\include\w32err.h">
+				</File>
+			</Filter>
+			<Filter
+				Name="glob"
+				Filter="">
+				<File
+					RelativePath=".\glob\fnmatch.h">
+				</File>
+				<File
+					RelativePath=".\glob\glob.h">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /tags/kBuild-0.1.4/src/kmk/makefile.com
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/makefile.com	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/makefile.com	(revision 1780)
@@ -0,0 +1,155 @@
+$!
+$! Makefile.com - builds GNU Make for VMS
+$!
+$! P1 is non-empty if you want to link with the VAXCRTL library instead
+$!    of the shareable executable
+$! P2 = DEBUG will build an image with debug information
+$! P3 = WALL will enable all warning messages (some are suppressed since
+$!      one macro intentionally causes an error condition)
+$!
+$! In case of problems with the install you might contact me at
+$! zinser@decus.de (preferred) or zinser@sysdev.deutsche-boerse.com
+$
+$! hb
+$! But don't ask Martin Zinser about the lines, I added/changed.
+$! In case of an error do some cleanup
+$ on error then $ goto cleanup
+$! in case somebody set up her/his own symbol for cc
+$ set symbol/scope=(nolocal,noglobal)
+$!
+$! Just some general constants...
+$!
+$ true  = 1
+$ false = 0
+$ tmpnam = "temp_" + f$getjpi("","pid")
+$ tt = tmpnam + ".txt"
+$ tc = tmpnam + ".c"
+$!
+$! Look for the compiler used
+$!
+$ lval = ""
+$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
+$  then
+$   if f$trnlnm("SYS").eqs."" then def/nolog sys sys$library:
+$   ccopt = ""
+$  else
+$   ccopt = "/decc/prefix=(all,except=(globfree,glob))"
+$   if f$trnlnm("SYS").eqs.""
+$    then
+$     if f$trnlnm("DECC$LIBRARY_INCLUDE").nes.""
+$      then
+$       define sys decc$library_include:
+$      else
+$       if f$search("SYS$COMMON:[DECC$LIB.REFERENCE]DECC$RTLDEF.DIR").nes."" -
+           then lval = "SYS$COMMON:[DECC$LIB.REFERENCE.DECC$RTLDEF],"
+$       if f$search("SYS$COMMON:[DECC$LIB.REFERENCE]SYS$STARLET_C.DIR").nes."" -
+           then lval = lval+"SYS$COMMON:[DECC$LIB.REFERENCE.SYS$STARLET_C],"
+$       lval=lval+"SYS$LIBRARY:"
+$       define sys 'lval
+$      endif
+$   endif
+$ endif
+$!
+$! Should we build a debug image
+$!
+$ if (p2.eqs."DEBUG")
+$  then
+$   ccopt = ccopt + "/noopt/debug"
+$   lopt = "/debug"
+$ else
+$   lopt = ""
+$ endif
+$!
+$! Do we want to see all warnings
+$!
+$ if (p3.nes."WALL")
+$ then
+$   gosub check_cc_qual
+$ endif
+$ filelist = "alloca ar arscan commands default dir expand file function " + -
+             "hash implicit job main misc read remake remote-stub rule " + -
+	     "signame variable version vmsfunctions vmsify vpath " + -
+	     "[.glob]glob [.glob]fnmatch getopt1 getopt strcache"
+$ copy config.h-vms config.h
+$ n=0
+$ open/write optf make.opt
+$ loop:
+$ cfile = f$elem(n," ",filelist)
+$ if cfile .eqs. " " then goto linkit
+$ write sys$output "Compiling ''cfile'..."
+$ call compileit 'cfile' 'p1'
+$ n = n + 1
+$ goto loop
+$ linkit:
+$ close optf
+$ if p1 .nes. "" then goto link_using_library
+$ link/exe=make make.opt/opt'lopt
+$ goto cleanup
+$
+$ link_using_library:
+$ link/exe=make make.opt/opt,sys$library:vaxcrtl/lib'lopt
+$
+$ cleanup:
+$ if f$trnlnm("SYS").nes."" then $ deassign sys
+$ if f$trnlnm("OPTF").nes."" then $ close optf
+$ if f$search("make.opt").nes."" then $ del make.opt;*
+$ exit
+$!
+$!-----------------------------------------------------------------------------
+$!
+$! Check if this is a define relating to the properties of the C/C++
+$! compiler
+$!
+$CHECK_CC_QUAL:
+$ open/write tmpc 'tc
+$ ccqual = "/warn=(disable=questcompare)"
+$ write tmpc "#include <stdio.h>"
+$ write tmpc "unsigned int i = 1;"
+$ write tmpc "int main(){"
+$ write tmpc "if (i < 0){printf(""Mission impossible\n"");}}"
+$ close tmpc
+$ gosub cc_qual_check
+$ return
+$!
+$!-----------------------------------------------------------------------------
+$!
+$! Check for properties of C/C++ compiler
+$!
+$CC_QUAL_CHECK:
+$ cc_qual = false
+$ set message/nofac/noident/nosever/notext
+$ cc 'ccqual' 'tmpnam'
+$ if $status then cc_qual = true
+$ set message/fac/ident/sever/text
+$ delete/nolog 'tmpnam'.*;*
+$ if cc_qual then ccopt = ccopt + ccqual
+$ return
+$!-----------------------------------------------------------------------------
+$!
+$ compileit : subroutine
+$ ploc = f$locate("]",p1)
+$ filnam = p1
+$ if ploc .lt. f$length(p1) then filnam=f$extract(ploc+1,100,p1)
+$ write optf "''filnam'"
+$ cc'ccopt'/include=([],[.glob]) -
+  /define=("allocated_variable_expand_for_file=alloc_var_expand_for_file","unlink=remove","HAVE_CONFIG_H","VMS") -
+  'p1'
+$ exit
+$ endsubroutine : compileit
+$!
+$!-----------------------------------------------------------------------------
+$!Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+$!2006 Free Software Foundation, Inc.
+$!This file is part of GNU Make.
+$!
+$!GNU Make is free software; you can redistribute it and/or modify it under the
+$!terms of the GNU General Public License as published by the Free Software
+$!Foundation; either version 2, or (at your option) any later version.
+$!
+$!GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+$!WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+$!A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+$!
+$!You should have received a copy of the GNU General Public License along with
+$!GNU Make; see the file COPYING.  If not, write to the Free Software
+$!Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/makefile.vms
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/makefile.vms	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/makefile.vms	(revision 1780)
@@ -0,0 +1,148 @@
+# -*-Makefile-*- to build GNU make on VMS
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+# 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# VMS extensions from GNU Make 3.60 imported by
+#  Klaus Kämpf (kkaempf@rmi.de)
+# Modified for version 3.78.1 by Hartmut.Becker@compaq.com.
+# Modified for version 3.80 by zinser@decus.de
+# Modified for version 3.81 by Hartmut Becker
+
+CC = cc
+CP = copy
+
+%.obj: %.c
+	$(CC) $(CFLAGS)/obj=$@ $<
+#
+#	Makefile for GNU Make
+#
+
+ifeq ($(CC),cc)
+CFLAGS = $(defines) /include=([],[.glob])/prefix=(all,except=(glob,globfree))/standard=relaxed/warn=(disable=questcompare)
+else
+CFLAGS = $(defines) /include=([],[.glob])
+endif
+#LDFLAGS = /deb
+LDFLAGS =
+
+ifeq ($(CC),cc)
+defines = /define=("unlink=remove","HAVE_CONFIG_H","VMS","allocated_variable_expand_for_file=alloc_var_expand_for_file")
+else
+ifeq ($(ARCH),VAX)
+defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE","VAX")
+else
+defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE")
+endif
+endif
+
+LOAD_AVG = /define="NO_LDAV"
+
+# If you don't want archive support, comment these out.
+ARCHIVES = ,ar.obj,arscan.obj
+ARCHIVES_SRC = ar.c arscan.c
+
+# If your system needs extra libraries loaded in, define them here.
+# System V probably need -lPW for alloca.
+# if on vax, uncomment the following line
+#LOADLIBES = ,c.opt/opt
+ifeq ($(CC),cc)
+#LOADLIBES =,sys$$library:vaxcrtl.olb/lib
+CRT0 =
+else
+LOADLIBES =,gnu_cc_library:libgcc.olb/lib
+endif
+
+# If your system doesn't have alloca, or the one provided is bad,
+# get it from the Emacs distribution and define these.
+#ALLOCA = ,alloca.obj
+#ALLOCASRC = alloca.c
+
+# If there are remote execution facilities defined,
+# enable them with switches here (see remote-*.c).
+REMOTE =
+
+# Any extra object files your system needs.
+extras = ,signame.obj,remote-stub.obj,vmsfunctions.obj,vmsify.obj
+#,directory.obj
+# as an alternative:
+glob = ,[.glob]glob.obj,[.glob]fnmatch.obj
+getopt = ,getopt.obj,getopt1.obj
+# Directory to install `make' in.
+bindir = []
+# Directory to install the man page in.
+mandir = []
+# Number to put on the man page filename.
+manext = 1
+
+objs = commands.obj,job.obj,dir.obj,file.obj,misc.obj,hash.obj,\
+       main.obj,read.obj,remake.obj,rule.obj,implicit.obj,\
+       default.obj,variable.obj,expand.obj,function.obj,strcache.obj,\
+       vpath.obj,version.obj$(ARCHIVES)$(ALLOCA)$(extras)$(getopt)$(glob)
+srcs = commands.c job.c dir.c file.c misc.c  hash.c \
+	main.c read.c remake.c rule.c implicit.c \
+	default.c variable.c expand.c function.c strcache.c \
+	vpath.c version.c vmsfunctions.c vmsify.c $(ARCHIVES_SRC) $(ALLOCASRC) \
+	commands.h dep.h filedef.h job.h make.h rule.h variable.h
+
+
+.PHONY: all doc
+all: config.h make.exe
+
+doc: make.info make.dvi
+
+
+make.exe: $(objs)
+	$(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)$(CRT0)
+
+.PHONY: clean realclean
+clean:
+	$$ purge [...]
+	-$(RM) make.exe;,*.obj;
+	-$(RM) [.glob]*.obj;
+
+# Automatically generated dependencies.
+commands.obj: commands.c make.h dep.h commands.h filedef.h variable.h job.h
+job.obj: job.c vmsjobs.c make.h commands.h job.h filedef.h variable.h
+dir.obj: dir.c make.h
+file.obj: file.c make.h commands.h dep.h filedef.h variable.h
+misc.obj: misc.c make.h dep.h
+hash.obj: hash.c make.h hash.h
+strcache.obj: strcache.c make.h hash.h
+main.obj: main.c make.h commands.h dep.h filedef.h variable.h job.h
+read.obj: read.c make.h commands.h dep.h filedef.h variable.h
+remake.obj: remake.c make.h commands.h job.h dep.h filedef.h
+rule.obj: rule.c make.h commands.h dep.h filedef.h variable.h rule.h
+implicit.obj: implicit.c make.h rule.h dep.h filedef.h
+default.obj: default.c make.h rule.h dep.h filedef.h commands.h variable.h
+variable.obj: variable.c make.h commands.h variable.h dep.h filedef.h
+expand.obj: expand.c make.h commands.h filedef.h variable.h
+function.obj: function.c make.h variable.h dep.h commands.h job.h
+vpath.obj: vpath.c make.h filedef.h variable.h
+version.obj: version.c config.h
+arscan.obj: arscan.c
+ar.obj: ar.c make.h filedef.h
+signame.obj: signame.c
+remote-stub.obj: remote-stub.c
+[.glob]glob.obj: [.glob]glob.c
+[.glob]fnmatch.obj: [.glob]fnmatch.c
+getopt.obj: getopt.c
+getopt1.obj: getopt1.c
+vmsfunctions.obj: vmsfunctions.c make.h vmsdir.h
+vmsify.obj: vmsify.c make.h
+
+config.h: config.h-vms
+	$(CP) $< $@
Index: /tags/kBuild-0.1.4/src/kmk/misc.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/misc.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/misc.c	(revision 1780)
@@ -0,0 +1,976 @@
+/* Miscellaneous generic support functions for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "dep.h"
+#include "debug.h"
+
+/* All bcopy calls in this file can be replaced by memcpy and save a tick or two. */
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+# undef bcopy
+# if defined(__GNUC__) && defined(CONFIG_WITH_OPTIMIZATION_HACKS)
+#  define bcopy(src, dst, size)   __builtin_memcpy ((dst), (src), (size))
+# else
+#  define bcopy(src, dst, size)   memcpy ((dst), (src), (size))
+# endif
+#endif
+
+/* Variadic functions.  We go through contortions to allow proper function
+   prototypes for both ANSI and pre-ANSI C compilers, and also for those
+   which support stdarg.h vs. varargs.h, and finally those which have
+   vfprintf(), etc. and those who have _doprnt... or nothing.
+
+   This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and
+   VA_END macros used here since we have multiple print functions.  */
+
+#if USE_VARIADIC
+# if HAVE_STDARG_H
+#  include <stdarg.h>
+#  define VA_START(args, lastarg) va_start(args, lastarg)
+# else
+#  include <varargs.h>
+#  define VA_START(args, lastarg) va_start(args)
+# endif
+# if HAVE_VPRINTF
+#  define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args))
+# else
+#  define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp))
+# endif
+# define VA_END(args) va_end(args)
+#else
+/* We can't use any variadic interface! */
+# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
+# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
+# define VA_START(args, lastarg)
+# define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist)
+# define VA_END(args)
+#endif
+
+
+/* Compare strings *S1 and *S2.
+   Return negative if the first is less, positive if it is greater,
+   zero if they are equal.  */
+
+int
+alpha_compare (const void *v1, const void *v2)
+{
+  const char *s1 = *((char **)v1);
+  const char *s2 = *((char **)v2);
+
+  if (*s1 != *s2)
+    return *s1 - *s2;
+  return strcmp (s1, s2);
+}
+
+
+/* Discard each backslash-newline combination from LINE.
+   Backslash-backslash-newline combinations become backslash-newlines.
+   This is done by copying the text at LINE into itself.  */
+
+void
+collapse_continuations (char *line)
+{
+  register char *in, *out, *p;
+  register int backslash;
+  register unsigned int bs_write;
+
+  in = strchr (line, '\n');
+  if (in == 0)
+    return;
+
+  out = in;
+  while (out > line && out[-1] == '\\')
+    --out;
+
+  while (*in != '\0')
+    {
+      /* BS_WRITE gets the number of quoted backslashes at
+	 the end just before IN, and BACKSLASH gets nonzero
+	 if the next character is quoted.  */
+      backslash = 0;
+      bs_write = 0;
+      for (p = in - 1; p >= line && *p == '\\'; --p)
+	{
+	  if (backslash)
+	    ++bs_write;
+	  backslash = !backslash;
+
+	  /* It should be impossible to go back this far without exiting,
+	     but if we do, we can't get the right answer.  */
+	  if (in == out - 1)
+	    abort ();
+	}
+
+      /* Output the appropriate number of backslashes.  */
+      while (bs_write-- > 0)
+	*out++ = '\\';
+
+      /* Skip the newline.  */
+      ++in;
+
+      /* If the newline is quoted, discard following whitespace
+	 and any preceding whitespace; leave just one space.  */
+      if (backslash)
+	{
+	  in = next_token (in);
+	  while (out > line && isblank ((unsigned char)out[-1]))
+	    --out;
+	  *out++ = ' ';
+	}
+      else
+	/* If the newline isn't quoted, put it in the output.  */
+	*out++ = '\n';
+
+      /* Now copy the following line to the output.
+	 Stop when we find backslashes followed by a newline.  */
+      while (*in != '\0')
+	if (*in == '\\')
+	  {
+	    p = in + 1;
+	    while (*p == '\\')
+	      ++p;
+	    if (*p == '\n')
+	      {
+		in = p;
+		break;
+	      }
+	    while (in < p)
+	      *out++ = *in++;
+	  }
+	else
+	  *out++ = *in++;
+    }
+
+  *out = '\0';
+}
+
+
+/* Print N spaces (used in debug for target-depth).  */
+
+void
+print_spaces (unsigned int n)
+{
+  while (n-- > 0)
+    putchar (' ');
+}
+
+
+
+/* Return a string whose contents concatenate those of s1, s2, s3.
+   This string lives in static, re-used memory.  */
+
+char *
+concat (const char *s1, const char *s2, const char *s3)
+{
+  unsigned int len1, len2, len3;
+  static unsigned int rlen = 0;
+  static char *result = NULL;
+
+  len1 = (s1 && *s1 != '\0') ? strlen (s1) : 0;
+  len2 = (s2 && *s2 != '\0') ? strlen (s2) : 0;
+  len3 = (s3 && *s3 != '\0') ? strlen (s3) : 0;
+
+  if (len1 + len2 + len3 + 1 > rlen)
+    result = xrealloc (result, (rlen = len1 + len2 + len3 + 10));
+
+  if (len1)
+    memcpy (result, s1, len1);
+  if (len2)
+    memcpy (result + len1, s2, len2);
+  if (len3)
+    memcpy (result + len1 + len2, s3, len3);
+
+  result[len1+len2+len3] = '\0';
+
+  return result;
+}
+
+
+/* Print a message on stdout.  */
+
+void
+#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
+message (int prefix, const char *fmt, ...)
+#else
+message (prefix, fmt, va_alist)
+     int prefix;
+     const char *fmt;
+     va_dcl
+#endif
+{
+#if USE_VARIADIC
+  va_list args;
+#endif
+
+  log_working_directory (1);
+
+  if (fmt != 0)
+    {
+      if (prefix)
+	{
+	  if (makelevel == 0)
+	    printf ("%s: ", program);
+	  else
+	    printf ("%s[%u]: ", program, makelevel);
+	}
+      VA_START (args, fmt);
+      VA_PRINTF (stdout, fmt, args);
+      VA_END (args);
+      putchar ('\n');
+    }
+
+  fflush (stdout);
+}
+
+/* Print an error message.  */
+
+void
+#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
+error (const struct floc *flocp, const char *fmt, ...)
+#else
+error (flocp, fmt, va_alist)
+     const struct floc *flocp;
+     const char *fmt;
+     va_dcl
+#endif
+{
+#if USE_VARIADIC
+  va_list args;
+#endif
+
+  log_working_directory (1);
+
+  if (flocp && flocp->filenm)
+    fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
+  else if (makelevel == 0)
+    fprintf (stderr, "%s: ", program);
+  else
+    fprintf (stderr, "%s[%u]: ", program, makelevel);
+
+  VA_START(args, fmt);
+  VA_PRINTF (stderr, fmt, args);
+  VA_END (args);
+
+  putc ('\n', stderr);
+  fflush (stderr);
+}
+
+/* Print an error message and exit.  */
+
+void
+#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
+fatal (const struct floc *flocp, const char *fmt, ...)
+#else
+fatal (flocp, fmt, va_alist)
+     const struct floc *flocp;
+     const char *fmt;
+     va_dcl
+#endif
+{
+#if USE_VARIADIC
+  va_list args;
+#endif
+
+  log_working_directory (1);
+
+  if (flocp && flocp->filenm)
+    fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
+  else if (makelevel == 0)
+    fprintf (stderr, "%s: *** ", program);
+  else
+    fprintf (stderr, "%s[%u]: *** ", program, makelevel);
+
+  VA_START(args, fmt);
+  VA_PRINTF (stderr, fmt, args);
+  VA_END (args);
+
+  fputs (_(".  Stop.\n"), stderr);
+
+  die (2);
+}
+
+#ifndef HAVE_STRERROR
+
+#undef	strerror
+
+char *
+strerror (int errnum)
+{
+  extern int errno, sys_nerr;
+#ifndef __DECC
+  extern char *sys_errlist[];
+#endif
+  static char buf[] = "Unknown error 12345678901234567890";
+
+  if (errno < sys_nerr)
+    return sys_errlist[errnum];
+
+  sprintf (buf, _("Unknown error %d"), errnum);
+  return buf;
+}
+#endif
+
+/* Print an error message from errno.  */
+
+void
+perror_with_name (const char *str, const char *name)
+{
+  error (NILF, _("%s%s: %s"), str, name, strerror (errno));
+}
+
+/* Print an error message from errno and exit.  */
+
+void
+pfatal_with_name (const char *name)
+{
+  fatal (NILF, _("%s: %s"), name, strerror (errno));
+
+  /* NOTREACHED */
+}
+
+
+/* Like malloc but get fatal error if memory is exhausted.  */
+/* Don't bother if we're using dmalloc; it provides these for us.  */
+
+#if !defined(HAVE_DMALLOC_H) && !defined(ELECTRIC_HEAP) /* bird */
+
+#undef xmalloc
+#undef xrealloc
+#undef xstrdup
+
+void *
+xmalloc (unsigned int size)
+{
+  /* Make sure we don't allocate 0, for pre-ANSI libraries.  */
+  void *result = malloc (size ? size : 1);
+  if (result == 0)
+    fatal (NILF, _("virtual memory exhausted"));
+#ifdef CONFIG_WITH_MAKE_STATS
+  make_stats_allocations++;
+  if (make_expensive_statistics)
+    {
+      unsigned int actual_size = SIZE_OF_HEAP_BLOCK (result);
+      make_stats_allocated += actual_size;
+      make_stats_allocated_sum += actual_size;
+    }
+#endif
+  return result;
+}
+
+
+void *
+xrealloc (void *ptr, unsigned int size)
+{
+  void *result;
+#ifdef CONFIG_WITH_MAKE_STATS
+  if (make_expensive_statistics && ptr != NULL)
+    {
+      unsigned int actual_size = SIZE_OF_HEAP_BLOCK (ptr);
+      make_stats_allocated -= actual_size;
+      make_stats_allocated_sum -= actual_size;
+    }
+#endif
+
+  /* Some older implementations of realloc() don't conform to ANSI.  */
+  if (! size)
+    size = 1;
+  result = ptr ? realloc (ptr, size) : malloc (size);
+  if (result == 0)
+    fatal (NILF, _("virtual memory exhausted"));
+#ifdef CONFIG_WITH_MAKE_STATS
+  if (!ptr)
+    make_stats_allocations++;
+  if (make_expensive_statistics)
+    {
+      unsigned int actual_size = SIZE_OF_HEAP_BLOCK (result);
+      make_stats_allocated += actual_size;
+      make_stats_allocated_sum += actual_size;
+    }
+#endif
+  return result;
+}
+
+
+char *
+xstrdup (const char *ptr)
+{
+  char *result;
+
+#ifdef HAVE_STRDUP
+  result = strdup (ptr);
+#else
+  result = malloc (strlen (ptr) + 1);
+#endif
+
+  if (result == 0)
+    fatal (NILF, _("virtual memory exhausted"));
+
+#ifdef CONFIG_WITH_MAKE_STATS
+  make_stats_allocations++;
+  if (make_expensive_statistics)
+    {
+      unsigned int actual_size = SIZE_OF_HEAP_BLOCK (result);
+      make_stats_allocated += actual_size;
+      make_stats_allocated_sum += actual_size;
+    }
+#endif
+#ifdef HAVE_STRDUP
+  return result;
+#else
+  return strcpy (result, ptr);
+#endif
+}
+
+#endif  /* HAVE_DMALLOC_H */
+
+char *
+savestring (const char *str, unsigned int length)
+{
+  char *out = xmalloc (length + 1);
+  if (length > 0)
+    memcpy (out, str, length);
+  out[length] = '\0';
+  return out;
+}
+
+
+
+#ifndef CONFIG_WITH_OPTIMIZATION_HACKS /* This is really a reimplemntation of
+   memchr, only slower. It's been replaced by a macro in the header file. */
+
+/* Limited INDEX:
+   Search through the string STRING, which ends at LIMIT, for the character C.
+   Returns a pointer to the first occurrence, or nil if none is found.
+   Like INDEX except that the string searched ends where specified
+   instead of at the first null.  */
+
+char *
+lindex (const char *s, const char *limit, int c)
+{
+  while (s < limit)
+    if (*s++ == c)
+      return (char *)(s - 1);
+
+  return 0;
+}
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+
+
+/* Return the address of the first whitespace or null in the string S.  */
+
+char *
+end_of_token (const char *s)
+{
+  while (*s != '\0' && !isblank ((unsigned char)*s))
+    ++s;
+  return (char *)s;
+}
+
+#ifdef WINDOWS32
+/*
+ * Same as end_of_token, but take into account a stop character
+ */
+char *
+end_of_token_w32 (const char *s, char stopchar)
+{
+  const char *p = s;
+  int backslash = 0;
+
+  while (*p != '\0' && *p != stopchar
+	 && (backslash || !isblank ((unsigned char)*p)))
+    {
+      if (*p++ == '\\')
+        {
+          backslash = !backslash;
+          while (*p == '\\')
+            {
+              backslash = !backslash;
+              ++p;
+            }
+        }
+      else
+        backslash = 0;
+    }
+
+  return (char *)p;
+}
+#endif
+
+/* Return the address of the first nonwhitespace or null in the string S.  */
+
+char *
+next_token (const char *s)
+{
+  while (isblank ((unsigned char)*s))
+    ++s;
+  return (char *)s;
+}
+
+/* Find the next token in PTR; return the address of it, and store the length
+   of the token into *LENGTHPTR if LENGTHPTR is not nil.  Set *PTR to the end
+   of the token, so this function can be called repeatedly in a loop.  */
+
+char *
+find_next_token (const char **ptr, unsigned int *lengthptr)
+{
+  const char *p = next_token (*ptr);
+
+  if (*p == '\0')
+    return 0;
+
+  *ptr = end_of_token (p);
+  if (lengthptr != 0)
+    *lengthptr = *ptr - p;
+
+  return (char *)p;
+}
+
+
+
+/* Allocate a new `struct dep' with all fields initialized to 0.   */
+
+struct dep *
+alloc_dep ()
+{
+  struct dep *d = xmalloc (sizeof (struct dep));
+  memset (d, '\0', sizeof (struct dep));
+  return d;
+}
+
+
+/* Free `struct dep' along with `name' and `stem'.   */
+
+void
+free_dep (struct dep *d)
+{
+  free (d);
+}
+
+/* Copy a chain of `struct dep', making a new chain
+   with the same contents as the old one.  */
+
+struct dep *
+copy_dep_chain (const struct dep *d)
+{
+  struct dep *firstnew = 0;
+  struct dep *lastnew = 0;
+
+  while (d != 0)
+    {
+      struct dep *c = xmalloc (sizeof (struct dep));
+      memcpy (c, d, sizeof (struct dep));
+
+      c->next = 0;
+      if (firstnew == 0)
+	firstnew = lastnew = c;
+      else
+	lastnew = lastnew->next = c;
+
+      d = d->next;
+    }
+
+  return firstnew;
+}
+
+/* Free a chain of 'struct dep'.  */
+
+void
+free_dep_chain (struct dep *d)
+{
+  while (d != 0)
+    {
+      struct dep *df = d;
+      d = d->next;
+      free_dep (df);
+    }
+}
+
+/* Free a chain of struct nameseq.
+   For struct dep chains use free_dep_chain.  */
+
+void
+free_ns_chain (struct nameseq *ns)
+{
+  while (ns != 0)
+    {
+      struct nameseq *t = ns;
+      ns = ns->next;
+      free (t);
+    }
+}
+
+
+
+#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
+
+/* If we don't have strcasecmp() (from POSIX), or anything that can substitute
+   for it, define our own version.  */
+
+int
+strcasecmp (const char *s1, const char *s2)
+{
+  while (1)
+    {
+      int c1 = (int) *(s1++);
+      int c2 = (int) *(s2++);
+
+      if (isalpha (c1))
+        c1 = tolower (c1);
+      if (isalpha (c2))
+        c2 = tolower (c2);
+
+      if (c1 != '\0' && c1 == c2)
+        continue;
+
+      return (c1 - c2);
+    }
+}
+#endif
+
+
+#ifdef	GETLOADAVG_PRIVILEGED
+
+#ifdef POSIX
+
+/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
+   functions, they work as POSIX.1 says.  Some systems (Alpha OSF/1 1.2,
+   for example) which claim to be POSIX.1 also have the BSD setreuid and
+   setregid functions, but they don't work as in BSD and only the POSIX.1
+   way works.  */
+
+#undef HAVE_SETREUID
+#undef HAVE_SETREGID
+
+#else	/* Not POSIX.  */
+
+/* Some POSIX.1 systems have the seteuid and setegid functions.  In a
+   POSIX-like system, they are the best thing to use.  However, some
+   non-POSIX systems have them too but they do not work in the POSIX style
+   and we must use setreuid and setregid instead.  */
+
+#undef HAVE_SETEUID
+#undef HAVE_SETEGID
+
+#endif	/* POSIX.  */
+
+#ifndef	HAVE_UNISTD_H
+extern int getuid (), getgid (), geteuid (), getegid ();
+extern int setuid (), setgid ();
+#ifdef HAVE_SETEUID
+extern int seteuid ();
+#else
+#ifdef	HAVE_SETREUID
+extern int setreuid ();
+#endif	/* Have setreuid.  */
+#endif	/* Have seteuid.  */
+#ifdef HAVE_SETEGID
+extern int setegid ();
+#else
+#ifdef	HAVE_SETREGID
+extern int setregid ();
+#endif	/* Have setregid.  */
+#endif	/* Have setegid.  */
+#endif	/* No <unistd.h>.  */
+
+/* Keep track of the user and group IDs for user- and make- access.  */
+static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
+#define	access_inited	(user_uid != -1)
+static enum { make, user } current_access;
+
+
+/* Under -d, write a message describing the current IDs.  */
+
+static void
+log_access (const char *flavor)
+{
+  if (! ISDB (DB_JOBS))
+    return;
+
+  /* All the other debugging messages go to stdout,
+     but we write this one to stderr because it might be
+     run in a child fork whose stdout is piped.  */
+
+  fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
+	   flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
+           (unsigned long) getegid (), (unsigned long) getgid ());
+  fflush (stderr);
+}
+
+
+static void
+init_access (void)
+{
+#ifndef VMS
+  user_uid = getuid ();
+  user_gid = getgid ();
+
+  make_uid = geteuid ();
+  make_gid = getegid ();
+
+  /* Do these ever fail?  */
+  if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
+    pfatal_with_name ("get{e}[gu]id");
+
+  log_access (_("Initialized access"));
+
+  current_access = make;
+#endif
+}
+
+#endif	/* GETLOADAVG_PRIVILEGED */
+
+/* Give the process appropriate permissions for access to
+   user data (i.e., to stat files, or to spawn a child process).  */
+void
+user_access (void)
+{
+#ifdef	GETLOADAVG_PRIVILEGED
+
+  if (!access_inited)
+    init_access ();
+
+  if (current_access == user)
+    return;
+
+  /* We are in "make access" mode.  This means that the effective user and
+     group IDs are those of make (if it was installed setuid or setgid).
+     We now want to set the effective user and group IDs to the real IDs,
+     which are the IDs of the process that exec'd make.  */
+
+#ifdef	HAVE_SETEUID
+
+  /* Modern systems have the seteuid/setegid calls which set only the
+     effective IDs, which is ideal.  */
+
+  if (seteuid (user_uid) < 0)
+    pfatal_with_name ("user_access: seteuid");
+
+#else	/* Not HAVE_SETEUID.  */
+
+#ifndef	HAVE_SETREUID
+
+  /* System V has only the setuid/setgid calls to set user/group IDs.
+     There is an effective ID, which can be set by setuid/setgid.
+     It can be set (unless you are root) only to either what it already is
+     (returned by geteuid/getegid, now in make_uid/make_gid),
+     the real ID (return by getuid/getgid, now in user_uid/user_gid),
+     or the saved set ID (what the effective ID was before this set-ID
+     executable (make) was exec'd).  */
+
+  if (setuid (user_uid) < 0)
+    pfatal_with_name ("user_access: setuid");
+
+#else	/* HAVE_SETREUID.  */
+
+  /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
+     They may be set to themselves or each other.  So you have two alternatives
+     at any one time.  If you use setuid/setgid, the effective will be set to
+     the real, leaving only one alternative.  Using setreuid/setregid, however,
+     you can toggle between your two alternatives by swapping the values in a
+     single setreuid or setregid call.  */
+
+  if (setreuid (make_uid, user_uid) < 0)
+    pfatal_with_name ("user_access: setreuid");
+
+#endif	/* Not HAVE_SETREUID.  */
+#endif	/* HAVE_SETEUID.  */
+
+#ifdef	HAVE_SETEGID
+  if (setegid (user_gid) < 0)
+    pfatal_with_name ("user_access: setegid");
+#else
+#ifndef	HAVE_SETREGID
+  if (setgid (user_gid) < 0)
+    pfatal_with_name ("user_access: setgid");
+#else
+  if (setregid (make_gid, user_gid) < 0)
+    pfatal_with_name ("user_access: setregid");
+#endif
+#endif
+
+  current_access = user;
+
+  log_access (_("User access"));
+
+#endif	/* GETLOADAVG_PRIVILEGED */
+}
+
+/* Give the process appropriate permissions for access to
+   make data (i.e., the load average).  */
+void
+make_access (void)
+{
+#ifdef	GETLOADAVG_PRIVILEGED
+
+  if (!access_inited)
+    init_access ();
+
+  if (current_access == make)
+    return;
+
+  /* See comments in user_access, above.  */
+
+#ifdef	HAVE_SETEUID
+  if (seteuid (make_uid) < 0)
+    pfatal_with_name ("make_access: seteuid");
+#else
+#ifndef	HAVE_SETREUID
+  if (setuid (make_uid) < 0)
+    pfatal_with_name ("make_access: setuid");
+#else
+  if (setreuid (user_uid, make_uid) < 0)
+    pfatal_with_name ("make_access: setreuid");
+#endif
+#endif
+
+#ifdef	HAVE_SETEGID
+  if (setegid (make_gid) < 0)
+    pfatal_with_name ("make_access: setegid");
+#else
+#ifndef	HAVE_SETREGID
+  if (setgid (make_gid) < 0)
+    pfatal_with_name ("make_access: setgid");
+#else
+  if (setregid (user_gid, make_gid) < 0)
+    pfatal_with_name ("make_access: setregid");
+#endif
+#endif
+
+  current_access = make;
+
+  log_access (_("Make access"));
+
+#endif	/* GETLOADAVG_PRIVILEGED */
+}
+
+/* Give the process appropriate permissions for a child process.
+   This is like user_access, but you can't get back to make_access.  */
+void
+child_access (void)
+{
+#ifdef	GETLOADAVG_PRIVILEGED
+
+  if (!access_inited)
+    abort ();
+
+  /* Set both the real and effective UID and GID to the user's.
+     They cannot be changed back to make's.  */
+
+#ifndef	HAVE_SETREUID
+  if (setuid (user_uid) < 0)
+    pfatal_with_name ("child_access: setuid");
+#else
+  if (setreuid (user_uid, user_uid) < 0)
+    pfatal_with_name ("child_access: setreuid");
+#endif
+
+#ifndef	HAVE_SETREGID
+  if (setgid (user_gid) < 0)
+    pfatal_with_name ("child_access: setgid");
+#else
+  if (setregid (user_gid, user_gid) < 0)
+    pfatal_with_name ("child_access: setregid");
+#endif
+
+  log_access (_("Child access"));
+
+#endif	/* GETLOADAVG_PRIVILEGED */
+}
+
+
+#ifdef NEED_GET_PATH_MAX
+unsigned int
+get_path_max (void)
+{
+  static unsigned int value;
+
+  if (value == 0)
+    {
+      long int x = pathconf ("/", _PC_PATH_MAX);
+      if (x > 0)
+	value = x;
+      else
+	return MAXPATHLEN;
+    }
+
+  return value;
+}
+#endif
+
+
+
+/* This code is stolen from gnulib.
+   If/when we abandon the requirement to work with K&R compilers, we can
+   remove this (and perhaps other parts of GNU make!) and migrate to using
+   gnulib directly.
+
+   This is called only through atexit(), which means die() has already been
+   invoked.  So, call exit() here directly.  Apparently that works...?
+*/
+
+/* Close standard output, exiting with status 'exit_failure' on failure.
+   If a program writes *anything* to stdout, that program should close
+   stdout and make sure that it succeeds before exiting.  Otherwise,
+   suppose that you go to the extreme of checking the return status
+   of every function that does an explicit write to stdout.  The last
+   printf can succeed in writing to the internal stream buffer, and yet
+   the fclose(stdout) could still fail (due e.g., to a disk full error)
+   when it tries to write out that buffered data.  Thus, you would be
+   left with an incomplete output file and the offending program would
+   exit successfully.  Even calling fflush is not always sufficient,
+   since some file systems (NFS and CODA) buffer written/flushed data
+   until an actual close call.
+
+   Besides, it's wasteful to check the return value from every call
+   that writes to stdout -- just let the internal stream state record
+   the failure.  That's what the ferror test is checking below.
+
+   It's important to detect such failures and exit nonzero because many
+   tools (most notably `make' and other build-management systems) depend
+   on being able to detect failure in other tools via their exit status.  */
+
+void
+close_stdout (void)
+{
+  int prev_fail = ferror (stdout);
+  int fclose_fail = fclose (stdout);
+
+  if (prev_fail || fclose_fail)
+    {
+      if (fclose_fail)
+        error (NILF, _("write error: %s"), strerror (errno));
+      else
+        error (NILF, _("write error"));
+      exit (EXIT_FAILURE);
+    }
+}
+
+#if defined(CONFIG_WITH_MAKE_STATS) && !defined(ELECTRIC_HEAP)
+#undef free
+void xfree(void *ptr)
+{
+  if (ptr)
+    {
+      make_stats_allocations--;
+      if (make_expensive_statistics)
+        make_stats_allocated -= SIZE_OF_HEAP_BLOCK (ptr);
+      free (ptr);
+    }
+}
+#endif
+
Index: /tags/kBuild-0.1.4/src/kmk/po/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/po/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/po/ChangeLog	(revision 1780)
@@ -0,0 +1,69 @@
+2006-01-28  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added new translation for Vietnamese (vi).
+
+2005-07-14  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added new translation for Indonesian (id).
+
+2005-05-09  Paul D. Smith  <psmith@gnu.org>
+
+	* POTFILES.in: Add new file vmsjobs.c.
+
+2005-04-06  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added a new translation for Kinywarwanda (rw).
+
+2005-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added a new translation for Irish (ga).
+
+2005-02-01  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added a new translation for Finnish (fi).
+
+2003-10-18  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added a new translation for Belarusian (be).
+
+2002-12-19  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Added a new translation for Ukrainian (uk).
+
+2002-10-05  Paul D. Smith  <psmith@gnu.org>
+
+	* POTFILES.in: Add variable.h as it has a translatable string.
+
+2002-08-08  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Add a new translation for Chinese (simplified) (zh_CN).
+
+2002-08-02  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS: Add a new translation for Swedish (sv).
+
+2002-04-21  Paul D. Smith  <psmith@gnu.org>
+
+	* LINGUAS, hr.po: Added new translation: Croatian.
+
+	* da.po, de.po, es.po, fr.po, gl.po, he.po, ja.po, ko.po, nl.po,
+	pl.po, pt_BR.po, ru.po, tr.po: Moved from i18n to here.
+	* .cvsignore: Moved from i18n to here.
+
+	* POTFILES.in, LINGUAS, Makevars: Created.
+
+
+Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/po/LINGUAS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/po/LINGUAS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/po/LINGUAS	(revision 1780)
@@ -0,0 +1,5 @@
+# Set of available languages: 23 languages
+
+be da de es fi fr ga gl he hr id ja ko nl pl pt_BR ru rw sv tr uk vi zh_CN
+
+# Can't seem to get en@quot and en@boldquot to build properly?
Index: /tags/kBuild-0.1.4/src/kmk/po/Makevars
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/po/Makevars	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/po/Makevars	(revision 1780)
@@ -0,0 +1,58 @@
+# This is a -*-Makefile-*-
+# Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding
+# package.  (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.)  Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright.  The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Free Software Foundation, Inc.
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+#   in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+#   understood.
+# - Strings which make invalid assumptions about notation of date, time or
+#   money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = bug-make@gnu.org
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used.  It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
Index: /tags/kBuild-0.1.4/src/kmk/po/POTFILES.in
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/po/POTFILES.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/po/POTFILES.in	(revision 1780)
@@ -0,0 +1,42 @@
+# List of source files containing translatable strings.
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+# Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ar.c
+arscan.c
+commands.c
+dir.c
+expand.c
+file.c
+function.c
+getopt.c
+hash.c
+implicit.c
+job.c
+kbuild.c
+main.c
+misc.c
+read.c
+remake.c
+remote-cstms.c
+rule.c
+signame.c
+strcache.c
+variable.c
+variable.h
+vmsfunctions.c
+vmsjobs.c
+vpath.c
Index: /tags/kBuild-0.1.4/src/kmk/prepare_w32.bat
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/prepare_w32.bat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/prepare_w32.bat	(revision 1780)
@@ -0,0 +1,6 @@
+@echo off
+@echo Windows32 CVS build preparation of config.h.W32 and NMakefile.
+if not exist config.h.W32 copy config.h.W32.template config.h.W32
+if not exist config.h copy config.h.W32 config.h
+if not exist NMakefile copy NMakefile.template NMakefile
+@echo Preparation complete.  Run build_w32.bat to compile and link.
Index: /tags/kBuild-0.1.4/src/kmk/read.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/read.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/read.c	(revision 1780)
@@ -0,0 +1,3939 @@
+/* Reading and parsing of makefiles for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#include <assert.h>
+
+#include <glob.h>
+
+#include "dep.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "variable.h"
+#include "rule.h"
+#include "debug.h"
+#include "hash.h"
+#ifdef KMK
+# include "kbuild.h"
+#endif
+#ifdef CONFIG_WITH_INCLUDEDEP
+# ifdef HAVE_FCNTL_H
+#  include <fcntl.h>
+# else
+#  include <sys/file.h>
+#endif
+# ifdef WINDOWS32
+#  include <io.h>
+# endif
+#endif
+
+#ifndef WINDOWS32
+#ifndef _AMIGA
+#ifndef VMS
+#include <pwd.h>
+#else
+struct passwd *getpwnam (char *name);
+#endif
+#endif
+#endif /* !WINDOWS32 */
+
+/* A 'struct ebuffer' controls the origin of the makefile we are currently
+   eval'ing.
+*/
+
+struct ebuffer
+  {
+    char *buffer;       /* Start of the current line in the buffer.  */
+    char *bufnext;      /* Start of the next line in the buffer.  */
+    char *bufstart;     /* Start of the entire buffer.  */
+    unsigned int size;  /* Malloc'd size of buffer. */
+    FILE *fp;           /* File, or NULL if this is an internal buffer.  */
+    struct floc floc;   /* Info on the file in fp (if any).  */
+  };
+
+/* Types of "words" that can be read in a makefile.  */
+enum make_word_type
+  {
+     w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon,
+     w_varassign
+  };
+
+
+/* A `struct conditionals' contains the information describing
+   all the active conditionals in a makefile.
+
+   The global variable `conditionals' contains the conditionals
+   information for the current makefile.  It is initialized from
+   the static structure `toplevel_conditionals' and is later changed
+   to new structures for included makefiles.  */
+
+struct conditionals
+  {
+    unsigned int if_cmds;	/* Depth of conditional nesting.  */
+    unsigned int allocated;	/* Elts allocated in following arrays.  */
+    char *ignoring;		/* Are we ignoring or interpreting?
+                                   0=interpreting, 1=not yet interpreted,
+                                   2=already interpreted */
+    char *seen_else;		/* Have we already seen an `else'?  */
+  };
+
+static struct conditionals toplevel_conditionals;
+static struct conditionals *conditionals = &toplevel_conditionals;
+
+
+/* Default directories to search for include files in  */
+
+static const char *default_include_directories[] =
+  {
+#ifndef KMK
+#if defined(WINDOWS32) && !defined(INCLUDEDIR)
+/* This completely up to the user when they install MSVC or other packages.
+   This is defined as a placeholder.  */
+# define INCLUDEDIR "."
+#endif
+# ifdef INCLUDEDIR  /* bird */
+    INCLUDEDIR,
+# else              /* bird */
+    ".",            /* bird */
+# endif             /* bird */
+#ifndef _AMIGA
+    "/usr/gnu/include",
+    "/usr/local/include",
+    "/usr/include",
+#endif
+#endif /* !KMK */
+    0
+  };
+
+/* List of directories to search for include files in  */
+
+static const char **include_directories;
+
+/* Maximum length of an element of the above.  */
+
+static unsigned int max_incl_len;
+
+/* The filename and pointer to line number of the
+   makefile currently being read in.  */
+
+const struct floc *reading_file = 0;
+
+/* The chain of makefiles read by read_makefile.  */
+
+static struct dep *read_makefiles = 0;
+
+static int eval_makefile (const char *filename, int flags);
+static int eval (struct ebuffer *buffer, int flags);
+
+static long readline (struct ebuffer *ebuf);
+static void do_define (char *name, unsigned int namelen,
+                       enum variable_origin origin, struct ebuffer *ebuf);
+static int conditional_line (char *line, int len, const struct floc *flocp);
+static void record_files (struct nameseq *filenames, const char *pattern,
+                          const char *pattern_percent, struct dep *deps,
+                          unsigned int cmds_started, char *commands,
+                          unsigned int commands_idx, int two_colon,
+                          const struct floc *flocp);
+static void record_target_var (struct nameseq *filenames, char *defn,
+                               enum variable_origin origin, int enabled,
+                               const struct floc *flocp);
+static enum make_word_type get_next_mword (char *buffer, char *delim,
+                                           char **startp, unsigned int *length);
+static void remove_comments (char *line);
+static char *find_char_unquote (char *string, int stop1, int stop2,
+                                int blank, int ignorevars);
+
+
+/* Read in all the makefiles and return the chain of their names.  */
+
+struct dep *
+read_all_makefiles (const char **makefiles)
+{
+  unsigned int num_makefiles = 0;
+
+  /* Create *_LIST variables, to hold the makefiles, targets, and variables
+     we will be reading. */
+
+  define_variable ("MAKEFILE_LIST", sizeof ("MAKEFILE_LIST")-1, "", o_file, 0);
+
+  DB (DB_BASIC, (_("Reading makefiles...\n")));
+
+  /* If there's a non-null variable MAKEFILES, its value is a list of
+     files to read first thing.  But don't let it prevent reading the
+     default makefiles and don't let the default goal come from there.  */
+
+  {
+    char *value;
+    char *name, *p;
+    unsigned int length;
+
+    {
+      /* Turn off --warn-undefined-variables while we expand MAKEFILES.  */
+      int save = warn_undefined_variables_flag;
+      warn_undefined_variables_flag = 0;
+
+      value = allocated_variable_expand ("$(MAKEFILES)");
+
+      warn_undefined_variables_flag = save;
+    }
+
+    /* Set NAME to the start of next token and LENGTH to its length.
+       MAKEFILES is updated for finding remaining tokens.  */
+    p = value;
+
+    while ((name = find_next_token ((const char **)&p, &length)) != 0)
+      {
+	if (*p != '\0')
+	  *p++ = '\0';
+	eval_makefile (name, RM_NO_DEFAULT_GOAL|RM_INCLUDED|RM_DONTCARE);
+      }
+
+    free (value);
+  }
+
+  /* Read makefiles specified with -f switches.  */
+
+  if (makefiles != 0)
+    while (*makefiles != 0)
+      {
+	struct dep *tail = read_makefiles;
+	register struct dep *d;
+
+	if (! eval_makefile (*makefiles, 0))
+	  perror_with_name ("", *makefiles);
+
+	/* Find the right element of read_makefiles.  */
+	d = read_makefiles;
+	while (d->next != tail)
+	  d = d->next;
+
+	/* Use the storage read_makefile allocates.  */
+	*makefiles = dep_name (d);
+	++num_makefiles;
+	++makefiles;
+      }
+
+  /* If there were no -f switches, try the default names.  */
+
+  if (num_makefiles == 0)
+    {
+      static char *default_makefiles[] =
+#ifdef VMS
+	/* all lower case since readdir() (the vms version) 'lowercasifies' */
+# ifdef KMK
+	{ "makefile.kmk", "makefile.vms", "gnumakefile.", "makefile.", 0 };
+# else
+	{ "makefile.vms", "gnumakefile.", "makefile.", 0 };
+# endif
+#else
+#ifdef _AMIGA
+        /* what's the deal here? no dots? */
+# ifdef KMK
+	{ "Makefile.kmk", "makefile.kmk", "GNUmakefile", "Makefile", "SMakefile", 0 };
+# else
+	{ "GNUmakefile", "Makefile", "SMakefile", 0 };
+# endif
+#else /* !Amiga && !VMS */
+# ifdef KMK
+	{ "Makefile.kmk", "makefile.kmk", "GNUmakefile", "makefile", "Makefile", 0 };
+# else
+	{ "GNUmakefile", "makefile", "Makefile", 0 };
+# endif
+#endif /* AMIGA */
+#endif /* VMS */
+      register char **p = default_makefiles;
+      while (*p != 0 && !file_exists_p (*p))
+	++p;
+
+      if (*p != 0)
+	{
+	  if (! eval_makefile (*p, 0))
+	    perror_with_name ("", *p);
+	}
+      else
+	{
+	  /* No default makefile was found.  Add the default makefiles to the
+	     `read_makefiles' chain so they will be updated if possible.  */
+	  struct dep *tail = read_makefiles;
+	  /* Add them to the tail, after any MAKEFILES variable makefiles.  */
+	  while (tail != 0 && tail->next != 0)
+	    tail = tail->next;
+	  for (p = default_makefiles; *p != 0; ++p)
+	    {
+	      struct dep *d = alloc_dep ();
+	      d->file = enter_file (strcache_add (*p));
+	      d->file->dontcare = 1;
+	      /* Tell update_goal_chain to bail out as soon as this file is
+		 made, and main not to die if we can't make this file.  */
+	      d->changed = RM_DONTCARE;
+	      if (tail == 0)
+		read_makefiles = d;
+	      else
+		tail->next = d;
+	      tail = d;
+	    }
+	  if (tail != 0)
+	    tail->next = 0;
+	}
+    }
+
+  return read_makefiles;
+}
+
+
+/* Install a new conditional and return the previous one.  */
+
+static struct conditionals *
+install_conditionals (struct conditionals *new)
+{
+  struct conditionals *save = conditionals;
+
+  memset (new, '\0', sizeof (*new));
+  conditionals = new;
+
+  return save;
+}
+
+/* Free the current conditionals and reinstate a saved one.  */
+
+static void
+restore_conditionals (struct conditionals *saved)
+{
+  /* Free any space allocated by conditional_line.  */
+  if (conditionals->ignoring)
+    free (conditionals->ignoring);
+  if (conditionals->seen_else)
+    free (conditionals->seen_else);
+
+  /* Restore state.  */
+  conditionals = saved;
+}
+
+
+static int
+eval_makefile (const char *filename, int flags)
+{
+  struct dep *deps;
+  struct ebuffer ebuf;
+  const struct floc *curfile;
+  char *expanded = 0;
+  int makefile_errno;
+  int r;
+
+  filename = strcache_add (filename);
+  ebuf.floc.filenm = filename;
+  ebuf.floc.lineno = 1;
+
+  if (ISDB (DB_VERBOSE))
+    {
+      printf (_("Reading makefile `%s'"), filename);
+      if (flags & RM_NO_DEFAULT_GOAL)
+	printf (_(" (no default goal)"));
+      if (flags & RM_INCLUDED)
+	printf (_(" (search path)"));
+      if (flags & RM_DONTCARE)
+	printf (_(" (don't care)"));
+      if (flags & RM_NO_TILDE)
+	printf (_(" (no ~ expansion)"));
+      puts ("...");
+    }
+
+  /* First, get a stream to read.  */
+
+  /* Expand ~ in FILENAME unless it came from `include',
+     in which case it was already done.  */
+  if (!(flags & RM_NO_TILDE) && filename[0] == '~')
+    {
+      expanded = tilde_expand (filename);
+      if (expanded != 0)
+	filename = expanded;
+    }
+
+  ebuf.fp = fopen (filename, "r");
+  /* Save the error code so we print the right message later.  */
+  makefile_errno = errno;
+
+  /* If the makefile wasn't found and it's either a makefile from
+     the `MAKEFILES' variable or an included makefile,
+     search the included makefile search path for this makefile.  */
+  if (ebuf.fp == 0 && (flags & RM_INCLUDED) && *filename != '/')
+    {
+      unsigned int i;
+      for (i = 0; include_directories[i] != 0; ++i)
+	{
+	  const char *included = concat (include_directories[i], "/", filename);
+	  ebuf.fp = fopen (included, "r");
+	  if (ebuf.fp)
+	    {
+	      filename = strcache_add (included);
+	      break;
+	    }
+	}
+    }
+
+  /* Add FILENAME to the chain of read makefiles.  */
+  deps = alloc_dep ();
+  deps->next = read_makefiles;
+  read_makefiles = deps;
+  deps->file = lookup_file (filename);
+  if (deps->file == 0)
+    deps->file = enter_file (filename);
+  filename = deps->file->name;
+  deps->changed = flags;
+  if (flags & RM_DONTCARE)
+    deps->file->dontcare = 1;
+
+  if (expanded)
+    free (expanded);
+
+  /* If the makefile can't be found at all, give up entirely.  */
+
+  if (ebuf.fp == 0)
+    {
+      /* If we did some searching, errno has the error from the last
+	 attempt, rather from FILENAME itself.  Restore it in case the
+	 caller wants to use it in a message.  */
+      errno = makefile_errno;
+      return 0;
+    }
+
+  /* Add this makefile to the list. */
+  do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file,
+                          f_append, 0);
+
+#ifdef KMK
+  /* Buffer the entire file or at least 256KB (footer.kmk) of it. */
+  {
+    void *stream_buf = NULL;
+    struct stat st;
+    if (!fstat (fileno (ebuf.fp), &st))
+      {
+        unsigned int stream_buf_size = 256*1024;
+        if (st.st_size < stream_buf_size)
+          stream_buf_size = (st.st_size + 0xfff) & ~0xfffU;
+        stream_buf = xmalloc (stream_buf_size);
+        setvbuf (ebuf.fp, stream_buf, _IOFBF, stream_buf_size);
+      }
+#endif
+
+  /* Evaluate the makefile */
+
+  ebuf.size = 200;
+  ebuf.buffer = ebuf.bufnext = ebuf.bufstart = xmalloc (ebuf.size);
+
+  curfile = reading_file;
+  reading_file = &ebuf.floc;
+
+  r = eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL));
+
+  reading_file = curfile;
+
+  fclose (ebuf.fp);
+
+#ifdef KMK
+   if (stream_buf)
+     free (stream_buf);
+  }
+#endif
+  free (ebuf.bufstart);
+  alloca (0);
+  return r;
+}
+
+int
+eval_buffer (char *buffer)
+{
+  struct ebuffer ebuf;
+  struct conditionals *saved;
+  struct conditionals new;
+  const struct floc *curfile;
+  int r;
+
+  /* Evaluate the buffer */
+
+  ebuf.size = strlen (buffer);
+  ebuf.buffer = ebuf.bufnext = ebuf.bufstart = buffer;
+  ebuf.fp = NULL;
+
+  ebuf.floc = *reading_file;
+
+  curfile = reading_file;
+  reading_file = &ebuf.floc;
+
+  saved = install_conditionals (&new);
+
+  r = eval (&ebuf, 1);
+
+  restore_conditionals (saved);
+
+  reading_file = curfile;
+
+  alloca (0);
+  return r;
+}
+
+#ifdef CONFIG_WITH_INCLUDEDEP
+/* no nonsense dependency file including.
+
+   Because nobody wants bogus dependency files to break their incremental
+   builds with hard to comprehend error messages, this function does not
+   use the normal eval routine but does all the parsing itself. This isn't,
+   as much work as it sounds, because the necessary feature set is very
+   limited.
+
+   eval_include_dep groks:
+
+   define var
+   endef
+
+   var [|:|?|>]= value [\]
+
+   [\]
+   file: [deps] [\]
+
+   */
+void
+eval_include_dep (const char *name, struct floc *f)
+{
+  int fd;
+  char *file_base;
+  const char *file_end, *cur, *endp;
+  struct stat st;
+  unsigned line_no;
+
+  /* open and read it into memory. ignore non-existing dependency files
+     or that we can't read. */
+  errno = 0;
+#ifdef O_BINARY
+  fd = open (name, O_RDONLY | O_BINARY, 0);
+#else
+  fd = open (name, O_RDONLY, 0);
+#endif
+  if (fd < 0)
+    {
+      int err = errno;
+      if (err == ENOENT || !file_exists_p (name))
+        return;
+      error (f, "%s: %s", name, strerror (err));
+      return;
+    }
+  if (fstat (fd, &st))
+    {
+      error (f, "%s: fstat: %s", name, strerror (errno));
+      close (fd);
+      return;
+    }
+  file_base = xmalloc (st.st_size + 1);
+  if (read (fd, file_base, st.st_size) != st.st_size)
+    {
+      error (f, "%s: read: %s", name, strerror (errno));
+      close (fd);
+      free (file_base);
+      return;
+    }
+  close (fd);
+  file_end = file_base + st.st_size;
+  file_base[st.st_size] = '\0';
+
+  /* now parse the file. */
+  line_no = 1;
+  cur = file_base;
+  while (cur < file_end)
+    {
+      /* skip empty lines */
+      while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
+        ++cur;
+      if (cur >= file_end)
+        break;
+      if (*cur == '#')
+        {
+          cur = memchr (cur, '\n', file_end - cur);
+          if (!cur)
+            break;
+        }
+      if (*cur == '\\')
+        {
+          unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
+                           : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
+                           : (file_end - cur == 1) ? 1 : 0;
+           if (eol_len)
+             {
+               cur += eol_len;
+               line_no++;
+               continue;
+             }
+        }
+      if (*cur == '\n')
+        {
+          cur++;
+          line_no++;
+          continue;
+        }
+
+      /* define var
+         ...
+         endef */
+      if (strneq (cur, "define ", 7))
+        {
+          const char *var;
+          unsigned var_len;
+          const char *value_start;
+          const char *value_end;
+          char *value;
+          unsigned value_len;
+          int found_endef = 0;
+
+          /* extract the variable name. */
+          cur += 7;
+          while (isblank ((unsigned char)*cur))
+            ++cur;
+          value_start = endp = memchr (cur, '\n', file_end - cur);
+          if (!endp)
+              endp = cur;
+          while (endp > cur && isspace ((unsigned char)endp[-1]))
+            --endp;
+          var_len = endp - cur;
+          if (!var_len)
+          {
+              error (f, "%s(%d): bogus define statement.", name, line_no);
+              break;
+          }
+          var = strcache_add_len (cur, var_len);
+
+          /* find the end of the variable. */
+          cur = value_end = value_start = value_start + 1;
+          ++line_no;
+          while (cur < file_end)
+            {
+              /* check for endef, don't bother with skipping leading spaces. */
+              if (   file_end - cur >= 5
+                  && strneq (cur, "endef", 5))
+                {
+                  endp = cur + 5;
+                  while (endp < file_end && isspace ((unsigned char)*endp) && *endp != '\n')
+                    endp++;
+                  if (endp >= file_end || *endp == '\n')
+                    {
+                      found_endef = 1;
+                      cur = endp >= file_end ? file_end : endp + 1;
+                      break;
+                    }
+                }
+
+              /* skip a line ahead. */
+              cur = value_end = memchr (cur, '\n', file_end - cur);
+              if (cur != NULL)
+                ++cur;
+              else
+                cur = value_end = file_end;
+              ++line_no;
+            }
+
+          if (!found_endef)
+            {
+              error (f, "%s(%d): missing endef, dropping the rest of the file.", name, line_no);
+              break;
+            }
+          value_len = value_end - value_start;
+          if (memchr (value_start, '\0', value_len))
+            {
+              error (f, "%s(%d): '\\0' in define, dropping the rest of the file.", name, line_no);
+              break;
+            }
+
+          /* make a copy of the value, converting \r\n to \n, and define it. */
+          value = xmalloc (value_len + 1);
+          endp = memchr (value_start, '\r', value_len);
+          if (endp)
+            {
+              const char *src = value_start;
+              char *dst = value;
+              for (;;)
+                {
+                  size_t len = endp - src;
+                  memcpy (dst, src, len);
+                  dst += len;
+                  src = endp;
+                  if (src + 1 < file_end && src[1] == '\n')
+                      src++; /* skip the '\r' */
+                  if (src >= value_end)
+                    break;
+                  endp = memchr (endp + 1, '\r', src - value_end);
+                  if (!endp)
+                    endp = value_end;
+                }
+              value_len = dst - value;
+            }
+          else
+            memcpy (value, value_start, value_len);
+          value [value_len] = '\0';
+
+          define_variable_in_set (var, var_len, value, value_len,
+                                  0 /* don't duplicate */, o_file,
+                                  0 /* defines are recursive but this is faster */,
+                                  NULL /* global set */, f);
+        }
+
+      /* file: deps
+         OR
+         variable [:]= value */
+      else
+        {
+          const char *colonp;
+          const char *equalp;
+
+          /* Look for a colon and an equal sign, optimize for colon.
+             Only one file is support and the colon / equal must be on
+             the same line. */
+          colonp = memchr (cur, ':', file_end - cur);
+#ifdef HAVE_DOS_PATHS
+          while (   colonp
+                 && colonp + 1 < file_end
+                 && (colonp[1] == '/' || colonp[1] == '\\')
+                 && colonp > cur
+                 && isalpha ((unsigned char)colonp[-1])
+                 && (   colonp == cur + 1
+                     || strchr (" \t(", colonp[-2]) != 0))
+              colonp = memchr (colonp + 1, ':', file_end - (colonp + 1));
+#endif
+          endp = NULL;
+          if (   !colonp
+              ||  (endp = memchr (cur, '\n', colonp - cur)))
+            {
+              colonp = NULL;
+              equalp = memchr (cur, '=', (endp ? endp : file_end) - cur);
+              if (   !equalp
+                  || (!endp && memchr (cur, '\n', equalp - cur)))
+                {
+                  error (f, "%s(%d): no colon.", name, line_no);
+                  break;
+                }
+            }
+          else
+            equalp = memchr (cur, '=', (colonp + 2 <= file_end
+                                        ? colonp + 2 : file_end) - cur);
+          if (equalp)
+            {
+              /* An assignment of some sort. */
+              const char *var;
+              unsigned var_len;
+              const char *value_start;
+              const char *value_end;
+              char *value;
+              unsigned value_len;
+              unsigned multi_line = 0;
+              enum variable_flavor flavor;
+
+              /* figure the flavor first. */
+              flavor = f_recursive;
+              if (equalp > cur)
+                {
+                  if (equalp[-1] == ':')
+                    flavor = f_simple;
+                  else if (equalp[-1] == '?')
+                    flavor = f_conditional;
+                  else if (equalp[-1] == '+')
+                    flavor = f_append;
+                  else if (equalp[-1] == '>')
+                    flavor = f_prepend;
+                }
+
+              /* extract the variable name. */
+              endp = flavor == f_recursive ? equalp : equalp - 1;
+              while (endp > cur && isblank ((unsigned char)endp[-1]))
+                --endp;
+              var_len = endp - cur;
+              if (!var_len)
+                {
+                  error (f, "%s(%d): empty variable. (includedep)", name, line_no);
+                  break;
+                }
+              if (   memchr (cur, '$', var_len)
+                  || memchr (cur, ' ', var_len)
+                  || memchr (cur, '\t', var_len))
+                {
+                  error (f, "%s(%d): fancy variable name. (includedep)", name, line_no);
+                  break;
+                }
+              var = strcache_add_len (cur, var_len);
+
+              /* find the start of the value. */
+              cur = equalp + 1;
+              while (cur < file_end && isblank ((unsigned char)*cur))
+                cur++;
+              value_start = cur;
+
+              /* find the end of the value / line (this isn't 101% correct). */
+              value_end = cur;
+              while (cur < file_end)
+                {
+                  endp = value_end = memchr (cur, '\n', file_end - cur);
+                  if (!value_end)
+                    value_end = file_end;
+                  if (value_end - 1 >= cur && value_end[-1] == '\r')
+                    --value_end;
+                  if (value_end - 1 < cur || value_end[-1] != '\\')
+                    {
+                      cur = endp ? endp + 1 : file_end;
+                      break;
+                    }
+                  --value_end;
+                  if (value_end - 1 >= cur && value_end[-1] == '\\')
+                    {
+                      error (f, "%s(%d): fancy escaping! (includedep)", name, line_no);
+                      cur = NULL;
+                      break;
+                    }
+                  if (!endp)
+                    {
+                      cur = file_end;
+                      break;
+                    }
+
+                  cur = endp + 1;
+                  ++multi_line;
+                  ++line_no;
+                }
+              if (!cur)
+                break;
+              ++line_no;
+
+              /* make a copy of the value, converting \r\n to \n, and define it. */
+              value_len = value_end - value_start;
+              value = xmalloc (value_len + 1);
+              if (!multi_line)
+                  memcpy (value, value_start, value_len);
+              else
+                {
+                  /* unescape it */
+                  const char *src = value_start;
+                  char *dst = value;
+                  while (src < value_end)
+                    {
+                      const char *nextp;
+
+                      endp = memchr (src, '\n', value_end - src);
+                      if (!endp)
+                        nextp = endp = value_end;
+                      else
+                        nextp = endp + 1;
+                      if (endp > src && endp[-1] == '\r')
+                        --endp;
+                      if (endp > src && endp[-1] == '\\')
+                        --endp;
+
+                      if (src != value_start)
+                        *dst++ = ' ';
+                      memcpy (dst, src, endp - src);
+                      dst += endp - src;
+                      src = nextp;
+                    }
+                  value_len = dst - value;
+                }
+              value [value_len] = '\0';
+
+              /* do the definition */
+              if (flavor == f_recursive
+               || (   flavor == f_simple
+                   && !memchr (value, '$', value_len)))
+                define_variable_in_set (var, var_len, value, value_len,
+                                        0 /* don't duplicate */, o_file,
+                                        flavor == f_recursive /* recursive */,
+                                        NULL /* global set */, f);
+              else
+                {
+                  do_variable_definition (f, var, value, o_file, flavor,
+                                          0 /* not target var */);
+                  free (value);
+                }
+            }
+          else
+            {
+              /* file: dependencies */
+
+              struct nameseq *filenames = 0;
+              struct dep *deps = 0;
+              struct dep **nextdep = &deps;
+              struct dep *dep;
+              int next_line = 1;
+
+              /* extract the filename, ASSUME a single one. */
+              endp = colonp;
+              while (endp > cur && isblank ((unsigned char)endp[-1]))
+                --endp;
+              if (cur == endp)
+                {
+                  error (f, "%s(%d): empty filename.", name, line_no);
+                  break;
+                }
+              if (   memchr (cur, '$', endp - cur)
+                  || memchr (cur, ' ', endp - cur)
+                  || memchr (cur, '\t', endp - cur))
+                {
+                  error (f, "%s(%d): multiple / fancy file name. (includedep)", name, line_no);
+                  break;
+                }
+              filenames = xmalloc (sizeof (struct nameseq));
+              memset (filenames, 0, sizeof (*filenames));
+              filenames->name = strcache_add_len (cur, endp - cur);
+
+              /* parse any dependencies. */
+              cur = colonp + 1;
+              while (cur < file_end)
+                {
+                  /* skip blanks and count lines. */
+                  while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
+                    ++cur;
+                  if (cur >= file_end)
+                    break;
+                  if (*cur == '\n')
+                    {
+                      cur++;
+                      line_no++;
+                      break;
+                    }
+
+                  /* continuation + eol? */
+                  if (*cur == '\\')
+                    {
+                      unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
+                                       : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
+                                       : (file_end - cur == 1) ? 1 : 0;
+                      if (eol_len)
+                        {
+                          cur += eol_len;
+                          line_no++;
+                          continue;
+                        }
+                    }
+
+                  /* find the end of the filename */
+                  endp = cur;
+                  while (endp < file_end && !isspace ((unsigned char)*endp))
+                    ++endp;
+
+                  /* add it to the list. */
+                  *nextdep = dep = alloc_dep ();
+                  dep->name = strcache_add_len (cur, endp - cur);
+                  nextdep = &dep->next;
+
+                  cur = endp;
+                }
+
+              /* enter the file with its dependencies. */
+              record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, f);
+            }
+        }
+    }
+  free (file_base);
+}
+#endif /* CONFIG_WITH_INCLUDEDEP */
+
+
+
+/* Read file FILENAME as a makefile and add its contents to the data base.
+
+   SET_DEFAULT is true if we are allowed to set the default goal.  */
+
+
+static int
+eval (struct ebuffer *ebuf, int set_default)
+{
+  char *collapsed = 0;
+  unsigned int collapsed_length = 0;
+  unsigned int commands_len = 200;
+  char *commands;
+  unsigned int commands_idx = 0;
+  unsigned int cmds_started, tgts_started;
+  int ignoring = 0, in_ignored_define = 0;
+  int no_targets = 0;		/* Set when reading a rule without targets.  */
+  struct nameseq *filenames = 0;
+  struct dep *deps = 0;
+  long nlines = 0;
+  int two_colon = 0;
+  const char *pattern = 0;
+  const char *pattern_percent;
+  struct floc *fstart;
+  struct floc fi;
+
+#define record_waiting_files()						      \
+  do									      \
+    { 									      \
+      if (filenames != 0)						      \
+        {                                                                     \
+	  fi.lineno = tgts_started;                                           \
+	  record_files (filenames, pattern, pattern_percent, deps,            \
+                        cmds_started, commands, commands_idx, two_colon,      \
+                        &fi);                                                 \
+        }                                                                     \
+      filenames = 0;							      \
+      commands_idx = 0;							      \
+      no_targets = 0;                                                         \
+      pattern = 0;                                                            \
+    } while (0)
+
+  pattern_percent = 0;
+  cmds_started = tgts_started = 1;
+
+  fstart = &ebuf->floc;
+  fi.filenm = ebuf->floc.filenm;
+
+  /* Loop over lines in the file.
+     The strategy is to accumulate target names in FILENAMES, dependencies
+     in DEPS and commands in COMMANDS.  These are used to define a rule
+     when the start of the next rule (or eof) is encountered.
+
+     When you see a "continue" in the loop below, that means we are moving on
+     to the next line _without_ ending any rule that we happen to be working
+     with at the moment.  If you see a "goto rule_complete", then the
+     statement we just parsed also finishes the previous rule.  */
+
+  commands = xmalloc (200);
+
+  while (1)
+    {
+      unsigned int linelen;
+      char *line;
+      unsigned int wlen;
+      char *p;
+      char *p2;
+
+      /* Grab the next line to be evaluated */
+      ebuf->floc.lineno += nlines;
+      nlines = readline (ebuf);
+
+      /* If there is nothing left to eval, we're done.  */
+      if (nlines < 0)
+        break;
+
+      /* If this line is empty, skip it.  */
+      line = ebuf->buffer;
+      if (line[0] == '\0')
+        continue;
+
+      linelen = strlen (line);
+
+      /* Check for a shell command line first.
+	 If it is not one, we can stop treating tab specially.  */
+      if (line[0] == cmd_prefix)
+	{
+	  if (no_targets)
+	    /* Ignore the commands in a rule with no targets.  */
+	    continue;
+
+	  /* If there is no preceding rule line, don't treat this line
+	     as a command, even though it begins with a tab character.
+	     SunOS 4 make appears to behave this way.  */
+
+	  if (filenames != 0)
+	    {
+	      if (ignoring)
+		/* Yep, this is a shell command, and we don't care.  */
+		continue;
+
+	      /* Append this command line to the line being accumulated.  */
+	      if (commands_idx == 0)
+		cmds_started = ebuf->floc.lineno;
+
+	      if (linelen + 1 + commands_idx > commands_len)
+		{
+		  commands_len = (linelen + 1 + commands_idx) * 2;
+		  commands = xrealloc (commands, commands_len);
+		}
+	      memcpy (&commands[commands_idx], line, linelen);
+	      commands_idx += linelen;
+	      commands[commands_idx++] = '\n';
+
+	      continue;
+	    }
+	}
+
+      /* This line is not a shell command line.  Don't worry about tabs.
+         Get more space if we need it; we don't need to preserve the current
+         contents of the buffer.  */
+
+      if (collapsed_length < linelen+1)
+	{
+	  collapsed_length = linelen+1;
+          if (collapsed)
+            free (collapsed);
+	  collapsed = xmalloc (collapsed_length);
+	}
+      strcpy (collapsed, line);
+      /* Collapse continuation lines.  */
+      collapse_continuations (collapsed);
+      remove_comments (collapsed);
+
+      /* Compare a word, both length and contents. */
+#define	word1eq(s) 	(wlen == sizeof(s)-1 && strneq (s, p, sizeof(s)-1))
+      p = collapsed;
+      while (isspace ((unsigned char)*p))
+	++p;
+
+      if (*p == '\0')
+	/* This line is completely empty--ignore it.  */
+	continue;
+
+      /* Find the end of the first token.  Note we don't need to worry about
+       * ":" here since we compare tokens by length (so "export" will never
+       * be equal to "export:").
+       */
+      for (p2 = p+1; *p2 != '\0' && !isspace ((unsigned char)*p2); ++p2)
+        ;
+      wlen = p2 - p;
+
+      /* Find the start of the second token.  If it looks like a target or
+         variable definition it can't be a preprocessor token so skip
+         them--this allows variables/targets named `ifdef', `export', etc. */
+      while (isspace ((unsigned char)*p2))
+        ++p2;
+
+      if ((p2[0] == ':' || p2[0] == '+' || p2[0] == '=') && p2[1] == '\0')
+        {
+          /* It can't be a preprocessor token so skip it if we're ignoring */
+          if (ignoring)
+            continue;
+
+          goto skip_conditionals;
+        }
+
+      /* We must first check for conditional and `define' directives before
+	 ignoring anything, since they control what we will do with
+	 following lines.  */
+
+      if (!in_ignored_define)
+	{
+ 	  int i = conditional_line (p, wlen, fstart);
+          if (i != -2)
+            {
+              if (i == -1)
+                fatal (fstart, _("invalid syntax in conditional"));
+
+              ignoring = i;
+              continue;
+            }
+	}
+
+      if (word1eq ("endef"))
+	{
+	  if (!in_ignored_define)
+	    fatal (fstart, _("extraneous `endef'"));
+          in_ignored_define = 0;
+	  continue;
+	}
+
+      if (word1eq ("define"))
+	{
+	  if (ignoring)
+	    in_ignored_define = 1;
+	  else
+	    {
+              if (*p2 == '\0')
+                fatal (fstart, _("empty variable name"));
+
+	      /* Let the variable name be the whole rest of the line,
+		 with trailing blanks stripped (comments have already been
+		 removed), so it could be a complex variable/function
+		 reference that might contain blanks.  */
+	      p = strchr (p2, '\0');
+	      while (isblank ((unsigned char)p[-1]))
+		--p;
+	      do_define (p2, p - p2, o_file, ebuf);
+	    }
+	  continue;
+	}
+
+      if (word1eq ("override"))
+        {
+	  if (*p2 == '\0')
+	    error (fstart, _("empty `override' directive"));
+
+	  if (strneq (p2, "define", 6)
+	      && (isblank ((unsigned char)p2[6]) || p2[6] == '\0'))
+	    {
+	      if (ignoring)
+		in_ignored_define = 1;
+	      else
+		{
+		  p2 = next_token (p2 + 6);
+                  if (*p2 == '\0')
+                    fatal (fstart, _("empty variable name"));
+
+		  /* Let the variable name be the whole rest of the line,
+		     with trailing blanks stripped (comments have already been
+		     removed), so it could be a complex variable/function
+		     reference that might contain blanks.  */
+		  p = strchr (p2, '\0');
+		  while (isblank ((unsigned char)p[-1]))
+		    --p;
+		  do_define (p2, p - p2, o_override, ebuf);
+		}
+	    }
+	  else if (!ignoring
+		   && !try_variable_definition (fstart, p2, o_override, 0))
+	    error (fstart, _("invalid `override' directive"));
+
+	  continue;
+	}
+#ifdef CONFIG_WITH_LOCAL_VARIABLES
+
+      if (word1eq ("local"))
+        {
+          if (*p2 == '\0')
+            error (fstart, _("empty `local' directive"));
+
+          if (strneq (p2, "define", 6)
+              && (isblank ((unsigned char)p2[6]) || p2[6] == '\0'))
+            {
+              if (ignoring)
+                in_ignored_define = 1;
+              else
+                {
+                  p2 = next_token (p2 + 6);
+                  if (*p2 == '\0')
+                    fatal (fstart, _("empty variable name"));
+
+                  /* Let the variable name be the whole rest of the line,
+                     with trailing blanks stripped (comments have already been
+                     removed), so it could be a complex variable/function
+                     reference that might contain blanks.  */
+                  p = strchr (p2, '\0');
+                  while (isblank ((unsigned char)p[-1]))
+                    --p;
+                  do_define (p2, p - p2, o_local, ebuf);
+                }
+            }
+          else if (!ignoring
+                   && !try_variable_definition (fstart, p2, o_local, 0))
+            error (fstart, _("invalid `local' directive"));
+
+          continue;
+        }
+#endif /* CONFIG_WITH_LOCAL_VARIABLES */
+
+      if (ignoring)
+	/* Ignore the line.  We continue here so conditionals
+	   can appear in the middle of a rule.  */
+	continue;
+
+      if (word1eq ("export"))
+	{
+          /* 'export' by itself causes everything to be exported. */
+	  if (*p2 == '\0')
+            export_all_variables = 1;
+          else
+            {
+              struct variable *v;
+
+              v = try_variable_definition (fstart, p2, o_file, 0);
+              if (v != 0)
+                v->export = v_export;
+              else
+                {
+                  unsigned int l;
+                  const char *cp;
+                  char *ap;
+
+                  /* Expand the line so we can use indirect and constructed
+                     variable names in an export command.  */
+                  cp = ap = allocated_variable_expand (p2);
+
+                  for (p = find_next_token (&cp, &l); p != 0;
+                       p = find_next_token (&cp, &l))
+                    {
+                      v = lookup_variable (p, l);
+                      if (v == 0)
+                        v = define_variable_loc (p, l, "", o_file, 0, fstart);
+                      v->export = v_export;
+                    }
+
+                  free (ap);
+                }
+            }
+          goto rule_complete;
+	}
+
+      if (word1eq ("unexport"))
+	{
+	  if (*p2 == '\0')
+	    export_all_variables = 0;
+          else
+            {
+              unsigned int l;
+              struct variable *v;
+              const char *cp;
+              char *ap;
+
+              /* Expand the line so we can use indirect and constructed
+                 variable names in an unexport command.  */
+              cp = ap = allocated_variable_expand (p2);
+
+              for (p = find_next_token (&cp, &l); p != 0;
+                   p = find_next_token (&cp, &l))
+                {
+                  v = lookup_variable (p, l);
+                  if (v == 0)
+                    v = define_variable_loc (p, l, "", o_file, 0, fstart);
+
+                  v->export = v_noexport;
+                }
+
+              free (ap);
+            }
+          goto rule_complete;
+	}
+
+ skip_conditionals:
+      if (word1eq ("vpath"))
+	{
+          const char *cp;
+	  char *vpat;
+	  unsigned int l;
+	  cp = variable_expand (p2);
+	  p = find_next_token (&cp, &l);
+	  if (p != 0)
+	    {
+	      vpat = savestring (p, l);
+	      p = find_next_token (&cp, &l);
+	      /* No searchpath means remove all previous
+		 selective VPATH's with the same pattern.  */
+	    }
+	  else
+	    /* No pattern means remove all previous selective VPATH's.  */
+	    vpat = 0;
+	  construct_vpath_list (vpat, p);
+	  if (vpat != 0)
+	    free (vpat);
+
+          goto rule_complete;
+	}
+
+#ifdef CONFIG_WITH_INCLUDEDEP
+      if (word1eq ("includedep"))
+        {
+          /* We have found an `includedep' line specifying a single makefile
+             to be read at this point. This include variation does no
+             globbing and do not support multiple names. It's trying to save
+             time by being dead simple as well as ignoring errors. */
+          char *free_me = NULL;
+          char *name = p2;
+          char *end = strchr (name, '\0');
+          char saved;
+          if (memchr (name, '$', end - name))
+            {
+              free_me = name = allocated_variable_expand (name);
+              while (isspace ((unsigned char)*name))
+                ++name;
+              end = strchr (name, '\0');
+            }
+
+          while (end > name && isspace ((unsigned char)end[-1]))
+            --end;
+
+          saved = *end; /* not sure if this is required... */
+          *end = '\0';
+          eval_include_dep (name, fstart);
+          *end = saved;
+
+          if (free_me)
+            free (free_me);
+          goto rule_complete;
+        }
+#endif /* CONFIG_WITH_INCLUDEDEP */
+
+      if (word1eq ("include") || word1eq ("-include") || word1eq ("sinclude"))
+	{
+	  /* We have found an `include' line specifying a nested
+	     makefile to be read at this point.  */
+	  struct conditionals *save;
+          struct conditionals new_conditionals;
+	  struct nameseq *files;
+	  /* "-include" (vs "include") says no error if the file does not
+	     exist.  "sinclude" is an alias for this from SGI.  */
+	  int noerror = (p[0] != 'i');
+
+	  p = allocated_variable_expand (p2);
+
+          /* If no filenames, it's a no-op.  */
+	  if (*p == '\0')
+            {
+              free (p);
+              continue;
+            }
+
+	  /* Parse the list of file names.  */
+	  p2 = p;
+	  files = multi_glob (parse_file_seq (&p2, '\0',
+					      sizeof (struct nameseq),
+					      1),
+			      sizeof (struct nameseq));
+	  free (p);
+
+	  /* Save the state of conditionals and start
+	     the included makefile with a clean slate.  */
+	  save = install_conditionals (&new_conditionals);
+
+	  /* Record the rules that are waiting so they will determine
+	     the default goal before those in the included makefile.  */
+	  record_waiting_files ();
+
+	  /* Read each included makefile.  */
+	  while (files != 0)
+	    {
+	      struct nameseq *next = files->next;
+	      const char *name = files->name;
+              int r;
+
+	      free (files);
+	      files = next;
+
+              r = eval_makefile (name, (RM_INCLUDED | RM_NO_TILDE
+                                        | (noerror ? RM_DONTCARE : 0)));
+	      if (!r && !noerror)
+                error (fstart, "%s: %s", name, strerror (errno));
+	    }
+
+	  /* Restore conditional state.  */
+	  restore_conditionals (save);
+
+          goto rule_complete;
+	}
+
+      if (try_variable_definition (fstart, p, o_file, 0))
+	/* This line has been dealt with.  */
+	goto rule_complete;
+
+      /* This line starts with a tab but was not caught above because there
+         was no preceding target, and the line might have been usable as a
+         variable definition.  But now we know it is definitely lossage.  */
+      if (line[0] == cmd_prefix)
+        fatal(fstart, _("commands commence before first target"));
+
+      /* This line describes some target files.  This is complicated by
+         the existence of target-specific variables, because we can't
+         expand the entire line until we know if we have one or not.  So
+         we expand the line word by word until we find the first `:',
+         then check to see if it's a target-specific variable.
+
+         In this algorithm, `lb_next' will point to the beginning of the
+         unexpanded parts of the input buffer, while `p2' points to the
+         parts of the expanded buffer we haven't searched yet. */
+
+      {
+        enum make_word_type wtype;
+        enum variable_origin v_origin;
+        int exported;
+        char *cmdleft, *semip, *lb_next;
+        unsigned int plen = 0;
+        char *colonp;
+        const char *end, *beg; /* Helpers for whitespace stripping. */
+
+        /* Record the previous rule.  */
+
+        record_waiting_files ();
+        tgts_started = fstart->lineno;
+
+        /* Search the line for an unquoted ; that is not after an
+           unquoted #.  */
+        cmdleft = find_char_unquote (line, ';', '#', 0, 1);
+        if (cmdleft != 0 && *cmdleft == '#')
+          {
+            /* We found a comment before a semicolon.  */
+            *cmdleft = '\0';
+            cmdleft = 0;
+          }
+        else if (cmdleft != 0)
+          /* Found one.  Cut the line short there before expanding it.  */
+          *(cmdleft++) = '\0';
+        semip = cmdleft;
+
+        collapse_continuations (line);
+
+        /* We can't expand the entire line, since if it's a per-target
+           variable we don't want to expand it.  So, walk from the
+           beginning, expanding as we go, and looking for "interesting"
+           chars.  The first word is always expandable.  */
+        wtype = get_next_mword(line, NULL, &lb_next, &wlen);
+        switch (wtype)
+          {
+          case w_eol:
+            if (cmdleft != 0)
+              fatal(fstart, _("missing rule before commands"));
+            /* This line contained something but turned out to be nothing
+               but whitespace (a comment?).  */
+            continue;
+
+          case w_colon:
+          case w_dcolon:
+            /* We accept and ignore rules without targets for
+               compatibility with SunOS 4 make.  */
+            no_targets = 1;
+            continue;
+
+          default:
+            break;
+          }
+
+        p2 = variable_expand_string(NULL, lb_next, wlen);
+
+        while (1)
+          {
+            lb_next += wlen;
+            if (cmdleft == 0)
+              {
+                /* Look for a semicolon in the expanded line.  */
+                cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
+
+                if (cmdleft != 0)
+                  {
+                    unsigned long p2_off = p2 - variable_buffer;
+                    unsigned long cmd_off = cmdleft - variable_buffer;
+                    char *pend = p2 + strlen(p2);
+
+                    /* Append any remnants of lb, then cut the line short
+                       at the semicolon.  */
+                    *cmdleft = '\0';
+
+                    /* One school of thought says that you shouldn't expand
+                       here, but merely copy, since now you're beyond a ";"
+                       and into a command script.  However, the old parser
+                       expanded the whole line, so we continue that for
+                       backwards-compatiblity.  Also, it wouldn't be
+                       entirely consistent, since we do an unconditional
+                       expand below once we know we don't have a
+                       target-specific variable. */
+                    (void)variable_expand_string(pend, lb_next, (long)-1);
+                    lb_next += strlen(lb_next);
+                    p2 = variable_buffer + p2_off;
+                    cmdleft = variable_buffer + cmd_off + 1;
+                  }
+              }
+
+            colonp = find_char_unquote(p2, ':', 0, 0, 0);
+#ifdef HAVE_DOS_PATHS
+            /* The drive spec brain-damage strikes again...  */
+            /* Note that the only separators of targets in this context
+               are whitespace and a left paren.  If others are possible,
+               they should be added to the string in the call to index.  */
+            while (colonp && (colonp[1] == '/' || colonp[1] == '\\') &&
+                   colonp > p2 && isalpha ((unsigned char)colonp[-1]) &&
+                   (colonp == p2 + 1 || strchr (" \t(", colonp[-2]) != 0))
+              colonp = find_char_unquote(colonp + 1, ':', 0, 0, 0);
+#endif
+            if (colonp != 0)
+              break;
+
+            wtype = get_next_mword(lb_next, NULL, &lb_next, &wlen);
+            if (wtype == w_eol)
+              break;
+
+            p2 += strlen(p2);
+            *(p2++) = ' ';
+            p2 = variable_expand_string(p2, lb_next, wlen);
+            /* We don't need to worry about cmdleft here, because if it was
+               found in the variable_buffer the entire buffer has already
+               been expanded... we'll never get here.  */
+          }
+
+        p2 = next_token (variable_buffer);
+
+        /* If the word we're looking at is EOL, see if there's _anything_
+           on the line.  If not, a variable expanded to nothing, so ignore
+           it.  If so, we can't parse this line so punt.  */
+        if (wtype == w_eol)
+          {
+            if (*p2 != '\0')
+              /* There's no need to be ivory-tower about this: check for
+                 one of the most common bugs found in makefiles...  */
+              fatal (fstart, _("missing separator%s"),
+                     !strneq(line, "        ", 8) ? ""
+                     : _(" (did you mean TAB instead of 8 spaces?)"));
+            continue;
+          }
+
+        /* Make the colon the end-of-string so we know where to stop
+           looking for targets.  */
+        *colonp = '\0';
+        filenames = multi_glob (parse_file_seq (&p2, '\0',
+                                                sizeof (struct nameseq),
+                                                1),
+                                sizeof (struct nameseq));
+        *p2 = ':';
+
+        if (!filenames)
+          {
+            /* We accept and ignore rules without targets for
+               compatibility with SunOS 4 make.  */
+            no_targets = 1;
+            continue;
+          }
+        /* This should never be possible; we handled it above.  */
+        assert (*p2 != '\0');
+        ++p2;
+
+        /* Is this a one-colon or two-colon entry?  */
+        two_colon = *p2 == ':';
+        if (two_colon)
+          p2++;
+
+        /* Test to see if it's a target-specific variable.  Copy the rest
+           of the buffer over, possibly temporarily (we'll expand it later
+           if it's not a target-specific variable).  PLEN saves the length
+           of the unparsed section of p2, for later.  */
+        if (*lb_next != '\0')
+          {
+            unsigned int l = p2 - variable_buffer;
+            plen = strlen (p2);
+            variable_buffer_output (p2+plen, lb_next, strlen (lb_next)+1);
+            p2 = variable_buffer + l;
+          }
+
+        /* See if it's an "override" or "export" keyword; if so see if what
+           comes after it looks like a variable definition.  */
+
+        wtype = get_next_mword (p2, NULL, &p, &wlen);
+
+        v_origin = o_file;
+        exported = 0;
+        if (wtype == w_static)
+          {
+            if (word1eq ("override"))
+              {
+                v_origin = o_override;
+                wtype = get_next_mword (p+wlen, NULL, &p, &wlen);
+              }
+            else if (word1eq ("export"))
+              {
+                exported = 1;
+                wtype = get_next_mword (p+wlen, NULL, &p, &wlen);
+              }
+          }
+
+        if (wtype != w_eol)
+          wtype = get_next_mword (p+wlen, NULL, NULL, NULL);
+
+        if (wtype == w_varassign)
+          {
+            /* If there was a semicolon found, add it back, plus anything
+               after it.  */
+            if (semip)
+              {
+                unsigned int l = p - variable_buffer;
+                *(--semip) = ';';
+                variable_buffer_output (p2 + strlen (p2),
+                                        semip, strlen (semip)+1);
+                p = variable_buffer + l;
+              }
+            record_target_var (filenames, p, v_origin, exported, fstart);
+            filenames = 0;
+            continue;
+          }
+
+        /* This is a normal target, _not_ a target-specific variable.
+           Unquote any = in the dependency list.  */
+        find_char_unquote (lb_next, '=', 0, 0, 0);
+
+        /* We have some targets, so don't ignore the following commands.  */
+        no_targets = 0;
+
+        /* Expand the dependencies, etc.  */
+        if (*lb_next != '\0')
+          {
+            unsigned int l = p2 - variable_buffer;
+            (void) variable_expand_string (p2 + plen, lb_next, (long)-1);
+            p2 = variable_buffer + l;
+
+            /* Look for a semicolon in the expanded line.  */
+            if (cmdleft == 0)
+              {
+                cmdleft = find_char_unquote (p2, ';', 0, 0, 0);
+                if (cmdleft != 0)
+                  *(cmdleft++) = '\0';
+              }
+          }
+
+        /* Is this a static pattern rule: `target: %targ: %dep; ...'?  */
+        p = strchr (p2, ':');
+        while (p != 0 && p[-1] == '\\')
+          {
+            register char *q = &p[-1];
+            register int backslash = 0;
+            while (*q-- == '\\')
+              backslash = !backslash;
+            if (backslash)
+              p = strchr (p + 1, ':');
+            else
+              break;
+          }
+#ifdef _AMIGA
+        /* Here, the situation is quite complicated. Let's have a look
+           at a couple of targets:
+
+           install: dev:make
+
+           dev:make: make
+
+           dev:make:: xyz
+
+           The rule is that it's only a target, if there are TWO :'s
+           OR a space around the :.
+        */
+        if (p && !(isspace ((unsigned char)p[1]) || !p[1]
+                   || isspace ((unsigned char)p[-1])))
+          p = 0;
+#endif
+#ifdef HAVE_DOS_PATHS
+        {
+          int check_again;
+          do {
+            check_again = 0;
+            /* For DOS-style paths, skip a "C:\..." or a "C:/..." */
+            if (p != 0 && (p[1] == '\\' || p[1] == '/') &&
+                isalpha ((unsigned char)p[-1]) &&
+                (p == p2 + 1 || strchr (" \t:(", p[-2]) != 0)) {
+              p = strchr (p + 1, ':');
+              check_again = 1;
+            }
+          } while (check_again);
+        }
+#endif
+        if (p != 0)
+          {
+            struct nameseq *target;
+            target = parse_file_seq (&p2, ':', sizeof (struct nameseq), 1);
+            ++p2;
+            if (target == 0)
+              fatal (fstart, _("missing target pattern"));
+            else if (target->next != 0)
+              fatal (fstart, _("multiple target patterns (target `%s')"), target->name); /* bird */
+            pattern_percent = find_percent_cached (&target->name);
+            pattern = target->name;
+            if (pattern_percent == 0)
+              fatal (fstart, _("target pattern contains no `%%' (target `%s')"), target->name); /* bird */
+            free (target);
+          }
+        else
+          pattern = 0;
+
+        /* Strip leading and trailing whitespaces. */
+        beg = p2;
+        end = beg + strlen (beg) - 1;
+        strip_whitespace (&beg, &end);
+
+        if (beg <= end && *beg != '\0')
+          {
+            /* Put all the prerequisites here; they'll be parsed later.  */
+            deps = alloc_dep ();
+            deps->name = strcache_add_len (beg, end - beg + 1);
+          }
+        else
+          deps = 0;
+
+        commands_idx = 0;
+        if (cmdleft != 0)
+          {
+            /* Semicolon means rest of line is a command.  */
+            unsigned int l = strlen (cmdleft);
+
+            cmds_started = fstart->lineno;
+
+            /* Add this command line to the buffer.  */
+            if (l + 2 > commands_len)
+              {
+                commands_len = (l + 2) * 2;
+                commands = xrealloc (commands, commands_len);
+              }
+            memcpy (commands, cmdleft, l);
+            commands_idx += l;
+            commands[commands_idx++] = '\n';
+          }
+
+        /* Determine if this target should be made default. We used to do
+           this in record_files() but because of the delayed target recording
+           and because preprocessor directives are legal in target's commands
+           it is too late. Consider this fragment for example:
+
+           foo:
+
+           ifeq ($(.DEFAULT_GOAL),foo)
+              ...
+           endif
+
+           Because the target is not recorded until after ifeq directive is
+           evaluated the .DEFAULT_GOAL does not contain foo yet as one
+           would expect. Because of this we have to move some of the logic
+           here.  */
+
+        if (**default_goal_name == '\0' && set_default)
+          {
+            const char *name;
+            struct dep *d;
+            struct nameseq *t = filenames;
+
+            for (; t != 0; t = t->next)
+              {
+                int reject = 0;
+                name = t->name;
+
+                /* We have nothing to do if this is an implicit rule. */
+                if (strchr (name, '%') != 0)
+                  break;
+
+                /* See if this target's name does not start with a `.',
+                   unless it contains a slash.  */
+                if (*name == '.' && strchr (name, '/') == 0
+#ifdef HAVE_DOS_PATHS
+                    && strchr (name, '\\') == 0
+#endif
+                    )
+                  continue;
+
+
+                /* If this file is a suffix, don't let it be
+                   the default goal file.  */
+                for (d = suffix_file->deps; d != 0; d = d->next)
+                  {
+                    register struct dep *d2;
+                    if (*dep_name (d) != '.' && streq (name, dep_name (d)))
+                      {
+                        reject = 1;
+                        break;
+                      }
+                    for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)
+                      {
+                        unsigned int l = strlen (dep_name (d2));
+                        if (!strneq (name, dep_name (d2), l))
+                          continue;
+                        if (streq (name + l, dep_name (d)))
+                          {
+                            reject = 1;
+                            break;
+                          }
+                      }
+
+                    if (reject)
+                      break;
+                  }
+
+                if (!reject)
+                  {
+                    define_variable_global (".DEFAULT_GOAL", 13, t->name,
+                                            o_file, 0, NILF);
+                    break;
+                  }
+              }
+          }
+
+        continue;
+      }
+
+      /* We get here except in the case that we just read a rule line.
+	 Record now the last rule we read, so following spurious
+	 commands are properly diagnosed.  */
+ rule_complete:
+      record_waiting_files ();
+    }
+
+#undef	word1eq
+
+  if (conditionals->if_cmds)
+    fatal (fstart, _("missing `endif'"));
+
+  /* At eof, record the last rule.  */
+  record_waiting_files ();
+
+  if (collapsed)
+    free (collapsed);
+  free (commands);
+
+  return 1;
+}
+
+
+
+/* Remove comments from LINE.
+   This is done by copying the text at LINE onto itself.  */
+
+static void
+remove_comments (char *line)
+{
+  char *comment;
+
+  comment = find_char_unquote (line, '#', 0, 0, 0);
+
+  if (comment != 0)
+    /* Cut off the line at the #.  */
+    *comment = '\0';
+}
+
+/* Execute a `define' directive.
+   The first line has already been read, and NAME is the name of
+   the variable to be defined.  The following lines remain to be read.  */
+
+static void
+do_define (char *name, unsigned int namelen,
+           enum variable_origin origin, struct ebuffer *ebuf)
+{
+  struct floc defstart;
+  long nlines = 0;
+  int nlevels = 1;
+  unsigned int length = 100;
+  char *definition = xmalloc (length);
+  unsigned int idx = 0;
+  char *p;
+
+  /* Expand the variable name.  */
+  char *var = alloca (namelen + 1);
+  memcpy (var, name, namelen);
+  var[namelen] = '\0';
+  var = variable_expand (var);
+
+  defstart = ebuf->floc;
+
+  while (1)
+    {
+      unsigned int len;
+      char *line;
+
+      nlines = readline (ebuf);
+      ebuf->floc.lineno += nlines;
+
+      /* If there is nothing left to eval, we're done. */
+      if (nlines < 0)
+        break;
+
+      line = ebuf->buffer;
+
+      collapse_continuations (line);
+
+      /* If the line doesn't begin with a tab, test to see if it introduces
+         another define, or ends one.  */
+
+      /* Stop if we find an 'endef' */
+      if (line[0] != cmd_prefix)
+        {
+          p = next_token (line);
+          len = strlen (p);
+
+          /* If this is another 'define', increment the level count.  */
+          if ((len == 6 || (len > 6 && isblank ((unsigned char)p[6])))
+              && strneq (p, "define", 6))
+            ++nlevels;
+
+          /* If this is an 'endef', decrement the count.  If it's now 0,
+             we've found the last one.  */
+          else if ((len == 5 || (len > 5 && isblank ((unsigned char)p[5])))
+                   && strneq (p, "endef", 5))
+            {
+              p += 5;
+              remove_comments (p);
+              if (*next_token (p) != '\0')
+                error (&ebuf->floc,
+                       _("Extraneous text after `endef' directive"));
+
+              if (--nlevels == 0)
+                {
+                  /* Define the variable.  */
+                  if (idx == 0)
+                    definition[0] = '\0';
+                  else
+                    definition[idx - 1] = '\0';
+
+                  /* Always define these variables in the global set.  */
+                  define_variable_global (var, strlen (var), definition,
+                                          origin, 1, &defstart);
+                  free (definition);
+                  return;
+                }
+            }
+        }
+
+      /* Otherwise add this line to the variable definition.  */
+      len = strlen (line);
+      if (idx + len + 1 > length)
+        {
+          length = (idx + len) * 2;
+          definition = xrealloc (definition, length + 1);
+        }
+
+      memcpy (&definition[idx], line, len);
+      idx += len;
+      /* Separate lines with a newline.  */
+      definition[idx++] = '\n';
+    }
+
+  /* No `endef'!!  */
+  fatal (&defstart, _("missing `endef', unterminated `define'"));
+
+  /* NOTREACHED */
+  return;
+}
+
+
+/* Interpret conditional commands "ifdef", "ifndef", "ifeq",
+   "ifneq", "if1of", "ifn1of", "else" and "endif".
+   LINE is the input line, with the command as its first word.
+
+   FILENAME and LINENO are the filename and line number in the
+   current makefile.  They are used for error messages.
+
+   Value is -2 if the line is not a conditional at all,
+   -1 if the line is an invalid conditional,
+   0 if following text should be interpreted,
+   1 if following text should be ignored.  */
+
+static int
+conditional_line (char *line, int len, const struct floc *flocp)
+{
+  char *cmdname;
+  enum { c_ifdef, c_ifndef, c_ifeq, c_ifneq,
+#ifdef CONFIG_WITH_SET_CONDITIONALS
+    c_if1of, c_ifn1of,
+#endif
+#ifdef CONFIG_WITH_IF_CONDITIONALS
+    c_ifcond,
+#endif
+    c_else, c_endif
+  } cmdtype;
+  unsigned int i;
+  unsigned int o;
+
+  /* Compare a word, both length and contents. */
+#define	word1eq(s)      (len == sizeof(s)-1 && strneq (s, line, sizeof(s)-1))
+#define	chkword(s, t)   if (word1eq (s)) { cmdtype = (t); cmdname = (s); }
+
+  /* Make sure this line is a conditional.  */
+  chkword ("ifdef", c_ifdef)
+  else chkword ("ifndef", c_ifndef)
+  else chkword ("ifeq", c_ifeq)
+  else chkword ("ifneq", c_ifneq)
+#ifdef CONFIG_WITH_SET_CONDITIONALS
+  else chkword ("if1of", c_if1of)
+  else chkword ("ifn1of", c_ifn1of)
+#endif
+#ifdef CONFIG_WITH_IF_CONDITIONALS
+  else chkword ("if", c_ifcond)
+#endif
+  else chkword ("else", c_else)
+  else chkword ("endif", c_endif)
+  else
+    return -2;
+
+  /* Found one: skip past it and any whitespace after it.  */
+  line = next_token (line + len);
+
+#define EXTRANEOUS() error (flocp, _("Extraneous text after `%s' directive"), cmdname)
+
+  /* An 'endif' cannot contain extra text, and reduces the if-depth by 1  */
+  if (cmdtype == c_endif)
+    {
+      if (*line != '\0')
+	EXTRANEOUS ();
+
+      if (!conditionals->if_cmds)
+	fatal (flocp, _("extraneous `%s'"), cmdname);
+
+      --conditionals->if_cmds;
+
+      goto DONE;
+    }
+
+  /* An 'else' statement can either be simple, or it can have another
+     conditional after it.  */
+  if (cmdtype == c_else)
+    {
+      const char *p;
+
+      if (!conditionals->if_cmds)
+	fatal (flocp, _("extraneous `%s'"), cmdname);
+
+      o = conditionals->if_cmds - 1;
+
+      if (conditionals->seen_else[o])
+        fatal (flocp, _("only one `else' per conditional"));
+
+      /* Change the state of ignorance.  */
+      switch (conditionals->ignoring[o])
+        {
+          case 0:
+            /* We've just been interpreting.  Never do it again.  */
+            conditionals->ignoring[o] = 2;
+            break;
+          case 1:
+            /* We've never interpreted yet.  Maybe this time!  */
+            conditionals->ignoring[o] = 0;
+            break;
+        }
+
+      /* It's a simple 'else'.  */
+      if (*line == '\0')
+        {
+          conditionals->seen_else[o] = 1;
+          goto DONE;
+        }
+
+      /* The 'else' has extra text.  That text must be another conditional
+         and cannot be an 'else' or 'endif'.  */
+
+      /* Find the length of the next word.  */
+      for (p = line+1; *p != '\0' && !isspace ((unsigned char)*p); ++p)
+        ;
+      len = p - line;
+
+      /* If it's 'else' or 'endif' or an illegal conditional, fail.  */
+      if (word1eq("else") || word1eq("endif")
+          || conditional_line (line, len, flocp) < 0)
+	EXTRANEOUS ();
+      else
+        {
+          /* conditional_line() created a new level of conditional.
+             Raise it back to this level.  */
+          if (conditionals->ignoring[o] < 2)
+            conditionals->ignoring[o] = conditionals->ignoring[o+1];
+          --conditionals->if_cmds;
+        }
+
+      goto DONE;
+    }
+
+  if (conditionals->allocated == 0)
+    {
+      conditionals->allocated = 5;
+      conditionals->ignoring = xmalloc (conditionals->allocated);
+      conditionals->seen_else = xmalloc (conditionals->allocated);
+    }
+
+  o = conditionals->if_cmds++;
+  if (conditionals->if_cmds > conditionals->allocated)
+    {
+      conditionals->allocated += 5;
+      conditionals->ignoring = xrealloc (conditionals->ignoring,
+                                         conditionals->allocated);
+      conditionals->seen_else = xrealloc (conditionals->seen_else,
+                                          conditionals->allocated);
+    }
+
+  /* Record that we have seen an `if...' but no `else' so far.  */
+  conditionals->seen_else[o] = 0;
+
+  /* Search through the stack to see if we're already ignoring.  */
+  for (i = 0; i < o; ++i)
+    if (conditionals->ignoring[i])
+      {
+	/* We are already ignoring, so just push a level to match the next
+	   "else" or "endif", and keep ignoring.  We don't want to expand
+	   variables in the condition.  */
+	conditionals->ignoring[o] = 1;
+	return 1;
+      }
+
+  if (cmdtype == c_ifdef || cmdtype == c_ifndef)
+    {
+      char *var;
+      struct variable *v;
+      char *p;
+
+      /* Expand the thing we're looking up, so we can use indirect and
+         constructed variable names.  */
+      var = allocated_variable_expand (line);
+
+      /* Make sure there's only one variable name to test.  */
+      p = end_of_token (var);
+      i = p - var;
+      p = next_token (p);
+      if (*p != '\0')
+	return -1;
+
+      var[i] = '\0';
+      v = lookup_variable (var, i);
+
+      conditionals->ignoring[o] =
+        ((v != 0 && *v->value != '\0') == (cmdtype == c_ifndef));
+
+      free (var);
+    }
+#ifdef CONFIG_WITH_IF_CONDITIONALS
+  else if (cmdtype == c_ifcond)
+    {
+      int rval = expr_eval_if_conditionals (line, flocp);
+      if (rval == -1)
+          return rval;
+      conditionals->ignoring[o] = rval;
+    }
+#endif
+  else
+    {
+#ifdef CONFIG_WITH_SET_CONDITIONALS
+      /* "ifeq", "ifneq", "if1of" or "ifn1of". */
+#else
+      /* "ifeq" or "ifneq".  */
+#endif
+      char *s1, *s2;
+      unsigned int l;
+      char termin = *line == '(' ? ',' : *line;
+
+      if (termin != ',' && termin != '"' && termin != '\'')
+	return -1;
+
+      s1 = ++line;
+      /* Find the end of the first string.  */
+      if (termin == ',')
+	{
+	  int count = 0;
+	  for (; *line != '\0'; ++line)
+	    if (*line == '(')
+	      ++count;
+	    else if (*line == ')')
+	      --count;
+	    else if (*line == ',' && count <= 0)
+	      break;
+	}
+      else
+	while (*line != '\0' && *line != termin)
+	  ++line;
+
+      if (*line == '\0')
+	return -1;
+
+      if (termin == ',')
+	{
+	  /* Strip blanks after the first string.  */
+	  char *p = line++;
+	  while (isblank ((unsigned char)p[-1]))
+	    --p;
+	  *p = '\0';
+	}
+      else
+	*line++ = '\0';
+
+      s2 = variable_expand (s1);
+      /* We must allocate a new copy of the expanded string because
+	 variable_expand re-uses the same buffer.  */
+      l = strlen (s2);
+      s1 = alloca (l + 1);
+      memcpy (s1, s2, l + 1);
+
+      if (termin != ',')
+	/* Find the start of the second string.  */
+	line = next_token (line);
+
+      termin = termin == ',' ? ')' : *line;
+      if (termin != ')' && termin != '"' && termin != '\'')
+	return -1;
+
+      /* Find the end of the second string.  */
+      if (termin == ')')
+	{
+	  int count = 0;
+	  s2 = next_token (line);
+	  for (line = s2; *line != '\0'; ++line)
+	    {
+	      if (*line == '(')
+		++count;
+	      else if (*line == ')')
+		{
+		  if (count <= 0)
+		    break;
+		  else
+		    --count;
+		}
+	    }
+	}
+      else
+	{
+	  ++line;
+	  s2 = line;
+	  while (*line != '\0' && *line != termin)
+	    ++line;
+	}
+
+      if (*line == '\0')
+	return -1;
+
+      *line = '\0';
+      line = next_token (++line);
+      if (*line != '\0')
+	EXTRANEOUS ();
+
+      s2 = variable_expand (s2);
+#ifdef CONFIG_WITH_SET_CONDITIONALS
+      if (cmdtype == c_if1of || cmdtype == c_ifn1of)
+        {
+          const char *s1_cur;
+          unsigned int s1_len;
+          const char *s1_iterator = s1;
+
+          conditionals->ignoring[o] = (cmdtype == c_if1of); /* if not found */
+          while ((s1_cur = find_next_token (&s1_iterator, &s1_len)) != 0)
+            {
+              const char *s2_cur;
+              unsigned int s2_len;
+              const char *s2_iterator = s2;
+              while ((s2_cur = find_next_token (&s2_iterator, &s2_len)) != 0)
+                if (s2_len == s1_len
+                 && strneq (s2_cur, s1_cur, s1_len) )
+                  {
+                    conditionals->ignoring[o] = (cmdtype != c_if1of); /* found */
+                    break;
+                  }
+            }
+        }
+      else
+        conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq));
+#else
+      conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq));
+#endif
+    }
+
+ DONE:
+  /* Search through the stack to see if we're ignoring.  */
+  for (i = 0; i < conditionals->if_cmds; ++i)
+    if (conditionals->ignoring[i])
+      return 1;
+  return 0;
+}
+
+
+/* Remove duplicate dependencies in CHAIN.  */
+
+static unsigned long
+dep_hash_1 (const void *key)
+{
+  return_STRING_HASH_1 (dep_name ((struct dep const *) key));
+}
+
+static unsigned long
+dep_hash_2 (const void *key)
+{
+  return_STRING_HASH_2 (dep_name ((struct dep const *) key));
+}
+
+static int
+dep_hash_cmp (const void *x, const void *y)
+{
+  struct dep *dx = (struct dep *) x;
+  struct dep *dy = (struct dep *) y;
+  int cmp = strcmp (dep_name (dx), dep_name (dy));
+
+  /* If the names are the same but ignore_mtimes are not equal, one of these
+     is an order-only prerequisite and one isn't.  That means that we should
+     remove the one that isn't and keep the one that is.  */
+
+  if (!cmp && dx->ignore_mtime != dy->ignore_mtime)
+    dx->ignore_mtime = dy->ignore_mtime = 0;
+
+  return cmp;
+}
+
+
+void
+uniquize_deps (struct dep *chain)
+{
+  struct hash_table deps;
+  register struct dep **depp;
+
+  hash_init (&deps, 500, dep_hash_1, dep_hash_2, dep_hash_cmp);
+
+  /* Make sure that no dependencies are repeated.  This does not
+     really matter for the purpose of updating targets, but it
+     might make some names be listed twice for $^ and $?.  */
+
+  depp = &chain;
+  while (*depp)
+    {
+      struct dep *dep = *depp;
+      struct dep **dep_slot = (struct dep **) hash_find_slot (&deps, dep);
+      if (HASH_VACANT (*dep_slot))
+	{
+	  hash_insert_at (&deps, dep, dep_slot);
+	  depp = &dep->next;
+	}
+      else
+	{
+	  /* Don't bother freeing duplicates.
+	     It's dangerous and little benefit accrues.  */
+	  *depp = dep->next;
+	}
+    }
+
+  hash_free (&deps, 0);
+}
+
+
+/* Record target-specific variable values for files FILENAMES.
+   TWO_COLON is nonzero if a double colon was used.
+
+   The links of FILENAMES are freed, and so are any names in it
+   that are not incorporated into other data structures.
+
+   If the target is a pattern, add the variable to the pattern-specific
+   variable value list.  */
+
+static void
+record_target_var (struct nameseq *filenames, char *defn,
+                   enum variable_origin origin, int exported,
+                   const struct floc *flocp)
+{
+  struct nameseq *nextf;
+  struct variable_set_list *global;
+
+  global = current_variable_set_list;
+
+  /* If the variable is an append version, store that but treat it as a
+     normal recursive variable.  */
+
+  for (; filenames != 0; filenames = nextf)
+    {
+      struct variable *v;
+      const char *name = filenames->name;
+      const char *fname;
+      const char *percent;
+      struct pattern_var *p;
+
+      nextf = filenames->next;
+      free (filenames);
+
+      /* If it's a pattern target, then add it to the pattern-specific
+         variable list.  */
+      percent = find_percent_cached (&name);
+      if (percent)
+        {
+          /* Get a reference for this pattern-specific variable struct.  */
+          p = create_pattern_var (name, percent);
+          p->variable.fileinfo = *flocp;
+          /* I don't think this can fail since we already determined it was a
+             variable definition.  */
+          v = parse_variable_definition (&p->variable, defn);
+          assert (v != 0);
+
+          if (v->flavor == f_simple)
+            v->value = allocated_variable_expand (v->value);
+          else
+            v->value = xstrdup (v->value);
+
+          fname = p->target;
+        }
+      else
+        {
+          struct file *f;
+
+          /* Get a file reference for this file, and initialize it.
+             We don't want to just call enter_file() because that allocates a
+             new entry if the file is a double-colon, which we don't want in
+             this situation.  */
+          f = lookup_file (name);
+          if (!f)
+            f = enter_file (strcache_add (name));
+          else if (f->double_colon)
+            f = f->double_colon;
+
+          initialize_file_variables (f, 1);
+          fname = f->name;
+
+          current_variable_set_list = f->variables;
+          v = try_variable_definition (flocp, defn, origin, 1);
+          if (!v)
+            error (flocp, _("Malformed target-specific variable definition"));
+          current_variable_set_list = global;
+        }
+
+      /* Set up the variable to be *-specific.  */
+      v->origin = origin;
+      v->per_target = 1;
+      v->export = exported ? v_export : v_default;
+
+      /* If it's not an override, check to see if there was a command-line
+         setting.  If so, reset the value.  */
+      if (origin != o_override)
+        {
+          struct variable *gv;
+          int len = strlen(v->name);
+
+          gv = lookup_variable (v->name, len);
+          if (gv && (gv->origin == o_env_override || gv->origin == o_command))
+            {
+              if (v->value != 0)
+                free (v->value);
+              v->value = xstrdup (gv->value);
+              v->origin = gv->origin;
+              v->recursive = gv->recursive;
+              v->append = 0;
+            }
+        }
+    }
+}
+
+
+/* Record a description line for files FILENAMES,
+   with dependencies DEPS, commands to execute described
+   by COMMANDS and COMMANDS_IDX, coming from FILENAME:COMMANDS_STARTED.
+   TWO_COLON is nonzero if a double colon was used.
+   If not nil, PATTERN is the `%' pattern to make this
+   a static pattern rule, and PATTERN_PERCENT is a pointer
+   to the `%' within it.
+
+   The links of FILENAMES are freed, and so are any names in it
+   that are not incorporated into other data structures.  */
+
+static void
+record_files (struct nameseq *filenames, const char *pattern,
+              const char *pattern_percent, struct dep *deps,
+              unsigned int cmds_started, char *commands,
+              unsigned int commands_idx, int two_colon,
+              const struct floc *flocp)
+{
+  struct nameseq *nextf;
+  int implicit = 0;
+  unsigned int max_targets = 0, target_idx = 0;
+  const char **targets = 0, **target_percents = 0;
+  struct commands *cmds;
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  struct file *prev_file = 0;
+  enum multitarget_mode { m_unsettled, m_no, m_yes, m_yes_maybe }
+    multi_mode = !two_colon && !pattern ? m_unsettled : m_no;
+#endif
+
+  /* If we've already snapped deps, that means we're in an eval being
+     resolved after the makefiles have been read in.  We can't add more rules
+     at this time, since they won't get snapped and we'll get core dumps.
+     See Savannah bug # 12124.  */
+  if (snapped_deps)
+    fatal (flocp, _("prerequisites cannot be defined in command scripts"));
+
+  if (commands_idx > 0)
+    {
+      cmds = xmalloc (sizeof (struct commands));
+      cmds->fileinfo.filenm = flocp->filenm;
+      cmds->fileinfo.lineno = cmds_started;
+      cmds->commands = savestring (commands, commands_idx);
+      cmds->command_lines = 0;
+    }
+  else
+    cmds = 0;
+
+  for (; filenames != 0; filenames = nextf)
+    {
+      const char *name = filenames->name;
+      struct file *f;
+      struct dep *this = 0;
+      const char *implicit_percent;
+
+      nextf = filenames->next;
+      free (filenames);
+
+      /* Check for special targets.  Do it here instead of, say, snap_deps()
+         so that we can immediately use the value.  */
+
+      if (streq (name, ".POSIX"))
+        posix_pedantic = 1;
+      else if (streq (name, ".SECONDEXPANSION"))
+        second_expansion = 1;
+#ifdef CONFIG_WITH_2ND_TARGET_EXPANSION
+      else if (streq (name, ".SECONDTARGETEXPANSION"))
+        second_target_expansion = 1;
+#endif
+
+      implicit_percent = find_percent_cached (&name);
+      implicit |= implicit_percent != 0;
+
+      if (implicit)
+        {
+          if (pattern != 0)
+            fatal (flocp, _("mixed implicit and static pattern rules"));
+
+          if (implicit_percent == 0)
+            fatal (flocp, _("mixed implicit and normal rules"));
+
+	  if (targets == 0)
+	    {
+	      max_targets = 5;
+	      targets = xmalloc (5 * sizeof (char *));
+	      target_percents = xmalloc (5 * sizeof (char *));
+	      target_idx = 0;
+	    }
+	  else if (target_idx == max_targets - 1)
+	    {
+	      max_targets += 5;
+	      targets = xrealloc ((void *)targets, max_targets * sizeof (char *));
+	      target_percents = xrealloc ((void *)target_percents,
+                                          max_targets * sizeof (char *));
+	    }
+	  targets[target_idx] = name;
+	  target_percents[target_idx] = implicit_percent;
+	  ++target_idx;
+	  continue;
+	}
+
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+      /* Check for the explicit multitarget mode operators. For this to be
+         identified as an explicit multiple target rule, the first + or +|
+         operator *must* appear between the first two files. If not found as
+         the 2nd file or if found as the 1st file, the rule will be rejected
+         as a potential multiple first target rule. For the subsequent files
+         the operator is only required to switch between maybe and non-maybe
+         mode:
+         `primary + 2nd 3rd +| 4th-maybe + 5th-for-sure: deps; cmds'
+
+         The whole idea of the maybe-updated files is this:
+            timestamp +| maybe.h: src1.c src2.c
+                grep goes-into-maybe.h $* > timestamp
+                cmp timestamp maybe.h || cp -f timestamp maybe.h
+
+        This is implemented in remake.c where we don't consider the mtime of
+        the maybe-updated targets. */
+      if (multi_mode != m_no && name[0] == '+'
+        && (name[1] == '\0' || (name[1] == '|' && name[2] == '\0')))
+        {
+          if (!prev_file)
+            multi_mode = m_no; /* first */
+          else
+            {
+              if (multi_mode == m_unsettled)
+                {
+                  prev_file->multi_head = prev_file;
+
+                  /* Only the primary file needs the dependencies. */
+                  if (deps)
+                    {
+                      free_dep_chain (deps);
+                      deps = NULL;
+                    }
+                }
+              multi_mode = name[1] == '\0' ? m_yes : m_yes_maybe;
+              continue;
+            }
+        }
+      else if (multi_mode == m_unsettled && prev_file)
+        multi_mode = m_no;
+#endif
+
+      /* If this is a static pattern rule:
+         `targets: target%pattern: dep%pattern; cmds',
+         make sure the pattern matches this target name.  */
+      if (pattern && !pattern_matches (pattern, pattern_percent, name))
+        error (flocp, _("target `%s' doesn't match the target pattern"), name);
+      else if (deps)
+        {
+          /* If there are multiple filenames, copy the chain DEPS for all but
+             the last one.  It is not safe for the same deps to go in more
+             than one place in the database.  */
+          this = nextf != 0 ? copy_dep_chain (deps) : deps;
+          this->need_2nd_expansion = (second_expansion
+				      && strchr (this->name, '$'));
+        }
+
+      if (!two_colon)
+	{
+	  /* Single-colon.  Combine these dependencies
+	     with others in file's existing record, if any.  */
+	  f = enter_file (strcache_add (name));
+
+	  if (f->double_colon)
+	    fatal (flocp,
+                   _("target file `%s' has both : and :: entries"), f->name);
+
+	  /* If CMDS == F->CMDS, this target was listed in this rule
+	     more than once.  Just give a warning since this is harmless.  */
+	  if (cmds != 0 && cmds == f->cmds)
+	    error (flocp,
+                   _("target `%s' given more than once in the same rule."),
+                   f->name);
+
+	  /* Check for two single-colon entries both with commands.
+	     Check is_target so that we don't lose on files such as .c.o
+	     whose commands were preinitialized.  */
+	  else if (cmds != 0 && f->cmds != 0 && f->is_target)
+	    {
+	      error (&cmds->fileinfo,
+                     _("warning: overriding commands for target `%s'"),
+                     f->name);
+	      error (&f->cmds->fileinfo,
+                     _("warning: ignoring old commands for target `%s'"),
+                     f->name);
+	    }
+
+	  f->is_target = 1;
+
+	  /* Defining .DEFAULT with no deps or cmds clears it.  */
+	  if (f == default_file && this == 0 && cmds == 0)
+	    f->cmds = 0;
+	  if (cmds != 0)
+	    f->cmds = cmds;
+
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+          /* If this is an explicit multi target rule, add it to the
+             target chain and set the multi_maybe flag according to
+             the current mode. */
+
+          if (multi_mode >= m_yes)
+            {
+              f->multi_maybe = multi_mode == m_yes_maybe;
+              prev_file->multi_next = f;
+              assert (prev_file->multi_head != 0);
+              f->multi_head = prev_file->multi_head;
+
+              if (f == suffix_file)
+                error (flocp,
+                       _(".SUFFIXES encountered in an explicit multi target rule"));
+            }
+          prev_file = f;
+#endif
+
+	  /* Defining .SUFFIXES with no dependencies clears out the list of
+	     suffixes.  */
+	  if (f == suffix_file && this == 0)
+	    {
+              free_dep_chain (f->deps);
+	      f->deps = 0;
+	    }
+          else if (this != 0)
+	    {
+	      /* Add the file's old deps and the new ones in THIS together.  */
+
+              if (f->deps != 0)
+                {
+                  struct dep **d_ptr = &f->deps;
+
+                  while ((*d_ptr)->next != 0)
+                    d_ptr = &(*d_ptr)->next;
+
+                  if (cmds != 0)
+                    /* This is the rule with commands, so put its deps
+                       last. The rationale behind this is that $< expands to
+                       the first dep in the chain, and commands use $<
+                       expecting to get the dep that rule specifies.  However
+                       the second expansion algorithm reverses the order thus
+                       we need to make it last here.  */
+                    (*d_ptr)->next = this;
+                  else
+                    {
+                      /* This is the rule without commands. Put its
+                         dependencies at the end but before dependencies from
+                         the rule with commands (if any). This way everything
+                         appears in makefile order.  */
+
+                      if (f->cmds != 0)
+                        {
+                          this->next = *d_ptr;
+                          *d_ptr = this;
+                        }
+                      else
+                        (*d_ptr)->next = this;
+                    }
+                }
+              else
+                f->deps = this;
+
+              /* This is a hack. I need a way to communicate to snap_deps()
+                 that the last dependency line in this file came with commands
+                 (so that logic in snap_deps() can put it in front and all
+                 this $< -logic works). I cannot simply rely on file->cmds
+                 being not 0 because of the cases like the following:
+
+                 foo: bar
+                 foo:
+                     ...
+
+                 I am going to temporarily "borrow" UPDATING member in
+                 `struct file' for this.   */
+
+              if (cmds != 0)
+                f->updating = 1;
+	    }
+	}
+      else
+	{
+	  /* Double-colon.  Make a new record even if there already is one.  */
+	  f = lookup_file (name);
+
+	  /* Check for both : and :: rules.  Check is_target so
+	     we don't lose on default suffix rules or makefiles.  */
+	  if (f != 0 && f->is_target && !f->double_colon)
+	    fatal (flocp,
+                   _("target file `%s' has both : and :: entries"), f->name);
+	  f = enter_file (strcache_add (name));
+	  /* If there was an existing entry and it was a double-colon entry,
+	     enter_file will have returned a new one, making it the prev
+	     pointer of the old one, and setting its double_colon pointer to
+	     the first one.  */
+	  if (f->double_colon == 0)
+	    /* This is the first entry for this name, so we must set its
+	       double_colon pointer to itself.  */
+	    f->double_colon = f;
+	  f->is_target = 1;
+	  f->deps = this;
+	  f->cmds = cmds;
+	}
+
+      /* If this is a static pattern rule, set the stem to the part of its
+         name that matched the `%' in the pattern, so you can use $* in the
+         commands.  */
+      if (pattern)
+        {
+          static const char *percent = "%";
+          char *buffer = variable_expand ("");
+          const size_t buffer_offset = buffer - variable_buffer; /* bird */
+          char *o = patsubst_expand_pat (buffer, name, pattern, percent,
+                                         pattern_percent+1, percent+1);
+          buffer = variable_buffer + buffer_offset; /* bird - variable_buffer may have been reallocated. */
+          f->stem = strcache_add_len (buffer, o - buffer);
+          if (this)
+            {
+              this->staticpattern = 1;
+              this->stem = f->stem;
+            }
+        }
+
+      name = f->name;
+
+      /* If this target is a default target, update DEFAULT_GOAL_FILE.  */
+      if (streq (*default_goal_name, name)
+          && (default_goal_file == 0
+              || ! streq (default_goal_file->name, name)))
+        default_goal_file = f;
+    }
+
+  if (implicit)
+    {
+      if (deps)
+        deps->need_2nd_expansion = second_expansion;
+      create_pattern_rule (targets, target_percents, target_idx,
+                           two_colon, deps, cmds, 1);
+    }
+}
+
+
+/* Search STRING for an unquoted STOPCHAR or blank (if BLANK is nonzero).
+   Backslashes quote STOPCHAR, blanks if BLANK is nonzero, and backslash.
+   Quoting backslashes are removed from STRING by compacting it into
+   itself.  Returns a pointer to the first unquoted STOPCHAR if there is
+   one, or nil if there are none.  STOPCHARs inside variable references are
+   ignored if IGNOREVARS is true.
+
+   STOPCHAR _cannot_ be '$' if IGNOREVARS is true.  */
+
+static char *
+find_char_unquote (char *string, int stop1, int stop2, int blank,
+                   int ignorevars)
+{
+  unsigned int string_len = 0;
+  char *p = string;
+  register int ch; /* bird: 'optimiziations' */
+
+  if (ignorevars)
+    ignorevars = '$';
+
+  while (1)
+    {
+      if (stop2 && blank)
+	while ((ch = *p) != '\0' && ch != ignorevars && ch != stop1 && ch != stop2
+	       && ! isblank ((unsigned char) ch))
+	  ++p;
+      else if (stop2)
+	while ((ch = *p) != '\0' && ch != ignorevars && ch != stop1 && ch != stop2)
+	  ++p;
+      else if (blank)
+	while ((ch = *p) != '\0' && ch != ignorevars && ch != stop1
+	       && ! isblank ((unsigned char) ch))
+	  ++p;
+      else
+	while ((ch = *p) != '\0' && ch != ignorevars && ch != stop1)
+	  ++p;
+
+      if (ch == '\0')
+	break;
+
+      /* If we stopped due to a variable reference, skip over its contents.  */
+      if (ch == ignorevars)
+        {
+          char openparen = p[1];
+
+          p += 2;
+
+          /* Skip the contents of a non-quoted, multi-char variable ref.  */
+          if (openparen == '(' || openparen == '{')
+            {
+              unsigned int pcount = 1;
+              char closeparen = (openparen == '(' ? ')' : '}');
+
+              while ((ch = *p))
+                {
+                  if (ch == openparen)
+                    ++pcount;
+                  else if (ch == closeparen)
+                    if (--pcount == 0)
+                      {
+                        ++p;
+                        break;
+                      }
+                  ++p;
+                }
+            }
+
+          /* Skipped the variable reference: look for STOPCHARS again.  */
+          continue;
+        }
+
+      if (p > string && p[-1] == '\\')
+	{
+	  /* Search for more backslashes.  */
+	  int i = -2;
+	  while (&p[i] >= string && p[i] == '\\')
+	    --i;
+	  ++i;
+	  /* Only compute the length if really needed.  */
+	  if (string_len == 0)
+	    string_len = strlen (string);
+	  /* The number of backslashes is now -I.
+	     Copy P over itself to swallow half of them.  */
+	  memmove (&p[i], &p[i/2], (string_len - (p - string)) - (i/2) + 1);
+	  p += i/2;
+	  if (i % 2 == 0)
+	    /* All the backslashes quoted each other; the STOPCHAR was
+	       unquoted.  */
+	    return p;
+
+	  /* The STOPCHAR was quoted by a backslash.  Look for another.  */
+	}
+      else
+	/* No backslash in sight.  */
+	return p;
+    }
+
+  /* Never hit a STOPCHAR or blank (with BLANK nonzero).  */
+  return 0;
+}
+
+/* Search PATTERN for an unquoted % and handle quoting.  */
+
+char *
+find_percent (char *pattern)
+{
+  return find_char_unquote (pattern, '%', 0, 0, 0);
+}
+
+/* Search STRING for an unquoted % and handle quoting.  Returns a pointer to
+   the % or NULL if no % was found.
+   This version is used with strings in the string cache: if there's a need to
+   modify the string a new version will be added to the string cache and
+   *STRING will be set to that.  */
+
+const char *
+find_percent_cached (const char **string)
+{
+  const char *p = *string;
+  char *new = 0;
+  int slen;
+
+  /* If the first char is a % return now.  This lets us avoid extra tests
+     inside the loop.  */
+  if (*p == '%')
+    return p;
+
+  while (1)
+    {
+      while (*p != '\0' && *p != '%')
+        ++p;
+
+      if (*p == '\0')
+        break;
+
+      /* See if this % is escaped with a backslash; if not we're done.  */
+      if (p[-1] != '\\')
+        break;
+
+      {
+        /* Search for more backslashes.  */
+        char *pv;
+        int i = -2;
+
+        while (&p[i] >= *string && p[i] == '\\')
+          --i;
+        ++i;
+
+        /* At this point we know we'll need to allocate a new string.
+           Make a copy if we haven't yet done so.  */
+        if (! new)
+          {
+            slen = strlen (*string);
+            new = alloca (slen + 1);
+            memcpy (new, *string, slen + 1);
+            p = new + (p - *string);
+            *string = new;
+          }
+
+        /* At this point *string, p, and new all point into the same string.
+           Get a non-const version of p so we can modify new.  */
+        pv = new + (p - *string);
+
+        /* The number of backslashes is now -I.
+           Copy P over itself to swallow half of them.  */
+        memmove (&pv[i], &pv[i/2], (slen - (pv - new)) - (i/2) + 1);
+        p += i/2;
+
+        /* If the backslashes quoted each other; the % was unquoted.  */
+        if (i % 2 == 0)
+          break;
+      }
+    }
+
+  /* If we had to change STRING, add it to the strcache.  */
+  if (new)
+    {
+      *string = strcache_add (*string);
+      p = *string + (p - new);
+    }
+
+  /* If we didn't find a %, return NULL.  Otherwise return a ptr to it.  */
+  return (*p == '\0') ? NULL : p;
+}
+
+
+/* Parse a string into a sequence of filenames represented as a
+   chain of struct nameseq's in reverse order and return that chain.
+
+   The string is passed as STRINGP, the address of a string pointer.
+   The string pointer is updated to point at the first character
+   not parsed, which either is a null char or equals STOPCHAR.
+
+   SIZE is how big to construct chain elements.
+   This is useful if we want them actually to be other structures
+   that have room for additional info.
+
+   If STRIP is nonzero, strip `./'s off the beginning.  */
+
+struct nameseq *
+parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip)
+{
+  struct nameseq *new = 0;
+  struct nameseq *new1;
+#ifndef NO_ARCHIVES /* bird: MSC warning */
+  struct nameseq *lastnew1;
+#endif
+  char *p = *stringp;
+
+#ifdef VMS
+# define VMS_COMMA ','
+#else
+# define VMS_COMMA 0
+#endif
+
+  while (1)
+    {
+      const char *name;
+      char *q;
+
+      /* Skip whitespace; see if any more names are left.  */
+      p = next_token (p);
+      if (*p == '\0')
+	break;
+      if (*p == stopchar)
+	break;
+
+      /* There are, so find the end of the next name.  */
+      q = p;
+      p = find_char_unquote (q, stopchar, VMS_COMMA, 1, 0);
+#ifdef VMS
+	/* convert comma separated list to space separated */
+      if (p && *p == ',')
+	*p =' ';
+#endif
+#ifdef _AMIGA
+      if (stopchar == ':' && p && *p == ':'
+          && !(isspace ((unsigned char)p[1]) || !p[1]
+               || isspace ((unsigned char)p[-1])))
+	p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0);
+#endif
+#ifdef HAVE_DOS_PATHS
+    /* For DOS paths, skip a "C:\..." or a "C:/..." until we find the
+       first colon which isn't followed by a slash or a backslash.
+       Note that tokens separated by spaces should be treated as separate
+       tokens since make doesn't allow path names with spaces */
+    if (stopchar == ':')
+      while (p != 0 && !isspace ((unsigned char)*p) &&
+             (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]))
+        p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0);
+#endif
+      if (p == 0)
+	p = q + strlen (q);
+
+      if (strip)
+#ifdef VMS
+	/* Skip leading `[]'s.  */
+	while (p - q > 2 && q[0] == '[' && q[1] == ']')
+#else
+	/* Skip leading `./'s.  */
+	while (p - q > 2 && q[0] == '.' && q[1] == '/')
+#endif
+	  {
+	    q += 2;		/* Skip "./".  */
+	    while (q < p && *q == '/')
+	      /* Skip following slashes: ".//foo" is "foo", not "/foo".  */
+	      ++q;
+	  }
+
+      /* Extract the filename just found, and skip it.  */
+
+      if (q == p)
+	/* ".///" was stripped to "". */
+#if defined(VMS)
+	continue;
+#elif defined(_AMIGA)
+        name = "";
+#else
+	name = "./";
+#endif
+      else
+#ifdef VMS
+/* VMS filenames can have a ':' in them but they have to be '\'ed but we need
+ *  to remove this '\' before we can use the filename.
+ * Savestring called because q may be read-only string constant.
+ */
+	{
+	  char *qbase = xstrdup (q);
+	  char *pbase = qbase + (p-q);
+	  char *q1 = qbase;
+	  char *q2 = q1;
+	  char *p1 = pbase;
+
+	  while (q1 != pbase)
+	    {
+	      if (*q1 == '\\' && *(q1+1) == ':')
+		{
+		  q1++;
+		  p1--;
+		}
+	      *q2++ = *q1++;
+	    }
+	  name = strcache_add_len (qbase, p1 - qbase);
+	  free (qbase);
+	}
+#else
+	name = strcache_add_len (q, p - q);
+#endif
+
+      /* Add it to the front of the chain.  */
+      new1 = xmalloc (size);
+      new1->name = name;
+      new1->next = new;
+      new = new1;
+    }
+
+#ifndef NO_ARCHIVES
+
+  /* Look for multi-word archive references.
+     They are indicated by a elt ending with an unmatched `)' and
+     an elt further down the chain (i.e., previous in the file list)
+     with an unmatched `(' (e.g., "lib(mem").  */
+
+  new1 = new;
+  lastnew1 = 0;
+  while (new1 != 0)
+    if (new1->name[0] != '('	/* Don't catch "(%)" and suchlike.  */
+	&& new1->name[strlen (new1->name) - 1] == ')'
+	&& strchr (new1->name, '(') == 0)
+      {
+	/* NEW1 ends with a `)' but does not contain a `('.
+	   Look back for an elt with an opening `(' but no closing `)'.  */
+
+	struct nameseq *n = new1->next, *lastn = new1;
+	char *paren = 0;
+	while (n != 0 && (paren = strchr (n->name, '(')) == 0)
+	  {
+	    lastn = n;
+	    n = n->next;
+	  }
+	if (n != 0
+	    /* Ignore something starting with `(', as that cannot actually
+	       be an archive-member reference (and treating it as such
+	       results in an empty file name, which causes much lossage).  */
+	    && n->name[0] != '(')
+	  {
+	    /* N is the first element in the archive group.
+	       Its name looks like "lib(mem" (with no closing `)').  */
+
+	    char *libname;
+
+	    /* Copy "lib(" into LIBNAME.  */
+	    ++paren;
+	    libname = alloca (paren - n->name + 1);
+	    memcpy (libname, n->name, paren - n->name);
+	    libname[paren - n->name] = '\0';
+
+	    if (*paren == '\0')
+	      {
+		/* N was just "lib(", part of something like "lib( a b)".
+		   Edit it out of the chain and free its storage.  */
+		lastn->next = n->next;
+		free (n);
+		/* LASTN->next is the new stopping elt for the loop below.  */
+		n = lastn->next;
+	      }
+	    else
+	      {
+		/* Replace N's name with the full archive reference.  */
+		n->name = strcache_add (concat (libname, paren, ")"));
+	      }
+
+	    if (new1->name[1] == '\0')
+	      {
+		/* NEW1 is just ")", part of something like "lib(a b )".
+		   Omit it from the chain and free its storage.  */
+		if (lastnew1 == 0)
+		  new = new1->next;
+		else
+		  lastnew1->next = new1->next;
+		lastn = new1;
+		new1 = new1->next;
+		free (lastn);
+	      }
+	    else
+	      {
+		/* Replace also NEW1->name, which already has closing `)'.  */
+		new1->name = strcache_add (concat (libname, new1->name, ""));
+		new1 = new1->next;
+	      }
+
+	    /* Trace back from NEW1 (the end of the list) until N
+	       (the beginning of the list), rewriting each name
+	       with the full archive reference.  */
+
+	    while (new1 != n)
+	      {
+		new1->name = strcache_add (concat (libname, new1->name, ")"));
+		lastnew1 = new1;
+		new1 = new1->next;
+	      }
+	  }
+	else
+	  {
+	    /* No frobnication happening.  Just step down the list.  */
+	    lastnew1 = new1;
+	    new1 = new1->next;
+	  }
+      }
+    else
+      {
+	lastnew1 = new1;
+	new1 = new1->next;
+      }
+
+#endif
+
+  *stringp = p;
+  return new;
+}
+
+
+/* Find the next line of text in an eval buffer, combining continuation lines
+   into one line.
+   Return the number of actual lines read (> 1 if continuation lines).
+   Returns -1 if there's nothing left in the buffer.
+
+   After this function, ebuf->buffer points to the first character of the
+   line we just found.
+ */
+
+/* Read a line of text from a STRING.
+   Since we aren't really reading from a file, don't bother with linenumbers.
+ */
+
+static unsigned long
+readstring (struct ebuffer *ebuf)
+{
+  char *eol;
+
+  /* If there is nothing left in this buffer, return 0.  */
+  if (ebuf->bufnext >= ebuf->bufstart + ebuf->size)
+    return -1;
+
+  /* Set up a new starting point for the buffer, and find the end of the
+     next logical line (taking into account backslash/newline pairs).  */
+
+  eol = ebuf->buffer = ebuf->bufnext;
+
+  while (1)
+    {
+      int backslash = 0;
+      char *bol = eol;
+      char *p;
+
+      /* Find the next newline.  At EOS, stop.  */
+      eol = p = strchr (eol , '\n');
+      if (!eol)
+        {
+          ebuf->bufnext = ebuf->bufstart + ebuf->size + 1;
+          return 0;
+        }
+
+      /* Found a newline; if it's escaped continue; else we're done.  */
+      while (p > bol && *(--p) == '\\')
+        backslash = !backslash;
+      if (!backslash)
+        break;
+      ++eol;
+    }
+
+  /* Overwrite the newline char.  */
+  *eol = '\0';
+  ebuf->bufnext = eol+1;
+
+  return 0;
+}
+
+static long
+readline (struct ebuffer *ebuf)
+{
+  char *p;
+  char *end;
+  char *start;
+  long nlines = 0;
+
+  /* The behaviors between string and stream buffers are different enough to
+     warrant different functions.  Do the Right Thing.  */
+
+  if (!ebuf->fp)
+    return readstring (ebuf);
+
+  /* When reading from a file, we always start over at the beginning of the
+     buffer for each new line.  */
+
+  p = start = ebuf->bufstart;
+  end = p + ebuf->size;
+  *p = '\0';
+
+  while (fgets (p, end - p, ebuf->fp) != 0)
+    {
+      char *p2;
+      unsigned long len;
+      int backslash;
+
+      len = strlen (p);
+      if (len == 0)
+	{
+	  /* This only happens when the first thing on the line is a '\0'.
+	     It is a pretty hopeless case, but (wonder of wonders) Athena
+	     lossage strikes again!  (xmkmf puts NULs in its makefiles.)
+	     There is nothing really to be done; we synthesize a newline so
+	     the following line doesn't appear to be part of this line.  */
+	  error (&ebuf->floc,
+                 _("warning: NUL character seen; rest of line ignored"));
+	  p[0] = '\n';
+	  len = 1;
+	}
+
+      /* Jump past the text we just read.  */
+      p += len;
+
+      /* If the last char isn't a newline, the whole line didn't fit into the
+         buffer.  Get some more buffer and try again.  */
+      if (p[-1] != '\n')
+        goto more_buffer;
+
+      /* We got a newline, so add one to the count of lines.  */
+      ++nlines;
+
+#if !defined(WINDOWS32) && !defined(__MSDOS__) && !defined(__EMX__)
+      /* Check to see if the line was really ended with CRLF; if so ignore
+         the CR.  */
+      if ((p - start) > 1 && p[-2] == '\r')
+        {
+          --p;
+          p[-1] = '\n';
+        }
+#endif
+
+      backslash = 0;
+      for (p2 = p - 2; p2 >= start; --p2)
+	{
+	  if (*p2 != '\\')
+	    break;
+          backslash = !backslash;
+	}
+
+      if (!backslash)
+	{
+	  p[-1] = '\0';
+	  break;
+	}
+
+      /* It was a backslash/newline combo.  If we have more space, read
+         another line.  */
+      if (end - p >= 80)
+        continue;
+
+      /* We need more space at the end of our buffer, so realloc it.
+         Make sure to preserve the current offset of p.  */
+    more_buffer:
+      {
+        unsigned long off = p - start;
+        ebuf->size *= 2;
+        start = ebuf->buffer = ebuf->bufstart = xrealloc (start, ebuf->size);
+        p = start + off;
+        end = start + ebuf->size;
+        *p = '\0';
+      }
+    }
+
+  if (ferror (ebuf->fp))
+    pfatal_with_name (ebuf->floc.filenm);
+
+  /* If we found some lines, return how many.
+     If we didn't, but we did find _something_, that indicates we read the last
+     line of a file with no final newline; return 1.
+     If we read nothing, we're at EOF; return -1.  */
+
+  return nlines ? nlines : p == ebuf->bufstart ? -1 : 1;
+}
+
+
+/* Parse the next "makefile word" from the input buffer, and return info
+   about it.
+
+   A "makefile word" is one of:
+
+     w_bogus        Should never happen
+     w_eol          End of input
+     w_static       A static word; cannot be expanded
+     w_variable     A word containing one or more variables/functions
+     w_colon        A colon
+     w_dcolon       A double-colon
+     w_semicolon    A semicolon
+     w_varassign    A variable assignment operator (=, :=, +=, >=, or ?=)
+
+   Note that this function is only used when reading certain parts of the
+   makefile.  Don't use it where special rules hold sway (RHS of a variable,
+   in a command list, etc.)  */
+
+static enum make_word_type
+get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length)
+{
+  enum make_word_type wtype = w_bogus;
+  char *p = buffer, *beg;
+  char c;
+
+  /* Skip any leading whitespace.  */
+  while (isblank ((unsigned char)*p))
+    ++p;
+
+  beg = p;
+  c = *(p++);
+  switch (c)
+    {
+    case '\0':
+      wtype = w_eol;
+      break;
+
+    case ';':
+      wtype = w_semicolon;
+      break;
+
+    case '=':
+      wtype = w_varassign;
+      break;
+
+    case ':':
+      wtype = w_colon;
+      switch (*p)
+        {
+        case ':':
+          ++p;
+          wtype = w_dcolon;
+          break;
+
+        case '=':
+          ++p;
+          wtype = w_varassign;
+          break;
+        }
+      break;
+
+    case '+':
+    case '?':
+#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+    case '>':
+#endif
+      if (*p == '=')
+        {
+          ++p;
+          wtype = w_varassign;
+          break;
+        }
+
+    default:
+      if (delim && strchr (delim, c))
+        wtype = w_static;
+      break;
+    }
+
+  /* Did we find something?  If so, return now.  */
+  if (wtype != w_bogus)
+    goto done;
+
+  /* This is some non-operator word.  A word consists of the longest
+     string of characters that doesn't contain whitespace, one of [:=#],
+     or [?+]=, or one of the chars in the DELIM string.  */
+
+  /* We start out assuming a static word; if we see a variable we'll
+     adjust our assumptions then.  */
+  wtype = w_static;
+
+  /* We already found the first value of "c", above.  */
+  while (1)
+    {
+      char closeparen;
+      int count;
+
+      switch (c)
+        {
+        case '\0':
+        case ' ':
+        case '\t':
+        case '=':
+          goto done_word;
+
+        case ':':
+#ifdef HAVE_DOS_PATHS
+	  /* A word CAN include a colon in its drive spec.  The drive
+	     spec is allowed either at the beginning of a word, or as part
+	     of the archive member name, like in "libfoo.a(d:/foo/bar.o)".  */
+	  if (!(p - beg >= 2
+		&& (*p == '/' || *p == '\\') && isalpha ((unsigned char)p[-2])
+		&& (p - beg == 2 || p[-3] == '(')))
+#endif
+	  goto done_word;
+
+        case '$':
+          c = *(p++);
+          if (c == '$')
+            break;
+
+          /* This is a variable reference, so note that it's expandable.
+             Then read it to the matching close paren.  */
+          wtype = w_variable;
+
+          if (c == '(')
+            closeparen = ')';
+          else if (c == '{')
+            closeparen = '}';
+          else
+            /* This is a single-letter variable reference.  */
+            break;
+
+          for (count=0; *p != '\0'; ++p)
+            {
+              if (*p == c)
+                ++count;
+              else if (*p == closeparen && --count < 0)
+                {
+                  ++p;
+                  break;
+                }
+            }
+          break;
+
+        case '?':
+        case '+':
+#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+        case '>':
+#endif
+          if (*p == '=')
+            goto done_word;
+          break;
+
+        case '\\':
+          switch (*p)
+            {
+            case ':':
+            case ';':
+            case '=':
+            case '\\':
+              ++p;
+              break;
+            }
+          break;
+
+        default:
+          if (delim && strchr (delim, c))
+            goto done_word;
+          break;
+        }
+
+      c = *(p++);
+    }
+ done_word:
+  --p;
+
+ done:
+  if (startp)
+    *startp = beg;
+  if (length)
+    *length = p - beg;
+  return wtype;
+}
+
+
+/* Construct the list of include directories
+   from the arguments and the default list.  */
+
+void
+construct_include_path (const char **arg_dirs)
+{
+#ifdef VAXC		/* just don't ask ... */
+  stat_t stbuf;
+#else
+  struct stat stbuf;
+#endif
+  const char **dirs;
+  const char **cpp;
+  unsigned int idx;
+
+  /* Compute the number of pointers we need in the table.  */
+  idx = sizeof (default_include_directories) / sizeof (const char *);
+  if (arg_dirs)
+    for (cpp = arg_dirs; *cpp != 0; ++cpp)
+      ++idx;
+
+#ifdef  __MSDOS__
+  /* Add one for $DJDIR.  */
+  ++idx;
+#endif
+#ifdef KMK
+  /* Add one for the kBuild directory. */
+  ++idx;
+#endif
+
+  dirs = xmalloc (idx * sizeof (const char *));
+
+  idx = 0;
+  max_incl_len = 0;
+
+  /* First consider any dirs specified with -I switches.
+     Ignore any that don't exist.  Remember the maximum string length.  */
+
+  if (arg_dirs)
+    while (*arg_dirs != 0)
+      {
+	const char *dir = *(arg_dirs++);
+        char *expanded = 0;
+        int e;
+
+	if (dir[0] == '~')
+	  {
+	    expanded = tilde_expand (dir);
+	    if (expanded != 0)
+	      dir = expanded;
+	  }
+
+        EINTRLOOP (e, stat (dir, &stbuf));
+	if (e == 0 && S_ISDIR (stbuf.st_mode))
+          {
+            unsigned int len = strlen (dir);
+            /* If dir name is written with trailing slashes, discard them.  */
+            while (len > 1 && dir[len - 1] == '/')
+              --len;
+            if (len > max_incl_len)
+              max_incl_len = len;
+            dirs[idx++] = strcache_add_len (dir, len);
+          }
+
+	if (expanded)
+	  free (expanded);
+      }
+
+  /* Now add the standard default dirs at the end.  */
+
+#ifdef  __MSDOS__
+  {
+    /* The environment variable $DJDIR holds the root of the DJGPP directory
+       tree; add ${DJDIR}/include.  */
+    struct variable *djdir = lookup_variable ("DJDIR", 5);
+
+    if (djdir)
+      {
+        unsigned int len = strlen (djdir->value) + 8;
+	char *defdir = alloca (len + 1);
+
+	strcat (strcpy (defdir, djdir->value), "/include");
+	dirs[idx++] = strcache_add (defdir);
+
+        if (len > max_incl_len)
+          max_incl_len = len;
+      }
+  }
+#endif
+#ifdef KMK
+  /* Add $(KBUILD_PATH). */
+  {
+    size_t len = strlen (get_kbuild_path ());
+    dirs[idx++] = strcache_add_len (get_kbuild_path (), len);
+    if (len > max_incl_len)
+      max_incl_len = len;
+  }
+#endif
+
+  for (cpp = default_include_directories; *cpp != 0; ++cpp)
+    {
+      int e;
+
+      EINTRLOOP (e, stat (*cpp, &stbuf));
+      if (e == 0 && S_ISDIR (stbuf.st_mode))
+        {
+          unsigned int len = strlen (*cpp);
+          /* If dir name is written with trailing slashes, discard them.  */
+          while (len > 1 && (*cpp)[len - 1] == '/')
+            --len;
+          if (len > max_incl_len)
+            max_incl_len = len;
+          dirs[idx++] = strcache_add_len (*cpp, len - 1);
+        }
+    }
+
+  dirs[idx] = 0;
+
+  /* Now add each dir to the .INCLUDE_DIRS variable.  */
+
+  for (cpp = dirs; *cpp != 0; ++cpp)
+    do_variable_definition (NILF, ".INCLUDE_DIRS", *cpp,
+                            o_default, f_append, 0);
+
+  include_directories = dirs;
+}
+
+
+/* Expand ~ or ~USER at the beginning of NAME.
+   Return a newly malloc'd string or 0.  */
+
+char *
+tilde_expand (const char *name)
+{
+#ifndef VMS
+  if (name[1] == '/' || name[1] == '\0')
+    {
+      extern char *getenv ();
+      char *home_dir;
+      int is_variable;
+
+      {
+	/* Turn off --warn-undefined-variables while we expand HOME.  */
+	int save = warn_undefined_variables_flag;
+	warn_undefined_variables_flag = 0;
+
+	home_dir = allocated_variable_expand ("$(HOME)");
+
+	warn_undefined_variables_flag = save;
+      }
+
+      is_variable = home_dir[0] != '\0';
+      if (!is_variable)
+	{
+	  free (home_dir);
+	  home_dir = getenv ("HOME");
+	}
+# if !defined(_AMIGA) && !defined(WINDOWS32)
+      if (home_dir == 0 || home_dir[0] == '\0')
+	{
+	  extern char *getlogin ();
+	  char *logname = getlogin ();
+	  home_dir = 0;
+	  if (logname != 0)
+	    {
+	      struct passwd *p = getpwnam (logname);
+	      if (p != 0)
+		home_dir = p->pw_dir;
+	    }
+	}
+# endif /* !AMIGA && !WINDOWS32 */
+      if (home_dir != 0)
+	{
+	  char *new = xstrdup (concat (home_dir, "", name + 1));
+	  if (is_variable)
+	    free (home_dir);
+	  return new;
+	}
+    }
+# if !defined(_AMIGA) && !defined(WINDOWS32)
+  else
+    {
+      struct passwd *pwent;
+      char *userend = strchr (name + 1, '/');
+      if (userend != 0)
+	*userend = '\0';
+      pwent = getpwnam (name + 1);
+      if (pwent != 0)
+	{
+	  if (userend == 0)
+	    return xstrdup (pwent->pw_dir);
+	  else
+	    return xstrdup (concat (pwent->pw_dir, "/", userend + 1));
+	}
+      else if (userend != 0)
+	*userend = '/';
+    }
+# endif /* !AMIGA && !WINDOWS32 */
+#endif /* !VMS */
+  return 0;
+}
+
+/* Given a chain of struct nameseq's describing a sequence of filenames,
+   in reverse of the intended order, return a new chain describing the
+   result of globbing the filenames.  The new chain is in forward order.
+   The links of the old chain are freed or used in the new chain.
+   Likewise for the names in the old chain.
+
+   SIZE is how big to construct chain elements.
+   This is useful if we want them actually to be other structures
+   that have room for additional info.  */
+
+struct nameseq *
+multi_glob (struct nameseq *chain, unsigned int size)
+{
+  void dir_setup_glob (glob_t *);
+  struct nameseq *new = 0;
+  struct nameseq *old;
+  struct nameseq *nexto;
+  glob_t gl;
+#if defined(KMK) || defined(__EMX__) /* speed optimization */
+  int rc;
+#endif
+
+  dir_setup_glob (&gl);
+
+  for (old = chain; old != 0; old = nexto)
+    {
+      const char *gname;
+#ifndef NO_ARCHIVES
+      char *arname = 0;
+      char *memname = 0;
+#endif
+      nexto = old->next;
+      gname = old->name;
+
+      if (gname[0] == '~')
+	{
+	  char *newname = tilde_expand (old->name);
+	  if (newname != 0)
+            gname = newname;
+	}
+
+#ifndef NO_ARCHIVES
+      if (ar_name (gname))
+	{
+	  /* OLD->name is an archive member reference.  Replace it with the
+	     archive file name, and save the member name in MEMNAME.  We will
+	     glob on the archive name and then reattach MEMNAME later.  */
+	  ar_parse_name (gname, &arname, &memname);
+	  gname = arname;
+	}
+#endif /* !NO_ARCHIVES */
+
+#if defined(KMK) || defined(__EMX__) /* speed optimization */
+      if (!strpbrk(gname, "*?["))
+        {
+          gl.gl_pathc = 1;
+          gl.gl_pathv = (char **)&gname;
+          rc = 0;
+        }
+      else
+        rc = glob (gname, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl);
+      switch (rc)
+#else
+      switch (glob (gname, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl))
+#endif
+	{
+	case 0:			/* Success.  */
+	  {
+	    int i = gl.gl_pathc;
+	    while (i-- > 0)
+	      {
+#ifndef NO_ARCHIVES
+		if (memname != 0)
+		  {
+		    /* Try to glob on MEMNAME within the archive.  */
+		    struct nameseq *found
+		      = ar_glob (gl.gl_pathv[i], memname, size);
+		    if (! found)
+		      {
+			/* No matches.  Use MEMNAME as-is.  */
+			unsigned int alen = strlen (gl.gl_pathv[i]);
+			unsigned int mlen = strlen (memname);
+                        char *name;
+			struct nameseq *elt = xmalloc (size);
+                        memset (elt, '\0', size);
+
+                        name = alloca (alen + 1 + mlen + 2);
+			memcpy (name, gl.gl_pathv[i], alen);
+			name[alen] = '(';
+			memcpy (name+alen+1, memname, mlen);
+			name[alen + 1 + mlen] = ')';
+			name[alen + 1 + mlen + 1] = '\0';
+                        elt->name = strcache_add (name);
+			elt->next = new;
+			new = elt;
+		      }
+		    else
+		      {
+			/* Find the end of the FOUND chain.  */
+			struct nameseq *f = found;
+			while (f->next != 0)
+			  f = f->next;
+
+			/* Attach the chain being built to the end of the FOUND
+			   chain, and make FOUND the new NEW chain.  */
+			f->next = new;
+			new = found;
+		      }
+		  }
+		else
+#endif /* !NO_ARCHIVES */
+		  {
+		    struct nameseq *elt = xmalloc (size);
+                    memset (elt, '\0', size);
+		    elt->name = strcache_add (gl.gl_pathv[i]);
+		    elt->next = new;
+		    new = elt;
+		  }
+	      }
+#if defined(KMK) || defined(__EMX__) /* speed optimization */
+            if (gl.gl_pathv != (char **)&gname)
+#endif
+	    globfree (&gl);
+	    free (old);
+	    break;
+	  }
+
+	case GLOB_NOSPACE:
+	  fatal (NILF, _("virtual memory exhausted"));
+	  break;
+
+	default:
+	  old->next = new;
+	  new = old;
+	  break;
+	}
+
+#ifndef NO_ARCHIVES
+      if (arname)
+        free (arname);
+#endif
+    }
+
+  return new;
+}
Index: /tags/kBuild-0.1.4/src/kmk/readme.vms
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/readme.vms	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/readme.vms	(revision 1780)
@@ -0,0 +1,315 @@
+This is the VMS version of GNU Make, updated by Hartmut Becker
+
+Changes are based on GNU make 3.80. Latest changes are for OpenVMS/I64
+and new VMS CRTLs.
+
+This version was tested on OpenVMS/I64 V8.2 (field test) with hp C
+X7.1-024 OpenVMS/Alpha V7.3-2 with Compaq C V6.5-001 and OpenVMS/VAX 7.1
+with Compaq C V6.2-003 There are still some warning and informational
+message issued by the compilers.
+
+Build instructions
+Make a 1st version
+       $ @makefile.com
+       $ rena make.exe 1st-make.exe
+Use the 1st version to generate a 2nd version
+       $ mc sys$disk:[]1st-make clean
+       $ mc sys$disk:[]1st-make
+Verify your 2nd version
+       $ rena make.exe 2nd-make.exe
+       $ mc sys$disk:[]2nd-make clean
+       $ mc sys$disk:[]2nd-make
+
+Changes:
+
+. In default.c define variable ARCH as IA64 for VMS on Itanium systems.
+
+. In makefile.vms avoid name collision for glob and globfree.
+
+In newer version of the VMS CRTL there are glob and globfree implemented.
+Compiling and linking may result in
+
+  %ILINK-W-MULDEFLNKG, symbol DECC$GLOBFREE has subsequent linkage definition
+       in module DECC$SHR file SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1
+  %ILINK-W-MULDEF, symbol DECC$GLOBFREE multiply defined
+       in module DECC$SHR file SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1
+
+linker messages (and similar for DECC$GLOB). The messages just say, that
+globfree is a known CRTL whose name was mapped by the compiler to
+DECC$GLOBFREE.  This is done in glob.c as well, so this name is defined
+twice. One possible solution is to use the VMS versions of glob and
+globfree. However, then the build environment needs to figure out if
+there is a new CRTL supporting these or not. This adds complexity. Even
+more, these functions return VMS file specifications, which is not
+expected by the other make sources. There is a switch at run time (a VMS
+logical DECC$GLOB_UNIX_STYLE), which can be set to get Unix style
+names. This may conflict with other software. The recommended solution
+for this is to set this switch just prior to calling main: in an
+initialization routine. This adds more complexity and more VMS specific
+code. It is easier to tell the compiler NOT to map the routine names
+with a simple change in makefile.vms.
+
+Some notes on case sensitive names in rules and on the disk. In the VMS
+template for CONFIG.H case sensitive rules can be enabled with defining
+WANT_CASE_SENSITIVE_TARGETS. For recent version of VMS there is a case
+sensitive file system: ODS5. To make use of that, additionally un-defining
+the HAVE_CASE_INSENSITIVE_FS is required. As these are C macros, different
+versions of make need to be built to have any case sensitivity for VMS
+working. Unfortunately, for ODS5 disks that's not all.
+
+- Usually DCL upcases command line tokens (except strings) and usually the
+  file system is case blind (similar to how Windows systems work)
+	$ set proc/parse=extended/case=sensitive
+  preserves lower and UPPER on the command line and (for this process and all
+  sub-processes) enables case sensitivity in the file system
+
+- Usually the CRTL tries to reverse what DCL did with command line tokens, it
+  lowercases all tokens (except strings)
+	$ define DECC$ARGV_PARSE_STYLE enable
+  passes (the now preserved) lower and UPPER from the command line to main()
+
+- Usually the CRTL upcases the arguments to open() and friends
+	$ define DECC$EFS_CASE_PRESERVE enable
+  preserves the names as is.
+
+It is important to know that not all VMS tools are ready for case sensitivity.
+With this setup some tools may not work as expected. The setup should not
+blindly be applied for all users in default login procedures.
+
+Example? The poor coding gives a compiler message, showing that there are
+different files:
+
+$ dir
+
+Directory ODS5DISK[HB]
+
+A.c;1               B.c;1               c.c;1               X.c;1
+x.c;1
+
+Total of 5 files.
+$ ods5make x.obj
+cc    /obj=x.obj x.c
+
+foo(){lowercase_x();}
+......^
+%CC-I-IMPLICITFUNC, In this statement, the identifier "lowercase_x" is implicitly declared as a function.
+at line number 1 in file ODS5DISK[HB]x.c;1
+$ mc SYS$SYSDEVICE:[HARTMUT.MAKE_3_80P]ods5make X.obj
+cc    /obj=X.obj X.c
+
+foo() {UPPERCASE_X();}
+.......^
+%CC-I-IMPLICITFUNC, In this statement, the identifier "UPPERCASE_X" is implicitly declared as a function.
+at line number 1 in file ODS5DISK[HB]X.c;1
+$ dir
+
+Directory ODS5DISK[HB]
+
+A.c;1               B.c;1               c.c;1               X.c;1
+x.c;1               X.obj;1             x.obj;1
+
+Total of 7 files.
+$
+
+
+This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com.
+
+It is based on the specific version 3.77k and on 3.78.1. 3.77k was done
+by Klaus Kämpf <kkaempf@rmi.de>, the code was based on the VMS port of
+GNU Make 3.60 by Mike Moretti.
+
+It was ported on OpenVMS/Alpha V7.1, DECC V5.7-006. It was re-build and
+tested on OpenVMS/Alpha V7.2, OpenVMS/VAX 7.1 and 5.5-2. Different
+versions of DECC were used. VAXC was tried: it fails; but it doesn't
+seem worth to get it working. There are still some PTRMISMATCH warnings
+during the compile. Although perl is working on VMS the test scripts
+don't work. The function $shell is still missing.
+
+There is a known bug in some of the VMS CRTLs. It is in the shipped
+versions of VMS V7.2 and V7.2-1 and in the currently (October 1999)
+available ECOs for VMS V7.1 and newer versions. It is fixed in versions
+shipped with newer VMS versions and all ECO kits after October 1999. It
+only shows up during the daylight saving time period (DST): stat()
+returns a modification time 1 hour ahead. This results in GNU make
+warning messages. For a just created source you will see:
+
+ $ gmake x.exe
+ gmake.exe;1: *** Warning: File `x.c' has modification time in the future (940582863 > 940579269)
+ cc    /obj=x.obj x.c
+ link  x.obj    /exe=x.exe
+ gmake.exe;1: *** Warning:  Clock skew detected.  Your build may be incomplete.
+
+
+New in 3.78.1:
+
+Fix a problem with automatically remaking makefiles. GNU make uses an
+execve to restart itself after a successful remake of the makefile. On
+UNIX systems execve replaces the running program with a new one and
+resets all signal handling to the default. On VMS execve creates a child
+process, signal and exit handlers of the parent are still active, and,
+unfortunately, corrupt the exit code from the child. Fix in job.c:
+ignore SIGCHLD.
+
+Added some switches to reflect latest features of DECC. Modifications in
+makefile.vms.
+
+Set some definitions to reflect latest features of DECC. Modifications in
+config.h-vms (which is copied to config.h).
+
+Added extern strcmpi declaration to avoid 'implicitly declared' messages.
+Modification in make.h.
+
+Default rule for C++, conditionals for gcc (GCC_IS_NATIVE) or DEC/Digital/
+Compaq c/c++ compilers. Modifications in default.c.
+
+Usage of opendir() and friends, suppress file version. Modifications in dir.c.
+
+Added VMS specific code to handle ctrl+c and ctrl+y to abort make.
+Modifications in job.c.
+
+Added support to have case sensitive targets and dependencies but to
+still use case blind file names. This is especially useful for Java
+makefiles on VMS:
+
+	.SUFFIXES :
+	.SUFFIXES :	.class .java
+	.java.class :
+		javac "$<
+	HelloWorld.class :      HelloWorld.java
+
+A new macro WANT_CASE_SENSITIVE_TARGETS in config.h-vms was introduced.
+It needs to be enabled to get this feature; default is disabled.  The
+macro HAVE_CASE_INSENSITIVE_FS must not be touched: it is still enabled.
+Modifications in file.c and config.h-vms.
+
+Bootstrap make to start building make is still makefile.com, but make
+needs to be re-made with a make to make a correct version: ignore all
+possible warnings, delete all objects, rename make.exe to a different
+name and run it.
+
+Made some minor modifications to the bootstrap build makefile.com.
+
+
+This is the VMS port of GNU Make.
+
+It is based on the VMS port of GNU Make 3.60 by Mike Moretti.
+
+This port was done by Klaus Kämpf <kkaempf@rmi.de>
+
+There is first-level support available from proGIS Software, Germany.
+Visit their web-site at http://www.progis.de to get information
+about other vms software and forthcoming updates to gnu make.
+
+New for 3.77:
+
+/bin/sh style I/O redirection is supported. You can now write lines like
+	mcr sys$disk:[]program.exe < input.txt > output.txt &> error.txt
+
+Makefile variables are looked up in the current environment. You can set
+symbols or logicals in DCL and evaluate them in the Makefile via
+$(<name-of-symbol-or-logical>).  Variables defined in the Makefile
+override VMS symbols/logicals !
+
+Functions for file names are working now. See the GNU Make manual for
+$(dir ...)  and $(wildcard ...).  Unix-style and VMS-style names are
+supported as arguments.
+
+The default rules are set up for GNU C. Building an executable from a
+single source file is as easy as 'make file.exe'.
+
+The variable $(ARCH) is predefined as ALPHA or VAX resp. Makefiles for
+different VMS systems can now be written by checking $(ARCH) as in
+  ifeq ($(ARCH),ALPHA)
+    $(ECHO) "On the Alpha"
+  else
+    $(ECHO) "On the VAX"
+  endif
+
+Command lines of excessive length are correctly broken and written to a
+batch file in sys$scratch for later execution. There's no limit to the
+lengths of commands (and no need for .opt files :-) any more.
+
+Empty commands are handled correctly and don't end in a new DCL process.
+
+
+New for 3.76:
+
+John W. Eaton has updated the VMS port to support libraries and VPATH.
+
+
+To build Make, simply type @makefile.  This should compile all the
+necessary files and link Make.  There is also a file called
+makefile.vms.  If you already have GNU Make built you can just use
+Make with this makefile to rebuild.
+
+Here are some notes about GNU Make for VMS:
+
+The cd command is supported if it's called as $(CD). This invokes
+the 'builtin_cd' command which changes the directory.
+Calling 'set def' doesn't do the trick, since a sub-shell is
+spawned for this command, the directory is changed *in this sub-shell*
+and the sub-shell ends.
+
+Libraries are not supported. They were in GNU Make 3.60 but somehow I
+didn't care porting the code. If there is enough interest, I'll do it at
+some later time.
+
+The variable $^ separates files with commas instead of spaces (It's the
+natural thing to do for VMS).
+
+See defaults.c for VMS default suffixes and my definitions for default
+rules and variables.
+
+The shell function is not implemented yet.
+
+Load average routines haven't been implemented for VMS yet.
+
+The default include directory for including other makefiles is
+SYS$SYSROOT:[SYSLIB] (I don't remember why I didn't just use
+SYS$LIBRARY: instead; maybe it wouldn't work that way).
+
+The default makefiles make looks for are: makefile.vms, gnumakefile,
+makefile., and gnumakefile. .
+
+The stat() function and handling of time stamps in VMS is broken, so I
+replaced it with a hack in vmsfunctions.c. I will provide a full rewrite
+somewhere in the future. Be warned, the time resolution inside make is
+less than what vms provides. This might be a problem on the faster Alphas.
+
+You can use a : in a filename only if you preceed it with a backslash ('\').
+E.g.- hobbes\:[bogas.files]
+
+Make ignores success, informational, or warning errors (-S-, -I-, or
+-W-).  But it will stop on -E- and -F- errors. (unless you do something
+to override this in your makefile, or whatever).
+
+Remote stuff isn't implemented yet.
+
+Multiple line DCL commands, such as "if" statements, must be put inside
+command files.  You can run a command file by using \@.
+
+
+VMS changes made for 3.74.3
+
+Lots of default settings are adapted for VMS. See default.c.
+
+Long command lines are now converted to command files.
+
+Comma (',') as a separator is now allowed. See makefile.vms for an example.
+
+-------------------------------------------------------------------------------
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/remake.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/remake.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/remake.c	(revision 1780)
@@ -0,0 +1,1751 @@
+/* Basic dependency engine for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "dep.h"
+#include "variable.h"
+#include "debug.h"
+
+#include <assert.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#include <sys/file.h>
+#endif
+
+#ifdef VMS
+#include <starlet.h>
+#endif
+#ifdef WINDOWS32
+#include <io.h>
+#endif
+
+extern int try_implicit_rule (struct file *file, unsigned int depth);
+
+
+/* The test for circular dependencies is based on the 'updating' bit in
+   `struct file'.  However, double colon targets have seperate `struct
+   file's; make sure we always use the base of the double colon chain. */
+
+#define start_updating(_f)  (((_f)->double_colon ? (_f)->double_colon : (_f))\
+                             ->updating = 1)
+#define finish_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\
+                             ->updating = 0)
+#define is_updating(_f)     (((_f)->double_colon ? (_f)->double_colon : (_f))\
+                             ->updating)
+
+
+/* Incremented when a command is started (under -n, when one would be).  */
+unsigned int commands_started = 0;
+
+/* Current value for pruning the scan of the goal chain (toggle 0/1).  */
+static unsigned int considered;
+
+static int update_file (struct file *file, unsigned int depth);
+static int update_file_1 (struct file *file, unsigned int depth);
+static int check_dep (struct file *file, unsigned int depth,
+                      FILE_TIMESTAMP this_mtime, int *must_make_ptr);
+static int touch_file (struct file *file);
+static void remake_file (struct file *file);
+static FILE_TIMESTAMP name_mtime (const char *name);
+static const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr);
+
+
+
+/* Remake all the goals in the `struct dep' chain GOALS.  Return -1 if nothing
+   was done, 0 if all goals were updated successfully, or 1 if a goal failed.
+
+   If rebuilding_makefiles is nonzero, these goals are makefiles, so -t, -q,
+   and -n should be disabled for them unless they were also command-line
+   targets, and we should only make one goal at a time and return as soon as
+   one goal whose `changed' member is nonzero is successfully made.  */
+
+int
+update_goal_chain (struct dep *goals)
+{
+  int t = touch_flag, q = question_flag, n = just_print_flag;
+  unsigned int j = job_slots;
+  int status = -1;
+
+#define	MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \
+		     : file_mtime (file))
+
+  /* Duplicate the chain so we can remove things from it.  */
+
+  goals = copy_dep_chain (goals);
+
+  {
+    /* Clear the `changed' flag of each goal in the chain.
+       We will use the flag below to notice when any commands
+       have actually been run for a target.  When no commands
+       have been run, we give an "up to date" diagnostic.  */
+
+    struct dep *g;
+    for (g = goals; g != 0; g = g->next)
+      g->changed = 0;
+  }
+
+  /* All files start with the considered bit 0, so the global value is 1.  */
+  considered = 1;
+
+  /* Update all the goals until they are all finished.  */
+
+  while (goals != 0)
+    {
+      register struct dep *g, *lastgoal;
+
+      /* Start jobs that are waiting for the load to go down.  */
+
+      start_waiting_jobs ();
+
+      /* Wait for a child to die.  */
+
+      reap_children (1, 0);
+
+      lastgoal = 0;
+      g = goals;
+      while (g != 0)
+	{
+	  /* Iterate over all double-colon entries for this file.  */
+	  struct file *file;
+	  int stop = 0, any_not_updated = 0;
+
+	  for (file = g->file->double_colon ? g->file->double_colon : g->file;
+	       file != NULL;
+	       file = file->prev)
+	    {
+	      unsigned int ocommands_started;
+	      int x;
+	      check_renamed (file);
+	      if (rebuilding_makefiles)
+		{
+		  if (file->cmd_target)
+		    {
+		      touch_flag = t;
+		      question_flag = q;
+		      just_print_flag = n;
+		    }
+		  else
+		    touch_flag = question_flag = just_print_flag = 0;
+		}
+
+	      /* Save the old value of `commands_started' so we can compare
+		 later.  It will be incremented when any commands are
+		 actually run.  */
+	      ocommands_started = commands_started;
+
+	      x = update_file (file, rebuilding_makefiles ? 1 : 0);
+	      check_renamed (file);
+
+	      /* Set the goal's `changed' flag if any commands were started
+		 by calling update_file above.  We check this flag below to
+		 decide when to give an "up to date" diagnostic.  */
+              if (commands_started > ocommands_started)
+                g->changed = 1;
+
+              /* If we updated a file and STATUS was not already 1, set it to
+                 1 if updating failed, or to 0 if updating succeeded.  Leave
+                 STATUS as it is if no updating was done.  */
+
+	      stop = 0;
+	      if ((x != 0 || file->updated) && status < 1)
+                {
+                  if (file->update_status != 0)
+                    {
+                      /* Updating failed, or -q triggered.  The STATUS value
+                         tells our caller which.  */
+                      status = file->update_status;
+                      /* If -q just triggered, stop immediately.  It doesn't
+                         matter how much more we run, since we already know
+                         the answer to return.  */
+                      stop = (question_flag && !keep_going_flag
+                              && !rebuilding_makefiles);
+                    }
+                  else
+                    {
+                      FILE_TIMESTAMP mtime = MTIME (file);
+                      check_renamed (file);
+
+                      if (file->updated && g->changed &&
+                           mtime != file->mtime_before_update)
+                        {
+                          /* Updating was done.  If this is a makefile and
+                             just_print_flag or question_flag is set (meaning
+                             -n or -q was given and this file was specified
+                             as a command-line target), don't change STATUS.
+                             If STATUS is changed, we will get re-exec'd, and
+                             enter an infinite loop.  */
+                          if (!rebuilding_makefiles
+                              || (!just_print_flag && !question_flag))
+                            status = 0;
+                          if (rebuilding_makefiles && file->dontcare)
+                            /* This is a default makefile; stop remaking.  */
+                            stop = 1;
+                        }
+                    }
+                }
+
+	      /* Keep track if any double-colon entry is not finished.
+                 When they are all finished, the goal is finished.  */
+	      any_not_updated |= !file->updated;
+
+	      if (stop)
+		break;
+	    }
+
+	  /* Reset FILE since it is null at the end of the loop.  */
+	  file = g->file;
+
+	  if (stop || !any_not_updated)
+	    {
+	      /* If we have found nothing whatever to do for the goal,
+		 print a message saying nothing needs doing.  */
+
+	      if (!rebuilding_makefiles
+		  /* If the update_status is zero, we updated successfully
+		     or not at all.  G->changed will have been set above if
+		     any commands were actually started for this goal.  */
+		  && file->update_status == 0 && !g->changed
+		  /* Never give a message under -s or -q.  */
+		  && !silent_flag && !question_flag)
+		message (1, ((file->phony || file->cmds == 0)
+			     ? _("Nothing to be done for `%s'.")
+			     : _("`%s' is up to date.")),
+			 file->name);
+
+	      /* This goal is finished.  Remove it from the chain.  */
+	      if (lastgoal == 0)
+		goals = g->next;
+	      else
+		lastgoal->next = g->next;
+
+	      /* Free the storage.  */
+	      free (g);
+
+	      g = lastgoal == 0 ? goals : lastgoal->next;
+
+	      if (stop)
+		break;
+	    }
+	  else
+	    {
+	      lastgoal = g;
+	      g = g->next;
+	    }
+	}
+
+      /* If we reached the end of the dependency graph toggle the considered
+         flag for the next pass.  */
+      if (g == 0)
+        considered = !considered;
+    }
+
+  if (rebuilding_makefiles)
+    {
+      touch_flag = t;
+      question_flag = q;
+      just_print_flag = n;
+      job_slots = j;
+    }
+
+  return status;
+}
+
+
+/* If FILE is not up to date, execute the commands for it.
+   Return 0 if successful, 1 if unsuccessful;
+   but with some flag settings, just call `exit' if unsuccessful.
+
+   DEPTH is the depth in recursions of this function.
+   We increment it during the consideration of our dependencies,
+   then decrement it again after finding out whether this file
+   is out of date.
+
+   If there are multiple double-colon entries for FILE,
+   each is considered in turn.  */
+
+static int
+update_file (struct file *file, unsigned int depth)
+{
+  register int status = 0;
+  register struct file *f;
+
+  f = file->double_colon ? file->double_colon : file;
+
+  /* Prune the dependency graph: if we've already been here on _this_
+     pass through the dependency graph, we don't have to go any further.
+     We won't reap_children until we start the next pass, so no state
+     change is possible below here until then.  */
+  if (f->considered == considered)
+    {
+      DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
+      return f->command_state == cs_finished ? f->update_status : 0;
+    }
+
+  /* This loop runs until we start commands for a double colon rule, or until
+     the chain is exhausted. */
+  for (; f != 0; f = f->prev)
+    {
+      f->considered = considered;
+
+      status |= update_file_1 (f, depth);
+      check_renamed (f);
+
+      /* Clean up any alloca() used during the update.  */
+      alloca (0);
+
+      /* If we got an error, don't bother with double_colon etc.  */
+      if (status != 0 && !keep_going_flag)
+	return status;
+
+      if (f->command_state == cs_running
+          || f->command_state == cs_deps_running)
+        {
+	  /* Don't run the other :: rules for this
+	     file until this rule is finished.  */
+          status = 0;
+          break;
+        }
+    }
+
+  /* Process the remaining rules in the double colon chain so they're marked
+     considered.  Start their prerequisites, too.  */
+  if (file->double_colon)
+    for (; f != 0 ; f = f->prev)
+      {
+        struct dep *d;
+
+        f->considered = considered;
+
+        for (d = f->deps; d != 0; d = d->next)
+          status |= update_file (d->file, depth + 1);
+      }
+
+  return status;
+}
+
+
+/* Show a message stating the target failed to build.  */
+
+static void
+complain (const struct file *file)
+{
+  const char *msg_noparent
+    = _("%sNo rule to make target `%s'%s");
+  const char *msg_parent
+    = _("%sNo rule to make target `%s', needed by `%s'%s");
+
+  if (!keep_going_flag)
+    {
+      if (file->parent == 0)
+        fatal (NILF, msg_noparent, "", file->name, "");
+
+      fatal (NILF, msg_parent, "", file->name, file->parent->name, "");
+    }
+
+  if (file->parent == 0)
+    error (NILF, msg_noparent, "*** ", file->name, ".");
+  else
+    error (NILF, msg_parent, "*** ", file->name, file->parent->name, ".");
+}
+
+/* Consider a single `struct file' and update it as appropriate.  */
+
+static int
+update_file_1 (struct file *file, unsigned int depth)
+{
+  register FILE_TIMESTAMP this_mtime;
+  int noexist, must_make, deps_changed;
+  int dep_status = 0;
+  register struct dep *d, *lastd;
+  int running = 0;
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  struct file *f2, *f3;
+
+  /* Always work on the primary multi target file. */
+
+  if (file->multi_head != NULL && file->multi_head != file)
+    {
+      DBS (DB_VERBOSE, (_("Considering target file `%s' -> multi head `%s'.\n"), 
+                          file->name, file->multi_head->name));
+      file = file->multi_head;
+    }
+  else
+#endif /* CONFIG_WITH_EXPLICIT_MULTITARGET */
+    DBF (DB_VERBOSE, _("Considering target file `%s'.\n"));
+
+  if (file->updated)
+    {
+      if (file->update_status > 0)
+	{
+	  DBF (DB_VERBOSE,
+               _("Recently tried and failed to update file `%s'.\n"));
+
+          /* If the file we tried to make is marked dontcare then no message
+             was printed about it when it failed during the makefile rebuild.
+             If we're trying to build it again in the normal rebuild, print a
+             message now.  */
+          if (file->dontcare && !rebuilding_makefiles)
+            {
+              file->dontcare = 0;
+              complain (file);
+            }
+
+	  return file->update_status;
+	}
+
+      DBF (DB_VERBOSE, _("File `%s' was considered already.\n"));
+      return 0;
+    }
+
+  switch (file->command_state)
+    {
+    case cs_not_started:
+    case cs_deps_running:
+      break;
+    case cs_running:
+      DBF (DB_VERBOSE, _("Still updating file `%s'.\n"));
+      return 0;
+    case cs_finished:
+      DBF (DB_VERBOSE, _("Finished updating file `%s'.\n"));
+      return file->update_status;
+    default:
+      abort ();
+    }
+
+  ++depth;
+
+  /* Notice recursive update of the same file.  */
+  start_updating (file);
+
+  /* Looking at the file's modtime beforehand allows the possibility
+     that its name may be changed by a VPATH search, and thus it may
+     not need an implicit rule.  If this were not done, the file
+     might get implicit commands that apply to its initial name, only
+     to have that name replaced with another found by VPATH search.
+
+     For multi target files check the other files and use the time
+     of the oldest / non-existing file. */
+
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  this_mtime = file_mtime (file);
+  f3 = file;
+  for (f2 = file->multi_next;
+       f2 != NULL && this_mtime != NONEXISTENT_MTIME;
+       f2 = f2->multi_next)
+    if (!f2->multi_maybe)
+      {
+        FILE_TIMESTAMP second_mtime = file_mtime (f2);
+        if (second_mtime < this_mtime)
+          {
+            this_mtime = second_mtime;
+            f3 = f2;
+          }
+      }
+  check_renamed (file);
+  noexist = this_mtime == NONEXISTENT_MTIME;
+  if (noexist)
+    DBS (DB_BASIC, (_("File `%s' does not exist.\n"), f3->name));
+#else /* !CONFIG_WITH_EXPLICIT_MULTITARGET */
+  this_mtime = file_mtime (file);
+  check_renamed (file);
+  noexist = this_mtime == NONEXISTENT_MTIME;
+  if (noexist)
+    DBF (DB_BASIC, _("File `%s' does not exist.\n"));
+#endif /* !CONFIG_WITH_EXPLICIT_MULTITARGET */
+  else if (ORDINARY_MTIME_MIN <= this_mtime && this_mtime <= ORDINARY_MTIME_MAX
+	   && file->low_resolution_time)
+    {
+      /* Avoid spurious rebuilds due to low resolution time stamps.  */
+      int ns = FILE_TIMESTAMP_NS (this_mtime);
+      if (ns != 0)
+	error (NILF, _("*** Warning: .LOW_RESOLUTION_TIME file `%s' has a high resolution time stamp"),
+	       file->name);
+      this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns;
+    }
+
+  must_make = noexist;
+
+  /* If file was specified as a target with no commands,
+     come up with some default commands.  */
+
+  if (!file->phony && file->cmds == 0 && !file->tried_implicit)
+    {
+      if (try_implicit_rule (file, depth))
+	DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
+      else
+	DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
+      file->tried_implicit = 1;
+    }
+  if (file->cmds == 0 && !file->is_target
+      && default_file != 0 && default_file->cmds != 0)
+    {
+      DBF (DB_IMPLICIT, _("Using default commands for `%s'.\n"));
+      file->cmds = default_file->cmds;
+    }
+
+  /* Update all non-intermediate files we depend on, if necessary,
+     and see whether any of them is more recent than this file.  
+     For explicit multitarget rules we must iterate all the output
+     files to get the correct picture. */
+
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  for (f2 = file; f2; f2 = f2->multi_next)
+    {
+      lastd = 0;
+      d = f2->deps;
+#else
+      lastd = 0;
+      d = file->deps;
+#endif
+      while (d != 0)
+        {
+          FILE_TIMESTAMP mtime;
+          int maybe_make;
+          int dontcare = 0;
+    
+          check_renamed (d->file);
+    
+          mtime = file_mtime (d->file);
+          check_renamed (d->file);
+    
+          if (is_updating (d->file))
+            {
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+              /* silently ignore the order-only dep hack. */
+              if (f2->multi_maybe && d->file == file)
+                {
+                  lastd = d;
+                  d = d->next;
+                  continue;
+                }
+#endif
+
+              error (NILF, _("Circular %s <- %s dependency dropped."),
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+                     f2->name, d->file->name);
+#else
+                     file->name, d->file->name);
+#endif
+              /* We cannot free D here because our the caller will still have
+                 a reference to it when we were called recursively via
+                 check_dep below.  */
+              if (lastd == 0)
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+                f2->deps = d->next;
+#else
+                file->deps = d->next;
+#endif
+              else
+                lastd->next = d->next;
+              d = d->next;
+              continue;
+            }
+    
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+          d->file->parent = f2;
+#else
+          d->file->parent = file;
+#endif
+          maybe_make = must_make;
+    
+          /* Inherit dontcare flag from our parent. */
+          if (rebuilding_makefiles)
+            {
+              dontcare = d->file->dontcare;
+              d->file->dontcare = file->dontcare;
+            }
+    
+    
+          dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);
+    
+          /* Restore original dontcare flag. */
+          if (rebuilding_makefiles)
+            d->file->dontcare = dontcare;
+    
+          if (! d->ignore_mtime)
+            must_make = maybe_make;
+    
+          check_renamed (d->file);
+    
+          {
+            register struct file *f = d->file;
+            if (f->double_colon)
+              f = f->double_colon;
+            do
+              {
+                running |= (f->command_state == cs_running
+                            || f->command_state == cs_deps_running);
+                f = f->prev;
+              }
+            while (f != 0);
+          }
+    
+          if (dep_status != 0 && !keep_going_flag)
+            break;
+    
+          if (!running)
+            /* The prereq is considered changed if the timestamp has changed while
+               it was built, OR it doesn't exist.  */
+            d->changed = ((file_mtime (d->file) != mtime)
+                          || (mtime == NONEXISTENT_MTIME));
+    
+          lastd = d;
+          d = d->next;
+        }
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+      if (dep_status != 0 && !keep_going_flag)
+        break;
+    }
+#endif
+
+  /* Now we know whether this target needs updating.
+     If it does, update all the intermediate files we depend on.  */
+
+  if (must_make || always_make_flag)
+    {
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+      for (f2 = file; f2; f2 = f2->multi_next)
+        for (d = f2->deps; d != 0; d = d->next)
+#else
+        for (d = file->deps; d != 0; d = d->next)
+#endif
+          if (d->file->intermediate)
+            {
+              int dontcare = 0;
+   
+              FILE_TIMESTAMP mtime = file_mtime (d->file);
+              check_renamed (d->file);
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+              d->file->parent = f2;
+#else
+              d->file->parent = file;
+#endif
+   
+              /* Inherit dontcare flag from our parent. */
+              if (rebuilding_makefiles)
+                {
+                  dontcare = d->file->dontcare;
+                  d->file->dontcare = file->dontcare;
+                }
+   
+   
+              dep_status |= update_file (d->file, depth);
+   
+              /* Restore original dontcare flag. */
+              if (rebuilding_makefiles)
+                d->file->dontcare = dontcare;
+   
+              check_renamed (d->file);
+                  
+              {
+                register struct file *f = d->file;
+                if (f->double_colon)
+          	f = f->double_colon;
+                do
+          	{
+          	  running |= (f->command_state == cs_running
+          	              || f->command_state == cs_deps_running);
+          	  f = f->prev;
+          	}
+                while (f != 0);
+              }
+   
+              if (dep_status != 0 && !keep_going_flag)
+                break;
+   
+              if (!running)
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+                d->changed = ((f2->phony && f2->cmds != 0)
+#else
+                d->changed = ((file->phony && file->cmds != 0)
+#endif
+          	            || file_mtime (d->file) != mtime);
+            }
+    }
+
+  finish_updating (file);
+
+  DBF (DB_VERBOSE, _("Finished prerequisites of target file `%s'.\n"));
+
+  if (running)
+    {
+      set_command_state (file, cs_deps_running);
+      --depth;
+      DBF (DB_VERBOSE, _("The prerequisites of `%s' are being made.\n"));
+      return 0;
+    }
+
+  /* If any dependency failed, give up now.  */
+
+  if (dep_status != 0)
+    {
+      file->update_status = dep_status;
+      notice_finished_file (file);
+
+      --depth;
+
+      DBF (DB_VERBOSE, _("Giving up on target file `%s'.\n"));
+
+      if (depth == 0 && keep_going_flag
+	  && !just_print_flag && !question_flag)
+	error (NILF,
+               _("Target `%s' not remade because of errors."), file->name);
+
+      return dep_status;
+    }
+
+  if (file->command_state == cs_deps_running)
+    /* The commands for some deps were running on the last iteration, but
+       they have finished now.  Reset the command_state to not_started to
+       simplify later bookkeeping.  It is important that we do this only
+       when the prior state was cs_deps_running, because that prior state
+       was definitely propagated to FILE's also_make's by set_command_state
+       (called above), but in another state an also_make may have
+       independently changed to finished state, and we would confuse that
+       file's bookkeeping (updated, but not_started is bogus state).  */
+    set_command_state (file, cs_not_started);
+
+  /* Now record which prerequisites are more
+     recent than this file, so we can define $?.  */
+
+  deps_changed = 0;
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  for (f2 = file; f2; f2 = f2->multi_next)
+#endif
+    for (d = file->deps; d != 0; d = d->next)
+      {
+        FILE_TIMESTAMP d_mtime = file_mtime (d->file);
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+        if (d->file == file && f2->multi_maybe)
+          continue;
+#endif
+        check_renamed (d->file);
+  
+        if (! d->ignore_mtime)
+          {
+#if 1
+            /* %%% In version 4, remove this code completely to
+             implement not remaking deps if their deps are newer
+             than their parents.  */
+            if (d_mtime == NONEXISTENT_MTIME && !d->file->intermediate)
+              /* We must remake if this dep does not
+                 exist and is not intermediate.  */
+              must_make = 1;
+#endif
+  
+            /* Set DEPS_CHANGED if this dep actually changed.  */
+            deps_changed |= d->changed;
+          }
+  
+        /* Set D->changed if either this dep actually changed,
+           or its dependent, FILE, is older or does not exist.  */
+        d->changed |= noexist || d_mtime > this_mtime;
+  
+        if (!noexist && ISDB (DB_BASIC|DB_VERBOSE))
+          {
+            const char *fmt = 0;
+  
+            if (d->ignore_mtime)
+              {
+                if (ISDB (DB_VERBOSE))
+                  fmt = _("Prerequisite `%s' is order-only for target `%s'.\n");
+              }
+            else if (d_mtime == NONEXISTENT_MTIME)
+              {
+                if (ISDB (DB_BASIC))
+                  fmt = _("Prerequisite `%s' of target `%s' does not exist.\n");
+              }
+            else if (d->changed)
+              {
+                if (ISDB (DB_BASIC))
+                  fmt = _("Prerequisite `%s' is newer than target `%s'.\n");
+              }
+            else if (ISDB (DB_VERBOSE))
+              fmt = _("Prerequisite `%s' is older than target `%s'.\n");
+  
+            if (fmt)
+              {
+                print_spaces (depth);
+                printf (fmt, dep_name (d), file->name);
+                fflush (stdout);
+              }
+          }
+      }
+
+  /* Here depth returns to the value it had when we were called.  */
+  depth--;
+
+  if (file->double_colon && file->deps == 0)
+    {
+      must_make = 1;
+      DBF (DB_BASIC,
+           _("Target `%s' is double-colon and has no prerequisites.\n"));
+    }
+  else if (!noexist && file->is_target && !deps_changed && file->cmds == 0
+           && !always_make_flag)
+    {
+      must_make = 0;
+      DBF (DB_VERBOSE,
+           _("No commands for `%s' and no prerequisites actually changed.\n"));
+    }
+  else if (!must_make && file->cmds != 0 && always_make_flag)
+    {
+      must_make = 1;
+      DBF (DB_VERBOSE, _("Making `%s' due to always-make flag.\n"));
+    }
+
+  if (!must_make)
+    {
+      if (ISDB (DB_VERBOSE))
+        {
+          print_spaces (depth);
+          printf (_("No need to remake target `%s'"), file->name);
+          if (!streq (file->name, file->hname))
+              printf (_("; using VPATH name `%s'"), file->hname);
+          puts (".");
+          fflush (stdout);
+        }
+
+      notice_finished_file (file);
+
+      /* Since we don't need to remake the file, convert it to use the
+         VPATH filename if we found one.  hfile will be either the
+         local name if no VPATH or the VPATH name if one was found.  */
+
+      while (file)
+        {
+          file->name = file->hname;
+          file = file->prev;
+        }
+
+      return 0;
+    }
+
+  DBF (DB_BASIC, _("Must remake target `%s'.\n"));
+
+  /* It needs to be remade.  If it's VPATH and not reset via GPATH, toss the
+     VPATH.  */
+  if (!streq(file->name, file->hname))
+    {
+      DB (DB_BASIC, (_("  Ignoring VPATH name `%s'.\n"), file->hname));
+      file->ignore_vpath = 1;
+    }
+
+  /* Now, take appropriate actions to remake the file.  */
+  remake_file (file);
+
+  if (file->command_state != cs_finished)
+    {
+      DBF (DB_VERBOSE, _("Commands of `%s' are being run.\n"));
+      return 0;
+    }
+
+  switch (file->update_status)
+    {
+    case 2:
+      DBF (DB_BASIC, _("Failed to remake target file `%s'.\n"));
+      break;
+    case 0:
+      DBF (DB_BASIC, _("Successfully remade target file `%s'.\n"));
+      break;
+    case 1:
+      DBF (DB_BASIC, _("Target file `%s' needs remade under -q.\n"));
+      break;
+    default:
+      assert (file->update_status >= 0 && file->update_status <= 2);
+      break;
+    }
+
+  file->updated = 1;
+  return file->update_status;
+}
+
+
+/* Set FILE's `updated' flag and re-check its mtime and the mtime's of all
+   files listed in its `also_make' member.  Under -t, this function also
+   touches FILE.
+
+   On return, FILE->update_status will no longer be -1 if it was.  */
+
+void
+notice_finished_file (struct file *file)
+{
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  struct file *f2;
+#endif
+  struct dep *d;
+  int ran = file->command_state == cs_running;
+  int touched = 0;
+  DB (DB_JOBS, (_("notice_finished_file - entering: file=%p `%s' update_status=%d command_state=%d\n"), /* bird */
+                  file, file->name, file->update_status, file->command_state));
+  file->command_state = cs_finished;
+  file->updated = 1;
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  if (file->multi_head)
+    {
+      assert (file == file->multi_head);
+      for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next)
+        {
+          f2->command_state = cs_finished;
+          f2->updated = 1;
+        }
+    }
+#endif
+
+#ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL
+  /* update not_parallel if the file was flagged for that. */
+  if (   ran
+      && (file->command_flags & (COMMANDS_NOTPARALLEL | COMMANDS_NO_COMMANDS))
+         == COMMANDS_NOTPARALLEL)
+    {
+      DB (DB_KMK, (_("not_parallel %d -> %d (file=%p `%s') [notice_finished_file]\n"), not_parallel,
+                   not_parallel - 1, file, file->name));
+      assert(not_parallel >= 1);
+      --not_parallel;
+    }
+#endif
+
+  if (touch_flag
+      /* The update status will be:
+		-1	if this target was not remade;
+		0	if 0 or more commands (+ or ${MAKE}) were run and won;
+		1	if some commands were run and lost.
+	 We touch the target if it has commands which either were not run
+	 or won when they ran (i.e. status is 0).  */
+      && file->update_status == 0)
+    {
+      if (file->cmds != 0 && file->cmds->any_recurse)
+	{
+	  /* If all the command lines were recursive,
+	     we don't want to do the touching.  */
+	  unsigned int i;
+	  for (i = 0; i < file->cmds->ncommand_lines; ++i)
+	    if (!(file->cmds->lines_flags[i] & COMMANDS_RECURSE))
+	      goto have_nonrecursing;
+	}
+      else
+	{
+	have_nonrecursing:
+	  if (file->phony)
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+            {
+              file->update_status = 0;
+              if (file->multi_head)
+                for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next)
+                  f2->update_status = 0;
+            }
+#else
+	    file->update_status = 0;
+#endif
+          /* According to POSIX, -t doesn't affect targets with no cmds.  */
+	  else if (file->cmds != 0)
+            {
+              /* Should set file's modification date and do nothing else.  */
+              file->update_status = touch_file (file);
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+              if (file->multi_head)
+                for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next)
+                  {
+                    /* figure out this, touch if it exist ignore otherwise? */
+                  }
+#endif
+
+              /* Pretend we ran a real touch command, to suppress the
+                 "`foo' is up to date" message.  */
+              commands_started++;
+
+              /* Request for the timestamp to be updated (and distributed
+                 to the double-colon entries). Simply setting ran=1 would
+                 almost have done the trick, but messes up with the also_make
+                 updating logic below.  */
+              touched = 1;
+            }
+	}
+    }
+
+  if (file->mtime_before_update == UNKNOWN_MTIME)
+    file->mtime_before_update = file->last_mtime;
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  if (file->multi_head)
+    for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next)
+      if (f2->mtime_before_update == UNKNOWN_MTIME)
+        f2->mtime_before_update = f2->last_mtime;
+#endif
+
+  if ((ran && !file->phony) || touched)
+    {
+      int i = 0;
+
+      /* If -n, -t, or -q and all the commands are recursive, we ran them so
+         really check the target's mtime again.  Otherwise, assume the target
+         would have been updated. */
+
+      if (question_flag || just_print_flag || touch_flag)
+        {
+          for (i = file->cmds->ncommand_lines; i > 0; --i)
+            if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE))
+              break;
+        }
+
+      /* If there were no commands at all, it's always new. */
+
+      else if (file->is_target && file->cmds == 0)
+	i = 1;
+
+      file->last_mtime = i == 0 ? UNKNOWN_MTIME : NEW_MTIME;
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+      if (file->multi_head)
+        for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next)
+          file->last_mtime = i == 0 ? UNKNOWN_MTIME : NEW_MTIME; /*??*/
+#endif
+    }
+
+  if (file->double_colon)
+    {
+      /* If this is a double colon rule and it is the last one to be
+         updated, propagate the change of modification time to all the
+         double-colon entries for this file.
+
+         We do it on the last update because it is important to handle
+         individual entries as separate rules with separate timestamps
+         while they are treated as targets and then as one rule with the
+         unified timestamp when they are considered as a prerequisite
+         of some target.  */
+
+      struct file *f;
+      FILE_TIMESTAMP max_mtime = file->last_mtime;
+
+      /* Check that all rules were updated and at the same time find
+         the max timestamp.  We assume UNKNOWN_MTIME is newer then
+         any other value.  */
+      for (f = file->double_colon; f != 0 && f->updated; f = f->prev)
+        if (max_mtime != UNKNOWN_MTIME
+            && (f->last_mtime == UNKNOWN_MTIME || f->last_mtime > max_mtime))
+          max_mtime = f->last_mtime;
+
+      if (f == 0)
+        for (f = file->double_colon; f != 0; f = f->prev)
+          f->last_mtime = max_mtime;
+    }
+
+  if (ran && file->update_status != -1)
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+    {
+#endif
+      /* We actually tried to update FILE, which has
+         updated its also_make's as well (if it worked).
+         If it didn't work, it wouldn't work again for them.
+         So mark them as updated with the same status.  */
+      for (d = file->also_make; d != 0; d = d->next)
+        {
+          d->file->command_state = cs_finished;
+          d->file->updated = 1;
+          d->file->update_status = file->update_status;
+
+          if (ran && !d->file->phony)
+            /* Fetch the new modification time.
+               We do this instead of just invalidating the cached time
+               so that a vpath_search can happen.  Otherwise, it would
+               never be done because the target is already updated.  */
+            f_mtime (d->file, 0);
+        }
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+      /* Same as above but for explicit multi target rules. */
+      if (file->multi_head)
+        for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next)
+          {
+            f2->update_status = file->update_status;
+            if (!f2->phony)
+              f_mtime (f2, 0);
+          }
+    }
+#endif
+  else if (file->update_status == -1)
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+    {
+      /* Nothing was done for FILE, but it needed nothing done.
+         So mark it now as "succeeded".  */
+      file->update_status = 0;
+      if (file->multi_head)
+        for (f2 = file->multi_next; f2 != 0; f2 = f2->multi_next)
+          f2->update_status = 0;
+    }
+#else
+    /* Nothing was done for FILE, but it needed nothing done.
+       So mark it now as "succeeded".  */
+    file->update_status = 0;
+#endif
+}
+
+
+/* Check whether another file (whose mtime is THIS_MTIME) needs updating on
+   account of a dependency which is file FILE.  If it does, store 1 in
+   *MUST_MAKE_PTR.  In the process, update any non-intermediate files that
+   FILE depends on (including FILE itself).  Return nonzero if any updating
+   failed.  */
+
+static int
+check_dep (struct file *file, unsigned int depth,
+           FILE_TIMESTAMP this_mtime, int *must_make_ptr)
+{
+  struct dep *d;
+  int dep_status = 0;
+
+  ++depth;
+  start_updating (file);
+
+  if (file->phony || !file->intermediate)
+    {
+      /* If this is a non-intermediate file, update it and record whether it
+         is newer than THIS_MTIME.  */
+      FILE_TIMESTAMP mtime;
+      dep_status = update_file (file, depth);
+      check_renamed (file);
+      mtime = file_mtime (file);
+      check_renamed (file);
+      if (mtime == NONEXISTENT_MTIME || mtime > this_mtime)
+	*must_make_ptr = 1;
+    }
+  else
+    {
+      /* FILE is an intermediate file.  */
+      FILE_TIMESTAMP mtime;
+
+      if (!file->phony && file->cmds == 0 && !file->tried_implicit)
+	{
+	  if (try_implicit_rule (file, depth))
+	    DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
+	  else
+	    DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
+	  file->tried_implicit = 1;
+	}
+      if (file->cmds == 0 && !file->is_target
+	  && default_file != 0 && default_file->cmds != 0)
+	{
+	  DBF (DB_IMPLICIT, _("Using default commands for `%s'.\n"));
+	  file->cmds = default_file->cmds;
+	}
+
+      check_renamed (file);
+      mtime = file_mtime (file);
+      check_renamed (file);
+      if (mtime != NONEXISTENT_MTIME && mtime > this_mtime)
+        /* If the intermediate file actually exists and is newer, then we
+           should remake from it.  */
+	*must_make_ptr = 1;
+      else
+	{
+          /* Otherwise, update all non-intermediate files we depend on, if
+             necessary, and see whether any of them is more recent than the
+             file on whose behalf we are checking.  */
+	  struct dep *lastd;
+
+	  lastd = 0;
+	  d = file->deps;
+	  while (d != 0)
+	    {
+              int maybe_make;
+
+	      if (is_updating (d->file))
+		{
+		  error (NILF, _("Circular %s <- %s dependency dropped."),
+			 file->name, d->file->name);
+		  if (lastd == 0)
+		    {
+		      file->deps = d->next;
+                      free_dep (d);
+		      d = file->deps;
+		    }
+		  else
+		    {
+		      lastd->next = d->next;
+                      free_dep (d);
+		      d = lastd->next;
+		    }
+		  continue;
+		}
+
+	      d->file->parent = file;
+              maybe_make = *must_make_ptr;
+	      dep_status |= check_dep (d->file, depth, this_mtime,
+                                       &maybe_make);
+              if (! d->ignore_mtime)
+                *must_make_ptr = maybe_make;
+	      check_renamed (d->file);
+	      if (dep_status != 0 && !keep_going_flag)
+		break;
+
+	      if (d->file->command_state == cs_running
+		  || d->file->command_state == cs_deps_running)
+		/* Record that some of FILE's deps are still being made.
+		   This tells the upper levels to wait on processing it until
+		   the commands are finished.  */
+		set_command_state (file, cs_deps_running);
+
+	      lastd = d;
+	      d = d->next;
+	    }
+	}
+    }
+
+  finish_updating (file);
+  return dep_status;
+}
+
+
+/* Touch FILE.  Return zero if successful, one if not.  */
+
+#define TOUCH_ERROR(call) return (perror_with_name (call, file->name), 1)
+
+static int
+touch_file (struct file *file)
+{
+  if (!silent_flag)
+    message (0, "touch %s", file->name);
+
+#ifndef	NO_ARCHIVES
+  if (ar_name (file->name))
+    return ar_touch (file->name);
+  else
+#endif
+    {
+      int fd = open (file->name, O_RDWR | O_CREAT, 0666);
+
+      if (fd < 0)
+	TOUCH_ERROR ("touch: open: ");
+      else
+	{
+	  struct stat statbuf;
+	  char buf = 'x';
+          int e;
+
+          EINTRLOOP (e, fstat (fd, &statbuf));
+	  if (e < 0)
+	    TOUCH_ERROR ("touch: fstat: ");
+	  /* Rewrite character 0 same as it already is.  */
+	  if (read (fd, &buf, 1) < 0)
+	    TOUCH_ERROR ("touch: read: ");
+	  if (lseek (fd, 0L, 0) < 0L)
+	    TOUCH_ERROR ("touch: lseek: ");
+	  if (write (fd, &buf, 1) < 0)
+	    TOUCH_ERROR ("touch: write: ");
+	  /* If file length was 0, we just
+	     changed it, so change it back.  */
+	  if (statbuf.st_size == 0)
+	    {
+	      (void) close (fd);
+	      fd = open (file->name, O_RDWR | O_TRUNC, 0666);
+	      if (fd < 0)
+		TOUCH_ERROR ("touch: open: ");
+	    }
+	  (void) close (fd);
+	}
+    }
+
+  return 0;
+}
+
+
+/* Having checked and updated the dependencies of FILE,
+   do whatever is appropriate to remake FILE itself.
+   Return the status from executing FILE's commands.  */
+
+static void
+remake_file (struct file *file)
+{
+#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET
+  assert(file->multi_head == NULL || file->multi_head == file);
+#endif
+
+  if (file->cmds == 0)
+    {
+      if (file->phony)
+	/* Phony target.  Pretend it succeeded.  */
+	file->update_status = 0;
+      else if (file->is_target)
+	/* This is a nonexistent target file we cannot make.
+	   Pretend it was successfully remade.  */
+	file->update_status = 0;
+      else
+        {
+          /* This is a dependency file we cannot remake.  Fail.  */
+          if (!rebuilding_makefiles || !file->dontcare)
+            complain (file);
+          file->update_status = 2;
+        }
+    }
+  else
+    {
+      chop_commands (file->cmds);
+
+      /* The normal case: start some commands.  */
+      if (!touch_flag || file->cmds->any_recurse)
+	{
+	  execute_file_commands (file);
+	  return;
+	}
+
+      /* This tells notice_finished_file it is ok to touch the file.  */
+      file->update_status = 0;
+    }
+
+  /* This does the touching under -t.  */
+  notice_finished_file (file);
+}
+
+
+/* Return the mtime of a file, given a `struct file'.
+   Caches the time in the struct file to avoid excess stat calls.
+
+   If the file is not found, and SEARCH is nonzero, VPATH searching and
+   replacement is done.  If that fails, a library (-lLIBNAME) is tried and
+   the library's actual name (/lib/libLIBNAME.a, etc.) is substituted into
+   FILE.  */
+
+FILE_TIMESTAMP
+f_mtime (struct file *file, int search)
+{
+  FILE_TIMESTAMP mtime;
+
+  /* File's mtime is not known; must get it from the system.  */
+
+#ifndef	NO_ARCHIVES
+  if (ar_name (file->name))
+    {
+      /* This file is an archive-member reference.  */
+
+      char *arname, *memname;
+      struct file *arfile;
+      time_t member_date;
+
+      /* Find the archive's name.  */
+      ar_parse_name (file->name, &arname, &memname);
+
+      /* Find the modification time of the archive itself.
+	 Also allow for its name to be changed via VPATH search.  */
+      arfile = lookup_file (arname);
+      if (arfile == 0)
+        arfile = enter_file (strcache_add (arname));
+      mtime = f_mtime (arfile, search);
+      check_renamed (arfile);
+      if (search && strcmp (arfile->hname, arname))
+	{
+	  /* The archive's name has changed.
+	     Change the archive-member reference accordingly.  */
+
+          char *name;
+	  unsigned int arlen, memlen;
+
+	  arlen = strlen (arfile->hname);
+	  memlen = strlen (memname);
+
+	  name = xmalloc (arlen + 1 + memlen + 2);
+	  memcpy (name, arfile->hname, arlen);
+	  name[arlen] = '(';
+	  memcpy (name + arlen + 1, memname, memlen);
+	  name[arlen + 1 + memlen] = ')';
+	  name[arlen + 1 + memlen + 1] = '\0';
+
+          /* If the archive was found with GPATH, make the change permanent;
+             otherwise defer it until later.  */
+          if (arfile->name == arfile->hname)
+            rename_file (file, name);
+          else
+            rehash_file (file, name);
+          check_renamed (file);
+	}
+
+      free (arname);
+
+      file->low_resolution_time = 1;
+
+      if (mtime == NONEXISTENT_MTIME)
+	/* The archive doesn't exist, so its members don't exist either.  */
+	return NONEXISTENT_MTIME;
+
+      member_date = ar_member_date (file->hname);
+      mtime = (member_date == (time_t) -1
+               ? NONEXISTENT_MTIME
+               : file_timestamp_cons (file->hname, member_date, 0));
+    }
+  else
+#endif
+    {
+      mtime = name_mtime (file->name);
+
+      if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath)
+	{
+	  /* If name_mtime failed, search VPATH.  */
+	  const char *name = vpath_search (file->name, &mtime);
+	  if (name
+	      /* Last resort, is it a library (-lxxx)?  */
+	      || (file->name[0] == '-' && file->name[1] == 'l'
+		  && (name = library_search (file->name, &mtime)) != 0))
+	    {
+	      if (mtime != UNKNOWN_MTIME)
+		/* vpath_search and library_search store UNKNOWN_MTIME
+		   if they didn't need to do a stat call for their work.  */
+		file->last_mtime = mtime;
+
+              /* If we found it in VPATH, see if it's in GPATH too; if so,
+                 change the name right now; if not, defer until after the
+                 dependencies are updated. */
+              if (gpath_search (name, strlen(name) - strlen(file->name) - 1))
+                {
+                  rename_file (file, name);
+                  check_renamed (file);
+                  return file_mtime (file);
+                }
+
+	      rehash_file (file, name);
+	      check_renamed (file);
+              /* If the result of a vpath search is -o or -W, preserve it.
+                 Otherwise, find the mtime of the resulting file.  */
+              if (mtime != OLD_MTIME && mtime != NEW_MTIME)
+                mtime = name_mtime (name);
+	    }
+	}
+    }
+
+  /* Files can have bogus timestamps that nothing newly made will be
+     "newer" than.  Updating their dependents could just result in loops.
+     So notify the user of the anomaly with a warning.
+
+     We only need to do this once, for now. */
+
+  if (!clock_skew_detected
+      && mtime != NONEXISTENT_MTIME && mtime != NEW_MTIME
+      && !file->updated)
+    {
+      static FILE_TIMESTAMP adjusted_now;
+
+      FILE_TIMESTAMP adjusted_mtime = mtime;
+
+#if defined(WINDOWS32) || defined(__MSDOS__)
+      /* Experimentation has shown that FAT filesystems can set file times
+         up to 3 seconds into the future!  Play it safe.  */
+
+#define FAT_ADJ_OFFSET  (FILE_TIMESTAMP) 3
+
+      FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS;
+      if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime)
+        adjusted_mtime -= adjustment;
+#elif defined(__EMX__)
+      /* FAT filesystems round time to the nearest even second!
+         Allow for any file (NTFS or FAT) to perhaps suffer from this
+         brain damage.  */
+      FILE_TIMESTAMP adjustment = (((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0
+                     && FILE_TIMESTAMP_NS (adjusted_mtime) == 0)
+                    ? (FILE_TIMESTAMP) 1 << FILE_TIMESTAMP_LO_BITS
+                    : 0);
+#endif
+
+      /* If the file's time appears to be in the future, update our
+         concept of the present and try once more.  */
+      if (adjusted_now < adjusted_mtime)
+        {
+          int resolution;
+          FILE_TIMESTAMP now = file_timestamp_now (&resolution);
+          adjusted_now = now + (resolution - 1);
+          if (adjusted_now < adjusted_mtime)
+            {
+#ifdef NO_FLOAT
+              error (NILF, _("Warning: File `%s' has modification time in the future"),
+                     file->name);
+#else
+              double from_now =
+                (FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now)
+                 + ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now))
+                    / 1e9));
+              error (NILF, _("Warning: File `%s' has modification time %.2g s in the future"),
+                     file->name, from_now);
+#endif
+              clock_skew_detected = 1;
+            }
+        }
+    }
+
+  /* Store the mtime into all the entries for this file.  */
+  if (file->double_colon)
+    file = file->double_colon;
+
+  do
+    {
+      /* If this file is not implicit but it is intermediate then it was
+	 made so by the .INTERMEDIATE target.  If this file has never
+	 been built by us but was found now, it existed before make
+	 started.  So, turn off the intermediate bit so make doesn't
+	 delete it, since it didn't create it.  */
+      if (mtime != NONEXISTENT_MTIME && file->command_state == cs_not_started
+	  && file->command_state == cs_not_started
+	  && !file->tried_implicit && file->intermediate)
+	file->intermediate = 0;
+
+      file->last_mtime = mtime;
+      file = file->prev;
+    }
+  while (file != 0);
+
+  return mtime;
+}
+
+
+/* Return the mtime of the file or archive-member reference NAME.  */
+
+/* First, we check with stat().  If the file does not exist, then we return
+   NONEXISTENT_MTIME.  If it does, and the symlink check flag is set, then
+   examine each indirection of the symlink and find the newest mtime.
+   This causes one duplicate stat() when -L is being used, but the code is
+   much cleaner.  */
+
+static FILE_TIMESTAMP
+name_mtime (const char *name)
+{
+  FILE_TIMESTAMP mtime;
+  struct stat st;
+  int e;
+
+  EINTRLOOP (e, stat (name, &st));
+  if (e == 0)
+    mtime = FILE_TIMESTAMP_STAT_MODTIME (name, st);
+  else if (errno == ENOENT || errno == ENOTDIR)
+    mtime = NONEXISTENT_MTIME;
+  else
+    {
+      perror_with_name ("stat: ", name);
+      return NONEXISTENT_MTIME;
+    }
+
+  /* If we get here we either found it, or it doesn't exist.
+     If it doesn't exist see if we can use a symlink mtime instead.  */
+
+#ifdef MAKE_SYMLINKS
+#ifndef S_ISLNK
+# define S_ISLNK(_m)     (((_m)&S_IFMT)==S_IFLNK)
+#endif
+  if (check_symlink_flag)
+    {
+      PATH_VAR (lpath);
+
+      /* Check each symbolic link segment (if any).  Find the latest mtime
+         amongst all of them (and the target file of course).
+         Note that we have already successfully dereferenced all the links
+         above.  So, if we run into any error trying to lstat(), or
+         readlink(), or whatever, something bizarre-o happened.  Just give up
+         and use whatever mtime we've already computed at that point.  */
+      strcpy (lpath, name);
+      while (1)
+        {
+          FILE_TIMESTAMP ltime;
+          PATH_VAR (lbuf);
+          long llen;
+          char *p;
+
+          EINTRLOOP (e, lstat (lpath, &st));
+          if (e)
+            {
+              /* Just take what we have so far.  */
+              if (errno != ENOENT && errno != ENOTDIR)
+                perror_with_name ("lstat: ", lpath);
+              break;
+            }
+
+          /* If this is not a symlink, we're done (we started with the real
+             file's mtime so we don't need to test it again).  */
+          if (!S_ISLNK (st.st_mode))
+            break;
+
+          /* If this mtime is newer than what we had, keep the new one.  */
+          ltime = FILE_TIMESTAMP_STAT_MODTIME (lpath, st);
+          if (ltime > mtime)
+            mtime = ltime;
+
+          /* Set up to check the file pointed to by this link.  */
+          EINTRLOOP (llen, readlink (lpath, lbuf, GET_PATH_MAX));
+          if (llen < 0)
+            {
+              /* Eh?  Just take what we have.  */
+              perror_with_name ("readlink: ", lpath);
+              break;
+            }
+          lbuf[llen] = '\0';
+
+          /* If the target is fully-qualified or the source is just a
+             filename, then the new path is the target.  Otherwise it's the
+             source directory plus the target.  */
+          if (lbuf[0] == '/' || (p = strrchr (lpath, '/')) == NULL)
+            strcpy (lpath, lbuf);
+          else if ((p - lpath) + llen + 2 > GET_PATH_MAX)
+            /* Eh?  Path too long!  Again, just go with what we have.  */
+            break;
+          else
+            /* Create the next step in the symlink chain.  */
+            strcpy (p+1, lbuf);
+        }
+    }
+#endif
+
+  return mtime;
+}
+
+
+/* Search for a library file specified as -lLIBNAME, searching for a
+   suitable library file in the system library directories and the VPATH
+   directories.  */
+
+static const char *
+library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
+{
+  static char *dirs[] =
+    {
+#ifdef KMK
+      ".",
+#else /* !KMK */
+#ifndef _AMIGA
+      "/lib",
+      "/usr/lib",
+#endif
+#if defined(WINDOWS32) && !defined(LIBDIR)
+/*
+ * This is completely up to the user at product install time. Just define
+ * a placeholder.
+ */
+#define LIBDIR "."
+#endif
+# ifdef LIBDIR      /* bird */
+      LIBDIR,			/* Defined by configuration.  */
+# else              /* bird */
+      ".",          /* bird */
+# endif             /* bird */
+#endif /* !KMK */
+      0
+    };
+
+  static char *libpatterns = NULL;
+
+  const char *libname = lib+2;	/* Name without the '-l'.  */
+  FILE_TIMESTAMP mtime;
+
+  /* Loop variables for the libpatterns value.  */
+  char *p;
+  const char *p2;
+  unsigned int len;
+
+  char **dp;
+
+  /* If we don't have libpatterns, get it.  */
+  if (!libpatterns)
+    {
+      int save = warn_undefined_variables_flag;
+      warn_undefined_variables_flag = 0;
+
+      libpatterns = xstrdup (variable_expand ("$(strip $(.LIBPATTERNS))"));
+
+      warn_undefined_variables_flag = save;
+    }
+
+  /* Loop through all the patterns in .LIBPATTERNS, and search on each one.  */
+  p2 = libpatterns;
+  while ((p = find_next_token (&p2, &len)) != 0)
+    {
+      static char *buf = NULL;
+      static unsigned int buflen = 0;
+      static int libdir_maxlen = -1;
+      char *libbuf = variable_expand ("");
+      const size_t libbuf_offset = libbuf - variable_buffer; /* bird */
+
+      /* Expand the pattern using LIBNAME as a replacement.  */
+      {
+	char c = p[len];
+	char *p3, *p4;
+
+	p[len] = '\0';
+	p3 = find_percent (p);
+	if (!p3)
+	  {
+	    /* Give a warning if there is no pattern, then remove the
+	       pattern so it's ignored next time.  */
+	    error (NILF, _(".LIBPATTERNS element `%s' is not a pattern"), p);
+	    for (; len; --len, ++p)
+	      *p = ' ';
+	    *p = c;
+	    continue;
+	  }
+	p4 = variable_buffer_output (libbuf, p, p3-p);
+	p4 = variable_buffer_output (p4, libname, strlen (libname));
+	p4 = variable_buffer_output (p4, p3+1, len - (p3-p));
+	p[len] = c;
+	libbuf = variable_buffer + libbuf_offset; /* bird - variable_buffer may have been reallocated. */
+      }
+
+      /* Look first for `libNAME.a' in the current directory.  */
+      mtime = name_mtime (libbuf);
+      if (mtime != NONEXISTENT_MTIME)
+	{
+	  if (mtime_ptr != 0)
+	    *mtime_ptr = mtime;
+	  return strcache_add (libbuf);
+	}
+
+      /* Now try VPATH search on that.  */
+
+      {
+        const char *file = vpath_search (libbuf, mtime_ptr);
+        if (file)
+          return file;
+      }
+
+      /* Now try the standard set of directories.  */
+
+      if (!buflen)
+	{
+	  for (dp = dirs; *dp != 0; ++dp)
+	    {
+	      int l = strlen (*dp);
+	      if (l > libdir_maxlen)
+		libdir_maxlen = l;
+	    }
+	  buflen = strlen (libbuf);
+	  buf = xmalloc(libdir_maxlen + buflen + 2);
+	}
+      else if (buflen < strlen (libbuf))
+	{
+	  buflen = strlen (libbuf);
+	  buf = xrealloc (buf, libdir_maxlen + buflen + 2);
+	}
+
+      for (dp = dirs; *dp != 0; ++dp)
+	{
+	  sprintf (buf, "%s/%s", *dp, libbuf);
+	  mtime = name_mtime (buf);
+	  if (mtime != NONEXISTENT_MTIME)
+	    {
+	      if (mtime_ptr != 0)
+		*mtime_ptr = mtime;
+	      return strcache_add (buf);
+	    }
+	}
+    }
+
+  return 0;
+}
Index: /tags/kBuild-0.1.4/src/kmk/remote-cstms.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/remote-cstms.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/remote-cstms.c	(revision 1780)
@@ -0,0 +1,304 @@
+/* GNU Make remote job exportation interface to the Customs daemon.
+   THIS CODE IS NOT SUPPORTED BY THE GNU PROJECT.
+   Please do not send bug reports or questions about it to
+   the Make maintainers.
+
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "job.h"
+#include "filedef.h"
+#include "commands.h"
+#include "job.h"
+#include "debug.h"
+
+#include <sys/time.h>
+#include <netdb.h>
+
+#include "customs.h"
+
+char *remote_description = "Customs";
+
+/* File name of the Customs `export' client command.
+   A full path name can be used to avoid some path-searching overhead.  */
+#define	EXPORT_COMMAND	"/usr/local/bin/export"
+
+/* ExportPermit gotten by start_remote_job_p, and used by start_remote_job.  */
+static ExportPermit permit;
+
+/* Normalized path name of the current directory.  */
+static char *normalized_cwd;
+
+/* Call once at startup even if no commands are run.  */
+
+void
+remote_setup (void)
+{
+}
+
+/* Called before exit.  */
+
+void
+remote_cleanup (void)
+{
+}
+
+
+/* Return nonzero if the next job should be done remotely.  */
+
+int
+start_remote_job_p (int first_p)
+{
+  static int inited = 0;
+  int status;
+  int njobs;
+
+  if (!inited)
+    {
+      /* Allow the user to turn off job exportation (useful while he is
+         debugging Customs, for example).  */
+      if (getenv ("GNU_MAKE_NO_CUSTOMS") != 0)
+        {
+          inited = -1;
+          return 0;
+        }
+
+      /* For secure Customs, make is installed setuid root and
+	 Customs requires a privileged source port be used.  */
+      make_access ();
+
+      if (ISDB (DB_JOBS))
+        Rpc_Debug(1);
+
+      /* Ping the daemon once to see if it is there.  */
+      inited = Customs_Ping () == RPC_SUCCESS ? 1 : -1;
+
+      /* Return to normal user access.  */
+      user_access ();
+
+      if (starting_directory == 0)
+	/* main couldn't figure it out.  */
+	inited = -1;
+      else
+	{
+	  /* Normalize the current directory path name to something
+	     that should work on all machines exported to.  */
+
+	  normalized_cwd = xmalloc (GET_PATH_MAX);
+	  strcpy (normalized_cwd, starting_directory);
+	  if (Customs_NormPath (normalized_cwd, GET_PATH_MAX) < 0)
+	    /* Path normalization failure means using Customs
+	       won't work, but it's not really an error.  */
+	    inited = -1;
+	}
+    }
+
+  if (inited < 0)
+    return 0;
+
+  njobs = job_slots_used;
+  if (!first_p)
+    njobs -= 1;		/* correction for being called from reap_children() */
+
+  /* the first job should run locally, or, if the -l flag is given, we use
+     that as clue as to how many local jobs should be scheduled locally */
+  if (max_load_average < 0 && njobs == 0 || njobs < max_load_average)
+     return 0;
+
+  status = Customs_Host (EXPORT_SAME, &permit);
+  if (status != RPC_SUCCESS)
+    {
+      DB (DB_JOBS, (_("Customs won't export: %s\n"),
+                    Rpc_ErrorMessage (status)));
+      return 0;
+    }
+
+  return !CUSTOMS_FAIL (&permit.addr);
+}
+
+
+/* Start a remote job running the command in ARGV, with environment from
+   ENVP.  It gets standard input from STDIN_FD.  On failure, return
+   nonzero.  On success, return zero, and set *USED_STDIN to nonzero if it
+   will actually use STDIN_FD, zero if not, set *ID_PTR to a unique
+   identification, and set *IS_REMOTE to nonzero if the job is remote, zero
+   if it is local (meaning *ID_PTR is a process ID).  */
+
+int
+start_remote_job (char **argv, char **envp, int stdin_fd,
+                  int *is_remote, int *id_ptr, int *used_stdin)
+{
+  char waybill[MAX_DATA_SIZE], msg[128];
+  struct hostent *host;
+  struct timeval timeout;
+  struct sockaddr_in sin;
+  int len;
+  int retsock, retport, sock;
+  Rpc_Stat status;
+  int pid;
+
+  /* Create the return socket.  */
+  retsock = Rpc_UdpCreate (True, 0);
+  if (retsock < 0)
+    {
+      error (NILF, "exporting: Couldn't create return socket.");
+      return 1;
+    }
+
+  /* Get the return socket's port number.  */
+  len = sizeof (sin);
+  if (getsockname (retsock, (struct sockaddr *) &sin, &len) < 0)
+    {
+      (void) close (retsock);
+      perror_with_name ("exporting: ", "getsockname");
+      return 1;
+    }
+  retport = sin.sin_port;
+
+  /* Create the TCP socket for talking to the remote child.  */
+  sock = Rpc_TcpCreate (False, 0);
+
+  /* Create a WayBill to give to the server.  */
+  len = Customs_MakeWayBill (&permit, normalized_cwd, argv[0], argv,
+			     envp, retport, waybill);
+
+  /* Modify the waybill as if the remote child had done `child_access ()'.  */
+  {
+    WayBill *wb = (WayBill *) waybill;
+    wb->ruid = wb->euid;
+    wb->rgid = wb->egid;
+  }
+
+  /* Send the request to the server, timing out in 20 seconds.  */
+  timeout.tv_usec = 0;
+  timeout.tv_sec = 20;
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons (Customs_Port ());
+  sin.sin_addr = permit.addr;
+  status = Rpc_Call (sock, &sin, (Rpc_Proc) CUSTOMS_IMPORT,
+		     len, (Rpc_Opaque) waybill,
+		     sizeof(msg), (Rpc_Opaque) msg,
+		     1, &timeout);
+
+  host = gethostbyaddr((char *)&permit.addr, sizeof(permit.addr), AF_INET);
+
+  if (status != RPC_SUCCESS)
+    {
+      (void) close (retsock);
+      (void) close (sock);
+      error (NILF, "exporting to %s: %s",
+             host ? host->h_name : inet_ntoa (permit.addr),
+             Rpc_ErrorMessage (status));
+      return 1;
+    }
+  else if (msg[0] != 'O' || msg[1] != 'k' || msg[2] != '\0')
+    {
+      (void) close (retsock);
+      (void) close (sock);
+      error (NILF, "exporting to %s: %s",
+             host ? host->h_name : inet_ntoa (permit.addr),
+             msg);
+      return 1;
+    }
+  else
+    {
+      error (NILF, "*** exported to %s (id %u)",
+	      host ? host->h_name : inet_ntoa (permit.addr),
+	      permit.id);
+    }
+
+  fflush (stdout);
+  fflush (stderr);
+
+  pid = vfork ();
+  if (pid < 0)
+    {
+      /* The fork failed!  */
+      perror_with_name ("vfork", "");
+      return 1;
+    }
+  else if (pid == 0)
+    {
+      /* Child side.  Run `export' to handle the connection.  */
+      static char sock_buf[20], retsock_buf[20], id_buf[20];
+      static char *new_argv[6] =
+	{ EXPORT_COMMAND, "-id", sock_buf, retsock_buf, id_buf, 0 };
+
+      /* Set up the arguments.  */
+      (void) sprintf (sock_buf, "%d", sock);
+      (void) sprintf (retsock_buf, "%d", retsock);
+      (void) sprintf (id_buf, "%x", permit.id);
+
+      /* Get the right stdin.  */
+      if (stdin_fd != 0)
+	(void) dup2 (stdin_fd, 0);
+
+      /* Unblock signals in the child.  */
+      unblock_sigs ();
+
+      /* Run the command.  */
+      exec_command (new_argv, envp);
+    }
+
+  /* Parent side.  Return the `export' process's ID.  */
+  (void) close (retsock);
+  (void) close (sock);
+  *is_remote = 0;
+  *id_ptr = pid;
+  *used_stdin = 1;
+  return 0;
+}
+
+
+/* Get the status of a dead remote child.  Block waiting for one to die
+   if BLOCK is nonzero.  Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR
+   to the termination signal or zero if it exited normally, and *COREDUMP_PTR
+   nonzero if it dumped core.  Return the ID of the child that died,
+   0 if we would have to block and !BLOCK, or < 0 if there were none.  */
+
+int
+remote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr,
+               int block)
+{
+  return -1;
+}
+
+/* Block asynchronous notification of remote child death.
+   If this notification is done by raising the child termination
+   signal, do not block that signal.  */
+void
+block_remote_children (void)
+{
+  return;
+}
+
+/* Restore asynchronous notification of remote child death.
+   If this is done by raising the child termination signal,
+   do not unblock that signal.  */
+void
+unblock_remote_children (void)
+{
+  return;
+}
+
+/* Send signal SIG to child ID.  Return 0 if successful, -1 if not.  */
+int
+remote_kill (int id, int sig)
+{
+  return -1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/remote-stub.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/remote-stub.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/remote-stub.c	(revision 1780)
@@ -0,0 +1,104 @@
+/* Template for the remote job exportation interface to GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+
+
+char *remote_description = 0;
+
+/* Call once at startup even if no commands are run.  */
+
+void
+remote_setup (void)
+{
+}
+
+/* Called before exit.  */
+
+void
+remote_cleanup (void)
+{
+}
+
+
+/* Return nonzero if the next job should be done remotely.  */
+
+int
+start_remote_job_p (int first_p UNUSED)
+{
+  return 0;
+}
+
+
+/* Start a remote job running the command in ARGV,
+   with environment from ENVP.  It gets standard input from STDIN_FD.  On
+   failure, return nonzero.  On success, return zero, and set *USED_STDIN
+   to nonzero if it will actually use STDIN_FD, zero if not, set *ID_PTR to
+   a unique identification, and set *IS_REMOTE to zero if the job is local,
+   nonzero if it is remote (meaning *ID_PTR is a process ID).  */
+
+int
+start_remote_job (char **argv UNUSED, char **envp UNUSED, int stdin_fd UNUSED,
+                  int *is_remote UNUSED, int *id_ptr UNUSED,
+                  int *used_stdin UNUSED)
+{
+  return -1;
+}
+
+
+/* Get the status of a dead remote child.  Block waiting for one to die
+   if BLOCK is nonzero.  Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR
+   to the termination signal or zero if it exited normally, and *COREDUMP_PTR
+   nonzero if it dumped core.  Return the ID of the child that died,
+   0 if we would have to block and !BLOCK, or < 0 if there were none.  */
+
+int
+remote_status (int *exit_code_ptr UNUSED, int *signal_ptr UNUSED,
+               int *coredump_ptr UNUSED, int block UNUSED)
+{
+  errno = ECHILD;
+  return -1;
+}
+
+/* Block asynchronous notification of remote child death.
+   If this notification is done by raising the child termination
+   signal, do not block that signal.  */
+void
+block_remote_children (void)
+{
+  return;
+}
+
+/* Restore asynchronous notification of remote child death.
+   If this is done by raising the child termination signal,
+   do not unblock that signal.  */
+void
+unblock_remote_children (void)
+{
+  return;
+}
+
+/* Send signal SIG to child ID.  Return 0 if successful, -1 if not.  */
+int
+remote_kill (int id UNUSED, int sig UNUSED)
+{
+  return -1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/rule.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/rule.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/rule.c	(revision 1780)
@@ -0,0 +1,552 @@
+/* Pattern and suffix rule internals for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#include <assert.h>
+
+#include "dep.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "variable.h"
+#include "rule.h"
+
+static void freerule (struct rule *rule, struct rule *lastrule);
+
+
+/* Chain of all pattern rules.  */
+
+struct rule *pattern_rules;
+
+/* Pointer to last rule in the chain, so we can add onto the end.  */
+
+struct rule *last_pattern_rule;
+
+/* Number of rules in the chain.  */
+
+unsigned int num_pattern_rules;
+
+/* Maximum number of target patterns of any pattern rule.  */
+
+unsigned int max_pattern_targets;
+
+/* Maximum number of dependencies of any pattern rule.  */
+
+unsigned int max_pattern_deps;
+
+/* Maximum length of the name of a dependencies of any pattern rule.  */
+
+unsigned int max_pattern_dep_length;
+
+/* Pointer to structure for the file .SUFFIXES
+   whose dependencies are the suffixes to be searched.  */
+
+struct file *suffix_file;
+
+/* Maximum length of a suffix.  */
+
+unsigned int maxsuffix;
+
+
+/* Compute the maximum dependency length and maximum number of
+   dependencies of all implicit rules.  Also sets the subdir
+   flag for a rule when appropriate, possibly removing the rule
+   completely when appropriate.  */
+
+void
+count_implicit_rule_limits (void)
+{
+  char *name;
+  int namelen;
+  struct rule *rule, *lastrule;
+
+  num_pattern_rules = max_pattern_targets = max_pattern_deps = 0;
+  max_pattern_dep_length = 0;
+
+  name = 0;
+  namelen = 0;
+  rule = pattern_rules;
+  lastrule = 0;
+  while (rule != 0)
+    {
+      unsigned int ndeps = 0;
+      struct dep *dep;
+      struct rule *next = rule->next;
+
+      ++num_pattern_rules;
+
+      if (rule->num > max_pattern_targets)
+	max_pattern_targets = rule->num;
+
+      for (dep = rule->deps; dep != 0; dep = dep->next)
+	{
+	  unsigned int len = strlen (dep->name);
+
+#ifdef VMS
+	  const char *p = strrchr (dep->name, ']');
+          const char *p2;
+          if (p == 0)
+            p = strrchr (dep->name, ':');
+          p2 = p != 0 ? strchr (dep->name, '%') : 0;
+#else
+	  const char *p = strrchr (dep->name, '/');
+	  const char *p2 = p != 0 ? strchr (dep->name, '%') : 0;
+#endif
+	  ndeps++;
+
+	  if (len > max_pattern_dep_length)
+	    max_pattern_dep_length = len;
+
+	  if (p != 0 && p2 > p)
+	    {
+	      /* There is a slash before the % in the dep name.
+		 Extract the directory name.  */
+	      if (p == dep->name)
+		++p;
+	      if (p - dep->name > namelen)
+		{
+		  namelen = p - dep->name;
+		  name = xrealloc (name, namelen + 1);
+		}
+	      memcpy (name, dep->name, p - dep->name);
+	      name[p - dep->name] = '\0';
+
+	      /* In the deps of an implicit rule the `changed' flag
+		 actually indicates that the dependency is in a
+		 nonexistent subdirectory.  */
+
+	      dep->changed = !dir_file_exists_p (name, "");
+	    }
+	  else
+	    /* This dependency does not reside in a subdirectory.  */
+	    dep->changed = 0;
+	}
+
+      if (ndeps > max_pattern_deps)
+	max_pattern_deps = ndeps;
+
+      lastrule = rule;
+      rule = next;
+    }
+
+  if (name != 0)
+    free (name);
+}
+
+
+/* Create a pattern rule from a suffix rule.
+   TARGET is the target suffix; SOURCE is the source suffix.
+   CMDS are the commands.
+   If TARGET is nil, it means the target pattern should be `(%.o)'.
+   If SOURCE is nil, it means there should be no deps.  */
+
+static void
+convert_suffix_rule (const char *target, const char *source,
+                     struct commands *cmds)
+{
+  const char **names, **percents;
+  struct dep *deps;
+
+  names = xmalloc (sizeof (const char *));
+  percents = xmalloc (sizeof (const char *));
+
+  if (target == 0)
+    {
+      /* Special case: TARGET being nil means we are defining a `.X.a' suffix
+         rule; the target pattern is always `(%.o)'.  */
+#ifdef VMS
+      *names = strcache_add_len ("(%.obj)", 7);
+#else
+      *names = strcache_add_len ("(%.o)", 5);
+#endif
+      *percents = *names + 1;
+    }
+  else
+    {
+      /* Construct the target name.  */
+      unsigned int len = strlen (target);
+      char *p = alloca (1 + len + 1);
+      p[0] = '%';
+      memcpy (p + 1, target, len + 1);
+      *names = strcache_add_len (p, len + 1);
+      *percents = *names;
+    }
+
+  if (source == 0)
+    deps = 0;
+  else
+    {
+      /* Construct the dependency name.  */
+      unsigned int len = strlen (source);
+      char *p = alloca (1 + len + 1);
+      p[0] = '%';
+      memcpy (p + 1, source, len + 1);
+      deps = alloc_dep ();
+      deps->name = strcache_add_len (p, len + 1);
+    }
+
+  create_pattern_rule (names, percents, 1, 0, deps, cmds, 0);
+}
+
+/* Convert old-style suffix rules to pattern rules.
+   All rules for the suffixes on the .SUFFIXES list are converted and added to
+   the chain of pattern rules.  */
+
+void
+convert_to_pattern (void)
+{
+  struct dep *d, *d2;
+  char *rulename;
+
+  /* We will compute every potential suffix rule (.x.y) from the list of
+     suffixes in the .SUFFIXES target's dependencies and see if it exists.
+     First find the longest of the suffixes.  */
+
+  maxsuffix = 0;
+  for (d = suffix_file->deps; d != 0; d = d->next)
+    {
+      unsigned int l = strlen (dep_name (d));
+      if (l > maxsuffix)
+	maxsuffix = l;
+    }
+
+  /* Space to construct the suffix rule target name.  */
+  rulename = alloca ((maxsuffix * 2) + 1);
+
+  for (d = suffix_file->deps; d != 0; d = d->next)
+    {
+      unsigned int slen;
+
+      /* Make a rule that is just the suffix, with no deps or commands.
+	 This rule exists solely to disqualify match-anything rules.  */
+      convert_suffix_rule (dep_name (d), 0, 0);
+
+      if (d->file->cmds != 0)
+	/* Record a pattern for this suffix's null-suffix rule.  */
+	convert_suffix_rule ("", dep_name (d), d->file->cmds);
+
+      /* Add every other suffix to this one and see if it exists as a
+         two-suffix rule.  */
+      slen = strlen (dep_name (d));
+      memcpy (rulename, dep_name (d), slen);
+
+      for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)
+	{
+          struct file *f;
+          unsigned int s2len;
+
+	  s2len = strlen (dep_name (d2));
+
+          /* Can't build something from itself.  */
+	  if (slen == s2len && streq (dep_name (d), dep_name (d2)))
+	    continue;
+
+	  memcpy (rulename + slen, dep_name (d2), s2len + 1);
+	  f = lookup_file (rulename);
+	  if (f == 0 || f->cmds == 0)
+	    continue;
+
+	  if (s2len == 2 && rulename[slen] == '.' && rulename[slen + 1] == 'a')
+	    /* A suffix rule `.X.a:' generates the pattern rule `(%.o): %.X'.
+	       It also generates a normal `%.a: %.X' rule below.  */
+	    convert_suffix_rule (NULL, /* Indicates `(%.o)'.  */
+				 dep_name (d),
+				 f->cmds);
+
+	  /* The suffix rule `.X.Y:' is converted
+	     to the pattern rule `%.Y: %.X'.  */
+	  convert_suffix_rule (dep_name (d2), dep_name (d), f->cmds);
+	}
+    }
+}
+
+
+/* Install the pattern rule RULE (whose fields have been filled in) at the end
+   of the list (so that any rules previously defined will take precedence).
+   If this rule duplicates a previous one (identical target and dependencies),
+   the old one is replaced if OVERRIDE is nonzero, otherwise this new one is
+   thrown out.  When an old rule is replaced, the new one is put at the end of
+   the list.  Return nonzero if RULE is used; zero if not.  */
+
+static int
+new_pattern_rule (struct rule *rule, int override)
+{
+  struct rule *r, *lastrule;
+  unsigned int i, j;
+
+  rule->in_use = 0;
+  rule->terminal = 0;
+
+  rule->next = 0;
+
+  /* Search for an identical rule.  */
+  lastrule = 0;
+  for (r = pattern_rules; r != 0; lastrule = r, r = r->next)
+    for (i = 0; i < rule->num; ++i)
+      {
+	for (j = 0; j < r->num; ++j)
+	  if (!streq (rule->targets[i], r->targets[j]))
+	    break;
+        /* If all the targets matched...  */
+	if (j == r->num)
+	  {
+	    struct dep *d, *d2;
+	    for (d = rule->deps, d2 = r->deps;
+		 d != 0 && d2 != 0; d = d->next, d2 = d2->next)
+	      if (!streq (dep_name (d), dep_name (d2)))
+		break;
+	    if (d == 0 && d2 == 0)
+	      {
+		/* All the dependencies matched.  */
+		if (override)
+		  {
+		    /* Remove the old rule.  */
+		    freerule (r, lastrule);
+		    /* Install the new one.  */
+		    if (pattern_rules == 0)
+		      pattern_rules = rule;
+		    else
+		      last_pattern_rule->next = rule;
+		    last_pattern_rule = rule;
+
+		    /* We got one.  Stop looking.  */
+		    goto matched;
+		  }
+		else
+		  {
+		    /* The old rule stays intact.  Destroy the new one.  */
+		    freerule (rule, (struct rule *) 0);
+		    return 0;
+		  }
+	      }
+	  }
+      }
+
+ matched:;
+
+  if (r == 0)
+    {
+      /* There was no rule to replace.  */
+      if (pattern_rules == 0)
+	pattern_rules = rule;
+      else
+	last_pattern_rule->next = rule;
+      last_pattern_rule = rule;
+    }
+
+  return 1;
+}
+
+
+/* Install an implicit pattern rule based on the three text strings
+   in the structure P points to.  These strings come from one of
+   the arrays of default implicit pattern rules.
+   TERMINAL specifies what the `terminal' field of the rule should be.  */
+
+void
+install_pattern_rule (struct pspec *p, int terminal)
+{
+  struct rule *r;
+  char *ptr;
+
+  r = xmalloc (sizeof (struct rule));
+
+  r->num = 1;
+  r->targets = xmalloc (sizeof (const char *));
+  r->suffixes = xmalloc (sizeof (const char *));
+  r->lens = xmalloc (sizeof (unsigned int));
+
+  r->lens[0] = strlen (p->target);
+  r->targets[0] = p->target;
+  r->suffixes[0] = find_percent_cached (&r->targets[0]);
+  assert (r->suffixes[0] != NULL);
+  ++r->suffixes[0];
+
+  ptr = p->dep;
+  r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0',
+                                                       sizeof (struct dep), 1),
+				       sizeof (struct dep));
+
+  if (new_pattern_rule (r, 0))
+    {
+      r->terminal = terminal;
+      r->cmds = xmalloc (sizeof (struct commands));
+      r->cmds->fileinfo.filenm = 0;
+      r->cmds->fileinfo.lineno = 0;
+      /* These will all be string literals, but we malloc space for them
+	 anyway because somebody might want to free them later.  */
+      r->cmds->commands = xstrdup (p->commands);
+      r->cmds->command_lines = 0;
+    }
+}
+
+
+/* Free all the storage used in RULE and take it out of the
+   pattern_rules chain.  LASTRULE is the rule whose next pointer
+   points to RULE.  */
+
+static void
+freerule (struct rule *rule, struct rule *lastrule)
+{
+  struct rule *next = rule->next;
+  struct dep *dep;
+
+  dep = rule->deps;
+  while (dep)
+    {
+      struct dep *t = dep->next;
+      free_dep (dep);
+      dep = t;
+    }
+
+  free (rule->targets);
+  free (rule->suffixes);
+  free (rule->lens);
+
+  /* We can't free the storage for the commands because there
+     are ways that they could be in more than one place:
+       * If the commands came from a suffix rule, they could also be in
+       the `struct file's for other suffix rules or plain targets given
+       on the same makefile line.
+       * If two suffixes that together make a two-suffix rule were each
+       given twice in the .SUFFIXES list, and in the proper order, two
+       identical pattern rules would be created and the second one would
+       be discarded here, but both would contain the same `struct commands'
+       pointer from the `struct file' for the suffix rule.  */
+
+  free (rule);
+
+  if (pattern_rules == rule)
+    if (lastrule != 0)
+      abort ();
+    else
+      pattern_rules = next;
+  else if (lastrule != 0)
+    lastrule->next = next;
+  if (last_pattern_rule == rule)
+    last_pattern_rule = lastrule;
+}
+
+
+/* Create a new pattern rule with the targets in the nil-terminated array
+   TARGETS.  TARGET_PERCENTS is an array of pointers to the % in each element
+   of TARGETS.  N is the number of items in the array (not counting the nil
+   element).  The new rule has dependencies DEPS and commands from COMMANDS.
+   It is a terminal rule if TERMINAL is nonzero.  This rule overrides
+   identical rules with different commands if OVERRIDE is nonzero.
+
+   The storage for TARGETS and its elements and TARGET_PERCENTS is used and
+   must not be freed until the rule is destroyed.  */
+
+void
+create_pattern_rule (const char **targets, const char **target_percents,
+                     unsigned int n, int terminal, struct dep *deps,
+                     struct commands *commands, int override)
+{
+  unsigned int i;
+  struct rule *r = xmalloc (sizeof (struct rule));
+
+  r->num = n;
+  r->cmds = commands;
+  r->deps = deps;
+  r->targets = targets;
+  r->suffixes = target_percents;
+  r->lens = xmalloc (n * sizeof (unsigned int));
+
+  for (i = 0; i < n; ++i)
+    {
+      r->lens[i] = strlen (targets[i]);
+      assert (r->suffixes[i] != NULL);
+      ++r->suffixes[i];
+    }
+
+  if (new_pattern_rule (r, override))
+    r->terminal = terminal;
+}
+
+
+/* Print the data base of rules.  */
+
+static void			/* Useful to call from gdb.  */
+print_rule (struct rule *r)
+{
+  unsigned int i;
+  struct dep *d;
+
+  for (i = 0; i < r->num; ++i)
+    {
+      fputs (r->targets[i], stdout);
+      putchar ((i + 1 == r->num) ? ':' : ' ');
+    }
+  if (r->terminal)
+    putchar (':');
+
+  for (d = r->deps; d != 0; d = d->next)
+    printf (" %s", dep_name (d));
+  putchar ('\n');
+
+  if (r->cmds != 0)
+    print_commands (r->cmds);
+}
+
+void
+print_rule_data_base (void)
+{
+  unsigned int rules, terminal;
+  struct rule *r;
+
+  puts (_("\n# Implicit Rules"));
+
+  rules = terminal = 0;
+  for (r = pattern_rules; r != 0; r = r->next)
+    {
+      ++rules;
+
+      putchar ('\n');
+      print_rule (r);
+
+      if (r->terminal)
+	++terminal;
+    }
+
+  if (rules == 0)
+    puts (_("\n# No implicit rules."));
+  else
+    {
+      printf (_("\n# %u implicit rules, %u"), rules, terminal);
+#ifndef	NO_FLOAT
+      printf (" (%.1f%%)", (double) terminal / (double) rules * 100.0);
+#else
+      {
+	int f = (terminal * 1000 + 5) / rules;
+	printf (" (%d.%d%%)", f/10, f%10);
+      }
+#endif
+      puts (_(" terminal."));
+    }
+
+  if (num_pattern_rules != rules)
+    {
+      /* This can happen if a fatal error was detected while reading the
+         makefiles and thus count_implicit_rule_limits wasn't called yet.  */
+      if (num_pattern_rules != 0)
+        fatal (NILF, _("BUG: num_pattern_rules wrong!  %u != %u"),
+               num_pattern_rules, rules);
+    }
+}
Index: /tags/kBuild-0.1.4/src/kmk/rule.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/rule.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/rule.h	(revision 1780)
@@ -0,0 +1,59 @@
+/* Definitions for using pattern rules in GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+
+/* Structure used for pattern (implicit) rules.  */
+
+struct rule
+  {
+    struct rule *next;
+    const char **targets;	/* Targets of the rule.  */
+    unsigned int *lens;		/* Lengths of each target.  */
+    const char **suffixes;	/* Suffixes (after `%') of each target.  */
+    struct dep *deps;		/* Dependencies of the rule.  */
+    struct commands *cmds;	/* Commands to execute.  */
+    unsigned short num;         /* Number of targets.  */
+    char terminal;		/* If terminal (double-colon).  */
+    char in_use;		/* If in use by a parent pattern_search.  */
+  };
+
+/* For calling install_pattern_rule.  */
+struct pspec
+  {
+    char *target, *dep, *commands;
+  };
+
+
+extern struct rule *pattern_rules;
+extern struct rule *last_pattern_rule;
+extern unsigned int num_pattern_rules;
+
+extern unsigned int max_pattern_deps;
+extern unsigned int max_pattern_targets;
+extern unsigned int max_pattern_dep_length;
+
+extern struct file *suffix_file;
+extern unsigned int maxsuffix;
+
+
+void count_implicit_rule_limits (void);
+void convert_to_pattern (void);
+void install_pattern_rule (struct pspec *p, int terminal);
+void create_pattern_rule (const char **targets, const char **target_percents,
+                          unsigned int num, int terminal, struct dep *deps,
+                          struct commands *commands, int override);
Index: /tags/kBuild-0.1.4/src/kmk/signame.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/signame.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/signame.c	(revision 1780)
@@ -0,0 +1,255 @@
+/* Convert between signal names and numbers.
+Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+/* If the system provides strsignal, we don't need it. */
+
+#if !HAVE_STRSIGNAL
+
+/* If the system provides sys_siglist, we'll use that.
+   Otherwise create our own.
+ */
+
+#if !HAVE_DECL_SYS_SIGLIST
+
+/* Some systems do not define NSIG in <signal.h>.  */
+#ifndef	NSIG
+#ifdef	_NSIG
+#define	NSIG	_NSIG
+#else
+#define	NSIG	32
+#endif
+#endif
+
+/* There is too much variation in Sys V signal numbers and names, so
+   we must initialize them at runtime.  */
+
+static const char *undoc;
+
+static const char *sys_siglist[NSIG];
+
+/* Table of abbreviations for signals.  Note:  A given number can
+   appear more than once with different abbreviations.  */
+#define SIG_TABLE_SIZE  (NSIG*2)
+
+typedef struct
+  {
+    int number;
+    const char *abbrev;
+  } num_abbrev;
+
+static num_abbrev sig_table[SIG_TABLE_SIZE];
+
+/* Number of elements of sig_table used.  */
+static int sig_table_nelts = 0;
+
+/* Enter signal number NUMBER into the tables with ABBREV and NAME.  */
+
+static void
+init_sig (int number, const char *abbrev, const char *name)
+{
+  /* If this value is ever greater than NSIG it seems like it'd be a bug in
+     the system headers, but... better safe than sorry.  We know, for
+     example, that this isn't always true on VMS.  */
+
+  if (number >= 0 && number < NSIG)
+    sys_siglist[number] = name;
+
+  if (sig_table_nelts < SIG_TABLE_SIZE)
+    {
+      sig_table[sig_table_nelts].number = number;
+      sig_table[sig_table_nelts++].abbrev = abbrev;
+    }
+}
+
+static int
+signame_init (void)
+{
+  int i;
+
+  undoc = xstrdup (_("unknown signal"));
+
+  /* Initialize signal names.  */
+  for (i = 0; i < NSIG; i++)
+    sys_siglist[i] = undoc;
+
+  /* Initialize signal names.  */
+#if defined (SIGHUP)
+  init_sig (SIGHUP, "HUP", _("Hangup"));
+#endif
+#if defined (SIGINT)
+  init_sig (SIGINT, "INT", _("Interrupt"));
+#endif
+#if defined (SIGQUIT)
+  init_sig (SIGQUIT, "QUIT", _("Quit"));
+#endif
+#if defined (SIGILL)
+  init_sig (SIGILL, "ILL", _("Illegal Instruction"));
+#endif
+#if defined (SIGTRAP)
+  init_sig (SIGTRAP, "TRAP", _("Trace/breakpoint trap"));
+#endif
+  /* If SIGIOT == SIGABRT, we want to print it as SIGABRT because
+     SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't.  */
+#if defined (SIGABRT)
+  init_sig (SIGABRT, "ABRT", _("Aborted"));
+#endif
+#if defined (SIGIOT)
+  init_sig (SIGIOT, "IOT", _("IOT trap"));
+#endif
+#if defined (SIGEMT)
+  init_sig (SIGEMT, "EMT", _("EMT trap"));
+#endif
+#if defined (SIGFPE)
+  init_sig (SIGFPE, "FPE", _("Floating point exception"));
+#endif
+#if defined (SIGKILL)
+  init_sig (SIGKILL, "KILL", _("Killed"));
+#endif
+#if defined (SIGBUS)
+  init_sig (SIGBUS, "BUS", _("Bus error"));
+#endif
+#if defined (SIGSEGV)
+  init_sig (SIGSEGV, "SEGV", _("Segmentation fault"));
+#endif
+#if defined (SIGSYS)
+  init_sig (SIGSYS, "SYS", _("Bad system call"));
+#endif
+#if defined (SIGPIPE)
+  init_sig (SIGPIPE, "PIPE", _("Broken pipe"));
+#endif
+#if defined (SIGALRM)
+  init_sig (SIGALRM, "ALRM", _("Alarm clock"));
+#endif
+#if defined (SIGTERM)
+  init_sig (SIGTERM, "TERM", _("Terminated"));
+#endif
+#if defined (SIGUSR1)
+  init_sig (SIGUSR1, "USR1", _("User defined signal 1"));
+#endif
+#if defined (SIGUSR2)
+  init_sig (SIGUSR2, "USR2", _("User defined signal 2"));
+#endif
+  /* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that
+     is what is in POSIX.1.  */
+#if defined (SIGCHLD)
+  init_sig (SIGCHLD, "CHLD", _("Child exited"));
+#endif
+#if defined (SIGCLD)
+  init_sig (SIGCLD, "CLD", _("Child exited"));
+#endif
+#if defined (SIGPWR)
+  init_sig (SIGPWR, "PWR", _("Power failure"));
+#endif
+#if defined (SIGTSTP)
+  init_sig (SIGTSTP, "TSTP", _("Stopped"));
+#endif
+#if defined (SIGTTIN)
+  init_sig (SIGTTIN, "TTIN", _("Stopped (tty input)"));
+#endif
+#if defined (SIGTTOU)
+  init_sig (SIGTTOU, "TTOU", _("Stopped (tty output)"));
+#endif
+#if defined (SIGSTOP)
+  init_sig (SIGSTOP, "STOP", _("Stopped (signal)"));
+#endif
+#if defined (SIGXCPU)
+  init_sig (SIGXCPU, "XCPU", _("CPU time limit exceeded"));
+#endif
+#if defined (SIGXFSZ)
+  init_sig (SIGXFSZ, "XFSZ", _("File size limit exceeded"));
+#endif
+#if defined (SIGVTALRM)
+  init_sig (SIGVTALRM, "VTALRM", _("Virtual timer expired"));
+#endif
+#if defined (SIGPROF)
+  init_sig (SIGPROF, "PROF", _("Profiling timer expired"));
+#endif
+#if defined (SIGWINCH)
+  /* "Window size changed" might be more accurate, but even if that
+     is all that it means now, perhaps in the future it will be
+     extended to cover other kinds of window changes.  */
+  init_sig (SIGWINCH, "WINCH", _("Window changed"));
+#endif
+#if defined (SIGCONT)
+  init_sig (SIGCONT, "CONT", _("Continued"));
+#endif
+#if defined (SIGURG)
+  init_sig (SIGURG, "URG", _("Urgent I/O condition"));
+#endif
+#if defined (SIGIO)
+  /* "I/O pending" has also been suggested.  A disadvantage is
+     that signal only happens when the process has
+     asked for it, not everytime I/O is pending.  Another disadvantage
+     is the confusion from giving it a different name than under Unix.  */
+  init_sig (SIGIO, "IO", _("I/O possible"));
+#endif
+#if defined (SIGWIND)
+  init_sig (SIGWIND, "WIND", _("SIGWIND"));
+#endif
+#if defined (SIGPHONE)
+  init_sig (SIGPHONE, "PHONE", _("SIGPHONE"));
+#endif
+#if defined (SIGPOLL)
+  init_sig (SIGPOLL, "POLL", _("I/O possible"));
+#endif
+#if defined (SIGLOST)
+  init_sig (SIGLOST, "LOST", _("Resource lost"));
+#endif
+#if defined (SIGDANGER)
+  init_sig (SIGDANGER, "DANGER", _("Danger signal"));
+#endif
+#if defined (SIGINFO)
+  init_sig (SIGINFO, "INFO", _("Information request"));
+#endif
+#if defined (SIGNOFP)
+  init_sig (SIGNOFP, "NOFP", _("Floating point co-processor not available"));
+#endif
+
+  return 1;
+}
+
+#endif  /* HAVE_DECL_SYS_SIGLIST */
+
+
+char *
+strsignal (int signal)
+{
+  static char buf[] = "Signal 12345678901234567890";
+
+#if ! HAVE_DECL_SYS_SIGLIST
+# if HAVE_DECL__SYS_SIGLIST
+#  define sys_siglist _sys_siglist
+# elif HAVE_DECL___SYS_SIGLIST
+#  define sys_siglist __sys_siglist
+# else
+  static char sig_initted = 0;
+
+  if (!sig_initted)
+    sig_initted = signame_init ();
+# endif
+#endif
+
+  if (signal > 0 || signal < NSIG)
+    return (char *) sys_siglist[signal];
+
+  sprintf (buf, "Signal %d", signal);
+  return buf;
+}
+
+#endif  /* HAVE_STRSIGNAL */
Index: /tags/kBuild-0.1.4/src/kmk/strcache.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/strcache.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/strcache.c	(revision 1780)
@@ -0,0 +1,250 @@
+/* Constant string caching for GNU Make.
+Copyright (C) 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#include <assert.h>
+
+#include "hash.h"
+
+/* The size (in bytes) of each cache buffer.
+   Try to pick something that will map well into the heap.  */
+#define CACHE_BUFFER_SIZE   (8192 - 16)
+
+
+/* A string cached here will never be freed, so we don't need to worry about
+   reference counting.  We just store the string, and then remember it in a
+   hash so it can be looked up again. */
+
+struct strcache {
+  struct strcache *next;    /* The next block of strings.  */
+  char *end;                /* Pointer to the beginning of the free space.  */
+  int count;                /* # of strings in this buffer (for stats).  */
+  int bytesfree;            /* The amount of the buffer that is free.  */
+  char buffer[1];           /* The buffer comes after this.  */
+};
+
+static int bufsize = CACHE_BUFFER_SIZE;
+static struct strcache *strcache = NULL;
+
+/* Add a new buffer to the cache.  Add it at the front to reduce search time.
+   This can also increase the overhead, since it's less likely that older
+   buffers will be filled in.  However, GNU make has so many smaller strings
+   that this doesn't seem to be much of an issue in practice.
+ */
+static struct strcache *
+new_cache()
+{
+  struct strcache *new;
+  new = xmalloc (sizeof (*new) + bufsize);
+  new->end = new->buffer;
+  new->count = 0;
+  new->bytesfree = bufsize;
+
+  new->next = strcache;
+  strcache = new;
+
+  return new;
+}
+
+static const char *
+add_string(const char *str, int len)
+{
+  struct strcache *best = NULL;
+  struct strcache *sp;
+  const char *res;
+
+  /* If the string we want is too large to fit into a single buffer, then
+     we're screwed; nothing will ever fit!  Change the maximum size of the
+     cache to be big enough.  */
+  if (len > bufsize)
+    bufsize = len * 2;
+
+  /* First, find a cache with enough free space.  We always look through all
+     the blocks and choose the one with the best fit (the one that leaves the
+     least amount of space free).  */
+  for (sp = strcache; sp != NULL; sp = sp->next)
+    if (sp->bytesfree > len && (!best || best->bytesfree > sp->bytesfree))
+      best = sp;
+
+  /* If nothing is big enough, make a new cache.  */
+  if (!best)
+    best = new_cache();
+
+  assert (best->bytesfree > len);
+
+  /* Add the string to the best cache.  */
+  res = best->end;
+  memcpy (best->end, str, len);
+  best->end += len;
+  *(best->end++) = '\0';
+  best->bytesfree -= len + 1;
+  ++best->count;
+
+  return res;
+}
+
+
+/* Hash table of strings in the cache.  */
+
+static unsigned long
+str_hash_1 (const void *key)
+{
+  return_ISTRING_HASH_1 ((const char *) key);
+}
+
+static unsigned long
+str_hash_2 (const void *key)
+{
+  return_ISTRING_HASH_2 ((const char *) key);
+}
+
+static int
+str_hash_cmp (const void *x, const void *y)
+{
+  return_ISTRING_COMPARE ((const char *) x, (const char *) y);
+}
+
+static struct hash_table strings;
+static unsigned long total_adds = 0;
+
+static const char *
+add_hash (const char *str, int len)
+{
+  /* Look up the string in the hash.  If it's there, return it.  */
+  char *const *slot = (char *const *) hash_find_slot (&strings, str);
+  const char *key = *slot;
+
+  /* Count the total number of adds we performed.  */
+  ++total_adds;
+
+  if (!HASH_VACANT (key))
+    return key;
+
+  /* Not there yet so add it to a buffer, then into the hash table.  */
+  key = add_string (str, len);
+  hash_insert_at (&strings, key, slot);
+  return key;
+}
+
+/* Returns true if the string is in the cache; false if not.  */
+int
+strcache_iscached (const char *str)
+{
+  struct strcache *sp;
+
+  for (sp = strcache; sp != 0; sp = sp->next)
+    if (str >= sp->buffer && str < sp->end)
+      return 1;
+
+  return 0;
+}
+
+/* If the string is already in the cache, return a pointer to the cached
+   version.  If not, add it then return a pointer to the cached version.
+   Note we do NOT take control of the string passed in.  */
+const char *
+strcache_add (const char *str)
+{
+  return add_hash (str, strlen (str));
+}
+
+const char *
+strcache_add_len (const char *str, int len)
+{
+  /* If we're not given a nul-terminated string we have to create one, because
+     the hashing functions expect it.  */
+  if (str[len] != '\0')
+    {
+      char *key = alloca (len + 1);
+      memcpy (key, str, len);
+      key[len] = '\0';
+      str = key;
+    }
+
+  return add_hash (str, len);
+}
+
+int
+strcache_setbufsize(int size)
+{
+  if (size > bufsize)
+    bufsize = size;
+  return bufsize;
+}
+
+void
+strcache_init (void)
+{
+#ifdef KMK
+  hash_init (&strings, 16384, str_hash_1, str_hash_2, str_hash_cmp);
+#else
+  hash_init (&strings, 8000, str_hash_1, str_hash_2, str_hash_cmp);
+#endif
+}
+
+
+/* Generate some stats output.  */
+
+void
+strcache_print_stats (const char *prefix)
+{
+  int numbuffs = 0, numstrs = 0;
+  int totsize = 0, avgsize, maxsize = 0, minsize = bufsize;
+  int totfree = 0, avgfree, maxfree = 0, minfree = bufsize;
+  int lastused = 0, lastfree = 0;
+
+  if (strcache)
+    {
+      const struct strcache *sp;
+
+      /* Count the first buffer separately since it's not full.  */
+      lastused = strcache->end - strcache->buffer;
+      lastfree = strcache->bytesfree;
+
+      for (sp = strcache->next; sp != NULL; sp = sp->next)
+        {
+          int bf = sp->bytesfree;
+          int sz = sp->end - sp->buffer;
+
+          ++numbuffs;
+          numstrs += sp->count;
+
+          totsize += sz;
+          maxsize = (sz > maxsize ? sz : maxsize);
+          minsize = (sz < minsize ? sz : minsize);
+
+          totfree += bf;
+          maxfree = (bf > maxfree ? bf : maxfree);
+          minfree = (bf < minfree ? bf : minfree);
+        }
+    }
+
+  avgsize = numbuffs ? (int)(totsize / numbuffs) : 0;
+  avgfree = numbuffs ? (int)(totfree / numbuffs) : 0;
+
+  printf (_("\n%s # of strings in strcache: %d / lookups = %lu / hits = %lu\n"),
+          prefix, numstrs, total_adds, (total_adds - numstrs));
+  printf (_("%s # of strcache buffers: %d (* %d B/buffer = %d B)\n"),
+          prefix, (numbuffs + 1), bufsize, ((numbuffs + 1) * bufsize));
+  printf (_("%s strcache used: total = %d (%d) / max = %d / min = %d / avg = %d\n"),
+          prefix, totsize, lastused, maxsize, minsize, avgsize);
+  printf (_("%s strcache free: total = %d (%d) / max = %d / min = %d / avg = %d\n"),
+          prefix, totfree, lastfree, maxfree, minfree, avgfree);
+
+  fputs (_("\n# strcache hash-table stats:\n# "), stdout);
+  hash_print_stats (&strings, stdout);
+}
Index: /tags/kBuild-0.1.4/src/kmk/subproc.bat
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/subproc.bat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/subproc.bat	(revision 1780)
@@ -0,0 +1,25 @@
+@echo off
+rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+rem 2005, 2006 Free Software Foundation, Inc.
+rem This file is part of GNU Make.
+
+rem GNU Make is free software; you can redistribute it and/or modify it under
+rem the terms of the GNU General Public License as published by the Free
+rem Software Foundation; either version 2, or (at your option) any later
+rem version.
+
+rem GNU Make is distributed in the hope that it will be useful, but WITHOUT
+rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+rem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+rem more details.
+
+rem You should have received a copy of the GNU General Public License along
+rem with GNU Make; see the file COPYING.  If not, write to the Free Software
+rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+cd w32\subproc
+set MAKE=%2
+set MAKEFILE=%1
+if x%2 == x set MAKE=nmake
+%MAKE% /f %MAKEFILE%
+cd ..\..
Index: /tags/kBuild-0.1.4/src/kmk/testcase-2ndtargetexp.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-2ndtargetexp.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-2ndtargetexp.kmk	(revision 1780)
@@ -0,0 +1,69 @@
+# $Id$
+## @file
+# kBuild - testcase for the 2nd target expansion feature.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+#
+# Enable it.
+#
+.SECONDTARGETEXPANSION:
+
+
+#
+# This is expanded immediately.
+#
+foo1 = foo1
+$(foo1):
+	$(if $(eq $@,foo1),$(ECHO) "foo1 works",$(ECHO) "foo1 is busted @=$@"; exit 1)
+
+# Mostly for making sure the ifeq test works below.
+flush_command_recoding := 1 # see record_waiting_files() in read.c
+ifeq ($(strip $(commands foo1)),)
+$(error No commands for foo1: $(commands foo1))
+endif
+
+
+#
+# This is expanded in the 2nd round.
+#
+$$(foo2):
+	$(if $(eq $@,foo2),$(ECHO) "foo2 works",$(ECHO) "foo2 is busted @=$@"; exit 1)
+
+# Check that a $(foo2) file exists.
+flush_command_recoding := 1 # see record_waiting_files() in read.c
+# $ (info $$(foo2) commands: $(commands $$(foo2)))
+ifeq ($(strip $(commands $$(foo2))),)
+$(error No commands for $$(foo2): $(commands $$(foo2)))
+endif
+
+
+all_recursive: foo1 foo2
+	$(ECHO) "2nd target expansion passes smoke testing"
+
+# define this last
+foo2 = foo2
+
Index: /tags/kBuild-0.1.4/src/kmk/testcase-if1of.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-if1of.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-if1of.kmk	(revision 1780)
@@ -0,0 +1,80 @@
+# $Id: $
+## @file
+# kBuild - testcase for the if1of and ifn1of conditionals.
+#
+
+#
+# Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+# the basics.
+if1of (asdf,asdf)
+else
+ $(error busted)
+endif
+ifn1of (asdf,asdf)
+ $(error busted)
+endif
+
+# larger sets.
+if1of (1,2 3 4 5 6 7 8 9 0)
+ $(error busted)
+endif
+if1of (1,12 3 4 5 6 7 8 9 0)
+ $(error busted)
+endif
+if1of (1,2 31 4 5 6 7 8 9 0)
+ $(error busted)
+endif
+ifn1of (1,1 2 3 4 5 6 7 8 9 0)
+ $(error busted)
+endif
+ifn1of (8,1 2 3 4 5 6 7 8 9 0)
+ $(error busted)
+endif
+ifn1of (asdf,asdf)
+ $(error busted)
+endif
+ifn1of (asdf,asdf asdf)
+ $(error busted)
+endif
+
+# any in set 1 match any in set 2.
+if1of (1 3 5 7 9, 2 4 6 8)
+ $(error busted)
+endif
+ifn1of (1 2 3 4 5, 2 4 6 8)
+ $(error busted)
+endif
+
+# real life.
+ifn1of (win linux, linux)
+ $(error busted)
+endif
+ifn1of (win.x86, win.amd64 linux.x86 darwin.x86 win.x86 os2.x86)
+ $(error busted)
+endif
+
+
+all_recursive:
+	$(ECHO) "if1of and ifn1of work fine"
Index: /tags/kBuild-0.1.4/src/kmk/testcase-ifcond.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-ifcond.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-ifcond.kmk	(revision 1780)
@@ -0,0 +1,798 @@
+# $Id$
+## @file
+# kBuild - testcase for the if conditionals.
+#
+
+#
+# Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+
+DEPTH = ../..
+include $(KBUILD_PATH)/header.kmk
+
+#
+# Note! The testcase are ordered by ascending operator precedence 
+#       with the exception of equal and not-equal because these
+#       are kind of useful for performing tests on non-logical ops.
+# 
+
+#
+# Parenthesis
+#
+$(warning unary operators: ( and ) )
+if (1)
+else
+$(error )
+endif
+
+if ((((1))))
+else
+$(error )
+endif
+
+
+#
+# Equal and Not Equal w/ some fundamental bits thrown in.
+#
+$(warning binary operators: == and != )
+
+if 1 == 1
+else
+$(error )
+endif
+
+if 2 == 3
+$(error )
+else
+endif
+
+if 2 != 3
+else
+$(error )
+endif
+
+if a != b
+else
+$(error )
+endif
+
+if asdf == asdf
+else
+$(error )
+endif
+
+if "asdf" == asdf
+else
+$(error )
+endif
+
+if 'asdf' == asdf
+else
+$(error )
+endif
+
+if 'asdf' == "asdf"
+else
+$(error )
+endif
+
+if 'asdf' == 'asdf'
+else
+$(error )
+endif
+
+if "asdf" == "asdf"
+else
+$(error )
+endif
+
+if 0x1 == 1
+else
+$(error )
+endif
+
+if 0xfff == 4095
+else
+$(error )
+endif
+
+if 0xfff == 4095
+else
+$(error )
+endif
+
+if 0d10 == 10
+else
+$(error )
+endif
+
+if 0d10 == 10
+else
+$(error )
+endif
+
+if 0xa == 012
+else
+$(error )
+endif
+
+if 0b1110 == 016
+else
+$(error )
+endif
+
+
+#
+# Logical OR
+#
+$(warning binary operator: || )
+if 1
+else
+$(error busted)
+endif
+
+if 1 || 1
+else
+$(error )
+endif
+
+if 0 || 0
+$(error )
+else
+endif
+
+if 1 || 0
+else
+$(error )
+endif
+
+if 0 || 1
+else
+$(error )
+endif
+
+if 0 || 0 || 0 || 0 || 0 || 0 || 0
+$(error )
+else
+endif
+
+if 0 || 0 || 0 || 1 || 0 || 0 || 0
+else
+$(error )
+endif
+
+if "asdf" || 0
+else
+$(error )
+endif
+
+if 0 || "asdf"
+else
+$(error )
+endif
+
+if 'asdf' || 0
+else
+$(error )
+endif
+
+if "" || 0
+$(error )
+endif
+if "" || 1
+else
+$(error )
+endif
+if '' || 0
+$(error )
+endif
+if '' || 1
+else
+$(error )
+endif
+
+if "" || ''
+$(error )
+endif
+if "1" || ''
+else
+$(error )
+endif
+if "1" || '1'
+else
+$(error )
+endif
+if "" || '1'
+else
+$(error )
+endif
+
+
+#
+# Logical AND
+#
+$(warning binary operator: && )
+if 1 && 1
+else
+$(error )
+endif
+if 1 && 0
+$(error )
+endif
+if 1234 && 0
+$(error )
+endif
+if 123434 && 0 && 123435 && 1
+$(error )
+endif
+
+if "" && 1
+$(error )
+endif
+if ("asdf" && 1) != 1
+$(error )
+endif
+if "1" && 'asdf'
+else
+$(error )
+endif
+if "1" && 'asdf' && 0
+$(error )
+endif
+
+if 0 || 1 && 0
+$(error )
+endif
+
+
+#
+# Bitwise OR
+#
+$(warning binary operator: | )
+if 1 | 0
+else
+$(error )
+endif
+if 1 | 1
+else
+$(error )
+endif
+if 11234 | 343423
+else
+$(error )
+endif
+if (1|2)!=3
+$(error )
+endif
+if 1|2 != 3
+else
+$(error )
+endif
+if (1|2|4|8)!=0xf
+$(error )
+endif
+
+
+#
+# Bitwise XOR
+#
+$(warning binary operator: ^ )
+if 1 ^ 1
+$(error )
+endif
+
+if (2 ^ 1) != 3
+$(error ) 
+endif
+
+if 7 != (2 ^ 1 ^ 4)
+$(error )
+endif
+
+if (2 ^ 1 | 2) != 3
+$(error )
+endif
+
+
+#
+# Bitwise AND
+#
+$(warning binary operator: & )
+if (4097 & 1) != 1
+$(error )
+endif
+if (0xfff & 0x0f0) != 0xf0
+$(error )
+endif
+if (0x1e3 & 0x100 | 3) != 0x103
+$(error )
+endif
+
+
+#
+# Greater than
+#
+$(warning binary operator: > )
+if 1 > 0
+else
+$(error )
+endif
+
+if 1024 > 1023
+else
+$(error )
+endif
+
+if 999 > 1023
+$(error )
+endif
+
+if (5 > 4 | 2) != 3
+$(error )
+endif
+
+if (1 & 8 > 4) != 1
+$(error )
+endif
+
+if (8 > 4 ^ 16) != 17
+$(error )
+endif
+
+if "b" > 'a'
+else
+$(error )
+endif
+if "abcdef" > 'ffdas'
+$(error )
+endif
+if abcdef > ffdas
+$(error )
+endif
+
+
+#
+# Greater or equal than
+#
+$(warning binary operator: >= )
+if 20 > 0
+else
+$(error )
+endif
+
+if 20 >= 20
+else
+$(error )
+endif
+
+if 19 >= 20
+$(error )
+endif
+
+if (1 & 8 >= 4) != 1
+$(error )
+endif
+
+if "x" >= 'x'
+else
+$(error )
+endif
+if "abdc" >= 'abcd'
+else
+$(error )
+endif
+if "ffdaaa" >= 'ffdasd'
+$(error )
+endif
+if asdf >= asdf
+else
+$(error )
+endif
+
+
+#
+# Less than
+#
+if 1 < 1
+$(error )
+endif
+if -123 < -134
+$(error )
+endif
+if 123 <= 7777
+else
+$(error )
+endif
+
+if "b" < 'a'
+$(error )
+endif
+if b < a
+$(error )
+endif
+if 'foobar' < 'a$'
+$(error )
+endif
+if hhhh < ggggg 
+$(error )
+endif
+if qwerty < qwerty0
+else
+$(error )
+endif
+
+
+#
+# Less or equal than
+#
+$(warning binary operator: >> )
+if 1 <= 0
+$(error )
+endif
+if 1 <= 1
+else
+$(error )
+endif
+if 123 <= 123 != 1
+$(error )
+endif
+if 560 <= 456
+$(error )
+endif
+
+if "a" <= 'a'
+else
+$(error )
+endif
+if "abcdef" <= 'abcdef'
+else
+$(error )
+endif
+if q12345z6 <= q12345z
+$(error )
+endif
+if QWERTY <= ABCDE
+$(error )
+endif
+
+
+#
+# Shift right
+#
+$(warning binary operator: >> )
+if 1 >> 0 != 1
+$(error )
+endif
+if 1024 >> 2 != 256
+$(error )
+endif
+if 102435 >> 4 > 1234 != 1
+$(error )
+endif
+
+
+#
+# Shift left
+#
+$(warning binary operator: << )
+if 1 << 0 != 1
+$(error )
+endif
+if 1 << 1 != 2
+$(error )
+endif
+if 1 << 4 != 16
+$(error )
+endif
+if 1 << 10 != 1024
+$(error )
+endif
+if 34 << 10 != 0x8800
+$(error )
+endif
+if 1099511627776 << 21 != 2305843009213693952
+$(error )
+endif
+if 1 << 61 != 2305843009213693952
+$(error )
+endif
+
+if 2 << 60 > 123434323 != 1
+$(error )
+endif
+
+
+#
+# Subtraction
+#
+$(warning binary operator: - )
+if 1-1 != 0
+$(error )
+endif
+if 1023-511 != 512
+$(error )
+endif
+if 4 - 3 << 3 != 8
+$(error )
+endif
+
+
+#
+# Addition
+#
+$(warning binary operator: + )
+if 1+1 != 2
+$(error )
+endif
+if 1234+1000 != 2234
+$(error )
+endif
+if 2 + 2 << 4 != 64
+$(error )
+endif
+
+
+#
+# Modulus
+#
+$(warning binary operator: % )
+if 0%2 != 0
+$(error )
+endif
+if 10%7 != 3
+$(error )
+endif
+if 10 + 100%70 - 3 != 37
+$(error )
+endif
+
+
+#
+# Division
+#
+$(warning binary operator: / )
+if 0/1 != 0
+$(error )
+endif
+if 1000/2 != 500
+$(error )
+endif
+if 1000/2 + 4 != 504
+$(error )
+endif
+if 5 + 1000/4 != 255
+$(error )
+endif
+
+
+#
+# Multiplication
+#
+$(warning binary operator: * )
+if 1*1 != 1
+$(error )
+endif
+if 10*10 != 100
+$(error )
+endif
+if 1024*64 != 65536
+$(error )
+endif
+if 10*10 - 10 != 90
+$(error )
+endif
+if 1000 - 10*10 != 900
+$(error )
+endif
+
+
+#
+# Logical NOT
+#
+$(warning unary operator: ! )
+if !1
+$(error )
+endif
+
+if !42 == 0
+else
+$(error )
+endif
+
+if !0 == 1
+else
+$(error )
+endif
+
+if !!0 == 0
+else
+$(error )
+endif
+
+if !0 * 123 != 123
+$(error )
+endif
+if !!!0 * 512 != 512
+$(error )
+endif
+
+
+#
+# Bitwise NOT
+#
+$(warning unary operator: ~ )
+if ~0xfff != 0xfffffffffffff000
+$(error )
+endif
+
+
+#
+# Pluss
+#
+$(warning unary operator: + )
+if +2 != 2
+$(error )
+endif
+if 1++++++++++++2134 != 2135
+$(error )
+endif
+
+
+#
+# Minus (negation)
+#
+$(warning unary operator: - )
+if --2 != 2
+$(error )
+endif
+
+if 1 - -2 != 3
+$(error )
+endif
+
+
+#
+# target
+#
+trg_deps_only: foobar
+trg_with_cmds: foobar
+	echo $@
+
+$(warning unary operator: target ) # This flushes stuff in read.c
+
+if target trg_with_cmds
+else
+$(error target trg_with_cmds)
+endif
+if target(trg_deps_only)
+$(error target trg_deps_only)
+endif
+if target ( foobar )
+$(error target foobar)
+endif
+
+
+#
+# defined
+#
+$(warning unary operator: defined )
+var_defined := 1
+var_not_defined :=
+
+if defined var_defined
+else
+$(error )
+endif
+if defined(var_defined)
+else
+$(error )
+endif
+if defined (var_defined)
+else
+$(error )
+endif
+if !defined(var_defined)
+$(error )
+endif
+if defined (var_not_defined)
+$(error )
+endif
+
+
+#
+# bool
+#
+$(warning unary operator: bool )
+if bool("Asdf") != 1
+$(error )
+endif
+if bool("") != 0
+$(error )
+endif
+
+
+#
+# bool
+#
+$(warning unary operator: num )
+if num("1234") != 1235 - 1
+$(error )
+endif
+if num('1234') != 1233 + 1
+$(error )
+endif
+
+
+#
+# str
+#
+$(warning unary operator: str )
+if str(a < b) != 1
+$(error )
+endif
+if str(a < b) != '1'
+$(error )
+endif
+if str( 1 ) != "1"
+$(error )
+endif
+if str( 1 ) != "1"
+$(error )
+endif
+if str( num(0x1000) ) != "4096"
+$(error )
+endif
+if str(0x1000) != 0x1000
+$(error )
+endif
+
+
+
+#
+# Quick check of $(if-expr ) and $(expr ).
+#
+$(warning $$(if-expr ,,) )
+ifeq ($(if-expr 0 || 2,42,500),42)
+else
+$(error )
+endif
+ifeq ($(if-expr 5+3 == 231,42,500),42)
+$(error )
+endif
+
+$(warning $$(expr ) )  
+ifeq ($(expr 5+3),8)
+else
+$(error expr:$(expr 5+3) expected 8)
+endif
+ifeq ($(expr 25*25),625)
+else
+$(error expr:$(expr 25*25) expected 625)
+endif
+ifeq ($(expr 100/3),3)
+$(error )
+endif
+
+
+
+all_recursive:
+	$(ECHO) "if works fine"
+
Index: /tags/kBuild-0.1.4/src/kmk/testcase-includedep-sub.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-includedep-sub.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-includedep-sub.kmk	(revision 1780)
@@ -0,0 +1,29 @@
+# $Id$
+## @file
+# kBuild - testcase for the includdep directive, helper file 
+#          that gets included all the time.
+#
+
+#
+# Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+testcase-includedep-sub.kmk=included
+
Index: /tags/kBuild-0.1.4/src/kmk/testcase-includedep.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-includedep.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-includedep.kmk	(revision 1780)
@@ -0,0 +1,91 @@
+# $Id$
+## @file
+# kBuild - testcase for the includedep directive.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+ifdef testcase-includedep-sub.kmk
+$(error testcase-includedep-sub.kmk is defined at the start of the testcase.)
+endif
+
+
+foo = testcase-includedep-sub
+includedep $(foo).kmk
+ifneq ($(testcase-includedep-sub.kmk),included)
+$(error The first test failed.)
+endif
+testcase-includedep-sub.kmk :=
+ifdef testcase-includedep-sub.kmk
+$(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.)
+endif
+
+
+foo = includedep
+includedep testcase-$(foo)-sub.kmk
+ifneq ($(testcase-includedep-sub.kmk),included)
+$(error The second test failed.)
+endif
+testcase-includedep-sub.kmk :=
+ifdef testcase-includedep-sub.kmk
+$(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.)
+endif
+
+
+foo = kmk
+includedep testcase-includedep-sub.$(foo)
+ifneq ($(testcase-includedep-sub.kmk),included)
+$(error The thrid test failed.)
+endif
+testcase-includedep-sub.kmk :=
+ifdef testcase-includedep-sub.kmk
+$(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.)
+endif
+
+
+includedep testcase-includedep-sub.kmk
+ifneq ($(testcase-includedep-sub.kmk),included)
+$(error The forth test failed.)
+endif
+testcase-includedep-sub.kmk :=
+ifdef testcase-includedep-sub.kmk
+$(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.)
+endif
+
+
+foo = asdf
+includedep testcase-$(foo)-sub.kmk
+ifeq ($(testcase-includedep-sub.kmk),included)
+$(error The fifth test failed.)
+endif
+testcase-includedep-sub.kmk :=
+ifdef testcase-includedep-sub.kmk
+$(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.)
+endif
+
+
+all_recursive:
+	$(ECHO) "includedep works fine"
+
Index: /tags/kBuild-0.1.4/src/kmk/testcase-libpath.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-libpath.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-libpath.kmk	(revision 1780)
@@ -0,0 +1,20 @@
+
+all:
+	@kmk_builtin_echo ""
+	@kmk_builtin_echo "Warning: This testcase requires manual inspection and is intended for OS/2 only."
+	@kmk_builtin_echo ""
+	@kmk_builtin_echo "getting:"
+	@kmk_builtin_echo "libpath BEGINLIBPATH:  $(libpath BEGINLIBPATH)"
+	@kmk_builtin_echo "libpath LIBPATH:       $(libpath LIBPATH)"
+	@kmk_builtin_echo "libpath ENDLIBPATH:    $(libpath ENDLIBPATH)"
+	@kmk_builtin_echo "libpath LIBPATHSTRICT: $(libpath LIBPATHSTRICT)"
+	@kmk_builtin_echo "setting:"
+	@kmk_builtin_echo "libpath ENDLIBPATH,\foobar:   $(libpath ENDLIBPATH,\foobar) -> $(libpath ENDLIBPATH)"
+	@kmk_builtin_echo "libpath ENDLIBPATH,:          $(libpath ENDLIBPATH,) -> $(libpath ENDLIBPATH)"
+	@kmk_builtin_echo "libpath BEGINLIBPATH,\qwerty: $(libpath BEGINLIBPATH,\qwerty) -> $(libpath BEGINLIBPATH)"
+	@kmk_builtin_echo "libpath BEGINLIBPATH,:        $(libpath BEGINLIBPATH,) -> $(libpath BEGINLIBPATH)"
+	@kmk_builtin_echo "libpath LIBPATHSTRICT,T:      $(libpath LIBPATHSTRICT,T) -> $(libpath LIBPATHSTRICT)"
+	@kmk_builtin_echo "libpath LIBPATHSTRICT,qwerty: $(libpath LIBPATHSTRICT,qwerty) -> $(libpath LIBPATHSTRICT)"
+	@kmk_builtin_echo "libpath LIBPATHSTRICT,F:      $(libpath LIBPATHSTRICT,F) -> $(libpath LIBPATHSTRICT)"
+	@kmk_builtin_echo "libpath LIBPATHSTRICT,:       $(libpath LIBPATHSTRICT,) -> $(libpath LIBPATHSTRICT)"
+
Index: /tags/kBuild-0.1.4/src/kmk/testcase-local.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-local.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-local.kmk	(revision 1780)
@@ -0,0 +1,127 @@
+#
+# local variables:
+#	o The keyword will make sure the variable is defined in
+#     current variable context instead of the global one.
+#   o Local variables are readable by children but not writable,
+#     writes goes to the globle space (a sideeffect / feature).
+#   o Local variables hides global and parent variables.
+#
+
+
+# global variable.
+var_exists1 = 1
+
+
+
+##
+# A simple define that is $(eval)uated.
+define def_test1
+
+# check that the existing variable is accessible.
+ifneq ($(var_exists1),1)
+ $(error var_exists1=$(var_exists1) (def_test1/1))
+endif
+
+# Quick check with a couple of local variables.
+local var_local1 = 2
+ifneq ($(var_local1),2)
+ $(error var_local1=$(var_local1) (def_test1/2))
+endif
+local var_local2 = 3
+ifneq ($(var_local2),3)
+ $(error var_local2=$(var_local2) (def_test1/3))
+endif
+
+# var_local1 and var_local2 should remain unchanged, var_local3 shouldn't exist.
+$(evalctx $(value def_test2))
+
+ifneq ($(var_local1),2)
+ $(error var_local1=$(var_local1) (def_test1/4))
+endif
+ifneq ($(var_local2),3)
+ $(error var_local2=$(var_local2) (def_test1/5))
+endif
+ifneq ($(var_local3),)
+ $(error var_local3=$(var_local3) (def_test1/6))
+endif
+
+endef # def_test1
+
+
+
+##
+# Called by def_test1, this checks that the locals of def_test1
+# are accessible and can be hidden by another local variable
+# or updated if assigned to.
+define def_test2
+
+# check that the existing variables are accessible, including the def_test1 ones.
+ifneq ($(var_exists1),1)
+ $(error var_exists1=$(var_exists1) (def_test2/1))
+endif
+ifneq ($(var_local1),2)
+ $(error var_local1=$(var_local1) (def_test2/2))
+endif
+ifneq ($(var_local2),3)
+ $(error var_local2=$(var_local2) (def_test2/3))
+endif
+
+# Make a local var_local1 that hides the one in def_test1.
+local var_local1 = 20
+ifneq ($(var_local1),20)
+ $(error var_local1=$(var_local1) (def_test2/4))
+endif
+
+# FEATURE: Update the var_local2 variable, this should be visible in the global space and not the local.
+var_local2 = 30
+ifneq ($(var_local2),3)
+ $(error var_local2=$(var_local2) (def_test2/5))
+endif
+
+# create a new local variable that isn't accessible from def_test1.
+local var_local3 = 4
+ifneq ($(var_local3),4)
+ $(error var_local3=$(var_local3) (def_test2/6))
+endif
+
+endef # def_test2
+
+
+
+#
+# The test body
+#
+
+# None of the local variables should exist.
+ifneq ($(var_local1),)
+ $(error var_local1=$(var_local1))
+endif
+ifneq ($(var_local2),)
+ $(error var_local2=$(var_local2))
+endif
+ifneq ($(var_local3),)
+ $(error var_local3=$(var_local3))
+endif
+
+# Evaluate the function in a local context.
+$(evalctx $(value def_test1))
+
+# FEATURE: see var_local2 = 30 in def_test2.
+ifneq ($(var_local2),30)
+ $(error var_local2=$(var_local2))
+endif
+
+# None of the other local variables should exist.
+ifneq ($(var_local1),)
+ $(error var_local1=$(var_local1))
+endif
+ifneq ($(var_local3),)
+ $(error var_local3=$(var_local3))
+endif
+
+
+
+# dummy
+all:
+	echo local variables works.
+
Index: /tags/kBuild-0.1.4/src/kmk/testcase-math.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-math.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-math.kmk	(revision 1780)
@@ -0,0 +1,99 @@
+# $Id: $
+## @file
+#
+# kBuild - testcase for the math functions.
+#
+# Copyright (c) 2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kLdr.
+#
+# kLdr 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.
+#
+# kLdr 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 kLdr; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+ifneq ($(not 1),)
+ $(error The 'not' function is missing)
+endif
+ifneq ($(eq 1,1),1)
+ $(error The 'eq' function is missing)
+endif
+
+
+ASSERT_TRUE  = $(if $(not $(1)),$(error failure: '$(1)' isn't true))
+ASSERT_FALSE = $(if       $(1) ,$(error failure: '$(1)' isn't false))
+
+$(call ASSERT_TRUE, $(int-eq 0x0, 0))
+$(call ASSERT_FALSE,$(int-eq 1, 0))
+$(call ASSERT_FALSE,$(int-eq 1123123123, 9898787987))
+$(call ASSERT_TRUE, $(int-eq 1234567890, 1234567890))
+$(call ASSERT_TRUE, $(int-eq 0x1c, 28))
+$(call ASSERT_TRUE, $(int-eq 1c, 28))
+$(call ASSERT_TRUE, $(int-ne 0x123, -0x123))
+$(call ASSERT_TRUE, $(int-ne 123, -0x123))
+$(call ASSERT_FALSE,$(int-ne 0x100, 256))
+$(call ASSERT_FALSE,$(int-ne 0x0, 0))
+$(call ASSERT_FALSE,$(int-ne 0x1c, 28))
+$(call ASSERT_TRUE, $(int-le 0, 0))
+$(call ASSERT_TRUE, $(int-le -0, 0))
+$(call ASSERT_FALSE,$(int-le 5, 1))
+$(call ASSERT_FALSE,$(int-lt 5, 1))
+$(call ASSERT_FALSE,$(int-lt 5, 5))
+$(call ASSERT_TRUE, $(int-lt 9, 10))
+$(call ASSERT_TRUE, $(int-lt -9, -8))
+$(call ASSERT_TRUE, $(int-ge 0, 0))
+$(call ASSERT_TRUE, $(int-ge -0, 0))
+$(call ASSERT_TRUE, $(int-ge 1, 0))
+$(call ASSERT_TRUE, $(int-ge -55, -55))
+$(call ASSERT_TRUE, $(int-ge 512, 400))
+$(call ASSERT_TRUE, $(int-ge -18, -19))
+$(call ASSERT_FALSE,$(int-ge -19, -18))
+$(call ASSERT_FALSE,$(int-ge 15, 20))
+$(call ASSERT_FALSE,$(int-gt 15, 20))
+$(call ASSERT_FALSE,$(int-gt 15, 15))
+$(call ASSERT_TRUE, $(int-gt 20, 15))
+
+ASSERT2 = $(if $(not $(int-eq $(1),$(2))),$(error failure: '$(1)' -ne '$(2)'))
+$(call ASSERT2,$(int-add 1, 1),0x2)
+$(call ASSERT2,$(int-add 1, 1, 1, 1, 1, 1, 1),7)
+$(call ASSERT2,$(int-add 1, -1),0)
+$(call ASSERT2,$(int-sub 1, -1),2)
+$(call ASSERT2,$(int-sub 1, 5),-4)
+$(call ASSERT2,$(int-mul 0x10, 0x20),0x200)
+$(call ASSERT2,$(int-mul 0x20, 0x10),0x200)
+$(call ASSERT2,$(int-mul 4, 7),28)
+$(call ASSERT2,$(int-mul 2, 2, 2, 2, 2, 4, 1, 1, 1, 1),128)
+$(call ASSERT2,$(int-div 0x1000, 0x100),0x10)
+$(call ASSERT2,$(int-div 999, 10),99)
+$(call ASSERT2,$(int-div 4096, 4,2,2,2,2),64)
+#$(call ASSERT2,$(int-div 0x1230023213, 0),0x0)
+$(call ASSERT2,$(int-mod 19, 10),9)
+$(call ASSERT2,$(int-mod 9, 10),9)
+$(call ASSERT2,$(int-mod 30, 10),0)
+$(call ASSERT2,$(int-not 0),-1)
+$(call ASSERT2,$(int-and 1, 1),1)
+$(call ASSERT2,$(int-and 0x123123214, 0xfff),0x214)
+$(call ASSERT2,$(int-and 0x123123214, 0xf0f, 0xf),4)
+$(call ASSERT2,$(int-or 1, 1, 1, 2, 2),3)
+$(call ASSERT2,$(int-xor 1, 1, 2, 2),0)
+$(call ASSERT2,$(int-xor 1, 2, 4),7)
+
+
+all_recursive:
+	$(ECHO) The math works. 6 * 7 = $(int-mul 6,7)
+
Index: /tags/kBuild-0.1.4/src/kmk/testcase-stack.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-stack.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-stack.kmk	(revision 1780)
@@ -0,0 +1,86 @@
+# $Id: $
+## @file
+#
+# kBuild - testcase for the functions.
+#
+# Copyright (c) 2006-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kLdr.
+#
+# kLdr 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.
+#
+# kLdr 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 kLdr; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+ifneq ($(not 1),)
+ $(error The 'not' function is missing)
+endif
+ifneq ($(eq 1,1),1)
+ $(error The 'eq' function is missing)
+endif
+
+ASSERT1 = $(if $(not $(eq $(STACK1),$(1))),$(error failure: STACK1:='$(STACK1)' expected='$(1)'))
+$(call stack-push,STACK1,1)
+$(call ASSERT,1)
+$(call stack-push,STACK1,2)
+$(call ASSERT,1 2)
+$(call stack-push,STACK1,3)
+$(call ASSERT,1 2 3)
+$(call stack-push,STACK1,4)
+$(call ASSERT,1 2 3 4)
+$(call stack-push,STACK1,5)
+$(call ASSERT,1 2 3 4 5)
+$(call stack-popv,STACK1)
+$(call ASSERT,1 2 3 4)
+$(call stack-push,STACK1,5)
+$(call ASSERT,1 2 3 4 5)
+$(call stack-popv,STACK1)
+$(call ASSERT,1 2 3 4)
+$(call stack-popv,STACK1)
+$(call ASSERT,1 2 3)
+$(call stack-push,STACK1,4)
+$(call ASSERT,1 2 3 4)
+$(call stack-push,STACK1,5)
+$(call ASSERT,1 2 3 4 5)
+top := $(call stack-top,STACK1)
+$(if $(not $(eq $(top),5)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='5'))
+$(call ASSERT,1 2 3 4 5)
+top := $(call stack-pop,STACK1)
+$(if $(not $(eq $(top),5)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='5'))
+$(call ASSERT,1 2 3 4)
+top := $(call stack-pop,STACK1)
+$(if $(not $(eq $(top),4)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='4'))
+$(call ASSERT,1 2 3)
+top := $(call stack-pop,STACK1)
+$(if $(not $(eq $(top),3)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='3'))
+$(call ASSERT,1 2)
+top := $(call stack-pop,STACK1)
+$(if $(not $(eq $(top),2)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='2'))
+$(call ASSERT,1)
+top := $(call stack-top,STACK1)
+$(if $(not $(eq $(top),1)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='1'))
+$(call ASSERT,1)
+top := $(call stack-pop,STACK1)
+$(if $(not $(eq $(top),1)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='1'))
+$(call ASSERT,)
+top := $(call stack-pop,STACK1)
+$(if $(not $(eq $(top),)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected=''))
+$(call ASSERT,)
+
+all_recursive:
+	$(ECHO) The stack works.$(STACK1)
Index: /tags/kBuild-0.1.4/src/kmk/testcase-which.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-which.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-which.kmk	(revision 1780)
@@ -0,0 +1,5 @@
+
+all:
+	@echo which kmk: $(which kmk)
+	@echo which kmk: $(which kmk kmk kmk )
+
Index: /tags/kBuild-0.1.4/src/kmk/testcase-xargs.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/testcase-xargs.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/testcase-xargs.kmk	(revision 1780)
@@ -0,0 +1,60 @@
+# $Id$
+## @file
+#
+# kBuild - testcase for the xargs function.
+#          Requires manual inspection of the output.
+#
+# Copyright (c) 2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+#
+# This file is part of kLdr.
+#
+# kLdr 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.
+#
+# kLdr 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 kLdr; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+ifneq ($(not 1),)
+ $(error The 'not' function is missing)
+endif
+ifneq ($(eq 1,1),1)
+ $(error The 'eq' function is missing)
+endif
+
+
+ASSERT_TRUE  = $(if $(not $(1)),$(error failure: '$(1)' isn't true))
+ASSERT_FALSE = $(if       $(1) ,$(error failure: '$(1)' isn't false))
+
+# 94 bytes
+ONEARG = abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_xxxxxxxxxxxx
+ITERATIONS := 0 1 2 3 4 5 6 7 8 9
+ITERATIONS := $(foreach i, 0 1 2 3 4 5 6 7 8 9,$(addprefix $(i),$(ITERATIONS)))
+ITERATIONS := $(foreach i, 0 1 2 3 4 5 6 7 8 9,$(addprefix $(i),$(ITERATIONS)))
+ITERATIONS := $(foreach i, 0 1 2 3 4 5 6 7 8 9,$(addprefix $(i),$(ITERATIONS)))
+ITERATIONS := $(foreach i, 0 1 2 3 4 5 6 7 8 9,$(addprefix $(i),$(ITERATIONS)))
+
+# add a 5 bytes sequence number and a space, then duplicate it 10000 times:
+#	100 bytes * 10000 = 1,000,000 bytes.
+REALLY_LONG := $(foreach i,$(ITERATIONS),$(i)$(ONEARG))
+
+
+#$(call ASSERT_TRUE, $(xargs $(ECHO) 1:, $(ECHO) 2:, $(ECHO) 3:, asdf asdf asdf asdf asdf asdf asdf adf asdf asdf))
+
+all_recursive:
+	$(xargs @$(ECHO_EXT) 1:, @$(ECHO_EXT) 2:, @$(ECHO_EXT) 3:, $(REALLY_LONG))
+	$(ECHO) done
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/COPYING
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/COPYING	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/COPYING	(revision 1780)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, 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.
+
+
+		    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.)
+
+
+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.
+
+
+  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.
+
+
+  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
+
+
+	Appendix: 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., 675 Mass Ave, Cambridge, MA 02139, 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.
Index: /tags/kBuild-0.1.4/src/kmk/tests/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/ChangeLog	(revision 1780)
@@ -0,0 +1,850 @@
+2006-10-01  Paul Smith  <psmith@paulandlesley.org>
+
+	* run_make_tests.pl (set_more_defaults): Remove setting of LANG in
+	ENV here.  This doesn't always work.
+	* test_driver.pl (toplevel): Set LC_ALL to 'C' in the make
+	environment.  Fixes Savannah bug #16698.
+
+2006-09-30  Paul Smith  <psmith@paulandlesley.org>
+
+	* scripts/variables/automatic: Add back the test for bug #8154.
+
+2006-04-01  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/realpath: Don't run tests with multiple
+	initial slashes on Windows: those paths mean something different.
+
+2006-03-19  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/parallelism: Test that the jobserver is
+	properly managed when we have to re-exec the master instance of
+	make.
+
+2006-03-17  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/statipattrules: Add tests for bug #16053.
+
+2006-03-09  Paul Smith  <psmith@gnu.org>
+
+	* scripts/features/escape: Use "pre:" not "p:" to avoid conflicts
+	with DOS drive letters.  Fixes Savannah bug #15947.
+
+	* test_driver.pl (run_each_test): Set the status properly even
+	when a test fails to execute.  Fixes Savannah bug #15942.
+
+	* scripts/functions/foreach: Use a different environment variable
+	other than PATH to avoid differences with Windows platforms.
+	Fixes Savannah bug #15938.
+
+2006-03-05  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (set_more_defaults): Add CYGWIN_NT as a port
+	type W32.  Fixed Savannah bug #15937.
+
+	* scripts/features/default_names: Don't call error() when the test
+	fails.  Fixes Savannah bug #15941.
+
+2006-02-17  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/targetvars: Test a complex construction which
+	guarantees that we have to merge variable lists of different
+	sizes.  Tests for Savannah bug #15757.
+
+2006-02-15  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/error: Make sure filename/lineno information
+	is related to where the error is expanded, not where it's set.
+	* scripts/functions/warning: Ditto.
+	* scripts/functions/foreach: Check for different error conditions.
+	* scripts/functions/word: Ditto.
+	* scripts/variables/negative: Test some variable reference failure
+	conditions.
+	* scripts/options/warn-undefined-variables: Test the
+	--warn-undefined-variables flag.
+
+2006-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (set_more_defaults): Update valgrind support
+	for newer versions.
+	* test_driver.pl (toplevel): Skip all hidden files/directories (ones
+	beginning with ".").
+
+	* scripts/functions/andor: Tests for $(and ..) and $(or ...)
+	functions.
+
+2006-02-08  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/parallelism: Add a test for bug #15641.
+
+2006-02-06  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-W: Add a test for bug #15341.
+
+2006-01-03  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/variables/automatic: Add a test for bug #8154.
+
+	* README: Update to reflect the current state of the test suite.
+
+2005-12-12  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/parallelism, scripts/functions/wildcard,
+	scripts/targets/FORCE, scripts/targets/PHONY,
+	scripts/targets/SILENT: Use the default setting for
+	$delete_command.  Fixes bug #15085.
+
+	* run_make_tests.pl (get_this_pwd) [VMS]: Use -no_ask with delete_file.
+
+2005-12-11  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/misc/general4: Test implicit rules with '$' in the
+	prereq list & prereq patterns.
+	* scripts/features/se_implicit: Add in .SECONDEXPANSION settings.
+
+2005-12-09  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patternrules: Add a test for bug #13022.
+
+2005-12-07  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/double_colon: Add a test for bug #14334.
+
+2005-11-17  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/functions/flavor: Add a test for the flavor function.
+
+2005-11-14  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/variables/INCLUDE_DIRS: Add a test for the .INCLUDE_DIRS
+	special variable.
+
+2005-10-24  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/misc/general4: Test '$$' in prerequisites list.
+	* scripts/features/statipattrules: Rewrite to use run_make_test().
+	Add various static pattern info.
+	* scripts/features/se_statpat: Enable .SECONDEXPANSION target.
+	* scripts/features/se_explicit: Add tests for handling '$$' in
+	prerequisite lists with and without setting .SECONDEXPANSION.
+	* scripts/features/order_only: Convert to run_make_test().
+	* run_make_tests.pl (set_more_defaults): If we can't get the value
+	of $(MAKE) from make, then fatal immediately.
+
+2005-08-31  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (get_this_pwd): Require the POSIX module (in
+	an eval to trap errors) and if it exists, use POSIX::getcwd to
+	find the working directory.  If it doesn't exist, go back to the
+	previous methods.  This tries to be more accurate on Windows
+	systems.
+
+2005-08-29  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/abspath: Add some text to the error messages
+	to get a better idea of what's wrong.  Make warnings instead of
+	errors.
+
+	* scripts/features/patspecific_vars: Don't use "test", which is
+	UNIX specific.  Print the values and let the test script match
+	them.
+
+2005-08-25  Paul Smith  <psmith@gnu.org>
+
+	* scripts/variables/SHELL: Use a /./ prefix instead of //: the
+	former works better with non-UNIX environments.  Fixes Savannah
+	bug #14129.
+
+2005-08-13  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/functions/wildcard: Wrap calls to $(wildcard ) with
+	$(sort) so that the resulting order is no longer filesystem-
+	dependant.
+
+2005-08-10  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/statipattrules: Add a test for Savannah bug #13881.
+
+2005-08-07  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/parallelism: Add a test for a bug reported by
+	Michael Matz (matz@suse.de) in which make exits without waiting
+	for all its children in some situations during parallel builds.
+
+2005-07-08  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl: Reset the environment to a clean value every
+	time before we invoke make.  I'm suspicious that the environment
+	isn't handled the same way in Windows as it is in UNIX, and some
+	variables are leaking out beyond the tests they are intended for.
+	Create an %extraENV hash tests can set to add more env. vars.
+	* tests/scripts/features/export: Change to use %extraENV.
+	* tests/scripts/functions/eval: Ditto.
+	* tests/scripts/functions/origin: Ditto.
+	* tests/scripts/options/dash-e: Ditto.
+	* tests/scripts/variables/SHELL: Ditto.
+
+2005-06-27  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-W: Use 'echo >>' instead of touch to update
+	files.
+	* scripts/features/reinvoke: Rewrite to be safer on systems with
+	subsecond timestamps.
+	* scripts/features/patternrules: False exits with different error
+	codes on different systems (for example, Linux => 1, Solaris => 255).
+
+	* scripts/options/dash-W: Set the timestamp to foo.x in the future,
+	to be sure it will be considered updated when it's remade.
+
+2005-06-26  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/shell: New test suite for the shell function.
+
+2005-06-25  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/include: Test include/-include/sinclude with no
+	arguments.  Tests fix for Savannah bug #1761.
+
+	* scripts/misc/general3: Implement comprehensive testing of
+	backslash-newline behavior in command scripts: various types of
+	quoting, fast path / slow path, etc.
+	Tests fix for Savannah bug #1332.
+
+	* scripts/options/symlinks: Test symlinks to non-existent files.
+	Tests fix for Savannah bug #13280.
+
+	* scripts/misc/general3: Test semicolons in variable references.
+	Tests fix for Savannah bug #1454.
+
+	* scripts/variables/MAKE_RESTARTS: New file: test the
+	MAKE_RESTARTS variable.
+	* scripts/options/dash-B: Test re-exec doesn't loop infinitely.
+	Tests fix for Savannah bug #7566.
+	* scripts/options/dash-W: New file: test the -W flag, including
+	re-exec infinite looping.
+
+2005-06-12  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/misc/close_stdout: Add a test for Savannah bug #1328.
+	This test only works on systems that have /dev/full (e.g., Linux).
+
+2005-06-09  Paul D. Smith  <psmith@gnu.org>
+
+        * scripts/functions/foreach: Add a test for Savannah bug #11913.
+
+2005-05-31  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/include: Add a test for Savannah bug #13216.
+	* scripts/features/patternrules: Add a test for Savannah bug #13218.
+
+2005-05-13  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/conditionals: Add tests for the new if... else
+	if... endif syntax.
+
+2005-05-03  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/variables/DEFAULT_GOAL: Rename DEFAULT_TARGET to
+	DEFAULT_GOAL.
+
+2005-05-02  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/parallelism: Add a test for exporting recursive
+	variables containing $(shell ) calls.  Rewrite this script to use
+	run_make_test() everywhere.
+
+2005-04-07  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/targets/SECONDARY: Add a test for Savannah bug #12331.
+
+2005-03-15  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/variables/automatic: Add a test for Savannah bug #12320.
+
+2005-03-10  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patternrules: Add a test for Savannah bug #12267.
+
+2005-03-09  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/variables/DEFAULT_TARGET: Add a test for Savannah
+	bug #12266.
+
+2005-03-04  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patternrules: Add a test for Savannah bug #12202.
+
+2005-03-03  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/se_implicit: Add a test for stem
+	termination bug. Add a test for stem triple-expansion bug.
+
+	* scripts/features/se_statpat: Add a test for stem
+	triple-expansion bug.
+
+	* scripts/features/statipattrules: Change test #4 to reflect
+	new way empty prerequisite list is handled.
+
+
+2005-03-01  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/statipattrules: Add a test for
+	Savannah bug #12180.
+
+2005-02-28  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-q: Add a test for Savannah bug # 7144.
+
+	* scripts/options/symlinks: New file to test checking of symlink
+	timestamps.  Can't use filename dash-L because it conflicts with
+	dash-l on case-insensitive filesystems.
+
+	* scripts/variables/MAKEFILE_LIST, scripts/variables/MFILE_LIST:
+	Rename MAKEFILE_LIST test to MFILE_LIST, for systems that need 8.3
+	unique filenames.
+
+2005-02-28  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/variables/DEFAULT_TARGET: Test the .DEFAULT_TARGET
+	special variable.
+
+2005-02-27  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/se_explicit: Test the second expansion in
+	explicit rules.
+	* scripts/features/se_implicit: Test the second expansion in
+	implicit rules.
+	* scripts/features/se_statpat: Test the second expansion in
+	static pattern rules.
+	* scripts/variables/automatic: Fix to work with the second
+	expansion.
+
+	* scripts/misc/general4: Add a test for bug #12091.
+
+2005-02-27  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/eval: Check that eval of targets within
+	command scripts fails.  See Savannah bug # 12124.
+
+2005-02-26  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (compare_output): If a basic comparison of the
+	log and answer doesn't match, try harder: change all backslashes
+	to slashes and all CRLF to LF.  This helps on DOS/Windows systems.
+
+2005-02-09  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/recursion: Test command line variable settings:
+	only one instance of a given variable should be provided.
+
+2004-11-30  Boris Kolpackov  <boris@kolpackov.net>
+
+	* tests/scripts/functions/abspath: New file: test `abspath'
+	built-in function.
+
+	* tests/scripts/functions/realpath: New file: test `realpath'
+	built-in function.
+
+2004-11-28  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-C [WINDOWS32]: Add a test for bug #10252;
+	this doesn't really test anything useful in UNIX but...
+
+	* scripts/variables/SHELL: New file: test proper handling of SHELL
+	according to POSIX rules.  Fixes bug #1276.
+
+2004-10-21  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/functions/word: Test $(firstword ) and $(lastword ).
+
+2004-10-05  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patspecific_vars: Test simple/recursive
+	variable expansion.
+
+2004-09-28  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/include: Test dontcare flag inheritance
+	when rebuilding makefiles.
+
+2004-09-27  Boris Kolpackov  <boris@kolpackov.net>
+
+	* scripts/features/patspecific_vars: Test exported variables.
+
+2004-09-22  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (run_make_test): Don't add newlines to the
+	makestring or answer if they are completely empty.
+
+	* scripts/features/patternrules: Rename from implicit_prereq_eval.
+
+	* scripts/test_template: Rework the template.
+
+2004-09-21  Boris Kolpackov  <boris@kolpackov.net>
+
+	* run_make_tests.pl: Change `#!/usr/local/bin/perl' to be
+	`#!/usr/bin/env perl'.
+
+	* scripts/features/implicit_prereq_eval: Test implicit rule
+	prerequisite evaluation code.
+
+2004-09-21  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (run_make_test): Enhance to allow the make
+	string to be undef: in that case it reuses the previous make
+	string.  Allows multiple tests on the same makefile.
+
+	* scripts/variables/flavors: Add some tests for prefix characters
+	interacting with define/endef variables.
+
+2004-09-20  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/substitution: Rewrite to use run_make_test()
+	interface, and add test for substitution failures reported by
+	Markus Mauhart <qwe123@chello.at>.
+
+2004-03-22  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (run_each_test, toplevel, compare_output): Change
+	to track both the testing categories _AND_ the number of
+	individual tests, and report both sets of numbers.
+
+2004-02-21  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/origin: Set our own environment variable
+	rather than relying on $HOME.
+
+2004-01-21  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/conditionals: Test arguments to ifn?def which
+	contain whitespace (such as a function that is evaluated).  Bug
+	#7257.
+
+2004-01-07  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/order_only: Test order-only prerequisites in
+	pattern rules (patch #2349).
+
+2003-11-02  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/if: Test if on conditionals with trailing
+	whitespace--bug #5798.
+
+	* scripts/functions/eval: Test eval in a non-file context--bug #6195.
+
+2003-04-19  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/patspecific_vars: Test multiple patterns
+	matching the same target--Bug #1405.
+
+2003-04-09  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (set_more_defaults): A new $port_type of
+	'OS/2' for (surprise!) OS/2.  Also choose a wait time of 2 seconds
+	for OS/2.
+
+2003-03-28  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/targets/SECONDARY: Test the "global" .SECONDARY (with
+	not prerequisites)--Bug #2515.
+
+2003-01-30  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/targetvars: Test very long target-specific
+	variable definition lines (longer than the default make buffer
+	length).  Tests patch # 1022.
+
+	* scripts/functions/eval: Test very recursive $(eval ...) calls
+	with simple variable expansion (bug #2238).
+
+	* scripts/functions/word: Test error handling for word and
+	wordlist functions (bug #2407).
+
+2003-01-22  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/call: Test recursive argument masking (bug
+	#1744).
+
+2002-10-25  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/eval: Test using $(eval ...) inside
+	conditionals (Bug #1516).
+
+2002-10-14  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-t: Add a test for handling -t on targets
+	with no commands (Bug #1418).
+
+2002-10-13  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/targetvars: Add a test for exporting
+	target-specific vars (Bug #1391).
+
+2002-10-05  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/variables/automatic: Add tests for $$(@), $${@}, $${@D},
+	and $${@F}.
+
+2002-09-23  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/escape: Test handling of escaped comment
+	characters in targets and prerequisites.
+
+2002-09-18  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/export: Test export/unexport of multiple
+	variables in a single command.
+
+2002-09-17  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/targetvars: Tests for Bug #940: test
+	target-specific and pattern-specific variables in conjunction with
+	double-colon targets.
+
+2002-09-10  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (compare_output): Match the new format for time
+	skew error messages.
+
+	* scripts/features/export: Created.  Add tests for export/unexport
+	capabilities, including exporting/unexporting expanded variables.
+
+	* scripts/features/conditionals: Add a test for expanded variables
+	in ifdef conditionals.
+
+2002-09-04  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/reinvoke: Change touch/sleep combos to utouch
+	invocations.
+	* scripts/features/vpathgpath: Ditto.
+	* scripts/features/vpathplus: Ditto.
+	* scripts/options/dash-n: Ditto.
+	* scripts/targets/INTERMEDIATE: Ditto.
+	* scripts/targets/SECONDARY: Ditto.
+
+	* scripts/options/dash-t: Added a test for the -t bug fixed by
+	Henning Makholm.  This test was also contributed by Henning.
+
+	* scripts/misc/general4: Add a test suite for obscure algorithmic
+	features of make.  First test: make sure creation subdirectories
+	as prerequisites of targets works properly.
+
+	* scripts/misc/version: Remove this bogus test.
+
+2002-08-07  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/misc/general3: Add a test for makefiles that don't end
+	in newlines.
+
+	* scripts/variables/special: Create tests for the special
+	variables (.VARIABLES and .TARGETS).  Comment out .TARGETS test
+	for now as it's not yet supported.
+
+2002-08-01  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-B: Add a test for the new -B option.
+
+2002-07-11  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (valid_option): Add support for Valgrind.  Use
+	-valgrind option to the test suite.
+	(set_more_defaults): Set up the file descriptor to capture
+	Valgrind output.  We have to unset its close-on-exec flag; we
+	hardcode the value for F_SETFD (2) rather than load it; hopefully
+	this will help us avoid breaking the Windows/DOS test suite.
+
+2002-07-10  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/variables/automatic: Add some tests for $$@, $$(@D), and
+	$$(@F).
+
+	* test_driver.pl (utouch): Create a new function that creates a
+	file with a specific timestamp offset.  Use of this function will
+	let us avoid lots of annoying sleep() invocations in the tests
+	just to get proper timestamping, which will make the tests run a
+	lot faster.  So far it's only used in the automatic test suite.
+
+2002-07-09  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/variables/automatic: Create a test for automatic variables.
+
+2002-07-08  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/order_only: Test new order-only prerequisites.
+
+2002-07-07  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/eval: Test new function.
+	* scripts/functions/value: Test new function.
+	* scripts/variables/MAKEFILE_LIST: Test new variable.
+
+2002-04-28  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/call: New test: transitive closure
+	implementation using $(call ...) to test variable recursion.
+
+2002-04-21  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (compare_dir_tree): Ignore CVS and RCS
+	directories in the script directories.
+
+2001-05-02  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/variables/flavors: Test define/endef scripts where only
+	one of the command lines is quiet.
+
+2000-06-22  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-q: New file; test the -q option.  Includes
+	a test for PR/1780.
+
+2000-06-21  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/targetvars: Added a test for PR/1709: allowing
+	semicolons in target-specific variable values.
+
+2000-06-19  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/addsuffix: Test for an empty final argument.
+	Actually this bug might have happened for any function, but this
+	one was handy.
+
+2000-06-17  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* scripts/options/general: If parallel jobs are not supported,
+	expect a warning message from Make.
+
+2000-06-15  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* scripts/options/general: Don't try -jN with N != 1 if parallel
+	jobs are not supported.
+
+2000-05-24  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/general: Test general option processing (PR/1716).
+
+2000-04-11  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/strip: Test empty value to strip (PR/1689).
+
+2000-04-08  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* scripts/features/reinvoke: Sleep before updating the target
+	files in the first test, to ensure its time stamp really gets
+	newer; otherwise Make might re-exec more than once.
+
+2000-04-07  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* scripts/features/double_colon: Don't run the parallel tests if
+	parallel jobs aren't supported.
+
+2000-04-04  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/word: wordlist doesn't swap arguments anymore.
+
+2000-03-27  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/statipattrules: Test that static pattern rules
+	whose prerequisite patterns resolve to empty strings throw an
+	error (instead of dumping core).  Fixes PR/1670.
+
+	* scripts/features/reinvoke: Make more robust by touching "b"
+	first, to ensure it's not newer than "a".
+	Reported by Marco Franzen <Marco.Franzen@Thyron.com>.
+	* scripts/options/dash-n: Ditto.
+
+	* scripts/functions/call: Whoops.  The fix to PR/1527 caused
+	recursive invocations of $(call ...) to break.  I can't come up
+	with any way to get both working at the same time, so I backed out
+	the fix to 1527 and added a test case for recursive calls.  This
+	also tests the fix for PR/1610.
+
+	* scripts/features/double_colon: Test that circular dependencies
+	in double-colon rule sets are detected correctly (PR/1671).
+
+2000-03-26  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/targets/INTERMEDIATE: Test that make doesn't remove
+	.INTERMEDIATE files when given on the command line (PR/1669).
+
+2000-03-08  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-k: Add a test for error detection by
+	multiple targets depending on the same prerequisite with -k.
+	For PR/1634.
+
+2000-02-07  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/escape: Add a test for backslash-escaped spaces
+	in a target name (PR/1586).
+
+2000-02-04  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/patspecific_vars: Add a test for pattern-specific
+	target variables inherited from the parent target (PR/1407).
+
+2000-02-02  Paul D. Smith  <psmith@gnu.org>
+
+	* run_make_tests.pl (set_more_defaults): Hard-code the LANG to C
+	to make sure sorting order, etc. is predictable.
+	Reported by Andreas Jaeger <aj@suse.de>.
+
+	* run_make_tests.pl (set_more_defaults): Set the $wtime variable
+	depending on the OS.  Eli Zaretskii <eliz@is.elta.co.il> reports
+	this seems to need to be *4* on DOS/Windows, not just 2.  Keep it
+	1 for other systems.
+	* scripts/features/vpathplus (touchfiles): Use the $wtime value
+	instead of hardcoding 2.
+	* scripts/targets/SECONDARY: Ditto.
+	* scripts/targets/INTERMEDIATE: Ditto.
+
+2000-01-27  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (toplevel): Don't try to run test scripts which
+	are really directories.
+
+2000-01-23  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/include: Remove a check; the fix caused more
+	problems than the error, so I removed it and removed the test for
+	it.
+
+2000-01-11  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/call: Add a test for PR/1517 and PR/1527: make
+	sure $(call ...) doesn't eval its arguments and that you can
+	invoke foreach from it without looping forever.
+
+1999-12-15  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/targets/INTERMEDIATE: Add a test for PR/1423: make sure
+	.INTERMEDIATE settings on files don't disable them as implicit
+	intermediate possibilities.
+
+1999-12-01  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/double_colon: Add a test for PR/1476: Try
+	double-colon rules as non-goal targets and during parallel builds
+	to make sure they're handled serially.
+
+1999-11-17  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/functions/if: Add a test for PR/1429: put some text
+	after an if-statement to make sure it works.
+
+	* scripts/features/targetvars: Add a test for PR/1380: handling +=
+	in target-specific variable definitions correctly.
+
+1999-10-15  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/variables/MAKEFILES: This was really broken: it didn't
+	test anything at all, really.  Rewrote it, plus added a test for
+	PR/1394.
+
+1999-10-13  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/options/dash-n: Add a test for PR/1379: "-n doesn't
+	behave properly when used with recursive targets".
+
+1999-10-08  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/targetvars: Add a check for PR/1378:
+	"Target-specific vars don't inherit correctly"
+
+1999-09-29  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (get_osname): Change $fancy_file_names to
+	$short_filenames and reverse the logic.
+	(run_each_test): Change test of non-existent $port_host to use
+	$short_filenames--problem reported by Eli Zaretskii.
+
+1999-09-23  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/parallelism: Add a check to ensure that the
+	jobserver works when we re-invoke.  Also cleaned up the tests a
+	little, reducing the number of rules we use so the test won't need
+	as many "sleep" commands.
+
+1999-09-16  Paul D. Smith  <psmith@gnu.org>
+
+	* scripts/features/reinvoke: Remove invocations of "touch" in
+	makefiles.  See the comments on the touch function rewrite below.
+	Note that UNIX touch behaves the same way if the file already
+	exists: it sets the time to the _local_ time.  We don't want
+	this.  This is probably a good tip for makefile writers in
+	general, actually... where practical.
+	* scripts/options/dash-l: Ditto.
+	* scripts/options/dash-n: Ditto.
+
+	* test_driver.pl (run_each_test): In retrospect, I don't like the
+	.lN/.bN/.dN postfix required by DOS.  So, for non-DOS systems I
+	changed it back to use .log, .base, and .diff.
+
+	* run_make_tests.pl (set_more_defaults): Move the check for the
+	make pathname to here from set_defaults (that's too early since it
+	happens before the command line processing).
+	Create a new variable $port_type, calculated from $osname, to
+	specify what kind of system we're running on.  We should integrate
+	the VOS stuff here, too.
+	(valid_option): Comment out the workdir/-work stuff so people
+	won't be fooled into thinking it works... someone needs to fix
+	this, though!
+
+	* scripts/functions/origin: Use $port_type instead of $osname.
+	* scripts/functions/foreach: Ditto.
+	* scripts/features/default_names: Ditto.
+
+1999-09-15  Paul D. Smith  <psmith@gnu.org>
+
+	* test_driver.pl (touch): Rewrite this function.  Previously it
+	used to use utime() to hard-set the time based on the current
+	local clock, or, if the file didn't exist, it merely created it.
+	This mirrors exactly what real UNIX touch does, but it fails badly
+	on networked filesystems where the FS server clock is skewed from
+	the local clock: normally modifying a file causes it to get a mod
+	time based on the _server's_ clock.  Hard-setting it based on the
+	_local_ clock causes gratuitous errors and makes the tests
+	unreliable except on local filesystems.  The new function will
+	simply modify the file, allowing the filesystem to set the mod
+	time as it sees fit.
+
+	* scripts/features/parallelism: The second test output could
+	change depending on how fast some scripts completed; use "sleep"
+	to force the order we want.
+
+	* test_driver.pl (toplevel): A bug in Perl 5.000 to Perl 5.004
+	means that "%ENV = ();" doesn't do the right thing.  This worked
+	in Perl 4 and was fixed in Perl 5.004_01, but use a loop to delete
+	the environment rather than require specific versions.
+
+	* run_make_tests.pl (set_more_defaults): Don't use Perl 5 s///
+	modifier "s", so the tests will run with Perl 4.
+	(set_more_defaults): Set $pure_log to empty if there's no -logfile
+	option in PURIFYOPTIONS.
+	(setup_for_test): Don't remove any logs unless $pure_log is set.
+
+1999-09-15  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* scripts/features/reinvoke: Put the SHELL definition in the right
+	test makefile.
+
+1999-09-15  Paul D. Smith  <psmith@gnu.org>
+
+	ChangeLog file for the test suite created.
+
+
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/tests/NEWS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/NEWS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/NEWS	(revision 1780)
@@ -0,0 +1,180 @@
+Changes from 0.4.9 to 3.78 (Sep 6, 1999):
+
+    Lots of new tests.  Renamed to follow the GNU make scheme.  Also
+    added some support for using Purify with make.
+
+    Rob Tulloh contributed some changes to get the test suite running on
+    NT; I tweaked them a bit (hopefully I didn't break anything!)  Note
+    that NT doesn't grok the self-exec funkiness that Unix shells use,
+    so instead I broke that out into a separate shell script
+    "run_make_tests" that invokes perl with the (renamed) script
+    run_make_tests.pl.
+
+    Eli Zaretski contributed changes to get the test suite running on
+    DOS with DJGPP.  I also meddled in these somewhat.
+
+    If you're on DOS or NT you should run "perl.exe run_make_tests.pl ..."
+    If you're on Unix, you can continue to run "./run_make_tests ..." as
+    before.
+
+Changes from 0.4.8 to 0.4.9 (May 14, 1998):
+
+    Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to
+    blame for problems in this version :).
+
+    Add some perl to test_driver.pl to strip out GNU make clock skew
+    warning messages from the output before comparing it to the
+    known-good output.
+
+    A new test for escaped :'s in filenames (someone on VMS found this
+    didn't work anymore in 3.77): scripts/features/escape.
+
+Changes from 0.4.7 to 0.4.8 (May 14, 1998):
+
+    Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to
+    blame for problems in this version :).
+
+    New tests for features to be included in GNU make 3.77.
+
+Changes from 0.4.6 to 0.4.7 (August 18, 1997):
+
+    Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to
+    blame for problems in this version :).
+
+    Reworked some tests to make sure they all work with both perl4 and perl5.
+
+    Work around a bug in perl 5.004 which doesn't clean the environment
+    correctly in all cases (fixed in at least 5.004_02).
+
+    Updated functions/strip to test for newline stripping.
+
+    Keep a $PURIFYOPTIONS env variable if present.
+
+Changes from 0.4.5 to 0.4.6 (April 07, 1997):
+
+    Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to
+    blame for problems in this version :).
+
+    Updated to work with GNU make 3.76 (and pretests).
+
+    Added new tests and updated existing ones.  Note that the new tests
+    weren't tested with perl 4, however I think they should work.
+
+    Ignore any tests whose filenames end in "~", so that Emacs backup
+    files aren't run.
+
+Changes from 0.4.4 to 0.4.5 (April 29, 1995):
+
+    Updated to be compatible with perl 5.001 as well as 4.036.
+
+    Note: the test suite still won't work on 14-char filesystems
+    (sorry, Kaveh), but I will get to it.
+
+    Also, some tests and stuff still haven't made it in because I
+    haven't had time to write the test scripts for them.  But they,
+    too, will get in eventually.  Contributions of scripts (ie, tests
+    that I can just drop in) are particularly welcome and will be
+    incorporated immediately.
+
+Changes from 0.4.3 to 0.4.4 (March 1995):
+
+    Updated for changes in make 3.72.12, and to ignore CVS directories
+    (thanks go to Jim Meyering for the patches for this).
+
+    Fixed uname call to not make a mess on BSD/OS 2.0 (whose uname -a
+    is very verbose).  Let me know if this doesn't work correctly on
+    your system.
+
+    Changed to display test name while it is running, not just when it
+    finishes.
+
+    Note: the test suite still won't work on 14-char filesystems
+    (sorry, Kaveh), but I will get to it.
+
+    Also, some tests and stuff still haven't made it in because I
+    haven't had time to write the test scripts for them.  But they,
+    too, will get in eventually.
+
+Changes from 0.4 to 0.4.3 (October 1994):
+
+    Fixed bugs (like dependencies on environment variables).
+
+    Caught up with changes in make.
+
+    The load_limit test should now silently ignore a failure due to
+    make not being able to read /dev/kmem.
+
+    Reorganized tests into subdirs and renamed lots of things so that
+    those poor souls who still have to deal with 14-char filename
+    limits won't hate me any more.  Thanks very much to Kaveh R. Ghazi
+    <ghazi@noc.rutgers.edu> for helping me with the implementation and
+    testing of these changes, and for putting up with all my whining
+    about it...
+
+    Added a $| = 1 so that systems that don't seem to automatically
+    flush their output for some reason will still print all the
+    output.  I'd hate for someone to miss out on the smiley that
+    you're supposed to get when all the tests pass... :-)
+
+Changes from 0.3 to 0.4 (August 1993):
+
+    Lost in the mists of time (and my hurry to get it out before I
+    left my job).
+
+Changes from 0.2 to 0.3 (9-30-92):
+
+    Several tests fixed to match the fact that MAKELEVEL > 0 or -C now
+    imply -w.
+
+    parallel_execution test fixed to not use double colon rules any
+    more since their behavior has changed.
+
+    errors_in_commands test fixed to handle different error messages
+    and return codes from rm.
+
+    Several tests fixed to handle -make_path with a relative path
+    and/or a name other than "make" for make.
+
+    dash-e-option test fixed to use $PATH instead of $USER (since the
+    latter does not exist on some System V systems).  This also
+    removes the dependency on getlogin (which fails under certain
+    weird conditions).
+
+    test_driver_core changed so that you can give a test name like
+    scripts/errors_in_commands and it will be handled correctly (handy
+    if you have a shell with filename completion).
+
+Changes from 0.1 to 0.2 (5-4-92):
+
+    README corrected to require perl 4.019, not 4.010.
+
+    -make_path replaces -old.
+
+    errors_in_commands test updated for change in format introduced in
+    make 3.62.6.
+
+    test_driver_core now uses a better way of figuring what OS it is
+    running on (thanks to meyering@cs.utexas.edu (Jim Meyering) for
+    suggesting this, as well as discovering the hard way that the old
+    way (testing for /mnt) fails on his machine).
+
+    Some new tests were added.
+
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/tests/README
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/README	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/README	(revision 1780)
@@ -0,0 +1,103 @@
+The test suite was originally written by Steve McGee and Chris Arthur.
+It is covered by the GNU General Public License (Version 2), described
+in the file COPYING.  It has been maintained as part of GNU make proper
+since GNU make 3.78.
+
+This entire test suite, including all test files, are copyright and
+distributed under the following terms:
+
+ -----------------------------------------------------------------------------
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ This file is part of GNU Make.
+
+ GNU Make is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+
+ GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Make; see the file COPYING.  If not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ -----------------------------------------------------------------------------
+
+The test suite requires Perl.  These days, you should have at least Perl
+5.004 (available from ftp.gnu.org, and portable to many machines).  It
+used to work with Perl 4.036 but official support for Perl 4.x was
+abandoned a long time ago, due to lack of testbeds, as well as interest.
+
+The test suite assumes that the first "diff" it finds on your PATH is
+GNU diff, but that only matters if a test fails.
+
+To run the test suite on a UNIX system, use "perl ./run_make_tests"
+(or just "./run_make_tests" if you have a perl on your PATH).
+
+To run the test suite on Windows NT or DOS systems, use
+"perl.exe ./run_make-tests.pl".
+
+By default, the test engine picks up the first executable called "make"
+that it finds in your path.  You may use the -make_path option (ie,
+"perl run_make_tests -make_path /usr/local/src/make-3.78/make") if
+you want to run a particular copy.  This now works correctly with
+relative paths and when make is called something other than "make" (like
+"gmake").
+
+Tests cannot end with a "~" character, as the test suite will ignore any
+that do (I was tired of having it run my Emacs backup files as tests :))
+
+Also, sometimes the tests may behave strangely on networked
+filesystems.  You can use mkshadow to create a copy of the test suite in
+/tmp or similar, and try again.  If the error disappears, it's an issue
+with your network or file server, not GNU make (I believe).  This
+shouldn't happen very often anymore: I've done a lot of work on the
+tests to reduce the impacts of this situation.
+
+The options/dash-l test will not really test anything if the copy of
+make you are using can't obtain the system load.  Some systems require
+make to be setgid sys or kmem for this; if you don't want to install
+make just to test it, make it setgid to kmem or whatever group /dev/kmem
+is (ie, "chgrp kmem make;chmod g+s make" as root).  In any case, the
+options/dash-l test should no longer *fail* because make can't read
+/dev/kmem.
+
+A directory named "work" will be created when the tests are run which
+will contain any makefiles and "diff" files of tests that fail so that
+you may look at them afterward to see the output of make and the
+expected result.
+
+There is a -help option which will give you more information about the
+other possible options for the test suite.
+
+
+Open Issues
+-----------
+
+The test suite has a number of problems which should be addressed.  One
+VERY serious one is that there is no real documentation.  You just have
+to see the existing tests.  Use the newer tests: many of the tests
+haven't been updated to use the latest/greatest test methods.  See the
+ChangeLog in the tests directory for pointers.
+
+The second serious problem is that it's not parallelizable: it scribbles
+all over its installation directory and so can only test one make at a
+time.  The third serious problem is that it's not relocatable: the only
+way it works when you build out of the source tree is to create
+symlinks, which doesn't work on every system and is bogus to boot.  The
+fourth serious problem is that it doesn't create its own sandbox when
+running tests, so that if a test forgets to clean up after itself that
+can impact future tests.
+
+
+Bugs
+----
+
+Any complaints/suggestions/bugs/etc. for the test suite itself (as
+opposed to problems in make that the suite finds) should be handled the
+same way as normal GNU make bugs/problems (see the README for GNU make).
+
+
+                                                Paul D. Smith
+						Chris Arthur
Index: /tags/kBuild-0.1.4/src/kmk/tests/mkshadow
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/mkshadow	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/mkshadow	(revision 1780)
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# Simple script to make a "shadow" test directory, using symbolic links.
+# Typically you'd put the shadow in /tmp or another local disk
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+case "$1" in
+  "") echo 'Usage: mkshadow <destdir>'; exit 1 ;;
+esac
+
+dest="$1"
+
+if [ ! -d "$dest" ]; then
+  echo "Destination directory \`$dest' must exist!"
+  exit 1
+fi
+
+if [ ! -f run_make_tests ]; then
+  echo "The current directory doesn't appear to contain the test suite!"
+  exit 1
+fi
+
+suite=`pwd | sed 's%^/tmp_mnt%%'`
+name=`basename "$suite"`
+
+files=`echo *`
+
+set -e
+
+mkdir "$dest/$name"
+cd "$dest/$name"
+
+ln -s "$suite" .testdir
+
+for f in $files; do
+  ln -s .testdir/$f .
+done
+
+rm -rf work
+
+echo "Shadow test suite created in \`$dest/$name'."
+exit 0
Index: /tags/kBuild-0.1.4/src/kmk/tests/run_make_tests
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/run_make_tests	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/run_make_tests	(revision 1780)
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec perl $0.pl ${1+"$@"}
Index: /tags/kBuild-0.1.4/src/kmk/tests/run_make_tests.pl
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/run_make_tests.pl	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/run_make_tests.pl	(revision 1780)
@@ -0,0 +1,355 @@
+#!/usr/bin/env perl
+# -*-perl-*-
+
+# Test driver for the Make test suite
+
+# Usage:  run_make_tests  [testname]
+#                         [-debug]
+#                         [-help]
+#                         [-verbose]
+#                         [-keep]
+#                         [-make <make prog>]
+#                        (and others)
+
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$valgrind = 0;              # invoke make with valgrind
+$valgrind_args = '--num-callers=15 --tool=memcheck --leak-check=full';
+$pure_log = undef;
+
+require "test_driver.pl";
+
+# Some target systems might not have the POSIX module...
+$has_POSIX = eval { require "POSIX.pm" };
+
+#$SIG{INT} = sub { print STDERR "Caught a signal!\n"; die @_; };
+
+sub valid_option
+{
+   local($option) = @_;
+
+   if ($option =~ /^-make([-_]?path)?$/)
+   {
+      $make_path = shift @argv;
+      if (!-f $make_path)
+      {
+	 print "$option $make_path: Not found.\n";
+	 exit 0;
+      }
+      return 1;
+   }
+
+   if ($option =~ /^-valgrind$/i) {
+     $valgrind = 1;
+     return 1;
+   }
+
+# This doesn't work--it _should_!  Someone badly needs to fix this.
+#
+#   elsif ($option =~ /^-work([-_]?dir)?$/)
+#   {
+#      $workdir = shift @argv;
+#      return 1;
+#   }
+
+   return 0;
+}
+
+
+# This is an "all-in-one" function.  Arguments are as follows:
+#
+#  [0] (string):  The makefile to be tested.  undef means use the last one.
+#  [1] (string):  Arguments to pass to make.
+#  [2] (string):  Answer we should get back.
+#  [3] (integer): Exit code we expect.  A missing code means 0 (success)
+
+$old_makefile = undef;
+
+sub run_make_test
+{
+  local ($makestring, $options, $answer, $err_code) = @_;
+
+  # If the user specified a makefile string, create a new makefile to contain
+  # it.  If the first value is not defined, use the last one (if there is
+  # one).
+
+  if (! defined $makestring) {
+    defined $old_makefile
+      || die "run_make_test(undef) invoked before run_make_test('...')\n";
+    $makefile = $old_makefile;
+  } else {
+    if (! defined($makefile)) {
+      $makefile = &get_tmpfile();
+    }
+
+    # Make sure it ends in a newline.
+    $makestring && $makestring !~ /\n$/s and $makestring .= "\n";
+
+    # Replace @MAKEFILE@ with the makefile name and @MAKE@ with the path to
+    # make
+    $makestring =~ s/#MAKEFILE#/$makefile/g;
+    $makestring =~ s/#MAKEPATH#/$mkpath/g;
+    $makestring =~ s/#MAKE#/$make_name/g;
+    $makestring =~ s/#PWD#/$pwd/g;
+
+    # Populate the makefile!
+    open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n";
+    print MAKEFILE $makestring;
+    close(MAKEFILE) || die "Failed to write $makefile: $!\n";
+  }
+
+  # Do the same processing on $answer as we did on $makestring.
+
+  $answer && $answer !~ /\n$/s and $answer .= "\n";
+  $answer =~ s/#MAKEFILE#/$makefile/g;
+  $answer =~ s/#MAKEPATH#/$mkpath/g;
+  $answer =~ s/#MAKE#/$make_name/g;
+  $answer =~ s/#PWD#/$pwd/g;
+
+  &run_make_with_options($makefile, $options, &get_logfile(0), $err_code);
+  &compare_output($answer, &get_logfile(1));
+
+  $old_makefile = $makefile;
+  $makefile = undef;
+}
+
+# The old-fashioned way...
+sub run_make_with_options {
+  local ($filename,$options,$logname,$expected_code) = @_;
+  local($code);
+  local($command) = $make_path;
+
+  $expected_code = 0 unless defined($expected_code);
+
+  # Reset to reflect this one test.
+  $test_passed = 1;
+
+  if ($filename) {
+    $command .= " -f $filename";
+  }
+
+  if ($options) {
+    $command .= " $options";
+  }
+
+  if ($valgrind) {
+    print VALGRIND "\n\nExecuting: $command\n";
+  }
+
+  $code = &run_command_with_output($logname,$command);
+
+  # Check to see if we have Purify errors.  If so, keep the logfile.
+  # For this to work you need to build with the Purify flag -exit-status=yes
+
+  if ($pure_log && -f $pure_log) {
+    if ($code & 0x7000) {
+      $code &= ~0x7000;
+
+      # If we have a purify log, save it
+      $tn = $pure_testname . ($num_of_logfiles ? ".$num_of_logfiles" : "");
+      print("Renaming purify log file to $tn\n") if $debug;
+      rename($pure_log, "$tn")
+        || die "Can't rename $log to $tn: $!\n";
+      ++$purify_errors;
+    } else {
+      unlink($pure_log);
+    }
+  }
+
+  if ($code != $expected_code) {
+    print "Error running $make_path (expected $expected_code; got $code): $command\n";
+    $test_passed = 0;
+    # If it's a SIGINT, stop here
+    if ($code & 127) {
+      print STDERR "\nCaught signal ".($code & 127)."!\n";
+      exit($code);
+    }
+    return 0;
+  }
+
+  if ($profile & $vos) {
+    system "add_profile $make_path";
+  }
+
+  1;
+}
+
+sub print_usage
+{
+   &print_standard_usage ("run_make_tests",
+                          "[-make_path make_pathname] [-valgrind]",);
+}
+
+sub print_help
+{
+   &print_standard_help ("-make_path",
+          "\tYou may specify the pathname of the copy of make to run.");
+}
+
+sub get_this_pwd {
+  $delete_command = 'rm -f';
+  if ($has_POSIX) {
+    $__pwd = POSIX::getcwd();
+  } elsif ($vos) {
+    $delete_command = "delete_file -no_ask";
+    $__pwd = `++(current_dir)`;
+  } else {
+    # No idea... just try using pwd as a last resort.
+    chop ($__pwd = `pwd`);
+  }
+
+  return $__pwd;
+}
+
+sub set_defaults
+{
+   # $profile = 1;
+   $testee = "GNU make";
+   $make_path = "make";
+   $tmpfilesuffix = "mk";
+   $pwd = &get_this_pwd;
+}
+
+sub set_more_defaults
+{
+   local($string);
+   local($index);
+
+   # find the type of the port.  We do this up front to have a single
+   # point of change if it needs to be tweaked.
+   #
+   # This is probably not specific enough.
+   #
+   if ($osname =~ /Windows/i || $osname =~ /MINGW32/i || $osname =~ /CYGWIN_NT/i) {
+     $port_type = 'W32';
+   }
+   # Bleah, the osname is so variable on DOS.  This kind of bites.
+   # Well, as far as I can tell if we check for some text at the
+   # beginning of the line with either no spaces or a single space, then
+   # a D, then either "OS", "os", or "ev" and a space.  That should
+   # match and be pretty specific.
+   elsif ($osname =~ /^([^ ]*|[^ ]* [^ ]*)D(OS|os|ev) /) {
+     $port_type = 'DOS';
+   }
+   # Check for OS/2
+   elsif ($osname =~ m%OS/2%) {
+     $port_type = 'OS/2';
+   }
+   # Everything else, right now, is UNIX.  Note that we should integrate
+   # the VOS support into this as well and get rid of $vos; we'll do
+   # that next time.
+   else {
+     $port_type = 'UNIX';
+   }
+
+   # On DOS/Windows system the filesystem apparently can't track
+   # timestamps with second granularity (!!).  Change the sleep time
+   # needed to force a file to be considered "old".
+   $wtime = $port_type eq 'UNIX' ? 1 : $port_type eq 'OS/2' ? 2 : 4;
+
+   print "Port type: $port_type\n" if $debug;
+   print "Make path: $make_path\n" if $debug;
+
+   # Find the full pathname of Make.  For DOS systems this is more
+   # complicated, so we ask make itself.
+   my $mk = `sh -c 'echo "all:;\@echo \\\$(MAKE)" | $make_path -f-'`;
+   chop $mk;
+   $mk or die "FATAL ERROR: Cannot determine the value of \$(MAKE):\n
+'echo \"all:;\@echo \\\$(MAKE)\" | $make_path -f-' failed!\n";
+   $make_path = $mk;
+   print "Make\t= `$make_path'\n" if $debug;
+
+   $string = `$make_path -v -f /dev/null 2> /dev/null`;
+
+   $string =~ /^(GNU Make [^,\n]*)/;
+   $testee_version = "$1\n";
+
+   $string = `sh -c "$make_path -f /dev/null 2>&1"`;
+   if ($string =~ /(.*): \*\*\* No targets\.  Stop\./) {
+     $make_name = $1;
+   }
+   else {
+     if ($make_path =~ /$pathsep([^\n$pathsep]*)$/) {
+       $make_name = $1;
+     }
+     else {
+       $make_name = $make_path;
+     }
+   }
+
+   # prepend pwd if this is a relative path (ie, does not
+   # start with a slash, but contains one).  Thanks for the
+   # clue, Roland.
+
+   if (index ($make_path, ":") != 1 && index ($make_path, "/") > 0)
+   {
+      $mkpath = "$pwd$pathsep$make_path";
+   }
+   else
+   {
+      $mkpath = $make_path;
+   }
+
+   # Get Purify log info--if any.
+
+   if (exists $ENV{PURIFYOPTIONS}
+       && $ENV{PURIFYOPTIONS} =~ /.*-logfile=([^ ]+)/) {
+     $pure_log = $1 || '';
+     $pure_log =~ s/%v/$make_name/;
+     $purify_errors = 0;
+   }
+
+   $string = `sh -c "$make_path -j 2 -f /dev/null 2>&1"`;
+   if ($string =~ /not supported/) {
+     $parallel_jobs = 0;
+   }
+   else {
+     $parallel_jobs = 1;
+   }
+
+   # Set up for valgrind, if requested.
+
+   if ($valgrind) {
+     open(VALGRIND, "> valgrind.out")
+       || die "Cannot open valgrind.out: $!\n";
+     #  -q --leak-check=yes
+     exists $ENV{VALGRIND_ARGS} and $valgrind_args = $ENV{VALGRIND_ARGS};
+     $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $valgrind_args $make_path";
+     # F_SETFD is 2
+     fcntl(VALGRIND, 2, 0) or die "fcntl(setfd) failed: $!\n";
+     system("echo Starting on `date` 1>&".fileno(VALGRIND));
+     print "Enabled valgrind support.\n";
+   }
+}
+
+sub setup_for_test
+{
+  $makefile = &get_tmpfile;
+  if (-f $makefile) {
+    unlink $makefile;
+  }
+
+  # Get rid of any Purify logs.
+  if ($pure_log) {
+    ($pure_testname = $testname) =~ tr,/,_,;
+    $pure_testname = "$pure_log.$pure_testname";
+    system("rm -f $pure_testname*");
+    print("Purify testfiles are: $pure_testname*\n") if $debug;
+  }
+}
+
+exit !&toplevel;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/comments
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/comments	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/comments	(revision 1780)
@@ -0,0 +1,35 @@
+$description = "The following test creates a makefile to test comments\n"
+              ."and comment continuation to the next line using a \n"
+              ."backslash within makefiles.";
+
+$details = "To test comments within a makefile, a semi-colon was placed \n"
+          ."after a comment was started.  This should not be reported as\n"
+          ."an error since it is within a comment.  We then continue the \n"
+          ."comment to the next line using a backslash.  To test whether\n"
+          ."the comment really continued, we place an echo command with some\n"
+          ."text on the line which should never execute since it should be \n"
+          ."within a comment\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<\EOF;
+# Test comment vs semicolon parsing and line continuation
+target: # this ; is just a comment \
+	@echo This is within a comment. 
+	@echo There should be no errors for this makefile.
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "There should be no errors for this makefile.\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer,&get_logfile(1))
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/conditionals
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/conditionals	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/conditionals	(revision 1780)
@@ -0,0 +1,146 @@
+#                                                                    -*-perl-*-
+$description = "Check GNU make conditionals.";
+
+$details = "Attempt various different flavors of GNU make conditionals.";
+
+run_make_test('
+arg1 = first
+arg2 = second
+arg3 = third
+arg4 = cc
+arg5 = second
+
+all:
+ifeq ($(arg1),$(arg2))
+	@echo arg1 equals arg2
+else
+	@echo arg1 NOT equal arg2
+endif
+
+ifeq \'$(arg2)\' "$(arg5)"
+	@echo arg2 equals arg5
+else
+	@echo arg2 NOT equal arg5
+endif
+
+ifneq \'$(arg3)\' \'$(arg4)\'
+	@echo arg3 NOT equal arg4
+else
+	@echo arg3 equal arg4
+endif
+
+ifndef undefined
+	@echo variable is undefined
+else
+	@echo variable undefined is defined
+endif
+ifdef arg4
+	@echo arg4 is defined
+else
+	@echo arg4 is NOT defined
+endif',
+              '',
+              'arg1 NOT equal arg2
+arg2 equals arg5
+arg3 NOT equal arg4
+variable is undefined
+arg4 is defined');
+
+
+# Test expansion of variables inside ifdef.
+
+run_make_test('
+foo = 1
+
+FOO = foo
+F = f
+
+DEF = no
+DEF2 = no
+
+ifdef $(FOO)
+DEF = yes
+endif
+
+ifdef $(F)oo
+DEF2 = yes
+endif
+
+
+DEF3 = no
+FUNC = $1
+ifdef $(call FUNC,DEF)3
+  DEF3 = yes
+endif
+
+all:; @echo DEF=$(DEF) DEF2=$(DEF2) DEF3=$(DEF3)',
+              '',
+              'DEF=yes DEF2=yes DEF3=yes');
+
+
+# Test all the different "else if..." constructs
+
+run_make_test('
+arg1 = first
+arg2 = second
+arg3 = third
+arg4 = cc
+arg5 = fifth
+
+result =
+
+ifeq ($(arg1),$(arg2))
+  result += arg1 equals arg2
+else ifeq \'$(arg2)\' "$(arg5)"
+  result += arg2 equals arg5
+else ifneq \'$(arg3)\' \'$(arg3)\'
+  result += arg3 NOT equal arg4
+else ifndef arg5
+  result += variable is undefined
+else ifdef undefined
+  result += arg4 is defined
+else
+  result += success
+endif
+
+
+all: ; @echo $(result)',
+              '',
+              'success');
+
+
+# Test some random "else if..." construct nesting
+
+run_make_test('
+arg1 = first
+arg2 = second
+arg3 = third
+arg4 = cc
+arg5 = second
+
+ifeq ($(arg1),$(arg2))
+  $(info failed 1)
+else ifeq \'$(arg2)\' "$(arg2)"
+  ifdef undefined
+    $(info failed 2)
+  else
+    $(info success)
+  endif
+else ifneq \'$(arg3)\' \'$(arg3)\'
+  $(info failed 3)
+else ifdef arg5
+  $(info failed 4)
+else ifdef undefined
+  $(info failed 5)
+else
+  $(info failed 6)
+endif
+
+.PHONY: all
+all: ; @:',
+              '',
+              'success');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/default_names
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/default_names	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/default_names	(revision 1780)
@@ -0,0 +1,41 @@
+#                                                                    -*-perl-*-
+
+$description = "This script tests to make sure that Make looks for
+default makefiles in the correct order (GNUmakefile,makefile,Makefile)";
+
+# Create a makefile called "GNUmakefile"
+$makefile = "GNUmakefile";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE "FIRST: ; \@echo It chose GNUmakefile\n";
+close(MAKEFILE);
+
+# DOS/WIN32 platforms preserve case, but Makefile is the same file as makefile.
+# Just test what we can here (avoid Makefile versus makefile test).
+
+if ($port_type eq 'UNIX') {
+  # Create another makefile called "makefile"
+  open(MAKEFILE,"> makefile");
+  print MAKEFILE "SECOND: ; \@echo It chose makefile\n";
+  close(MAKEFILE);
+}
+
+# Create another makefile called "Makefile"
+open(MAKEFILE,"> Makefile");
+print MAKEFILE "THIRD: ; \@echo It chose Makefile\n";
+close(MAKEFILE);
+
+
+&run_make_with_options("","",&get_logfile);
+&compare_output("It chose GNUmakefile\n",&get_logfile(1));
+unlink $makefile;
+
+if ($port_type eq 'UNIX') {
+  &run_make_with_options("","",&get_logfile);
+  &compare_output("It chose makefile\n",&get_logfile(1));
+  unlink "makefile";
+}
+
+&run_make_with_options("","",&get_logfile);
+&compare_output("It chose Makefile\n",&get_logfile(1));
+unlink "Makefile";
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/double_colon
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/double_colon	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/double_colon	(revision 1780)
@@ -0,0 +1,155 @@
+#                                                                    -*-perl-*-
+$description = "Test handling of double-colon rules.";
+
+$details = "\
+We test these features:
+
+  - Multiple commands for the same (double-colon) target
+  - Different prerequisites for targets: only out-of-date
+    ones are rebuilt.
+  - Double-colon targets that aren't the goal target.
+
+Then we do the same thing for parallel builds: double-colon
+targets should always be built serially.";
+
+# The Contents of the MAKEFILE ...
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+
+all: baz
+
+foo:: f1.h ; @echo foo FIRST
+foo:: f2.h ; @echo foo SECOND
+
+bar:: ; @echo aaa; sleep 1; echo aaa done
+bar:: ; @echo bbb
+
+baz:: ; @echo aaa
+baz:: ; @echo bbb
+
+biz:: ; @echo aaa
+biz:: two ; @echo bbb
+
+two: ; @echo two
+
+f1.h f2.h: ; @echo $@
+
+d :: ; @echo ok
+d :: d ; @echo oops
+
+EOF
+
+close(MAKEFILE);
+
+# TEST 0: A simple double-colon rule that isn't the goal target.
+
+&run_make_with_options($makefile, "all", &get_logfile, 0);
+$answer = "aaa\nbbb\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 1: As above, in parallel
+
+if ($parallel_jobs) {
+  &run_make_with_options($makefile, "-j10 all", &get_logfile, 0);
+  $answer = "aaa\nbbb\n";
+  &compare_output($answer, &get_logfile(1));
+}
+
+# TEST 2: A simple double-colon rule that is the goal target
+
+&run_make_with_options($makefile, "bar", &get_logfile, 0);
+$answer = "aaa\naaa done\nbbb\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 3: As above, in parallel
+
+if ($parallel_jobs) {
+  &run_make_with_options($makefile, "-j10 bar", &get_logfile, 0);
+  $answer = "aaa\naaa done\nbbb\n";
+  &compare_output($answer, &get_logfile(1));
+}
+
+# TEST 4: Each double-colon rule is supposed to be run individually
+
+&utouch(-5, 'f2.h');
+&touch('foo');
+
+&run_make_with_options($makefile, "foo", &get_logfile, 0);
+$answer = "f1.h\nfoo FIRST\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 5: Again, in parallel.
+
+if ($parallel_jobs) {
+  &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
+  $answer = "f1.h\nfoo FIRST\n";
+  &compare_output($answer, &get_logfile(1));
+}
+
+# TEST 6: Each double-colon rule is supposed to be run individually
+
+&utouch(-5, 'f1.h');
+unlink('f2.h');
+&touch('foo');
+
+&run_make_with_options($makefile, "foo", &get_logfile, 0);
+$answer = "f2.h\nfoo SECOND\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 7: Again, in parallel.
+
+if ($parallel_jobs) {
+  &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
+  $answer = "f2.h\nfoo SECOND\n";
+  &compare_output($answer, &get_logfile(1));
+}
+
+# TEST 8: Test circular dependency check; PR/1671
+
+&run_make_with_options($makefile, "d", &get_logfile, 0);
+$answer = "ok\n$make_name: Circular d <- d dependency dropped.\noops\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 8: I don't grok why this is different than the above, but it is...
+#
+# Hmm... further testing indicates this might be timing-dependent?
+#
+#if ($parallel_jobs) {
+#  &run_make_with_options($makefile, "-j10 biz", &get_logfile, 0);
+#  $answer = "aaa\ntwo\nbbb\n";
+#  &compare_output($answer, &get_logfile(1));
+#}
+
+unlink('foo','f1.h','f2.h');
+
+
+# TEST 9: make sure all rules in s double colon family get executed
+#         (Savannah bug #14334).
+#
+
+&touch('one');
+&touch('two');
+
+run_make_test('
+.PHONY: all
+all: result
+
+result:: one
+	@echo $^ >>$@
+	@echo $^
+
+result:: two
+	@echo $^ >>$@
+	@echo $^
+
+',
+'',
+'one
+two');
+
+unlink('result','one','two');
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/echoing
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/echoing	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/echoing	(revision 1780)
@@ -0,0 +1,87 @@
+$description = "The following test creates a makefile to test command \n"
+              ."echoing.  It tests that when a command line starts with \n"
+              ."a '\@', the echoing of that line is suppressed.  It also \n"
+              ."tests the -n option which tells make to ONLY echo the  \n"
+              ."commands and no execution happens.  In this case, even \n"
+              ."the commands with '\@' are printed. Lastly, it tests the \n"
+              ."-s flag which tells make to prevent all echoing, as if \n"
+              ."all commands started with a '\@'.";
+
+$details = "This test is similar to the 'clean' test except that a '\@' has\n"
+          ."been placed in front of the delete command line.  Four tests \n"
+          ."are run here.  First, make is run normally and the first echo\n"
+          ."command should be executed.  In this case there is no '\@' so \n"
+          ."we should expect make to display the command AND display the \n"
+          ."echoed message.  Secondly, make is run with the clean target, \n"
+          ."but since there is a '\@' at the beginning of the command, we\n"
+          ."expect no output; just the deletion of a file which we check \n"
+          ."for.  Third, we give the clean target again except this time\n"
+          ."we give make the -n option.  We now expect the command to be \n"
+          ."displayed but not to be executed.  In this case we need only \n"
+          ."to check the output since an error message would be displayed\n"
+          ."if it actually tried to run the delete command again and the \n"
+          ."file didn't exist. Lastly, we run the first test again with \n"
+          ."the -s option and check that make did not echo the echo \n"
+          ."command before printing the message.";
+
+$example = "EXAMPLE_FILE";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "all: \n";
+print MAKEFILE "\techo This makefile did not clean the dir... good\n";
+print MAKEFILE "clean: \n";
+print MAKEFILE "\t\@$delete_command $example\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch($example);
+
+# TEST #1
+# -------
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+$answer = "echo This makefile did not clean the dir... good\n"
+         ."This makefile did not clean the dir... good\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2
+# -------
+
+&run_make_with_options($makefile,"clean",&get_logfile,0);
+if (-f $example) {
+  $test_passed = 0;
+}
+&compare_output('',&get_logfile(1));
+
+# TEST #3
+# -------
+
+&run_make_with_options($makefile,"-n clean",&get_logfile,0);
+$answer = "$delete_command $example\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #4
+# -------
+
+&run_make_with_options($makefile,"-s",&get_logfile,0);
+$answer = "This makefile did not clean the dir... good\n";
+&compare_output($answer,&get_logfile(1));
+
+
+1;
+
+
+
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/errors
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/errors	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/errors	(revision 1780)
@@ -0,0 +1,92 @@
+#                                                                    -*-perl-*-
+
+$description = "The following tests the -i option and the '-' in front of \n"
+              ."commands to test that make ignores errors in these commands\n"
+              ."and continues processing.";
+
+$details = "This test runs two makes.  The first runs on a target with a \n"
+          ."command that has a '-' in front of it (and a command that is \n"
+          ."intended to fail) and then a delete command after that is \n"
+          ."intended to succeed.  If make ignores the failure of the first\n"
+          ."command as it is supposed to, then the second command should \n"
+          ."delete a file and this is what we check for.  The second make\n"
+          ."that is run in this test is identical except that the make \n"
+          ."command is given with the -i option instead of the '-' in \n"
+          ."front of the command.  They should run the same. ";
+
+if ($vos)
+{
+   $rm_command = "delete_file";
+}
+else
+{
+   $rm_command = "rm";
+}
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "clean:\n"
+              ."\t-$rm_command cleanit\n"
+              ."\t$rm_command foo\n"
+	      ."clean2: \n"
+              ."\t$rm_command cleanit\n"
+              ."\t$rm_command foo\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch("foo");
+
+unlink("cleanit");
+$cleanit_error = `sh -c "$rm_command cleanit 2>&1"`;
+$delete_error_code = $? >> 8;
+
+# TEST #1
+# -------
+
+$answer = "$rm_command cleanit\n"
+         . $cleanit_error
+         ."$make_name: [clean] Error $delete_error_code (ignored)\n"
+         ."$rm_command foo\n";
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# If make acted as planned, it should ignore the error from the first
+# command in the target and execute the second which deletes the file "foo"
+# This file, therefore, should not exist if the test PASSES.
+if (-f "foo") {
+  $test_passed = 0;
+}
+
+# The output for this on VOS is too hard to replicate, so we only check it
+# on unix.
+if (!$vos)
+{
+   &compare_output($answer,&get_logfile(1));
+}
+
+
+&touch("foo");
+
+# TEST #2
+# -------
+
+$answer = "$rm_command cleanit\n"
+         . $cleanit_error
+         ."$make_name: [clean2] Error $delete_error_code (ignored)\n"
+         ."$rm_command foo\n";
+
+&run_make_with_options($makefile,"clean2 -i",&get_logfile);
+
+if (-f "foo") {
+  $test_passed = 0;
+}
+
+if (!$vos) {
+   &compare_output($answer,&get_logfile(1));
+}
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/escape
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/escape	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/escape	(revision 1780)
@@ -0,0 +1,58 @@
+#                                                                    -*-perl-*-
+$description = "Test various types of escaping in makefiles.";
+
+$details = "\
+Make sure that escaping of `:' works in target names.
+Make sure escaping of whitespace works in target names.
+Make sure that escaping of '#' works.";
+
+
+close(MAKEFILE);
+
+
+# TEST 1
+
+run_make_test('
+$(path)foo : ; @echo "touch ($@)"
+
+foo\ bar: ; @echo "touch ($@)"
+
+sharp: foo\#bar.ext
+foo\#bar.ext: ; @echo "foo#bar.ext = ($@)"',
+	      '',
+	      'touch (foo)');
+
+# TEST 2: This one should fail, since the ":" is unquoted.
+
+run_make_test(undef,
+	      'path=pre:',
+	      "#MAKEFILE#:2: *** target pattern contains no `%'.  Stop.",
+	      512);
+
+# TEST 3: This one should work, since we escape the ":".
+
+run_make_test(undef,
+	      "'path=pre\\:'",
+	      'touch (pre:foo)');
+
+# TEST 4: This one should fail, since the escape char is escaped.
+
+run_make_test(undef,
+	      "'path=pre\\\\:'",
+	      "#MAKEFILE#:2: *** target pattern contains no `%'.  Stop.",
+	      512);
+
+# TEST 5: This one should work
+
+run_make_test(undef,
+	      "'foo bar'",
+	      'touch (foo bar)');
+
+# TEST 6: Test escaped comments
+
+run_make_test(undef,
+	      'sharp',
+	      'foo#bar.ext = (foo#bar.ext)');
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/export
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/export	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/export	(revision 1780)
@@ -0,0 +1,246 @@
+#                                                                    -*-perl-*-
+$description = "Check GNU make export/unexport commands.";
+
+$details = "";
+
+# The test driver cleans out our environment for us so we don't have to worry
+# about that here.
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOMAKE';
+
+FOO = foo
+BAR = bar
+BOZ = boz
+
+export BAZ = baz
+export BOZ
+
+BITZ = bitz
+BOTZ = botz
+
+export BITZ BOTZ
+unexport BOTZ
+
+ifdef EXPORT_ALL
+export
+endif
+
+ifdef UNEXPORT_ALL
+unexport
+endif
+
+ifdef EXPORT_ALL_PSEUDO
+.EXPORT_ALL_VARIABLES:
+endif
+
+all:
+	@echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)"
+	@echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ"
+
+EOMAKE
+
+close(MAKEFILE);
+
+# TEST 0: basics
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# TEST 1: make sure vars inherited from the parent are exported
+
+$extraENV{FOO} = 1;
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# TEST 2: global export.  Explicit unexport takes precedence.
+
+&run_make_with_options($makefile,"EXPORT_ALL=1",&get_logfile,0);
+
+$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# TEST 3: global unexport.  Explicit export takes precedence.
+
+&run_make_with_options($makefile,"UNEXPORT_ALL=1",&get_logfile,0);
+
+$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# TEST 4: both: in the above makefile the unexport comes last so that rules.
+
+&run_make_with_options($makefile,"EXPORT_ALL=1 UNEXPORT_ALL=1",&get_logfile,0);
+
+$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# TEST 5: test the pseudo target.
+
+&run_make_with_options($makefile,"EXPORT_ALL_PSEUDO=1",&get_logfile,0);
+
+$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST 6: Test the expansion of variables inside export
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+
+print MAKEFILE <<'EOF';
+
+foo = f-ok
+bar = b-ok
+
+FOO = foo
+F = f
+
+BAR = bar
+B = b
+
+export $(FOO)
+export $(B)ar
+
+all:
+	@echo foo=$(foo) bar=$(bar)
+	@echo foo=$$foo bar=$$bar
+
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2,"",&get_logfile,0);
+$answer = "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST 7: Test the expansion of variables inside unexport
+
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile3");
+
+print MAKEFILE <<'EOF';
+
+foo = f-ok
+bar = b-ok
+
+FOO = foo
+F = f
+
+BAR = bar
+B = b
+
+export foo bar
+
+unexport $(FOO)
+unexport $(B)ar
+
+all:
+	@echo foo=$(foo) bar=$(bar)
+	@echo foo=$$foo bar=$$bar
+
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile3,"",&get_logfile,0);
+$answer = "foo=f-ok bar=b-ok\nfoo= bar=\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST 7: Test exporting multiple variables on the same line
+
+$makefile4 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile4");
+
+print MAKEFILE <<'EOF';
+
+A = a
+B = b
+C = c
+D = d
+E = e
+F = f
+G = g
+H = h
+I = i
+J = j
+
+SOME = A B C
+
+export F G H I J
+
+export D E $(SOME)
+
+all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile4,"",&get_logfile,0);
+$answer = "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST 8: Test unexporting multiple variables on the same line
+
+$makefile5 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile5");
+
+print MAKEFILE <<'EOF';
+
+A = a
+B = b
+C = c
+D = d
+E = e
+F = f
+G = g
+H = h
+I = i
+J = j
+
+SOME = A B C
+
+unexport F G H I J
+
+unexport D E $(SOME)
+
+all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J
+EOF
+
+close(MAKEFILE);
+
+@extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
+
+&run_make_with_options($makefile5,"",&get_logfile,0);
+$answer = "A= B= C= D= E= F= G= H= I= J=\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/include
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/include	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/include	(revision 1780)
@@ -0,0 +1,120 @@
+#                                     -*-mode: perl; rm-trailing-spaces: nil-*-
+
+$description = "Test various forms of the GNU make `include' command.";
+
+$details = "\
+Test include, -include, sinclude and various regressions involving them.
+Test extra whitespace at the end of the include, multiple -includes and
+sincludes (should not give an error) and make sure that errors are reported
+for targets that were also -included.";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+
+# The contents of the Makefile ...
+
+print MAKEFILE <<EOF;
+\#Extra space at the end of the following file name
+include $makefile2
+all: ; \@echo There should be no errors for this makefile.
+
+-include nonexistent.mk
+-include nonexistent.mk
+sinclude nonexistent.mk
+sinclude nonexistent-2.mk
+-include makeit.mk
+sinclude makeit.mk
+
+error: makeit.mk
+EOF
+
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE "ANOTHER: ; \@echo This is another included makefile\n";
+
+close(MAKEFILE);
+
+# Create the answer to what should be produced by this Makefile
+&run_make_with_options($makefile, "all", &get_logfile);
+$answer = "There should be no errors for this makefile.\n";
+&compare_output($answer, &get_logfile(1));
+
+&run_make_with_options($makefile, "ANOTHER", &get_logfile);
+$answer = "This is another included makefile\n";
+&compare_output($answer, &get_logfile(1));
+
+$makefile = undef;
+
+# Try to build the "error" target; this will fail since we don't know
+# how to create makeit.mk, but we should also get a message (even though
+# the -include suppressed it during the makefile read phase, we should
+# see one during the makefile run phase).
+
+run_make_test
+  ('
+-include foo.mk
+error: foo.mk ; @echo $@
+',
+   '',
+   "#MAKE#: *** No rule to make target `foo.mk', needed by `error'.  Stop.\n",
+   512
+  );
+
+# Make sure that target-specific variables don't impact things.  This could
+# happen because a file record is created when a target-specific variable is
+# set.
+
+run_make_test
+  ('
+bar.mk: foo := baz
+-include bar.mk
+hello: ; @echo hello
+',
+   '',
+   "hello\n"
+  );
+
+
+# Test inheritance of dontcare flag when rebuilding makefiles.
+#
+run_make_test('
+.PHONY: all
+all: ; @:
+
+-include foo
+
+foo: bar; @:
+', '', '');
+
+1;
+
+
+# Make sure that we don't die when the command fails but we dontcare.
+# (Savannah bug #13216).
+#
+run_make_test('
+.PHONY: all
+all:; @:
+
+-include foo
+
+foo: bar; @:
+
+bar:; @exit 1
+', '', '');
+
+# Check include, sinclude, -include with no filenames.
+# (Savannah bug #1761).
+
+run_make_test('
+.PHONY: all
+all:; @:
+include
+-include
+sinclude', '', '');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/mult_rules
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/mult_rules	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/mult_rules	(revision 1780)
@@ -0,0 +1,78 @@
+$description = "\
+The following test creates a makefile to test the presence
+of multiple rules for one target.  One file can be the
+target of several rules if at most one rule has commands;
+the other rules can only have dependencies.";
+
+$details = "\
+The makefile created in this test contains two hardcoded rules
+for foo.o and bar.o.  It then gives another multiple target rule
+with the same names as above but adding more dependencies.
+Additionally, another variable extradeps is listed as a
+dependency but is defined to be null.  It can however be defined
+on the make command line as extradeps=extra.h which adds yet
+another dependency to the targets.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOF;
+objects = foo.o bar.o
+foo.o : defs.h
+bar.o : defs.h test.h
+extradeps = 
+\$(objects) : config.h \$(extradeps) 
+\t\@echo EXTRA EXTRA
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch("defs.h","test.h","config.h");
+
+if ($vos)
+{
+   $error_code = 3307;
+}
+else 
+{
+   $error_code = 512;
+}
+
+&run_make_with_options($makefile,
+                       "extradeps=extra.h",
+                       &get_logfile,
+                       $error_code);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "$make_name: *** No rule to make target `extra.h', needed by `foo.o'.  Stop.\n";
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2
+# -------
+
+&touch("extra.h");
+
+&run_make_with_options($makefile,
+                       "extradeps=extra.h",
+                       &get_logfile,
+                       0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "EXTRA EXTRA\n";
+
+&compare_output($answer,&get_logfile(1));
+
+unlink("defs.h","test.h","config.h","extra.h");
+
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/mult_targets
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/mult_targets	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/mult_targets	(revision 1780)
@@ -0,0 +1,46 @@
+$description = "The following test creates a makefile to test that a \n "
+              ."rule with multiple targets is equivalent to writing \n"
+              ."many rules, each with one target, and all identical aside\n"
+              ."from that.";
+
+$details = "A makefile is created with one rule and two targets.  Make \n"
+          ."is called twice, once for each target, and the output which \n"
+          ."contains the target name with \$@ is looked at for the changes.\n"
+          ."This test also tests the substitute function by replacing \n"
+          ."the word output with nothing in the target name giving either\n"
+          ."an output of \"I am little\" or \"I am big\"";  
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "bigoutput littleoutput: test.h\n";
+print MAKEFILE "\t\@echo I am \$(subst output,,\$@)\n";  
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch("test.h");
+
+&run_make_with_options($makefile,"bigoutput",&get_logfile);
+
+
+# Create the answer to what should be produced by this Makefile
+$answer = "I am big\n";
+
+&compare_output($answer,&get_logfile(1));
+
+&run_make_with_options($makefile,"littleoutput",&get_logfile);
+$answer = "I am little\n";
+&compare_output($answer,&get_logfile(1));
+
+unlink "test.h";
+
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/order_only
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/order_only	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/order_only	(revision 1780)
@@ -0,0 +1,118 @@
+#                                                                    -*-perl-*-
+$description = "Test order-only prerequisites.";
+
+$details = "\
+Create makefiles with various combinations of normal and order-only
+prerequisites and ensure they behave properly.  Test the \$| variable.";
+
+# TEST #0 -- Basics
+
+run_make_test('
+%r: | baz ; @echo $< $^ $|
+bar: foo
+foo:;@:
+baz:;@:',
+              '', "foo foo baz\n");
+
+# TEST #1 -- First try: the order-only prereqs need to be built.
+
+run_make_test(q!
+foo: bar | baz
+	@echo '$$^ = $^'
+	@echo '$$| = $|'
+	touch $@
+
+.PHONY: baz
+
+bar baz:
+	touch $@!,
+              '', "touch bar\ntouch baz\n\$^ = bar\n\$| = baz\ntouch foo\n");
+
+
+# TEST #2 -- now we do it again: baz is PHONY but foo should _NOT_ be updated
+
+run_make_test(undef, '', "touch baz\n");
+
+unlink(qw(foo bar baz));
+
+# TEST #3 -- Make sure the order-only prereq was promoted to normal.
+
+run_make_test(q!
+foo: bar | baz
+	@echo '$$^ = $^'
+	@echo '$$| = $|'
+	touch $@
+
+foo: baz
+
+.PHONY: baz
+
+bar baz:
+	touch $@!,
+              '', "touch bar\ntouch baz\n\$^ = bar baz\n\$| = \ntouch foo\n");
+
+
+# TEST #4 -- now we do it again
+
+run_make_test(undef, '', "touch baz\n\$^ = bar baz\n\$| = \ntouch foo\n");
+
+unlink(qw(foo bar baz));
+
+# Test empty normal prereqs
+
+# TEST #5 -- make sure the parser was correct.
+
+run_make_test(q!
+foo:| baz
+	@echo '$$^ = $^'
+	@echo '$$| = $|'
+	touch $@
+
+.PHONY: baz
+
+baz:
+	touch $@!,
+              '', "touch baz\n\$^ = \n\$| = baz\ntouch foo\n");
+
+# TEST #6 -- now we do it again: this time foo won't be built
+
+run_make_test(undef, '', "touch baz\n");
+
+unlink(qw(foo baz));
+
+# Test order-only in pattern rules
+
+# TEST #7 -- make sure the parser was correct.
+
+run_make_test(q!
+%.w : %.x | baz
+	@echo '$$^ = $^'
+	@echo '$$| = $|'
+	touch $@
+
+all: foo.w
+
+.PHONY: baz
+foo.x baz:
+	touch $@!,
+              '',
+              "touch foo.x\ntouch baz\n\$^ = foo.x\n\$| = baz\ntouch foo.w\n");
+
+# TEST #8 -- now we do it again: this time foo.w won't be built
+
+run_make_test(undef, '', "touch baz\n");
+
+unlink(qw(foo.w foo.x baz));
+
+# TEST #9 -- make sure that $< is set correctly in the face of order-only
+# prerequisites in pattern rules.
+
+run_make_test('
+%r: | baz ; @echo $< $^ $|
+bar: foo
+foo:;@:
+baz:;@:',
+              '', "foo foo baz\n");
+
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/override
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/override	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/override	(revision 1780)
@@ -0,0 +1,34 @@
+$description = "The following test creates a makefile to ...";
+
+$details = "";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "override define foo\n"
+              ."\@echo First comes the definition.\n"
+              ."\@echo Then comes the override.\n"
+              ."endef\n"
+              ."all: \n"
+              ."\t\$(foo)\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"foo=Hello",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "First comes the definition.\n"
+         ."Then comes the override.\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/parallelism
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/parallelism	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/parallelism	(revision 1780)
@@ -0,0 +1,164 @@
+#                                                                    -*-perl-*-
+
+$description = "Test parallelism (-j) option.";
+
+
+$details = "This test creates a makefile with two double-colon default
+rules.  The first rule has a series of sleep and echo commands
+intended to run in series.  The second and third have just an
+echo statement.  When make is called in this test, it is given
+the -j option with a value of 4.  This tells make that it may
+start up to four jobs simultaneously.  In this case, since the
+first command is a sleep command, the output of the second
+and third commands will appear before the first if indeed
+make is running all of these commands in parallel.";
+
+if (!$parallel_jobs) {
+  return -1;
+}
+
+if ($vos) {
+  $sleep_command = "sleep -seconds";
+}
+else {
+  $sleep_command = "sleep";
+}
+
+
+run_make_test("
+all : def_1 def_2 def_3
+def_1 : ; \@echo ONE; $sleep_command 3 ; echo TWO
+def_2 : ; \@$sleep_command 2 ; echo THREE
+def_3 : ; \@$sleep_command 1 ; echo FOUR",
+              '-j4', "ONE\nFOUR\nTHREE\nTWO");
+
+# Test parallelism with included files.  Here we sleep/echo while
+# building the included files, to test that they are being built in
+# parallel.
+run_make_test("
+all: 1 2; \@echo success
+-include 1.inc 2.inc
+1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@
+2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@",
+              "-j4",
+              "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n");
+
+unlink('1.inc', '2.inc');
+
+
+# Test parallelism with included files--this time recurse first and make
+# sure the jobserver works.
+run_make_test("
+recurse: ; \@\$(MAKE) --no-print-directory -f #MAKEFILE# INC=yes all
+all: 1 2; \@echo success
+
+INC = no
+ifeq (\$(INC),yes)
+-include 1.inc 2.inc
+endif
+
+1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@
+2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@",
+              "-j4",
+              "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n");
+
+unlink('1.inc', '2.inc');
+
+# Grant Taylor reports a problem where tokens can be lost (not written back
+# to the pipe when they should be): this happened when there is a $(shell ...)
+# function in an exported recursive variable.  I added some code to check
+# for this situation and print a message if it occurred.  This test used
+# to trigger this code when I added it but no longer does after the fix.
+
+run_make_test("
+export HI = \$(shell \$(\$\@.CMD))
+first.CMD = echo hi
+second.CMD = $sleep_command 4; echo hi
+
+.PHONY: all first second
+all: first second
+
+first second: ; \@echo \$\@; $sleep_command 1; echo \$\@",
+              '-j2', "first\nfirst\nsecond\nsecond");
+
+# Michael Matz <matz@suse.de> reported a bug where if make is running in
+# parallel without -k and two jobs die in a row, but not too close to each
+# other, then make will quit without waiting for the rest of the jobs to die.
+
+run_make_test("
+.PHONY: all fail.1 fail.2 fail.3 ok
+all: fail.1 ok fail.2 fail.3
+
+fail.1 fail.2 fail.3:
+	\@sleep \$(patsubst fail.%,%,\$\@)
+	\@echo Fail
+	\@exit 1
+
+ok:
+	\@sleep 4
+	\@echo Ok done",
+              '-rR -j5', 'Fail
+#MAKE#: *** [fail.1] Error 1
+#MAKE#: *** Waiting for unfinished jobs....
+Fail
+#MAKE#: *** [fail.2] Error 1
+Fail
+#MAKE#: *** [fail.3] Error 1
+Ok done',
+             512);
+
+
+# Test for Savannah bug #15641.
+#
+run_make_test('
+.PHONY: all
+all:; @:
+
+-include foo.d
+
+foo.d: comp
+	@echo building $@
+
+comp: mod_a.o mod_b.o; @:
+
+mod_a.o mod_b.o:
+	@exit 1
+', '-j2', '');
+
+
+# Make sure that all jobserver FDs are closed if we need to re-exec the
+# master copy.
+#
+# First, find the "default" file descriptors we normally use
+# Then make sure they're still used.
+#
+# Right now we don't have a way to run a makefile and capture the output
+# without checking it, so we can't really write this test.
+
+# run_make_test('
+# submake: ; @$(MAKE) --no-print-directory -f #MAKEFILE# fdprint 5>output
+
+# dependfile: ; @echo FOO=bar > $@
+
+# INCL := true
+
+# FOO=foo
+# ifeq ($(INCL),true)
+# -include dependfile
+# endif
+
+# fdprint: ; @echo $(filter --jobserver%,$(MAKEFLAGS))
+
+# recurse: ; @$(MAKE) --no-print-directory -f #MAKEFILE# submake INCL=true',
+#               '-j2 INCL=false fdprint',
+#               'bar');
+
+# unlink('dependfile', 'output');
+
+
+# # Do it again, this time where the include is done by the non-master make.
+# run_make_test(undef, '-j2 recurse INCL=false', 'bar');
+
+# unlink('dependfile', 'output');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/patspecific_vars
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/patspecific_vars	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/patspecific_vars	(revision 1780)
@@ -0,0 +1,124 @@
+#                                                                    -*-perl-*-
+$description = "Test pattern-specific variable settings.";
+
+$details = "\
+Create a makefile containing various flavors of pattern-specific variable
+settings, override and non-override, and using various variable expansion
+rules, semicolon interference, etc.";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+all: one.x two.x three.x
+FOO = foo
+BAR = bar
+BAZ = baz
+one.x: override FOO = one
+%.x: BAR = two
+t%.x: BAR = four
+thr% : override BAZ = three
+one.x two.x three.x: ; @echo $@: $(FOO) $(BAR) $(BAZ)
+four.x: baz ; @echo $@: $(FOO) $(BAR) $(BAZ)
+baz: ; @echo $@: $(FOO) $(BAR) $(BAZ)
+
+# test matching multiple patterns
+a%: AAA = aaa
+%b: BBB = ccc
+a%: BBB += ddd
+%b: AAA ?= xxx
+%b: AAA += bbb
+.PHONY: ab
+ab: ; @echo $(AAA); echo $(BBB)
+EOF
+
+close(MAKEFILE);
+
+
+# TEST #1 -- basics
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "one.x: one two baz\ntwo.x: foo four baz\nthree.x: foo four three\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2 -- try the override feature
+
+&run_make_with_options($makefile, "BAZ=five", &get_logfile);
+$answer = "one.x: one two five\ntwo.x: foo four five\nthree.x: foo four three\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #3 -- make sure patterns are inherited properly
+
+&run_make_with_options($makefile, "four.x", &get_logfile);
+$answer = "baz: foo two baz\nfour.x: foo two baz\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #4 -- test multiple patterns matching the same target
+
+&run_make_with_options($makefile, "ab", &get_logfile);
+$answer = "aaa bbb\nccc ddd\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #5 -- test pattern-specific exported variables
+#
+run_make_test('
+/%: export foo := foo
+
+/bar:
+	@echo $(foo) $$foo
+', '', 'foo foo');
+
+
+# TEST #6 -- test expansion of pattern-specific simple variables
+#
+run_make_test('
+.PHONY: all
+
+all: inherit := good $$t
+all: bar baz
+
+b%: pattern := good $$t
+
+global := orginal $$t
+
+
+# normal target
+#
+ifdef rec
+bar: a = global: $(global) pattern: $(pattern) inherit: $(inherit)
+else
+bar: a := global: $(global) pattern: $(pattern) inherit: $(inherit)
+endif
+
+bar: ; @echo \'normal: $a;\'
+
+
+# pattern target
+#
+ifdef rec
+%z: a = global: $(global) pattern: $(pattern) inherit: $(inherit)
+else
+%z: a := global: $(global) pattern: $(pattern) inherit: $(inherit)
+endif
+
+%z: ; @echo \'pattrn: $a;\'
+
+
+global := new $$t
+',
+'',
+'normal: global: orginal $t pattern:  inherit: ;
+pattrn: global: orginal $t pattern:  inherit: ;');
+
+
+# TEST #7 -- test expansion of pattern-specific recursive variables
+#
+run_make_test(undef, # reuse previous makefile
+'rec=1',
+'normal: global: new $t pattern: good $t inherit: good $t;
+pattrn: global: new $t pattern: good $t inherit: good $t;');
+
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/patternrules
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/patternrules	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/patternrules	(revision 1780)
@@ -0,0 +1,149 @@
+#                                                                    -*-perl-*-
+
+$description = "Test pattern rules.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+
+# TEST #0: Make sure that multiple patterns where the same target
+#          can be built are searched even if the first one fails
+#          to match properly.
+#
+
+run_make_test('
+.PHONY: all
+
+all: case.1 case.2 case.3
+a: void
+
+# 1 - existing file
+%.1: void
+	@exit 1
+%.1: #MAKEFILE#
+	@exit 0
+
+# 2 - phony
+%.2: void
+	@exit 1
+%.2: 2.phony
+	@exit 0
+.PHONY: 2.phony
+
+# 3 - implicit-phony
+%.3: void
+	@exit 1
+%.3: 3.implicit-phony
+	@exit 0
+
+3.implicit-phony:
+',
+'',
+'');
+
+# TEST #1: make sure files that are built via implicit rules are marked
+#          as targets (Savannah bug #12202).
+#
+run_make_test('
+TARGETS := foo foo.out
+
+.PHONY: all foo.in
+
+all: $(TARGETS)
+
+%: %.in
+	@echo $@
+
+%.out: %
+	@echo $@
+
+foo.in: ; @:
+
+',
+'',
+'foo
+foo.out');
+
+
+# TEST #2: make sure intermediate files that also happened to be
+#          prerequisites are not removed (Savannah bug #12267).
+#
+run_make_test('
+$(dir)/foo.o:
+
+$(dir)/foo.y:
+	@echo $@
+
+%.c: %.y
+	touch $@
+
+%.o: %.c
+	@echo $@
+
+.PHONY: install
+install: $(dir)/foo.c
+
+',
+"dir=$dir",
+"$dir/foo.y
+touch $dir/foo.c
+$dir/foo.o");
+
+unlink("$dir/foo.c");
+
+
+# TEST #3: make sure precious flag is set properly for targets
+#          that are built via implicit rules (Savannah bug #13218).
+#
+run_make_test('
+.DELETE_ON_ERROR:
+
+.PRECIOUS: %.bar
+
+%.bar:; @touch $@ && exit 1
+
+$(dir)/foo.bar:
+
+',
+"dir=$dir",
+"#MAKE#: *** [$dir/foo.bar] Error 1",
+512);
+
+unlink("$dir/foo.bar");
+
+
+# TEST #4: make sure targets of a matched implicit pattern rule are
+#          never considered intermediate (Savannah bug #13022).
+#
+run_make_test('
+.PHONY: all
+all: foo.c foo.o
+
+%.h %.c: %.in
+	touch $*.h
+	touch $*.c
+
+%.o: %.c %.h
+	echo $+ >$@
+
+%.o: %.c
+	@echo wrong rule
+
+foo.in:
+	touch $@
+
+',
+'',
+'touch foo.in
+touch foo.h
+touch foo.c
+echo foo.c foo.h >foo.o');
+
+unlink('foo.in', 'foo.h', 'foo.c', 'foo.o');
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/quoting
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/quoting	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/quoting	(revision 1780)
@@ -0,0 +1,32 @@
+#                                                                    -*-perl-*-
+
+$description = "The following test creates a makefile to test using \n" .
+               "quotes within makefiles.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOM';
+SHELL = /bin/sh
+TEXFONTS = NICEFONT
+DEFINES = -DDEFAULT_TFM_PATH=\".:$(TEXFONTS)\"
+test: ; @"echo" 'DEFINES = $(DEFINES)'
+EOM
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+
+# Create the answer to what should be produced by this Makefile
+$answer = 'DEFINES = -DDEFAULT_TFM_PATH=\".:NICEFONT\"' . "\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/recursion
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/recursion	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/recursion	(revision 1780)
@@ -0,0 +1,55 @@
+#                                                                    -*-perl-*-
+$description = "Test recursion.";
+
+$details = "DETAILS";
+
+# Test some basic recursion.
+run_make_test('
+all:
+	$(MAKE) -f #MAKEFILE# foo
+foo:
+	@echo $(MAKE)
+	@echo MAKELEVEL = $(MAKELEVEL)
+	$(MAKE) -f #MAKEFILE# last
+last:
+	@echo $(MAKE)
+	@echo MAKELEVEL = $(MAKELEVEL)
+	@echo THE END
+',
+              ('CFLAGS=-O -w' . ($parallel_jobs ? '-j 2' : '')),
+              ($vos
+               ? "#MAKE#: Entering directory `#PWD#'
+make 'CFLAGS=-O' -f #MAKEFILE# foo
+make CFLAGS=-O
+MAKELEVEL = 0
+make 'CFLAGS=-O' -f #MAKEFILE# last
+make CFLAGS=-O
+MAKELEVEL = 0
+THE END
+#MAKE#: Leaving directory `#PWD#'"
+               : "#MAKE#: Entering directory `#PWD#'
+#MAKEPATH# -f #MAKEFILE# foo
+#MAKE#[1]: Entering directory `#PWD#'
+#MAKEPATH#
+MAKELEVEL = 1
+#MAKEPATH# -f #MAKEFILE# last
+#MAKE#[2]: Entering directory `#PWD#'
+#MAKEPATH#
+MAKELEVEL = 2
+THE END
+#MAKE#[2]: Leaving directory `#PWD#'
+#MAKE#[1]: Leaving directory `#PWD#'
+#MAKE#: Leaving directory `#PWD#'"));
+
+
+# Test command line overrides.
+run_make_test('
+recur: all ; @$(MAKE) --no-print-directory -f #MAKEFILE# a=AA all
+all: ; @echo "MAKEOVERRIDES = $(MAKEOVERRIDES)"
+',
+              'a=ZZ',
+              'MAKEOVERRIDES = a=ZZ
+MAKEOVERRIDES = a=AA
+');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/reinvoke
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/reinvoke	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/reinvoke	(revision 1780)
@@ -0,0 +1,65 @@
+#                                                              -*-mode: perl-*-
+
+$description = "Test GNU make's auto-reinvocation feature.";
+
+$details = "\
+If the makefile or one it includes can be rebuilt then it is, and make
+is reinvoked.  We create a rule to rebuild the makefile from a temp
+file, then touch the temp file to make it newer than the makefile.";
+
+$omkfile = $makefile;
+
+&utouch(-600, 'incl.mk');
+# For some reason if we don't do this then the test fails for systems
+# with sub-second timestamps, maybe + NFS?  Not sure.
+&utouch(-1, 'incl-1.mk');
+
+run_make_test('
+all: ; @echo running rules.
+
+#MAKEFILE# incl.mk: incl-1.mk
+	@echo rebuilding $@
+	@echo >> $@
+
+include incl.mk',
+              '', "rebuilding incl.mk\nrunning rules.\n");
+
+# Make sure updating the makefile itself also works
+
+&utouch(-600, $omkfile);
+
+run_make_test(undef, '', "rebuilding #MAKEFILE#\nrunning rules.\n");
+
+&rmfiles('incl.mk', 'incl-1.mk');
+
+
+# In this test we create an included file that's out-of-date, but then
+# the rule doesn't update it.  Make shouldn't re-exec.
+
+&utouch(-600, 'b','a');
+#&utouch(-10, 'a');
+&touch('c');
+
+run_make_test('
+SHELL = /bin/sh
+
+all: ; @echo hello
+
+a : b ; echo >> $@
+
+b : c ; [ -f $@ ] || echo >> $@
+
+c: ; echo >> $@
+
+include $(F)',
+              'F=a', "[ -f b ] || echo >> b\nhello\n");
+
+# Now try with the file we're not updating being the actual file we're
+# including: this and the previous one test different parts of the code.
+
+run_make_test(undef, "F=b", "[ -f b ] || echo >> b\nhello\n")
+
+&rmfiles('a','b','c');
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_explicit
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_explicit	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_explicit	(revision 1780)
@@ -0,0 +1,127 @@
+#                                                                    -*-perl-*-
+$description = "Test second expansion in ordinary rules.";
+
+$details = "";
+
+# TEST #0: Test handing of '$' in prerequisites with and without second
+# expansion.
+
+run_make_test(q!
+ifdef SE
+  .SECONDEXPANSION:
+endif
+foo$$bar: bar$$baz bar$$biz ; @echo '$@ : $^'
+PRE = one two
+bar$$baz: $$(PRE)
+baraz: $$(PRE)
+PRE = three four
+.DEFAULT: ; @echo '$@'
+!,
+              '',
+              "\$\nbar\$biz\nfoo\$bar : bar\$baz bar\$biz");
+
+run_make_test(undef, 'SE=1', "three\nfour\nbariz\nfoo\$bar : baraz bariz");
+
+# TEST #1: automatic variables.
+#
+run_make_test('
+.SECONDEXPANSION:
+.DEFAULT: ; @echo $@
+
+foo: bar baz
+
+foo: biz | buz
+
+foo: $$@.1 \
+     $$<.2 \
+     $$(addsuffix .3,$$^) \
+     $$(addsuffix .4,$$+) \
+     $$|.5 \
+     $$*.6
+
+',
+'',
+'bar
+baz
+biz
+buz
+foo.1
+bar.2
+bar.3
+baz.3
+biz.3
+bar.4
+baz.4
+biz.4
+buz.5
+.6
+');
+
+
+# Test #2: target/pattern -specific variables.
+#
+run_make_test('
+.SECONDEXPANSION:
+.DEFAULT: ; @echo $@
+
+foo.x: $$a $$b
+
+foo.x: a := bar
+
+%.x: b := baz
+
+',
+'',
+'bar
+baz
+');
+
+
+# Test #3: order of prerequisites.
+#
+run_make_test('
+.SECONDEXPANSION:
+.DEFAULT: ; @echo $@
+
+all: foo bar baz
+
+# Subtest #1
+#
+foo: foo.1; @:
+
+foo: foo.2
+
+foo: foo.3
+
+
+# Subtest #2
+#
+bar: bar.2
+
+bar: bar.1; @:
+
+bar: bar.3
+
+
+# Subtest #3
+#
+baz: baz.1
+
+baz: baz.2
+
+baz: ; @:
+
+',
+'',
+'foo.1
+foo.2
+foo.3
+bar.1
+bar.2
+bar.3
+baz.1
+baz.2
+');
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_implicit
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_implicit	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_implicit	(revision 1780)
@@ -0,0 +1,232 @@
+#                                                                    -*-perl-*-
+$description = "Test second expansion in ordinary rules.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+
+# Test #1: automatic variables.
+#
+run_make_test('
+.SECONDEXPANSION:
+.DEFAULT: ; @echo $@
+
+foo.a: bar baz
+
+foo.a: biz | buz
+
+foo.%: 1.$$@ \
+       2.$$< \
+       $$(addprefix 3.,$$^) \
+       $$(addprefix 4.,$$+) \
+       5.$$| \
+       6.$$*
+	@:
+
+1.foo.a \
+2.bar \
+3.bar \
+3.baz \
+3.biz \
+4.bar \
+4.baz \
+4.biz \
+5.buz \
+6.a:
+	@echo $@
+
+',
+'',
+'1.foo.a
+2.bar
+3.bar
+3.baz
+3.biz
+4.bar
+4.baz
+4.biz
+5.buz
+6.a
+bar
+baz
+biz
+buz
+');
+
+
+# Test #2: target/pattern -specific variables.
+#
+run_make_test('
+.SECONDEXPANSION:
+foo.x:
+
+foo.%: $$(%_a) $$(%_b) bar
+	@:
+
+foo.x: x_a := bar
+
+%.x: x_b := baz
+
+bar baz: ; @echo $@
+
+',
+'',
+'bar
+baz
+');
+
+
+# Test #3: order of prerequisites.
+#
+run_make_test('
+.SECONDEXPANSION:
+.DEFAULT: ; @echo $@
+
+all: foo bar baz
+
+
+# Subtest #1
+#
+%oo: %oo.1; @:
+
+foo: foo.2
+
+foo: foo.3
+
+foo.1: ; @echo $@
+
+
+# Subtest #2
+#
+bar: bar.2
+
+%ar: %ar.1; @:
+
+bar: bar.3
+
+bar.1: ; @echo $@
+
+
+# Subtest #3
+#
+baz: baz.1
+
+baz: baz.2
+
+%az: ; @:
+
+',
+'',
+'foo.1
+foo.2
+foo.3
+bar.1
+bar.2
+bar.3
+baz.1
+baz.2
+');
+
+
+# Test #4: stem splitting logic.
+#
+run_make_test('
+.SECONDEXPANSION:
+$(dir)/tmp/bar.o:
+
+$(dir)/tmp/foo/bar.c: ; @echo $@
+$(dir)/tmp/bar/bar.c: ; @echo $@
+foo.h: ; @echo $@
+
+%.o: $$(addsuffix /%.c,foo bar) foo.h
+	@echo $@: {$<} $^
+
+',
+"dir=$dir",
+"$dir/tmp/foo/bar.c
+$dir/tmp/bar/bar.c
+foo.h
+$dir/tmp/bar.o: {$dir/tmp/foo/bar.c} $dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h
+");
+
+
+# Test #5: stem splitting logic and order-only prerequisites.
+#
+run_make_test('
+.SECONDEXPANSION:
+$(dir)/tmp/foo.o: $(dir)/tmp/foo.c
+$(dir)/tmp/foo.c: ; @echo $@
+bar.h: ; @echo $@
+
+%.o: %.c|bar.h
+	@echo $@: {$<} {$|} $^
+
+',
+"dir=$dir",
+"$dir/tmp/foo.c
+bar.h
+$dir/tmp/foo.o: {$dir/tmp/foo.c} {bar.h} $dir/tmp/foo.c
+");
+
+
+# Test #6: lack of implicit prerequisites.
+#
+run_make_test('
+.SECONDEXPANSION:
+foo.o: foo.c
+foo.c: ; @echo $@
+
+%.o:
+	@echo $@: {$<} $^
+
+',
+'',
+'foo.c
+foo.o: {foo.c} foo.c
+');
+
+# Test #7: Test stem from the middle of the name.
+#
+run_make_test('
+.SECONDEXPANSION:
+foobarbaz:
+
+foo%baz: % $$*.1
+	@echo $*
+
+bar bar.1:
+	@echo $@
+
+',
+'',
+'bar
+bar.1
+bar
+');
+
+# Test #8: Make sure stem triple-expansion does not happen.
+#
+run_make_test('
+.SECONDEXPANSION:
+foo$$bar:
+
+f%r: % $$*.1
+	@echo \'$*\'
+
+oo$$ba oo$$ba.1:
+	@echo \'$@\'
+
+',
+'',
+'oo$ba
+oo$ba.1
+oo$ba
+');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_statpat
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_statpat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/se_statpat	(revision 1780)
@@ -0,0 +1,128 @@
+#                                                                    -*-perl-*-
+$description = "Test second expansion in static pattern rules.";
+
+$details = "";
+
+# Test #1: automatic variables.
+#
+run_make_test('
+.SECONDEXPANSION:
+.DEFAULT: ; @echo $@
+
+foo.a foo.b: foo.%: bar.% baz.%
+
+foo.a foo.b: foo.%: biz.% | buz.%
+
+foo.a foo.b: foo.%: $$@.1 \
+                    $$<.2 \
+                    $$(addsuffix .3,$$^) \
+                    $$(addsuffix .4,$$+) \
+                    $$|.5 \
+                    $$*.6
+
+',
+'',
+'bar.a
+baz.a
+biz.a
+buz.a
+foo.a.1
+bar.a.2
+bar.a.3
+baz.a.3
+biz.a.3
+bar.a.4
+baz.a.4
+biz.a.4
+buz.a.5
+a.6
+');
+
+
+# Test #2: target/pattern -specific variables.
+#
+run_make_test('
+.SECONDEXPANSION:
+.DEFAULT: ; @echo $@
+
+foo.x foo.y: foo.%: $$(%_a) $$($$*_b)
+
+foo.x: x_a := bar
+
+%.x: x_b := baz
+
+
+',
+'',
+'bar
+baz
+');
+
+
+# Test #3: order of prerequisites.
+#
+run_make_test('
+.SECONDEXPANSION:
+.DEFAULT: ; @echo $@
+
+all: foo.a bar.a baz.a
+
+# Subtest #1
+#
+foo.a foo.b: foo.%: foo.%.1; @:
+
+foo.a foo.b: foo.%: foo.%.2
+
+foo.a foo.b: foo.%: foo.%.3
+
+
+# Subtest #2
+#
+bar.a bar.b: bar.%: bar.%.2
+
+bar.a bar.b: bar.%: bar.%.1; @:
+
+bar.a bar.b: bar.%: bar.%.3
+
+
+# Subtest #3
+#
+baz.a baz.b: baz.%: baz.%.1
+
+baz.a baz.b: baz.%: baz.%.2
+
+baz.a baz.b: ; @:
+
+',
+'',
+'foo.a.1
+foo.a.2
+foo.a.3
+bar.a.1
+bar.a.2
+bar.a.3
+baz.a.1
+baz.a.2
+');
+
+
+# Test #4: Make sure stem triple-expansion does not happen.
+#
+run_make_test('
+.SECONDEXPANSION:
+foo$$bar: f%r: % $$*.1
+	@echo \'$*\'
+
+oo$$ba oo$$ba.1:
+	@echo \'$@\'
+
+',
+'',
+'oo$ba
+oo$ba.1
+oo$ba
+');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/statipattrules
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/statipattrules	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/statipattrules	(revision 1780)
@@ -0,0 +1,111 @@
+#                                                                    -*-perl-*-
+$description = "Test handling of static pattern rules.";
+
+$details = "\
+The makefile created in this test has three targets.  The
+filter command is used to get those target names ending in
+.o and statically creates a compile command with the target
+name and the target name with .c.  It also does the same thing
+for another target filtered with .elc and creates a command
+to emacs a .el file";
+
+&touch('bar.c', 'lose.c');
+
+#   TEST #0
+#   -------
+
+run_make_test('
+files = foo.elc bar.o lose.o
+
+$(filter %.o,$(files)): %.o: %.c ; @echo CC -c $(CFLAGS) $< -o $@
+
+$(filter %.elc,$(files)): %.elc: %.el ; @echo emacs $<
+',
+              '',
+              'CC -c bar.c -o bar.o');
+
+#  TEST #1
+#  -------
+
+run_make_test(undef, 'lose.o', 'CC -c lose.c -o lose.o');
+
+
+#   TEST #2
+#   -------
+&touch("foo.el");
+
+run_make_test(undef, 'foo.elc', 'emacs foo.el');
+
+# Clean up after the first tests.
+unlink('foo.el', 'bar.c', 'lose.c');
+
+
+# TEST #3 -- PR/1670: don't core dump on invalid static pattern rules
+# -------
+
+run_make_test('
+.DEFAULT: ; @echo $@
+foo: foo%: % %.x % % % y.% % ; @echo $@
+',
+              '', ".x\ny.\nfoo");
+
+
+# TEST #4 -- bug #12180: core dump on a stat pattern rule with an empty
+#                        prerequisite list.
+run_make_test('
+foo.x bar.x: %.x : ; @echo $@
+
+',
+              '', 'foo.x');
+
+
+# TEST #5 -- bug #13881: double colon static pattern rule does not
+#                        substitute %.
+run_make_test('
+foo.bar:: %.bar: %.baz
+foo.baz: ;@:
+',
+              '', '');
+
+
+# TEST #6: make sure the second stem does not overwrite the first
+#          perprerequisite's stem (Savannah bug #16053).
+#
+run_make_test('
+all.foo.bar: %.foo.bar: %.one
+
+all.foo.bar: %.bar: %.two
+
+all.foo.bar:
+	@echo $*
+	@echo $^
+
+.DEFAULT:;@:
+',
+'',
+'all.foo
+all.one all.foo.two');
+
+
+# TEST #7: make sure the second stem does not overwrite the first
+#          perprerequisite's stem when second expansion is enabled
+#          (Savannah bug #16053).
+#
+run_make_test('
+.SECONDEXPANSION:
+
+all.foo.bar: %.foo.bar: %.one $$*-one
+
+all.foo.bar: %.bar: %.two $$*-two
+
+all.foo.bar:
+	@echo $*
+	@echo $^
+
+.DEFAULT:;@:
+',
+'',
+'all.foo
+all.one all-one all.foo.two all.foo-two');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/targetvars
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/targetvars	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/targetvars	(revision 1780)
@@ -0,0 +1,307 @@
+#                                                                    -*-perl-*-
+$description = "Test target-specific variable settings.";
+
+$details = "\
+Create a makefile containing various flavors of target-specific variable
+values, override and non-override, and using various variable expansion
+rules, semicolon interference, etc.";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+SHELL = /bin/sh
+export FOO = foo
+export BAR = bar
+one: override FOO = one
+one two: ; @echo $(FOO) $(BAR)
+two: BAR = two
+three: ; BAR=1000
+	@echo $(FOO) $(BAR)
+# Some things that shouldn't be target vars
+funk : override
+funk : override adelic
+adelic override : ; echo $@
+# Test per-target recursive variables
+four:FOO=x
+four:VAR$(FOO)=ok
+four: ; @echo '$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)'
+five:FOO=x
+five six : VAR$(FOO)=good
+five six: ;@echo '$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)'
+# Test per-target variable inheritance
+seven: eight
+seven eight: ; @echo $@: $(FOO) $(BAR)
+seven: BAR = seven
+seven: FOO = seven
+eight: BAR = eight
+# Test the export keyword with per-target variables
+nine: ; @echo $(FOO) $(BAR) $$FOO $$BAR
+nine: FOO = wallace
+nine-a: export BAZ = baz
+nine-a: ; @echo $$BAZ
+# Test = escaping
+EQ = =
+ten: one\=two
+ten: one \= two
+ten one$(EQ)two $(EQ):;@echo $@
+.PHONY: one two three four five six seven eight nine ten $(EQ) one$(EQ)two
+# Test target-specific vars with pattern/suffix rules
+QVAR = qvar
+RVAR = =
+%.q : ; @echo $(QVAR) $(RVAR)
+foo.q : RVAR += rvar
+# Target-specific vars with multiple LHS pattern rules
+%.r %.s %.t: ; @echo $(QVAR) $(RVAR) $(SVAR) $(TVAR)
+foo.r : RVAR += rvar
+foo.t : TVAR := $(QVAR)
+EOF
+
+close(MAKEFILE);
+
+# TEST #1
+
+&run_make_with_options($makefile, "one two three", &get_logfile);
+$answer = "one bar\nfoo two\nBAR=1000\nfoo bar\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #2
+
+&run_make_with_options($makefile, "one two FOO=1 BAR=2", &get_logfile);
+$answer = "one 2\n1 2\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #3
+
+&run_make_with_options($makefile, "four", &get_logfile);
+$answer = "x ok  ok\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #4
+
+&run_make_with_options($makefile, "seven", &get_logfile);
+$answer = "eight: seven eight\nseven: seven seven\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #5
+
+&run_make_with_options($makefile, "nine", &get_logfile);
+$answer = "wallace bar wallace bar\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #5-a
+
+&run_make_with_options($makefile, "nine-a", &get_logfile);
+$answer = "baz\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #6
+
+&run_make_with_options($makefile, "ten", &get_logfile);
+$answer = "one=two\none bar\n=\nfoo two\nten\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #6
+
+&run_make_with_options($makefile, "foo.q bar.q", &get_logfile);
+$answer = "qvar = rvar\nqvar =\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #7
+
+&run_make_with_options($makefile, "foo.t bar.s", &get_logfile);
+$answer = "qvar = qvar\nqvar =\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #8
+# For PR/1378: Target-specific vars don't inherit correctly
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile2");
+print MAKEFILE <<'EOF';
+foo: FOO = foo
+bar: BAR = bar
+foo: bar
+bar: baz
+baz: ; @echo $(FOO) $(BAR)
+EOF
+close(MAKEFILE);
+
+&run_make_with_options("$makefile2", "", &get_logfile);
+$answer = "foo bar\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #9
+# For PR/1380: Using += assignment in target-specific variables sometimes fails
+# Also PR/1831
+
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile3");
+print MAKEFILE <<'EOF';
+.PHONY: all one
+all: FOO += baz
+all: one; @echo $(FOO)
+
+FOO = bar
+
+one: FOO += biz
+one: FOO += boz
+one: ; @echo $(FOO)
+EOF
+close(MAKEFILE);
+
+&run_make_with_options("$makefile3", "", &get_logfile);
+$answer = "bar baz biz boz\nbar baz\n";
+&compare_output($answer, &get_logfile(1));
+
+# Test #10
+
+&run_make_with_options("$makefile3", "one", &get_logfile);
+$answer = "bar biz boz\n";
+&compare_output($answer, &get_logfile(1));
+
+# Test #11
+# PR/1709: Test semicolons in target-specific variable values
+
+$makefile4 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile4");
+print MAKEFILE <<'EOF';
+foo : FOO = ; ok
+foo : ; @echo '$(FOO)'
+EOF
+close(MAKEFILE);
+
+&run_make_with_options("$makefile4", "", &get_logfile);
+$answer = "; ok\n";
+&compare_output($answer, &get_logfile(1));
+
+# Test #12
+# PR/2020: More hassles with += target-specific vars.  I _really_ think
+# I nailed it this time :-/.
+
+$makefile5 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile5");
+print MAKEFILE <<'EOF';
+.PHONY: a
+
+BLAH := foo
+COMMAND = echo $(BLAH)
+
+a: ; @$(COMMAND)
+
+a: BLAH := bar
+a: COMMAND += snafu $(BLAH)
+EOF
+close(MAKEFILE);
+
+&run_make_with_options("$makefile5", "", &get_logfile);
+$answer = "bar snafu bar\n";
+&compare_output($answer, &get_logfile(1));
+
+# Test #13
+# Test double-colon rules with target-specific variable values
+
+$makefile6 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile6");
+print MAKEFILE <<'EOF';
+W = bad
+X = bad
+foo: W = ok
+foo:: ; @echo $(W) $(X) $(Y) $(Z)
+foo:: ; @echo $(W) $(X) $(Y) $(Z)
+foo: X = ok
+
+Y = foo
+bar: foo
+bar: Y = bar
+
+Z = nopat
+ifdef PATTERN
+  fo% : Z = pat
+endif
+
+EOF
+close(MAKEFILE);
+
+&run_make_with_options("$makefile6", "foo", &get_logfile);
+$answer = "ok ok foo nopat\nok ok foo nopat\n";
+&compare_output($answer, &get_logfile(1));
+
+# Test #14
+# Test double-colon rules with target-specific variable values and
+# inheritance
+
+&run_make_with_options("$makefile6", "bar", &get_logfile);
+$answer = "ok ok bar nopat\nok ok bar nopat\n";
+&compare_output($answer, &get_logfile(1));
+
+# Test #15
+# Test double-colon rules with pattern-specific variable values
+
+&run_make_with_options("$makefile6", "foo PATTERN=yes", &get_logfile);
+$answer = "ok ok foo pat\nok ok foo pat\n";
+&compare_output($answer, &get_logfile(1));
+
+
+# Test #16
+# Test target-specific variables with very long command line
+# (> make default buffer length)
+
+$makefile7 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile7");
+print MAKEFILE <<'EOF';
+base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions        CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if [ -f               "build_information.generate" ]; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi  )
+
+deals_changed_since: ; @echo $(BUILD_OBJ)
+
+EOF
+close(MAKEFILE);
+
+&run_make_with_options("$makefile7", '', &get_logfile);
+$answer = "no build information\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #17
+
+# Test a merge of set_lists for files, where one list is much longer
+# than the other.  See Savannah bug #15757.
+
+mkdir('t1', 0777);
+touch('t1/rules.mk');
+
+run_make_test('
+VPATH = t1
+include rules.mk
+.PHONY: all
+all: foo.x
+foo.x : rules.mk ; @echo MYVAR=$(MYVAR) FOOVAR=$(FOOVAR) ALLVAR=$(ALLVAR)
+all: ALLVAR = xxx
+foo.x: FOOVAR = bar
+rules.mk : MYVAR = foo
+.INTERMEDIATE: foo.x rules.mk
+',
+              '-I t1',
+              'MYVAR= FOOVAR=bar ALLVAR=xxx');
+
+rmfiles('t1/rules.mk');
+rmdir('t1');
+
+# TEST #18
+
+# Test appending to a simple variable containing a "$": avoid a
+# double-expansion.  See Savannah bug #15913.
+
+run_make_test("
+VAR := \$\$FOO
+foo: VAR += BAR
+foo: ; \@echo '\$(VAR)'",
+              '',
+              '$FOO BAR');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/varnesting
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/varnesting	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/varnesting	(revision 1780)
@@ -0,0 +1,34 @@
+$description = "The following test creates a makefile to ...";
+
+$details = "";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "x = variable1\n"
+              ."variable2 := Hello\n"
+              ."y = \$(subst 1,2,\$(x))\n"
+              ."z = y\n"
+              ."a := \$(\$(\$(z)))\n"
+              ."all: \n"
+              ."\t\@echo \$(a)\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "Hello\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpath
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpath	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpath	(revision 1780)
@@ -0,0 +1,62 @@
+$description = "The following test creates a makefile to test the \n"
+              ."vpath directive which allows you to specify a search \n"
+              ."path for a particular class of filenames, those that\n"
+              ."match a particular pattern.";
+
+$details = "This tests the vpath directive by specifying search directories\n"
+         ."for one class of filenames with the form: vpath pattern directories"
+         ."\nIn this test, we specify the working directory for all files\n"
+         ."that end in c or h.  We also test the variables $@ (which gives\n"
+         ."target name) and $^ (which is a list of all dependencies \n"
+         ."including the directories in which they were found).  It also\n"
+         ."uses the function firstword used to extract just the first\n"
+         ."dependency from the entire list.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "vpath %.c foo\n";
+print MAKEFILE "vpath %.c $workdir\n";
+print MAKEFILE "vpath %.h $workdir\n";
+print MAKEFILE "objects = main.o kbd.o commands.o display.o insert.o\n";
+print MAKEFILE "edit:  \$(objects)\n";
+print MAKEFILE "\t\@echo cc -o \$@ \$^\n";
+print MAKEFILE "main.o : main.c defs.h\n";
+print MAKEFILE "\t\@echo cc -c \$(firstword \$^)\n";
+print MAKEFILE "kbd.o : kbd.c defs.h command.h\n";
+print MAKEFILE "\t\@echo cc -c kbd.c\n";
+print MAKEFILE "commands.o : command.c defs.h command.h\n";
+print MAKEFILE "\t\@echo cc -c commands.c\n";
+print MAKEFILE "display.o : display.c defs.h buffer.h\n";
+print MAKEFILE "\t\@echo cc -c display.c\n";
+print MAKEFILE "insert.o : insert.c defs.h buffer.h\n";
+print MAKEFILE "\t\@echo cc -c insert.c\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
+               "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
+               "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+               "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
+	       "$workdir${pathsep}command.c");
+
+&touch(@files_to_touch);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "cc -c $workdir${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n"
+         ."cc -c display.c\n"
+         ."cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o "
+         ."insert.o\n";
+
+if (&compare_output($answer,&get_logfile(1)))
+{
+  unlink @files_to_touch;
+}
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpath2
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpath2	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpath2	(revision 1780)
@@ -0,0 +1,45 @@
+$description = "This is part 2 in a series to test the vpath directive\n"
+              ."It tests the three forms of the directive:\n"
+              ."     vpath pattern directive\n"
+              ."     vpath pattern  (clears path associated with pattern)\n"
+              ."     vpath          (clears all paths specified with vpath)\n";
+
+$details = "This test simply adds many search paths using various vpath\n"
+          ."directive forms and clears them afterwards.  It has a simple\n"
+          ."rule to print a message at the end to confirm that the makefile\n"
+          ."ran with no errors.\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "VPATH = $workdir:$sourcedir\n";
+print MAKEFILE "vpath %.c foo\n";
+print MAKEFILE "vpath %.c $workdir\n";
+print MAKEFILE "vpath %.c $sourcedir\n";
+print MAKEFILE "vpath %.h $workdir\n";
+print MAKEFILE "vpath %.c\n";
+print MAKEFILE "vpath\n";
+print MAKEFILE "all:\n";
+print MAKEFILE "\t\@echo ALL IS WELL\n";
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "ALL IS WELL\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpathgpath
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpathgpath	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpathgpath	(revision 1780)
@@ -0,0 +1,66 @@
+#                                                                    -*-perl-*-
+$description = "Tests VPATH+/GPATH functionality.";
+
+$details = "";
+
+$VP = "$workdir$pathsep";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "VPATH = $VP\n";
+
+print MAKEFILE <<'EOMAKE';
+
+GPATH = $(VPATH)
+
+.SUFFIXES: .a .b .c .d
+.PHONY: general rename notarget intermediate
+
+%.a:
+%.b:
+%.c:
+%.d:
+
+%.a : %.b ; cat $^ > $@
+%.b : %.c ; cat $^ > $@
+%.c :: %.d ; cat $^ > $@
+
+# General testing info:
+
+general: foo.b
+foo.b: foo.c bar.c
+
+EOMAKE
+
+close(MAKEFILE);
+
+@touchedfiles = ();
+
+$off = -500;
+
+sub touchfiles {
+  foreach (@_) {
+    ($f = $_) =~ s,VP/,$VP,g;
+    &utouch($off, $f);
+    $off += 10;
+    push(@touchedfiles, $f);
+  }
+}
+
+# Run the general-case test
+
+&touchfiles("VP/foo.d", "VP/bar.d", "VP/foo.c", "VP/bar.c", "foo.b", "bar.d");
+
+&run_make_with_options($makefile,"general",&get_logfile());
+
+push(@touchedfiles, "bar.c");
+
+$answer = "$make_name: Nothing to be done for `general'.\n";
+
+&compare_output($answer,&get_logfile(1));
+
+unlink(@touchedfiles) unless $keep;
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpathplus
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpathplus	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/features/vpathplus	(revision 1780)
@@ -0,0 +1,128 @@
+#                                                                    -*-perl-*-
+$description = "Tests the new VPATH+ functionality added in 3.76.";
+
+$details = "";
+
+$VP = "$workdir$pathsep";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "VPATH = $VP\n";
+
+print MAKEFILE <<'EOMAKE';
+
+SHELL = /bin/sh
+
+.SUFFIXES: .a .b .c .d
+.PHONY: general rename notarget intermediate
+
+%.a:
+%.b:
+%.c:
+%.d:
+
+%.a : %.b
+	cat $^ > $@
+%.b : %.c
+	cat $^ > $@ 2>/dev/null || exit 1
+%.c :: %.d
+	cat $^ > $@
+
+# General testing info:
+
+general: foo.b
+foo.b: foo.c bar.c
+
+# Rename testing info:
+
+rename: $(VPATH)/foo.c foo.d
+
+# Target not made testing info:
+
+notarget: notarget.b
+notarget.c: notarget.d
+	-@echo "not creating $@ from $^"
+
+# Intermediate files:
+
+intermediate: inter.a
+
+EOMAKE
+
+close(MAKEFILE);
+
+@touchedfiles = ();
+
+$off = -500;
+
+sub touchfiles {
+  foreach (@_) {
+    &utouch($off, $_);
+    $off += 10;
+    push(@touchedfiles, $_);
+  }
+}
+
+# Run the general-case test
+
+&touchfiles("$VP/foo.d", "$VP/bar.d", "$VP/foo.c", "$VP/bar.c", "foo.b", "bar.d");
+
+&run_make_with_options($makefile,"general",&get_logfile);
+
+push(@touchedfiles, "bar.c");
+
+$answer = "cat bar.d > bar.c
+cat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1
+";
+&compare_output($answer,&get_logfile(1));
+
+# Test rules that don't make the target correctly
+
+&touchfiles("$VP/notarget.c", "notarget.b", "notarget.d");
+
+&run_make_with_options($makefile,"notarget",&get_logfile,512);
+
+$answer = "not creating notarget.c from notarget.d
+cat notarget.c > notarget.b 2>/dev/null || exit 1
+$make_name: *** [notarget.b] Error 1
+";
+
+&compare_output($answer,&get_logfile(1));
+
+# Test intermediate file handling (part 1)
+
+&touchfiles("$VP/inter.d");
+
+&run_make_with_options($makefile,"intermediate",&get_logfile);
+
+push(@touchedfiles, "inter.a", "inter.b");
+
+$answer = "cat ${VP}inter.d > inter.c
+cat inter.c > inter.b 2>/dev/null || exit 1
+cat inter.b > inter.a
+rm inter.b inter.c
+";
+&compare_output($answer,&get_logfile(1));
+
+# Test intermediate file handling (part 2)
+
+&utouch(-20, "inter.a");
+&utouch(-10, "$VP/inter.b");
+&touch("$VP/inter.d");
+
+push(@touchedfiles, "$VP/inter.b", "$VP/inter.d");
+
+&run_make_with_options($makefile,"intermediate",&get_logfile);
+
+$answer = "cat ${VP}inter.d > inter.c
+cat inter.c > inter.b 2>/dev/null || exit 1
+cat inter.b > inter.a
+rm inter.c
+";
+&compare_output($answer,&get_logfile(1));
+
+unlink @touchedfiles unless $keep;
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/abspath
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/abspath	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/abspath	(revision 1780)
@@ -0,0 +1,81 @@
+#                                                                    -*-perl-*-
+$description = "Test the abspath functions.";
+
+$details = "";
+
+run_make_test('
+ifneq ($(realpath $(abspath .)),$(CURDIR))
+  $(warning .: abs="$(abspath .)" real="$(realpath $(abspath .))" curdir="$(CURDIR)")
+endif
+
+ifneq ($(realpath $(abspath ./)),$(CURDIR))
+  $(warning ./: abs="$(abspath ./)" real="$(realpath $(abspath ./))" curdir="$(CURDIR)")
+endif
+
+ifneq ($(realpath $(abspath .///)),$(CURDIR))
+  $(warning .///: abs="$(abspath .///)" real="$(realpath $(abspath .///))" curdir="$(CURDIR)")
+endif
+
+ifneq ($(abspath /),/)
+  $(warning /: abspath="$(abspath /)")
+endif
+
+ifneq ($(abspath ///),/)
+  $(warning ///: abspath="$(abspath ///)")
+endif
+
+ifneq ($(abspath /.),/)
+  $(warning /.: abspath="$(abspath /.)")
+endif
+
+ifneq ($(abspath ///.),/)
+  $(warning ///.: abspath="$(abspath ///.)")
+endif
+
+ifneq ($(abspath /./),/)
+  $(warning /./: abspath="$(abspath /./)")
+endif
+
+ifneq ($(abspath /.///),/)
+  $(warning /.///: abspath="$(abspath /.///)")
+endif
+
+ifneq ($(abspath /..),/)
+  $(warning /..: abspath="$(abspath /..)")
+endif
+
+ifneq ($(abspath ///..),/)
+  $(warning ///..: abspath="$(abspath ///..)")
+endif
+
+ifneq ($(abspath /../),/)
+  $(warning /../: abspath="$(abspath /../)")
+endif
+
+ifneq ($(abspath /..///),/)
+  $(warning /..///: abspath="$(abspath /..///)")
+endif
+
+
+ifneq ($(abspath /foo/bar/..),/foo)
+  $(warning /foo/bar/..: abspath="$(abspath /foo/bar/..)")
+endif
+
+ifneq ($(abspath /foo/bar/../../../baz),/baz)
+  $(warning /foo/bar/../../../baz: abspath="$(abspath /foo/bar/../../../baz)")
+endif
+
+ifneq ($(abspath /foo/bar/../ /..),/foo /)
+  $(warning /foo/bar/../ /..: abspath="$(abspath /foo/bar/../ /..)")
+endif
+
+
+.PHONY: all
+all: ; @:
+',
+'',
+'');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/addprefix
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/addprefix	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/addprefix	(revision 1780)
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the addprefix "
+              ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(addprefix src${pathsep},a.b.z.foo hacks) \n"
+              ."all: \n"
+              ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "src${pathsep}a.b.z.foo src${pathsep}hacks\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created.  You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/addsuffix
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/addsuffix	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/addsuffix	(revision 1780)
@@ -0,0 +1,36 @@
+#                                                                    -*-perl-*-
+$description = "Test the addsuffix function.";
+
+$details = "";
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOMAKE;
+string := \$(addsuffix .c,src${pathsep}a.b.z.foo hacks)
+one: ; \@echo \$(string)
+
+two: ; \@echo \$(addsuffix foo,)
+EOMAKE
+
+close(MAKEFILE);
+
+
+# TEST 0
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "src${pathsep}a.b.z.foo.c hacks.c\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST 1
+
+&run_make_with_options($makefile, "two", &get_logfile);
+$answer = "\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/andor
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/andor	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/andor	(revision 1780)
@@ -0,0 +1,50 @@
+#                                                                    -*-perl-*-
+$description = "Test the and & or functions.\n";
+
+$details = "Try various uses of and & or to ensure they all give the correct
+results.\n";
+
+# TEST #0
+# For $(and ...), it will either be empty or the last value
+run_make_test('
+NEQ = $(subst $1,,$2)
+f =
+t = true
+
+all:
+	@echo 1 $(and    ,$t)
+	@echo 2 $(and $t)
+	@echo 3 $(and $t,)
+	@echo 4 $(and z,true,$f,false)
+	@echo 5 $(and $t,$f,$(info bad short-circuit))
+	@echo 6 $(and $(call NEQ,a,b),true)
+	@echo 7 $(and $(call NEQ,a,a),true)
+	@echo 8 $(and z,true,fal,se) hi
+	@echo 9 $(and ,true,fal,se)there
+	@echo 10 $(and   $(e) ,$t)',
+              '',
+              "1\n2 true\n3\n4\n5\n6 true\n7\n8 se hi\n9 there\n10\n");
+
+# TEST #1
+# For $(or ...), it will either be empty or the first true value
+run_make_test('
+NEQ = $(subst $1,,$2)
+f =
+t = true
+
+all:
+	@echo 1 $(or    ,    )
+	@echo 2 $(or $t)
+	@echo 3 $(or ,$t)
+	@echo 4 $(or z,true,$f,false)
+	@echo 5 $(or $t,$(info bad short-circuit))
+	@echo 6 $(or $(info short-circuit),$t)
+	@echo 7 $(or $(call NEQ,a,b),true)
+	@echo 8 $(or $(call NEQ,a,a),true)
+	@echo 9 $(or z,true,fal,se) hi
+	@echo 10 $(or ,true,fal,se)there
+	@echo 11 $(or   $(e) ,$f)',
+              '',
+              "short-circuit\n1\n2 true\n3 true\n4 z\n5 true\n6 true\n7 b\n8 true\n9 z hi\n10 truethere\n11\n");
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/basename
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/basename	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/basename	(revision 1780)
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the suffix "
+              ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(basename src${pathsep}a.b.z.foo.c src${pathsep}hacks src.bar${pathsep}a.b.z.foo.c src.bar${pathsep}hacks hacks) \n"
+              ."all: \n"
+              ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "src${pathsep}a.b.z.foo src${pathsep}hacks src.bar${pathsep}a.b.z.foo src.bar${pathsep}hacks hacks\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created.  You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/call
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/call	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/call	(revision 1780)
@@ -0,0 +1,99 @@
+#                                                                    -*-perl-*-
+$description = "Test the call function.\n";
+
+$details = "Try various uses of call and ensure they all give the correct
+results.\n";
+
+open(MAKEFILE, "> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOMAKE';
+# Simple, just reverse two things
+#
+reverse = $2 $1
+
+# A complex `map' function, using recursive `call'.
+#
+map = $(foreach a,$2,$(call $1,$a))
+
+# Test using a builtin; this is silly as it's simpler to do without call
+#
+my-notdir = $(call notdir,$(1))
+
+# Test using non-expanded builtins
+#
+my-foreach = $(foreach $(1),$(2),$(3))
+my-if      = $(if $(1),$(2),$(3))
+
+# Test recursive invocations of call with different arguments
+#
+one = $(1) $(2) $(3)
+two = $(call one,$(1),foo,$(2))
+
+# Test recursion on the user-defined function.  As a special case make
+# won't error due to this.
+# Implement transitive closure using $(call ...)
+#
+DEP_foo = bar baz quux
+DEP_baz = quux blarp
+rest = $(wordlist 2,$(words ${1}),${1})
+tclose = $(if $1,$(firstword $1) \
+		$(call tclose,$(sort ${DEP_$(firstword $1)} $(call rest,$1))))
+
+all: ; @echo '$(call reverse,bar,foo)'; \
+        echo '$(call map,origin,MAKE reverse map)'; \
+        echo '$(call my-notdir,a/b   c/d      e/f)'; \
+        echo '$(call my-foreach)'; \
+        echo '$(call my-foreach,a,,,)'; \
+        echo '$(call my-if,a,b,c)'; \
+        echo '$(call two,bar,baz)'; \
+	echo '$(call tclose,foo)'
+
+
+
+EOMAKE
+
+# These won't work until/unless PR/1527 is resolved.
+#        echo '$(call my-foreach,a,x y z,$(a)$(a))'; \
+#        echo '$(call my-if,,$(warning don't print this),ok)'
+#
+# $answer = "xx yy zz\nok\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "foo bar\ndefault file file\nb d f\n\n\nb\nbar foo baz\nfoo bar baz blarp quux \n";
+&compare_output($answer, &get_logfile(1));
+
+
+# TEST eclipsing of arguments when invoking sub-calls
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE <<'EOF';
+
+all = $1 $2 $3 $4 $5 $6 $7 $8 $9
+
+level1 = $(call all,$1,$2,$3,$4,$5)
+level2 = $(call level1,$1,$2,$3)
+level3 = $(call level2,$1,$2,$3,$4,$5)
+
+all:
+	@echo $(call all,1,2,3,4,5,6,7,8,9,10,11)
+	@echo $(call level1,1,2,3,4,5,6,7,8)
+	@echo $(call level2,1,2,3,4,5,6,7,8)
+	@echo $(call level3,1,2,3,4,5,6,7,8)
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "", &get_logfile);
+$answer = "1 2 3 4 5 6 7 8 9\n1 2 3 4 5\n1 2 3\n1 2 3\n";
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/dir
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/dir	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/dir	(revision 1780)
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the dir "
+              ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(dir src${pathsep}foo.c hacks) \n"
+              ."all: \n"
+              ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "src${pathsep} .${pathsep}\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created.  You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/error
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/error	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/error	(revision 1780)
@@ -0,0 +1,73 @@
+#                                                                    -*-Perl-*-
+
+$description = "\
+The following test creates a makefile to test the error function.";
+
+$details = "";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE 'err = $(error Error found!)
+
+ifdef ERROR1
+$(error error is $(ERROR1))
+endif
+
+ifdef ERROR2
+$(error error is $(ERROR2))
+endif
+
+ifdef ERROR3
+all: some; @echo $(error error is $(ERROR3))
+endif
+
+ifdef ERROR4
+all: some; @echo error is $(ERROR4)
+	@echo $(error error is $(ERROR4))
+endif
+
+some: ; @echo Some stuff
+
+testvar: ; @: $(err)
+';
+
+close(MAKEFILE);
+
+# Test #1
+
+&run_make_with_options($makefile, "ERROR1=yes", &get_logfile, 512);
+$answer = "$makefile:4: *** error is yes.  Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #2
+
+&run_make_with_options($makefile, "ERROR2=no", &get_logfile, 512);
+$answer = "$makefile:8: *** error is no.  Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #3
+
+&run_make_with_options($makefile, "ERROR3=maybe", &get_logfile, 512);
+$answer = "Some stuff\n$makefile:12: *** error is maybe.  Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #4
+
+&run_make_with_options($makefile, "ERROR4=definitely", &get_logfile, 512);
+$answer = "Some stuff\n$makefile:16: *** error is definitely.  Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #5
+
+&run_make_with_options($makefile, "testvar", &get_logfile, 512);
+$answer = "$makefile:22: *** Error found!.  Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/eval
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/eval	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/eval	(revision 1780)
@@ -0,0 +1,169 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the eval function.";
+
+$details = "This is a test of the eval function in GNU make.
+This function will evaluate inline makefile syntax and incorporate the
+results into its internal database.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+define Y
+  all:: ; @echo $AA
+  A = B
+endef
+
+X = $(eval $(value Y))
+
+$(eval $(shell echo A = A))
+$(eval $(Y))
+$(eval A = C)
+$(eval $(X))
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "AA\nBA\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# Test to make sure defining variables when we have extra scope pushed works
+# as expected.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE <<'EOF';
+VARS = A B
+
+VARSET = $(1) = $(2)
+
+$(foreach v,$(VARS),$(eval $(call VARSET,$v,$v)))
+
+all: ; @echo A = $(A) B = $(B)
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "", &get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "A = A B = B\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# Test to make sure eval'ing inside conditionals works properly
+
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile3");
+
+print MAKEFILE <<'EOF';
+FOO = foo
+
+all:: ; @echo it
+
+define Y
+  all:: ; @echo worked
+endef
+
+ifdef BAR
+$(eval $(Y))
+endif
+
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile3, "", &get_logfile);
+$answer = "it\n";
+&compare_output($answer,&get_logfile(1));
+
+&run_make_with_options($makefile3, "BAR=1", &get_logfile);
+$answer = "it\nworked\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST very recursive invocation of eval
+
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile3");
+
+print MAKEFILE <<'EOF';
+..9 := 0 1 2 3 4 5 6 7 8 9
+rev=$(eval res:=)$(foreach word,$1,$(eval res:=${word} ${res}))${res}
+a:=$(call rev,${..9})
+all: ; @echo '[$(a)]'
+
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile3, "", &get_logfile);
+$answer = "[         9 8 7 6 5 4 3 2 1 0 ]\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST eval with no filename context.
+# The trick here is that because EVAR is taken from the environment, it must
+# be evaluated before every command is invoked.  Make sure that works, when
+# we have no file context for reading_file (bug # 6195)
+
+$makefile4 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile4");
+
+print MAKEFILE <<'EOF';
+EVAR = $(eval FOBAR = 1)
+all: ; @echo "OK"
+
+EOF
+
+close(MAKEFILE);
+
+$extraENV{EVAR} = '1';
+&run_make_with_options($makefile4, "", &get_logfile);
+$answer = "OK\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# Clean out previous information to allow new run_make_test() interface.
+# If we ever convert all the above to run_make_test() we can remove this line.
+$makefile = undef;
+
+# Test handling of backslashes in strings to be evaled.
+
+run_make_test('
+define FOO
+all: ; @echo hello \
+world
+endef
+$(eval $(FOO))
+', '', 'hello world');
+
+run_make_test('
+define FOO
+all: ; @echo '."'".'he\llo'."'".'
+	@echo world
+endef
+$(eval $(FOO))
+', '', 'he\llo
+world');
+
+
+# We don't allow new target/prerequisite relationships to be defined within a
+# command script, because these are evaluated after snap_deps() and that
+# causes lots of problems (like core dumps!)
+# See Savannah bug # 12124.
+
+run_make_test('deps: ; $(eval deps: foo)', '',
+              '#MAKEFILE#:1: *** prerequisites cannot be defined in command scripts.  Stop.',
+              512);
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/filter-out
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/filter-out	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/filter-out	(revision 1780)
@@ -0,0 +1,28 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the filter-out function.";
+
+$details = "The makefile created in this test has two variables.  The
+filter-out function is first used to discard names ending in
+.o with a single simple pattern.  The second filter-out function
+augments the simple pattern with three literal names, which are
+also added to the text argument.  This tests an internal hash table
+which is only used if there are multiple literals present in both
+the pattern and text arguments.  The result of both filter-out
+functions is the same single .elc name.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+files1 := $(filter-out %.o, foo.elc bar.o lose.o)
+files2 := $(filter-out foo.i bar.i lose.i %.o, foo.i bar.i lose.i foo.elc bar.o lose.o)
+all: ; @echo $(files1) $(files2)
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile, 0);
+$answer = "foo.elc foo.elc\n";
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/findstring
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/findstring	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/findstring	(revision 1780)
@@ -0,0 +1,47 @@
+$description = "The following test creates a makefile to test the findstring "
+              ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(findstring port, reporter)\n"
+              ."all: \n"
+              ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,
+                       "",
+                       &get_logfile,
+                       0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "port\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created.  You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/flavor
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/flavor	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/flavor	(revision 1780)
@@ -0,0 +1,44 @@
+#                                                                    -*-perl-*-
+$description = "Test the flavor function.";
+
+$details = "";
+
+
+# Test #1: Test general logic.
+#
+run_make_test('
+s := s
+r = r
+
+$(info u $(flavor u))
+$(info s $(flavor s))
+$(info r $(flavor r))
+
+ra += ra
+rc ?= rc
+
+$(info ra $(flavor ra))
+$(info rc $(flavor rc))
+
+s += s
+r += r
+
+$(info s $(flavor s))
+$(info r $(flavor r))
+
+
+.PHONY: all
+all:;@:
+',
+'',
+'u undefined
+s simple
+r recursive
+ra recursive
+rc recursive
+s simple
+r recursive');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/foreach
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/foreach	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/foreach	(revision 1780)
@@ -0,0 +1,77 @@
+#                                                                    -*-perl-*-
+# $Id: foreach,v 1.5 2006/03/10 02:20:46 psmith Exp $
+
+$description = "Test the foreach function.";
+
+$details = "This is a test of the foreach function in gnu make.
+This function starts with a space separated list of
+names and a variable. Each name in the list is subsituted
+into the variable and the given text evaluated. The general
+form of the command is $(foreach var,$list,$text). Several
+types of foreach loops are tested\n";
+
+
+# TEST 0
+
+# Set an environment variable that we can test in the makefile.
+$extraENV{FOOFOO} = 'foo foo';
+
+run_make_test("space = ' '".'
+null :=
+auto_var = udef space CC null FOOFOO MAKE foo CFLAGS WHITE @ <
+foo = bletch null @ garf
+av = $(foreach var, $(auto_var), $(origin $(var)) )
+override WHITE := BLACK
+for_var = $(addsuffix .c,foo $(null) $(foo) $(space) $(av) )
+fe = $(foreach var2, $(for_var),$(subst .c,.o, $(var2) ) )
+all: auto for2
+auto : ; @echo $(av)
+for2: ; @echo $(fe)',
+              '-e WHITE=WHITE CFLAGS=',
+              "undefined file default file environment default file command line override automatic automatic
+foo.o bletch.o null.o @.o garf.o .o    .o undefined.o file.o default.o file.o environment.o default.o file.o command.o line.o override.o automatic.o automatic.o");
+
+delete $extraENV{FOOFOO};
+
+# TEST 1: Test that foreach variables take precedence over global
+# variables in a global scope (like inside an eval).  Tests bug #11913
+
+run_make_test('
+.PHONY: all target
+all: target
+
+x := BAD
+
+define mktarget
+target: x := $(x)
+target: ; @echo "$(x)"
+endef
+
+x := GLOBAL
+
+$(foreach x,FOREACH,$(eval $(value mktarget)))',
+              '',
+              'FOREACH');
+
+
+# TEST 2: Check some error conditions.
+
+run_make_test('
+x = $(foreach )
+y = $x
+
+all: ; @echo $y',
+              '',
+              "#MAKEFILE#:2: *** insufficient number of arguments (1) to function `foreach'.  Stop.",
+              512);
+
+run_make_test('
+x = $(foreach )
+y := $x
+
+all: ; @echo $y',
+              '',
+              "#MAKEFILE#:2: *** insufficient number of arguments (1) to function `foreach'.  Stop.",
+              512);
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/if
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/if	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/if	(revision 1780)
@@ -0,0 +1,33 @@
+#                                                                    -*-perl-*-
+$description = "Test the if function.\n";
+
+$details = "Try various uses of if and ensure they all give the correct
+results.\n";
+
+open(MAKEFILE, "> $makefile");
+
+print MAKEFILE <<EOMAKE;
+NEQ = \$(subst \$1,,\$2)
+e =
+
+all:
+\t\@echo 1 \$(if    ,true,false)
+\t\@echo 2 \$(if ,true,)
+\t\@echo 3 \$(if ,true)
+\t\@echo 4 \$(if z,true,false)
+\t\@echo 5 \$(if z,true,\$(shell echo hi))
+\t\@echo 6 \$(if ,\$(shell echo hi),false)
+\t\@echo 7 \$(if \$(call NEQ,a,b),true,false)
+\t\@echo 8 \$(if \$(call NEQ,a,a),true,false)
+\t\@echo 9 \$(if z,true,fal,se) hi
+\t\@echo 10 \$(if ,true,fal,se)there
+\t\@echo 11 \$(if \$(e) ,true,false)
+EOMAKE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "1 false\n2\n3\n4 true\n5 true\n6 false\n7 true\n8 false\n9 true hi\n10 fal,sethere\n11 false\n";
+&compare_output($answer, &get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/join
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/join	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/join	(revision 1780)
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the join "
+              ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(join a b c,foo      hacks .pl1) \n"
+              ."all: \n"
+              ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "afoo bhacks c.pl1\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created.  You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/notdir
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/notdir	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/notdir	(revision 1780)
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the notdir "
+              ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(notdir ${pathsep}src${pathsep}foo.c hacks) \n"
+              ."all: \n"
+              ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "foo.c hacks\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created.  You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/origin
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/origin	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/origin	(revision 1780)
@@ -0,0 +1,51 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the origin function.";
+
+$details = "This is a test of the origin function in gnu make.
+This function will report on where a variable was
+defined per the following list:
+
+'undefined'            never defined
+'default'              default definition
+'environment'          environment var without -e
+'environment override' environment var with    -e
+'file'                 defined in makefile
+'command line'         defined on the command line
+'override'             defined by override in makefile
+'automatic'            Automatic variable\n";
+
+# Set an environment variable
+$extraENV{MAKETEST} = 1;
+
+run_make_test('
+foo := bletch garf
+auto_var = undefined CC MAKETEST MAKE foo CFLAGS WHITE @
+av = $(foreach var, $(auto_var), $(origin $(var)) )
+override WHITE := BLACK
+all: auto
+	@echo $(origin undefined)
+	@echo $(origin CC)
+	@echo $(origin MAKETEST)
+	@echo $(origin MAKE)
+	@echo $(origin foo)
+	@echo $(origin CFLAGS)
+	@echo $(origin WHITE)
+	@echo $(origin @)
+auto :
+	@echo $(av)',
+	      '-e WHITE=WHITE CFLAGS=',
+	      'undefined default environment default file command line override automatic
+undefined
+default
+environment
+default
+file
+command line
+override
+automatic');
+
+# Reset an environment variable
+delete $extraENV{MAKETEST};
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/realpath
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/realpath	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/realpath	(revision 1780)
@@ -0,0 +1,82 @@
+#                                                                    -*-perl-*-
+$description = "Test the realpath functions.";
+
+$details = "";
+
+run_make_test('
+ifneq ($(realpath .),$(CURDIR))
+  $(error )
+endif
+
+ifneq ($(realpath ./),$(CURDIR))
+  $(error )
+endif
+
+ifneq ($(realpath .///),$(CURDIR))
+  $(error )
+endif
+
+ifneq ($(realpath /),/)
+  $(error )
+endif
+
+ifneq ($(realpath /.),/)
+  $(error )
+endif
+
+ifneq ($(realpath /./),/)
+  $(error )
+endif
+
+ifneq ($(realpath /.///),/)
+  $(error )
+endif
+
+ifneq ($(realpath /..),/)
+  $(error )
+endif
+
+ifneq ($(realpath /../),/)
+  $(error )
+endif
+
+ifneq ($(realpath /..///),/)
+  $(error )
+endif
+
+ifneq ($(realpath . /..),$(CURDIR) /)
+  $(error )
+endif
+
+.PHONY: all
+all: ; @:
+',
+              '',
+              '');
+
+# On Windows platforms, "//" means something special.  So, don't do these
+# tests there.
+
+if ($port_type ne 'W32') {
+  run_make_test('
+ifneq ($(realpath ///),/)
+  $(error )
+endif
+
+ifneq ($(realpath ///.),/)
+  $(error )
+endif
+
+ifneq ($(realpath ///..),/)
+  $(error )
+endif
+
+.PHONY: all
+all: ; @:',
+                '',
+                '');
+}
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/shell
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/shell	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/shell	(revision 1780)
@@ -0,0 +1,23 @@
+#                                                                    -*-perl-*-
+
+$description = 'Test the $(shell ...) function.';
+
+$details = '';
+
+
+# Test shells inside rules.
+run_make_test('.PHONY: all
+all: ; @echo $(shell echo hi)
+','','hi');
+
+
+# Test shells inside exported environment variables.
+# This is the test that fails if we try to put make exported variables into
+# the environment for a $(shell ...) call.
+run_make_test('
+export HI = $(shell echo hi)
+.PHONY: all
+all: ; @echo $$HI
+','','hi');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/sort
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/sort	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/sort	(revision 1780)
@@ -0,0 +1,55 @@
+$description = "The following test creates a makefile to verify\n"
+              ."the ability of make to sort lists of object. Sort\n"
+              ."will also remove any duplicate entries. This will also\n"
+              ."be tested.";
+
+$details = "The make file is built with a list of object in a random order\n"
+          ."and includes some duplicates. Make should sort all of the elements\n"
+          ."remove all duplicates\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "foo := moon_light days \n"
+              ."foo1:= jazz\n"
+              ."bar := captured \n"
+              ."bar2 = boy end, has rise A midnight \n"
+              ."bar3:= \$(foo)\n"
+              ."s1  := _by\n"
+              ."s2  := _and_a\n"
+              ."t1  := \$(addsuffix \$(s1), \$(bar) )\n"
+              ."t2  := \$(addsuffix \$(s2), \$(foo1) )\n" 
+              ."t3  := \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \$(t2) \n"
+              ."t4  := \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \$(t3) \n"
+              ."t5  := \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \$(t4) \n"
+              ."t6  := \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \$(t5) \n"
+              ."t7  := \$(t6) \$(t6) \$(t6) \n"
+              ."p1  := \$(addprefix \$(foo1), \$(s2) )\n"
+              ."blank:= \n"
+              ."all:\n"
+              ."\t\@echo \$(sort \$(bar2) \$(foo)  \$(addsuffix \$(s1), \$(bar) ) \$(t2) \$(bar2) \$(bar3))\n"
+              ."\t\@echo \$(sort \$(blank) \$(foo) \$(bar2) \$(t1) \$(p1) )\n"
+              ."\t\@echo \$(sort \$(foo) \$(bar2) \$(t1) \$(t4) \$(t5) \$(t7) \$(t6) )\n";
+
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "A boy captured_by days end, has jazz_and_a midnight moon_light rise\n"
+         ."A boy captured_by days end, has jazz_and_a midnight moon_light rise\n"
+         ."A boy captured_by days end, has jazz_and_a midnight moon_light rise\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/strip
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/strip	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/strip	(revision 1780)
@@ -0,0 +1,57 @@
+#                                                                    -*-perl-*-
+$description = "The following test creates a makefile to verify
+the ability of make to strip white space from lists of object.\n";
+
+
+$details = "The make file is built with a list of objects that contain white space
+These are then run through the strip command to remove it. This is then
+verified by echoing the result.\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOMAKE';
+TEST1 := "Is this TERMINAL fun?                                                               What makes you believe is this terminal fun?                                                                                                                                               JAPAN is a WONDERFUL planet -- I wonder if we will ever reach                                         their level of COMPARATIVE SHOPPING..."
+E :=
+TEST2 := $E   try this     and		this     	$E
+
+define TEST3
+
+and these	        test out
+
+
+some
+blank lines
+
+
+
+endef
+
+.PHONY: all
+all:
+	@echo '$(strip  $(TEST1) )'
+	@echo '$(strip  $(TEST2) )'
+	@echo '$(strip  $(TEST3) )'
+
+space: ; @echo '$(strip ) $(strip  	   )'
+
+EOMAKE
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile);
+$answer = "\"Is this TERMINAL fun? What makes you believe is this terminal fun? JAPAN is a WONDERFUL planet -- I wonder if we will ever reach their level of COMPARATIVE SHOPPING...\"
+try this and this
+and these test out some blank lines
+";
+&compare_output($answer,&get_logfile(1));
+
+
+&run_make_with_options($makefile,"space",&get_logfile);
+$answer = " \n";
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/substitution
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/substitution	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/substitution	(revision 1780)
@@ -0,0 +1,38 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the subst and patsubst functions";
+
+$details = "";
+
+# Generic patsubst test: test both the function and variable form.
+
+run_make_test('
+foo := a.o b.o c.o
+bar := $(foo:.o=.c)
+bar2:= $(foo:%.o=%.c)
+bar3:= $(patsubst %.c,%.o,x.c.c bar.c)
+all:;@echo $(bar); echo $(bar2); echo $(bar3)',
+'',
+'a.c b.c c.c
+a.c b.c c.c
+x.c.o bar.o');
+
+# Patsubst without '%'--shouldn't match because the whole word has to match
+# in patsubst.  Based on a bug report by Markus Mauhart <qwe123@chello.at>
+
+run_make_test('all:;@echo $(patsubst Foo,Repl,FooFoo)', '', 'FooFoo');
+
+# Variable subst where a pattern matches multiple times in a single word.
+# Based on a bug report by Markus Mauhart <qwe123@chello.at>
+
+run_make_test('
+A := fooBARfooBARfoo
+all:;@echo $(A:fooBARfoo=REPL)', '', 'fooBARREPL');
+
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/suffix
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/suffix	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/suffix	(revision 1780)
@@ -0,0 +1,57 @@
+$description = "The following test creates a makefile to test the suffix\n"
+              ."function. \n";
+
+$details = "The suffix function will return the string following the last _._\n"
+          ."the list provided. It will provide all of the unique suffixes found\n"
+          ."in the list. The long strings are sorted to remove duplicates.\n";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string  := word.pl general_test2.pl1 FORCE.pl word.pl3 generic_test.perl /tmp.c/bar foo.baz/bar.c MAKEFILES_variable.c\n"
+              ."string2 := \$(string) \$(string) \$(string) \$(string) \$(string) \$(string) \$(string)\n"
+              ."string3 := \$(string2) \$(string2) \$(string2) \$(string2) \$(string2) \$(string2) \$(string2)\n"
+              ."string4 := \$(string3) \$(string3) \$(string3) \$(string3) \$(string3) \$(string3) \$(string3)\n"
+              ."all: \n"
+              ."\t\@echo \$(suffix \$(string)) \n"
+              ."\t\@echo \$(sort \$(suffix \$(string4))) \n"
+              ."\t\@echo \$(suffix \$(string) a.out) \n"
+              ."\t\@echo \$(sort \$(suffix \$(string3))) \n";
+
+
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+
+# COMPARE RESULTS
+$answer = ".pl .pl1 .pl .pl3 .perl .c .c\n"
+         .".c .perl .pl .pl1 .pl3\n"
+         .".pl .pl1 .pl .pl3 .perl .c .c .out\n"
+         .".c .perl .pl .pl1 .pl3\n";
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created.  You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/value
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/value	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/value	(revision 1780)
@@ -0,0 +1,30 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the value function.";
+
+$details = "This is a test of the value function in GNU make.
+This function will evaluate to the value of the named variable with no
+further expansion performed on it.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+export FOO = foo
+
+recurse = FOO = $FOO
+static := FOO = $(value FOO)
+
+all: ; @echo $(recurse) $(value recurse) $(static) $(value static)
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "FOO = OO FOO = foo FOO = foo FOO = foo\n";
+
+
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/warning
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/warning	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/warning	(revision 1780)
@@ -0,0 +1,65 @@
+#                                                                    -*-Perl-*-
+
+$description = "\
+The following test creates a makefile to test the warning function.";
+
+$details = "";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+ifdef WARNING1
+$(warning warning is $(WARNING1))
+endif
+
+ifdef WARNING2
+$(warning warning is $(WARNING2))
+endif
+
+ifdef WARNING3
+all: some; @echo hi $(warning warning is $(WARNING3))
+endif
+
+ifdef WARNING4
+all: some; @echo hi
+	@echo there $(warning warning is $(WARNING4))
+endif
+
+some: ; @echo Some stuff
+
+EOF
+
+close(MAKEFILE);
+
+# Test #1
+
+&run_make_with_options($makefile, "WARNING1=yes", &get_logfile, 0);
+$answer = "$makefile:2: warning is yes\nSome stuff\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #2
+
+&run_make_with_options($makefile, "WARNING2=no", &get_logfile, 0);
+$answer = "$makefile:6: warning is no\nSome stuff\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #3
+
+&run_make_with_options($makefile, "WARNING3=maybe", &get_logfile, 0);
+$answer = "Some stuff\n$makefile:10: warning is maybe\nhi\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #4
+
+&run_make_with_options($makefile, "WARNING4=definitely", &get_logfile, 0);
+$answer = "Some stuff\n$makefile:14: warning is definitely\nhi\nthere\n";
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/wildcard
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/wildcard	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/wildcard	(revision 1780)
@@ -0,0 +1,94 @@
+#                                                                    -*-perl-*-
+
+$description = "The following test creates a makefile to test wildcard
+expansions and the ability to put a command on the same
+line as the target name separated by a semi-colon.";
+
+$details = "\
+This test creates 4 files by the names of 1.example,
+two.example and 3.example.  We execute three tests.  The first
+executes the print1 target which tests the '*' wildcard by
+echoing all filenames by the name of '*.example'.  The second
+test echo's all files which match '?.example' and
+[a-z0-9].example.  Lastly we clean up all of the files using
+the '*' wildcard as in the first test";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOM;
+.PHONY: print1 print2 clean
+print1: ;\@echo \$(sort \$(wildcard example.*))
+print2:
+\t\@echo \$(sort \$(wildcard example.?))
+\t\@echo \$(sort \$(wildcard example.[a-z0-9]))
+\t\@echo \$(sort \$(wildcard example.[!A-Za-z_\\!]))
+clean:
+\t$delete_command \$(sort \$(wildcard example.*))
+EOM
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch("example.1");
+&touch("example.two");
+&touch("example.3");
+&touch("example.for");
+&touch("example._");
+
+# TEST #1
+# -------
+
+$answer = "example.1 example.3 example._ example.for example.two\n";
+
+&run_make_with_options($makefile,"print1",&get_logfile);
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2
+# -------
+
+$answer = "example.1 example.3 example._\n"
+         ."example.1 example.3\n"
+         ."example.1 example.3\n";
+
+&run_make_with_options($makefile,"print2",&get_logfile);
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #3
+# -------
+
+$answer = "$delete_command example.1 example.3 example._ example.for example.two";
+if ($vos)
+{
+   $answer .= " \n";
+}
+else
+{
+   $answer .= "\n";
+}
+
+&run_make_with_options($makefile,"clean",&get_logfile);
+
+if ((-f "example.1")||(-f "example.two")||(-f "example.3")||(-f "example.for")) {
+   $test_passed = 0;
+}
+
+&compare_output($answer,&get_logfile(1));
+
+
+1;
+
+
+
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/word
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/word	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/functions/word	(revision 1780)
@@ -0,0 +1,167 @@
+#                                                                    -*-perl-*-
+$description = "\
+Test the word, words, wordlist, firstword, and lastword functions.\n";
+
+$details = "\
+Produce a variable with a large number of words in it,
+determine the number of words, and then read each one back.\n";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE <<'EOF';
+string  := word.pl general_test2.pl   FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl
+string2 := $(string) $(string) $(string) $(string) $(string) $(string) $(string)
+string3 := $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) $(string2)
+string4 := $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) $(string3)
+all:
+	@echo $(words $(string))
+	@echo $(words $(string4))
+	@echo $(word 1, $(string))
+	@echo $(word 100, $(string))
+	@echo $(word 1, $(string))
+	@echo $(word 1000, $(string3))
+	@echo $(wordlist 3, 4, $(string))
+	@echo $(wordlist 4, 3, $(string))
+	@echo $(wordlist 1, 6, $(string))
+	@echo $(wordlist 5, 7, $(string))
+	@echo $(wordlist 100, 110, $(string))
+	@echo $(wordlist 7, 10, $(string2))
+EOF
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "6\n"
+         ."2058\n"
+         ."word.pl\n"
+         ."\n"
+         ."word.pl\n"
+         ."\n"
+	 ."FORCE.pl word.pl\n"
+	 ."\n"
+	 ."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n"
+	 ."generic_test.perl MAKEFILES_variable.pl\n"
+	 ."\n"
+	 ."word.pl general_test2.pl FORCE.pl word.pl\n";
+&compare_output($answer, &get_logfile(1));
+
+
+# Test error conditions
+
+run_make_test('FOO = foo bar biz baz
+
+word-e1: ; @echo $(word ,$(FOO))
+word-e2: ; @echo $(word abc ,$(FOO))
+word-e3: ; @echo $(word 1a,$(FOO))
+
+wordlist-e1: ; @echo $(wordlist ,,$(FOO))
+wordlist-e2: ; @echo $(wordlist abc ,,$(FOO))
+wordlist-e3: ; @echo $(wordlist 1, 12a ,$(FOO))',
+              'word-e1',
+              "#MAKEFILE#:3: *** non-numeric first argument to `word' function: ''.  Stop.",
+              512);
+
+run_make_test(undef,
+              'word-e2',
+              "#MAKEFILE#:4: *** non-numeric first argument to `word' function: 'abc '.  Stop.",
+              512);
+
+run_make_test(undef,
+              'word-e3',
+              "#MAKEFILE#:5: *** non-numeric first argument to `word' function: '1a'.  Stop.",
+              512);
+
+run_make_test(undef,
+              'wordlist-e1',
+              "#MAKEFILE#:7: *** non-numeric first argument to `wordlist' function: ''.  Stop.",
+              512);
+
+run_make_test(undef,
+              'wordlist-e2',
+              "#MAKEFILE#:8: *** non-numeric first argument to `wordlist' function: 'abc '.  Stop.",
+              512);
+
+run_make_test(undef,
+              'wordlist-e3',
+              "#MAKEFILE#:9: *** non-numeric second argument to `wordlist' function: ' 12a '.  Stop.",
+              512);
+
+# Test error conditions again, but this time in a variable reference
+
+run_make_test('FOO = foo bar biz baz
+
+W = $(word $x,$(FOO))
+WL = $(wordlist $s,$e,$(FOO))
+
+word-e: ; @echo $(W)
+wordlist-e: ; @echo $(WL)',
+              'word-e x=',
+              "#MAKEFILE#:3: *** non-numeric first argument to `word' function: ''.  Stop.",
+              512);
+
+run_make_test(undef,
+              'word-e x=abc',
+              "#MAKEFILE#:3: *** non-numeric first argument to `word' function: 'abc'.  Stop.",
+              512);
+
+run_make_test(undef,
+              'word-e x=0',
+              "#MAKEFILE#:3: *** first argument to `word' function must be greater than 0.  Stop.",
+              512);
+
+run_make_test(undef,
+              'wordlist-e s= e=',
+              "#MAKEFILE#:4: *** non-numeric first argument to `wordlist' function: ''.  Stop.",
+              512);
+
+run_make_test(undef,
+              'wordlist-e s=abc e=',
+              "#MAKEFILE#:4: *** non-numeric first argument to `wordlist' function: 'abc'.  Stop.",
+              512);
+
+run_make_test(undef,
+              'wordlist-e s=4 e=12a',
+              "#MAKEFILE#:4: *** non-numeric second argument to `wordlist' function: '12a'.  Stop.",
+              512);
+
+run_make_test(undef,
+              'wordlist-e s=0 e=12',
+              "#MAKEFILE#:4: *** invalid first argument to `wordlist' function: `0'.  Stop.",
+              512);
+
+
+# TEST #8 -- test $(firstword )
+#
+run_make_test('
+void :=
+list := $(void) foo bar baz #
+
+a := $(word 1,$(list))
+b := $(firstword $(list))
+
+.PHONY: all
+
+all:
+	@test "$a" = "$b" && echo $a
+',
+'',
+'foo');
+
+
+# TEST #9 -- test $(lastword )
+#
+run_make_test('
+void :=
+list := $(void) foo bar baz #
+
+a := $(word $(words $(list)),$(list))
+b := $(lastword $(list))
+
+.PHONY: all
+
+all:
+	@test "$a" = "$b" && echo $a
+',
+'',
+'baz');
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/close_stdout
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/close_stdout	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/close_stdout	(revision 1780)
@@ -0,0 +1,9 @@
+#                                                                    -*-perl-*-
+
+$description = "Make sure make exits with an error if stdout is full.";
+
+if (-e '/dev/full') {
+  run_make_test('', '-v > /dev/full', '#MAKE#: write error', 256);
+}
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general1
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general1	(revision 1780)
@@ -0,0 +1,51 @@
+#                                                                    -*-perl-*-
+
+$description = "The following test creates a makefile to test the
+simple functionality of make.  It mimics the
+rebuilding of a product with dependencies.
+It also tests the simple definition of VPATH.";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<EOF;
+VPATH = $workdir
+edit:  main.o kbd.o commands.o display.o \\
+       insert.o
+\t\@echo cc -o edit main.o kbd.o commands.o display.o \\
+                  insert.o
+main.o : main.c defs.h
+\t\@echo cc -c main.c
+kbd.o : kbd.c defs.h command.h
+\t\@echo cc -c kbd.c
+commands.o : command.c defs.h command.h
+\t\@echo cc -c commands.c
+display.o : display.c defs.h buffer.h
+\t\@echo cc -c display.c
+insert.o : insert.c defs.h buffer.h
+\t\@echo cc -c insert.c
+EOF
+
+close(MAKEFILE);
+
+
+@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
+               "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
+               "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+               "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
+	       "$workdir${pathsep}command.c");
+
+&touch(@files_to_touch);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "cc -c main.c\ncc -c kbd.c\ncc -c commands.c\ncc -c display.c
+cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o insert.o\n";
+
+# COMPARE RESULTS
+
+if (&compare_output($answer,&get_logfile(1))) {
+  unlink @files_to_touch;
+}
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general2
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general2	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general2	(revision 1780)
@@ -0,0 +1,50 @@
+#                                                                    -*-perl-*-
+
+$description = "The following test creates a makefile to test the
+simple functionality of make.  It is the same as
+general_test1 except that this one tests the
+definition of a variable to hold the object filenames.";
+
+open(MAKEFILE,"> $makefile");
+
+# The contents of the Makefile ...
+
+print MAKEFILE <<EOF;
+VPATH = $workdir
+objects = main.o kbd.o commands.o display.o insert.o
+edit:  \$(objects)
+\t\@echo cc -o edit \$(objects)
+main.o : main.c defs.h
+\t\@echo cc -c main.c
+kbd.o : kbd.c defs.h command.h
+\t\@echo cc -c kbd.c
+commands.o : command.c defs.h command.h
+\t\@echo cc -c commands.c
+display.o : display.c defs.h buffer.h
+\t\@echo cc -c display.c
+insert.o : insert.c defs.h buffer.h
+\t\@echo cc -c insert.c
+EOF
+
+close(MAKEFILE);
+
+
+@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
+               "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
+               "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+               "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
+	       "$workdir${pathsep}command.c");
+
+&touch(@files_to_touch);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "cc -c main.c\ncc -c kbd.c\ncc -c commands.c\ncc -c display.c
+cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o insert.o\n";
+
+if (&compare_output($answer,&get_logfile(1))) {
+  unlink @files_to_touch;
+}
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general3
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general3	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general3	(revision 1780)
@@ -0,0 +1,313 @@
+#                                                                    -*-perl-*-
+
+$description = "\
+This tests random features of the parser that need to be supported, and
+which have either broken at some point in the past or seem likely to
+break.";
+
+run_make_test("
+# We want to allow both empty commands _and_ commands that resolve to empty.
+EMPTY =
+
+.PHONY: all a1 a2 a3 a4
+all: a1 a2 a3 a4
+
+a1:;
+a2:
+\t
+a3:;\$(EMPTY)
+a4:
+\t\$(EMPTY)
+
+\# Non-empty lines that expand to nothing should also be ignored.
+STR =     \# Some spaces
+TAB =   \t  \# A TAB and some spaces
+
+\$(STR)
+
+\$(STR) \$(TAB)",
+              '', "#MAKE#: Nothing to be done for `all'.");
+
+# TEST 2
+
+# Make sure files without trailing newlines are handled properly.
+# Have to use the old style invocation to test this.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE "all:;\@echo FOO = \$(FOO)\nFOO = foo";
+close(MAKEFILE);
+
+&run_make_with_options($makefile2,"",&get_logfile);
+$answer = "FOO = foo\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST 3
+
+# Check semicolons in variable references
+
+run_make_test('
+$(if true,$(info true; true))
+all: ; @:
+',
+              '', 'true; true');
+
+# TEST 4
+
+# Check that backslashes in command scripts are handled according to POSIX.
+# Checks Savannah bug # 1332.
+
+# Test the fastpath / no quotes
+run_make_test('
+all:
+	@echo foo\
+bar
+	@echo foo\
+	bar
+	@echo foo\
+    bar
+	@echo foo\
+	    bar
+	@echo foo \
+bar
+	@echo foo \
+	bar
+	@echo foo \
+    bar
+	@echo foo \
+	    bar
+',
+              '', 'foobar
+foobar
+foo bar
+foo bar
+foo bar
+foo bar
+foo bar
+foo bar');
+
+# Test the fastpath / single quotes
+run_make_test("
+all:
+	\@echo 'foo\\
+bar'
+	\@echo 'foo\\
+	bar'
+	\@echo 'foo\\
+    bar'
+	\@echo 'foo\\
+	    bar'
+	\@echo 'foo \\
+bar'
+	\@echo 'foo \\
+	bar'
+	\@echo 'foo \\
+    bar'
+	\@echo 'foo \\
+	    bar'
+",
+              '', 'foo\
+bar
+foo\
+bar
+foo\
+    bar
+foo\
+    bar
+foo \
+bar
+foo \
+bar
+foo \
+    bar
+foo \
+    bar');
+
+# Test the fastpath / double quotes
+run_make_test('
+all:
+	@echo "foo\
+bar"
+	@echo "foo\
+	bar"
+	@echo "foo\
+    bar"
+	@echo "foo\
+	    bar"
+	@echo "foo \
+bar"
+	@echo "foo \
+	bar"
+	@echo "foo \
+    bar"
+	@echo "foo \
+	    bar"
+',
+              '', 'foobar
+foobar
+foo    bar
+foo    bar
+foo bar
+foo bar
+foo     bar
+foo     bar');
+
+# Test the slow path / no quotes
+run_make_test('
+all:
+	@echo hi; echo foo\
+bar
+	@echo hi; echo foo\
+	bar
+	@echo hi; echo foo\
+ bar
+	@echo hi; echo foo\
+	 bar
+	@echo hi; echo foo \
+bar
+	@echo hi; echo foo \
+	bar
+	@echo hi; echo foo \
+ bar
+	@echo hi; echo foo \
+	 bar
+',
+              '', 'hi
+foobar
+hi
+foobar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar');
+
+# Test the slow path / no quotes.  This time we put the slow path
+# determination _after_ the backslash-newline handling.
+run_make_test('
+all:
+	@echo foo\
+bar; echo hi
+	@echo foo\
+	bar; echo hi
+	@echo foo\
+ bar; echo hi
+	@echo foo\
+	 bar; echo hi
+	@echo foo \
+bar; echo hi
+	@echo foo \
+	bar; echo hi
+	@echo foo \
+ bar; echo hi
+	@echo foo \
+	 bar; echo hi
+',
+              '', 'foobar
+hi
+foobar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi');
+
+# Test the slow path / single quotes
+run_make_test("
+all:
+	\@echo hi; echo 'foo\\
+bar'
+	\@echo hi; echo 'foo\\
+	bar'
+	\@echo hi; echo 'foo\\
+    bar'
+	\@echo hi; echo 'foo\\
+	    bar'
+	\@echo hi; echo 'foo \\
+bar'
+	\@echo hi; echo 'foo \\
+	bar'
+	\@echo hi; echo 'foo \\
+    bar'
+	\@echo hi; echo 'foo \\
+	    bar'
+",
+              '', 'hi
+foo\
+bar
+hi
+foo\
+bar
+hi
+foo\
+    bar
+hi
+foo\
+    bar
+hi
+foo \
+bar
+hi
+foo \
+bar
+hi
+foo \
+    bar
+hi
+foo \
+    bar');
+
+# Test the slow path / double quotes
+run_make_test('
+all:
+	@echo hi; echo "foo\
+bar"
+	@echo hi; echo "foo\
+	bar"
+	@echo hi; echo "foo\
+    bar"
+	@echo hi; echo "foo\
+	    bar"
+	@echo hi; echo "foo \
+bar"
+	@echo hi; echo "foo \
+	bar"
+	@echo hi; echo "foo \
+    bar"
+	@echo hi; echo "foo \
+	    bar"
+',
+              '', 'hi
+foobar
+hi
+foobar
+hi
+foo    bar
+hi
+foo    bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo     bar
+hi
+foo     bar');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general4
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/misc/general4	(revision 1780)
@@ -0,0 +1,83 @@
+#                                                                    -*-perl-*-
+
+$description = "\
+This tests random features of make's algorithms, often somewhat obscure,
+which have either broken at some point in the past or seem likely to
+break.";
+
+run_make_test('
+# Make sure that subdirectories built as prerequisites are actually handled
+# properly.
+
+all: dir/subdir/file.a
+
+dir/subdir: ; @echo mkdir -p dir/subdir
+
+dir/subdir/file.b: dir/subdir ; @echo touch dir/subdir/file.b
+
+dir/subdir/%.a: dir/subdir/%.b ; @echo cp $< $@',
+              '', "mkdir -p dir/subdir\ntouch dir/subdir/file.b\ncp dir/subdir/file.b dir/subdir/file.a\n");
+
+# Test implicit rules
+
+&touch('foo.c');
+run_make_test('foo: foo.o',
+              'CC="@echo cc" OUTPUT_OPTION=',
+              'cc -c foo.c
+cc foo.o -o foo');
+unlink('foo.c');
+
+
+# Test other implicit rule searching
+
+&touch('bar');
+run_make_test('
+test.foo:
+%.foo : baz ; @echo done $<
+%.foo : bar ; @echo done $<
+fox: baz
+',
+              '',
+              'done bar');
+unlink('bar');
+
+
+# Test implicit rules with '$' in the name (see se_implicit)
+
+run_make_test(q!
+%.foo : baz$$bar ; @echo 'done $<'
+%.foo : bar$$baz ; @echo 'done $<'
+test.foo:
+baz$$bar bar$$baz: ; @echo '$@'
+!,
+              '',
+              "baz\$bar\ndone baz\$bar");
+
+
+# Test implicit rules with '$' in the name (see se_implicit)
+# Use the '$' in the pattern.
+
+run_make_test(q!
+%.foo : %$$bar ; @echo 'done $<'
+test.foo:
+test$$bar: ; @echo '$@'
+!,
+              '',
+              "test\$bar\ndone test\$bar");
+
+# Make sure that subdirectories built as prerequisites are actually handled
+# properly... this time with '$'
+
+run_make_test(q!
+
+all: dir/subdir/file.$$a
+
+dir/subdir: ; @echo mkdir -p '$@'
+
+dir/subdir/file.$$b: dir/subdir ; @echo touch '$@'
+
+dir/subdir/%.$$a: dir/subdir/%.$$b ; @echo 'cp $< $@'
+!,
+              '', "mkdir -p dir/subdir\ntouch dir/subdir/file.\$b\ncp dir/subdir/file.\$b dir/subdir/file.\$a\n");
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-B
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-B	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-B	(revision 1780)
@@ -0,0 +1,73 @@
+#                                                                    -*-perl-*-
+
+$description = "Test make -B (always remake) option.\n";
+
+$details = "\
+Construct a simple makefile that builds a target.
+Invoke make once, so it builds everything.  Invoke it again and verify
+that nothing is built.  Then invoke it with -B and verify that everything
+is built again.";
+
+&touch('bar.x');
+
+run_make_test('
+.SUFFIXES:
+
+.PHONY: all
+all: foo
+
+foo: bar.x
+	@echo cp $< $@
+	@echo "" > $@
+',
+              '', 'cp bar.x foo');
+
+run_make_test(undef, '', "#MAKE#: Nothing to be done for `all'.");
+run_make_test(undef, '-B', 'cp bar.x foo');
+
+# Put the timestamp for foo into the future; it should still be remade.
+
+utouch(1000, 'foo');
+run_make_test(undef, '', "#MAKE#: Nothing to be done for `all'.");
+run_make_test(undef, '-B', 'cp bar.x foo');
+
+# Clean up
+
+rmfiles('bar.x', 'foo');
+
+# Test -B with the re-exec feature: we don't want to re-exec forever
+# Savannah bug # 7566
+
+run_make_test('
+all: ; @:
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @touch $@
+',
+              '-B', 'MAKE_RESTARTS=
+#MAKEFILE#:4: foo.x: No such file or directory
+MAKE_RESTARTS=1');
+
+rmfiles('foo.x');
+
+# Test -B with the re-exec feature: we DO want -B in the "normal" part of the
+# makefile.
+
+&touch('blah.x');
+
+run_make_test('
+all: blah.x ; @echo $@
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @touch $@
+blah.x: ; @echo $@
+',
+              '-B', 'MAKE_RESTARTS=
+#MAKEFILE#:4: foo.x: No such file or directory
+MAKE_RESTARTS=1
+blah.x
+all');
+
+rmfiles('foo.x', 'blah.x');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-C
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-C	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-C	(revision 1780)
@@ -0,0 +1,71 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the -C option to GNU make.";
+
+$details = "\
+This test is similar to the clean test except that this test creates the file
+to delete in the work directory instead of the current directory.  Make is
+called from another directory using the -C workdir option so that it can both
+find the makefile and the file to delete in the work directory.";
+
+$example = $workdir . $pathsep . "EXAMPLE";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE <<EOF;
+all: ; \@echo This makefile did not clean the dir ... good
+clean: ; $delete_command EXAMPLE\$(ext)
+EOF
+close(MAKEFILE);
+
+# TEST #1
+# -------
+&touch($example);
+
+&run_make_with_options("${testname}.mk",
+	               "-C $workdir clean",
+		       &get_logfile);
+
+chdir $workdir;
+$wpath = &get_this_pwd;
+chdir $pwd;
+
+if (-f $example) {
+  $test_passed = 0;
+}
+
+# Create the answer to what should be produced by this Makefile
+$answer = "$make_name: Entering directory `$wpath'\n"
+        . "$delete_command EXAMPLE\n"
+        . "$make_name: Leaving directory `$wpath'\n";
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2
+# -------
+# Do it again with trailing "/"; this should work the same
+
+$example .= "slash";
+
+&touch($example);
+
+&run_make_with_options("${testname}.mk",
+	               "-C $workdir/ clean ext=slash",
+		       &get_logfile);
+
+chdir $workdir;
+$wpath = &get_this_pwd;
+chdir $pwd;
+
+if (-f $example) {
+  $test_passed = 0;
+}
+
+# Create the answer to what should be produced by this Makefile
+$answer = "$make_name: Entering directory `$wpath'\n"
+        . "$delete_command EXAMPLEslash\n"
+        . "$make_name: Leaving directory `$wpath'\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-I
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-I	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-I	(revision 1780)
@@ -0,0 +1,59 @@
+#                                                                    -*-perl-*-
+
+$description ="The following test creates a makefile to test the -I option.";
+
+$details = "\
+This test tests the -I option by including a filename in
+another directory and giving make that directory name
+under -I in the command line.  Without this option, the make
+would fail to find the included file.  It also checks to make
+sure that the -I option gets passed to recursive makes.";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+$mf2 = substr ($makefile2, index ($makefile2, $pathsep) + 1);
+print MAKEFILE <<EOF;
+include $mf2
+all:
+\t\@echo There should be no errors for this makefile.
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE <<EOF;
+ANOTHER:
+\t\@echo This is another included makefile
+recurse:
+\t\$(MAKE) ANOTHER -f $makefile
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"-I $workdir all",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "There should be no errors for this makefile.\n";
+&compare_output($answer,&get_logfile(1));
+
+
+$answer = "This is another included makefile\n";
+&run_make_with_options($makefile,"-I $workdir ANOTHER",&get_logfile);
+&compare_output($answer,&get_logfile(1));
+
+
+$answer = "$mkpath ANOTHER -f $makefile
+${make_name}[1]: Entering directory `$pwd'
+This is another included makefile
+${make_name}[1]: Leaving directory `$pwd'\n";
+
+&run_make_with_options($makefile,"-I $workdir recurse",&get_logfile);
+&compare_output($answer,&get_logfile(1));
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-W
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-W	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-W	(revision 1780)
@@ -0,0 +1,88 @@
+#                                                                    -*-perl-*-
+
+$description = "Test make -W (what if) option.\n";
+
+# Basic build
+
+run_make_test('
+a.x: b.x
+a.x b.x: ; echo >> $@
+',
+              '', "echo >> b.x\necho >> a.x");
+
+# Run it again: nothing should happen
+
+run_make_test(undef, '', "#MAKE#: `a.x' is up to date.");
+
+# Now run it with -W b.x: should rebuild a.x
+
+run_make_test(undef, '-W b.x', 'echo >> a.x');
+
+# Put the timestamp for a.x into the future; it should still be remade.
+
+utouch(1000, 'a.x');
+run_make_test(undef, '', "#MAKE#: `a.x' is up to date.");
+run_make_test(undef, '-W b.x', 'echo >> a.x');
+
+# Clean up
+
+rmfiles('a.x', 'b.x');
+
+# Test -W with the re-exec feature: we don't want to re-exec forever
+# Savannah bug # 7566
+
+# First set it up with a normal build
+
+run_make_test('
+all: baz.x ; @:
+include foo.x
+foo.x: bar.x
+	@echo "\$$(info restarts=\$$(MAKE_RESTARTS))" > $@
+	@echo "touch $@"
+bar.x: ; echo >> $@
+baz.x: bar.x ; @echo "touch $@"
+',
+              '', '#MAKEFILE#:3: foo.x: No such file or directory
+echo >> bar.x
+touch foo.x
+restarts=1
+touch baz.x');
+
+# Now run with -W bar.x
+
+# Tweak foo.x's timestamp so the update will change it.
+&utouch(1000, 'foo.x');
+
+run_make_test(undef, '-W bar.x', "restarts=\ntouch foo.x\nrestarts=1\ntouch baz.x");
+
+rmfiles('foo.x', 'bar.x');
+
+# Test -W on vpath-found files: it should take effect.
+# Savannah bug # 15341
+
+mkdir('x-dir', 0777);
+utouch(-20, 'x-dir/x');
+touch('y');
+
+run_make_test('
+y: x ; @echo cp $< $@
+',
+              '-W x-dir/x VPATH=x-dir',
+              'cp x-dir/x y');
+
+# Make sure ./ stripping doesn't interfere with the match.
+
+run_make_test('
+y: x ; @echo cp $< $@
+',
+              '-W ./x-dir/x VPATH=x-dir',
+              'cp x-dir/x y');
+
+run_make_test(undef,
+              '-W x-dir/x VPATH=./x-dir',
+              'cp ./x-dir/x y');
+
+unlink(qw(y x-dir/x));
+rmdir('x-dir');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-e
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-e	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-e	(revision 1780)
@@ -0,0 +1,24 @@
+#                                                                    -*-perl-*-
+
+$description = "The following test creates a makefile to ...";
+
+$details = "";
+
+$extraENV{GOOGLE} = 'boggle';
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+GOOGLE = bazzle
+all:; @echo "$(GOOGLE)"
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, '-e' ,&get_logfile);
+
+$answer = "boggle\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-f
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-f	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-f	(revision 1780)
@@ -0,0 +1,85 @@
+$description = "The following test tests that if you specify greater \n"
+              ."than one '-f makefilename' on the command line, \n"
+              ."that make concatenates them.  This test creates three \n"
+              ."makefiles and specifies all of them with the -f option \n"
+              ."on the command line.  To make sure they were concatenated, \n"
+              ."we then call make with the rules from the concatenated \n"
+              ."makefiles one at a time.  Finally, it calls all three \n"
+              ."rules in one call to make and checks that the output\n"
+              ."is in the correct order.";
+
+$makefile2 = &get_tmpfile;
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "all: \n";
+print MAKEFILE "\t\@echo This is the output from the original makefile\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+# Create a second makefile
+open(MAKEFILE,"> $makefile2");
+print MAKEFILE "TWO: \n";
+print MAKEFILE "\t\@echo This is the output from makefile 2\n";
+close(MAKEFILE);
+
+# Create a third makefile
+open(MAKEFILE,"> $makefile3");
+print MAKEFILE "THREE: \n";
+print MAKEFILE "\t\@echo This is the output from makefile 3\n";
+close(MAKEFILE);
+
+
+# Create the answer to what should be produced by this Makefile
+$answer = "This is the output from the original makefile\n";
+
+# Run make to catch the default rule
+&run_make_with_options($makefile,"-f $makefile2 -f $makefile3",&get_logfile,0);
+
+&compare_output($answer,&get_logfile(1));
+
+
+# Run Make again with the rule from the second makefile: TWO
+$answer = "This is the output from makefile 2\n";
+
+&run_make_with_options($makefile,"-f $makefile2 -f $makefile3 TWO",&get_logfile,0);
+
+&compare_output($answer,&get_logfile(1));
+     
+
+# Run Make again with the rule from the third makefile: THREE
+
+$answer = "This is the output from makefile 3\n";
+&run_make_with_options($makefile,
+                       "-f $makefile2 -f $makefile3 THREE",
+                       &get_logfile,
+                       0);
+&compare_output($answer,&get_logfile(1));
+
+
+# Run Make again with ALL three rules in the order 2 1 3 to make sure
+# that all rules are executed in the proper order
+
+$answer = "This is the output from makefile 2\n";
+$answer .= "This is the output from the original makefile\n";
+$answer .= "This is the output from makefile 3\n";
+&run_make_with_options($makefile,
+                       "-f $makefile2 -f $makefile3 TWO all THREE",
+		       &get_logfile,
+                       0);
+&compare_output($answer,&get_logfile(1));
+       
+
+
+
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-k
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-k	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-k	(revision 1780)
@@ -0,0 +1,114 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the make -k (don't stop on error) option.\n";
+
+$details = "\
+The makefile created in this test is a simulation of building
+a small product.  However, the trick to this one is that one
+of the dependencies of the main target does not exist.
+Without the -k option, make would fail immediately and not
+build any part of the target.  What we are looking for here,
+is that make builds the rest of the dependencies even though
+it knows that at the end it will fail to rebuild the main target.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOF;
+VPATH = $workdir
+edit:  main.o kbd.o commands.o display.o
+\t\@echo cc -o edit main.o kbd.o commands.o display.o
+
+main.o : main.c defs.h
+\t\@echo cc -c main.c
+
+kbd.o : kbd.c defs.h command.h
+\t\@echo cc -c kbd.c
+
+commands.o : command.c defs.h command.h
+\t\@echo cc -c commands.c
+
+display.o : display.c defs.h buffer.h
+\t\@echo cc -c display.c
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
+               "$workdir${pathsep}command.h",
+               "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+               "$workdir${pathsep}buffer.h",
+	       "$workdir${pathsep}command.c");
+
+&touch(@files_to_touch);
+
+if ($vos) {
+  $error_code = 3307;
+}
+else {
+  $error_code = 512;
+}
+
+&run_make_with_options($makefile, "-k", &get_logfile, $error_code);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "cc -c main.c
+$make_name: *** No rule to make target `kbd.c', needed by `kbd.o'.
+cc -c commands.c
+cc -c display.c
+$make_name: Target `edit' not remade because of errors.\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer, &get_logfile(1));
+
+unlink(@files_to_touch) unless $keep;
+
+
+# TEST 1: Make sure that top-level targets that depend on targets that
+# previously failed to build, aren't attempted.  Regression for PR/1634.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE <<'EOF';
+.SUFFIXES:
+
+all: exe1 exe2; @echo making $@
+
+exe1 exe2: lib; @echo cp $^ $@
+
+lib: foo.o; @echo cp $^ $@
+
+foo.o: ; exit 1
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "-k", &get_logfile, $error_code);
+
+$answer = "exit 1
+$make_name: *** [foo.o] Error 1
+$make_name: Target `all' not remade because of errors.\n";
+
+&compare_output($answer, &get_logfile(1));
+
+# TEST -- make sure we keep the error code if we can't create an included
+# makefile.
+
+run_make_test('all: ; @echo hi
+include ifile
+ifile: no-such-file; @false
+',
+              '-k',
+              "#MAKEFILE#:2: ifile: No such file or directory
+#MAKE#: *** No rule to make target `no-such-file', needed by `ifile'.
+#MAKE#: Failed to remake makefile `ifile'.
+hi\n",
+              512);
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-l
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-l	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-l	(revision 1780)
@@ -0,0 +1,55 @@
+#                                                                    -*-perl-*-
+# Date: Tue, 11 Aug 1992 09:34:26 -0400
+# From: pds@lemming.webo.dg.com (Paul D. Smith)
+
+$description = "Test load balancing (-l) option.";
+
+$details = "\
+This test creates a makefile where all depends on three rules
+which contain the same body.  Each rule checks for the existence
+of a temporary file; if it exists an error is generated.  If it
+doesn't exist then it is created, the rule sleeps, then deletes
+the temp file again.  Thus if any of the rules are run in
+parallel the test will fail.  When make is called in this test,
+it is given the -l option with a value of 0.0001.  This ensures
+that the load will be above this number and make will therefore
+decide that it cannot run more than one job even though -j 4 was
+also specified on the command line.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOF';
+SHELL = /bin/sh
+
+define test
+if [ ! -f test-file ]; then \
+  echo >> test-file; sleep 2; rm -f test-file; \
+else \
+  echo $@ FAILED; \
+fi
+endef
+
+all : ONE TWO THREE
+ONE : ; @$(test)
+TWO : ; @$(test)
+THREE : ; @$(test)
+EOF
+
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+$mkoptions = "-l 0.0001";
+$mkoptions .= " -j 4" if ($parallel_jobs);
+
+&run_make_with_options($makefile, $mkoptions, &get_logfile);
+
+$slurp = &read_file_into_string (&get_logfile(1));
+if ($slurp !~ /cannot enforce load limit/) {
+  &compare_output("", &get_logfile(1));
+}
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-n
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-n	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-n	(revision 1780)
@@ -0,0 +1,70 @@
+#                                                                    -*-perl-*-
+$description = "Test the -n option.\n";
+
+$details = "Try various uses of -n and ensure they all give the correct results.\n";
+
+open(MAKEFILE, "> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOMAKE';
+
+final: intermediate ; echo >> $@
+intermediate: orig ; echo >> $@
+
+EOMAKE
+
+close(MAKEFILE);
+
+&touch('orig');
+
+# TEST 0
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "echo >> intermediate\necho >> final\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 1
+
+&run_make_with_options($makefile, "-Worig -n", &get_logfile);
+$answer = "echo >> intermediate\necho >> final\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('orig', 'intermediate', 'final');
+
+# We consider the actual updated timestamp of targets with all
+# recursive commands, even with -n.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+
+print MAKEFILE <<'EOF';
+.SUFFIXES:
+BAR =     # nothing
+FOO = +$(BAR)
+a: b; echo > $@
+b: c; $(FOO)
+EOF
+
+close(MAKEFILE);
+
+&utouch(-20, 'b');
+&utouch(-10, 'a');
+&touch('c');
+
+# TEST 2
+
+&run_make_with_options($makefile2, "", &get_logfile);
+$answer = "$make_name: `a' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 3
+
+&run_make_with_options($makefile2, "-n", &get_logfile);
+$answer = "$make_name: `a' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('a', 'b', 'c');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-q
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-q	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-q	(revision 1780)
@@ -0,0 +1,57 @@
+#                                                                    -*-perl-*-
+$description = "Test the -q option.\n";
+
+$details = "Try various uses of -q and ensure they all give the correct results.\n";
+
+# TEST 0
+
+run_make_test('
+one:
+two: ;
+three: ; :
+four: ; $(.XY)
+five: ; \
+ $(.XY)
+six: ; \
+ $(.XY)
+	$(.XY)
+seven: ; \
+ $(.XY)
+	: foo
+	$(.XY)
+',
+              '-q one', '');
+
+# TEST 1
+
+run_make_test(undef, '-q two', '');
+
+# TEST 2
+
+run_make_test(undef, '-q three', '', 256);
+
+# TEST 3
+
+run_make_test(undef, '-q four', '');
+
+# TEST 4
+
+run_make_test(undef, '-q five', '');
+
+# TEST 5
+
+run_make_test(undef, '-q six', '');
+
+# TEST 6
+
+run_make_test(undef, '-q seven', '', 256);
+
+# TEST 7 : Savannah bug # 7144
+
+run_make_test('
+one:: ; @echo one
+one:: ; @echo two
+',
+              '-q', '', 256);
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-t
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-t	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/dash-t	(revision 1780)
@@ -0,0 +1,58 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the -t option.\n";
+
+$details = "Look out for regressions of prior bugs related to -t.\n";
+# That means, nobody has even tried to make the tests below comprehensive
+
+# TEST 0
+# bug reported by Henning Makholm <henning@makholm.net> on 2001-11-03:
+#   make 3.79.1 touches only interm-[ab] but reports final-[a] as
+#   'up to date' without touching them.
+# The 'obvious' fix didn't work for double-colon rules, so pay special
+# attention to them.
+
+open(MAKEFILE, "> $makefile");
+print MAKEFILE <<'EOMAKE';
+final-a: interm-a ; echo >> $@
+final-b: interm-b ; echo >> $@
+interm-a:: orig1-a ; echo >> $@
+interm-a:: orig2-a ; echo >> $@
+interm-b:: orig1-b ; echo >> $@
+interm-b:: orig2-b ; echo >> $@
+EOMAKE
+close(MAKEFILE);
+
+&utouch(-30, 'orig1-a','orig2-b');
+&utouch(-20, 'interm-a','interm-b');
+&utouch(-10, 'final-a','final-b');
+&touch('orig2-a','orig1-b');
+
+&run_make_with_options($makefile, "-t final-a final-b", &get_logfile);
+$answer = "touch interm-a\ntouch final-a\ntouch interm-b\ntouch final-b\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('orig1-a', 'orig2-a', 'interm-a', 'final-a');
+unlink('orig1-b', 'orig2-b', 'interm-b', 'final-b');
+
+# TEST 1
+# -t should not touch files with no commands.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE <<'EOMAKE';
+
+PHOOEY: xxx
+xxx: ; @:
+
+EOMAKE
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "-t", &get_logfile);
+$answer = "touch xxx\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('xxx');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/general
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/general	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/general	(revision 1780)
@@ -0,0 +1,35 @@
+#                                                                    -*-perl-*-
+$description = "Test generic option processing.\n";
+
+open(MAKEFILE, "> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "foo 1foo: ; \@echo \$\@\n";
+
+close(MAKEFILE);
+
+# TEST 0
+
+&run_make_with_options($makefile, "-j 1foo", &get_logfile);
+if (!$parallel_jobs) {
+  $answer = "$make_name: Parallel jobs (-j) are not supported on this platform.\n$make_name: Resetting to single job (-j1) mode.\n1foo\n";
+}
+else {
+  $answer = "1foo\n";
+}
+
+# TEST 1
+
+# This test prints the usage string; I don't really know a good way to
+# test it.  I guess I could invoke make with a known-bad option to see
+# what the usage looks like, then compare it to what I get here... :(
+
+# If I were always on UNIX, I could invoke it with 2>/dev/null, then
+# just check the error code.
+
+&run_make_with_options($makefile, "-j1foo 2>/dev/null", &get_logfile, 512);
+$answer = "";
+&compare_output($answer, &get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/symlinks
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/symlinks	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/symlinks	(revision 1780)
@@ -0,0 +1,68 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the -L option.";
+
+$details = "Verify that symlink handling with and without -L works properly.";
+
+# Only run these tests if the system sypports symlinks
+
+# Apparently the Windows port of Perl reports that it does support symlinks
+# (in that the symlink() function doesn't fail) but it really doesn't, so
+# check for it explicitly.
+
+if ($port_type eq 'W32' || !( eval { symlink("",""); 1 })) {
+  # This test is N/A 
+  -1;
+} else {
+
+  # Set up a symlink sym -> dep
+  # We'll make both dep and targ older than sym
+  $pwd =~ m%/([^/]+)$%;
+  $dirnm = $1;
+  &utouch(-10, 'dep');
+  &utouch(-5, 'targ');
+  symlink("../$dirnm/dep", 'sym');
+
+  # Without -L, nothing should happen
+  # With -L, it should update targ
+  run_make_test('targ: sym ; @echo make $@ from $<', '',
+                "#MAKE#: `targ' is up to date.");
+  run_make_test(undef, '-L', "make targ from sym");
+
+  # Now update dep; in all cases targ should be out of date.
+  &touch('dep');
+  run_make_test(undef, '', "make targ from sym");
+  run_make_test(undef, '-L', "make targ from sym");
+
+  # Now update targ; in all cases targ should be up to date.
+  &touch('targ');
+  run_make_test(undef, '', "#MAKE#: `targ' is up to date.");
+  run_make_test(undef, '-L', "#MAKE#: `targ' is up to date.");
+
+  # Add in a new link between sym and dep.  Be sure it's newer than targ.
+  sleep(1);
+  rename('dep', 'dep1');
+  symlink('dep1', 'dep');
+
+  # Without -L, nothing should happen
+  # With -L, it should update targ
+  run_make_test(undef, '', "#MAKE#: `targ' is up to date.");
+  run_make_test(undef, '-L', "make targ from sym");
+
+  rmfiles('targ', 'dep', 'sym', 'dep1');
+
+  # Check handling when symlinks point to non-existent files.  Without -L we
+  # should get an error: with -L we should use the timestamp of the symlink.
+
+  symlink("../$dirname/dep", 'sym');
+  run_make_test('targ: sym ; @echo make $@ from $<', '',
+                "#MAKE#: *** No rule to make target `sym', needed by `targ'.  Stop.", 512);
+
+  run_make_test('targ: sym ; @echo make $@ from $<', '-L',
+                'make targ from sym');
+
+
+  rmfiles('targ', 'sym');
+
+  1;
+}
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/warn-undefined-variables
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/warn-undefined-variables	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/options/warn-undefined-variables	(revision 1780)
@@ -0,0 +1,25 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the --warn-undefined-variables option.";
+
+$details = "Verify that warnings are printed for referencing undefined variables.";
+
+# Without --warn-undefined-variables, nothing should happen
+run_make_test('
+EMPTY =
+EREF = $(EMPTY)
+UREF = $(UNDEFINED)
+
+SEREF := $(EREF)
+SUREF := $(UREF)
+
+all: ; @echo ref $(EREF) $(UREF)',
+              '', 'ref');
+
+# With --warn-undefined-variables, it should warn me
+run_make_test(undef, '--warn-undefined-variables',
+              "#MAKEFILE#:7: warning: undefined variable `UNDEFINED'
+#MAKEFILE#:9: warning: undefined variable `UNDEFINED'
+ref");
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/DEFAULT
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/DEFAULT	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/DEFAULT	(revision 1780)
@@ -0,0 +1,53 @@
+$description = "The following test creates a makefile to override part\n"
+              ."of one Makefile with Another Makefile with the .DEFAULT\n"
+              ."rule.";
+
+$details = "This tests the use of the .DEFAULT special target to say that \n"
+          ."to remake any target that cannot be made fram the information\n"
+          ."in the containing makefile, make should look in another makefile\n"
+          ."This test gives this makefile the target bar which is not \n"
+          ."defined here but passes the target bar on to another makefile\n"
+          ."which does have the target bar defined.\n";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "foo:\n";
+print MAKEFILE "\t\@echo Executing rule FOO\n\n";
+print MAKEFILE ".DEFAULT:\n";
+print MAKEFILE "\t\@\$(MAKE) -f $makefile2 \$\@ \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE "bar:\n";
+print MAKEFILE "\t\@echo Executing rule BAR\n\n";
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,'bar',&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "${make_name}[1]: Entering directory `$pwd'\n"
+        . "Executing rule BAR\n"
+        . "${make_name}[1]: Leaving directory `$pwd'\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/FORCE
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/FORCE	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/FORCE	(revision 1780)
@@ -0,0 +1,40 @@
+#                                                                    -*-perl-*-
+
+$description = "The following tests rules without Commands or Dependencies.";
+
+$details = "If the rule ...\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE ".IGNORE :\n";
+print MAKEFILE "clean: FORCE\n";
+print MAKEFILE "\t$delete_command clean\n";
+print MAKEFILE "FORCE:\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+# Create a file named "clean".  This is the same name as the target clean
+# and tricks the target into thinking that it is up to date.  (Unless you
+# use the .PHONY target.
+&touch("clean");
+
+$answer = "$delete_command clean\n";
+&run_make_with_options($makefile,"clean",&get_logfile);
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/INTERMEDIATE
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/INTERMEDIATE	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/INTERMEDIATE	(revision 1780)
@@ -0,0 +1,108 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the behaviour of the .INTERMEDIATE target.";
+
+$details = "\
+Test the behavior of the .INTERMEDIATE special target.
+Create a makefile where a file would not normally be considered
+intermediate, then specify it as .INTERMEDIATE.  Build and ensure it's
+deleted properly.  Rebuild to ensure that it's not created if it doesn't
+exist but doesn't need to be built.  Change the original and ensure
+that the intermediate file and the ultimate target are both rebuilt, and
+that the intermediate file is again deleted.
+
+Try this with implicit rules and explicit rules: both should work.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+
+.INTERMEDIATE: foo.e bar.e
+
+# Implicit rule test
+%.d : %.e ; cp $< $@
+%.e : %.f ; cp $< $@
+
+foo.d: foo.e
+
+# Explicit rule test
+foo.c: foo.e bar.e; cat $^ > $@
+EOF
+
+close(MAKEFILE);
+
+# TEST #0
+
+&utouch(-20, 'foo.f', 'bar.f');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #1
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "$make_name: `foo.d' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #2
+
+&utouch(-10, 'foo.d');
+&touch('foo.f');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #3
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm bar.e foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #4
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "$make_name: `foo.c' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #5
+
+&utouch(-10, 'foo.c');
+&touch('foo.f');
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm bar.e foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #6 -- added for PR/1669: don't remove files mentioned on the cmd line.
+
+&run_make_with_options($makefile,'foo.e',&get_logfile);
+$answer = "cp foo.f foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('foo.f', 'foo.e', 'foo.d', 'foo.c', 'bar.f', 'bar.e', 'bar.d', 'bar.c');
+
+# TEST #7 -- added for PR/1423
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+
+print MAKEFILE <<'EOF';
+all: foo
+foo.a: ; touch $@
+%: %.a ; touch $@
+.INTERMEDIATE: foo.a
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, '-R', &get_logfile);
+$answer = "touch foo.a\ntouch foo\nrm foo.a\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('foo');
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/PHONY
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/PHONY	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/PHONY	(revision 1780)
@@ -0,0 +1,54 @@
+#                                                                    -*-perl-*-
+
+$description = "The following tests the use of a PHONY target.  It makes\n"
+              ."sure that the rules under a target get executed even if\n"
+              ."a filename of the same name of the target exists in the\n"
+              ."directory.\n";
+
+$details = "This makefile in this test declares the target clean to be a \n"
+          ."PHONY target.  We then create a file named \"clean\" in the \n"
+          ."directory.  Although this file exists, the rule under the target\n"
+          ."clean should still execute because of it's phony status.";
+
+$example = "EXAMPLE_FILE";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE ".PHONY : clean \n";
+print MAKEFILE "all: \n";
+print MAKEFILE "\t\@echo This makefile did not clean the dir ... good\n";
+print MAKEFILE "clean: \n";
+print MAKEFILE "\t$delete_command $example clean\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch($example);
+
+# Create a file named "clean".  This is the same name as the target clean
+# and tricks the target into thinking that it is up to date.  (Unless you
+# use the .PHONY target.
+&touch("clean");
+
+$answer = "$delete_command $example clean\n";
+&run_make_with_options($makefile,"clean",&get_logfile);
+
+if (-f $example) {
+  $test_passed = 0;
+}
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/SECONDARY
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/SECONDARY	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/SECONDARY	(revision 1780)
@@ -0,0 +1,125 @@
+#! -*-perl-*-
+
+$description = "Test the behaviour of the .SECONDARY target.";
+
+$details = "\
+Test the behavior of the .SECONDARY special target.
+Create a makefile where a file would not normally be considered
+intermediate, then specify it as .SECONDARY.  Build and note that it's
+not automatically deleted.  Delete the file.  Rebuild to ensure that
+it's not created if it doesn't exist but doesn't need to be built.
+Change the original and ensure that the secondary file and the ultimate
+target are both rebuilt, and that the secondary file is not deleted.
+
+Try this with implicit rules and explicit rules: both should work.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+
+.SECONDARY: foo.e
+
+# Implicit rule test
+%.d : %.e ; cp $< $@
+%.e : %.f ; cp $< $@
+
+foo.d: foo.e
+
+# Explicit rule test
+foo.c: foo.e ; cp $< $@
+EOF
+
+close(MAKEFILE);
+
+# TEST #1
+
+&utouch(-20, 'foo.f');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.d\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #2
+
+unlink('foo.e');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "$make_name: `foo.d' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #3
+
+&utouch(-10, 'foo.d');
+&touch('foo.f');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.d\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #4
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "cp foo.e foo.c\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #5
+
+unlink('foo.e');
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "$make_name: `foo.c' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #6
+
+&utouch(-10, 'foo.c');
+&touch('foo.f');
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.c\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('foo.f', 'foo.e', 'foo.d', 'foo.c');
+
+# TEST #7 -- test the "global" .SECONDARY, with no targets.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+
+print MAKEFILE <<'EOF';
+.SECONDARY:
+
+final: intermediate
+intermediate: source
+
+final intermediate source:
+	echo $< > $@
+EOF
+
+close(MAKEFILE);
+
+&utouch(-10, 'source');
+touch('final');
+
+&run_make_with_options($makefile2, '', &get_logfile);
+$answer = "$make_name: `final' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('source', 'final', 'intermediate');
+
+
+# TEST #8 -- test the "global" .SECONDARY, with .PHONY.
+
+touch('version2');
+run_make_test('
+.PHONY: version
+.SECONDARY:
+version2: version ; @echo GOOD
+all: version2',
+              'all', 'GOOD');
+
+unlink('version2');
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/SILENT
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/SILENT	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/SILENT	(revision 1780)
@@ -0,0 +1,42 @@
+#                                                                    -*-perl-*-
+
+$description = "The following tests the special target .SILENT.  By simply\n"
+              ."mentioning this as a target, it tells make not to print\n"
+              ."commands before executing them.";
+
+$details = "This test is the same as the clean test except that it should\n"
+          ."not echo its command before deleting the specified file.\n";
+
+$example = "EXAMPLE_FILE";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE ".SILENT : clean\n";
+print MAKEFILE "clean: \n";
+print MAKEFILE "\t$delete_command EXAMPLE_FILE\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch($example);
+
+$answer = "";
+&run_make_with_options($makefile,"clean",&get_logfile,0);
+if (-f $example) {
+  $test_passed = 0;
+}
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/clean
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/clean	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/targets/clean	(revision 1780)
@@ -0,0 +1,50 @@
+#                                                                    -*-perl-*-
+
+$description = "The following test creates a makefile to delete a \n"
+              ."file in the directory.  It tests to see if make will \n"
+              ."NOT execute the command unless the rule is given in \n"
+              ."the make command line.";
+
+$example = "EXAMPLE_FILE";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "all: \n";
+print MAKEFILE "\t\@echo This makefile did not clean the dir... good\n";
+print MAKEFILE "clean: \n";
+print MAKEFILE "\t$delete_command EXAMPLE_FILE\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch($example);
+
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "This makefile did not clean the dir... good\n";
+
+&compare_output($answer,&get_logfile(1)) || &error ("abort");
+
+
+$answer = "$delete_command $example\n";
+&run_make_with_options($makefile,"clean",&get_logfile,0);
+if (-f $example) {
+  $test_passed = 0;
+}
+&compare_output($answer,&get_logfile(1)) || &error ("abort");
+
+1;
+
+
+
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/test_template
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/test_template	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/test_template	(revision 1780)
@@ -0,0 +1,29 @@
+#                                                                    -*-perl-*-
+
+$description = "<FILL IN SHORT DESCRIPTION HERE>";
+$details = "<FILL IN DETAILS OF HOW YOU TEST WHAT YOU SAY YOU ARE TESTING>";
+
+# Run a make test.  See the documentation of run_make_test() in
+# run_make_tests.pl, but briefly the first argument is a string with the
+# contents of a makefile to be tested, the second is a string containing the
+# arguments to be passed to the make invocation, the third is a string
+# containing the expected output.  The fourth is the expected exit code for
+# make.  If not specified, it's assumed that the make program should succeed
+# (exit with 0).
+
+run_make_test('Your test makefile goes here',
+              'Arguments to pass to make go here',
+              'Expected output from the invocation goes here');
+
+# There are various special tokens, options, etc.  See the full documentation
+# in run_make_tests.pl.
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/CURDIR
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/CURDIR	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/CURDIR	(revision 1780)
@@ -0,0 +1,20 @@
+#                                                                    -*-perl-*-
+
+$description = "This tests the CURDIR varaible.";
+
+$details = "Echo CURDIR both with and without -C.  Also ensure overrides work.";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE "all: ; \@echo \$(CURDIR)\n";
+close(MAKEFILE);
+
+
+# TEST #1
+# -------
+
+&run_make_with_options($makefile,"",&get_logfile);
+$answer = "$pwd\n";
+&compare_output($answer,&get_logfile(1));
+
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/DEFAULT_GOAL
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/DEFAULT_GOAL	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/DEFAULT_GOAL	(revision 1780)
@@ -0,0 +1,78 @@
+#                                                                    -*-perl-*-
+$description = "Test the .DEFAULT_GOAL special variable.";
+
+$details = "";
+
+
+# Test #1: basic logic.
+#
+run_make_test('
+# Basics.
+#
+foo: ; @:
+
+ifneq ($(.DEFAULT_GOAL),foo)
+$(error )
+endif
+
+# Reset to empty.
+#
+.DEFAULT_GOAL :=
+
+bar: ; @:
+
+ifneq ($(.DEFAULT_GOAL),bar)
+$(error )
+endif
+
+# Change to a different goal.
+#
+
+.DEFAULT_GOAL := baz
+
+baz: ; @echo $@
+',
+'',
+'baz');
+
+
+# Test #2: unknown goal.
+#
+run_make_test('
+.DEFAULT_GOAL = foo
+',
+'',
+'#MAKE#: *** No rule to make target `foo\'.  Stop.',
+512);
+
+
+# Test #3: more than one goal.
+#
+run_make_test('
+.DEFAULT_GOAL := foo bar
+',
+'',
+'#MAKE#: *** .DEFAULT_GOAL contains more than one target.  Stop.',
+512);
+
+
+# Test #4: Savannah bug #12226.
+#
+run_make_test('
+define rule
+foo: ; @echo $$@
+endef
+
+define make-rule
+$(eval $(rule))
+endef
+
+$(call make-rule)
+
+',
+'',
+'foo');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/INCLUDE_DIRS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/INCLUDE_DIRS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/INCLUDE_DIRS	(revision 1780)
@@ -0,0 +1,46 @@
+#                                                                    -*-perl-*-
+$description = "Test the .INCLUDE_DIRS special variable.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+# Test #1: The content of .INCLUDE_DIRS depends on the platform for which
+#          make was built. What we know for sure is that it shouldn't be
+#          empty.
+#
+run_make_test('
+ifeq ($(.INCLUDE_DIRS),)
+$(warning .INCLUDE_DIRS is empty)
+endif
+
+.PHONY: all
+all:;@:
+',
+'',
+'');
+
+
+# Test #2: Make sure -I paths end up in .INCLUDE_DIRS.
+#
+run_make_test('
+ifeq ($(dir),)
+$(warning dir is empty)
+endif
+
+ifeq ($(filter $(dir),$(.INCLUDE_DIRS)),)
+$(warning .INCLUDE_DIRS does not contain $(dir))
+endif
+
+.PHONY: all
+all:;@:
+',
+"-I$dir dir=$dir",
+'');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKE
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKE	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKE	(revision 1780)
@@ -0,0 +1,35 @@
+#								     -*-perl-*-
+
+$description = "The following test creates a makefile to test MAKE \n"
+              ."(very generic)";
+
+$details = "DETAILS";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "TMP  := \$(MAKE)\n";
+print MAKEFILE "MAKE := \$(subst X=\$(X),,\$(MAKE))\n\n";
+print MAKEFILE "all:\n";
+print MAKEFILE "\t\@echo \$(TMP)\n";
+print MAKEFILE "\t\$(MAKE) -f $makefile foo\n\n";
+print MAKEFILE "foo:\n";
+print MAKEFILE "\t\@echo \$(MAKE)\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "$mkpath\n$mkpath -f $makefile foo\n"
+	. "${make_name}[1]: Entering directory `$pwd'\n"
+	. "$mkpath\n${make_name}[1]: Leaving directory `$pwd'\n";
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+&rmfiles("foo");
+# COMPARE RESULTS
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKECMDGOALS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKECMDGOALS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKECMDGOALS	(revision 1780)
@@ -0,0 +1,52 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the MAKECMDGOALS variable.";
+
+$details = "\
+We construct a makefile with various targets, all of which print out
+\$(MAKECMDGOALS), then call it different ways.";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE "\
+.DEFAULT all:
+	\@echo \$(MAKECMDGOALS)
+";
+close(MAKEFILE);
+
+# TEST #1
+
+&run_make_with_options($makefile,
+                       "",
+                       &get_logfile,
+                       0);
+$answer = "\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #2
+
+&run_make_with_options($makefile,
+                       "all",
+                       &get_logfile,
+                       0);
+$answer = "all\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #3
+
+&run_make_with_options($makefile,
+                       "foo bar baz yaz",
+                       &get_logfile,
+                       0);
+$answer = "foo bar baz yaz\nfoo bar baz yaz\nfoo bar baz yaz\nfoo bar baz yaz\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKEFILES
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKEFILES	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKEFILES	(revision 1780)
@@ -0,0 +1,34 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the MAKEFILES variable.";
+
+$makefile2 = &get_tmpfile;
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE 'all: ; @echo DEFAULT RULE: M2=$(M2) M3=$(M3)', "\n";
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+print MAKEFILE <<EOF;
+M2 = m2
+NDEF: ; \@echo RULE FROM MAKEFILE 2
+EOF
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile3");
+print MAKEFILE <<EOF;
+M3 = m3
+NDEF3: ; \@echo RULE FROM MAKEFILE 3
+EOF
+close(MAKEFILE);
+
+
+&run_make_with_options($makefile, "MAKEFILES='$makefile2 $makefile3'",
+                       &get_logfile);
+$answer = "DEFAULT RULE: M2=m2 M3=m3\n";
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKEFILE_LIST
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKEFILE_LIST	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKEFILE_LIST	(revision 1780)
@@ -0,0 +1,30 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the MAKEFILE_LIST variable.";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE <<EOF;
+m1 := \$(MAKEFILE_LIST)
+include $makefile2
+m3 := \$(MAKEFILE_LIST)
+
+all:
+\t\@echo \$(m1)
+\t\@echo \$(m2)
+\t\@echo \$(m3)
+EOF
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+print MAKEFILE "m2 := \$(MAKEFILE_LIST)\n";
+close(MAKEFILE);
+
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "$makefile\n$makefile $makefile2\n$makefile $makefile2\n";
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKELEVEL
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKELEVEL	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKELEVEL	(revision 1780)
@@ -0,0 +1,33 @@
+#                                                                    -*-perl-*-
+
+$description = "The following test creates a makefile to test
+makelevels in Make. It prints \$(MAKELEVEL) and then
+prints the environment variable MAKELEVEL";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOF;
+all:
+\t\@echo MAKELEVEL is \$(MAKELEVEL)
+\techo \$\$MAKELEVEL
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+# RUN MAKE
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# SET ANSWER
+
+$answer = "MAKELEVEL is 0\necho \$MAKELEVEL\n1\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKE_RESTARTS
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKE_RESTARTS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MAKE_RESTARTS	(revision 1780)
@@ -0,0 +1,62 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the MAKE_RESTARTS variable.";
+
+# Test basic capability
+
+run_make_test('
+all: ; @:
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @touch $@
+',
+              '', 'MAKE_RESTARTS=
+#MAKEFILE#:4: foo.x: No such file or directory
+MAKE_RESTARTS=1');
+
+rmfiles('foo.x');
+
+# Test multiple restarts
+
+run_make_test('
+all: ; @:
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @echo "include bar.x" > $@
+bar.x: ; @touch $@
+',
+              '', 'MAKE_RESTARTS=
+#MAKEFILE#:4: foo.x: No such file or directory
+MAKE_RESTARTS=1
+foo.x:1: bar.x: No such file or directory
+MAKE_RESTARTS=2');
+
+rmfiles('foo.x', 'bar.x');
+
+# Test multiple restarts and make sure the variable is cleaned up
+
+run_make_test('
+recurse:
+	@echo recurse MAKE_RESTARTS=$$MAKE_RESTARTS
+	@$(MAKE) -f #MAKEFILE# all
+all:
+	@echo all MAKE_RESTARTS=$$MAKE_RESTARTS
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @echo "include bar.x" > $@
+bar.x: ; @touch $@
+',
+              '', "MAKE_RESTARTS=
+#MAKEFILE#:8: foo.x: No such file or directory
+MAKE_RESTARTS=1
+foo.x:1: bar.x: No such file or directory
+MAKE_RESTARTS=2
+recurse MAKE_RESTARTS=
+MAKE_RESTARTS=
+#MAKE#[1]: Entering directory `#PWD#'
+all MAKE_RESTARTS=
+#MAKE#[1]: Leaving directory `#PWD#'");
+
+rmfiles('foo.x', 'bar.x');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MFILE_LIST
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MFILE_LIST	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/MFILE_LIST	(revision 1780)
@@ -0,0 +1,30 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the MAKEFILE_LIST variable.";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE <<EOF;
+m1 := \$(MAKEFILE_LIST)
+include $makefile2
+m3 := \$(MAKEFILE_LIST)
+
+all:
+\t\@echo \$(m1)
+\t\@echo \$(m2)
+\t\@echo \$(m3)
+EOF
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+print MAKEFILE "m2 := \$(MAKEFILE_LIST)\n";
+close(MAKEFILE);
+
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "$makefile\n$makefile $makefile2\n$makefile $makefile2\n";
+&compare_output($answer,&get_logfile(1));
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/SHELL
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/SHELL	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/SHELL	(revision 1780)
@@ -0,0 +1,56 @@
+#                                                                    -*-perl-*-
+
+$description = "Test proper handling of SHELL.";
+
+# Find the default value when SHELL is not set.  On UNIX it will be /bin/sh,
+# but on other platforms who knows?
+resetENV();
+delete $ENV{SHELL};
+$mshell = `echo 'all:;\@echo \$(SHELL)' | $make_path -f-`;
+chop $mshell;
+
+# According to POSIX, the value of SHELL in the environment has no impact on
+# the value in the makefile.
+# Note %extraENV takes precedence over the default value for the shell.
+
+$extraENV{SHELL} = '/dev/null';
+run_make_test('all:;@echo "$(SHELL)"', '', $mshell);
+
+# According to POSIX, any value of SHELL set in the makefile should _NOT_ be
+# exported to the subshell!  I wanted to set SHELL to be $^X (perl) in the
+# makefile, but make runs $(SHELL) -c 'commandline' and that doesn't work at
+# all when $(SHELL) is perl :-/.  So, we just add an extra initial /./ which
+# works well on UNIX and seems to work OK on at least some non-UNIX systems.
+
+$extraENV{SHELL} = $mshell;
+
+run_make_test("SHELL := /./$mshell\n".'
+all:;@echo "$(SHELL) $$SHELL"
+', '', "/./$mshell $mshell");
+
+# As a GNU make extension, if make's SHELL variable is explicitly exported,
+# then we really _DO_ export it.
+
+$extraENV{SHELL} = $mshell;
+
+run_make_test("export SHELL := /./$mshell\n".'
+all:;@echo "$(SHELL) $$SHELL"
+', '', "/./$mshell /./$mshell");
+
+
+# Test out setting of SHELL, both exported and not, as a target-specific
+# variable.
+
+$extraENV{SHELL} = $mshell;
+
+run_make_test("all: SHELL := /./$mshell\n".'
+all:;@echo "$(SHELL) $$SHELL"
+', '', "/./$mshell $mshell");
+
+$extraENV{SHELL} = $mshell;
+
+run_make_test("all: export SHELL := /./$mshell\n".'
+all:;@echo "$(SHELL) $$SHELL"
+', '', "/./$mshell $mshell");
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/automatic
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/automatic	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/automatic	(revision 1780)
@@ -0,0 +1,110 @@
+#                                                                    -*-perl-*-
+
+$description = "Test automatic variable setting.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+open(MAKEFILE, "> $makefile");
+print MAKEFILE "dir = $dir\n";
+print MAKEFILE <<'EOF';
+.SUFFIXES:
+.SUFFIXES: .x .y .z
+$(dir)/foo.x : baz.z $(dir)/bar.y baz.z
+	@echo '$$@ = $@, $$(@D) = $(@D), $$(@F) = $(@F)'
+	@echo '$$* = $*, $$(*D) = $(*D), $$(*F) = $(*F)'
+	@echo '$$< = $<, $$(<D) = $(<D), $$(<F) = $(<F)'
+	@echo '$$^ = $^, $$(^D) = $(^D), $$(^F) = $(^F)'
+	@echo '$$+ = $+, $$(+D) = $(+D), $$(+F) = $(+F)'
+	@echo '$$? = $?, $$(?D) = $(?D), $$(?F) = $(?F)'
+	touch $@
+
+$(dir)/bar.y baz.z : ; touch $@
+EOF
+close(MAKEFILE);
+
+# TEST #0 -- simple test
+# -------
+
+# Touch these into the past
+&utouch(-10, qw(foo.x baz.z));
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "touch $dir/bar.y
+\$\@ = $dir/foo.x, \$(\@D) = $dir, \$(\@F) = foo.x
+\$* = $dir/foo, \$(*D) = $dir, \$(*F) = foo
+\$< = baz.z, \$(<D) = ., \$(<F) = baz.z
+\$^ = baz.z $dir/bar.y, \$(^D) = . $dir, \$(^F) = baz.z bar.y
+\$+ = baz.z $dir/bar.y baz.z, \$(+D) = . $dir ., \$(+F) = baz.z bar.y baz.z
+\$? = $dir/bar.y, \$(?D) = $dir, \$(?F) = bar.y
+touch $dir/foo.x\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink(qw(foo.x bar.y baz.z));
+
+# TEST #1 -- test the SysV emulation of $$@ etc.
+# -------
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE "dir = $dir\n";
+print MAKEFILE <<'EOF';
+.SECONDEXPANSION:
+.SUFFIXES:
+.DEFAULT: ; @echo '$@'
+
+$(dir)/foo $(dir)/bar: $@.x $$@.x $$$@.x $$$$@.x $$(@D).x $$(@F).x
+
+$(dir)/x.z $(dir)/y.z: $(dir)/%.z : $@.% $$@.% $$$@.% $$$$@.% $$(@D).% $$(@F).%
+
+$(dir)/biz: $$(@).x $${@}.x $${@D}.x $${@F}.x
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "$dir/foo $dir/bar", &get_logfile);
+$answer = ".x\n$dir/foo.x\nx\n\$@.x\n$dir.x\nfoo.x\n$dir/bar.x\nbar.x\n";
+&compare_output($answer, &get_logfile(1));
+
+&run_make_with_options($makefile2, "$dir/x.z $dir/y.z", &get_logfile);
+$answer = ".x\n$dir/x.z.x\nx\n\$@.x\n$dir.x\nx.z.x\n.y\n$dir/y.z.y\n\y\n\$@.y\n$dir.y\ny.z.y\n";
+&compare_output($answer, &get_logfile(1));
+
+&run_make_with_options($makefile2, "$dir/biz", &get_logfile);
+$answer = "$dir/biz.x\n$dir.x\nbiz.x\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #2 -- test for Savannah bug #12320.
+#
+run_make_test('
+.SUFFIXES: .b .src
+
+mbr.b: mbr.src
+	@echo $*
+
+mbr.src: ; @:',
+              '',
+              'mbr');
+
+# TEST #3 -- test for Savannah bug #8154
+# Make sure that nonexistent prerequisites are listed in $?, since they are
+# considered reasons for the target to be rebuilt.
+#
+# See also Savannah bugs #16002 and #16051.
+
+touch('foo');
+
+run_make_test('
+foo: bar ; @echo "\$$? = $?"
+bar: ;',
+              '',
+              '$? = bar');
+
+unlink('foo');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/flavors
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/flavors	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/flavors	(revision 1780)
@@ -0,0 +1,183 @@
+#                                                                    -*-perl-*-
+
+$description = "Test various flavors of make variable setting.";
+
+$details = "";
+
+open(MAKEFILE, "> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOF';
+foo = $(bar)
+bar = ${ugh}
+ugh = Hello
+
+all: multi ; @echo $(foo)
+
+multi: ; $(multi)
+
+x := foo
+y := $(x) bar
+x := later
+
+nullstring :=
+space := $(nullstring) $(nullstring)
+
+next: ; @echo $x$(space)$y
+
+define multi
+@echo hi
+echo there
+endef
+
+ifdef BOGUS
+define
+@echo error
+endef
+endif
+
+define outer
+ define inner
+  A = B
+ endef
+endef
+
+$(eval $(outer))
+
+outer: ; @echo $(inner)
+
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+# TEST #1
+# -------
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "hi\necho there\nthere\nHello\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #2
+# -------
+
+&run_make_with_options($makefile, "next", &get_logfile);
+$answer = "later foo bar\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #3
+# -------
+
+&run_make_with_options($makefile, "BOGUS=true", &get_logfile, 512);
+$answer = "$makefile:24: *** empty variable name.  Stop.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #4
+# -------
+
+&run_make_with_options($makefile, "outer", &get_logfile);
+$answer = "A = B\n";
+&compare_output($answer, &get_logfile(1));
+
+# Clean up from "old style" testing.  If all the above tests are converted to
+# run_make_test() syntax than this line can be removed.
+$makefile = undef;
+
+# -------------------------
+# Make sure that prefix characters apply properly to define/endef values.
+#
+# There's a bit of oddness here if you try to use a variable to hold the
+# prefix character for a define.  Even though something like this:
+#
+#       define foo
+#       echo bar
+#       endef
+#
+#       all: ; $(V)$(foo)
+#
+# (where V=@) can be seen by the user to be obviously different than this:
+#
+#       define foo
+#       $(V)echo bar
+#       endef
+#
+#       all: ; $(foo)
+#
+# and the user thinks it should behave the same as when the "@" is literal
+# instead of in a variable, that can't happen because by the time make
+# expands the variables for the command line and sees it begins with a "@" it
+# can't know anymore whether the prefix character came before the variable
+# reference or was included in the first line of the variable reference.
+
+# TEST #5
+# -------
+
+run_make_test('
+define FOO
+$(V1)echo hello
+$(V2)echo world
+endef
+all: ; @$(FOO)
+', '', 'hello
+world');
+
+# TEST #6
+# -------
+
+run_make_test(undef, 'V1=@ V2=@', 'hello
+world');
+
+# TEST #7
+# -------
+
+run_make_test('
+define FOO
+$(V1)echo hello
+$(V2)echo world
+endef
+all: ; $(FOO)
+', 'V1=@', 'hello
+echo world
+world');
+
+# TEST #8
+# -------
+
+run_make_test(undef, 'V2=@', 'echo hello
+hello
+world');
+
+# TEST #9
+# -------
+
+run_make_test(undef, 'V1=@ V2=@', 'hello
+world');
+
+# TEST #10
+# -------
+# Test the basics; a "@" internally to the variable applies to only one line.
+# A "@" before the variable applies to the entire variable.
+
+run_make_test('
+define FOO
+@echo hello
+echo world
+endef
+define BAR
+echo hello
+echo world
+endef
+
+all: foo bar
+foo: ; $(FOO)
+bar: ; @$(BAR)
+', '', 'hello
+echo world
+world
+hello
+world
+');
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/negative
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/negative	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/negative	(revision 1780)
@@ -0,0 +1,46 @@
+#                                                                    -*-perl-*-
+
+$description = "Run some negative tests (things that should fail).";
+
+# TEST #0
+# Check that non-terminated variable references are detected (and
+# reported using the best filename/lineno info
+run_make_test('
+foo = bar
+x = $(foo
+y = $x
+
+all: ; @echo $y
+',
+              '', '#MAKEFILE#:3: *** unterminated variable reference.  Stop.',
+              512);
+
+# TEST #1
+# Bogus variable value passed on the command line.
+run_make_test(undef,
+              'x=\$\(other',
+              '#MAKEFILE#:4: *** unterminated variable reference.  Stop.',
+              512);
+
+# TEST #2
+# Again, but this time while reading the makefile.
+run_make_test('
+foo = bar
+x = $(foo
+y = $x
+
+z := $y
+
+all: ; @echo $y
+',
+              '', '#MAKEFILE#:3: *** unterminated variable reference.  Stop.',
+              512);
+
+# TEST #3
+# Bogus variable value passed on the command line.
+run_make_test(undef,
+              'x=\$\(other',
+              '#MAKEFILE#:4: *** unterminated variable reference.  Stop.',
+              512);
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/special
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/special	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/scripts/variables/special	(revision 1780)
@@ -0,0 +1,54 @@
+#                                                                    -*-perl-*-
+
+$description = "Test special GNU make variables.";
+
+$details = "";
+
+&run_make_test('
+
+X1 := $(sort $(filter FOO BAR,$(.VARIABLES)))
+
+FOO := foo
+
+X2 := $(sort $(filter FOO BAR,$(.VARIABLES)))
+
+BAR := bar
+
+all:
+	@echo X1 = $(X1)
+	@echo X2 = $(X2)
+	@echo LAST = $(sort $(filter FOO BAR,$(.VARIABLES)))
+',
+               '', "X1 =\nX2 = FOO\nLAST = BAR FOO\n");
+
+
+
+# $makefile2 = &get_tmpfile;
+# open(MAKEFILE, "> $makefile2");
+
+# print MAKEFILE <<'EOF';
+
+# X1 := $(sort $(.TARGETS))
+
+# all: foo
+# 	@echo X1 = $(X1)
+# 	@echo X2 = $(X2)
+# 	@echo LAST = $(sort $(.TARGETS))
+
+# X2 := $(sort $(.TARGETS))
+
+# foo:
+
+# EOF
+
+# close(MAKEFILE);
+
+# # TEST #2
+# # -------
+
+# &run_make_with_options($makefile2, "", &get_logfile);
+# $answer = "X1 =\nX2 = all\nLAST = all foo\n";
+# &compare_output($answer, &get_logfile(1));
+
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/tests/test_driver.pl
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/tests/test_driver.pl	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/tests/test_driver.pl	(revision 1780)
@@ -0,0 +1,1188 @@
+#!/usr/bin/perl
+# -*-perl-*-
+#
+# Modification history:
+# Written 91-12-02 through 92-01-01 by Stephen McGee.
+# Modified 92-02-11 through 92-02-22 by Chris Arthur to further generalize.
+#
+# Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+# 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+# Test driver routines used by a number of test suites, including
+# those for SCS, make, roll_dir, and scan_deps (?).
+#
+# this routine controls the whole mess; each test suite sets up a few
+# variables and then calls &toplevel, which does all the real work.
+
+# $Id: test_driver.pl,v 1.21 2007/03/20 03:02:26 psmith Exp $
+
+
+# The number of test categories we've run
+$categories_run = 0;
+# The number of test categroies that have passed
+$categories_passed = 0;
+# The total number of individual tests that have been run
+$total_tests_run = 0;
+# The total number of individual tests that have passed
+$total_tests_passed = 0;
+# The number of tests in this category that have been run
+$tests_run = 0;
+# The number of tests in this category that have passed
+$tests_passed = 0;
+
+
+# Yeesh.  This whole test environment is such a hack!
+$test_passed = 1;
+
+
+# %makeENV is the cleaned-out environment.
+%makeENV = ();
+
+# %extraENV are any extra environment variables the tests might want to set.
+# These are RESET AFTER EVERY TEST!
+%extraENV = ();
+
+# %origENV is the caller's original environment
+%origENV = %ENV;
+
+sub resetENV
+{
+  # We used to say "%ENV = ();" but this doesn't work in Perl 5.000
+  # through Perl 5.004.  It was fixed in Perl 5.004_01, but we don't
+  # want to require that here, so just delete each one individually.
+  foreach $v (keys %ENV) {
+    delete $ENV{$v};
+  }
+
+  %ENV = %makeENV;
+  foreach $v (keys %extraENV) {
+    $ENV{$v} = $extraENV{$v};
+    delete $extraENV{$v};
+  }
+}
+
+sub toplevel
+{
+  # Pull in benign variables from the user's environment
+
+  foreach (# UNIX-specific things
+           'TZ', 'TMPDIR', 'HOME', 'USER', 'LOGNAME', 'PATH',
+           # Purify things
+           'PURIFYOPTIONS',
+           # Windows NT-specific stuff
+           'Path', 'SystemRoot',
+           # DJGPP-specific stuff
+           'DJDIR', 'DJGPP', 'SHELL', 'COMSPEC', 'HOSTNAME', 'LFN',
+           'FNCASE', '387', 'EMU387', 'GROUP'
+          ) {
+    $makeENV{$_} = $ENV{$_} if $ENV{$_};
+  }
+
+  # Make sure our compares are not foiled by locale differences
+
+  $makeENV{LC_ALL} = 'C';
+
+  # Replace the environment with the new one
+  #
+  %origENV = %ENV;
+
+  resetENV();
+
+  $| = 1;                     # unbuffered output
+
+  $debug = 0;                 # debug flag
+  $profile = 0;               # profiling flag
+  $verbose = 0;               # verbose mode flag
+  $detail = 0;                # detailed verbosity
+  $keep = 0;                  # keep temp files around
+  $workdir = "work";          # The directory where the test will start running
+  $scriptdir = "scripts";     # The directory where we find the test scripts
+  $tmpfilesuffix = "t";       # the suffix used on tmpfiles
+  $default_output_stack_level = 0;  # used by attach_default_output, etc.
+  $default_input_stack_level = 0;   # used by attach_default_input, etc.
+  $cwd = ".";                 # don't we wish we knew
+  $cwdslash = "";             # $cwd . $pathsep, but "" rather than "./"
+
+  &get_osname;  # sets $osname, $vos, $pathsep, and $short_filenames
+
+  &set_defaults;  # suite-defined
+
+  &parse_command_line (@ARGV);
+
+  print "OS name = `$osname'\n" if $debug;
+
+  $workpath = "$cwdslash$workdir";
+  $scriptpath = "$cwdslash$scriptdir";
+
+  &set_more_defaults;  # suite-defined
+
+  &print_banner;
+
+  if (-d $workpath)
+  {
+    print "Clearing $workpath...\n";
+    &remove_directory_tree("$workpath/")
+          || &error ("Couldn't wipe out $workpath\n");
+  }
+  else
+  {
+    mkdir ($workpath, 0777) || &error ("Couldn't mkdir $workpath: $!\n");
+  }
+
+  if (!-d $scriptpath)
+  {
+    &error ("Failed to find $scriptpath containing perl test scripts.\n");
+  }
+
+  if (@TESTS)
+  {
+    print "Making work dirs...\n";
+    foreach $test (@TESTS)
+    {
+      if ($test =~ /^([^\/]+)\//)
+      {
+        $dir = $1;
+        push (@rmdirs, $dir);
+        -d "$workpath/$dir"
+	   || mkdir ("$workpath/$dir", 0777)
+           || &error ("Couldn't mkdir $workpath/$dir: $!\n");
+      }
+    }
+  }
+  else
+  {
+    print "Finding tests...\n";
+    opendir (SCRIPTDIR, $scriptpath)
+	|| &error ("Couldn't opendir $scriptpath: $!\n");
+    @dirs = grep (!/^(\..*|CVS|RCS)$/, readdir (SCRIPTDIR) );
+    closedir (SCRIPTDIR);
+    foreach $dir (@dirs)
+    {
+      next if ($dir =~ /^(\..*|CVS|RCS)$/ || ! -d "$scriptpath/$dir");
+      push (@rmdirs, $dir);
+      mkdir ("$workpath/$dir", 0777)
+           || &error ("Couldn't mkdir $workpath/$dir: $!\n");
+      opendir (SCRIPTDIR, "$scriptpath/$dir")
+	  || &error ("Couldn't opendir $scriptpath/$dir: $!\n");
+      @files = grep (!/^(\..*|CVS|RCS|.*~)$/, readdir (SCRIPTDIR) );
+      closedir (SCRIPTDIR);
+      foreach $test (@files)
+      {
+        -d $test and next;
+	push (@TESTS, "$dir/$test");
+      }
+    }
+  }
+
+  if (@TESTS == 0)
+  {
+    &error ("\nNo tests in $scriptpath, and none were specified.\n");
+  }
+
+  print "\n";
+
+  &run_each_test;
+
+  foreach $dir (@rmdirs)
+  {
+    rmdir ("$workpath/$dir");
+  }
+
+  $| = 1;
+
+  $categories_failed = $categories_run - $categories_passed;
+  $total_tests_failed = $total_tests_run - $total_tests_passed;
+
+  if ($total_tests_failed)
+  {
+    print "\n$total_tests_failed Test";
+    print "s" unless $total_tests_failed == 1;
+    print " in $categories_failed Categor";
+    print ($categories_failed == 1 ? "y" : "ies");
+    print " Failed (See .$diffext files in $workdir dir for details) :-(\n\n";
+    return 0;
+  }
+  else
+  {
+    print "\n$total_tests_passed Test";
+    print "s" unless $total_tests_passed == 1;
+    print " in $categories_passed Categor";
+    print ($categories_passed == 1 ? "y" : "ies");
+    print " Complete ... No Failures :-)\n\n";
+    return 1;
+  }
+}
+
+sub get_osname
+{
+  # Set up an initial value.  In perl5 we can do it the easy way.
+  #
+  $osname = defined($^O) ? $^O : '';
+
+  # See if the filesystem supports long file names with multiple
+  # dots.  DOS doesn't.
+  $short_filenames = 0;
+  (open (TOUCHFD, "> fancy.file.name") && close (TOUCHFD))
+      || ($short_filenames = 1);
+  unlink ("fancy.file.name") || ($short_filenames = 1);
+
+  if (! $short_filenames) {
+    # Thanks go to meyering@cs.utexas.edu (Jim Meyering) for suggesting a
+    # better way of doing this.  (We used to test for existence of a /mnt
+    # dir, but that apparently fails on an SGI Indigo (whatever that is).)
+    # Because perl on VOS translates /'s to >'s, we need to test for
+    # VOSness rather than testing for Unixness (ie, try > instead of /).
+
+    mkdir (".ostest", 0777) || &error ("Couldn't create .ostest: $!\n", 1);
+    open (TOUCHFD, "> .ostest>ick") && close (TOUCHFD);
+    chdir (".ostest") || &error ("Couldn't chdir to .ostest: $!\n", 1);
+  }
+
+  if (! $short_filenames && -f "ick")
+  {
+    $osname = "vos";
+    $vos = 1;
+    $pathsep = ">";
+  }
+  else
+  {
+    # the following is regrettably knarly, but it seems to be the only way
+    # to not get ugly error messages if uname can't be found.
+    # Hmmm, BSD/OS 2.0's uname -a is excessively verbose.  Let's try it
+    # with switches first.
+    eval "chop (\$osname = `sh -c 'uname -nmsr 2>&1'`)";
+    if ($osname =~ /not found/i)
+    {
+	$osname = "(something unixy with no uname)";
+    }
+    elsif ($@ ne "" || $?)
+    {
+        eval "chop (\$osname = `sh -c 'uname -a 2>&1'`)";
+        if ($@ ne "" || $?)
+        {
+	    $osname = "(something unixy)";
+	}
+    }
+    $vos = 0;
+    $pathsep = "/";
+  }
+
+  if (! $short_filenames) {
+    chdir ("..") || &error ("Couldn't chdir to ..: $!\n", 1);
+    unlink (".ostest>ick");
+    rmdir (".ostest") || &error ("Couldn't rmdir .ostest: $!\n", 1);
+  }
+}
+
+sub parse_command_line
+{
+  @argv = @_;
+
+  # use @ARGV if no args were passed in
+
+  if (@argv == 0)
+  {
+    @argv = @ARGV;
+  }
+
+  # look at each option; if we don't recognize it, maybe the suite-specific
+  # command line parsing code will...
+
+  while (@argv)
+  {
+    $option = shift @argv;
+    if ($option =~ /^-debug$/i)
+    {
+      print "\nDEBUG ON\n";
+      $debug = 1;
+    }
+    elsif ($option =~ /^-usage$/i)
+    {
+      &print_usage;
+      exit 0;
+    }
+    elsif ($option =~ /^-(h|help)$/i)
+    {
+      &print_help;
+      exit 0;
+    }
+    elsif ($option =~ /^-profile$/i)
+    {
+      $profile = 1;
+    }
+    elsif ($option =~ /^-verbose$/i)
+    {
+      $verbose = 1;
+    }
+    elsif ($option =~ /^-detail$/i)
+    {
+      $detail = 1;
+      $verbose = 1;
+    }
+    elsif ($option =~ /^-keep$/i)
+    {
+      $keep = 1;
+    }
+    elsif (&valid_option($option))
+    {
+      # The suite-defined subroutine takes care of the option
+    }
+    elsif ($option =~ /^-/)
+    {
+      print "Invalid option: $option\n";
+      &print_usage;
+      exit 0;
+    }
+    else # must be the name of a test
+    {
+      $option =~ s/\.pl$//;
+      push(@TESTS,$option);
+    }
+  }
+}
+
+sub max
+{
+  local($num) = shift @_;
+  local($newnum);
+
+  while (@_)
+  {
+    $newnum = shift @_;
+    if ($newnum > $num)
+    {
+      $num = $newnum;
+    }
+  }
+
+  return $num;
+}
+
+sub print_centered
+{
+  local($width, $string) = @_;
+  local($pad);
+
+  if (length ($string))
+  {
+    $pad = " " x ( ($width - length ($string) + 1) / 2);
+    print "$pad$string";
+  }
+}
+
+sub print_banner
+{
+  local($info);
+  local($line);
+  local($len);
+
+  $info = "Running tests for $testee on $osname\n";  # $testee is suite-defined
+  $len = &max (length ($line), length ($testee_version),
+               length ($banner_info), 73) + 5;
+  $line = ("-" x $len) . "\n";
+  if ($len < 78)
+  {
+    $len = 78;
+  }
+
+  &print_centered ($len, $line);
+  &print_centered ($len, $info);
+  &print_centered ($len, $testee_version);  # suite-defined
+  &print_centered ($len, $banner_info);     # suite-defined
+  &print_centered ($len, $line);
+  print "\n";
+}
+
+sub run_each_test
+{
+  $categories_run = 0;
+
+  foreach $testname (sort @TESTS)
+  {
+    ++$categories_run;
+    $suite_passed = 1;       # reset by test on failure
+    $num_of_logfiles = 0;
+    $num_of_tmpfiles = 0;
+    $description = "";
+    $details = "";
+    $old_makefile = undef;
+    $testname =~ s/^$scriptpath$pathsep//;
+    $perl_testname = "$scriptpath$pathsep$testname";
+    $testname =~ s/(\.pl|\.perl)$//;
+    $testpath = "$workpath$pathsep$testname";
+    # Leave enough space in the extensions to append a number, even
+    # though it needs to fit into 8+3 limits.
+    if ($short_filenames) {
+      $logext = 'l';
+      $diffext = 'd';
+      $baseext = 'b';
+      $extext = '';
+    } else {
+      $logext = 'log';
+      $diffext = 'diff';
+      $baseext = 'base';
+      $extext = '.';
+    }
+    $log_filename = "$testpath.$logext";
+    $diff_filename = "$testpath.$diffext";
+    $base_filename = "$testpath.$baseext";
+    $tmp_filename = "$testpath.$tmpfilesuffix";
+
+    &setup_for_test;          # suite-defined
+
+    $output = "........................................................ ";
+
+    substr($output,0,length($testname)) = "$testname ";
+
+    print $output;
+
+    # Run the actual test!
+    $tests_run = 0;
+    $tests_passed = 0;
+    $code = do $perl_testname;
+
+    $total_tests_run += $tests_run;
+    $total_tests_passed += $tests_passed;
+
+    # How did it go?
+    if (!defined($code))
+    {
+      $suite_passed = 0;
+      if (length ($@)) {
+        warn "\n*** Test died ($testname): $@\n";
+      } else {
+        warn "\n*** Couldn't run $perl_testname\n";
+      }
+    }
+    elsif ($code == -1) {
+      $suite_passed = 0;
+    }
+    elsif ($code != 1 && $code != -1) {
+      $suite_passed = 0;
+      warn "\n*** Test returned $code\n";
+    }
+
+    if ($suite_passed) {
+      ++$categories_passed;
+      $status = "ok     ($tests_passed passed)";
+      for ($i = $num_of_tmpfiles; $i; $i--)
+      {
+        &rmfiles ($tmp_filename . &num_suffix ($i) );
+      }
+
+      for ($i = $num_of_logfiles ? $num_of_logfiles : 1; $i; $i--)
+      {
+        &rmfiles ($log_filename . &num_suffix ($i) );
+        &rmfiles ($base_filename . &num_suffix ($i) );
+      }
+    }
+    elsif (!defined $code || $code > 0) {
+      $status = "FAILED ($tests_passed/$tests_run passed)";
+    }
+    elsif ($code < 0) {
+      $status = "N/A";
+      --$categories_run;
+    }
+
+    # If the verbose option has been specified, then a short description
+    # of each test is printed before displaying the results of each test
+    # describing WHAT is being tested.
+
+    if ($verbose)
+    {
+      if ($detail)
+      {
+        print "\nWHAT IS BEING TESTED\n";
+        print "--------------------";
+      }
+      print "\n\n$description\n\n";
+    }
+
+    # If the detail option has been specified, then the details of HOW
+    # the test is testing what it says it is testing in the verbose output
+    # will be displayed here before the results of the test are displayed.
+
+    if ($detail)
+    {
+      print "\nHOW IT IS TESTED\n";
+      print "----------------";
+      print "\n\n$details\n\n";
+    }
+
+    print "$status\n";
+  }
+}
+
+# If the keep flag is not set, this subroutine deletes all filenames that
+# are sent to it.
+
+sub rmfiles
+{
+  local(@files) = @_;
+
+  if (!$keep)
+  {
+    return (unlink @files);
+  }
+
+  return 1;
+}
+
+sub print_standard_usage
+{
+  local($plname,@moreusage) = @_;
+  local($line);
+
+  print "usage:\t$plname [testname] [-verbose] [-detail] [-keep]\n";
+  print "\t\t\t[-profile] [-usage] [-help] [-debug]\n";
+  foreach (@moreusage) {
+    print "\t\t\t$_\n";
+  }
+}
+
+sub print_standard_help
+{
+  local(@morehelp) = @_;
+  local($line);
+  local($tline);
+  local($t) = "      ";
+
+  $line = "Test Driver For $testee";
+  print "$line\n";
+  $line = "=" x length ($line);
+  print "$line\n";
+
+  &print_usage;
+
+  print "\ntestname\n"
+      . "${t}You may, if you wish, run only ONE test if you know the name\n"
+      . "${t}of that test and specify this name anywhere on the command\n"
+      . "${t}line.  Otherwise ALL existing tests in the scripts directory\n"
+      . "${t}will be run.\n"
+      . "-verbose\n"
+      . "${t}If this option is given, a description of every test is\n"
+      . "${t}displayed before the test is run. (Not all tests may have\n"
+      . "${t}descriptions at this time)\n"
+      . "-detail\n"
+      . "${t}If this option is given, a detailed description of every\n"
+      . "${t}test is displayed before the test is run. (Not all tests\n"
+      . "${t}have descriptions at this time)\n"
+      . "-profile\n"
+      . "${t}If this option is given, then the profile file\n"
+      . "${t}is added to other profiles every time $testee is run.\n"
+      . "${t}This option only works on VOS at this time.\n"
+      . "-keep\n"
+      . "${t}You may give this option if you DO NOT want ANY\n"
+      . "${t}of the files generated by the tests to be deleted. \n"
+      . "${t}Without this option, all files generated by the test will\n"
+      . "${t}be deleted IF THE TEST PASSES.\n"
+      . "-debug\n"
+      . "${t}Use this option if you would like to see all of the system\n"
+      . "${t}calls issued and their return status while running the tests\n"
+      . "${t}This can be helpful if you're having a problem adding a test\n"
+      . "${t}to the suite, or if the test fails!\n";
+
+  foreach $line (@morehelp)
+  {
+    $tline = $line;
+    if (substr ($tline, 0, 1) eq "\t")
+    {
+      substr ($tline, 0, 1) = $t;
+    }
+    print "$tline\n";
+  }
+}
+
+#######################################################################
+###########         Generic Test Driver Subroutines         ###########
+#######################################################################
+
+sub get_caller
+{
+  local($depth);
+  local($package);
+  local($filename);
+  local($linenum);
+
+  $depth = defined ($_[0]) ? $_[0] : 1;
+  ($package, $filename, $linenum) = caller ($depth + 1);
+  return "$filename: $linenum";
+}
+
+sub error
+{
+  local($message) = $_[0];
+  local($caller) = &get_caller (1);
+
+  if (defined ($_[1]))
+  {
+    $caller = &get_caller ($_[1] + 1) . " -> $caller";
+  }
+
+  die "$caller: $message";
+}
+
+sub compare_output
+{
+  local($answer,$logfile) = @_;
+  local($slurp, $answer_matched) = ('', 0);
+
+  print "Comparing Output ........ " if $debug;
+
+  $slurp = &read_file_into_string ($logfile);
+
+  # For make, get rid of any time skew error before comparing--too bad this
+  # has to go into the "generic" driver code :-/
+  $slurp =~ s/^.*modification time .*in the future.*\n//gm;
+  $slurp =~ s/^.*Clock skew detected.*\n//gm;
+
+  ++$tests_run;
+
+  if ($slurp eq $answer) {
+    $answer_matched = 1;
+  } else {
+    # See if it is a slash or CRLF problem
+    local ($answer_mod) = $answer;
+
+    $answer_mod =~ tr,\\,/,;
+    $answer_mod =~ s,\r\n,\n,gs;
+
+    $slurp =~ tr,\\,/,;
+    $slurp =~ s,\r\n,\n,gs;
+
+    $answer_matched = ($slurp eq $answer_mod);
+  }
+
+  if ($answer_matched && $test_passed)
+  {
+    print "ok\n" if $debug;
+    ++$tests_passed;
+    return 1;
+  }
+
+  if (! $answer_matched) {
+    print "DIFFERENT OUTPUT\n" if $debug;
+
+    &create_file (&get_basefile, $answer);
+
+    print "\nCreating Difference File ...\n" if $debug;
+
+    # Create the difference file
+
+    local($command) = "diff -c " . &get_basefile . " " . $logfile;
+    &run_command_with_output(&get_difffile,$command);
+  }
+
+  $suite_passed = 0;
+  return 0;
+}
+
+sub read_file_into_string
+{
+  local($filename) = @_;
+  local($oldslash) = $/;
+
+  undef $/;
+
+  open (RFISFILE, $filename) || return "";
+  local ($slurp) = <RFISFILE>;
+  close (RFISFILE);
+
+  $/ = $oldslash;
+
+  return $slurp;
+}
+
+sub attach_default_output
+{
+  local ($filename) = @_;
+  local ($code);
+
+  if ($vos)
+  {
+    $code = system "++attach_default_output_hack $filename";
+    $code == -2 || &error ("adoh death\n", 1);
+    return 1;
+  }
+
+  open ("SAVEDOS" . $default_output_stack_level . "out", ">&STDOUT")
+        || &error ("ado: $! duping STDOUT\n", 1);
+  open ("SAVEDOS" . $default_output_stack_level . "err", ">&STDERR")
+        || &error ("ado: $! duping STDERR\n", 1);
+
+  open (STDOUT, "> " . $filename)
+        || &error ("ado: $filename: $!\n", 1);
+  open (STDERR, ">&STDOUT")
+        || &error ("ado: $filename: $!\n", 1);
+
+  $default_output_stack_level++;
+}
+
+# close the current stdout/stderr, and restore the previous ones from
+# the "stack."
+
+sub detach_default_output
+{
+  local ($code);
+
+  if ($vos)
+  {
+    $code = system "++detach_default_output_hack";
+    $code == -2 || &error ("ddoh death\n", 1);
+    return 1;
+  }
+
+  if (--$default_output_stack_level < 0)
+  {
+    &error ("default output stack has flown under!\n", 1);
+  }
+
+  close (STDOUT);
+  close (STDERR);
+
+  open (STDOUT, ">&SAVEDOS" . $default_output_stack_level . "out")
+        || &error ("ddo: $! duping STDOUT\n", 1);
+  open (STDERR, ">&SAVEDOS" . $default_output_stack_level . "err")
+        || &error ("ddo: $! duping STDERR\n", 1);
+
+  close ("SAVEDOS" . $default_output_stack_level . "out")
+        || &error ("ddo: $! closing SCSDOSout\n", 1);
+  close ("SAVEDOS" . $default_output_stack_level . "err")
+         || &error ("ddo: $! closing SAVEDOSerr\n", 1);
+}
+
+# run one command (passed as a list of arg 0 - n), returning 0 on success
+# and nonzero on failure.
+
+sub run_command
+{
+  local ($code);
+
+  # We reset this before every invocation.  On Windows I think there is only
+  # one environment, not one per process, so I think that variables set in
+  # test scripts might leak into subsequent tests if this isn't reset--???
+  resetENV();
+
+  print "\nrun_command: @_\n" if $debug;
+  $code = system @_;
+  print "run_command: \"@_\" returned $code.\n" if $debug;
+
+  return $code;
+}
+
+# run one command (passed as a list of arg 0 - n, with arg 0 being the
+# second arg to this routine), returning 0 on success and non-zero on failure.
+# The first arg to this routine is a filename to connect to the stdout
+# & stderr of the child process.
+
+sub run_command_with_output
+{
+  local ($filename) = shift;
+  local ($code);
+
+  # We reset this before every invocation.  On Windows I think there is only
+  # one environment, not one per process, so I think that variables set in
+  # test scripts might leak into subsequent tests if this isn't reset--???
+  resetENV();
+
+  &attach_default_output ($filename);
+  $code = system @_;
+  &detach_default_output;
+
+  print "run_command_with_output: '@_' returned $code.\n" if $debug;
+
+  return $code;
+}
+
+# performs the equivalent of an "rm -rf" on the first argument.  Like
+# rm, if the path ends in /, leaves the (now empty) directory; otherwise
+# deletes it, too.
+
+sub remove_directory_tree
+{
+  local ($targetdir) = @_;
+  local ($nuketop) = 1;
+  local ($ch);
+
+  $ch = substr ($targetdir, length ($targetdir) - 1);
+  if ($ch eq "/" || $ch eq $pathsep)
+  {
+    $targetdir = substr ($targetdir, 0, length ($targetdir) - 1);
+    $nuketop = 0;
+  }
+
+  if (! -e $targetdir)
+  {
+    return 1;
+  }
+
+  &remove_directory_tree_inner ("RDT00", $targetdir) || return 0;
+  if ($nuketop)
+  {
+    rmdir $targetdir || return 0;
+  }
+
+  return 1;
+}
+
+sub remove_directory_tree_inner
+{
+  local ($dirhandle, $targetdir) = @_;
+  local ($object);
+  local ($subdirhandle);
+
+  opendir ($dirhandle, $targetdir) || return 0;
+  $subdirhandle = $dirhandle;
+  $subdirhandle++;
+  while ($object = readdir ($dirhandle))
+  {
+    if ($object =~ /^(\.\.?|CVS|RCS)$/)
+    {
+      next;
+    }
+
+    $object = "$targetdir$pathsep$object";
+    lstat ($object);
+
+    if (-d _ && &remove_directory_tree_inner ($subdirhandle, $object))
+    {
+      rmdir $object || return 0;
+    }
+    else
+    {
+      unlink $object || return 0;
+    }
+  }
+  closedir ($dirhandle);
+  return 1;
+}
+
+# We used to use this behavior for this function:
+#
+#sub touch
+#{
+#  local (@filenames) = @_;
+#  local ($now) = time;
+#  local ($file);
+#
+#  foreach $file (@filenames)
+#  {
+#    utime ($now, $now, $file)
+#          || (open (TOUCHFD, ">> $file") && close (TOUCHFD))
+#               || &error ("Couldn't touch $file: $!\n", 1);
+#  }
+#  return 1;
+#}
+#
+# But this behaves badly on networked filesystems where the time is
+# skewed, because it sets the time of the file based on the _local_
+# host.  Normally when you modify a file, it's the _remote_ host that
+# determines the modtime, based on _its_ clock.  So, instead, now we open
+# the file and write something into it to force the remote host to set
+# the modtime correctly according to its clock.
+#
+
+sub touch
+{
+  local ($file);
+
+  foreach $file (@_) {
+    (open(T, ">> $file") && print(T "\n") && close(T))
+	|| &error("Couldn't touch $file: $!\n", 1);
+  }
+}
+
+# Touch with a time offset.  To DTRT, call touch() then use stat() to get the
+# access/mod time for each file and apply the offset.
+
+sub utouch
+{
+  local ($off) = shift;
+  local ($file);
+
+  &touch(@_);
+
+  local (@s) = stat($_[0]);
+
+  utime($s[8]+$off, $s[9]+$off, @_);
+}
+
+# open a file, write some stuff to it, and close it.
+
+sub create_file
+{
+  local ($filename, @lines) = @_;
+
+  open (CF, "> $filename") || &error ("Couldn't open $filename: $!\n", 1);
+  foreach $line (@lines)
+  {
+    print CF $line;
+  }
+  close (CF);
+}
+
+# create a directory tree described by an associative array, wherein each
+# key is a relative pathname (using slashes) and its associated value is
+# one of:
+#    DIR            indicates a directory
+#    FILE:contents  indicates a file, which should contain contents +\n
+#    LINK:target    indicates a symlink, pointing to $basedir/target
+# The first argument is the dir under which the structure will be created
+# (the dir will be made and/or cleaned if necessary); the second argument
+# is the associative array.
+
+sub create_dir_tree
+{
+  local ($basedir, %dirtree) = @_;
+  local ($path);
+
+  &remove_directory_tree ("$basedir");
+  mkdir ($basedir, 0777) || &error ("Couldn't mkdir $basedir: $!\n", 1);
+
+  foreach $path (sort keys (%dirtree))
+  {
+    if ($dirtree {$path} =~ /^DIR$/)
+    {
+      mkdir ("$basedir/$path", 0777)
+               || &error ("Couldn't mkdir $basedir/$path: $!\n", 1);
+    }
+    elsif ($dirtree {$path} =~ /^FILE:(.*)$/)
+    {
+      &create_file ("$basedir/$path", $1 . "\n");
+    }
+    elsif ($dirtree {$path} =~ /^LINK:(.*)$/)
+    {
+      symlink ("$basedir/$1", "$basedir/$path")
+        || &error ("Couldn't symlink $basedir/$path -> $basedir/$1: $!\n", 1);
+    }
+    else
+    {
+      &error ("Bogus dirtree type: \"$dirtree{$path}\"\n", 1);
+    }
+  }
+  if ($just_setup_tree)
+  {
+    die "Tree is setup...\n";
+  }
+}
+
+# compare a directory tree with an associative array in the format used
+# by create_dir_tree, above.
+# The first argument is the dir under which the structure should be found;
+# the second argument is the associative array.
+
+sub compare_dir_tree
+{
+  local ($basedir, %dirtree) = @_;
+  local ($path);
+  local ($i);
+  local ($bogus) = 0;
+  local ($contents);
+  local ($target);
+  local ($fulltarget);
+  local ($found);
+  local (@files);
+  local (@allfiles);
+
+  opendir (DIR, $basedir) || &error ("Couldn't open $basedir: $!\n", 1);
+  @allfiles = grep (!/^(\.\.?|CVS|RCS)$/, readdir (DIR) );
+  closedir (DIR);
+  if ($debug)
+  {
+    print "dirtree: (%dirtree)\n$basedir: (@allfiles)\n";
+  }
+
+  foreach $path (sort keys (%dirtree))
+  {
+    if ($debug)
+    {
+      print "Checking $path ($dirtree{$path}).\n";
+    }
+
+    $found = 0;
+    foreach $i (0 .. $#allfiles)
+    {
+      if ($allfiles[$i] eq $path)
+      {
+        splice (@allfiles, $i, 1);  # delete it
+        if ($debug)
+        {
+          print "     Zapped $path; files now (@allfiles).\n";
+        }
+        lstat ("$basedir/$path");
+        $found = 1;
+        last;
+      }
+    }
+
+    if (!$found)
+    {
+      print "compare_dir_tree: $path does not exist.\n";
+      $bogus = 1;
+      next;
+    }
+
+    if ($dirtree {$path} =~ /^DIR$/)
+    {
+      if (-d _ && opendir (DIR, "$basedir/$path") )
+      {
+        @files = readdir (DIR);
+        closedir (DIR);
+        @files = grep (!/^(\.\.?|CVS|RCS)$/ && ($_ = "$path/$_"), @files);
+        push (@allfiles, @files);
+        if ($debug)
+        {
+          print "     Read in $path; new files (@files).\n";
+        }
+      }
+      else
+      {
+        print "compare_dir_tree: $path is not a dir.\n";
+        $bogus = 1;
+      }
+    }
+    elsif ($dirtree {$path} =~ /^FILE:(.*)$/)
+    {
+      if (-l _ || !-f _)
+      {
+        print "compare_dir_tree: $path is not a file.\n";
+        $bogus = 1;
+        next;
+      }
+
+      if ($1 ne "*")
+      {
+        $contents = &read_file_into_string ("$basedir/$path");
+        if ($contents ne "$1\n")
+        {
+          print "compare_dir_tree: $path contains wrong stuff."
+              . "  Is:\n$contentsShould be:\n$1\n";
+          $bogus = 1;
+        }
+      }
+    }
+    elsif ($dirtree {$path} =~ /^LINK:(.*)$/)
+    {
+      $target = $1;
+      if (!-l _)
+      {
+        print "compare_dir_tree: $path is not a link.\n";
+        $bogus = 1;
+        next;
+      }
+
+      $contents = readlink ("$basedir/$path");
+      $contents =~ tr/>/\//;
+      $fulltarget = "$basedir/$target";
+      $fulltarget =~ tr/>/\//;
+      if (!($contents =~ /$fulltarget$/))
+      {
+        if ($debug)
+        {
+          $target = $fulltarget;
+        }
+        print "compare_dir_tree: $path should be link to $target, "
+            . "not $contents.\n";
+        $bogus = 1;
+      }
+    }
+    else
+    {
+      &error ("Bogus dirtree type: \"$dirtree{$path}\"\n", 1);
+    }
+  }
+
+  if ($debug)
+  {
+    print "leftovers: (@allfiles).\n";
+  }
+
+  foreach $file (@allfiles)
+  {
+    print "compare_dir_tree: $file should not exist.\n";
+    $bogus = 1;
+  }
+
+  return !$bogus;
+}
+
+# this subroutine generates the numeric suffix used to keep tmp filenames,
+# log filenames, etc., unique.  If the number passed in is 1, then a null
+# string is returned; otherwise, we return ".n", where n + 1 is the number
+# we were given.
+
+sub num_suffix
+{
+  local($num) = @_;
+
+  if (--$num > 0) {
+    return "$extext$num";
+  }
+
+  return "";
+}
+
+# This subroutine returns a log filename with a number appended to
+# the end corresponding to how many logfiles have been created in the
+# current running test.  An optional parameter may be passed (0 or 1).
+# If a 1 is passed, then it does NOT increment the logfile counter
+# and returns the name of the latest logfile.  If either no parameter
+# is passed at all or a 0 is passed, then the logfile counter is
+# incremented and the new name is returned.
+
+sub get_logfile
+{
+  local($no_increment) = @_;
+
+  $num_of_logfiles += !$no_increment;
+
+  return ($log_filename . &num_suffix ($num_of_logfiles));
+}
+
+# This subroutine returns a base (answer) filename with a number
+# appended to the end corresponding to how many logfiles (and thus
+# base files) have been created in the current running test.
+# NO PARAMETERS ARE PASSED TO THIS SUBROUTINE.
+
+sub get_basefile
+{
+  return ($base_filename . &num_suffix ($num_of_logfiles));
+}
+
+# This subroutine returns a difference filename with a number appended
+# to the end corresponding to how many logfiles (and thus diff files)
+# have been created in the current running test.
+
+sub get_difffile
+{
+  return ($diff_filename . &num_suffix ($num_of_logfiles));
+}
+
+# just like logfile, only a generic tmp filename for use by the test.
+# they are automatically cleaned up unless -keep was used, or the test fails.
+# Pass an argument of 1 to return the same filename as the previous call.
+
+sub get_tmpfile
+{
+  local($no_increment) = @_;
+
+  $num_of_tmpfiles += !$no_increment;
+
+  return ($tmp_filename . &num_suffix ($num_of_tmpfiles));
+}
+
+1;
Index: /tags/kBuild-0.1.4/src/kmk/variable.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/variable.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/variable.c	(revision 1780)
@@ -0,0 +1,2287 @@
+/* Internals of variables for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+
+#include <assert.h>
+
+#include "dep.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "variable.h"
+#include "rule.h"
+#ifdef WINDOWS32
+#include "pathstuff.h"
+#endif
+#include "hash.h"
+#ifdef KMK
+# include "kbuild.h"
+#endif
+
+/* Chain of all pattern-specific variables.  */
+
+static struct pattern_var *pattern_vars;
+
+/* Pointer to last struct in the chain, so we can add onto the end.  */
+
+static struct pattern_var *last_pattern_var;
+
+/* Create a new pattern-specific variable struct.  */
+
+struct pattern_var *
+create_pattern_var (const char *target, const char *suffix)
+{
+  register struct pattern_var *p = xmalloc (sizeof (struct pattern_var));
+
+  if (last_pattern_var != 0)
+    last_pattern_var->next = p;
+  else
+    pattern_vars = p;
+  last_pattern_var = p;
+  p->next = 0;
+
+  p->target = target;
+  p->len = strlen (target);
+  p->suffix = suffix + 1;
+
+  return p;
+}
+
+/* Look up a target in the pattern-specific variable list.  */
+
+static struct pattern_var *
+lookup_pattern_var (struct pattern_var *start, const char *target)
+{
+  struct pattern_var *p;
+  unsigned int targlen = strlen(target);
+
+  for (p = start ? start->next : pattern_vars; p != 0; p = p->next)
+    {
+      const char *stem;
+      unsigned int stemlen;
+
+      if (p->len > targlen)
+        /* It can't possibly match.  */
+        continue;
+
+      /* From the lengths of the filename and the pattern parts,
+         find the stem: the part of the filename that matches the %.  */
+      stem = target + (p->suffix - p->target - 1);
+      stemlen = targlen - p->len + 1;
+
+      /* Compare the text in the pattern before the stem, if any.  */
+      if (stem > target && !strneq (p->target, target, stem - target))
+        continue;
+
+      /* Compare the text in the pattern after the stem, if any.
+         We could test simply using streq, but this way we compare the
+         first two characters immediately.  This saves time in the very
+         common case where the first character matches because it is a
+         period.  */
+      if (*p->suffix == stem[stemlen]
+          && (*p->suffix == '\0' || streq (&p->suffix[1], &stem[stemlen+1])))
+        break;
+    }
+
+  return p;
+}
+
+
+/* Hash table of all global variable definitions.  */
+
+#if defined(VARIABLE_HASH) || defined(CONFIG_WITH_OPTIMIZATION_HACKS)
+# ifdef _MSC_VER
+#  define inline _inline
+typedef signed int int32_t;
+typedef signed short int int16_t;
+# endif
+static inline unsigned long variable_hash_2i(register const char *var, register int length)
+{
+# define UPDATE_HASH(ch) hash = (ch) + (hash << 6) + (hash << 16) - hash
+# ifndef CONFIG_WITH_OPTIMIZATION_HACKS
+#  if 1
+    register const unsigned char *uvar = (const unsigned char *)var;
+    register unsigned long hash = 0;
+    while (length-- > 0)
+        UPDATE_HASH(*uvar++);
+    return hash;
+#  else
+    return_STRING_N_HASH_2 (var, length);
+#  endif
+# else /* CONFIG_WITH_OPTIMIZATION_HACKS */
+    register unsigned long hash = 0;
+    register const unsigned char *uvar = (const unsigned char *)var;
+    register const unsigned char *uvar_end = uvar + length;
+    switch (length)
+    {
+        default:
+        case 32: //UPDATE_HASH(uvar_end[-16]);
+        case 31: UPDATE_HASH(uvar_end[-15]);
+        case 30: //UPDATE_HASH(uvar_end[-14]);
+        case 29: UPDATE_HASH(uvar_end[-13]);
+        case 28: //UPDATE_HASH(uvar_end[-12]);
+        case 27: UPDATE_HASH(uvar_end[-11]);
+        case 26: //UPDATE_HASH(uvar_end[-10]);
+        case 25: UPDATE_HASH(uvar_end[-9]);
+        case 24: //UPDATE_HASH(uvar[15]);
+        case 23: UPDATE_HASH(uvar[14]);
+        case 22: //UPDATE_HASH(uvar[13]);
+        case 21: UPDATE_HASH(uvar[12]);
+        case 20: //UPDATE_HASH(uvar[11]);
+        case 19: UPDATE_HASH(uvar[10]);
+        case 18: //UPDATE_HASH(uvar[9]);
+        case 17: UPDATE_HASH(uvar[8]);
+        case 16: //UPDATE_HASH(uvar_end[-8]);
+        case 15: UPDATE_HASH(uvar_end[-7]);
+        case 14: //UPDATE_HASH(uvar_end[-6]);
+        case 13: UPDATE_HASH(uvar_end[-5]);
+        case 12: //UPDATE_HASH(uvar_end[-4]);
+        case 11: UPDATE_HASH(uvar_end[-3]);
+        case 10: //UPDATE_HASH(uvar_end[-2]);
+        case 9:  UPDATE_HASH(uvar_end[-1]);
+        case 8:  //UPDATE_HASH(uvar[7]);
+        case 7:  UPDATE_HASH(uvar[6]);
+        case 6:  //UPDATE_HASH(uvar[5]);
+        case 5:  UPDATE_HASH(uvar[4]);
+        case 4:  //UPDATE_HASH(uvar[3]);
+        case 3:  UPDATE_HASH(uvar[2]);
+        case 2:  //UPDATE_HASH(uvar[1]);
+        case 1:  UPDATE_HASH(uvar[0]);
+        case 0:
+            return hash;
+    }
+# endif /* CONFIG_WITH_OPTIMIZATION_HACKS*/
+# undef UPDATE_HASH
+}
+
+static inline unsigned long variable_hash_1i(register const char *var, register int length)
+{
+# define UPDATE_HASH(ch) hash = ((hash << 5) + hash) + (ch)
+# ifndef CONFIG_WITH_OPTIMIZATION_HACKS
+#  if 1
+    register const unsigned char *uvar = (const unsigned char *)var;
+    register unsigned long hash = 5381;
+    while (length-- > 0)
+      UPDATE_HASH(*uvar++);
+    return hash;
+#  else
+    return_STRING_N_HASH_1 (var, length);
+#  endif
+# else /* CONFIG_WITH_OPTIMIZATION_HACKS */
+    register const unsigned char *uvar = (const unsigned char *)var;
+    register const unsigned char *uvar_end = (const unsigned char *)var + length;
+    register unsigned long hash = ((5381 << 5) + 5381) + *uvar;
+    switch (length)
+    {
+        default:
+#if 0 /* seems to be a waste of time. */
+        case 97: UPDATE_HASH(uvar_end[-77]);
+        case 96: //UPDATE_HASH(uvar_end[-76]);
+        case 95: //UPDATE_HASH(uvar_end[-75]);
+        case 94: //UPDATE_HASH(uvar_end[-74]);
+        case 93: UPDATE_HASH(uvar_end[-73]);
+        case 92: //UPDATE_HASH(uvar_end[-72]);
+        case 91: //UPDATE_HASH(uvar_end[-71]);
+        case 90: //UPDATE_HASH(uvar_end[-70]);
+        case 89: UPDATE_HASH(uvar_end[-69]);
+        case 88: //UPDATE_HASH(uvar_end[-68]);
+        case 87: //UPDATE_HASH(uvar_end[-67]);
+        case 86: //UPDATE_HASH(uvar_end[-66]);
+        case 85: UPDATE_HASH(uvar_end[-65]);
+        case 84: //UPDATE_HASH(uvar_end[-64]);
+        case 83: //UPDATE_HASH(uvar_end[-63]);
+        case 82: //UPDATE_HASH(uvar_end[-62]);
+        case 81: UPDATE_HASH(uvar_end[-61]);
+        case 80: //UPDATE_HASH(uvar_end[-60]);
+        case 79: //UPDATE_HASH(uvar_end[-59]);
+        case 78: //UPDATE_HASH(uvar_end[-58]);
+        case 77: UPDATE_HASH(uvar_end[-57]);
+        case 76: //UPDATE_HASH(uvar_end[-56]);
+        case 75: //UPDATE_HASH(uvar_end[-55]);
+        case 74: //UPDATE_HASH(uvar_end[-54]);
+        case 73: UPDATE_HASH(uvar_end[-53]);
+        case 72: //UPDATE_HASH(uvar_end[-52]);
+        case 71: //UPDATE_HASH(uvar_end[-51]);
+        case 70: //UPDATE_HASH(uvar_end[-50]);
+        case 69: UPDATE_HASH(uvar_end[-49]);
+        case 68: //UPDATE_HASH(uvar_end[-48]);
+        case 67: //UPDATE_HASH(uvar_end[-47]);
+        case 66: //UPDATE_HASH(uvar_end[-46]);
+        case 65: UPDATE_HASH(uvar_end[-49]);
+        case 64: //UPDATE_HASH(uvar_end[-48]);
+        case 63: //UPDATE_HASH(uvar_end[-47]);
+        case 62: //UPDATE_HASH(uvar_end[-46]);
+        case 61: UPDATE_HASH(uvar_end[-45]);
+        case 60: //UPDATE_HASH(uvar_end[-44]);
+        case 59: //UPDATE_HASH(uvar_end[-43]);
+        case 58: //UPDATE_HASH(uvar_end[-42]);
+        case 57: UPDATE_HASH(uvar_end[-41]);
+        case 56: //UPDATE_HASH(uvar_end[-40]);
+        case 55: //UPDATE_HASH(uvar_end[-39]);
+        case 54: //UPDATE_HASH(uvar_end[-38]);
+        case 53: UPDATE_HASH(uvar_end[-37]);
+        case 52: //UPDATE_HASH(uvar_end[-36]);
+        case 51: UPDATE_HASH(uvar_end[-35]);
+        case 50: //UPDATE_HASH(uvar_end[-34]);
+        case 49: UPDATE_HASH(uvar_end[-33]);
+#endif
+        case 48: //UPDATE_HASH(uvar_end[-32]);
+        case 47: UPDATE_HASH(uvar_end[-31]);
+        case 46: //UPDATE_HASH(uvar_end[-30]);
+        case 45: UPDATE_HASH(uvar_end[-29]);
+        case 44: //UPDATE_HASH(uvar_end[-28]);
+        case 43: UPDATE_HASH(uvar_end[-27]);
+        case 42: //UPDATE_HASH(uvar_end[-26]);
+        case 41: UPDATE_HASH(uvar_end[-25]);
+        case 40: //UPDATE_HASH(uvar_end[-24]);
+        case 39: UPDATE_HASH(uvar_end[-23]);
+        case 38: //UPDATE_HASH(uvar_end[-22]);
+        case 37: UPDATE_HASH(uvar_end[-21]);
+        case 36: //UPDATE_HASH(uvar_end[-20]);
+        case 35: UPDATE_HASH(uvar_end[-19]);
+        case 34: //UPDATE_HASH(uvar_end[-18]);
+        case 33: UPDATE_HASH(uvar_end[-17]);
+
+        case 32: UPDATE_HASH(uvar_end[-16]);
+        case 31: UPDATE_HASH(uvar_end[-15]);
+        case 30: UPDATE_HASH(uvar_end[-14]);
+        case 29: UPDATE_HASH(uvar_end[-13]);
+        case 28: UPDATE_HASH(uvar[15]);
+        case 27: UPDATE_HASH(uvar[14]);
+        case 26: UPDATE_HASH(uvar[13]);
+        case 25: UPDATE_HASH(uvar[12]);
+
+        case 24: UPDATE_HASH(uvar_end[-12]);
+        case 23: UPDATE_HASH(uvar_end[-11]);
+        case 22: UPDATE_HASH(uvar_end[-10]);
+        case 21: UPDATE_HASH(uvar_end[-9]);
+        case 20: UPDATE_HASH(uvar[7]);
+        case 19: UPDATE_HASH(uvar[6]);
+        case 18: UPDATE_HASH(uvar[5]);
+        case 17: UPDATE_HASH(uvar[4]);
+
+        case 16: UPDATE_HASH(uvar_end[-8]);
+        case 15: UPDATE_HASH(uvar_end[-7]);
+        case 14: UPDATE_HASH(uvar_end[-6]);
+        case 13: UPDATE_HASH(uvar_end[-5]);
+        case 12: UPDATE_HASH(uvar[11]);
+        case 11: UPDATE_HASH(uvar[10]);
+        case 10: UPDATE_HASH(uvar[9]);
+        case 9:  UPDATE_HASH(uvar[8]);
+
+        case 8:  UPDATE_HASH(uvar_end[-4]);
+        case 7:  UPDATE_HASH(uvar_end[-3]);
+        case 6:  UPDATE_HASH(uvar_end[-2]);
+        case 5:  UPDATE_HASH(uvar_end[-1]);
+        case 4:  UPDATE_HASH(uvar[3]);
+        case 3:  UPDATE_HASH(uvar[2]);
+        case 2:  UPDATE_HASH(uvar[1]);
+        case 1:  return hash;
+        case 0:  return 5381; /* shouldn't happen */
+    }
+# endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+# undef UPDATE_HASH
+}
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+
+static unsigned long
+variable_hash_1 (const void *keyv)
+{
+  struct variable const *key = (struct variable const *) keyv;
+#ifdef VARIABLE_HASH /* bird */
+# ifdef VARIABLE_HASH_STRICT
+  if (key->hash1 != variable_hash_1i (key->name, key->length))
+    __asm__("int3");
+  if (key->hash2 && key->hash2 != variable_hash_2i (key->name, key->length))
+    __asm__("int3");
+# endif
+  return key->hash1;
+#else
+# ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+  return variable_hash_1i (key->name, key->length);
+# else
+  return_STRING_N_HASH_1 (key->name, key->length);
+# endif
+#endif
+}
+
+static unsigned long
+variable_hash_2 (const void *keyv)
+{
+#ifdef VARIABLE_HASH /* bird */
+  struct variable *key = (struct variable *) keyv;
+  if (!key->hash2)
+    key->hash2 = variable_hash_2i (key->name, key->length);
+  return key->hash2;
+#else
+  struct variable const *key = (struct variable const *) keyv;
+# ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+  return variable_hash_2i (key->name, key->length);
+# else
+  return_STRING_N_HASH_2 (key->name, key->length);
+# endif
+#endif
+}
+
+static int
+variable_hash_cmp (const void *xv, const void *yv)
+{
+  struct variable const *x = (struct variable const *) xv;
+  struct variable const *y = (struct variable const *) yv;
+  int result = x->length - y->length;
+  if (result)
+    return result;
+#ifdef VARIABLE_HASH
+#ifdef VARIABLE_HASH_STRICT /* bird */
+  if (x->hash1 != variable_hash_1i (x->name, x->length))
+    __asm__("int3");
+  if (x->hash2 && x->hash2 != variable_hash_2i (x->name, x->length))
+    __asm__("int3");
+  if (y->hash1 != variable_hash_1i (y->name, y->length))
+    __asm__("int3");
+  if (y->hash2 && y->hash2 != variable_hash_2i (y->name, y->length))
+    __asm__("int3");
+#endif
+  /* hash 1 */
+  result = x->hash1 - y->hash1;
+  if (result)
+    return result;
+#endif
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS /* bird: speed */
+  {
+    const char *xs = x->name;
+    const char *ys = y->name;
+    switch (x->length)
+      {
+        case 8:
+            result = *(int32_t*)(xs + 4) - *(int32_t*)(ys + 4);
+            if (result)
+              return result;
+            return *(int32_t*)xs - *(int32_t*)ys;
+        case 7:
+            result = xs[6] - ys[6];
+            if (result)
+                return result;
+        case 6:
+            result = *(int32_t*)xs - *(int32_t*)ys;
+            if (result)
+                return result;
+            return *(int16_t*)(xs + 4) - *(int16_t*)(ys + 4);
+        case 5:
+            result = xs[4] - ys[4];
+            if (result)
+                return result;
+        case 4:
+            return *(int32_t*)xs - *(int32_t*)ys;
+        case 3:
+            result = xs[2] - ys[2];
+            if (result)
+                return result;
+        case 2:
+            return *(int16_t*)xs - *(int16_t*)ys;
+        case 1:
+            return *xs - *ys;
+        case 0:
+            return 0;
+      }
+  }
+#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+#ifdef VARIABLE_HASH
+  /* hash 2 */
+  if (!x->hash2)
+    ((struct variable *)x)->hash2 = variable_hash_2i (x->name, x->length);
+  if (!y->hash2)
+    ((struct variable *)y)->hash2 = variable_hash_2i (y->name, y->length);
+  result = x->hash2 - y->hash2;
+  if (result)
+    return result;
+#endif
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+  return memcmp (x->name, y->name, x->length);
+#else
+  return_STRING_N_COMPARE (x->name, y->name, x->length);
+#endif
+}
+
+#ifndef	VARIABLE_BUCKETS
+# ifdef KMK /* Move to Makefile.kmk? */
+#  define VARIABLE_BUCKETS		16384
+# else  /*!KMK*/
+#define VARIABLE_BUCKETS		523
+# endif /*!KMK*/
+#endif
+#ifndef	PERFILE_VARIABLE_BUCKETS
+# ifdef KMK /* Move to Makefile.kmk? */
+#  define PERFILE_VARIABLE_BUCKETS	64
+# else
+#define	PERFILE_VARIABLE_BUCKETS	23
+# endif
+#endif
+#ifndef	SMALL_SCOPE_VARIABLE_BUCKETS
+# ifdef KMK /* Move to Makefile.kmk? */
+#  define SMALL_SCOPE_VARIABLE_BUCKETS  32
+# else
+#define	SMALL_SCOPE_VARIABLE_BUCKETS	13
+# endif
+#endif
+
+static struct variable_set global_variable_set;
+static struct variable_set_list global_setlist
+  = { 0, &global_variable_set };
+struct variable_set_list *current_variable_set_list = &global_setlist;
+
+
+/* Implement variables.  */
+
+void
+init_hash_global_variable_set (void)
+{
+  hash_init (&global_variable_set.table, VARIABLE_BUCKETS,
+	     variable_hash_1, variable_hash_2, variable_hash_cmp);
+}
+
+/* Define variable named NAME with value VALUE in SET.  VALUE is copied.
+   LENGTH is the length of NAME, which does not need to be null-terminated.
+   ORIGIN specifies the origin of the variable (makefile, command line
+   or environment).
+   If RECURSIVE is nonzero a flag is set in the variable saying
+   that it should be recursively re-expanded.  */
+
+#ifdef CONFIG_WITH_VALUE_LENGTH
+struct variable *
+define_variable_in_set (const char *name, unsigned int length,
+                        const char *value, unsigned int value_length, int duplicate_value,
+                        enum variable_origin origin, int recursive,
+                        struct variable_set *set, const struct floc *flocp)
+#else
+struct variable *
+define_variable_in_set (const char *name, unsigned int length,
+                        const char *value, enum variable_origin origin,
+                        int recursive, struct variable_set *set,
+                        const struct floc *flocp)
+#endif
+{
+  struct variable *v;
+  struct variable **var_slot;
+  struct variable var_key;
+
+  if (set == NULL)
+    set = &global_variable_set;
+
+  var_key.name = (char *) name;
+  var_key.length = length;
+#ifdef VARIABLE_HASH /* bird */
+  var_key.hash1 = variable_hash_1i (name, length);
+  var_key.hash2 = 0;
+#endif
+  var_slot = (struct variable **) hash_find_slot (&set->table, &var_key);
+
+  if (env_overrides && origin == o_env)
+    origin = o_env_override;
+
+  v = *var_slot;
+  if (! HASH_VACANT (v))
+    {
+      if (env_overrides && v->origin == o_env)
+	/* V came from in the environment.  Since it was defined
+	   before the switches were parsed, it wasn't affected by -e.  */
+	v->origin = o_env_override;
+
+      /* A variable of this name is already defined.
+	 If the old definition is from a stronger source
+	 than this one, don't redefine it.  */
+      if ((int) origin >= (int) v->origin)
+	{
+#ifdef CONFIG_WITH_VALUE_LENGTH
+          if (value_length == ~0U)
+            value_length = strlen (value);
+          else
+            assert (value_length == strlen (value));
+          if (!duplicate_value)
+            {
+              if (v->value != 0)
+                free (v->value);
+              v->value = (char *)value;
+              v->value_alloc_len = value_length + 1;
+            }
+          else
+            {
+              if ((unsigned int)v->value_alloc_len <= value_length)
+                {
+                  free (v->value);
+                  v->value_alloc_len = (value_length + 0x40) & ~0x3f;
+                  v->value = xmalloc (v->value_alloc_len);
+                }
+              memcpy (v->value, value, value_length + 1);
+            }
+          v->value_length = value_length;
+#else
+          if (v->value != 0)
+            free (v->value);
+	  v->value = xstrdup (value);
+#endif
+          if (flocp != 0)
+            v->fileinfo = *flocp;
+          else
+            v->fileinfo.filenm = 0;
+	  v->origin = origin;
+	  v->recursive = recursive;
+	}
+      return v;
+    }
+
+  /* Create a new variable definition and add it to the hash table.  */
+
+  v = xmalloc (sizeof (struct variable));
+  v->name = savestring (name, length);
+  v->length = length;
+#ifdef VARIABLE_HASH /* bird */
+  v->hash1 = variable_hash_1i (name, length);
+  v->hash2 = 0;
+#endif
+  hash_insert_at (&set->table, v, var_slot);
+#ifdef CONFIG_WITH_VALUE_LENGTH
+  if (value_length == ~0U)
+    value_length = strlen (value);
+  else
+    assert (value_length == strlen (value));
+  v->value_length = value_length;
+  if (!duplicate_value)
+    {
+      v->value_alloc_len = value_length + 1;
+      v->value = (char *)value;
+    }
+  else
+    {
+      v->value_alloc_len = (value_length + 32) & ~31;
+      v->value = xmalloc (v->value_alloc_len);
+      memcpy (v->value, value, value_length + 1);
+    }
+#else
+  v->value = xstrdup (value);
+#endif
+  if (flocp != 0)
+    v->fileinfo = *flocp;
+  else
+    v->fileinfo.filenm = 0;
+  v->origin = origin;
+  v->recursive = recursive;
+  v->special = 0;
+  v->expanding = 0;
+  v->exp_count = 0;
+  v->per_target = 0;
+  v->append = 0;
+  v->export = v_default;
+
+  v->exportable = 1;
+  if (*name != '_' && (*name < 'A' || *name > 'Z')
+      && (*name < 'a' || *name > 'z'))
+    v->exportable = 0;
+  else
+    {
+      for (++name; *name != '\0'; ++name)
+        if (*name != '_' && (*name < 'a' || *name > 'z')
+            && (*name < 'A' || *name > 'Z') && !ISDIGIT(*name))
+          break;
+
+      if (*name != '\0')
+        v->exportable = 0;
+    }
+
+  return v;
+}
+
+
+/* If the variable passed in is "special", handle its special nature.
+   Currently there are two such variables, both used for introspection:
+   .VARIABLES expands to a list of all the variables defined in this instance
+   of make.
+   .TARGETS expands to a list of all the targets defined in this
+   instance of make.
+   Returns the variable reference passed in.  */
+
+#define EXPANSION_INCREMENT(_l)  ((((_l) / 500) + 1) * 500)
+
+static struct variable *
+handle_special_var (struct variable *var)
+{
+  static unsigned long last_var_count = 0;
+
+
+  /* This one actually turns out to be very hard, due to the way the parser
+     records targets.  The way it works is that target information is collected
+     internally until make knows the target is completely specified.  It unitl
+     it sees that some new construct (a new target or variable) is defined that
+     it knows the previous one is done.  In short, this means that if you do
+     this:
+
+       all:
+
+       TARGS := $(.TARGETS)
+
+     then $(TARGS) won't contain "all", because it's not until after the
+     variable is created that the previous target is completed.
+
+     Changing this would be a major pain.  I think a less complex way to do it
+     would be to pre-define the target files as soon as the first line is
+     parsed, then come back and do the rest of the definition as now.  That
+     would allow $(.TARGETS) to be correct without a major change to the way
+     the parser works.
+
+  if (streq (var->name, ".TARGETS"))
+    var->value = build_target_list (var->value);
+  else
+  */
+
+  if (streq (var->name, ".VARIABLES")
+      && global_variable_set.table.ht_fill != last_var_count)
+    {
+      unsigned long max = EXPANSION_INCREMENT (strlen (var->value));
+      unsigned long len;
+      char *p;
+      struct variable **vp = (struct variable **) global_variable_set.table.ht_vec;
+      struct variable **end = &vp[global_variable_set.table.ht_size];
+
+      /* Make sure we have at least MAX bytes in the allocated buffer.  */
+      var->value = xrealloc (var->value, max);
+
+      /* Walk through the hash of variables, constructing a list of names.  */
+      p = var->value;
+      len = 0;
+      for (; vp < end; ++vp)
+        if (!HASH_VACANT (*vp))
+          {
+            struct variable *v = *vp;
+            int l = v->length;
+
+            len += l + 1;
+            if (len > max)
+              {
+                unsigned long off = p - var->value;
+
+                max += EXPANSION_INCREMENT (l + 1);
+                var->value = xrealloc (var->value, max);
+                p = &var->value[off];
+              }
+
+            memcpy (p, v->name, l);
+            p += l;
+            *(p++) = ' ';
+          }
+      *(p-1) = '\0';
+
+      /* Remember how many variables are in our current count.  Since we never
+         remove variables from the list, this is a reliable way to know whether
+         the list is up to date or needs to be recomputed.  */
+
+      last_var_count = global_variable_set.table.ht_fill;
+    }
+
+  return var;
+}
+
+
+
+/* Lookup a variable whose name is a string starting at NAME
+   and with LENGTH chars.  NAME need not be null-terminated.
+   Returns address of the `struct variable' containing all info
+   on the variable, or nil if no such variable is defined.  */
+
+struct variable *
+lookup_variable (const char *name, unsigned int length)
+{
+  const struct variable_set_list *setlist;
+  struct variable var_key;
+
+  var_key.name = (char *) name;
+  var_key.length = length;
+#ifdef VARIABLE_HASH /* bird */
+  var_key.hash1 = variable_hash_1i (name, length);
+  var_key.hash2 = 0;
+#endif
+
+  for (setlist = current_variable_set_list;
+       setlist != 0; setlist = setlist->next)
+    {
+#ifdef VARIABLE_HASH /* bird: speed */
+      struct hash_table *ht = &setlist->set->table;
+      unsigned int hash_1 = var_key.hash1;
+      struct variable *v;
+
+      ht->ht_lookups++;
+      for (;;)
+        {
+          hash_1 &= (ht->ht_size - 1);
+          v = (struct variable *)ht->ht_vec[hash_1];
+
+          if (v == 0)
+              break;
+          if ((void *)v != hash_deleted_item)
+            {
+              if (variable_hash_cmp(&var_key, v) == 0)
+                {
+# ifdef VARIABLE_HASH_STRICT /* bird */
+                  struct variable *v2 = (struct variable *) hash_find_item ((struct hash_table *) &setlist->set->table, &var_key);
+                  assert(v2 == v);
+# endif
+                  return v->special ? handle_special_var (v) : v;
+                }
+              ht->ht_collisions++;
+            }
+          if (!var_key.hash2)
+             var_key.hash2 = variable_hash_2i(name, length);
+          hash_1 += (var_key.hash2 | 1);
+        }
+
+#else /* !VARIABLE_HASH */
+      const struct variable_set *set = setlist->set;
+      struct variable *v;
+
+      v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
+      if (v)
+	return v->special ? handle_special_var (v) : v;
+#endif /* !VARIABLE_HASH */
+    }
+
+#ifdef VMS
+  /* since we don't read envp[] on startup, try to get the
+     variable via getenv() here.  */
+  {
+    char *vname = alloca (length + 1);
+    char *value;
+    strncpy (vname, name, length);
+    vname[length] = 0;
+    value = getenv (vname);
+    if (value != 0)
+      {
+        char *sptr;
+        int scnt;
+
+        sptr = value;
+        scnt = 0;
+
+        while ((sptr = strchr (sptr, '$')))
+          {
+            scnt++;
+            sptr++;
+          }
+
+        if (scnt > 0)
+          {
+            char *nvalue;
+            char *nptr;
+
+            nvalue = alloca (strlen (value) + scnt + 1);
+            sptr = value;
+            nptr = nvalue;
+
+            while (*sptr)
+              {
+                if (*sptr == '$')
+                  {
+                    *nptr++ = '$';
+                    *nptr++ = '$';
+                  }
+                else
+                  {
+                    *nptr++ = *sptr;
+                  }
+                sptr++;
+              }
+
+            *nptr = '\0';
+            return define_variable (vname, length, nvalue, o_env, 1);
+
+          }
+
+        return define_variable (vname, length, value, o_env, 1);
+      }
+  }
+#endif /* VMS */
+
+  return 0;
+}
+
+
+/* Lookup a variable whose name is a string starting at NAME
+   and with LENGTH chars in set SET.  NAME need not be null-terminated.
+   Returns address of the `struct variable' containing all info
+   on the variable, or nil if no such variable is defined.  */
+
+struct variable *
+lookup_variable_in_set (const char *name, unsigned int length,
+                        const struct variable_set *set)
+{
+  struct variable var_key;
+
+  var_key.name = (char *) name;
+  var_key.length = length;
+#ifdef VARIABLE_HASH /* bird */
+  var_key.hash1 = variable_hash_1i (name, length);
+  var_key.hash2 = 0;
+#endif
+
+  return (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
+}
+
+
+/* Initialize FILE's variable set list.  If FILE already has a variable set
+   list, the topmost variable set is left intact, but the the rest of the
+   chain is replaced with FILE->parent's setlist.  If FILE is a double-colon
+   rule, then we will use the "root" double-colon target's variable set as the
+   parent of FILE's variable set.
+
+   If we're READING a makefile, don't do the pattern variable search now,
+   since the pattern variable might not have been defined yet.  */
+
+void
+initialize_file_variables (struct file *file, int reading)
+{
+  struct variable_set_list *l = file->variables;
+
+  if (l == 0)
+    {
+      l = (struct variable_set_list *)
+	xmalloc (sizeof (struct variable_set_list));
+      l->set = xmalloc (sizeof (struct variable_set));
+      hash_init (&l->set->table, PERFILE_VARIABLE_BUCKETS,
+                 variable_hash_1, variable_hash_2, variable_hash_cmp);
+      file->variables = l;
+    }
+
+  /* If this is a double-colon, then our "parent" is the "root" target for
+     this double-colon rule.  Since that rule has the same name, parent,
+     etc. we can just use its variables as the "next" for ours.  */
+
+  if (file->double_colon && file->double_colon != file)
+    {
+      initialize_file_variables (file->double_colon, reading);
+      l->next = file->double_colon->variables;
+      return;
+    }
+
+  if (file->parent == 0)
+    l->next = &global_setlist;
+  else
+    {
+      initialize_file_variables (file->parent, reading);
+      l->next = file->parent->variables;
+    }
+
+  /* If we're not reading makefiles and we haven't looked yet, see if
+     we can find pattern variables for this target.  */
+
+  if (!reading && !file->pat_searched)
+    {
+      struct pattern_var *p;
+
+      p = lookup_pattern_var (0, file->name);
+      if (p != 0)
+        {
+          struct variable_set_list *global = current_variable_set_list;
+
+          /* We found at least one.  Set up a new variable set to accumulate
+             all the pattern variables that match this target.  */
+
+          file->pat_variables = create_new_variable_set ();
+          current_variable_set_list = file->pat_variables;
+
+          do
+            {
+              /* We found one, so insert it into the set.  */
+
+              struct variable *v;
+
+              if (p->variable.flavor == f_simple)
+                {
+                  v = define_variable_loc (
+                    p->variable.name, strlen (p->variable.name),
+                    p->variable.value, p->variable.origin,
+                    0, &p->variable.fileinfo);
+
+                  v->flavor = f_simple;
+                }
+              else
+                {
+                  v = do_variable_definition (
+                    &p->variable.fileinfo, p->variable.name,
+                    p->variable.value, p->variable.origin,
+                    p->variable.flavor, 1);
+                }
+
+              /* Also mark it as a per-target and copy export status. */
+              v->per_target = p->variable.per_target;
+              v->export = p->variable.export;
+            }
+          while ((p = lookup_pattern_var (p, file->name)) != 0);
+
+          current_variable_set_list = global;
+        }
+      file->pat_searched = 1;
+    }
+
+  /* If we have a pattern variable match, set it up.  */
+
+  if (file->pat_variables != 0)
+    {
+      file->pat_variables->next = l->next;
+      l->next = file->pat_variables;
+    }
+}
+
+
+/* Pop the top set off the current variable set list,
+   and free all its storage.  */
+
+struct variable_set_list *
+create_new_variable_set (void)
+{
+  register struct variable_set_list *setlist;
+  register struct variable_set *set;
+
+  set = xmalloc (sizeof (struct variable_set));
+  hash_init (&set->table, SMALL_SCOPE_VARIABLE_BUCKETS,
+	     variable_hash_1, variable_hash_2, variable_hash_cmp);
+
+  setlist = (struct variable_set_list *)
+    xmalloc (sizeof (struct variable_set_list));
+  setlist->set = set;
+  setlist->next = current_variable_set_list;
+
+  return setlist;
+}
+
+static void
+free_variable_name_and_value (const void *item)
+{
+  struct variable *v = (struct variable *) item;
+  free (v->name);
+  free (v->value);
+}
+
+void
+free_variable_set (struct variable_set_list *list)
+{
+  hash_map (&list->set->table, free_variable_name_and_value);
+  hash_free (&list->set->table, 1);
+  free (list->set);
+  free (list);
+}
+
+/* Create a new variable set and push it on the current setlist.
+   If we're pushing a global scope (that is, the current scope is the global
+   scope) then we need to "push" it the other way: file variable sets point
+   directly to the global_setlist so we need to replace that with the new one.
+ */
+
+struct variable_set_list *
+push_new_variable_scope (void)
+{
+  current_variable_set_list = create_new_variable_set();
+  if (current_variable_set_list->next == &global_setlist)
+    {
+      /* It was the global, so instead of new -> &global we want to replace
+         &global with the new one and have &global -> new, with current still
+         pointing to &global  */
+      struct variable_set *set = current_variable_set_list->set;
+      current_variable_set_list->set = global_setlist.set;
+      global_setlist.set = set;
+      current_variable_set_list->next = global_setlist.next;
+      global_setlist.next = current_variable_set_list;
+      current_variable_set_list = &global_setlist;
+    }
+  return (current_variable_set_list);
+}
+
+void
+pop_variable_scope (void)
+{
+  struct variable_set_list *setlist;
+  struct variable_set *set;
+
+  /* Can't call this if there's no scope to pop!  */
+  assert(current_variable_set_list->next != NULL);
+
+  if (current_variable_set_list != &global_setlist)
+    {
+      /* We're not pointing to the global setlist, so pop this one.  */
+      setlist = current_variable_set_list;
+      set = setlist->set;
+      current_variable_set_list = setlist->next;
+    }
+  else
+    {
+      /* This set is the one in the global_setlist, but there is another global
+         set beyond that.  We want to copy that set to global_setlist, then
+         delete what used to be in global_setlist.  */
+      setlist = global_setlist.next;
+      set = global_setlist.set;
+      global_setlist.set = setlist->set;
+      global_setlist.next = setlist->next;
+    }
+
+  /* Free the one we no longer need.  */
+  free (setlist);
+  hash_map (&set->table, free_variable_name_and_value);
+  hash_free (&set->table, 1);
+  free (set);
+}
+
+
+/* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET.  */
+
+static void
+merge_variable_sets (struct variable_set *to_set,
+                     struct variable_set *from_set)
+{
+  struct variable **from_var_slot = (struct variable **) from_set->table.ht_vec;
+  struct variable **from_var_end = from_var_slot + from_set->table.ht_size;
+
+  for ( ; from_var_slot < from_var_end; from_var_slot++)
+    if (! HASH_VACANT (*from_var_slot))
+      {
+	struct variable *from_var = *from_var_slot;
+	struct variable **to_var_slot
+	  = (struct variable **) hash_find_slot (&to_set->table, *from_var_slot);
+	if (HASH_VACANT (*to_var_slot))
+	  hash_insert_at (&to_set->table, from_var, to_var_slot);
+	else
+	  {
+	    /* GKM FIXME: delete in from_set->table */
+	    free (from_var->value);
+	    free (from_var);
+	  }
+      }
+}
+
+/* Merge SETLIST1 into SETLIST0, freeing unused storage in SETLIST1.  */
+
+void
+merge_variable_set_lists (struct variable_set_list **setlist0,
+                          struct variable_set_list *setlist1)
+{
+  struct variable_set_list *to = *setlist0;
+  struct variable_set_list *last0 = 0;
+
+  /* If there's nothing to merge, stop now.  */
+  if (!setlist1)
+    return;
+
+  /* This loop relies on the fact that all setlists terminate with the global
+     setlist (before NULL).  If that's not true, arguably we SHOULD die.  */
+  if (to)
+    while (setlist1 != &global_setlist && to != &global_setlist)
+      {
+        struct variable_set_list *from = setlist1;
+        setlist1 = setlist1->next;
+
+        merge_variable_sets (to->set, from->set);
+
+        last0 = to;
+        to = to->next;
+      }
+
+  if (setlist1 != &global_setlist)
+    {
+      if (last0 == 0)
+	*setlist0 = setlist1;
+      else
+	last0->next = setlist1;
+    }
+}
+
+
+/* Define the automatic variables, and record the addresses
+   of their structures so we can change their values quickly.  */
+
+void
+define_automatic_variables (void)
+{
+#if defined(WINDOWS32) || defined(__EMX__)
+  extern char* default_shell;
+#else
+  extern char default_shell[];
+#endif
+  register struct variable *v;
+#ifndef KMK
+  char buf[200];
+#else
+  char buf[1024];
+  const char *val;
+  struct variable *envvar1;
+  struct variable *envvar2;
+#endif
+
+  sprintf (buf, "%u", makelevel);
+  (void) define_variable (MAKELEVEL_NAME, MAKELEVEL_LENGTH, buf, o_env, 0);
+
+  sprintf (buf, "%s%s%s",
+	   version_string,
+	   (remote_description == 0 || remote_description[0] == '\0')
+	   ? "" : "-",
+	   (remote_description == 0 || remote_description[0] == '\0')
+	   ? "" : remote_description);
+#ifndef KMK
+  (void) define_variable ("MAKE_VERSION", 12, buf, o_default, 0);
+#else /* KMK */
+
+  /* Define KMK_VERSION to indicate kMk. */
+  (void) define_variable ("KMK_VERSION", 11, buf, o_default, 0);
+
+  /* Define KBUILD_VERSION* */
+  sprintf (buf, "%d", KBUILD_VERSION_MAJOR);
+  define_variable ("KBUILD_VERSION_MAJOR", sizeof ("KBUILD_VERSION_MAJOR") - 1,
+                   buf, o_default, 0);
+  sprintf (buf, "%d", KBUILD_VERSION_MINOR);
+  define_variable ("KBUILD_VERSION_MINOR", sizeof("KBUILD_VERSION_MINOR") - 1,
+                   buf, o_default, 0);
+  sprintf (buf, "%d", KBUILD_VERSION_PATCH);
+  define_variable ("KBUILD_VERSION_PATCH", sizeof ("KBUILD_VERSION_PATCH") - 1,
+                   buf, o_default, 0);
+  sprintf (buf, "%d", KBUILD_SVN_REV);
+  define_variable ("KBUILD_KMK_REVISION", sizeof ("KBUILD_KMK_REVISION") - 1,
+                   buf, o_default, 0);
+
+  sprintf (buf, "%d.%d.%d-r%d", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR,
+           KBUILD_VERSION_PATCH, KBUILD_SVN_REV);
+  define_variable ("KBUILD_VERSION", sizeof ("KBUILD_VERSION") - 1,
+                   buf, o_default, 0);
+
+  /* The host defaults. The BUILD_* stuff will be replaced by KBUILD_* soon. */
+  envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST"));
+  envvar2 = lookup_variable (STRING_SIZE_TUPLE ("BUILD_PLATFORM"));
+  val = envvar1 ? envvar1->value : envvar2 ? envvar2->value : KBUILD_HOST;
+  if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value))
+    error (NULL, _("KBUILD_HOST and BUILD_PLATFORM differs, using KBUILD_HOST=%s."), val);
+  if (!envvar1)
+    define_variable ("KBUILD_HOST", sizeof ("KBUILD_HOST") - 1,
+                     val, o_default, 0);
+  if (!envvar2)
+    define_variable ("BUILD_PLATFORM", sizeof ("BUILD_PLATFORM") - 1,
+                     val, o_default, 0);
+
+  envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST_ARCH"));
+  envvar2 = lookup_variable (STRING_SIZE_TUPLE ("BUILD_PLATFORM_ARCH"));
+  val = envvar1 ? envvar1->value : envvar2 ? envvar2->value : KBUILD_HOST_ARCH;
+  if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value))
+    error (NULL, _("KBUILD_HOST_ARCH and BUILD_PLATFORM_ARCH differs, using KBUILD_HOST_ARCH=%s."), val);
+  if (!envvar1)
+    define_variable ("KBUILD_HOST_ARCH", sizeof ("KBUILD_HOST_ARCH") - 1,
+                     val, o_default, 0);
+  if (!envvar2)
+    define_variable ("BUILD_PLATFORM_ARCH", sizeof ("BUILD_PLATFORM_ARCH") - 1,
+                     val, o_default, 0);
+
+  envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST_CPU"));
+  envvar2 = lookup_variable (STRING_SIZE_TUPLE ("BUILD_PLATFORM_CPU"));
+  val = envvar1 ? envvar1->value : envvar2 ? envvar2->value : KBUILD_HOST_CPU;
+  if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value))
+    error (NULL, _("KBUILD_HOST_CPU and BUILD_PLATFORM_CPU differs, using KBUILD_HOST_CPU=%s."), val);
+  if (!envvar1)
+    define_variable ("KBUILD_HOST_CPU", sizeof ("KBUILD_HOST_CPU") - 1,
+                     val, o_default, 0);
+  if (!envvar2)
+    define_variable ("BUILD_PLATFORM_CPU", sizeof ("BUILD_PLATFORM_CPU") - 1,
+                     val, o_default, 0);
+
+  /* The kBuild locations. */
+  define_variable ("KBUILD_PATH", sizeof ("KBUILD_PATH") - 1,
+                   get_kbuild_path (), o_default, 0);
+  define_variable ("KBUILD_BIN_PATH", sizeof ("KBUILD_BIN_PATH") - 1,
+                   get_kbuild_bin_path (), o_default, 0);
+
+  define_variable ("PATH_KBUILD", sizeof ("PATH_KBUILD") - 1,
+                   get_kbuild_path (), o_default, 0);
+  define_variable ("PATH_KBUILD_BIN", sizeof ("PATH_KBUILD_BIN") - 1,
+                   get_kbuild_bin_path (), o_default, 0);
+
+  /* Define KMK_FEATURES to indicate various working KMK features. */
+# if defined (CONFIG_WITH_RSORT) \
+  && defined (CONFIG_WITH_ABSPATHEX) \
+  && defined (CONFIG_WITH_TOUPPER_TOLOWER) \
+  && defined (CONFIG_WITH_DEFINED) \
+  && defined (CONFIG_WITH_VALUE_LENGTH) && defined (CONFIG_WITH_COMPARE) \
+  && defined (CONFIG_WITH_STACK) \
+  && defined (CONFIG_WITH_MATH) \
+  && defined (CONFIG_WITH_XARGS) \
+  && defined (CONFIG_WITH_EXPLICIT_MULTITARGET) \
+  && defined (CONFIG_WITH_PREPEND_ASSIGNMENT) \
+  && defined (CONFIG_WITH_SET_CONDITIONALS) \
+  && defined (CONFIG_WITH_DATE) \
+  && defined (CONFIG_WITH_FILE_SIZE) \
+  && defined (CONFIG_WITH_WHICH) \
+  && defined (CONFIG_WITH_EVALPLUS) \
+  && defined (CONFIG_WITH_MAKE_STATS) \
+  && defined (CONFIG_WITH_COMMANDS_FUNC) \
+  && defined (KMK_HELPERS)
+  (void) define_variable ("KMK_FEATURES", 12,
+                          "append-dash-n abspath"
+                          " rsort"
+                          " abspathex"
+                          " toupper tolower"
+                          " defined"
+                          " comp-vars comp-cmds comp-cmds-ex"
+                          " stack"
+                          " math-int"
+                          " xargs"
+                          " explicit-multitarget"
+                          " prepend-assignment"
+                          " set-conditionals"
+                          " date"
+                          " file-size"
+                          " expr if-expr"
+                          " which"
+                          " evalctx evalval evalvalctx evalcall evalcall2"
+                          " make-stats"
+                          " commands"
+                          " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one "
+                          , o_default, 0);
+# else /* MSC can't deal with strings mixed with #if/#endif, thus the slow way. */
+#  error "All features should be enabled by default!"
+  strcpy (buf, "append-dash-n abspath");
+#  if defined (CONFIG_WITH_RSORT)
+  strcat (buf, " rsort");
+#  endif
+#  if defined (CONFIG_WITH_ABSPATHEX)
+  strcat (buf, " abspathex");
+#  endif
+#  if defined (CONFIG_WITH_TOUPPER_TOLOWER)
+  strcat (buf, " toupper tolower");
+#  endif
+#  if defined (CONFIG_WITH_DEFINED)
+  strcat (buf, " defined");
+#  endif
+#  if defined (CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE)
+  strcat (buf, " comp-vars comp-cmds comp-cmds-ex");
+#  endif
+#  if defined (CONFIG_WITH_STACK)
+  strcat (buf, " stack");
+#  endif
+#  if defined (CONFIG_WITH_MATH)
+  strcat (buf, " math-int");
+#  endif
+#  if defined (CONFIG_WITH_XARGS)
+  strcat (buf, " xargs");
+#  endif
+#  if defined (CONFIG_WITH_EXPLICIT_MULTITARGET)
+  strcat (buf, " explicit-multitarget");
+#  endif
+#  if defined (CONFIG_WITH_PREPEND_ASSIGNMENT)
+  strcat (buf, " prepend-assignment");
+#  endif
+#  if defined (CONFIG_WITH_SET_CONDITIONALS)
+  strcat (buf, " set-conditionals");
+#  endif
+#  if defined (CONFIG_WITH_DATE)
+  strcat (buf, " date");
+#  endif
+#  if defined (CONFIG_WITH_FILE_SIZE)
+  strcat (buf, " file-size");
+#  endif
+#  if defined (CONFIG_WITH_IF_CONDITIONALS)
+  strcat (buf, " expr if-expr");
+#  endif
+#  if defined (CONFIG_WITH_WHICH)
+  strcat (buf, " which");
+#  endif
+#  if defined (CONFIG_WITH_EVALPLUS)
+  strcat (buf, " evalctx evalval evalvalctx evalcall evalcall2");
+#  endif
+#  if defined (CONFIG_WITH_MAKE_STATS)
+  strcat (buf, " make-stats");
+#  endif
+#  if defined (CONFIG_WITH_COMMANDS_FUNC)
+  strcat (buf, " commands");
+#  endif
+#  if defined (KMK_HELPERS)
+  strcat (buf, " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one");
+#  endif
+  (void) define_variable ("KMK_FEATURES", 12, buf, o_default, 0);
+# endif
+
+#endif /* KMK */
+
+#ifdef CONFIG_WITH_KMK_BUILTIN
+  /* The supported kMk Builtin commands. */
+  (void) define_variable ("KMK_BUILTIN", 11, "append cat chmod cp cmp echo expr install kDepIDB ln md5sum mkdir mv printf rm rmdir test", o_default, 0);
+#endif
+
+#ifdef  __MSDOS__
+  /* Allow to specify a special shell just for Make,
+     and use $COMSPEC as the default $SHELL when appropriate.  */
+  {
+    static char shell_str[] = "SHELL";
+    const int shlen = sizeof (shell_str) - 1;
+    struct variable *mshp = lookup_variable ("MAKESHELL", 9);
+    struct variable *comp = lookup_variable ("COMSPEC", 7);
+
+    /* Make $MAKESHELL override $SHELL even if -e is in effect.  */
+    if (mshp)
+      (void) define_variable (shell_str, shlen,
+			      mshp->value, o_env_override, 0);
+    else if (comp)
+      {
+	/* $COMSPEC shouldn't override $SHELL.  */
+	struct variable *shp = lookup_variable (shell_str, shlen);
+
+	if (!shp)
+	  (void) define_variable (shell_str, shlen, comp->value, o_env, 0);
+      }
+  }
+#elif defined(__EMX__)
+  {
+    static char shell_str[] = "SHELL";
+    const int shlen = sizeof (shell_str) - 1;
+    struct variable *shell = lookup_variable (shell_str, shlen);
+    struct variable *replace = lookup_variable ("MAKESHELL", 9);
+
+    /* if $MAKESHELL is defined in the environment assume o_env_override */
+    if (replace && *replace->value && replace->origin == o_env)
+      replace->origin = o_env_override;
+
+    /* if $MAKESHELL is not defined use $SHELL but only if the variable
+       did not come from the environment */
+    if (!replace || !*replace->value)
+      if (shell && *shell->value && (shell->origin == o_env
+	  || shell->origin == o_env_override))
+	{
+	  /* overwrite whatever we got from the environment */
+	  free(shell->value);
+	  shell->value = xstrdup (default_shell);
+	  shell->origin = o_default;
+	}
+
+    /* Some people do not like cmd to be used as the default
+       if $SHELL is not defined in the Makefile.
+       With -DNO_CMD_DEFAULT you can turn off this behaviour */
+# ifndef NO_CMD_DEFAULT
+    /* otherwise use $COMSPEC */
+    if (!replace || !*replace->value)
+      replace = lookup_variable ("COMSPEC", 7);
+
+    /* otherwise use $OS2_SHELL */
+    if (!replace || !*replace->value)
+      replace = lookup_variable ("OS2_SHELL", 9);
+# else
+#   warning NO_CMD_DEFAULT: GNU make will not use CMD.EXE as default shell
+# endif
+
+    if (replace && *replace->value)
+      /* overwrite $SHELL */
+      (void) define_variable (shell_str, shlen, replace->value,
+			      replace->origin, 0);
+    else
+      /* provide a definition if there is none */
+      (void) define_variable (shell_str, shlen, default_shell,
+			      o_default, 0);
+  }
+
+#endif
+
+  /* This won't override any definition, but it will provide one if there
+     isn't one there.  */
+  v = define_variable ("SHELL", 5, default_shell, o_default, 0);
+
+  /* On MSDOS we do use SHELL from environment, since it isn't a standard
+     environment variable on MSDOS, so whoever sets it, does that on purpose.
+     On OS/2 we do not use SHELL from environment but we have already handled
+     that problem above. */
+#if !defined(__MSDOS__) && !defined(__EMX__)
+  /* Don't let SHELL come from the environment.  */
+  if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override)
+    {
+      free (v->value);
+      v->origin = o_file;
+      v->value = xstrdup (default_shell);
+#ifdef CONFIG_WITH_VALUE_LENGTH
+      v->value_length = strlen (v->value);
+      v->value_alloc_len = v->value_length + 1;
+#endif
+    }
+#endif
+
+  /* Make sure MAKEFILES gets exported if it is set.  */
+  v = define_variable ("MAKEFILES", 9, "", o_default, 0);
+  v->export = v_ifset;
+
+  /* Define the magic D and F variables in terms of
+     the automatic variables they are variations of.  */
+
+#ifdef VMS
+  define_variable ("@D", 2, "$(dir $@)", o_automatic, 1);
+  define_variable ("%D", 2, "$(dir $%)", o_automatic, 1);
+  define_variable ("*D", 2, "$(dir $*)", o_automatic, 1);
+  define_variable ("<D", 2, "$(dir $<)", o_automatic, 1);
+  define_variable ("?D", 2, "$(dir $?)", o_automatic, 1);
+  define_variable ("^D", 2, "$(dir $^)", o_automatic, 1);
+  define_variable ("+D", 2, "$(dir $+)", o_automatic, 1);
+#else
+  define_variable ("@D", 2, "$(patsubst %/,%,$(dir $@))", o_automatic, 1);
+  define_variable ("%D", 2, "$(patsubst %/,%,$(dir $%))", o_automatic, 1);
+  define_variable ("*D", 2, "$(patsubst %/,%,$(dir $*))", o_automatic, 1);
+  define_variable ("<D", 2, "$(patsubst %/,%,$(dir $<))", o_automatic, 1);
+  define_variable ("?D", 2, "$(patsubst %/,%,$(dir $?))", o_automatic, 1);
+  define_variable ("^D", 2, "$(patsubst %/,%,$(dir $^))", o_automatic, 1);
+  define_variable ("+D", 2, "$(patsubst %/,%,$(dir $+))", o_automatic, 1);
+#endif
+  define_variable ("@F", 2, "$(notdir $@)", o_automatic, 1);
+  define_variable ("%F", 2, "$(notdir $%)", o_automatic, 1);
+  define_variable ("*F", 2, "$(notdir $*)", o_automatic, 1);
+  define_variable ("<F", 2, "$(notdir $<)", o_automatic, 1);
+  define_variable ("?F", 2, "$(notdir $?)", o_automatic, 1);
+  define_variable ("^F", 2, "$(notdir $^)", o_automatic, 1);
+  define_variable ("+F", 2, "$(notdir $+)", o_automatic, 1);
+}
+
+
+int export_all_variables;
+
+/* Create a new environment for FILE's commands.
+   If FILE is nil, this is for the `shell' function.
+   The child's MAKELEVEL variable is incremented.  */
+
+char **
+target_environment (struct file *file)
+{
+  struct variable_set_list *set_list;
+  register struct variable_set_list *s;
+  struct hash_table table;
+  struct variable **v_slot;
+  struct variable **v_end;
+  struct variable makelevel_key;
+  char **result_0;
+  char **result;
+
+  if (file == 0)
+    set_list = current_variable_set_list;
+  else
+    set_list = file->variables;
+
+  hash_init (&table, VARIABLE_BUCKETS,
+	     variable_hash_1, variable_hash_2, variable_hash_cmp);
+
+  /* Run through all the variable sets in the list,
+     accumulating variables in TABLE.  */
+  for (s = set_list; s != 0; s = s->next)
+    {
+      struct variable_set *set = s->set;
+      v_slot = (struct variable **) set->table.ht_vec;
+      v_end = v_slot + set->table.ht_size;
+      for ( ; v_slot < v_end; v_slot++)
+	if (! HASH_VACANT (*v_slot))
+	  {
+	    struct variable **new_slot;
+	    struct variable *v = *v_slot;
+
+	    /* If this is a per-target variable and it hasn't been touched
+	       already then look up the global version and take its export
+	       value.  */
+	    if (v->per_target && v->export == v_default)
+	      {
+		struct variable *gv;
+
+		gv = lookup_variable_in_set (v->name, strlen(v->name),
+                                             &global_variable_set);
+		if (gv)
+		  v->export = gv->export;
+	      }
+
+	    switch (v->export)
+	      {
+	      case v_default:
+		if (v->origin == o_default || v->origin == o_automatic)
+		  /* Only export default variables by explicit request.  */
+		  continue;
+
+                /* The variable doesn't have a name that can be exported.  */
+                if (! v->exportable)
+                  continue;
+
+		if (! export_all_variables
+		    && v->origin != o_command
+		    && v->origin != o_env && v->origin != o_env_override)
+		  continue;
+		break;
+
+	      case v_export:
+		break;
+
+	      case v_noexport:
+                /* If this is the SHELL variable and it's not exported, then
+                   add the value from our original environment.  */
+                if (streq (v->name, "SHELL"))
+                  {
+                    extern struct variable shell_var;
+                    v = &shell_var;
+                    break;
+                  }
+                continue;
+
+	      case v_ifset:
+		if (v->origin == o_default)
+		  continue;
+		break;
+	      }
+
+	    new_slot = (struct variable **) hash_find_slot (&table, v);
+	    if (HASH_VACANT (*new_slot))
+	      hash_insert_at (&table, v, new_slot);
+	  }
+    }
+
+  makelevel_key.name = MAKELEVEL_NAME;
+  makelevel_key.length = MAKELEVEL_LENGTH;
+#ifdef VARIABLE_HASH /* bird */
+  makelevel_key.hash1 = variable_hash_1i (MAKELEVEL_NAME, MAKELEVEL_LENGTH);
+  makelevel_key.hash2 = 0;
+#endif
+  hash_delete (&table, &makelevel_key);
+
+  result = result_0 = xmalloc ((table.ht_fill + 2) * sizeof (char *));
+
+  v_slot = (struct variable **) table.ht_vec;
+  v_end = v_slot + table.ht_size;
+  for ( ; v_slot < v_end; v_slot++)
+    if (! HASH_VACANT (*v_slot))
+      {
+	struct variable *v = *v_slot;
+
+	/* If V is recursively expanded and didn't come from the environment,
+	   expand its value.  If it came from the environment, it should
+	   go back into the environment unchanged.  */
+	if (v->recursive
+	    && v->origin != o_env && v->origin != o_env_override)
+	  {
+	    char *value = recursively_expand_for_file (v, file);
+#ifdef WINDOWS32
+	    if (strcmp(v->name, "Path") == 0 ||
+		strcmp(v->name, "PATH") == 0)
+	      convert_Path_to_windows32(value, ';');
+#endif
+	    *result++ = xstrdup (concat (v->name, "=", value));
+	    free (value);
+	  }
+	else
+	  {
+#ifdef WINDOWS32
+            if (strcmp(v->name, "Path") == 0 ||
+                strcmp(v->name, "PATH") == 0)
+              convert_Path_to_windows32(v->value, ';');
+#endif
+	    *result++ = xstrdup (concat (v->name, "=", v->value));
+	  }
+      }
+
+  *result = xmalloc (100);
+  sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1);
+  *++result = 0;
+
+  hash_free (&table, 0);
+
+  return result_0;
+}
+
+
+#ifdef CONFIG_WITH_VALUE_LENGTH
+/* Worker function for do_variable_definition_append() and
+   append_expanded_string_to_variable().
+   The APPEND argument indicates whether it's an append or prepend operation. */
+void append_string_to_variable (struct variable *v, const char *value, unsigned int value_len, int append)
+{
+  /* The previous definition of the variable was recursive.
+     The new value is the unexpanded old and new values. */
+  unsigned int new_value_len = value_len + (v->value_length != 0 ? 1 + v->value_length : 0);
+  int done_1st_prepend_copy = 0;
+
+  /* Drop empty strings. Use $(NO_SUCH_VARIABLE) if a space is wanted. */
+  if (!value_len)
+      return;
+
+  /* adjust the size. */
+  if ((unsigned)v->value_alloc_len <= new_value_len + 1)
+    {
+      v->value_alloc_len *= 2;
+      if (v->value_alloc_len < new_value_len + 1)
+          v->value_alloc_len = (new_value_len + 1 + value_len + 0x7f) + ~0x7fU;
+      if (append || !v->value_length)
+        v->value = xrealloc (v->value, v->value_alloc_len);
+      else
+        {
+          /* avoid the extra memcpy the xrealloc may have to do */
+          char *new_buf = xmalloc (v->value_alloc_len);
+          memcpy (&new_buf[value_len + 1], v->value, v->value_length + 1);
+          done_1st_prepend_copy = 1;
+          free (v->value);
+          v->value = new_buf;
+        }
+    }
+
+  /* insert the new bits */
+  if (v->value_length != 0)
+    {
+      if (append)
+        {
+          v->value[v->value_length] = ' ';
+          memcpy (&v->value[v->value_length + 1], value, value_len + 1);
+        }
+      else
+        {
+          if (!done_1st_prepend_copy)
+            memmove (&v->value[value_len + 1], v->value, v->value_length + 1);
+          v->value[value_len] = ' ';
+          memcpy (v->value, value, value_len);
+        }
+    }
+  else
+    memcpy (v->value, value, value_len + 1);
+  v->value_length = new_value_len;
+}
+
+static struct variable *
+do_variable_definition_append (const struct floc *flocp, struct variable *v, const char *value,
+                               enum variable_origin origin, int append)
+{
+  if (env_overrides && origin == o_env)
+    origin = o_env_override;
+
+  if (env_overrides && v->origin == o_env)
+    /* V came from in the environment.  Since it was defined
+       before the switches were parsed, it wasn't affected by -e.  */
+    v->origin = o_env_override;
+
+  /* A variable of this name is already defined.
+     If the old definition is from a stronger source
+     than this one, don't redefine it.  */
+  if ((int) origin < (int) v->origin)
+    return v;
+  v->origin = origin;
+
+  /* location */
+  if (flocp != 0)
+    v->fileinfo = *flocp;
+
+  /* The juicy bits, append the specified value to the variable
+     This is a heavily exercised code path in kBuild. */
+  if (v->recursive)
+    append_string_to_variable (v, value, strlen (value), append);
+  else
+    /* The previous definition of the variable was simple.
+       The new value comes from the old value, which was expanded
+       when it was set; and from the expanded new value. */
+    append_expanded_string_to_variable (v, value, append);
+
+  /* update the variable */
+  return v;
+}
+#endif /* CONFIG_WITH_VALUE_LENGTH */
+
+
+/* Given a variable, a value, and a flavor, define the variable.
+   See the try_variable_definition() function for details on the parameters. */
+
+struct variable *
+do_variable_definition (const struct floc *flocp, const char *varname,
+                        const char *value, enum variable_origin origin,
+                        enum variable_flavor flavor, int target_var)
+{
+  const char *p;
+  char *alloc_value = NULL;
+  struct variable *v;
+  int append = 0;
+  int conditional = 0;
+  const size_t varname_len = strlen (varname); /* bird */
+#ifdef CONFIG_WITH_VALUE_LENGTH
+  unsigned int value_len = ~0U;
+#endif
+
+  /* Calculate the variable's new value in VALUE.  */
+
+  switch (flavor)
+    {
+    default:
+    case f_bogus:
+      /* Should not be possible.  */
+      abort ();
+    case f_simple:
+      /* A simple variable definition "var := value".  Expand the value.
+         We have to allocate memory since otherwise it'll clobber the
+	 variable buffer, and we may still need that if we're looking at a
+         target-specific variable.  */
+      p = alloc_value = allocated_variable_expand (value);
+      break;
+    case f_conditional:
+      /* A conditional variable definition "var ?= value".
+         The value is set IFF the variable is not defined yet. */
+      v = lookup_variable (varname, varname_len);
+      if (v)
+        return v;
+
+      conditional = 1;
+      flavor = f_recursive;
+      /* FALLTHROUGH */
+    case f_recursive:
+      /* A recursive variable definition "var = value".
+	 The value is used verbatim.  */
+      p = value;
+      break;
+#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+    case f_append:
+    case f_prepend:
+      {
+        const enum variable_flavor org_flavor = flavor;
+#else
+    case f_append:
+      {
+#endif
+
+#ifdef CONFIG_WITH_LOCAL_VARIABLES
+          /* If we have += but we're in a target or local variable context,
+             we want to append only with other variables in the context of
+             this target.  */
+        if (target_var || origin == o_local)
+#else
+        /* If we have += but we're in a target variable context, we want to
+           append only with other variables in the context of this target.  */
+        if (target_var)
+#endif
+          {
+            append = 1;
+            v = lookup_variable_in_set (varname, varname_len,
+                                        current_variable_set_list->set);
+
+            /* Don't append from the global set if a previous non-appending
+               target-specific variable definition exists. */
+            if (v && !v->append)
+              append = 0;
+          }
+        else
+          v = lookup_variable (varname, varname_len);
+
+        if (v == 0)
+          {
+            /* There was no old value.
+               This becomes a normal recursive definition.  */
+            p = value;
+            flavor = f_recursive;
+          }
+        else
+          {
+#ifdef CONFIG_WITH_VALUE_LENGTH
+            v->append = append;
+# ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+            return do_variable_definition_append (flocp, v, value, origin, org_flavor == f_append);
+# else
+            return do_variable_definition_append (flocp, v, value, origin, 1);
+# endif
+#else /* !CONFIG_WITH_VALUE_LENGTH */
+
+            /* Paste the old and new values together in VALUE.  */
+
+            unsigned int oldlen, vallen;
+            const char *val;
+            char *tp;
+
+            val = value;
+            if (v->recursive)
+              /* The previous definition of the variable was recursive.
+                 The new value is the unexpanded old and new values. */
+              flavor = f_recursive;
+            else
+              /* The previous definition of the variable was simple.
+                 The new value comes from the old value, which was expanded
+                 when it was set; and from the expanded new value.  Allocate
+                 memory for the expansion as we may still need the rest of the
+                 buffer if we're looking at a target-specific variable.  */
+              val = alloc_value = allocated_variable_expand (val);
+
+            oldlen = strlen (v->value);
+            vallen = strlen (val);
+            tp = alloca (oldlen + 1 + vallen + 1);
+# ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+            if (org_flavor == f_prepend)
+              {
+                memcpy (tp, val, vallen);
+                tp[oldlen] = ' ';
+                memcpy (&tp[oldlen + 1], v->value, oldlen + 1);
+              }
+            else
+# endif /* CONFIG_WITH_PREPEND_ASSIGNMENT */
+              {
+                memcpy (tp, v->value, oldlen);
+                tp[oldlen] = ' ';
+                memcpy (&tp[oldlen + 1], val, vallen + 1);
+              }
+            p = tp;
+#endif /* !CONFIG_WITH_VALUE_LENGTH */
+          }
+      }
+    }
+
+#ifdef __MSDOS__
+  /* Many Unix Makefiles include a line saying "SHELL=/bin/sh", but
+     non-Unix systems don't conform to this default configuration (in
+     fact, most of them don't even have `/bin').  On the other hand,
+     $SHELL in the environment, if set, points to the real pathname of
+     the shell.
+     Therefore, we generally won't let lines like "SHELL=/bin/sh" from
+     the Makefile override $SHELL from the environment.  But first, we
+     look for the basename of the shell in the directory where SHELL=
+     points, and along the $PATH; if it is found in any of these places,
+     we define $SHELL to be the actual pathname of the shell.  Thus, if
+     you have bash.exe installed as d:/unix/bash.exe, and d:/unix is on
+     your $PATH, then SHELL=/usr/local/bin/bash will have the effect of
+     defining SHELL to be "d:/unix/bash.exe".  */
+  if ((origin == o_file || origin == o_override)
+      && strcmp (varname, "SHELL") == 0)
+    {
+      PATH_VAR (shellpath);
+      extern char * __dosexec_find_on_path (const char *, char *[], char *);
+
+      /* See if we can find "/bin/sh.exe", "/bin/sh.com", etc.  */
+      if (__dosexec_find_on_path (p, NULL, shellpath))
+	{
+	  char *tp;
+
+	  for (tp = shellpath; *tp; tp++)
+            if (*tp == '\\')
+              *tp = '/';
+
+	  v = define_variable_loc (varname, varname_len,
+                                   shellpath, origin, flavor == f_recursive,
+                                   flocp);
+	}
+      else
+	{
+	  const char *shellbase, *bslash;
+	  struct variable *pathv = lookup_variable ("PATH", 4);
+	  char *path_string;
+	  char *fake_env[2];
+	  size_t pathlen = 0;
+
+	  shellbase = strrchr (p, '/');
+	  bslash = strrchr (p, '\\');
+	  if (!shellbase || bslash > shellbase)
+	    shellbase = bslash;
+	  if (!shellbase && p[1] == ':')
+	    shellbase = p + 1;
+	  if (shellbase)
+	    shellbase++;
+	  else
+	    shellbase = p;
+
+	  /* Search for the basename of the shell (with standard
+	     executable extensions) along the $PATH.  */
+	  if (pathv)
+	    pathlen = strlen (pathv->value);
+	  path_string = xmalloc (5 + pathlen + 2 + 1);
+	  /* On MSDOS, current directory is considered as part of $PATH.  */
+	  sprintf (path_string, "PATH=.;%s", pathv ? pathv->value : "");
+	  fake_env[0] = path_string;
+	  fake_env[1] = 0;
+	  if (__dosexec_find_on_path (shellbase, fake_env, shellpath))
+	    {
+	      char *tp;
+
+	      for (tp = shellpath; *tp; tp++)
+                if (*tp == '\\')
+                  *tp = '/';
+
+	      v = define_variable_loc (varname, varname_len,
+                                       shellpath, origin,
+                                       flavor == f_recursive, flocp);
+	    }
+	  else
+	    v = lookup_variable (varname, varname_len);
+
+	  free (path_string);
+	}
+    }
+  else
+#endif /* __MSDOS__ */
+#ifdef WINDOWS32
+  if (   varname_len == sizeof("SHELL") - 1 /* bird */
+      && (origin == o_file || origin == o_override || origin == o_command)
+      && streq (varname, "SHELL"))
+    {
+      extern char *default_shell;
+
+      /* Call shell locator function. If it returns TRUE, then
+	 set no_default_sh_exe to indicate sh was found and
+         set new value for SHELL variable.  */
+
+      if (find_and_set_default_shell (p))
+        {
+          v = define_variable_in_set (varname, varname_len, default_shell,
+# ifdef CONFIG_WITH_VALUE_LENGTH
+                                      ~0U, 1 /* duplicate_value */,
+# endif
+                                      origin, flavor == f_recursive,
+                                      (target_var
+                                       ? current_variable_set_list->set
+                                       : NULL),
+                                      flocp);
+          no_default_sh_exe = 0;
+        }
+      else
+        v = lookup_variable (varname, varname_len);
+    }
+  else
+#endif
+
+  /* If we are defining variables inside an $(eval ...), we might have a
+     different variable context pushed, not the global context (maybe we're
+     inside a $(call ...) or something.  Since this function is only ever
+     invoked in places where we want to define globally visible variables,
+     make sure we define this variable in the global set.  */
+
+  v = define_variable_in_set (varname, varname_len, p,
+#ifdef CONFIG_WITH_VALUE_LENGTH
+                              value_len, !alloc_value,
+#endif
+                              origin, flavor == f_recursive,
+#ifdef CONFIG_WITH_LOCAL_VARIABLES
+                              (target_var || origin == o_local
+#else
+                              (target_var
+#endif
+                               ? current_variable_set_list->set : NULL),
+                              flocp);
+  v->append = append;
+  v->conditional = conditional;
+
+#ifndef CONFIG_WITH_VALUE_LENGTH
+  if (alloc_value)
+    free (alloc_value);
+#endif
+
+  return v;
+}
+
+
+/* Try to interpret LINE (a null-terminated string) as a variable definition.
+
+   ORIGIN may be o_file, o_override, o_env, o_env_override,
+   or o_command specifying that the variable definition comes
+   from a makefile, an override directive, the environment with
+   or without the -e switch, or the command line.
+
+   See the comments for parse_variable_definition().
+
+   If LINE was recognized as a variable definition, a pointer to its `struct
+   variable' is returned.  If LINE is not a variable definition, NULL is
+   returned.  */
+
+struct variable *
+parse_variable_definition (struct variable *v, char *line)
+{
+  register int c;
+  register char *p = line;
+  register char *beg;
+  register char *end;
+  enum variable_flavor flavor = f_bogus;
+  char *name;
+
+  while (1)
+    {
+      c = *p++;
+      if (c == '\0' || c == '#')
+	return 0;
+      if (c == '=')
+	{
+	  end = p - 1;
+	  flavor = f_recursive;
+	  break;
+	}
+      else if (c == ':')
+	if (*p == '=')
+	  {
+	    end = p++ - 1;
+	    flavor = f_simple;
+	    break;
+	  }
+	else
+	  /* A colon other than := is a rule line, not a variable defn.  */
+	  return 0;
+      else if (c == '+' && *p == '=')
+	{
+	  end = p++ - 1;
+	  flavor = f_append;
+	  break;
+	}
+#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+      else if (c == '<' && *p == '=')
+        {
+          end = p++ - 1;
+          flavor = f_prepend;
+          break;
+        }
+#endif
+      else if (c == '?' && *p == '=')
+        {
+          end = p++ - 1;
+          flavor = f_conditional;
+          break;
+        }
+      else if (c == '$')
+	{
+	  /* This might begin a variable expansion reference.  Make sure we
+	     don't misrecognize chars inside the reference as =, := or +=.  */
+	  char closeparen;
+	  int count;
+	  c = *p++;
+	  if (c == '(')
+	    closeparen = ')';
+	  else if (c == '{')
+	    closeparen = '}';
+	  else
+	    continue;		/* Nope.  */
+
+	  /* P now points past the opening paren or brace.
+	     Count parens or braces until it is matched.  */
+	  count = 0;
+	  for (; *p != '\0'; ++p)
+	    {
+	      if (*p == c)
+		++count;
+	      else if (*p == closeparen && --count < 0)
+		{
+		  ++p;
+		  break;
+		}
+	    }
+	}
+    }
+  v->flavor = flavor;
+
+  beg = next_token (line);
+  while (end > beg && isblank ((unsigned char)end[-1]))
+    --end;
+  p = next_token (p);
+  v->value = p;
+#ifdef CONFIG_WITH_VALUE_LENGTH
+  v->value_length = v->value_alloc_len = -1;
+#endif
+
+  /* Expand the name, so "$(foo)bar = baz" works.  */
+  name = alloca (end - beg + 1);
+  memcpy (name, beg, end - beg);
+  name[end - beg] = '\0';
+  v->name = allocated_variable_expand (name);
+
+  if (v->name[0] == '\0')
+    fatal (&v->fileinfo, _("empty variable name"));
+
+  return v;
+}
+
+
+/* Try to interpret LINE (a null-terminated string) as a variable definition.
+
+   ORIGIN may be o_file, o_override, o_env, o_env_override, o_local,
+   or o_command specifying that the variable definition comes
+   from a makefile, an override directive, the environment with
+   or without the -e switch, or the command line.
+
+   See the comments for parse_variable_definition().
+
+   If LINE was recognized as a variable definition, a pointer to its `struct
+   variable' is returned.  If LINE is not a variable definition, NULL is
+   returned.  */
+
+struct variable *
+try_variable_definition (const struct floc *flocp, char *line,
+                         enum variable_origin origin, int target_var)
+{
+  struct variable v;
+  struct variable *vp;
+
+  if (flocp != 0)
+    v.fileinfo = *flocp;
+  else
+    v.fileinfo.filenm = 0;
+
+  if (!parse_variable_definition (&v, line))
+    return 0;
+
+  vp = do_variable_definition (flocp, v.name, v.value,
+                               origin, v.flavor, target_var);
+
+  free (v.name);
+
+  return vp;
+}
+
+
+/* Print information for variable V, prefixing it with PREFIX.  */
+
+static void
+print_variable (const void *item, void *arg)
+{
+  const struct variable *v = item;
+  const char *prefix = arg;
+  const char *origin;
+
+  switch (v->origin)
+    {
+    case o_default:
+      origin = _("default");
+      break;
+    case o_env:
+      origin = _("environment");
+      break;
+    case o_file:
+      origin = _("makefile");
+      break;
+    case o_env_override:
+      origin = _("environment under -e");
+      break;
+    case o_command:
+      origin = _("command line");
+      break;
+    case o_override:
+      origin = _("`override' directive");
+      break;
+    case o_automatic:
+      origin = _("automatic");
+      break;
+#ifdef CONFIG_WITH_LOCAL_VARIABLES
+    case o_local:
+      origin = _("`local' directive");
+      break;
+#endif
+    case o_invalid:
+    default:
+      abort ();
+    }
+  fputs ("# ", stdout);
+  fputs (origin, stdout);
+  if (v->fileinfo.filenm)
+    printf (_(" (from `%s', line %lu)"),
+            v->fileinfo.filenm, v->fileinfo.lineno);
+  putchar ('\n');
+  fputs (prefix, stdout);
+
+  /* Is this a `define'?  */
+  if (v->recursive && strchr (v->value, '\n') != 0)
+    printf ("define %s\n%s\nendef\n", v->name, v->value);
+  else
+    {
+      register char *p;
+
+      printf ("%s %s= ", v->name, v->recursive ? v->append ? "+" : "" : ":");
+
+      /* Check if the value is just whitespace.  */
+      p = next_token (v->value);
+      if (p != v->value && *p == '\0')
+	/* All whitespace.  */
+	printf ("$(subst ,,%s)", v->value);
+      else if (v->recursive)
+	fputs (v->value, stdout);
+      else
+	/* Double up dollar signs.  */
+	for (p = v->value; *p != '\0'; ++p)
+	  {
+	    if (*p == '$')
+	      putchar ('$');
+	    putchar (*p);
+	  }
+      putchar ('\n');
+    }
+}
+
+
+/* Print all the variables in SET.  PREFIX is printed before
+   the actual variable definitions (everything else is comments).  */
+
+void
+print_variable_set (struct variable_set *set, char *prefix)
+{
+  hash_map_arg (&set->table, print_variable, prefix);
+
+  fputs (_("# variable set hash-table stats:\n"), stdout);
+  fputs ("# ", stdout);
+  hash_print_stats (&set->table, stdout);
+  putc ('\n', stdout);
+}
+
+/* Print the data base of variables.  */
+
+void
+print_variable_data_base (void)
+{
+  puts (_("\n# Variables\n"));
+
+  print_variable_set (&global_variable_set, "");
+
+  puts (_("\n# Pattern-specific Variable Values"));
+
+  {
+    struct pattern_var *p;
+    int rules = 0;
+
+    for (p = pattern_vars; p != 0; p = p->next)
+      {
+        ++rules;
+        printf ("\n%s :\n", p->target);
+        print_variable (&p->variable, "# ");
+      }
+
+    if (rules == 0)
+      puts (_("\n# No pattern-specific variable values."));
+    else
+      printf (_("\n# %u pattern-specific variable values"), rules);
+  }
+}
+
+
+/* Print all the local variables of FILE.  */
+
+void
+print_file_variables (const struct file *file)
+{
+  if (file->variables != 0)
+    print_variable_set (file->variables->set, "# ");
+}
+
+#ifdef WINDOWS32
+void
+sync_Path_environment (void)
+{
+  char *path = allocated_variable_expand ("$(PATH)");
+  static char *environ_path = NULL;
+
+  if (!path)
+    return;
+
+  /*
+   * If done this before, don't leak memory unnecessarily.
+   * Free the previous entry before allocating new one.
+   */
+  if (environ_path)
+    free (environ_path);
+
+  /*
+   * Create something WINDOWS32 world can grok
+   */
+  convert_Path_to_windows32 (path, ';');
+  environ_path = xstrdup (concat ("PATH", "=", path));
+  putenv (environ_path);
+  free (path);
+}
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/variable.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/variable.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/variable.h	(revision 1780)
@@ -0,0 +1,288 @@
+/* Definitions for using variables in GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "hash.h"
+
+/* Codes in a variable definition saying where the definition came from.
+   Increasing numeric values signify less-overridable definitions.  */
+enum variable_origin
+  {
+    o_default,		/* Variable from the default set.  */
+    o_env,		/* Variable from environment.  */
+    o_file,		/* Variable given in a makefile.  */
+    o_env_override,	/* Variable from environment, if -e.  */
+    o_command,		/* Variable given by user.  */
+    o_override, 	/* Variable from an `override' directive.  */
+#ifdef CONFIG_WITH_LOCAL_VARIABLES
+    o_local,            /* Variable from an 'local' directive.  */
+#endif
+    o_automatic,	/* Automatic variable -- cannot be set.  */
+    o_invalid		/* Core dump time.  */
+  };
+
+enum variable_flavor
+  {
+    f_bogus,            /* Bogus (error) */
+    f_simple,           /* Simple definition (:=) */
+    f_recursive,        /* Recursive definition (=) */
+    f_append,           /* Appending definition (+=) */
+#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT
+    f_prepend,          /* Prepending definition (>=) */
+#endif
+    f_conditional       /* Conditional definition (?=) */
+  };
+
+/* Structure that represents one variable definition.
+   Each bucket of the hash table is a chain of these,
+   chained through `next'.  */
+
+#define EXP_COUNT_BITS  15      /* This gets all the bitfields into 32 bits */
+#define EXP_COUNT_MAX   ((1<<EXP_COUNT_BITS)-1)
+
+struct variable
+  {
+    char *name;			/* Variable name.  */
+    int length;			/* strlen (name) */
+#ifdef VARIABLE_HASH /* bird */
+    int hash1;                  /* the primary hash */
+    int hash2;                  /* the secondary hash */
+#endif
+#ifdef CONFIG_WITH_VALUE_LENGTH
+    int value_length;		/* The length of the value, usually unused.  */
+    int value_alloc_len;	/* The amount of memory we've actually allocated. */
+    /* FIXME: make lengths unsigned! */
+#endif
+    char *value;		/* Variable value.  */
+    struct floc fileinfo;       /* Where the variable was defined.  */
+    unsigned int recursive:1;	/* Gets recursively re-evaluated.  */
+    unsigned int append:1;	/* Nonzero if an appending target-specific
+                                   variable.  */
+    unsigned int conditional:1; /* Nonzero if set with a ?=. */
+    unsigned int per_target:1;	/* Nonzero if a target-specific variable.  */
+    unsigned int special:1;     /* Nonzero if this is a special variable. */
+    unsigned int exportable:1;  /* Nonzero if the variable _could_ be
+                                   exported.  */
+    unsigned int expanding:1;	/* Nonzero if currently being expanded.  */
+    unsigned int exp_count:EXP_COUNT_BITS;
+                                /* If >1, allow this many self-referential
+                                   expansions.  */
+    enum variable_flavor
+      flavor ENUM_BITFIELD (3);	/* Variable flavor.  */
+    enum variable_origin
+#ifdef CONFIG_WITH_LOCAL_VARIABLES
+      origin ENUM_BITFIELD (4);	/* Variable origin.  */
+#else
+      origin ENUM_BITFIELD (3);	/* Variable origin.  */
+#endif
+    enum variable_export
+      {
+	v_export,		/* Export this variable.  */
+	v_noexport,		/* Don't export this variable.  */
+	v_ifset,		/* Export it if it has a non-default value.  */
+	v_default		/* Decide in target_environment.  */
+      } export ENUM_BITFIELD (2);
+  };
+
+/* Structure that represents a variable set.  */
+
+struct variable_set
+  {
+    struct hash_table table;	/* Hash table of variables.  */
+  };
+
+/* Structure that represents a list of variable sets.  */
+
+struct variable_set_list
+  {
+    struct variable_set_list *next;	/* Link in the chain.  */
+    struct variable_set *set;		/* Variable set.  */
+  };
+
+/* Structure used for pattern-specific variables.  */
+
+struct pattern_var
+  {
+    struct pattern_var *next;
+    const char *suffix;
+    const char *target;
+    unsigned int len;
+    struct variable variable;
+  };
+
+extern char *variable_buffer;
+extern struct variable_set_list *current_variable_set_list;
+
+/* expand.c */
+char *variable_buffer_output (char *ptr, const char *string, unsigned int length);
+char *variable_expand (const char *line);
+char *variable_expand_for_file (const char *line, struct file *file);
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+char *variable_expand_for_file_2 (char *o, const char *line, struct file *file);
+#endif
+char *allocated_variable_expand_for_file (const char *line, struct file *file);
+#define	allocated_variable_expand(line) \
+  allocated_variable_expand_for_file (line, (struct file *) 0)
+char *expand_argument (const char *str, const char *end);
+char *variable_expand_string (char *line, const char *string, long length);
+void install_variable_buffer (char **bufp, unsigned int *lenp);
+void restore_variable_buffer (char *buf, unsigned int len);
+#ifdef CONFIG_WITH_VALUE_LENGTH
+extern void append_expanded_string_to_variable (struct variable *v, const char *value, int append);
+#endif
+
+/* function.c */
+int handle_function (char **op, const char **stringp);
+int pattern_matches (const char *pattern, const char *percent, const char *str);
+char *subst_expand (char *o, const char *text, const char *subst,
+                    const char *replace, unsigned int slen, unsigned int rlen,
+                    int by_word);
+char *patsubst_expand_pat (char *o, const char *text, const char *pattern,
+                           const char *replace, const char *pattern_percent,
+                           const char *replace_percent);
+char *patsubst_expand (char *o, const char *text, char *pattern, char *replace);
+#ifdef CONFIG_WITH_COMMANDS_FUNC
+char *func_commands (char *o, char **argv, const char *funcname);
+#endif
+
+/* expand.c */
+char *recursively_expand_for_file (struct variable *v, struct file *file);
+#define recursively_expand(v)   recursively_expand_for_file (v, NULL)
+
+/* variable.c */
+struct variable_set_list *create_new_variable_set (void);
+void free_variable_set (struct variable_set_list *);
+struct variable_set_list *push_new_variable_scope (void);
+void pop_variable_scope (void);
+void define_automatic_variables (void);
+void initialize_file_variables (struct file *file, int reading);
+void print_file_variables (const struct file *file);
+void print_variable_set (struct variable_set *set, char *prefix);
+void merge_variable_set_lists (struct variable_set_list **to_list,
+                               struct variable_set_list *from_list);
+struct variable *do_variable_definition (const struct floc *flocp,
+                                         const char *name, const char *value,
+                                         enum variable_origin origin,
+                                         enum variable_flavor flavor,
+                                         int target_var);
+struct variable *parse_variable_definition (struct variable *v, char *line);
+struct variable *try_variable_definition (const struct floc *flocp, char *line,
+                                          enum variable_origin origin,
+                                          int target_var);
+void init_hash_global_variable_set (void);
+void hash_init_function_table (void);
+struct variable *lookup_variable (const char *name, unsigned int length);
+struct variable *lookup_variable_in_set (const char *name, unsigned int length,
+                                         const struct variable_set *set);
+
+#ifdef CONFIG_WITH_VALUE_LENGTH
+void append_string_to_variable (struct variable *v, const char *value,
+                                unsigned int value_len, int append);
+
+struct variable *define_variable_in_set (const char *name, unsigned int length,
+                                         const char *value,
+                                         unsigned int value_length,
+                                         int duplicate_value,
+                                         enum variable_origin origin,
+                                         int recursive,
+                                         struct variable_set *set,
+                                         const struct floc *flocp);
+
+/* Define a variable in the current variable set.  */
+
+#define define_variable(n,l,v,o,r) \
+          define_variable_in_set((n),(l),(v),~0U,1,(o),(r),\
+                                 current_variable_set_list->set,NILF)
+
+#define define_variable_vl(n,l,v,vl,dv,o,r) \
+          define_variable_in_set((n),(l),(v),(vl),(dv),(o),(r),\
+                                 current_variable_set_list->set,NILF)
+
+/* Define a variable with a location in the current variable set.  */
+
+#define define_variable_loc(n,l,v,o,r,f) \
+          define_variable_in_set((n),(l),(v),~0U,1,(o),(r),\
+                                 current_variable_set_list->set,(f))
+
+/* Define a variable with a location in the global variable set.  */
+
+#define define_variable_global(n,l,v,o,r,f) \
+          define_variable_in_set((n),(l),(v),~0U,1,(o),(r),NULL,(f))
+
+#define define_variable_vl_global(n,l,v,vl,dv,o,r,f) \
+          define_variable_in_set((n),(l),(v),(vl),(dv),(o),(r),NULL,(f))
+
+/* Define a variable in FILE's variable set.  */
+
+#define define_variable_for_file(n,l,v,o,r,f) \
+          define_variable_in_set((n),(l),(v),~0U,1,(o),(r),(f)->variables->set,NILF)
+
+#else  /* !CONFIG_WITH_VALUE_LENGTH */
+
+struct variable *define_variable_in_set (const char *name, unsigned int length,
+                                         const char *value,
+                                         enum variable_origin origin,
+                                         int recursive,
+                                         struct variable_set *set,
+                                         const struct floc *flocp);
+
+/* Define a variable in the current variable set.  */
+
+#define define_variable(n,l,v,o,r) \
+          define_variable_in_set((n),(l),(v),(o),(r),\
+                                 current_variable_set_list->set,NILF)           /* force merge conflict */
+
+/* Define a variable with a location in the current variable set.  */
+
+#define define_variable_loc(n,l,v,o,r,f) \
+          define_variable_in_set((n),(l),(v),(o),(r),\
+                                 current_variable_set_list->set,(f))            /* force merge conflict */
+
+/* Define a variable with a location in the global variable set.  */
+
+#define define_variable_global(n,l,v,o,r,f) \
+          define_variable_in_set((n),(l),(v),(o),(r),NULL,(f))                  /* force merge conflict */
+
+/* Define a variable in FILE's variable set.  */
+
+#define define_variable_for_file(n,l,v,o,r,f) \
+          define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF)  /* force merge conflict */
+
+#endif /* !CONFIG_WITH_VALUE_LENGTH */
+
+/* Warn that NAME is an undefined variable.  */
+
+#define warn_undefined(n,l) do{\
+                              if (warn_undefined_variables_flag) \
+                                error (reading_file, \
+                                       _("warning: undefined variable `%.*s'"), \
+                                (int)(l), (n)); \
+                              }while(0)
+
+char **target_environment (struct file *file);
+
+struct pattern_var *create_pattern_var (const char *target,
+                                        const char *suffix);
+
+extern int export_all_variables;
+
+#ifdef KMK
+# define MAKELEVEL_NAME "KMK_LEVEL"
+#else
+#define MAKELEVEL_NAME "MAKELEVEL"
+#endif
+#define MAKELEVEL_LENGTH (sizeof (MAKELEVEL_NAME) - 1)
Index: /tags/kBuild-0.1.4/src/kmk/version.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/version.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/version.c	(revision 1780)
@@ -0,0 +1,36 @@
+/* Record version and build host architecture for GNU make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* We use <config.h> instead of "config.h" so that a compilation
+   using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
+   (which it would do because make.h was found in $srcdir).  */
+#include <config.h>
+
+#ifndef MAKE_HOST
+# define MAKE_HOST "unknown"
+#endif
+
+char *version_string = VERSION;
+char *make_host = MAKE_HOST;
+
+
+/*
+  Local variables:
+  version-control: never
+  End:
+ */
Index: /tags/kBuild-0.1.4/src/kmk/vmsdir.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/vmsdir.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/vmsdir.h	(revision 1780)
@@ -0,0 +1,77 @@
+/* dirent.h for vms
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef VMSDIR_H
+#define VMSDIR_H
+
+#include <rms.h>
+
+#define	MAXNAMLEN	255
+
+#ifndef __DECC
+#if !defined (__GNUC__) && !defined (__ALPHA)
+typedef unsigned long u_long;
+typedef unsigned short u_short;
+#endif
+#endif
+
+struct direct
+{
+  off_t d_off;
+  u_long d_fileno;
+  u_short d_reclen;
+  u_short d_namlen;
+  char d_name[MAXNAMLEN + 1];
+};
+
+#undef DIRSIZ
+#define DIRSIZ(dp)		\
+  (((sizeof (struct direct)	\
+     - (MAXNAMLEN+1)		\
+     + ((dp)->d_namlen+1))	\
+    + 3) & ~3)
+
+#define d_ino	d_fileno		/* compatability */
+
+
+/*
+ * Definitions for library routines operating on directories.
+ */
+
+typedef struct DIR
+{
+  struct direct dir;
+  char d_result[MAXNAMLEN + 1];
+#if defined (__ALPHA) || defined (__DECC)
+  struct FAB fab;
+#else
+  struct fabdef fab;
+#endif
+} DIR;
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define rewinddir(dirp)	seekdir((dirp), (long)0)
+
+DIR *opendir ();
+struct direct *readdir (DIR *dfd);
+int closedir (DIR *dfd);
+const char *vmsify (const char *name, int type);
+
+#endif /* VMSDIR_H */
Index: /tags/kBuild-0.1.4/src/kmk/vmsfunctions.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/vmsfunctions.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/vmsfunctions.c	(revision 1780)
@@ -0,0 +1,259 @@
+/* VMS functions
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "debug.h"
+#include "job.h"
+
+#ifdef __DECC
+#include <starlet.h>
+#endif
+#include <descrip.h>
+#include <rms.h>
+#include <iodef.h>
+#include <atrdef.h>
+#include <fibdef.h>
+#include "vmsdir.h"
+
+#ifdef HAVE_VMSDIR_H
+
+DIR *
+opendir (char *dspec)
+{
+  struct DIR *dir  = (struct DIR *)xmalloc (sizeof (struct DIR));
+  struct NAM *dnam = (struct NAM *)xmalloc (sizeof (struct NAM));
+  struct FAB *dfab = &dir->fab;
+  char *searchspec = xmalloc (MAXNAMLEN + 1);
+
+  memset (dir, 0, sizeof *dir);
+
+  *dfab = cc$rms_fab;
+  *dnam = cc$rms_nam;
+  sprintf (searchspec, "%s*.*;", dspec);
+
+  dfab->fab$l_fna = searchspec;
+  dfab->fab$b_fns = strlen (searchspec);
+  dfab->fab$l_nam = dnam;
+
+  *dnam = cc$rms_nam;
+  dnam->nam$l_esa = searchspec;
+  dnam->nam$b_ess = MAXNAMLEN;
+
+  if (! (sys$parse (dfab) & 1))
+    {
+      free (dir);
+      free (dnam);
+      free (searchspec);
+      return (NULL);
+    }
+
+  return dir;
+}
+
+#define uppercasify(str) \
+  do \
+    { \
+      char *tmp; \
+      for (tmp = (str); *tmp != '\0'; tmp++) \
+        if (islower ((unsigned char)*tmp)) \
+          *tmp = toupper ((unsigned char)*tmp); \
+    } \
+  while (0)
+
+struct direct *
+readdir (DIR *dir)
+{
+  struct FAB *dfab = &dir->fab;
+  struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
+  struct direct *dentry = &dir->dir;
+  int i;
+
+  memset (dentry, 0, sizeof *dentry);
+
+  dnam->nam$l_rsa = dir->d_result;
+  dnam->nam$b_rss = MAXNAMLEN;
+
+  DB (DB_VERBOSE, ("."));
+
+  if (!((i = sys$search (dfab)) & 1))
+    {
+      DB (DB_VERBOSE, (_("sys$search failed with %d\n"), i));
+      return (NULL);
+    }
+
+  dentry->d_off = 0;
+  if (dnam->nam$w_fid == 0)
+    dentry->d_fileno = 1;
+  else
+    dentry->d_fileno = dnam->nam$w_fid[0] + (dnam->nam$w_fid[1] << 16);
+
+  dentry->d_reclen = sizeof (struct direct);
+  dentry->d_namlen = dnam->nam$b_name + dnam->nam$b_type;
+  strncpy (dentry->d_name, dnam->nam$l_name, dentry->d_namlen);
+  dentry->d_name[dentry->d_namlen] = '\0';
+
+#ifdef HAVE_CASE_INSENSITIVE_FS
+  uppercasify (dentry->d_name);
+#endif
+
+  return (dentry);
+}
+
+int
+closedir (DIR *dir)
+{
+  if (dir != NULL)
+    {
+      struct FAB *dfab = &dir->fab;
+      struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
+      if (dnam != NULL)
+	free (dnam->nam$l_esa);
+      free (dnam);
+      free (dir);
+    }
+
+  return 0;
+}
+#endif /* compiled for OpenVMS prior to V7.x */
+
+char *
+getwd (char *cwd)
+{
+  static char buf[512];
+
+  if (cwd)
+    return (getcwd (cwd, 512));
+  else
+    return (getcwd (buf, 512));
+}
+
+int
+vms_stat (char *name, struct stat *buf)
+{
+  int status;
+  int i;
+
+  static struct FAB Fab;
+  static struct NAM Nam;
+  static struct fibdef Fib;	/* short fib */
+  static struct dsc$descriptor FibDesc =
+  { sizeof (Fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *) &Fib };
+  static struct dsc$descriptor_s DevDesc =
+  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &Nam.nam$t_dvi[1] };
+  static char EName[NAM$C_MAXRSS];
+  static char RName[NAM$C_MAXRSS];
+  static struct dsc$descriptor_s FileName =
+  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
+  static struct dsc$descriptor_s string =
+  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
+  static unsigned long Rdate[2];
+  static unsigned long Cdate[2];
+  static struct atrdef Atr[] =
+  {
+#if defined(VAX)
+    /* Revision date */
+    { sizeof (Rdate), ATR$C_REVDATE, (unsigned int) &Rdate[0] },
+    /* Creation date */
+    { sizeof (Cdate), ATR$C_CREDATE, (unsigned int) &Cdate[0] },
+#else
+    /* Revision date */
+    { sizeof (Rdate), ATR$C_REVDATE, &Rdate[0] },
+    /* Creation date */
+    { sizeof (Cdate), ATR$C_CREDATE, &Cdate[0]},
+#endif
+    { 0, 0, 0 }
+  };
+  static short int DevChan;
+  static short int iosb[4];
+
+  name = vmsify (name, 0);
+
+  /* initialize RMS structures, we need a NAM to retrieve the FID */
+  Fab = cc$rms_fab;
+  Fab.fab$l_fna = name;		/* name of file */
+  Fab.fab$b_fns = strlen (name);
+  Fab.fab$l_nam = &Nam;		/* FAB has an associated NAM */
+
+  Nam = cc$rms_nam;
+  Nam.nam$l_esa = EName;	/* expanded filename */
+  Nam.nam$b_ess = sizeof (EName);
+  Nam.nam$l_rsa = RName;	/* resultant filename */
+  Nam.nam$b_rss = sizeof (RName);
+
+  /* do $PARSE and $SEARCH here */
+  status = sys$parse (&Fab);
+  if (!(status & 1))
+    return -1;
+
+  DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
+  status = sys$assign (&DevDesc, &DevChan, 0, 0);
+  if (!(status & 1))
+    return -1;
+
+  FileName.dsc$a_pointer = Nam.nam$l_name;
+  FileName.dsc$w_length = Nam.nam$b_name + Nam.nam$b_type + Nam.nam$b_ver;
+
+  /* Initialize the FIB */
+  for (i = 0; i < 3; i++)
+    {
+#ifndef __VAXC
+      Fib.fib$w_fid[i] = Nam.nam$w_fid[i];
+      Fib.fib$w_did[i] = Nam.nam$w_did[i];
+#else
+      Fib.fib$r_fid_overlay.fib$w_fid[i] = Nam.nam$w_fid[i];
+      Fib.fib$r_did_overlay.fib$w_did[i] = Nam.nam$w_did[i];
+#endif
+    }
+
+  status = sys$qiow (0, DevChan, IO$_ACCESS, &iosb, 0, 0,
+		     &FibDesc, &FileName, 0, 0, &Atr, 0);
+  sys$dassgn (DevChan);
+  if (!(status & 1))
+    return -1;
+  status = iosb[0];
+  if (!(status & 1))
+    return -1;
+
+  status = stat (name, buf);
+  if (status)
+    return -1;
+
+  buf->st_mtime = ((Rdate[0] >> 24) & 0xff) + ((Rdate[1] << 8) & 0xffffff00);
+  buf->st_ctime = ((Cdate[0] >> 24) & 0xff) + ((Cdate[1] << 8) & 0xffffff00);
+
+  return 0;
+}
+
+char *
+cvt_time (unsigned long tval)
+{
+  static long int date[2];
+  static char str[27];
+  static struct dsc$descriptor date_str =
+  { 26, DSC$K_DTYPE_T, DSC$K_CLASS_S, str };
+
+  date[0] = (tval & 0xff) << 24;
+  date[1] = ((tval >> 8) & 0xffffff);
+
+  if ((date[0] == 0) && (date[1] == 0))
+    return ("never");
+
+  sys$asctim (0, &date_str, date, 0);
+  str[26] = '\0';
+
+  return (str);
+}
Index: /tags/kBuild-0.1.4/src/kmk/vmsify.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/vmsify.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/vmsify.c	(revision 1780)
@@ -0,0 +1,997 @@
+/* vmsify.c -- Module for vms <-> unix file name conversion
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+/* Written by Klaus Kämpf (kkaempf@progis.de)
+   of proGIS Software, Aachen, Germany */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#if VMS
+#include <unixlib.h>
+#include <stdlib.h>
+#include <jpidef.h>
+#include <descrip.h>
+#include <uaidef.h>
+#include <ssdef.h>
+#include <starlet.h>
+#include <lib$routines.h>
+/* Initialize a string descriptor (struct dsc$descriptor_s) for an
+   arbitrary string.   ADDR is a pointer to the first character
+   of the string, and LEN is the length of the string. */
+
+#define INIT_DSC_S(dsc, addr, len) do { \
+  (dsc).dsc$b_dtype = DSC$K_DTYPE_T;    \
+  (dsc).dsc$b_class = DSC$K_CLASS_S;    \
+  (dsc).dsc$w_length = (len);           \
+  (dsc).dsc$a_pointer = (addr);         \
+} while (0)
+
+/* Initialize a string descriptor (struct dsc$descriptor_s) for a
+   NUL-terminated string.  S is a pointer to the string; the length
+   is determined by calling strlen(). */
+
+#define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
+#endif
+
+/*
+  copy 'from' to 'to' up to but not including 'upto'
+  return 0 if eos on from
+  return 1 if upto found
+
+  return 'to' at last char + 1
+  return 'from' at match + 1 or eos if no match
+
+  if as_dir == 1, change all '.' to '_'
+  else change all '.' but the last to '_'
+*/
+
+static int
+copyto (char **to, const char **from, char upto, int as_dir)
+{
+  const char *s;
+
+  s = strrchr (*from, '.');
+
+  while (**from)
+    {
+      if (**from == upto)
+	{
+	  do
+	    {
+	      (*from)++;
+	    }
+	  while (**from == upto);
+	  return 1;
+	}
+      if (**from == '.')
+	{
+	  if ((as_dir == 1)
+	      || (*from != s))
+	    **to = '_';
+	  else
+	    **to = '.';
+	}
+      else
+	{
+#ifdef HAVE_CASE_INSENSITIVE_FS
+	  if (isupper ((unsigned char)**from))
+	    **to = tolower ((unsigned char)**from);
+	  else
+#endif
+	    **to = **from;
+	}
+      (*to)++;
+      (*from)++;
+    }
+
+  return 0;
+}
+
+
+/*
+  get translation of logical name
+
+*/
+
+static char *
+trnlog (const char *name)
+{
+  int stat;
+  static char reslt[1024];
+  $DESCRIPTOR (reslt_dsc, reslt);
+  short resltlen;
+  struct dsc$descriptor_s name_dsc;
+  char *s;
+
+  INIT_DSC_CSTRING (name_dsc, name);
+
+  stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
+
+  if ((stat&1) == 0)
+    {
+      return "";
+    }
+  if (stat == SS$_NOTRAN)
+    {
+      return "";
+    }
+  reslt[resltlen] = '\0';
+
+  s = malloc (resltlen+1);
+  if (s == 0)
+    return "";
+  strcpy (s, reslt);
+  return s;
+}
+
+static char *
+showall (char *s)
+{
+  static char t[512];
+  char *pt;
+
+  pt = t;
+  if (strchr (s, '\\') == 0)
+    return s;
+  while (*s)
+    {
+      if (*s == '\\')
+	{
+	  *pt++ = *s;
+	}
+      *pt++ = *s++;
+    }
+  return pt;
+}
+
+
+enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
+
+/*
+  convert unix style name to vms style
+  type = 0 -> name is a full name (directory and filename part)
+  type = 1 -> name is a directory
+  type = 2 -> name is a filename without directory
+
+  The following conversions are applied
+			(0)		(1)			(2)
+	input		full name	dir name		file name
+
+1	./		<cwd>		[]			<current directory>.dir
+2	../		<home of cwd>	<home of cwd>		<home of cwd>.dir
+
+3	//		<dev of cwd>:	<dev of cwd>:[000000]	<dev of cwd>:000000.dir
+4	//a		a:		a:			a:
+5	//a/		a:		a:			a:000000.dir
+
+9	/		[000000]	[000000]		000000.dir
+10	/a		[000000]a	[a]			[000000]a
+11	/a/		[a]		[a]			[000000]a.dir
+12	/a/b		[a]b		[a.b]			[a]b
+13	/a/b/		[a.b]		[a.b]			[a]b.dir
+14	/a/b/c		[a.b]c		[a.b.c]			[a.b]c
+15	/a/b/c/		[a.b.c]		[a.b.c]			[a.b]c.dir
+
+16	a		a		[.a]			a
+17	a/		[.a]		[.a]			a.dir
+18	a/b		[.a]b		[.a.b]			[.a]b
+19	a/b/		[.a.b]		[.a.b]			[.a]b.dir
+20	a/b/c		[.a.b]c		[.a.b.c]		[.a.b]c
+21	a/b/c/		[.a.b.c]	[.a.b.c]		[.a.b]c.dir
+
+22	a.b.c		a_b.c		[.a_b_c]		a_b_c.dir
+
+23	[x][y]z		[x.y]z		[x.y]z			[x.y]z
+24	[x][.y]z	[x.y]z		[x.y]z			[x.y]z
+
+25  filenames with '$'  are left unchanged if they contain no '/'
+25  filenames with ':' are left unchanged
+26  filenames with a single pair of '[' ']' are left unchanged
+
+  The input string is not written to.  The result is also const because
+  it's a static buffer; we don't want to change it.
+*/
+
+const char *
+vmsify (const char *name, int type)
+{
+/* max 255 device
+   max 39 directory
+   max 39 filename
+   max 39 filetype
+   max 5 version
+*/
+#define MAXPATHLEN 512
+
+  enum namestate nstate;
+  static char vmsname[MAXPATHLEN+1];
+  const char *fptr;
+  const char *t;
+  char *vptr;
+  int as_dir;
+  int count;
+
+  if (name == 0)
+    return 0;
+  fptr = name;
+  vptr = vmsname;
+  nstate = N_START;
+
+  /* case 25a */
+  t = strpbrk (name, "$:");
+
+  if (t != 0)
+    {
+      const char *s1;
+      const char *s2;
+
+      if (type == 1)
+        {
+          s1 = strchr (t+1, '[');
+          s2 = strchr (t+1, ']');
+        }
+
+      if (*t == '$')
+        {
+          if (strchr (name, '/') == 0)
+            {
+              strcpy (vmsname, name);
+              if ((type == 1) && (s1 != 0) && (s2 == 0))
+                strcat (vmsname, "]");
+              return vmsname;
+            }
+        }
+      else
+        {
+          strcpy (vmsname, name);
+          if ((type == 1) && (s1 != 0) && (s2 == 0))
+            strcat (vmsname, "]");
+          return vmsname;
+        }
+    }
+
+  /* case 26 */
+  t = strchr (name, '[');
+
+  if (t != 0)
+    {
+      const char *s;
+      const char *s1 = strchr (t+1, '[');
+      if (s1 == 0)
+	{
+          strcpy (vmsname, name);
+	  if ((type == 1) && (strchr (t+1, ']') == 0))
+            strcat (vmsname, "]");
+          return vmsname;
+	}
+      s1--;
+      if (*s1 != ']')
+	{
+          strcpy (vmsname, name);
+	  return vmsname;		/* not ][, keep unchanged */
+	}
+
+      /* we have ][ */
+
+      s = name;
+
+      /* s  -> starting char
+	 s1 -> ending ']'  */
+      do
+	{
+	  strncpy (vptr, s, s1-s);	/* copy up to but not including ']' */
+	  vptr += s1-s;
+	  if (*s1 == 0)
+	    break;
+	  s = s1 + 1;			/* s -> char behind ']' */
+	  if (*s != '[')		/* was '][' ? */
+	    break;			/* no, last ] found, exit */
+	  s++;
+	  if (*s != '.')
+	    *vptr++ = '.';
+	  s1 = strchr (s, ']');
+	  if (s1 == 0)			/* no closing ] */
+	    s1 = s + strlen (s);
+	}
+      while (1);
+
+      *vptr++ = ']';
+
+      fptr = s;
+
+    }
+  else		/* no [ in name */
+    {
+      int state = 0;
+      int rooted = 1;	/* flag if logical is rooted, else insert [000000] */
+
+      do
+	{
+      switch (state)
+	{
+	  case 0:				/* start of loop */
+	    if (*fptr == '/')
+	      {
+		fptr++;
+		state = 1;
+	      }
+	    else if (*fptr == '.')
+	      {
+		fptr++;
+		state = 10;
+	      }
+	    else
+	      state = 2;
+	    break;
+
+	  case 1:				/* '/' at start */
+	    if (*fptr == '/')
+	      {
+		fptr++;
+		state = 3;
+	      }
+	    else
+	      state = 4;
+	    break;
+
+	  case 2:				/* no '/' at start */
+            {
+            const char *s = strchr (fptr, '/');
+	    if (s == 0)			/* no '/' (16) */
+	      {
+		if (type == 1)
+		  {
+		    strcpy (vptr, "[.");
+		    vptr += 2;
+		  }
+		copyto (&vptr, &fptr, 0, (type==1));
+		if (type == 1)
+		  *vptr++ = ']';
+		state = -1;
+	      }
+	    else			/* found '/' (17..21) */
+	      {
+		if ((type == 2)
+		    && (*(s+1) == 0))	/* 17(2) */
+		  {
+		    copyto (&vptr, &fptr, '/', 1);
+		    state = 7;
+		  }
+		else
+		  {
+		    strcpy (vptr, "[.");
+		    vptr += 2;
+		    copyto (&vptr, &fptr, '/', 1);
+		    nstate = N_OPEN;
+		    state = 9;
+		  }
+	      }
+	    break;
+            }
+
+	  case 3:				/* '//' at start */
+            {
+            const char *s;
+            const char *s1;
+            char *vp;
+	    while (*fptr == '/')	/* collapse all '/' */
+	      fptr++;
+	    if (*fptr == 0)		/* just // */
+	      {
+		char cwdbuf[MAXPATHLEN+1];
+
+		s1 = getcwd(cwdbuf, MAXPATHLEN);
+		if (s1 == 0)
+		  {
+                    vmsname[0] = '\0';
+		    return vmsname;	/* FIXME, err getcwd */
+		  }
+		s = strchr (s1, ':');
+		if (s == 0)
+		  {
+                    vmsname[0] = '\0';
+		    return vmsname;	/* FIXME, err no device */
+		  }
+		strncpy (vptr, s1, s-s1+1);
+		vptr += s-s1+1;
+		state = -1;
+		break;
+	      }
+
+	    s = vptr;
+
+	    if (copyto (&vptr, &fptr, '/', 1) == 0)	/* copy device part */
+	      {
+		*vptr++ = ':';
+		state = -1;
+		break;
+	      }
+	    *vptr = ':';
+	    nstate = N_DEVICE;
+	    if (*fptr == 0)	/* just '//a/' */
+	      {
+		strcpy (vptr+1, "[000000]");
+		vptr += 9;
+		state = -1;
+		break;
+	      }
+	    *vptr = 0;
+				/* check logical for [000000] insertion */
+	    vp = trnlog (s);
+	    if (*vp != '\0')
+	      {			/* found translation */
+		for (;;)	/* loop over all nested logicals */
+		  {
+		    char *vp2 = vp + strlen (vp) - 1;
+		    if (*vp2 == ':')	/* translation ends in ':' */
+		      {
+			vp2 = trnlog (vp);
+			free (vp);
+			if (*vp2 == 0)
+			  {
+			    rooted = 0;
+			    break;
+			  }
+			vp = vp2;
+			continue;	/* next iteration */
+		      }
+		    if (*vp2 == ']')	/* translation ends in ']' */
+		      {
+			if (*(vp2-1) == '.')	/* ends in '.]' */
+			  {
+			    if (strncmp (fptr, "000000", 6) != 0)
+			      rooted = 0;
+			  }
+			else
+			  {
+			    strcpy (vmsname, s1);
+			    vp = strchr (vmsname, ']');
+			    *vp = '.';
+			    nstate = N_DOT;
+			    vptr = vp;
+			  }
+		      }
+		    break;
+		  }
+		free (vp);
+	      }
+	    else
+	      rooted = 0;
+
+	    if (*vptr == 0)
+	      {
+		nstate = N_DEVICE;
+	        *vptr++ = ':';
+	      }
+	    else
+	      vptr++;
+
+	    if (rooted == 0)
+	      {
+		nstate = N_DOT;
+	        strcpy (vptr, "[000000.");
+		vptr += 8;
+		vp = vptr-1;
+	      }
+	    else
+	      vp = 0;
+
+            /* vp-> '.' after 000000 or NULL */
+
+	    s = strchr (fptr, '/');
+	    if (s == 0)
+	      {				/* no next '/' */
+		if (*(vptr-1) == '.')
+		  *(vptr-1) = ']';
+		else if (rooted == 0)
+		  *vptr++ = ']';
+		copyto (&vptr, &fptr, 0, (type == 1));
+		state = -1;
+		break;
+	      }
+	    else
+	      {
+		while (*(s+1) == '/')	/* skip multiple '/' */
+		  s++;
+	      }
+
+	    if ((rooted != 0)
+	        && (*(vptr-1) != '.'))
+	      {
+		*vptr++ = '[';
+		nstate = N_DOT;
+	      }
+	    else
+	      if ((nstate == N_DOT)
+		 && (vp != 0)
+		 && (*(s+1) == 0))
+		{
+		  if (type == 2)
+		    {
+		      *vp = ']';
+		      nstate = N_CLOSED;
+		    }
+		}
+	    state = 9;
+	    break;
+            }
+	  case 4:				/* single '/' at start (9..15) */
+	    if (*fptr == 0)
+	      state = 5;
+	    else
+	      state = 6;
+	    break;
+
+	  case 5:				/* just '/' at start (9) */
+	    if (type != 2)
+	      {
+	        *vptr++ = '[';
+		nstate = N_OPEN;
+	      }
+	    strcpy (vptr, "000000");
+	    vptr += 6;
+	    if (type == 2)
+	      state = 7;
+	    else
+	      state = 8;
+	    break;
+
+	  case 6:		/* chars following '/' at start 10..15 */
+            {
+            const char *s;
+	    *vptr++ = '[';
+	    nstate = N_OPEN;
+	    s = strchr (fptr, '/');
+	    if (s == 0)			/* 10 */
+	      {
+		if (type != 1)
+		  {
+		    strcpy (vptr, "000000]");
+		    vptr += 7;
+		  }
+		copyto (&vptr, &fptr, 0, (type == 1));
+		if (type == 1)
+		  {
+		    *vptr++ = ']';
+		  }
+		state = -1;
+	      }
+	    else			/* 11..15 */
+	      {
+		if ( (type == 2)
+		   && (*(s+1) == 0))	/* 11(2) */
+		  {
+		    strcpy (vptr, "000000]");
+		    nstate = N_CLOSED;
+		    vptr += 7;
+		  }
+		copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
+		state = 9;
+	      }
+	    break;
+            }
+
+	  case 7:				/* add '.dir' and exit */
+	    if ((nstate == N_OPEN)
+		|| (nstate == N_DOT))
+	      {
+		char *vp = vptr-1;
+		while (vp > vmsname)
+		  {
+		    if (*vp == ']')
+		      {
+			break;
+		      }
+		    if (*vp == '.')
+		      {
+			*vp = ']';
+			break;
+		      }
+		    vp--;
+		  }
+	      }
+	    strcpy (vptr, ".dir");
+	    vptr += 4;
+	    state = -1;
+	    break;
+
+	  case 8:				/* add ']' and exit */
+	    *vptr++ = ']';
+	    state = -1;
+	    break;
+
+	  case 9:			/* 17..21, fptr -> 1st '/' + 1 */
+            {
+            const char *s;
+	    if (*fptr == 0)
+	      {
+		if (type == 2)
+		  {
+		    state = 7;
+		  }
+		else
+		  state = 8;
+		break;
+	      }
+	    s = strchr (fptr, '/');
+	    if (s == 0)
+	      {
+		if (type != 1)
+		  {
+		    if (nstate == N_OPEN)
+		      {
+			*vptr++ = ']';
+			nstate = N_CLOSED;
+		      }
+		    as_dir = 0;
+		  }
+		else
+		  {
+		    if (nstate == N_OPEN)
+		      {
+			*vptr++ = '.';
+			nstate = N_DOT;
+		      }
+		    as_dir = 1;
+		  }
+	      }
+	    else
+	      {
+		while (*(s+1) == '/')
+		  s++;
+		if ( (type == 2)
+		    && (*(s+1) == 0))		/* 19(2), 21(2)*/
+		  {
+		    if (nstate != N_CLOSED)
+		      {
+			*vptr++ = ']';
+			nstate = N_CLOSED;
+		      }
+		    as_dir = 1;
+		  }
+		else
+		  {
+		    if (nstate == N_OPEN)
+		      {
+			*vptr++ = '.';
+			nstate = N_DOT;
+		      }
+		    as_dir = 1;
+		  }
+	      }
+	    if ( (*fptr == '.')			/* check for '..' or '../' */
+		&& (*(fptr+1) == '.')
+		&& ((*(fptr+2) == '/')
+		    || (*(fptr+2) == 0)) )
+	      {
+                char *vp;
+		fptr += 2;
+		if (*fptr == '/')
+		  {
+		    do
+		      {
+			fptr++;
+		      }
+		    while (*fptr == '/');
+		  }
+		else if (*fptr == 0)
+		  type = 1;
+		vptr--;				/* vptr -> '.' or ']' */
+		vp = vptr;
+		for (;;)
+		  {
+		    vp--;
+		    if (*vp == '.')		/* one back */
+		      {
+			vptr = vp;
+			nstate = N_OPEN;
+			break;
+		      }
+		    if (*vp == '[')		/* top level reached */
+		      {
+			if (*fptr == 0)
+			  {
+			    strcpy (vp, "[000000]");
+			    vptr = vp + 8;
+			    nstate = N_CLOSED;
+			    s = 0;
+			    break;
+			  }
+			else
+			  {
+			    vptr = vp+1;
+			    nstate = N_OPEN;
+			    break;
+			  }
+		      }
+		  }
+	      }
+	    else
+	      {
+		copyto (&vptr, &fptr, '/', as_dir);
+		if (nstate == N_DOT)
+		  nstate = N_OPEN;
+	      }
+	    if (s == 0)
+	      {					/* 18,20 */
+		if (type == 1)
+		  *vptr++ = ']';
+		state = -1;
+	      }
+	    else
+	      {
+		if (*(s+1) == 0)
+		  {
+		    if (type == 2)		/* 19,21 */
+		      {
+		        state = 7;
+		      }
+		    else
+		      {
+			*vptr++ = ']';
+			state = -1;
+		      }
+		  }
+	      }
+	    break;
+            }
+
+	  case 10:				/* 1,2 first is '.' */
+	    if (*fptr == '.')
+	      {
+		fptr++;
+		state = 11;
+	      }
+	    else
+	      state = 12;
+	    break;
+
+	  case 11:				/* 2, '..' at start */
+	    count = 1;
+	    if (*fptr != 0)
+	      {
+		if (*fptr != '/')		/* got ..xxx */
+		  {
+                    strcpy (vmsname, name);
+		    return vmsname;
+		  }
+		do				/* got ../ */
+		  {
+		    fptr++;
+		    while (*fptr == '/') fptr++;
+		    if (*fptr != '.')
+		      break;
+		    if (*(fptr+1) != '.')
+		      break;
+		    fptr += 2;
+		    if ((*fptr == 0)
+			|| (*fptr == '/'))
+		      count++;
+		  }
+		while (*fptr == '/');
+	      }
+	    {					/* got '..' or '../' */
+              char *vp;
+	      char cwdbuf[MAXPATHLEN+1];
+
+	      vp = getcwd(cwdbuf, MAXPATHLEN);
+	      if (vp == 0)
+		{
+                  vmsname[0] = '\0';
+		  return vmsname;    /* FIXME, err getcwd */
+		}
+	      strcpy (vptr, vp);
+	      vp = strchr (vptr, ']');
+	      if (vp != 0)
+		{
+		  nstate = N_OPEN;
+		  while (vp > vptr)
+		    {
+		      vp--;
+		      if (*vp == '[')
+			{
+			  vp++;
+			  strcpy (vp, "000000]");
+			  state = -1;
+			  break;
+			}
+		      else if (*vp == '.')
+			{
+			  if (--count == 0)
+			    {
+			      if (*fptr == 0)	/* had '..' or '../' */
+				{
+				  *vp++ = ']';
+				  state = -1;
+				}
+			      else			/* had '../xxx' */
+				{
+				  state = 9;
+				}
+			      *vp = '\0';
+			      break;
+			    }
+			}
+		    }
+		}
+	      vptr += strlen (vptr);
+	    }
+	    break;
+
+	  case 12:				/* 1, '.' at start */
+	    if (*fptr != 0)
+	      {
+		if (*fptr != '/')
+		  {
+                    strcpy (vmsname, name);
+		    return vmsname;
+		  }
+		while (*fptr == '/')
+		  fptr++;
+	      }
+
+	    {
+              char *vp;
+	      char cwdbuf[MAXPATHLEN+1];
+
+	      vp = getcwd(cwdbuf, MAXPATHLEN);
+	      if (vp == 0)
+		{
+                  vmsname[0] = '\0';
+		  return vmsname;    /*FIXME, err getcwd */
+		}
+	      strcpy (vptr, vp);
+            }
+            if (*fptr == 0)
+              {
+                state = -1;
+                break;
+              }
+            else
+              {
+                char *vp = strchr (vptr, ']');
+                if (vp == 0)
+                  {
+                    state = -1;
+                    break;
+                  }
+                *vp = '\0';
+                nstate = N_OPEN;
+                vptr += strlen (vptr);
+                state = 9;
+              }
+	    break;
+	}
+
+	}
+      while (state > 0);
+
+
+    }
+
+
+  /* directory conversion done
+     fptr -> filename part of input string
+     vptr -> free space in vmsname
+  */
+
+  *vptr++ = 0;
+
+  return vmsname;
+}
+
+
+
+/*
+  convert from vms-style to unix-style
+
+  dev:[dir1.dir2]	//dev/dir1/dir2/
+*/
+
+const char *
+unixify (const char *name)
+{
+  static char piece[512];
+  const char *s;
+  char *p;
+
+  if (strchr (name, '/') != 0)		/* already in unix style */
+    {
+      strcpy (piece, name);
+      return piece;
+    }
+
+  p = piece;
+  *p = 0;
+
+  /* device part */
+
+  s = strchr (name, ':');
+
+  if (s != 0)
+    {
+      int l = s - name;
+      *p++ = '/';
+      *p++ = '/';
+      strncpy (p, name, l);
+      p += l;
+    }
+
+  /* directory part */
+
+  *p++ = '/';
+  s = strchr (name, '[');
+
+  if (s != 0)
+    {
+      s++;
+      switch (*s)
+        {
+	  case ']':		/* [] */
+	    strcat (p, "./");
+	    break;
+	  case '-':		/* [- */
+	    strcat (p, "../");
+	    break;
+	  case '.':
+	    strcat (p, "./");	/* [. */
+	    break;
+	  default:
+	    s--;
+	    break;
+        }
+      s++;
+      while (*s)
+        {
+	  if (*s == '.')
+	    *p++ = '/';
+	  else
+	    *p++ = *s;
+	  s++;
+	  if (*s == ']')
+	    {
+	      s++;
+	      break;
+	    }
+        }
+      if (*s != 0)		/* more after ']' ?? */
+        {
+	  if (*(p-1) != '/')
+	    *p++ = '/';
+	  strcpy (p, s);		/* copy it anyway */
+        }
+    }
+
+  else		/* no '[' anywhere */
+
+    {
+      *p++ = 0;
+    }
+
+  /* force end with '/' */
+
+  if (*(p-1) != '/')
+    *p++ = '/';
+  *p = 0;
+
+  return piece;
+}
+
+/* EOF */
Index: /tags/kBuild-0.1.4/src/kmk/vmsjobs.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/vmsjobs.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/vmsjobs.c	(revision 1780)
@@ -0,0 +1,684 @@
+/* --------------- Moved here from job.c ---------------
+   This file must be #included in job.c, as it accesses static functions.
+
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include <string.h>
+#include <descrip.h>
+#include <clidef.h>
+
+char *vmsify (char *name, int type);
+
+static int vms_jobsefnmask = 0;
+
+/* Wait for nchildren children to terminate */
+static void
+vmsWaitForChildren(int *status)
+{
+  while (1)
+    {
+      if (!vms_jobsefnmask)
+	{
+	  *status = 0;
+	  return;
+	}
+
+      *status = sys$wflor (32, vms_jobsefnmask);
+    }
+  return;
+}
+
+/* Set up IO redirection.  */
+
+char *
+vms_redirect (struct dsc$descriptor_s *desc, char *fname, char *ibuf)
+{
+  char *fptr;
+
+  ibuf++;
+  while (isspace ((unsigned char)*ibuf))
+    ibuf++;
+  fptr = ibuf;
+  while (*ibuf && !isspace ((unsigned char)*ibuf))
+    ibuf++;
+  *ibuf = 0;
+  if (strcmp (fptr, "/dev/null") != 0)
+    {
+      strcpy (fname, vmsify (fptr, 0));
+      if (strchr (fname, '.') == 0)
+	strcat (fname, ".");
+    }
+  desc->dsc$w_length = strlen(fname);
+  desc->dsc$a_pointer = fname;
+  desc->dsc$b_dtype = DSC$K_DTYPE_T;
+  desc->dsc$b_class = DSC$K_CLASS_S;
+
+  if (*fname == 0)
+    printf (_("Warning: Empty redirection\n"));
+  return ibuf;
+}
+
+
+/* found apostrophe at (p-1)
+   inc p until after closing apostrophe.
+ */
+
+char *
+vms_handle_apos (char *p)
+{
+  int alast;
+
+#define SEPCHARS ",/()= "
+
+  alast = 0;
+
+  while (*p != 0)
+    {
+      if (*p == '"')
+	{
+          if (alast)
+            {
+              alast = 0;
+              p++;
+	    }
+	  else
+	    {
+	      p++;
+	      if (strchr (SEPCHARS, *p))
+		break;
+	      alast = 1;
+	    }
+	}
+      else
+	p++;
+    }
+
+  return p;
+}
+
+/* This is called as an AST when a child process dies (it won't get
+   interrupted by anything except a higher level AST).
+*/
+int
+vmsHandleChildTerm(struct child *child)
+{
+    int status;
+    register struct child *lastc, *c;
+    int child_failed;
+
+    vms_jobsefnmask &= ~(1 << (child->efn - 32));
+
+    lib$free_ef(&child->efn);
+
+    (void) sigblock (fatal_signal_mask);
+
+    child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));
+
+    /* Search for a child matching the deceased one.  */
+    lastc = 0;
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+    for (c = children; c != 0 && c != child; lastc = c, c = c->next)
+      ;
+#else
+    c = child;
+#endif
+
+    if (child_failed && !c->noerror && !ignore_errors_flag)
+      {
+	/* The commands failed.  Write an error message,
+	   delete non-precious targets, and abort.  */
+	child_error (c->file->name, c->cstatus, 0, 0, 0);
+	c->file->update_status = 1;
+	delete_child_targets (c);
+      }
+    else
+      {
+	if (child_failed)
+	  {
+	    /* The commands failed, but we don't care.  */
+	    child_error (c->file->name, c->cstatus, 0, 0, 1);
+	    child_failed = 0;
+	  }
+
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+	/* If there are more commands to run, try to start them.  */
+	start_job (c);
+
+	switch (c->file->command_state)
+	  {
+	  case cs_running:
+	    /* Successfully started.  */
+	    break;
+
+	  case cs_finished:
+	    if (c->file->update_status != 0) {
+		/* We failed to start the commands.  */
+		delete_child_targets (c);
+	    }
+	    break;
+
+	  default:
+	    error (NILF, _("internal error: `%s' command_state"),
+                   c->file->name);
+	    abort ();
+	    break;
+	  }
+#endif /* RECURSIVEJOBS */
+      }
+
+    /* Set the state flag to say the commands have finished.  */
+    c->file->command_state = cs_finished;
+    notice_finished_file (c->file);
+
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+    /* Remove the child from the chain and free it.  */
+    if (lastc == 0)
+      children = c->next;
+    else
+      lastc->next = c->next;
+    free_child (c);
+#endif /* RECURSIVEJOBS */
+
+    /* There is now another slot open.  */
+    if (job_slots_used > 0)
+      --job_slots_used;
+
+    /* If the job failed, and the -k flag was not given, die.  */
+    if (child_failed && !keep_going_flag)
+      die (EXIT_FAILURE);
+
+    (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));
+
+    return 1;
+}
+
+/* VMS:
+   Spawn a process executing the command in ARGV and return its pid. */
+
+#define MAXCMDLEN 200
+
+/* local helpers to make ctrl+c and ctrl+y working, see below */
+#include <iodef.h>
+#include <libclidef.h>
+#include <ssdef.h>
+
+static int ctrlMask= LIB$M_CLI_CTRLY;
+static int oldCtrlMask;
+static int setupYAstTried= 0;
+static int pidToAbort= 0;
+static int chan= 0;
+
+static void
+reEnableAst(void)
+{
+	lib$enable_ctrl (&oldCtrlMask,0);
+}
+
+static void
+astHandler (void)
+{
+	if (pidToAbort) {
+		sys$forcex (&pidToAbort, 0, SS$_ABORT);
+		pidToAbort= 0;
+	}
+	kill (getpid(),SIGQUIT);
+}
+
+static void
+tryToSetupYAst(void)
+{
+	$DESCRIPTOR(inputDsc,"SYS$COMMAND");
+	int	status;
+	struct {
+		short int	status, count;
+		int	dvi;
+	} iosb;
+
+	setupYAstTried++;
+
+	if (!chan) {
+		status= sys$assign(&inputDsc,&chan,0,0);
+		if (!(status&SS$_NORMAL)) {
+			lib$signal(status);
+			return;
+		}
+	}
+	status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
+		astHandler,0,0,0,0,0);
+	if (status==SS$_NORMAL)
+		status= iosb.status;
+        if (status==SS$_ILLIOFUNC || status==SS$_NOPRIV) {
+		sys$dassgn(chan);
+#ifdef	CTRLY_ENABLED_ANYWAY
+		fprintf (stderr,
+                         _("-warning, CTRL-Y will leave sub-process(es) around.\n"));
+#else
+		return;
+#endif
+	}
+	else if (!(status&SS$_NORMAL)) {
+		sys$dassgn(chan);
+		lib$signal(status);
+		return;
+	}
+
+	/* called from AST handler ? */
+	if (setupYAstTried>1)
+		return;
+	if (atexit(reEnableAst))
+		fprintf (stderr,
+                         _("-warning, you may have to re-enable CTRL-Y handling from DCL.\n"));
+	status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);
+	if (!(status&SS$_NORMAL)) {
+		lib$signal(status);
+		return;
+	}
+}
+
+int
+child_execute_job (char *argv, struct child *child)
+{
+  int i;
+  static struct dsc$descriptor_s cmddsc;
+  static struct dsc$descriptor_s pnamedsc;
+  static struct dsc$descriptor_s ifiledsc;
+  static struct dsc$descriptor_s ofiledsc;
+  static struct dsc$descriptor_s efiledsc;
+  int have_redirection = 0;
+  int have_newline = 0;
+
+  int spflags = CLI$M_NOWAIT;
+  int status;
+  char *cmd = alloca (strlen (argv) + 512), *p, *q;
+  char ifile[256], ofile[256], efile[256];
+  char *comname = 0;
+  char procname[100];
+  int in_string;
+
+  /* Parse IO redirection.  */
+
+  ifile[0] = 0;
+  ofile[0] = 0;
+  efile[0] = 0;
+
+  DB (DB_JOBS, ("child_execute_job (%s)\n", argv));
+
+  while (isspace ((unsigned char)*argv))
+    argv++;
+
+  if (*argv == 0)
+    return 0;
+
+  sprintf (procname, "GMAKE_%05x", getpid () & 0xfffff);
+  pnamedsc.dsc$w_length = strlen(procname);
+  pnamedsc.dsc$a_pointer = procname;
+  pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;
+  pnamedsc.dsc$b_class = DSC$K_CLASS_S;
+
+  in_string = 0;
+  /* Handle comments and redirection. */
+  for (p = argv, q = cmd; *p; p++, q++)
+    {
+      if (*p == '"')
+        in_string = !in_string;
+      if (in_string)
+        {
+          *q = *p;
+          continue;
+        }
+      switch (*p)
+	{
+	  case '#':
+	    *p-- = 0;
+	    *q-- = 0;
+	    break;
+	  case '\\':
+	    p++;
+	    if (*p == '\n')
+	      p++;
+	    if (isspace ((unsigned char)*p))
+	      {
+		do { p++; } while (isspace ((unsigned char)*p));
+		p--;
+	      }
+	    *q = *p;
+	    break;
+	  case '<':
+	    p = vms_redirect (&ifiledsc, ifile, p);
+	    *q = ' ';
+	    have_redirection = 1;
+	    break;
+	  case '>':
+	    have_redirection = 1;
+	    if (*(p-1) == '2')
+	      {
+		q--;
+		if (strncmp (p, ">&1", 3) == 0)
+		  {
+		    p += 3;
+		    strcpy (efile, "sys$output");
+		    efiledsc.dsc$w_length = strlen(efile);
+		    efiledsc.dsc$a_pointer = efile;
+		    efiledsc.dsc$b_dtype = DSC$K_DTYPE_T;
+		    efiledsc.dsc$b_class = DSC$K_CLASS_S;
+		  }
+		else
+		  {
+		    p = vms_redirect (&efiledsc, efile, p);
+		  }
+	      }
+	    else
+	      {
+		p = vms_redirect (&ofiledsc, ofile, p);
+	      }
+	    *q = ' ';
+	    break;
+	  case '\n':
+	    have_newline = 1;
+	  default:
+	    *q = *p;
+	    break;
+	}
+    }
+  *q = *p;
+  while (isspace ((unsigned char)*--q))
+    *q = '\0';
+
+  if (strncmp (cmd, "builtin_", 8) == 0)
+    {
+      child->pid = 270163;
+      child->efn = 0;
+      child->cstatus = 1;
+
+      DB (DB_JOBS, (_("BUILTIN [%s][%s]\n"), cmd, cmd+8));
+
+      p = cmd + 8;
+
+      if ((*(p) == 'c')
+	  && (*(p+1) == 'd')
+	  && ((*(p+2) == ' ') || (*(p+2) == '\t')))
+	{
+	  p += 3;
+	  while ((*p == ' ') || (*p == '\t'))
+	    p++;
+	  DB (DB_JOBS, (_("BUILTIN CD %s\n"), p));
+	  if (chdir (p))
+	    return 0;
+	  else
+	    return 1;
+	}
+      else if ((*(p) == 'r')
+	  && (*(p+1) == 'm')
+	  && ((*(p+2) == ' ') || (*(p+2) == '\t')))
+	{
+	  int in_arg;
+
+	  /* rm  */
+	  p += 3;
+	  while ((*p == ' ') || (*p == '\t'))
+	    p++;
+	  in_arg = 1;
+
+	  DB (DB_JOBS, (_("BUILTIN RM %s\n"), p));
+	  while (*p)
+	    {
+	      switch (*p)
+		{
+		  case ' ':
+		  case '\t':
+		    if (in_arg)
+		      {
+			*p++ = ';';
+			in_arg = 0;
+		      }
+		    break;
+		  default:
+		    break;
+		}
+	      p++;
+	    }
+	}
+      else
+	{
+	  printf(_("Unknown builtin command '%s'\n"), cmd);
+	  fflush(stdout);
+	  return 0;
+	}
+    }
+
+  /* Create a *.com file if either the command is too long for
+     lib$spawn, or the command contains a newline, or if redirection
+     is desired. Forcing commands with newlines into DCLs allows to
+     store search lists on user mode logicals.  */
+
+  if (strlen (cmd) > MAXCMDLEN
+      || (have_redirection != 0)
+      || (have_newline != 0))
+    {
+      FILE *outfile;
+      char c;
+      char *sep;
+      int alevel = 0;	/* apostrophe level */
+
+      if (strlen (cmd) == 0)
+	{
+	  printf (_("Error, empty command\n"));
+	  fflush (stdout);
+	  return 0;
+	}
+
+      outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM");
+      if (outfile == 0)
+	pfatal_with_name (_("fopen (temporary file)"));
+
+      if (ifile[0])
+	{
+	  fprintf (outfile, "$ assign/user %s sys$input\n", ifile);
+          DB (DB_JOBS, (_("Redirected input from %s\n"), ifile));
+	  ifiledsc.dsc$w_length = 0;
+	}
+
+      if (efile[0])
+	{
+	  fprintf (outfile, "$ define sys$error %s\n", efile);
+          DB (DB_JOBS, (_("Redirected error to %s\n"), efile));
+	  efiledsc.dsc$w_length = 0;
+	}
+
+      if (ofile[0])
+	{
+	  fprintf (outfile, "$ define sys$output %s\n", ofile);
+	  DB (DB_JOBS, (_("Redirected output to %s\n"), ofile));
+	  ofiledsc.dsc$w_length = 0;
+	}
+
+      p = sep = q = cmd;
+      for (c = '\n'; c; c = *q++)
+	{
+	  switch (c)
+	    {
+            case '\n':
+              /* At a newline, skip any whitespace around a leading $
+                 from the command and issue exactly one $ into the DCL. */
+              while (isspace ((unsigned char)*p))
+                p++;
+              if (*p == '$')
+                p++;
+              while (isspace ((unsigned char)*p))
+                p++;
+              fwrite (p, 1, q - p, outfile);
+              fputc ('$', outfile);
+              fputc (' ', outfile);
+              /* Reset variables. */
+              p = sep = q;
+              break;
+
+	      /* Nice places for line breaks are after strings, after
+		 comma or space and before slash. */
+            case '"':
+              q = vms_handle_apos (q);
+              sep = q;
+              break;
+            case ',':
+            case ' ':
+              sep = q;
+              break;
+            case '/':
+            case '\0':
+              sep = q - 1;
+              break;
+            default:
+              break;
+	    }
+	  if (sep - p > 78)
+	    {
+	      /* Enough stuff for a line. */
+	      fwrite (p, 1, sep - p, outfile);
+	      p = sep;
+	      if (*sep)
+		{
+		  /* The command continues.  */
+		  fputc ('-', outfile);
+		}
+	      fputc ('\n', outfile);
+	    }
+  	}
+
+      fwrite (p, 1, q - p, outfile);
+      fputc ('\n', outfile);
+
+      fclose (outfile);
+
+      sprintf (cmd, "$ @%s", comname);
+
+      DB (DB_JOBS, (_("Executing %s instead\n"), cmd));
+    }
+
+  cmddsc.dsc$w_length = strlen(cmd);
+  cmddsc.dsc$a_pointer = cmd;
+  cmddsc.dsc$b_dtype = DSC$K_DTYPE_T;
+  cmddsc.dsc$b_class = DSC$K_CLASS_S;
+
+  child->efn = 0;
+  while (child->efn < 32 || child->efn > 63)
+    {
+      status = lib$get_ef ((unsigned long *)&child->efn);
+      if (!(status & 1))
+	return 0;
+    }
+
+  sys$clref (child->efn);
+
+  vms_jobsefnmask |= (1 << (child->efn - 32));
+
+/*
+             LIB$SPAWN  [command-string]
+			[,input-file]
+			[,output-file]
+			[,flags]
+			[,process-name]
+			[,process-id] [,completion-status-address] [,byte-integer-event-flag-num]
+			[,AST-address] [,varying-AST-argument]
+			[,prompt-string] [,cli] [,table]
+*/
+
+#ifndef DONTWAITFORCHILD
+/*
+ *	Code to make ctrl+c and ctrl+y working.
+ *	The problem starts with the synchronous case where after lib$spawn is
+ *	called any input will go to the child. But with input re-directed,
+ *	both control characters won't make it to any of the programs, neither
+ *	the spawning nor to the spawned one. Hence the caller needs to spawn
+ *	with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr
+ *	has to follow to simulate the wanted synchronous behaviour.
+ *	The next problem is ctrl+y which isn't caught by the crtl and
+ *	therefore isn't converted to SIGQUIT (for a signal handler which is
+ *	already established). The only way to catch ctrl+y, is an AST
+ *	assigned to the input channel. But ctrl+y handling of DCL needs to be
+ *	disabled, otherwise it will handle it. Not to mention the previous
+ *	ctrl+y handling of DCL needs to be re-established before make exits.
+ *	One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will
+ *	make it to the signal handler after the child "normally" terminates.
+ *	This isn't enough. It seems reasonable for simple command lines like
+ *	a 'cc foobar.c' spawned in a subprocess but it is unacceptable for
+ *	spawning make. Therefore we need to abort the process in the AST.
+ *
+ *	Prior to the spawn it is checked if an AST is already set up for
+ *	ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general
+ *	this will work except if make is run in a batch environment, but there
+ *	nobody can press ctrl+y. During the setup the DCL handling of ctrl+y
+ *	is disabled and an exit handler is established to re-enable it.
+ *	If the user interrupts with ctrl+y, the assigned AST will fire, force
+ *	an abort to the subprocess and signal SIGQUIT, which will be caught by
+ *	the already established handler and will bring us back to common code.
+ *	After the spawn (now /nowait) a sys$waitfr simulates the /wait and
+ *	enables the ctrl+y be delivered to this code. And the ctrl+c too,
+ *	which the crtl converts to SIGINT and which is caught by the common
+ *	signal handler. Because signals were blocked before entering this code
+ *	sys$waitfr will always complete and the SIGQUIT will be processed after
+ *	it (after termination of the current block, somewhere in common code).
+ *	And SIGINT too will be delayed. That is ctrl+c can only abort when the
+ *	current command completes. Anyway it's better than nothing :-)
+ */
+
+  if (!setupYAstTried)
+    tryToSetupYAst();
+  status = lib$spawn (&cmddsc,					/* cmd-string  */
+		      (ifiledsc.dsc$w_length == 0)?0:&ifiledsc, /* input-file  */
+		      (ofiledsc.dsc$w_length == 0)?0:&ofiledsc, /* output-file */
+		      &spflags,					/* flags  */
+		      &pnamedsc,				/* proc name  */
+		      &child->pid, &child->cstatus, &child->efn,
+		      0, 0,
+		      0, 0, 0);
+  if (status & 1)
+    {
+      pidToAbort= child->pid;
+      status= sys$waitfr (child->efn);
+      pidToAbort= 0;
+      vmsHandleChildTerm(child);
+    }
+#else
+  status = lib$spawn (&cmddsc,
+		      (ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
+		      (ofiledsc.dsc$w_length == 0)?0:&ofiledsc,
+		      &spflags,
+		      &pnamedsc,
+		      &child->pid, &child->cstatus, &child->efn,
+		      vmsHandleChildTerm, child,
+		      0, 0, 0);
+#endif
+
+  if (!(status & 1))
+    {
+      printf (_("Error spawning, %d\n") ,status);
+      fflush (stdout);
+      switch (status)
+        {
+        case 0x1c:
+          errno = EPROCLIM;
+          break;
+        default:
+          errno = EFAIL;
+        }
+    }
+
+  if (comname && !ISDB (DB_JOBS))
+    unlink (comname);
+
+  return (status & 1);
+}
Index: /tags/kBuild-0.1.4/src/kmk/vpath.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/vpath.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/vpath.c	(revision 1780)
@@ -0,0 +1,600 @@
+/* Implementation of pattern-matching file search paths for GNU Make.
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include "make.h"
+#include "filedef.h"
+#include "variable.h"
+#ifdef WINDOWS32
+#include "pathstuff.h"
+#endif
+
+
+/* Structure used to represent a selective VPATH searchpath.  */
+
+struct vpath
+  {
+    struct vpath *next;	/* Pointer to next struct in the linked list.  */
+    const char *pattern;/* The pattern to match.  */
+    const char *percent;/* Pointer into `pattern' where the `%' is.  */
+    unsigned int patlen;/* Length of the pattern.  */
+    const char **searchpath; /* Null-terminated list of directories.  */
+    unsigned int maxlen;/* Maximum length of any entry in the list.  */
+  };
+
+/* Linked-list of all selective VPATHs.  */
+
+static struct vpath *vpaths;
+
+/* Structure for the general VPATH given in the variable.  */
+
+static struct vpath *general_vpath;
+
+/* Structure for GPATH given in the variable.  */
+
+static struct vpath *gpaths;
+
+
+
+/* Reverse the chain of selective VPATH lists so they will be searched in the
+   order given in the makefiles and construct the list from the VPATH
+   variable.  */
+
+void
+build_vpath_lists ()
+{
+  register struct vpath *new = 0;
+  register struct vpath *old, *nexto;
+  register char *p;
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+  char expr[64];
+#endif 
+
+  /* Reverse the chain.  */
+  for (old = vpaths; old != 0; old = nexto)
+    {
+      nexto = old->next;
+      old->next = new;
+      new = old;
+    }
+
+  vpaths = new;
+
+  /* If there is a VPATH variable with a nonnull value, construct the
+     general VPATH list from it.  We use variable_expand rather than just
+     calling lookup_variable so that it will be recursively expanded.  */
+
+  {
+    /* Turn off --warn-undefined-variables while we expand SHELL and IFS.  */
+    int save = warn_undefined_variables_flag;
+    warn_undefined_variables_flag = 0;
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+    p = variable_expand (strcpy (expr, "$(strip $(VPATH))"));
+#else
+    p = variable_expand ("$(strip $(VPATH))");
+#endif 
+
+    warn_undefined_variables_flag = save;
+  }
+
+  if (*p != '\0')
+    {
+      /* Save the list of vpaths.  */
+      struct vpath *save_vpaths = vpaths;
+      char gp[] = "%";
+
+      /* Empty `vpaths' so the new one will have no next, and `vpaths'
+	 will still be nil if P contains no existing directories.  */
+      vpaths = 0;
+
+      /* Parse P.  */
+      construct_vpath_list (gp, p);
+
+      /* Store the created path as the general path,
+	 and restore the old list of vpaths.  */
+      general_vpath = vpaths;
+      vpaths = save_vpaths;
+    }
+
+  /* If there is a GPATH variable with a nonnull value, construct the
+     GPATH list from it.  We use variable_expand rather than just
+     calling lookup_variable so that it will be recursively expanded.  */
+
+  {
+    /* Turn off --warn-undefined-variables while we expand SHELL and IFS.  */
+    int save = warn_undefined_variables_flag;
+    warn_undefined_variables_flag = 0;
+
+#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+    p = variable_expand (strcpy (expr, "$(strip $(GPATH))"));
+#else
+    p = variable_expand ("$(strip $(GPATH))");
+#endif 
+
+    warn_undefined_variables_flag = save;
+  }
+
+  if (*p != '\0')
+    {
+      /* Save the list of vpaths.  */
+      struct vpath *save_vpaths = vpaths;
+      char gp[] = "%";
+
+      /* Empty `vpaths' so the new one will have no next, and `vpaths'
+	 will still be nil if P contains no existing directories.  */
+      vpaths = 0;
+
+      /* Parse P.  */
+      construct_vpath_list (gp, p);
+
+      /* Store the created path as the GPATH,
+	 and restore the old list of vpaths.  */
+      gpaths = vpaths;
+      vpaths = save_vpaths;
+    }
+}
+
+
+/* Construct the VPATH listing for the pattern and searchpath given.
+
+   This function is called to generate selective VPATH lists and also for
+   the general VPATH list (which is in fact just a selective VPATH that
+   is applied to everything).  The returned pointer is either put in the
+   linked list of all selective VPATH lists or in the GENERAL_VPATH
+   variable.
+
+   If SEARCHPATH is nil, remove all previous listings with the same
+   pattern.  If PATTERN is nil, remove all VPATH listings.  Existing
+   and readable directories that are not "." given in the searchpath
+   separated by the path element separator (defined in make.h) are
+   loaded into the directory hash table if they are not there already
+   and put in the VPATH searchpath for the given pattern with trailing
+   slashes stripped off if present (and if the directory is not the
+   root, "/").  The length of the longest entry in the list is put in
+   the structure as well.  The new entry will be at the head of the
+   VPATHS chain.  */
+
+void
+construct_vpath_list (char *pattern, char *dirpath)
+{
+  unsigned int elem;
+  char *p;
+  const char **vpath;
+  unsigned int maxvpath;
+  unsigned int maxelem;
+  const char *percent = NULL;
+
+  if (pattern != 0)
+    percent = find_percent (pattern);
+
+  if (dirpath == 0)
+    {
+      /* Remove matching listings.  */
+      struct vpath *path, *lastpath;
+
+      lastpath = 0;
+      path = vpaths;
+      while (path != 0)
+	{
+	  struct vpath *next = path->next;
+
+	  if (pattern == 0
+	      || (((percent == 0 && path->percent == 0)
+		   || (percent - pattern == path->percent - path->pattern))
+		  && streq (pattern, path->pattern)))
+	    {
+	      /* Remove it from the linked list.  */
+	      if (lastpath == 0)
+		vpaths = path->next;
+	      else
+		lastpath->next = next;
+
+	      /* Free its unused storage.  */
+	      free (path->searchpath);
+	      free (path);
+	    }
+	  else
+	    lastpath = path;
+
+	  path = next;
+	}
+
+      return;
+    }
+
+#ifdef WINDOWS32
+    convert_vpath_to_windows32(dirpath, ';');
+#endif
+
+  /* Skip over any initial separators and blanks.  */
+  while (*dirpath == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*dirpath))
+    ++dirpath;
+
+  /* Figure out the maximum number of VPATH entries and put it in
+     MAXELEM.  We start with 2, one before the first separator and one
+     nil (the list terminator) and increment our estimated number for
+     each separator or blank we find.  */
+  maxelem = 2;
+  p = dirpath;
+  while (*p != '\0')
+    if (*p++ == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
+      ++maxelem;
+
+  vpath = xmalloc (maxelem * sizeof (const char *));
+  maxvpath = 0;
+
+  elem = 0;
+  p = dirpath;
+  while (*p != '\0')
+    {
+      char *v;
+      unsigned int len;
+
+      /* Find the end of this entry.  */
+      v = p;
+      while (*p != '\0' && *p != PATH_SEPARATOR_CHAR
+	     && !isblank ((unsigned char)*p))
+	++p;
+
+      len = p - v;
+      /* Make sure there's no trailing slash,
+	 but still allow "/" as a directory.  */
+#if defined(__MSDOS__) || defined(__EMX__)
+      /* We need also to leave alone a trailing slash in "d:/".  */
+      if (len > 3 || (len > 1 && v[1] != ':'))
+#endif
+      if (len > 1 && p[-1] == '/')
+	--len;
+
+      /* Put the directory on the vpath list.  */
+      if (len > 1 || *v != '.')
+	{
+          vpath[elem++] = dir_name (strcache_add_len (v, len));
+          if (len > maxvpath)
+            maxvpath = len;
+	}
+
+      /* Skip over separators and blanks between entries.  */
+      while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p))
+	++p;
+    }
+
+  if (elem > 0)
+    {
+      struct vpath *path;
+      /* ELEM is now incremented one element past the last
+	 entry, to where the nil-pointer terminator goes.
+	 Usually this is maxelem - 1.  If not, shrink down.  */
+      if (elem < (maxelem - 1))
+	vpath = xrealloc (vpath, (elem+1) * sizeof (const char *));
+
+      /* Put the nil-pointer terminator on the end of the VPATH list.  */
+      vpath[elem] = NULL;
+
+      /* Construct the vpath structure and put it into the linked list.  */
+      path = xmalloc (sizeof (struct vpath));
+      path->searchpath = vpath;
+      path->maxlen = maxvpath;
+      path->next = vpaths;
+      vpaths = path;
+
+      /* Set up the members.  */
+      path->pattern = strcache_add (pattern);
+      path->patlen = strlen (pattern);
+      path->percent = percent ? path->pattern + (percent - pattern) : 0;
+    }
+  else
+    /* There were no entries, so free whatever space we allocated.  */
+    free (vpath);
+}
+
+
+/* Search the GPATH list for a pathname string that matches the one passed
+   in.  If it is found, return 1.  Otherwise we return 0.  */
+
+int
+gpath_search (const char *file, unsigned int len)
+{
+  const char **gp;
+
+  if (gpaths && (len <= gpaths->maxlen))
+    for (gp = gpaths->searchpath; *gp != NULL; ++gp)
+      if (strneq (*gp, file, len) && (*gp)[len] == '\0')
+        return 1;
+
+  return 0;
+}
+
+
+
+/* Search the given VPATH list for a directory where the name pointed to by
+   FILE exists.  If it is found, we return a cached name of the existing file
+   and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
+   stat call was done).  Otherwise we return NULL.  */
+
+static const char *
+selective_vpath_search (struct vpath *path, const char *file,
+                        FILE_TIMESTAMP *mtime_ptr)
+{
+  int not_target;
+  char *name;
+  const char *n;
+  const char *filename;
+  const char **vpath = path->searchpath;
+  unsigned int maxvpath = path->maxlen;
+  unsigned int i;
+  unsigned int flen, vlen, name_dplen;
+  int exists = 0;
+
+  /* Find out if *FILE is a target.
+     If and only if it is NOT a target, we will accept prospective
+     files that don't exist but are mentioned in a makefile.  */
+  {
+    struct file *f = lookup_file (file);
+    not_target = f == 0 || !f->is_target;
+  }
+
+  flen = strlen (file);
+
+  /* Split *FILE into a directory prefix and a name-within-directory.
+     NAME_DPLEN gets the length of the prefix; FILENAME gets the pointer to
+     the name-within-directory and FLEN is its length.  */
+
+  n = strrchr (file, '/');
+#ifdef HAVE_DOS_PATHS
+  /* We need the rightmost slash or backslash.  */
+  {
+    const char *bslash = strrchr(file, '\\');
+    if (!n || bslash > n)
+      n = bslash;
+  }
+#endif
+  name_dplen = n != 0 ? n - file : 0;
+  filename = name_dplen > 0 ? n + 1 : file;
+  if (name_dplen > 0)
+    flen -= name_dplen + 1;
+
+  /* Get enough space for the biggest VPATH entry, a slash, the directory
+     prefix that came with FILE, another slash (although this one may not
+     always be necessary), the filename, and a null terminator.  */
+  name = alloca (maxvpath + 1 + name_dplen + 1 + flen + 1);
+
+  /* Try each VPATH entry.  */
+  for (i = 0; vpath[i] != 0; ++i)
+    {
+      int exists_in_cache = 0;
+      char *p;
+
+      p = name;
+
+      /* Put the next VPATH entry into NAME at P and increment P past it.  */
+      vlen = strlen (vpath[i]);
+      memcpy (p, vpath[i], vlen);
+      p += vlen;
+
+      /* Add the directory prefix already in *FILE.  */
+      if (name_dplen > 0)
+	{
+#ifndef VMS
+	  *p++ = '/';
+#endif
+	  memcpy (p, file, name_dplen);
+	  p += name_dplen;
+	}
+
+#ifdef HAVE_DOS_PATHS
+      /* Cause the next if to treat backslash and slash alike.  */
+      if (p != name && p[-1] == '\\' )
+	p[-1] = '/';
+#endif
+      /* Now add the name-within-directory at the end of NAME.  */
+#ifndef VMS
+      if (p != name && p[-1] != '/')
+	{
+	  *p = '/';
+	  memcpy (p + 1, filename, flen + 1);
+	}
+      else
+#endif
+	memcpy (p, filename, flen + 1);
+
+      /* Check if the file is mentioned in a makefile.  If *FILE is not
+	 a target, that is enough for us to decide this file exists.
+	 If *FILE is a target, then the file must be mentioned in the
+	 makefile also as a target to be chosen.
+
+	 The restriction that *FILE must not be a target for a
+	 makefile-mentioned file to be chosen was added by an
+	 inadequately commented change in July 1990; I am not sure off
+	 hand what problem it fixes.
+
+	 In December 1993 I loosened this restriction to allow a file
+	 to be chosen if it is mentioned as a target in a makefile.  This
+	 seem logical.
+
+         Special handling for -W / -o: make sure we preserve the special
+         values here.  Actually this whole thing is a little bogus: I think
+         we should ditch the name/hname thing and look into the renamed
+         capability that already exists for files: that is, have a new struct
+         file* entry for the VPATH-found file, and set the renamed field if
+         we use it.
+      */
+      {
+	struct file *f = lookup_file (name);
+	if (f != 0)
+          {
+            exists = not_target || f->is_target;
+            if (exists && mtime_ptr
+                && (f->last_mtime == OLD_MTIME || f->last_mtime == NEW_MTIME))
+              {
+                *mtime_ptr = f->last_mtime;
+                mtime_ptr = 0;
+              }
+          }
+      }
+
+      if (!exists)
+	{
+	  /* That file wasn't mentioned in the makefile.
+	     See if it actually exists.  */
+
+#ifdef VMS
+	  exists_in_cache = exists = dir_file_exists_p (vpath[i], filename);
+#else
+	  /* Clobber a null into the name at the last slash.
+	     Now NAME is the name of the directory to look in.  */
+	  *p = '\0';
+
+	  /* We know the directory is in the hash table now because either
+	     construct_vpath_list or the code just above put it there.
+	     Does the file we seek exist in it?  */
+	  exists_in_cache = exists = dir_file_exists_p (name, filename);
+#endif
+	}
+
+      if (exists)
+	{
+	  /* The file is in the directory cache.
+	     Now check that it actually exists in the filesystem.
+	     The cache may be out of date.  When vpath thinks a file
+	     exists, but stat fails for it, confusion results in the
+	     higher levels.  */
+
+	  struct stat st;
+
+#ifndef VMS
+	  /* Put the slash back in NAME.  */
+	  *p = '/';
+#endif
+
+	  if (exists_in_cache)	/* Makefile-mentioned file need not exist.  */
+	    {
+              int e;
+
+              EINTRLOOP (e, stat (name, &st)); /* Does it really exist?  */
+              if (e != 0)
+                {
+                  exists = 0;
+                  continue;
+                }
+
+              /* Store the modtime into *MTIME_PTR for the caller.  */
+              if (mtime_ptr != 0)
+                {
+                  *mtime_ptr = FILE_TIMESTAMP_STAT_MODTIME (name, st);
+                  mtime_ptr = 0;
+                }
+            }
+
+          /* We have found a file.
+             If we get here and mtime_ptr hasn't been set, record
+             UNKNOWN_MTIME to indicate this.  */
+          if (mtime_ptr != 0)
+            *mtime_ptr = UNKNOWN_MTIME;
+
+          /* Store the name we found and return it.  */
+
+          return strcache_add_len (name, (p + 1 - name) + flen);
+	}
+    }
+
+  return 0;
+}
+
+
+/* Search the VPATH list whose pattern matches FILE for a directory where FILE
+   exists.  If it is found, return the cached name of an existing file, and
+   set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
+   stat call was done).  Otherwise we return 0.  */
+
+const char *
+vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr)
+{
+  struct vpath *v;
+
+  /* If there are no VPATH entries or FILENAME starts at the root,
+     there is nothing we can do.  */
+
+  if (file[0] == '/'
+#ifdef HAVE_DOS_PATHS
+      || file[0] == '\\' || file[1] == ':'
+#endif
+      || (vpaths == 0 && general_vpath == 0))
+    return 0;
+
+  for (v = vpaths; v != 0; v = v->next)
+    if (pattern_matches (v->pattern, v->percent, file))
+      {
+        const char *p = selective_vpath_search (v, file, mtime_ptr);
+        if (p)
+          return p;
+      }
+
+  if (general_vpath != 0)
+    {
+      const char *p = selective_vpath_search (general_vpath, file, mtime_ptr);
+      if (p)
+        return p;
+    }
+
+  return 0;
+}
+
+
+/* Print the data base of VPATH search paths.  */
+
+void
+print_vpath_data_base (void)
+{
+  unsigned int nvpaths;
+  struct vpath *v;
+
+  puts (_("\n# VPATH Search Paths\n"));
+
+  nvpaths = 0;
+  for (v = vpaths; v != 0; v = v->next)
+    {
+      register unsigned int i;
+
+      ++nvpaths;
+
+      printf ("vpath %s ", v->pattern);
+
+      for (i = 0; v->searchpath[i] != 0; ++i)
+	printf ("%s%c", v->searchpath[i],
+		v->searchpath[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR);
+    }
+
+  if (vpaths == 0)
+    puts (_("# No `vpath' search paths."));
+  else
+    printf (_("\n# %u `vpath' search paths.\n"), nvpaths);
+
+  if (general_vpath == 0)
+    puts (_("\n# No general (`VPATH' variable) search path."));
+  else
+    {
+      const char **path = general_vpath->searchpath;
+      unsigned int i;
+
+      fputs (_("\n# General (`VPATH' variable) search path:\n# "), stdout);
+
+      for (i = 0; path[i] != 0; ++i)
+	printf ("%s%c", path[i],
+		path[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR);
+    }
+}
Index: /tags/kBuild-0.1.4/src/kmk/w32/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/Makefile.am	(revision 1780)
@@ -0,0 +1,23 @@
+# Makefile.am to create libw32.a for mingw32 host.
+# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+noinst_LIBRARIES = libw32.a
+
+libw32_a_SOURCES =  subproc/misc.c subproc/sub_proc.c subproc/w32err.c \
+		    pathstuff.c
+
+libw32_a_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/subproc -I$(top_srcdir)
Index: /tags/kBuild-0.1.4/src/kmk/w32/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/Makefile.kmk	(revision 1780)
@@ -0,0 +1,38 @@
+# $Id: Makefile.kmk 785 2007-01-24 22:21:56Z bird $
+## @file
+# Sub-makefile for tstFileInfo / w32.
+#
+
+#
+# Copyright (c) 2007-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# tstFileInfo
+#
+PROGRAMS.win += tstFileInfo
+tstFileInfo_TEMPLATE = BIN
+tstFileInfo_SOURCES = tstFileInfo.c
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
Index: /tags/kBuild-0.1.4/src/kmk/w32/compat/dirent.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/compat/dirent.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/compat/dirent.c	(revision 1780)
@@ -0,0 +1,215 @@
+/* Directory entry code for Window platforms.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+
+#ifdef KMK
+# include "config.h" /* my_stat */
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef KMK_PRF
+# include <stdio.h>
+#endif
+#include "dirent.h"
+
+
+DIR*
+opendir(const char* pDirName)
+{
+	struct stat sb;
+	DIR*	pDir;
+	char*	pEndDirName;
+	int	nBufferLen;
+
+	/* sanity checks */
+	if (!pDirName) {
+		errno = EINVAL;
+		return NULL;
+	}
+	if (stat(pDirName, &sb) != 0) {
+		errno = ENOENT;
+		return NULL;
+	}
+	if ((sb.st_mode & S_IFMT) != S_IFDIR) {
+		errno = ENOTDIR;
+		return NULL;
+	}
+
+	/* allocate a DIR structure to return */
+	pDir = (DIR *) malloc(sizeof (DIR));
+
+	if (!pDir)
+		return NULL;
+
+	/* input directory name length */
+	nBufferLen = strlen(pDirName);
+
+	/* copy input directory name to DIR buffer */
+	strcpy(pDir->dir_pDirectoryName, pDirName);
+
+	/* point to end of the copied directory name */
+	pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];
+
+	/* if directory name did not end in '/' or '\', add '/' */
+	if ((*pEndDirName != '/') && (*pEndDirName != '\\')) {
+		pEndDirName++;
+		*pEndDirName = '/';
+	}
+
+	/* now append the wildcard character to the buffer */
+	pEndDirName++;
+	*pEndDirName = '*';
+	pEndDirName++;
+	*pEndDirName = '\0';
+
+	/* other values defaulted */
+	pDir->dir_nNumFiles = 0;
+	pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
+	pDir->dir_ulCookie = __DIRENT_COOKIE;
+
+#ifdef KMK_PRF
+	fprintf(stderr, "opendir(%s) -> %p\n", pDirName, pDir);
+#endif
+	return pDir;
+}
+
+void
+closedir(DIR *pDir)
+{
+	/* got a valid pointer? */
+	if (!pDir) {
+		errno = EINVAL;
+		return;
+	}
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
+		errno = EINVAL;
+		return;
+	}
+
+	/* close the WINDOWS32 directory handle */
+	if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
+		FindClose(pDir->dir_hDirHandle);
+
+	free(pDir);
+
+	return;
+}
+
+struct dirent *
+readdir(DIR* pDir)
+{
+	WIN32_FIND_DATA wfdFindData;
+
+	if (!pDir) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (pDir->dir_nNumFiles == 0) {
+		pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);
+		if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)
+			return NULL;
+	} else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))
+			return NULL;
+
+	/* bump count for next call to readdir() or telldir() */
+	pDir->dir_nNumFiles++;
+
+	/* fill in struct dirent values */
+	pDir->dir_sdReturn.d_ino = -1;
+	strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
+
+	return &pDir->dir_sdReturn;
+}
+
+void
+rewinddir(DIR* pDir)
+{
+	if (!pDir) {
+		errno = EINVAL;
+		return;
+	}
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
+		errno = EINVAL;
+		return;
+	}
+
+	/* close the WINDOWS32 directory handle */
+	if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
+		if (!FindClose(pDir->dir_hDirHandle))
+			errno = EBADF;
+
+	/* reset members which control readdir() */
+	pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
+	pDir->dir_nNumFiles = 0;
+
+	return;
+}
+
+int
+telldir(DIR* pDir)
+{
+	if (!pDir) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* return number of times readdir() called */
+	return pDir->dir_nNumFiles;
+}
+
+void
+seekdir(DIR* pDir, long nPosition)
+{
+	if (!pDir)
+		return;
+
+	/* sanity check that this is a DIR pointer */
+	if (pDir->dir_ulCookie != __DIRENT_COOKIE)
+		return;
+
+	/* go back to beginning of directory */
+	rewinddir(pDir);
+
+	/* loop until we have found position we care about */
+	for (--nPosition; nPosition && readdir(pDir); nPosition--);
+
+	/* flag invalid nPosition value */
+	if (nPosition)
+		errno = EINVAL;
+
+	return;
+}
Index: /tags/kBuild-0.1.4/src/kmk/w32/include/dirent.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/include/dirent.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/include/dirent.h	(revision 1780)
@@ -0,0 +1,60 @@
+/* Windows version of dirent.h
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef _DIRENT_H
+#define _DIRENT_H
+
+#ifdef __MINGW32__
+# include <windows.h>
+# include_next <dirent.h>
+#else
+
+#include <stdlib.h>
+#include <windows.h>
+#include <limits.h>
+#include <sys/types.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+#define __DIRENT_COOKIE 0xfefeabab
+
+
+struct dirent
+{
+  ino_t d_ino; 			/* unused - no equivalent on WINDOWS32 */
+  char d_name[NAME_MAX+1];
+};
+
+typedef struct dir_struct {
+	ULONG	dir_ulCookie;
+	HANDLE	dir_hDirHandle;
+	DWORD	dir_nNumFiles;
+	char	dir_pDirectoryName[NAME_MAX+1];
+	struct dirent dir_sdReturn;
+} DIR;
+
+DIR *opendir(const char *);
+struct dirent *readdir(DIR *);
+void rewinddir(DIR *);
+void closedir(DIR *);
+int telldir(DIR *);
+void seekdir(DIR *, long);
+
+#endif  /* !__MINGW32__ */
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/w32/include/pathstuff.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/include/pathstuff.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/include/pathstuff.h	(revision 1780)
@@ -0,0 +1,26 @@
+/* Definitions for Windows path manipulation.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef _PATHSTUFF_H
+#define _PATHSTUFF_H
+
+char *convert_Path_to_windows32(char *Path, char to_delim);
+char *convert_vpath_to_windows32(char *Path, char to_delim);
+char *w32ify(const char *filename, int resolve);
+char *getcwd_fs(char *buf, int len);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/w32/include/sub_proc.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/include/sub_proc.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/include/sub_proc.h	(revision 1780)
@@ -0,0 +1,60 @@
+/* Definitions for Windows process invocation.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef SUB_PROC_H
+#define SUB_PROC_H
+
+/*
+ * Component Name:
+ *
+ * $Date: 2006/02/11 22:16:05 $
+ *
+ * $Source: /sources/make/make/w32/include/sub_proc.h,v $
+ *
+ * $Id: sub_proc.h,v 1.8 2006/02/11 22:16:05 psmith Exp $
+ */
+
+#define EXTERN_DECL(entry, args) extern entry args
+#define VOID_DECL void
+
+EXTERN_DECL(HANDLE process_init, (VOID_DECL));
+EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth,
+	HANDLE stderrh));
+EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp,
+	char *exec_path, char *as_user));
+EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data,
+	int stdin_data_len));
+EXTERN_DECL(long process_file_io, (HANDLE proc));
+EXTERN_DECL(void process_cleanup, (HANDLE proc));
+EXTERN_DECL(HANDLE process_wait_for_any, (VOID_DECL));
+EXTERN_DECL(void process_register, (HANDLE proc));
+EXTERN_DECL(HANDLE process_easy, (char** argv, char** env));
+EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));
+EXTERN_DECL(int process_used_slots, (VOID_DECL));
+
+/* support routines */
+EXTERN_DECL(long process_errno, (HANDLE proc));
+EXTERN_DECL(long process_last_err, (HANDLE proc));
+EXTERN_DECL(long process_exit_code, (HANDLE proc));
+EXTERN_DECL(long process_signal, (HANDLE proc));
+EXTERN_DECL(char * process_outbuf, (HANDLE proc));
+EXTERN_DECL(char * process_errbuf, (HANDLE proc));
+EXTERN_DECL(int process_outcnt, (HANDLE proc));
+EXTERN_DECL(int process_errcnt, (HANDLE proc));
+EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3]));
+
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/w32/include/w32err.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/include/w32err.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/include/w32err.h	(revision 1780)
@@ -0,0 +1,27 @@
+/* Definitions for Windows error handling.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef _W32ERR_H_
+#define _W32ERR_H_
+
+#ifndef EXTERN_DECL
+#define EXTERN_DECL(entry, args) entry args
+#endif
+
+EXTERN_DECL(char * map_windows32_error_to_string, (DWORD error));
+
+#endif /* !_W32ERR_H */
Index: /tags/kBuild-0.1.4/src/kmk/w32/pathstuff.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/pathstuff.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/pathstuff.c	(revision 1780)
@@ -0,0 +1,306 @@
+/* Path conversion for Windows pathnames.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include <Windows.h> /* bird */
+#include <stdio.h>   /* bird */
+#include <string.h>
+#include <stdlib.h>
+#include "make.h"
+#include "pathstuff.h"
+
+/*
+ * Convert delimiter separated vpath to Canonical format.
+ */
+char *
+convert_vpath_to_windows32(char *Path, char to_delim)
+{
+    char *etok;            /* token separator for old Path */
+
+	/*
+	 * Convert all spaces to delimiters. Note that pathnames which
+	 * contain blanks get trounced here. Use 8.3 format as a workaround.
+	 */
+	for (etok = Path; etok && *etok; etok++)
+		if (isblank ((unsigned char) *etok))
+			*etok = to_delim;
+
+	return (convert_Path_to_windows32(Path, to_delim));
+}
+
+/*
+ * Convert delimiter separated path to Canonical format.
+ */
+char *
+convert_Path_to_windows32(char *Path, char to_delim)
+{
+    char *etok;            /* token separator for old Path */
+    char *p;            /* points to element of old Path */
+
+    /* is this a multi-element Path ? */
+    for (p = Path, etok = strpbrk(p, ":;");
+         etok;
+         etok = strpbrk(p, ":;"))
+        if ((etok - p) == 1) {
+            if (*(etok - 1) == ';' ||
+                *(etok - 1) == ':') {
+                etok[-1] = to_delim;
+                etok[0] = to_delim;
+                p = ++etok;
+                continue;    /* ignore empty bucket */
+            } else if (!isalpha ((unsigned char) *p)) {
+                /* found one to count, handle things like '.' */
+                *etok = to_delim;
+                p = ++etok;
+            } else if ((*etok == ':') && (etok = strpbrk(etok+1, ":;"))) {
+                /* found one to count, handle drive letter */
+                *etok = to_delim;
+                p = ++etok;
+            } else
+                /* all finished, force abort */
+                p += strlen(p);
+        } else {
+            /* found another one, no drive letter */
+            *etok = to_delim;
+            p = ++etok;
+	}
+
+    return Path;
+}
+
+#if 1 /* bird */
+extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull);
+#endif
+
+/*
+ * Convert to forward slashes. Resolve to full pathname optionally
+ */
+char *
+w32ify(const char *filename, int resolve)
+{
+    static char w32_path[FILENAME_MAX];
+    char *p;
+
+    if (resolve) {
+#if 1 /* bird */
+        nt_fullpath(filename, w32_path, sizeof(w32_path));
+#else   /* !bird */
+        _fullpath(w32_path, filename, sizeof (w32_path));
+#endif  /* !bird */
+    } else
+        strncpy(w32_path, filename, sizeof (w32_path));
+
+    for (p = w32_path; p && *p; p++)
+        if (*p == '\\')
+            *p = '/';
+
+    return w32_path;
+}
+
+char *
+getcwd_fs(char* buf, int len)
+{
+	char *p = getcwd(buf, len);
+
+	if (p) {
+		char *q = w32ify(buf, 0);
+		strncpy(buf, q, len);
+	}
+
+	return p;
+}
+
+#undef stat
+/*
+ * Workaround for directory names with trailing slashes.
+ * Added by bird reasons stated.
+ */
+int
+my_stat(const char *path, struct stat *st)
+{
+    int rc = stat(path, st);
+    if (    rc != 0
+        &&  errno == ENOENT
+        &&  *path != '\0')
+      {
+        char *slash = strchr(path, '\0') - 1;
+        if (*slash == '/' || *slash == '\\')
+          {
+            size_t len_path = slash - path + 1;
+            char *tmp = alloca(len_path + 4);
+            memcpy(tmp, path, len_path);
+            tmp[len_path] = '.';
+            tmp[len_path + 1] = '\0';
+            errno = 0;
+            rc = stat(tmp, st);
+            if (    rc == 0
+                &&  !S_ISDIR(st->st_mode))
+              {
+                errno = ENOTDIR;
+                rc = -1;
+              }
+          }
+      }
+#ifdef KMK_PRF
+    {
+        int err = errno;
+        fprintf(stderr, "stat(%s,) -> %d/%d\n", path, rc, errno);
+        errno = err;
+    }
+#endif
+    return rc;
+}
+
+#ifdef unused
+/*
+ * Convert delimiter separated pathnames (e.g. PATH) or single file pathname
+ * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that
+ * _NutPathToNutc() fails to convert, just return the path we were handed
+ * and assume the caller will know what to do with it (It was probably
+ * a mistake to try and convert it anyway due to some of the bizarre things
+ * that might look like pathnames in makefiles).
+ */
+char *
+convert_path_to_nutc(char *path)
+{
+    int  count;            /* count of path elements */
+    char *nutc_path;     /* new NutC path */
+    int  nutc_path_len;    /* length of buffer to allocate for new path */
+    char *pathp;        /* pointer to nutc_path used to build it */
+    char *etok;            /* token separator for old path */
+    char *p;            /* points to element of old path */
+    char sep;            /* what flavor of separator used in old path */
+    char *rval;
+
+    /* is this a multi-element path ? */
+    for (p = path, etok = strpbrk(p, ":;"), count = 0;
+         etok;
+         etok = strpbrk(p, ":;"))
+        if ((etok - p) == 1) {
+            if (*(etok - 1) == ';' ||
+                *(etok - 1) == ':') {
+                p = ++etok;
+                continue;    /* ignore empty bucket */
+            } else if (etok = strpbrk(etok+1, ":;"))
+                /* found one to count, handle drive letter */
+                p = ++etok, count++;
+            else
+                /* all finished, force abort */
+                p += strlen(p);
+        } else
+            /* found another one, no drive letter */
+            p = ++etok, count++;
+
+    if (count) {
+        count++;    /* x1;x2;x3 <- need to count x3 */
+
+        /*
+         * Hazard a guess on how big the buffer needs to be.
+         * We have to convert things like c:/foo to /c=/foo.
+         */
+        nutc_path_len = strlen(path) + (count*2) + 1;
+        nutc_path = xmalloc(nutc_path_len);
+        pathp = nutc_path;
+        *pathp = '\0';
+
+        /*
+         * Loop through PATH and convert one elemnt of the path at at
+         * a time. Single file pathnames will fail this and fall
+         * to the logic below loop.
+         */
+        for (p = path, etok = strpbrk(p, ":;");
+             etok;
+             etok = strpbrk(p, ":;")) {
+
+            /* don't trip up on device specifiers or empty path slots */
+            if ((etok - p) == 1)
+                if (*(etok - 1) == ';' ||
+                    *(etok - 1) == ':') {
+                    p = ++etok;
+                    continue;
+                } else if ((etok = strpbrk(etok+1, ":;")) == NULL)
+                    break;    /* thing found was a WINDOWS32 pathname */
+
+            /* save separator */
+            sep = *etok;
+
+            /* terminate the current path element -- temporarily */
+            *etok = '\0';
+
+#ifdef __NUTC__
+            /* convert to NutC format */
+            if (_NutPathToNutc(p, pathp, 0) == FALSE) {
+                free(nutc_path);
+                rval = savestring(path, strlen(path));
+                return rval;
+            }
+#else
+            *pathp++ = '/';
+            *pathp++ = p[0];
+            *pathp++ = '=';
+            *pathp++ = '/';
+            strcpy(pathp, &p[2]);
+#endif
+
+            pathp += strlen(pathp);
+            *pathp++ = ':';     /* use Unix style path separtor for new path */
+            *pathp   = '\0'; /* make sure we are null terminaed */
+
+            /* restore path separator */
+            *etok = sep;
+
+            /* point p to first char of next path element */
+            p = ++etok;
+
+        }
+    } else {
+        nutc_path_len = strlen(path) + 3;
+        nutc_path = xmalloc(nutc_path_len);
+        pathp = nutc_path;
+        *pathp = '\0';
+        p = path;
+    }
+
+    /*
+      * OK, here we handle the last element in PATH (e.g. c of a;b;c)
+     * or the path was a single filename and will be converted
+     * here. Note, testing p here assures that we don't trip up
+     * on paths like a;b; which have trailing delimiter followed by
+     * nothing.
+     */
+    if (*p != '\0') {
+#ifdef __NUTC__
+        if (_NutPathToNutc(p, pathp, 0) == FALSE) {
+            free(nutc_path);
+            rval = savestring(path, strlen(path));
+            return rval;
+        }
+#else
+        *pathp++ = '/';
+        *pathp++ = p[0];
+        *pathp++ = '=';
+        *pathp++ = '/';
+        strcpy(pathp, &p[2]);
+#endif
+    } else
+        *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */
+
+    rval = savestring(nutc_path, strlen(nutc_path));
+    free(nutc_path);
+    return rval;
+}
+
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/w32/subproc/NMakefile
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/subproc/NMakefile	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/subproc/NMakefile	(revision 1780)
@@ -0,0 +1,60 @@
+# NOTE: If you have no `make' program at all to process this makefile, run
+# `build.bat' instead.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+# 2006 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Make; see the file COPYING.  If not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#
+#       NMakefile for GNU Make (subproc library)
+#
+LIB = lib
+CC = cl
+MAKE = nmake
+
+OUTDIR=.
+MAKEFILE=NMakefile
+
+CFLAGS_any = /nologo /MT /W4 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS  -I. -I../include -I../../
+CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/
+CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/
+
+all: Release Debug
+
+Release:
+	$(MAKE) /f $(MAKEFILE) OUTDIR=WinRel CFLAGS="$(CFLAGS_release)" WinRel/subproc.lib
+Debug:
+	$(MAKE) /f $(MAKEFILE) OUTDIR=WinDebug CFLAGS="$(CFLAGS_debug)" WinDebug/subproc.lib
+
+clean:
+	rmdir /s /q WinRel WinDebug
+	erase *.pdb
+
+$(OUTDIR):
+	if not exist .\$@\nul mkdir .\$@
+
+OBJS = $(OUTDIR)/misc.obj $(OUTDIR)/w32err.obj $(OUTDIR)/sub_proc.obj
+
+$(OUTDIR)/subproc.lib: $(OUTDIR) $(OBJS)
+	$(LIB) -out:$@ @<<
+		$(OBJS)
+<<
+
+.c{$(OUTDIR)}.obj:
+	$(CC) $(CFLAGS) /c $<
+
+$(OUTDIR)/misc.obj: misc.c proc.h
+$(OUTDIR)/sub_proc.obj: sub_proc.c  ../include/sub_proc.h ../include/w32err.h proc.h
+$(OUTDIR)/w32err.obj: w32err.c ../include/w32err.h
Index: /tags/kBuild-0.1.4/src/kmk/w32/subproc/build.bat
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/subproc/build.bat	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/subproc/build.bat	(revision 1780)
@@ -0,0 +1,34 @@
+@if "%1" == "gcc" GoTo GCCBuild
+if not exist .\WinDebug\nul mkdir .\WinDebug
+cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c
+cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c
+cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c w32err.c
+lib.exe /NOLOGO /OUT:.\WinDebug\subproc.lib  .\WinDebug/misc.obj  .\WinDebug/sub_proc.obj  .\WinDebug/w32err.obj
+if not exist .\WinRel\nul mkdir .\WinRel
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c misc.c
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c
+cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c
+lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib  .\WinRel/misc.obj  .\WinRel/sub_proc.obj  .\WinRel/w32err.obj
+GoTo BuildEnd
+:GCCBuild
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c misc.c -o ../../w32_misc.o
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c sub_proc.c -o ../../sub_proc.o
+gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c w32err.c -o ../../w32err.o
+:BuildEnd
+
+@echo off
+rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+rem 2005, 2006 Free Software Foundation, Inc.
+rem This file is part of GNU Make.
+
+rem GNU Make is free software; you can redistribute it and/or modify it under the
+rem terms of the GNU General Public License as published by the Free Software
+rem Foundation; either version 2, or (at your option) any later version.
+
+rem GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+rem WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+rem A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+rem You should have received a copy of the GNU General Public License along with
+rem GNU Make; see the file COPYING.  If not, write to the Free Software
+rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Index: /tags/kBuild-0.1.4/src/kmk/w32/subproc/misc.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/subproc/misc.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/subproc/misc.c	(revision 1780)
@@ -0,0 +1,82 @@
+/* Process handling for Windows
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include "proc.h"
+
+
+/*
+ * Description:  Convert a NULL string terminated UNIX environment block to
+ *		an environment block suitable for a windows32 system call
+ *
+ * Returns:  TRUE= success, FALSE=fail
+ *
+ * Notes/Dependencies:  the environment block is sorted in case-insensitive
+ *	order, is double-null terminated, and is a char *, not a char **
+ */
+int _cdecl compare(const void *a1, const void *a2)
+{
+	return _stricoll(*((char**)a1),*((char**)a2));
+}
+bool_t
+arr2envblk(char **arr, char **envblk_out)
+{
+	char **tmp;
+	int size_needed;
+	int arrcnt;
+	char *ptr;
+
+	arrcnt = 0;
+	while (arr[arrcnt]) {
+		arrcnt++;
+	}
+
+	tmp = (char**) calloc(arrcnt + 1, sizeof(char *));
+	if (!tmp) {
+		return FALSE;
+	}
+
+	arrcnt = 0;
+	size_needed = 0;
+	while (arr[arrcnt]) {
+		tmp[arrcnt] = arr[arrcnt];
+		size_needed += strlen(arr[arrcnt]) + 1;
+		arrcnt++;
+	}
+	size_needed++;
+
+	qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare);
+
+	ptr = *envblk_out = calloc(size_needed, 1);
+	if (!ptr) {
+		free(tmp);
+		return FALSE;
+	}
+
+	arrcnt = 0;
+	while (tmp[arrcnt]) {
+		strcpy(ptr, tmp[arrcnt]);
+		ptr += strlen(tmp[arrcnt]) + 1;
+		arrcnt++;
+	}
+
+        free(tmp);
+	return TRUE;
+}
Index: /tags/kBuild-0.1.4/src/kmk/w32/subproc/proc.h
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/subproc/proc.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/subproc/proc.h	(revision 1780)
@@ -0,0 +1,30 @@
+/* Definitions for Windows
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#ifndef  _PROC_H
+#define _PROC_H
+
+typedef int bool_t;
+
+#define E_SCALL		101
+#define E_IO		102
+#define E_NO_MEM	103
+#define E_FORK		104
+
+extern bool_t arr2envblk(char **arr, char **envblk_out);
+
+#endif
Index: /tags/kBuild-0.1.4/src/kmk/w32/subproc/sub_proc.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/subproc/sub_proc.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/subproc/sub_proc.c	(revision 1780)
@@ -0,0 +1,1356 @@
+/* Process handling for Windows.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <process.h>  /* for msvc _beginthreadex, _endthreadex */
+#include <signal.h>
+#include <windows.h>
+
+#include "sub_proc.h"
+#include "proc.h"
+#include "w32err.h"
+#include "config.h"
+#include "debug.h"
+
+static char *make_command_line(char *shell_name, char *exec_path, char **argv);
+
+typedef struct sub_process_t {
+	int sv_stdin[2];
+	int sv_stdout[2];
+	int sv_stderr[2];
+	int using_pipes;
+	char *inp;
+	DWORD incnt;
+	char * volatile outp;
+	volatile DWORD outcnt;
+	char * volatile errp;
+	volatile DWORD errcnt;
+	int pid;
+	int exit_code;
+	int signal;
+	long last_err;
+	long lerrno;
+} sub_process;
+
+static long process_file_io_private(sub_process *pproc, BOOL fNeedToWait); /* bird */
+
+/* keep track of children so we can implement a waitpid-like routine */
+static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS];
+static int proc_index = 0;
+static int fake_exits_pending = 0;
+
+/*
+ * When a process has been waited for, adjust the wait state
+ * array so that we don't wait for it again
+ */
+static void
+process_adjust_wait_state(sub_process* pproc)
+{
+	int i;
+
+	if (!proc_index)
+		return;
+
+	for (i = 0; i < proc_index; i++)
+		if (proc_array[i]->pid == pproc->pid)
+			break;
+
+	if (i < proc_index) {
+		proc_index--;
+		if (i != proc_index)
+			memmove(&proc_array[i], &proc_array[i+1],
+				(proc_index-i) * sizeof(sub_process*));
+		proc_array[proc_index] = NULL;
+	}
+}
+
+/*
+ * Waits for any of the registered child processes to finish.
+ */
+static sub_process *
+process_wait_for_any_private(void)
+{
+	HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+	DWORD retval, which;
+	int i;
+
+	if (!proc_index)
+		return NULL;
+
+	/* build array of handles to wait for */
+	for (i = 0; i < proc_index; i++) {
+		handles[i] = (HANDLE) proc_array[i]->pid;
+
+		if (fake_exits_pending && proc_array[i]->exit_code)
+			break;
+	}
+
+	/* wait for someone to exit */
+	if (!fake_exits_pending) {
+		retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
+		which = retval - WAIT_OBJECT_0;
+	} else {
+		fake_exits_pending--;
+		retval = !WAIT_FAILED;
+		which = i;
+	}
+
+	/* return pointer to process */
+	if (retval != WAIT_FAILED) {
+		sub_process* pproc = proc_array[which];
+		process_adjust_wait_state(pproc);
+		return pproc;
+	} else
+		return NULL;
+}
+
+/*
+ * Terminate a process.
+ */
+BOOL
+process_kill(HANDLE proc, int signal)
+{
+	sub_process* pproc = (sub_process*) proc;
+	pproc->signal = signal;
+	return (TerminateProcess((HANDLE) pproc->pid, signal));
+}
+
+/*
+ * Use this function to register processes you wish to wait for by
+ * calling process_file_io(NULL) or process_wait_any(). This must be done
+ * because it is possible for callers of this library to reuse the same
+ * handle for multiple processes launches :-(
+ */
+void
+process_register(HANDLE proc)
+{
+	if (proc_index < MAXIMUM_WAIT_OBJECTS)
+		proc_array[proc_index++] = (sub_process *) proc;
+}
+
+/*
+ * Return the number of processes that we are still waiting for.
+ */
+int
+process_used_slots(void)
+{
+	return proc_index;
+}
+
+/*
+ * Public function which works kind of like waitpid(). Wait for any
+ * of the children to die and return results. To call this function,
+ * you must do 1 of things:
+ *
+ * 	x = process_easy(...);
+ *
+ * or
+ *
+ *	x = process_init_fd();
+ *	process_register(x);
+ *
+ * or
+ *
+ *	x = process_init();
+ *	process_register(x);
+ *
+ * You must NOT then call process_pipe_io() because this function is
+ * not capable of handling automatic notification of any child
+ * death.
+ */
+
+HANDLE
+process_wait_for_any(void)
+{
+	sub_process* pproc = process_wait_for_any_private();
+
+	if (!pproc)
+		return NULL;
+	else {
+		/*
+		 * Ouch! can't tell caller if this fails directly. Caller
+		 * will have to use process_last_err()
+		 */
+#ifdef KMK
+		(void) process_file_io_private(pproc, FALSE);
+#else
+		(void) process_file_io(pproc);
+#endif
+		return ((HANDLE) pproc);
+	}
+}
+
+long
+process_signal(HANDLE proc)
+{
+        if (proc == INVALID_HANDLE_VALUE) return 0;
+        return (((sub_process *)proc)->signal);
+}
+
+long
+process_last_err(HANDLE proc)
+{
+        if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
+	return (((sub_process *)proc)->last_err);
+}
+
+long
+process_exit_code(HANDLE proc)
+{
+        if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE;
+	return (((sub_process *)proc)->exit_code);
+}
+
+/*
+2006-02:
+All the following functions are currently unused.
+All of them would crash gmake if called with argument INVALID_HANDLE_VALUE.
+Hence whoever wants to use one of this functions must invent and implement
+a reasonable error handling for this function.
+
+char *
+process_outbuf(HANDLE proc)
+{
+	return (((sub_process *)proc)->outp);
+}
+
+char *
+process_errbuf(HANDLE proc)
+{
+	return (((sub_process *)proc)->errp);
+}
+
+int
+process_outcnt(HANDLE proc)
+{
+	return (((sub_process *)proc)->outcnt);
+}
+
+int
+process_errcnt(HANDLE proc)
+{
+	return (((sub_process *)proc)->errcnt);
+}
+
+void
+process_pipes(HANDLE proc, int pipes[3])
+{
+	pipes[0] = ((sub_process *)proc)->sv_stdin[0];
+	pipes[1] = ((sub_process *)proc)->sv_stdout[0];
+	pipes[2] = ((sub_process *)proc)->sv_stderr[0];
+	return;
+}
+*/
+
+	HANDLE
+process_init()
+{
+	sub_process *pproc;
+	/*
+	 * open file descriptors for attaching stdin/stdout/sterr
+	 */
+	HANDLE stdin_pipes[2];
+	HANDLE stdout_pipes[2];
+	HANDLE stderr_pipes[2];
+	SECURITY_ATTRIBUTES inherit;
+	BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
+
+	pproc = malloc(sizeof(*pproc));
+	memset(pproc, 0, sizeof(*pproc));
+
+	/* We can't use NULL for lpSecurityDescriptor because that
+	   uses the default security descriptor of the calling process.
+	   Instead we use a security descriptor with no DACL.  This
+	   allows nonrestricted access to the associated objects. */
+
+	if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
+					  SECURITY_DESCRIPTOR_REVISION)) {
+		pproc->last_err = GetLastError();
+		pproc->lerrno = E_SCALL;
+		return((HANDLE)pproc);
+	}
+
+	inherit.nLength = sizeof(inherit);
+	inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
+	inherit.bInheritHandle = TRUE;
+
+	// By convention, parent gets pipe[0], and child gets pipe[1]
+	// This means the READ side of stdin pipe goes into pipe[1]
+	// and the WRITE side of the stdout and stderr pipes go into pipe[1]
+	if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
+	CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
+	CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
+
+		pproc->last_err = GetLastError();
+		pproc->lerrno = E_SCALL;
+		return((HANDLE)pproc);
+	}
+
+	//
+	// Mark the parent sides of the pipes as non-inheritable
+	//
+	if (SetHandleInformation(stdin_pipes[0],
+				HANDLE_FLAG_INHERIT, 0) == FALSE ||
+		SetHandleInformation(stdout_pipes[0],
+				HANDLE_FLAG_INHERIT, 0) == FALSE ||
+		SetHandleInformation(stderr_pipes[0],
+				HANDLE_FLAG_INHERIT, 0) == FALSE) {
+
+		pproc->last_err = GetLastError();
+		pproc->lerrno = E_SCALL;
+		return((HANDLE)pproc);
+	}
+	pproc->sv_stdin[0]  = (int) stdin_pipes[0];
+	pproc->sv_stdin[1]  = (int) stdin_pipes[1];
+	pproc->sv_stdout[0] = (int) stdout_pipes[0];
+	pproc->sv_stdout[1] = (int) stdout_pipes[1];
+	pproc->sv_stderr[0] = (int) stderr_pipes[0];
+	pproc->sv_stderr[1] = (int) stderr_pipes[1];
+
+	pproc->using_pipes = 1;
+
+	pproc->lerrno = 0;
+
+	return((HANDLE)pproc);
+}
+
+
+	HANDLE
+process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
+{
+	sub_process *pproc;
+
+	pproc = malloc(sizeof(*pproc));
+	memset(pproc, 0, sizeof(*pproc));
+
+	/*
+	 * Just pass the provided file handles to the 'child side' of the
+	 * pipe, bypassing pipes altogether.
+	 */
+	pproc->sv_stdin[1]  = (int) stdinh;
+	pproc->sv_stdout[1] = (int) stdouth;
+	pproc->sv_stderr[1] = (int) stderrh;
+
+	pproc->last_err = pproc->lerrno = 0;
+
+	return((HANDLE)pproc);
+}
+
+
+static HANDLE
+find_file(char *exec_path, LPOFSTRUCT file_info)
+{
+	HANDLE exec_handle;
+	char *fname;
+	char *ext;
+#ifdef KMK
+	size_t exec_path_len;
+
+	/*
+	 * if there is an .exe extension there already, don't waste time here.
+	 * If .exe scripts become common, they can be handled in a CreateProcess
+	 * failure path instead of here.
+	 */
+	exec_path_len = strlen(exec_path);
+	if (	exec_path_len > 4
+		&&	exec_path[exec_path_len - 4] == '.'
+		&&  !stricmp(exec_path + exec_path_len - 3, "exe")){
+		return((HANDLE)HFILE_ERROR);
+	}
+
+	fname = malloc(exec_path_len + 5);
+#else
+	fname = malloc(strlen(exec_path) + 5);
+#endif
+	strcpy(fname, exec_path);
+	ext = fname + strlen(fname);
+
+	strcpy(ext, ".exe");
+	if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
+			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+		free(fname);
+		return(exec_handle);
+	}
+
+	strcpy(ext, ".cmd");
+	if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
+			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+		free(fname);
+		return(exec_handle);
+	}
+
+	strcpy(ext, ".bat");
+	if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
+			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+		free(fname);
+		return(exec_handle);
+	}
+
+	/* should .com come before this case? */
+	if ((exec_handle = (HANDLE)OpenFile(exec_path, file_info,
+			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+		free(fname);
+		return(exec_handle);
+	}
+
+	strcpy(ext, ".com");
+	if ((exec_handle = (HANDLE)OpenFile(fname, file_info,
+			OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) {
+		free(fname);
+		return(exec_handle);
+	}
+
+	free(fname);
+	return(exec_handle);
+}
+
+
+/*
+ * Description:   Create the child process to be helped
+ *
+ * Returns: success <=> 0
+ *
+ * Notes/Dependencies:
+ */
+long
+process_begin(
+	HANDLE proc,
+	char **argv,
+	char **envp,
+	char *exec_path,
+	char *as_user)
+{
+	sub_process *pproc = (sub_process *)proc;
+	char *shell_name = 0;
+	int file_not_found=0;
+	HANDLE exec_handle;
+	char buf[256];
+	DWORD bytes_returned;
+	DWORD flags;
+	char *command_line;
+	STARTUPINFO startInfo;
+	PROCESS_INFORMATION procInfo;
+	char *envblk=NULL;
+	OFSTRUCT file_info;
+
+
+	/*
+	 *  Shell script detection...  if the exec_path starts with #! then
+	 *  we want to exec shell-script-name exec-path, not just exec-path
+	 *  NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl.  We do not
+	 *  hard-code the path to the shell or perl or whatever:  Instead, we
+	 *  assume it's in the path somewhere (generally, the NT tools
+	 *  bin directory)
+	 *  We use OpenFile here because it is capable of searching the Path.
+	 */
+
+	exec_handle = find_file(exec_path, &file_info);
+
+	/*
+	 * If we couldn't open the file, just assume that Windows32 will be able
+	 * to find and execute it.
+	 */
+	if (exec_handle == (HANDLE)HFILE_ERROR) {
+		file_not_found++;
+	}
+	else {
+		/* Attempt to read the first line of the file */
+		if (ReadFile( exec_handle,
+				buf, sizeof(buf) - 1, /* leave room for trailing NULL */
+				&bytes_returned, 0) == FALSE || bytes_returned < 2) {
+
+			pproc->last_err = GetLastError();
+			pproc->lerrno = E_IO;
+			CloseHandle(exec_handle);
+			return(-1);
+		}
+		if (buf[0] == '#' && buf[1] == '!') {
+			/*
+			 *  This is a shell script...  Change the command line from
+			 *	exec_path args to shell_name exec_path args
+			 */
+			char *p;
+
+			/*  Make sure buf is NULL terminated */
+			buf[bytes_returned] = 0;
+			/*
+			 * Depending on the file system type, etc. the first line
+			 * of the shell script may end with newline or newline-carriage-return
+			 * Whatever it ends with, cut it off.
+			 */
+			p= strchr(buf, '\n');
+			if (p)
+				*p = 0;
+			p = strchr(buf, '\r');
+			if (p)
+				*p = 0;
+
+			/*
+			 *  Find base name of shell
+			 */
+			shell_name = strrchr( buf, '/');
+			if (shell_name) {
+				shell_name++;
+			} else {
+				shell_name = &buf[2];/* skipping "#!" */
+			}
+
+		}
+		CloseHandle(exec_handle);
+	}
+
+	flags = 0;
+
+	if (file_not_found)
+		command_line = make_command_line( shell_name, exec_path, argv);
+	else
+		command_line = make_command_line( shell_name, file_info.szPathName,
+				 argv);
+
+	if ( command_line == NULL ) {
+		pproc->last_err = 0;
+		pproc->lerrno = E_NO_MEM;
+		return(-1);
+	}
+
+	if (envp) {
+		if (arr2envblk(envp, &envblk) ==FALSE) {
+			pproc->last_err = 0;
+			pproc->lerrno = E_NO_MEM;
+			free( command_line );
+			return(-1);
+		}
+	}
+
+	if ((shell_name) || (file_not_found)) {
+		exec_path = 0;	/* Search for the program in %Path% */
+	} else {
+		exec_path = file_info.szPathName;
+	}
+
+	/*
+	 *  Set up inherited stdin, stdout, stderr for child
+	 */
+	GetStartupInfo(&startInfo);
+#ifndef KMK
+	startInfo.dwFlags = STARTF_USESTDHANDLES;
+#endif
+	startInfo.lpReserved = 0;
+	startInfo.cbReserved2 = 0;
+	startInfo.lpReserved2 = 0;
+	startInfo.lpTitle = shell_name ? shell_name : exec_path;
+#ifndef KMK
+	startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
+	startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
+	startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
+#else
+	if (    pproc->sv_stdin[1]
+		||  pproc->sv_stdout[1]
+		||  pproc->sv_stderr[1]) {
+		startInfo.dwFlags = STARTF_USESTDHANDLES;
+		startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
+		startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
+		startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
+	} else {
+		startInfo.dwFlags = 0;
+		startInfo.hStdInput = 0;
+		startInfo.hStdOutput = 0;
+		startInfo.hStdError = 0;
+	}
+#endif
+
+	if (as_user) {
+		if (envblk) free(envblk);
+		return -1;
+	} else {
+		DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n",
+			exec_path ? exec_path : "NULL",
+			command_line ? command_line : "NULL"));
+		if (CreateProcess(
+			exec_path,
+			command_line,
+			NULL,
+			0, /* default security attributes for thread */
+			TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
+			flags,
+			envblk,
+			0, /* default starting directory */
+			&startInfo,
+			&procInfo) == FALSE) {
+
+			pproc->last_err = GetLastError();
+			pproc->lerrno = E_FORK;
+#ifdef KMK
+			if (pproc->last_err == ERROR_FILE_NOT_FOUND)
+				pproc->exit_code = 127; /* see execve failure in job.c. */
+#endif
+			fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
+                                exec_path ? exec_path : "NULL", command_line);
+			if (envblk) free(envblk);
+			free( command_line );
+			return(-1);
+		}
+	}
+
+	pproc->pid = (int)procInfo.hProcess;
+	/* Close the thread handle -- we'll just watch the process */
+	CloseHandle(procInfo.hThread);
+
+	/* Close the halves of the pipes we don't need */
+#ifndef KMK
+	CloseHandle((HANDLE)pproc->sv_stdin[1]);
+	CloseHandle((HANDLE)pproc->sv_stdout[1]);
+	CloseHandle((HANDLE)pproc->sv_stderr[1]);
+	pproc->sv_stdin[1] = 0;
+	pproc->sv_stdout[1] = 0;
+	pproc->sv_stderr[1] = 0;
+#else
+	if ((HANDLE)pproc->sv_stdin[1]) {
+		CloseHandle((HANDLE)pproc->sv_stdin[1]);
+		pproc->sv_stdin[1] = 0;
+	}
+	if ((HANDLE)pproc->sv_stdout[1]) {
+		CloseHandle((HANDLE)pproc->sv_stdout[1]);
+		pproc->sv_stdout[1] = 0;
+	}
+	if ((HANDLE)pproc->sv_stderr[1]) {
+		CloseHandle((HANDLE)pproc->sv_stderr[1]);
+		pproc->sv_stderr[1] = 0;
+	}
+#endif
+
+	free( command_line );
+	if (envblk) free(envblk);
+	pproc->lerrno=0;
+	return 0;
+}
+
+
+
+static DWORD
+proc_stdin_thread(sub_process *pproc)
+{
+	DWORD in_done;
+	for (;;) {
+		if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
+					 &in_done, NULL) == FALSE)
+			_endthreadex(0);
+		// This if should never be true for anonymous pipes, but gives
+		// us a chance to change I/O mechanisms later
+		if (in_done < pproc->incnt) {
+			pproc->incnt -= in_done;
+			pproc->inp += in_done;
+		} else {
+			_endthreadex(0);
+		}
+	}
+	return 0; // for compiler warnings only.. not reached
+}
+
+static DWORD
+proc_stdout_thread(sub_process *pproc)
+{
+	DWORD bufsize = 1024;
+	char c;
+	DWORD nread;
+	pproc->outp = malloc(bufsize);
+	if (pproc->outp == NULL)
+		_endthreadex(0);
+	pproc->outcnt = 0;
+
+	for (;;) {
+		if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
+					== FALSE) {
+/*			map_windows32_error_to_string(GetLastError());*/
+			_endthreadex(0);
+		}
+		if (nread == 0)
+			_endthreadex(0);
+		if (pproc->outcnt + nread > bufsize) {
+			bufsize += nread + 512;
+			pproc->outp = realloc(pproc->outp, bufsize);
+			if (pproc->outp == NULL) {
+				pproc->outcnt = 0;
+				_endthreadex(0);
+			}
+		}
+		pproc->outp[pproc->outcnt++] = c;
+	}
+	return 0;
+}
+
+static DWORD
+proc_stderr_thread(sub_process *pproc)
+{
+	DWORD bufsize = 1024;
+	char c;
+	DWORD nread;
+	pproc->errp = malloc(bufsize);
+	if (pproc->errp == NULL)
+		_endthreadex(0);
+	pproc->errcnt = 0;
+
+	for (;;) {
+		if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
+			map_windows32_error_to_string(GetLastError());
+			_endthreadex(0);
+		}
+		if (nread == 0)
+			_endthreadex(0);
+		if (pproc->errcnt + nread > bufsize) {
+			bufsize += nread + 512;
+			pproc->errp = realloc(pproc->errp, bufsize);
+			if (pproc->errp == NULL) {
+				pproc->errcnt = 0;
+				_endthreadex(0);
+			}
+		}
+		pproc->errp[pproc->errcnt++] = c;
+	}
+	return 0;
+}
+
+
+/*
+ * Purpose: collects output from child process and returns results
+ *
+ * Description:
+ *
+ * Returns:
+ *
+ * Notes/Dependencies:
+ */
+	long
+process_pipe_io(
+	HANDLE proc,
+	char *stdin_data,
+	int stdin_data_len)
+{
+	sub_process *pproc = (sub_process *)proc;
+	bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
+	HANDLE childhand = (HANDLE) pproc->pid;
+	HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;
+	unsigned int dwStdin, dwStdout, dwStderr;
+	HANDLE wait_list[4];
+	DWORD wait_count;
+	DWORD wait_return;
+	HANDLE ready_hand;
+	bool_t child_dead = FALSE;
+	BOOL GetExitCodeResult;
+
+	/*
+	 *  Create stdin thread, if needed
+	 */
+	pproc->inp = stdin_data;
+	pproc->incnt = stdin_data_len;
+	if (!pproc->inp) {
+		stdin_eof = TRUE;
+		CloseHandle((HANDLE)pproc->sv_stdin[0]);
+		pproc->sv_stdin[0] = 0;
+	} else {
+		tStdin = (HANDLE) _beginthreadex( 0, 1024,
+			(unsigned (__stdcall *) (void *))proc_stdin_thread,
+						  pproc, 0, &dwStdin);
+		if (tStdin == 0) {
+			pproc->last_err = GetLastError();
+			pproc->lerrno = E_SCALL;
+			goto done;
+		}
+	}
+
+	/*
+	 *   Assume child will produce stdout and stderr
+	 */
+	tStdout = (HANDLE) _beginthreadex( 0, 1024,
+		(unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
+		&dwStdout);
+	tStderr = (HANDLE) _beginthreadex( 0, 1024,
+		(unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
+		&dwStderr);
+
+	if (tStdout == 0 || tStderr == 0) {
+
+		pproc->last_err = GetLastError();
+		pproc->lerrno = E_SCALL;
+		goto done;
+	}
+
+
+	/*
+	 *  Wait for all I/O to finish and for the child process to exit
+	 */
+
+	while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
+		wait_count = 0;
+		if (!stdin_eof) {
+			wait_list[wait_count++] = tStdin;
+		}
+		if (!stdout_eof) {
+			wait_list[wait_count++] = tStdout;
+		}
+		if (!stderr_eof) {
+			wait_list[wait_count++] = tStderr;
+		}
+		if (!child_dead) {
+			wait_list[wait_count++] = childhand;
+		}
+
+		wait_return = WaitForMultipleObjects(wait_count, wait_list,
+			 FALSE, /* don't wait for all: one ready will do */
+			 child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
+			 	one second to collect all remaining output */
+
+                if (wait_return == WAIT_FAILED) {
+/*			map_windows32_error_to_string(GetLastError());*/
+			pproc->last_err = GetLastError();
+			pproc->lerrno = E_SCALL;
+			goto done;
+		}
+
+		ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
+
+		if (ready_hand == tStdin) {
+			CloseHandle((HANDLE)pproc->sv_stdin[0]);
+			pproc->sv_stdin[0] = 0;
+			CloseHandle(tStdin);
+			tStdin = 0;
+			stdin_eof = TRUE;
+
+		} else if (ready_hand == tStdout) {
+
+		  	CloseHandle((HANDLE)pproc->sv_stdout[0]);
+			pproc->sv_stdout[0] = 0;
+			CloseHandle(tStdout);
+			tStdout = 0;
+		  	stdout_eof = TRUE;
+
+		} else if (ready_hand == tStderr) {
+
+			CloseHandle((HANDLE)pproc->sv_stderr[0]);
+			pproc->sv_stderr[0] = 0;
+			CloseHandle(tStderr);
+			tStderr = 0;
+			stderr_eof = TRUE;
+
+		} else if (ready_hand == childhand) {
+
+			DWORD ierr;
+			GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
+			if (ierr == CONTROL_C_EXIT) {
+				pproc->signal = SIGINT;
+			} else {
+				pproc->exit_code = ierr;
+			}
+			if (GetExitCodeResult == FALSE) {
+				pproc->last_err = GetLastError();
+				pproc->lerrno = E_SCALL;
+				goto done;
+			}
+			child_dead = TRUE;
+
+		} else {
+
+			/* ?? Got back a handle we didn't query ?? */
+			pproc->last_err = 0;
+			pproc->lerrno = E_FAIL;
+			goto done;
+		}
+	}
+
+ done:
+	if (tStdin != 0)
+		CloseHandle(tStdin);
+	if (tStdout != 0)
+		CloseHandle(tStdout);
+	if (tStderr != 0)
+		CloseHandle(tStderr);
+
+	if (pproc->lerrno)
+		return(-1);
+	else
+		return(0);
+
+}
+
+/*
+ * Purpose: collects output from child process and returns results
+ *
+ * Description:
+ *
+ * Returns:
+ *
+ * Notes/Dependencies:
+ */
+	long
+process_file_io(
+	HANDLE proc)
+{
+	sub_process *pproc;
+	if (proc == NULL)
+		pproc = process_wait_for_any_private();
+	else
+		pproc = (sub_process *)proc;
+
+	/* some sort of internal error */
+	if (!pproc)
+		return -1;
+
+	return process_file_io_private(proc, TRUE);
+}
+
+/* private function, avoid some kernel calls. (bird) */
+static long
+process_file_io_private(
+	sub_process *pproc,
+	BOOL fNeedToWait)
+{
+	HANDLE childhand;
+	DWORD wait_return;
+	BOOL GetExitCodeResult;
+	DWORD ierr;
+
+	childhand = (HANDLE) pproc->pid;
+
+	/*
+	 * This function is poorly named, and could also be used just to wait
+	 * for child death if you're doing your own pipe I/O.  If that is
+	 * the case, close the pipe handles here.
+	 */
+	if (pproc->sv_stdin[0]) {
+		CloseHandle((HANDLE)pproc->sv_stdin[0]);
+		pproc->sv_stdin[0] = 0;
+	}
+	if (pproc->sv_stdout[0]) {
+		CloseHandle((HANDLE)pproc->sv_stdout[0]);
+		pproc->sv_stdout[0] = 0;
+	}
+	if (pproc->sv_stderr[0]) {
+		CloseHandle((HANDLE)pproc->sv_stderr[0]);
+		pproc->sv_stderr[0] = 0;
+	}
+
+#ifdef KMK
+	if (childhand == NULL || childhand == INVALID_HANDLE_VALUE) {
+		goto done2;
+	}
+#endif
+
+	/*
+	 *  Wait for the child process to exit it we didn't do that already.
+	 */
+	if (fNeedToWait) {
+		wait_return = WaitForSingleObject(childhand, INFINITE);
+		if (wait_return != WAIT_OBJECT_0) {
+/*			map_windows32_error_to_string(GetLastError());*/
+			pproc->last_err = GetLastError();
+			pproc->lerrno = E_SCALL;
+			goto done2;
+		}
+	}
+
+	GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
+	if (ierr == CONTROL_C_EXIT) {
+		pproc->signal = SIGINT;
+	} else {
+		pproc->exit_code = ierr;
+	}
+	if (GetExitCodeResult == FALSE) {
+		pproc->last_err = GetLastError();
+		pproc->lerrno = E_SCALL;
+	}
+
+done2:
+	if (pproc->lerrno)
+		return(-1);
+	else
+		return(0);
+
+}
+
+/*
+ * Description:  Clean up any leftover handles, etc.  It is up to the
+ * caller to manage and free the input, ouput, and stderr buffers.
+ */
+	void
+process_cleanup(
+	HANDLE proc)
+{
+	sub_process *pproc = (sub_process *)proc;
+	int i;
+
+	if (pproc->using_pipes) {
+		for (i= 0; i <= 1; i++) {
+			if ((HANDLE)pproc->sv_stdin[i])
+				CloseHandle((HANDLE)pproc->sv_stdin[i]);
+			if ((HANDLE)pproc->sv_stdout[i])
+				CloseHandle((HANDLE)pproc->sv_stdout[i]);
+			if ((HANDLE)pproc->sv_stderr[i])
+				CloseHandle((HANDLE)pproc->sv_stderr[i]);
+		}
+	}
+	if ((HANDLE)pproc->pid)
+		CloseHandle((HANDLE)pproc->pid);
+
+	free(pproc);
+}
+
+
+/*
+ * Description:
+ *	 Create a command line buffer to pass to CreateProcess
+ *
+ * Returns:  the buffer or NULL for failure
+ *	Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...
+ *  Otherwise:   argv[0] argv[1] argv[2] ...
+ *
+ * Notes/Dependencies:
+ *   CreateProcess does not take an argv, so this command creates a
+ *   command line for the executable.
+ */
+
+static char *
+make_command_line( char *shell_name, char *full_exec_path, char **argv)
+{
+	int		argc = 0;
+	char**		argvi;
+	int*		enclose_in_quotes = NULL;
+	int*		enclose_in_quotes_i;
+	unsigned int	bytes_required = 0;
+	char*		command_line;
+	char*		command_line_i;
+	int  cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */
+	int have_sh = 0; /* HAVE_CYGWIN_SHELL */
+#undef HAVE_CYGWIN_SHELL
+#ifdef HAVE_CYGWIN_SHELL
+	have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe"));
+	cygwin_mode = 1;
+#endif
+
+	if (shell_name && full_exec_path) {
+		bytes_required
+		  = strlen(shell_name) + 1 + strlen(full_exec_path);
+		/*
+		 * Skip argv[0] if any, when shell_name is given.
+		 */
+		if (*argv) argv++;
+		/*
+		 * Add one for the intervening space.
+		 */
+		if (*argv) bytes_required++;
+	}
+
+	argvi = argv;
+	while (*(argvi++)) argc++;
+
+	if (argc) {
+		enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
+
+		if (!enclose_in_quotes) {
+			return NULL;
+		}
+	}
+
+	/* We have to make one pass through each argv[i] to see if we need
+	 * to enclose it in ", so we might as well figure out how much
+	 * memory we'll need on the same pass.
+	 */
+
+	argvi = argv;
+	enclose_in_quotes_i = enclose_in_quotes;
+	while(*argvi) {
+		char* p = *argvi;
+		unsigned int backslash_count = 0;
+
+		/*
+		 * We have to enclose empty arguments in ".
+		 */
+		if (!(*p)) *enclose_in_quotes_i = 1;
+
+		while(*p) {
+			switch (*p) {
+			case '\"':
+				/*
+				 * We have to insert a backslash for each "
+				 * and each \ that precedes the ".
+				 */
+				bytes_required += (backslash_count + 1);
+				backslash_count = 0;
+				break;
+
+#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
+			case '\\':
+				backslash_count++;
+				break;
+#endif
+	/*
+	 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
+	 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
+	 * that argv in always equals argv out. This was removed.  Say you have
+	 * such a program named glob.exe.  You enter
+	 * glob '*'
+	 * at the sh command prompt.  Obviously the intent is to make glob do the
+	 * wildcarding instead of sh.  If we set *enclose_in_quotes_i for '*' or '?',
+	 * then the command line that glob would see would be
+	 * glob "*"
+	 * and the _setargv in SETARGV.OBJ would _not_ expand the *.
+	 */
+			case ' ':
+			case '\t':
+				*enclose_in_quotes_i = 1;
+				/* fall through */
+
+			default:
+				backslash_count = 0;
+				break;
+			}
+
+			/*
+			 * Add one for each character in argv[i].
+			 */
+			bytes_required++;
+
+			p++;
+		}
+
+		if (*enclose_in_quotes_i) {
+			/*
+			 * Add one for each enclosing ",
+			 * and one for each \ that precedes the
+			 * closing ".
+			 */
+			bytes_required += (backslash_count + 2);
+		}
+
+		/*
+		 * Add one for the intervening space.
+		 */
+		if (*(++argvi)) bytes_required++;
+		enclose_in_quotes_i++;
+	}
+
+	/*
+	 * Add one for the terminating NULL.
+	 */
+	bytes_required++;
+#ifdef KMK /* for the space before the final " in case we need it. */
+	bytes_required++;
+#endif
+
+	command_line = (char*) malloc(bytes_required);
+
+	if (!command_line) {
+		if (enclose_in_quotes) free(enclose_in_quotes);
+		return NULL;
+	}
+
+	command_line_i = command_line;
+
+	if (shell_name && full_exec_path) {
+		while(*shell_name) {
+			*(command_line_i++) = *(shell_name++);
+		}
+
+		*(command_line_i++) = ' ';
+
+		while(*full_exec_path) {
+			*(command_line_i++) = *(full_exec_path++);
+		}
+
+		if (*argv) {
+			*(command_line_i++) = ' ';
+		}
+	}
+
+	argvi = argv;
+	enclose_in_quotes_i = enclose_in_quotes;
+
+	while(*argvi) {
+		char* p = *argvi;
+		unsigned int backslash_count = 0;
+
+		if (*enclose_in_quotes_i) {
+			*(command_line_i++) = '\"';
+		}
+
+		while(*p) {
+			if (*p == '\"') {
+				if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */
+					/* instead of a \", cygwin likes "" */
+					*(command_line_i++) = '\"';
+				} else {
+
+					/*
+					 * We have to insert a backslash for the "
+					 * and each \ that precedes the ".
+					 */
+					backslash_count++;
+
+					while(backslash_count) {
+						*(command_line_i++) = '\\';
+						backslash_count--;
+					};
+				}
+#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
+			} else if (*p == '\\') {
+				backslash_count++;
+			} else {
+				backslash_count = 0;
+#endif
+			}
+
+			/*
+			 * Copy the character.
+			 */
+			*(command_line_i++) = *(p++);
+		}
+
+		if (*enclose_in_quotes_i) {
+#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
+			/*
+			 * Add one \ for each \ that precedes the
+			 * closing ".
+			 */
+			while(backslash_count--) {
+				*(command_line_i++) = '\\';
+			};
+#endif
+#ifdef KMK
+                        /*
+                         * ash it put off by echo "hello world" ending up as:
+                         *  G:/.../kmk_ash.exe -c "echo ""hello world"""
+                         * It wants a space before the last '"'.
+			 * (The 'test_shell' goals in Makefile.kmk tests this problem.)
+                         */
+                        if (command_line_i[-1] == '\"' /* && cygwin_mode && have_sh*/ && !argvi[1]) {
+                            *(command_line_i++) = ' ';
+                        }
+#endif
+			*(command_line_i++) = '\"';
+		}
+
+		/*
+		 * Append an intervening space.
+		 */
+		if (*(++argvi)) {
+			*(command_line_i++) = ' ';
+		}
+
+		enclose_in_quotes_i++;
+	}
+
+	/*
+	 * Append the terminating NULL.
+	 */
+	*command_line_i = '\0';
+
+	if (enclose_in_quotes) free(enclose_in_quotes);
+	return command_line;
+}
+
+/*
+ * Description: Given an argv and optional envp, launch the process
+ *              using the default stdin, stdout, and stderr handles.
+ *              Also, register process so that process_wait_for_any_private()
+ *		can be used via process_file_io(NULL) or
+ *		process_wait_for_any().
+ *
+ * Returns:
+ *
+ * Notes/Dependencies:
+ */
+HANDLE
+process_easy(
+	char **argv,
+	char **envp)
+{
+#ifndef KMK
+  HANDLE hIn;
+  HANDLE hOut;
+  HANDLE hErr;
+#endif
+  HANDLE hProcess;
+
+  if (proc_index >= MAXIMUM_WAIT_OBJECTS) {
+	DB (DB_JOBS, ("process_easy: All process slots used up\n"));
+	return INVALID_HANDLE_VALUE;
+  }
+#ifndef KMK
+  if (DuplicateHandle(GetCurrentProcess(),
+                      GetStdHandle(STD_INPUT_HANDLE),
+                      GetCurrentProcess(),
+                      &hIn,
+                      0,
+                      TRUE,
+                      DUPLICATE_SAME_ACCESS) == FALSE) {
+    fprintf(stderr,
+            "process_easy: DuplicateHandle(In) failed (e=%ld)\n",
+            GetLastError());
+    return INVALID_HANDLE_VALUE;
+  }
+  if (DuplicateHandle(GetCurrentProcess(),
+                      GetStdHandle(STD_OUTPUT_HANDLE),
+                      GetCurrentProcess(),
+                      &hOut,
+                      0,
+                      TRUE,
+                      DUPLICATE_SAME_ACCESS) == FALSE) {
+    fprintf(stderr,
+           "process_easy: DuplicateHandle(Out) failed (e=%ld)\n",
+           GetLastError());
+    return INVALID_HANDLE_VALUE;
+  }
+  if (DuplicateHandle(GetCurrentProcess(),
+                      GetStdHandle(STD_ERROR_HANDLE),
+                      GetCurrentProcess(),
+                      &hErr,
+                      0,
+                      TRUE,
+                      DUPLICATE_SAME_ACCESS) == FALSE) {
+    fprintf(stderr,
+            "process_easy: DuplicateHandle(Err) failed (e=%ld)\n",
+            GetLastError());
+    return INVALID_HANDLE_VALUE;
+  }
+
+  hProcess = process_init_fd(hIn, hOut, hErr);
+#else
+  hProcess = process_init_fd(0, 0, 0);
+#endif /* !KMK */
+
+  if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
+    fake_exits_pending++;
+    /* process_begin() failed: make a note of that.  */
+    if (!((sub_process*) hProcess)->last_err)
+      ((sub_process*) hProcess)->last_err = -1;
+#ifdef KMK
+    if (!((sub_process*) hProcess)->exit_code)
+#endif
+      ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
+
+#ifndef KMK
+    /* close up unused handles */
+    CloseHandle(hIn);
+    CloseHandle(hOut);
+    CloseHandle(hErr);
+#endif
+  }
+
+  process_register(hProcess);
+
+  return hProcess;
+}
Index: /tags/kBuild-0.1.4/src/kmk/w32/subproc/w32err.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/subproc/w32err.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/subproc/w32err.c	(revision 1780)
@@ -0,0 +1,71 @@
+/* Error handling for Windows
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+GNU Make; see the file COPYING.  If not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+#include <windows.h>
+#include "w32err.h"
+
+/*
+ * Description: the windows32 version of perror()
+ *
+ * Returns:  a pointer to a static error
+ *
+ * Notes/Dependencies:  I got this from
+ *      comp.os.ms-windows.programmer.win32
+ */
+char *
+map_windows32_error_to_string (DWORD ercode) {
+/* __declspec (thread) necessary if you will use multiple threads on MSVC */
+#ifdef _MSC_VER
+__declspec (thread) static char szMessageBuffer[128];
+#else
+static char szMessageBuffer[128];
+#endif
+	/* Fill message buffer with a default message in
+	 * case FormatMessage fails
+	 */
+    wsprintf (szMessageBuffer, "Error %ld\n", ercode);
+
+	/*
+	 *  Special code for winsock error handling.
+	 */
+	if (ercode > WSABASEERR) {
+		HMODULE hModule = GetModuleHandle("wsock32");
+		if (hModule != NULL) {
+			FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
+				hModule,
+				ercode,
+				LANG_NEUTRAL,
+				szMessageBuffer,
+				sizeof(szMessageBuffer),
+				NULL);
+			FreeLibrary(hModule);
+		}
+	} else {
+		/*
+		 *  Default system message handling
+		 */
+    	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+                  NULL,
+                  ercode,
+                  LANG_NEUTRAL,
+                  szMessageBuffer,
+                  sizeof(szMessageBuffer),
+                  NULL);
+	}
+    return szMessageBuffer;
+}
+
Index: /tags/kBuild-0.1.4/src/kmk/w32/tstFileInfo.c
===================================================================
--- /tags/kBuild-0.1.4/src/kmk/w32/tstFileInfo.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/kmk/w32/tstFileInfo.c	(revision 1780)
@@ -0,0 +1,124 @@
+
+#include <stdio.h>
+#include <Windows.h>
+
+typedef enum _FILE_INFORMATION_CLASS {
+    FileDirectoryInformation       = 1,
+    FileFullDirectoryInformation,   // 2
+    FileBothDirectoryInformation,   // 3
+    FileBasicInformation,           // 4  wdm
+    FileStandardInformation,        // 5  wdm
+    FileInternalInformation,        // 6
+    FileEaInformation,              // 7
+    FileAccessInformation,          // 8
+    FileNameInformation,            // 9
+    FileRenameInformation,          // 10
+    FileLinkInformation,            // 11
+    FileNamesInformation,           // 12
+    FileDispositionInformation,     // 13
+    FilePositionInformation,        // 14 wdm
+    FileFullEaInformation,          // 15
+    FileModeInformation,            // 16
+    FileAlignmentInformation,       // 17
+    FileAllInformation,             // 18
+    FileAllocationInformation,      // 19
+    FileEndOfFileInformation,       // 20 wdm
+    FileAlternateNameInformation,   // 21
+    FileStreamInformation,          // 22
+    FilePipeInformation,            // 23
+    FilePipeLocalInformation,       // 24
+    FilePipeRemoteInformation,      // 25
+    FileMailslotQueryInformation,   // 26
+    FileMailslotSetInformation,     // 27
+    FileCompressionInformation,     // 28
+    FileObjectIdInformation,        // 29
+    FileCompletionInformation,      // 30
+    FileMoveClusterInformation,     // 31
+    FileQuotaInformation,           // 32
+    FileReparsePointInformation,    // 33
+    FileNetworkOpenInformation,     // 34
+    FileAttributeTagInformation,    // 35
+    FileTrackingInformation,        // 36
+    FileIdBothDirectoryInformation, // 37
+    FileIdFullDirectoryInformation, // 38
+    FileMaximumInformation
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef struct _FILE_NAME_INFORMATION
+{
+    ULONG FileNameLength;
+    WCHAR FileName[1];
+} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
+
+typedef LONG NTSTATUS;
+
+typedef struct _IO_STATUS_BLOCK 
+{
+    union
+    {
+        NTSTATUS Status;
+        PVOID Pointer;
+    };
+    ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+NTSYSAPI 
+NTSTATUS
+NTAPI
+NtQueryInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, 
+                       ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); 
+
+
+
+int main(int argc, char **argv)
+{
+    int rc = 0;
+    int i;
+
+    NTSTATUS (NTAPI *pfnNtQueryInformationFile)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation,  
+                                                ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); 
+
+    pfnNtQueryInformationFile = GetProcAddress(LoadLibrary("ntdll.dll"), "NtQueryInformationFile");
+
+    for (i = 1; i < argc; i++)
+    {
+        HANDLE hFile = CreateFile(argv[i],
+                                  GENERIC_READ,
+                                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                                  NULL,
+                                  OPEN_EXISTING,
+                                  FILE_FLAG_BACKUP_SEMANTICS,
+                                  NULL);
+        if (hFile)
+        {
+            long rcNt;
+            char abBuf[4096];
+            IO_STATUS_BLOCK Ios;
+
+            memset(abBuf, 0, sizeof(abBuf));
+            memset(&Ios, 0, sizeof(Ios));
+            rcNt = pfnNtQueryInformationFile(hFile, &Ios, abBuf, sizeof(abBuf), FileNameInformation);
+            if (rcNt >= 0)
+            {
+                PFILE_NAME_INFORMATION pFileNameInfo = (PFILE_NAME_INFORMATION)abBuf;
+                printf("#%d: %s - rcNt=%#x - FileNameInformation:\n"
+                       "        FileName: %ls\n"
+                       "  FileNameLength: %lu\n", 
+                       i, argv[i], rcNt, 
+                       pFileNameInfo->FileName, 
+                       pFileNameInfo->FileNameLength
+                       );
+            }
+            else
+                printf("#%d: %s - rcNt=%#x - FileNameInformation!\n", i, argv[i], rcNt);
+
+            CloseHandle(hFile);
+        }
+        else
+        {
+            printf("#%d: %s - open failed, last error %d\n", i, argv[i], GetLastError());
+            rc = 1;
+        }
+    }
+    return rc;
+}
Index: /tags/kBuild-0.1.4/src/lib/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/lib/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/Makefile.kmk	(revision 1780)
@@ -0,0 +1,55 @@
+# $Id$
+## @file
+# Sub-makefile for various libraries and stuff.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../..
+include $(KBUILD_PATH)/subheader.kmk
+
+LIBRARIES += kDep
+kDep_TEMPLATE = LIB
+kDep_DEFS.win += NEED_ISBLANK=1 __WIN32__=1
+kDep_SOURCES = kDep.c
+kDep_SOURCES.win = nt_fullpath.c
+kDep_NOINST = 1
+
+LIBRARIES += kUtil
+kUtil_TEMPLATE = LIB
+kUtil_DEFS.win = __WIN__
+kUtil_SOURCES = crc32.c md5.c
+kUtil_SOURCES.win = nt_fullpath.c
+kUtil_NOINST = 1
+
+LIBRARIES.win += kWinStartup
+kWinStartup_TEMPLATE = LIB
+kWinStartup_SOURCES = startuphacks-win.c
+kWinStartup_NOINST = 1
+
+PROGRAMS += wrapper
+wrapper_TEMPLATE = BIN
+wrapper_SOURCES = wrapper.c
+wrapper_NOINST = 1
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
Index: /tags/kBuild-0.1.4/src/lib/crc32.c
===================================================================
--- /tags/kBuild-0.1.4/src/lib/crc32.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/crc32.c	(revision 1780)
@@ -0,0 +1,170 @@
+/*	$NetBSD: crc.c,v 1.18 2006/09/04 20:01:10 dsl Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif*/
+
+/*#include <sys/cdefs.h> 
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)crc.c	8.1 (Berkeley) 6/17/93";
+#else 
+__RCSID("$NetBSD: crc.c,v 1.18 2006/09/04 20:01:10 dsl Exp $");
+#endif
+#endif*/ /* not lint */
+
+#include <sys/types.h>
+/*#include <unistd.h>
+
+#include "extern.h"*/
+
+#include "mytypes.h"
+#define u_int32_t uint32_t
+
+static const u_int32_t crctab[] = {
+	0x0,
+	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
+	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
+	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
+	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
+	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
+	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
+	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
+	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
+	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
+	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
+	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
+	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
+	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
+	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
+	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
+	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
+	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
+	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
+	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
+	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
+	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
+	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
+	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
+	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
+	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
+	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
+	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
+	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
+	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
+	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
+	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
+	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
+	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
+	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+#if 0
+/*
+ * Compute a POSIX 1003.2 checksum.  This routine has been broken out so that
+ * other programs can use it.  It takes a file descriptor to read from and
+ * locations to store the crc and the number of bytes read.  It returns 0 on
+ * success and 1 on failure.  Errno is set on failure.
+ */
+int
+crc(int fd, u_int32_t *cval, off_t *clen)
+{
+	u_char *p;
+	int nr;
+	u_int32_t thecrc;
+	off_t len;
+	u_char buf[16 * 1024];
+#endif 
+#define	COMPUTE(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
+#if 0
+
+	thecrc = 0;
+	len = 0;
+	while ((nr = read(fd, buf, sizeof(buf))) > 0)
+		for (len += nr, p = buf; nr--; ++p) {
+			COMPUTE(thecrc, *p);
+		}
+	if (nr < 0)
+		return 1;
+
+	*clen = len;
+
+	/* Include the length of the file. */
+	for (; len != 0; len >>= 8) {
+		COMPUTE(thecrc, len & 0xff);
+	}
+
+	*cval = ~thecrc;
+	return 0;
+}
+#endif
+
+/* These two are rather more useful to the outside world */
+
+uint32_t
+crc32(uint32_t thecrc, const void *buf, size_t len)
+{
+	const uint8_t *p = buf;
+
+	for (p = buf; len; p++, len--)
+		COMPUTE(thecrc, *p);
+	return thecrc;
+}
+
+#if 0
+uint32_t
+crc_byte(uint32_t thecrc, unsigned int byte_val)
+{
+	COMPUTE(thecrc, byte_val & 0xff);
+	return thecrc;
+}
+#endif
Index: /tags/kBuild-0.1.4/src/lib/crc32.h
===================================================================
--- /tags/kBuild-0.1.4/src/lib/crc32.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/crc32.h	(revision 1780)
@@ -0,0 +1,7 @@
+#ifndef ___crc32_h__
+#define ___crc32_h__
+
+#include "mytypes.h"
+uint32_t crc32(uint32_t, const void *, size_t);
+
+#endif
Index: /tags/kBuild-0.1.4/src/lib/k/kDefs.h
===================================================================
--- /tags/kBuild-0.1.4/src/lib/k/kDefs.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/k/kDefs.h	(revision 1780)
@@ -0,0 +1,528 @@
+/* $Id: kDefs.h 15 2008-05-05 22:14:33Z bird $ */
+/** @file
+ *
+ * kTypes - Defines and Macros.
+ *
+ * Copyright (c) 2007-2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of k*.
+ *
+ * k* 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 of the License, or
+ * (at your option) any later version.
+ *
+ * k* 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 k*; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___k_kDefs_h___
+#define ___k_kDefs_h___
+
+/** @defgroup grp_kDefs  kDefs - Defines and Macros
+ * @{ */
+
+/** @name Operative System Identifiers.
+ * These are the value that the K_OS \#define can take.
+ * @{
+ */
+/** Unknown OS. */
+#define K_OS_UNKNOWN    0
+/** Darwin - aka Mac OS X. */
+#define K_OS_DARWIN     1
+/** DragonFly BSD. */
+#define K_OS_DRAGONFLY  2
+/** FreeBSD. */
+#define K_OS_FREEBSD    3
+/** Linux. */
+#define K_OS_LINUX      4
+/** NetBSD. */
+#define K_OS_NETBSD     5
+/** NT (native). */
+#define K_OS_NT         6
+/** OpenBSD*/
+#define K_OS_OPENBSD    7
+/** OS/2 */
+#define K_OS_OS2        8
+/** Solaris */
+#define K_OS_SOLARIS    9
+/** Windows. */
+#define K_OS_WINDOWS    10
+/** The max K_OS_* value (exclusive). */
+#define K_OS_MAX        11
+/** @} */
+
+/** @def K_OS
+ * Indicates which OS we're targetting. It's a \#define with is
+ * assigned one of the K_OS_* defines above.
+ *
+ * So to test if we're on FreeBSD do the following:
+ * @code
+ *  #if K_OS == K_OS_FREEBSD
+ *  some_funky_freebsd_specific_stuff();
+ *  #endif
+ * @endcode
+ */
+#ifndef K_OS
+# if defined(__APPLE__)
+#  define K_OS      K_OS_DARWIN
+# elif defined(__DragonFly__)
+#  define K_OS      K_OS_DRAGONFLY
+# elif defined(__FreeBSD__) /*??*/
+#  define K_OS      K_OS_FREEBSD
+# elif defined(__gnu_linux__)
+#  define K_OS      K_OS_LINUX
+# elif defined(__NetBSD__) /*??*/
+#  define K_OS      K_OS_NETBSD
+# elif defined(__OpenBSD__) /*??*/
+#  define K_OS      K_OS_OPENBSD
+# elif defined(__OS2__)
+#  define K_OS      K_OS_OS2
+# elif defined(__sun__) || defined(__SunOS__) || defined(__sun) || defined(__SunOS)
+#  define K_OS      K_OS_SOLARIS
+# elif defined(_WIN32) || defined(_WIN64)
+#  define K_OS      K_OS_WINDOWS
+# else
+#  error "Port Me"
+# endif
+#endif
+#if K_OS < K_OS_UNKNOWN || K_OS >= K_OS_MAX
+# error "Invalid K_OS value."
+#endif
+
+
+
+/** @name   Architecture bit width.
+ * @{ */
+#define K_ARCH_BIT_8            0x0100  /**< 8-bit */
+#define K_ARCH_BIT_16           0x0200  /**< 16-bit */
+#define K_ARCH_BIT_32           0x0400  /**< 32-bit */
+#define K_ARCH_BIT_64           0x0800  /**< 64-bit */
+#define K_ARCH_BIT_128          0x1000  /**< 128-bit */
+#define K_ARCH_BIT_MASK         0x1f00  /**< The bit mask. */
+#define K_ARCH_BIT_SHIFT        5       /**< Shift count for producing the width in bits. */
+#define K_ARCH_BYTE_SHIFT       8       /**< Shift count for producing the width in bytes. */
+/** @} */
+
+/** @name   Architecture Endianness.
+ * @{ */
+#define K_ARCH_END_LITTLE       0x2000  /**< Little-endian. */
+#define K_ARCH_END_BIG          0x4000  /**< Big-endian. */
+#define K_ARCH_END_BI           0x6000  /**< Bi-endian, can be switched. */
+#define K_ARCH_END_MASK         0x6000  /**< The endian mask. */
+#define K_ARCH_END_SHIFT        13      /**< Shift count for converting between this K_ENDIAN_*. */
+/** @} */
+
+/** @name Architecture Identifiers.
+ * These are the value that the K_ARCH \#define can take.
+ *@{ */
+/** Unknown CPU architecture. */
+#define K_ARCH_UNKNOWN          ( 0 )
+/** Clone or Intel 16-bit x86. */
+#define K_ARCH_X86_16           ( 1 | K_ARCH_BIT_16 | K_ARCH_END_LITTLE)
+/** Clone or Intel 32-bit x86. */
+#define K_ARCH_X86_32           ( 2 | K_ARCH_BIT_32 | K_ARCH_END_LITTLE)
+/** AMD64 (including clones). */
+#define K_ARCH_AMD64            ( 3 | K_ARCH_BIT_64 | K_ARCH_END_LITTLE)
+/** Itanic (64-bit). */
+#define K_ARCH_IA64             ( 4 | K_ARCH_BIT_64 | K_ARCH_END_BI)
+/** ALPHA (64-bit). */
+#define K_ARCH_ALPHA            ( 5 | K_ARCH_BIT_64 | K_ARCH_END_BI)
+/** ALPHA limited to 32-bit. */
+#define K_ARCH_ALPHA_32         ( 6 | K_ARCH_BIT_32 | K_ARCH_END_BI)
+/** 32-bit ARM. */
+#define K_ARCH_ARM_32           ( 7 | K_ARCH_BIT_32 | K_ARCH_END_BI)
+/** 64-bit ARM. */
+#define K_ARCH_ARM_64           ( 8 | K_ARCH_BIT_64 | K_ARCH_END_BI)
+/** 32-bit MIPS. */
+#define K_ARCH_MIPS_32          ( 9 | K_ARCH_BIT_32 | K_ARCH_END_BI)
+/** 64-bit MIPS. */
+#define K_ARCH_MIPS_64          (10 | K_ARCH_BIT_64 | K_ARCH_END_BI)
+/** 32-bit PA-RISC. */
+#define K_ARCH_PARISC_32        (11 | K_ARCH_BIT_32 | K_ARCH_END_BI)
+/** 64-bit PA-RISC. */
+#define K_ARCH_PARISC_64        (12 | K_ARCH_BIT_64 | K_ARCH_END_BI)
+/** 32-bit PowerPC. */
+#define K_ARCH_POWERPC_32       (13 | K_ARCH_BIT_32 | K_ARCH_END_BI)
+/** 64-bit PowerPC. */
+#define K_ARCH_POWERPC_64       (14 | K_ARCH_BIT_64 | K_ARCH_END_BI)
+/** 32(31)-bit S390. */
+#define K_ARCH_S390_32          (15 | K_ARCH_BIT_32 | K_ARCH_END_BIG)
+/** 64-bit S390. */
+#define K_ARCH_S390_64          (16 | K_ARCH_BIT_64 | K_ARCH_END_BIG)
+/** 32-bit SPARC. */
+#define K_ARCH_SPARC_32         (17 | K_ARCH_BIT_32 | K_ARCH_END_BIG)
+/** 64-bit SPARC. */
+#define K_ARCH_SPARC_64         (18 | K_ARCH_BIT_64 | K_ARCH_END_BI)
+/** The end of the valid architecture values (exclusive). */
+#define K_ARCH_MAX              (19)
+/** @} */
+
+
+/** @def K_ARCH
+ * The value of this \#define indicates which architecture we're targetting.
+ */
+#ifndef K_ARCH
+  /* detection based on compiler defines. */
+# if defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64)
+#  define K_ARCH    K_ARCH_AMD64
+# elif defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386)
+#  define K_ARCH    K_ARCH_X86_32
+# elif defined(__ia64__) || defined(__IA64__) || defined(_M_IA64)
+#  define K_ARCH    K_ARCH_IA64
+# elif defined(__alpha__)
+#  define K_ARCH    K_ARCH_ALPHA
+# elif defined(__arm__) || defined(__arm32__)
+#  define K_ARCH    K_ARCH_ARM_32
+# elif defined(__hppa__) && defined(__LP64__)
+#  define K_ARCH    K_ARCH_PARISC_64
+# elif defined(__hppa__)
+#  define K_ARCH    K_ARCH_PARISC_32
+# elif defined(__mips64)
+#  define K_ARCH    K_ARCH_MIPS_64
+# elif defined(__mips__)
+#  define K_ARCH    K_ARCH_MIPS_32
+# elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
+#  define K_ARCH    K_ARCH_POWERPC_64
+# elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
+#  define K_ARCH    K_ARCH_POWERPC_32
+# elif defined(__sparcv9__) || defined(__sparcv9)
+#  define K_ARCH    K_ARCH_SPARC_64
+# elif defined(__sparc__) || defined(__sparc)
+#  define K_ARCH    K_ARCH_SPARC_32
+# elif defined(__s390x__)
+#  define K_ARCH    K_ARCH_S390_64
+# elif defined(__s390__)
+#  define K_ARCH    K_ARCH_S390_32
+# else
+#  error "Port Me"
+# endif
+#else
+  /* validate the user specified value. */
+# if (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_8 \
+  && (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_16 \
+  && (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_32 \
+  && (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_64 \
+  && (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_128
+#  error "Invalid K_ARCH value (bit)"
+# endif
+# if (K_ARCH & K_ARCH_END_MASK) != K_ARCH_END_LITTLE \
+  && (K_ARCH & K_ARCH_END_MASK) != K_ARCH_END_BIG \
+  && (K_ARCH & K_ARCH_END_MASK) != K_ARCH_END_BI
+#  error "Invalid K_ARCH value (endian)"
+# endif
+# if (K_ARCH & ~(K_ARCH_BIT_MASK | K_ARCH_BIT_END_MASK)) < K_ARCH_UNKNOWN \
+  || (K_ARCH & ~(K_ARCH_BIT_MASK | K_ARCH_BIT_END_MASK)) >= K_ARCH_MAX
+#  error "Invalid K_ARCH value"
+# endif
+#endif
+
+/** @def K_ARCH_IS_VALID
+ * Check if the architecture identifier is valid.
+ * @param   arch            The K_ARCH_* define to examin.
+ */
+#define K_ARCH_IS_VALID(arch)   (   (   ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_8 \
+                                     || ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_16 \
+                                     || ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_32 \
+                                     || ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_64 \
+                                     || ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_128) \
+                                 && \
+                                    (   ((arch) & K_ARCH_END_MASK) == K_ARCH_END_LITTLE \
+                                     || ((arch) & K_ARCH_END_MASK) == K_ARCH_END_BIG \
+                                     || ((arch) & K_ARCH_END_MASK) == K_ARCH_END_BI) \
+                                 && \
+                                    (   ((arch) & ~(K_ARCH_BIT_MASK | K_ARCH_END_MASK)) >= K_ARCH_UNKNOWN \
+                                     && ((arch) & ~(K_ARCH_BIT_MASK | K_ARCH_END_MASK)) < K_ARCH_MAX) \
+                                )
+
+/** @def K_ARCH_BITS_EX
+ * Determin the architure byte width of the specified architecture.
+ * @param   arch            The K_ARCH_* define to examin.
+ */
+#define K_ARCH_BITS_EX(arch)    ( ((arch) & K_ARCH_BIT_MASK) >> K_ARCH_BIT_SHIFT )
+
+/** @def K_ARCH_BYTES_EX
+ * Determin the architure byte width of the specified architecture.
+ * @param   arch            The K_ARCH_* define to examin.
+ */
+#define K_ARCH_BYTES_EX(arch)   ( ((arch) & K_ARCH_BIT_MASK) >> K_ARCH_BYTE_SHIFT )
+
+/** @def K_ARCH_ENDIAN_EX
+ * Determin the K_ENDIAN value for the specified architecture.
+ * @param   arch            The K_ARCH_* define to examin.
+ */
+#define K_ARCH_ENDIAN_EX(arch)  ( ((arch) & K_ARCH_END_MASK) >> K_ARCH_END_SHIFT )
+
+/** @def K_ARCH_BITS
+ * Determin the target architure bit width.
+ */
+#define K_ARCH_BITS             K_ARCH_BITS_EX(K_ARCH)
+
+/** @def K_ARCH_BYTES
+ * Determin the target architure byte width.
+ */
+#define K_ARCH_BYTES            K_ARCH_BYTES_EX(K_ARCH)
+
+/** @def K_ARCH_ENDIAN
+ * Determin the target K_ENDIAN value.
+ */
+#define K_ARCH_ENDIAN           K_ARCH_ENDIAN_EX(K_ARCH)
+
+
+
+/** @name Endianness Identifiers.
+ * These are the value that the K_ENDIAN \#define can take.
+ * @{ */
+#define K_ENDIAN_LITTLE         1       /**< Little-endian. */
+#define K_ENDIAN_BIG            2       /**< Big-endian. */
+#define K_ENDIAN_BI             3       /**< Bi-endian, can be switched. Only used with K_ARCH. */
+/** @} */
+
+/** @def K_ENDIAN
+ * The value of this \#define indicates the target endianness.
+ *
+ * @remark  It's necessary to define this (or add the necessary dection here)
+ *          on bi-endian architectures.
+ */
+#ifndef K_ENDIAN
+  /* use K_ARCH if possible. */
+# if K_ARCH_END != K_ENDIAN_BI
+#  define K_ENDIAN K_ARCH_ENDIAN
+# else
+#  error "Port Me or define K_ENDIAN."
+# endif
+#else
+  /* validate the user defined value. */
+# if K_ENDIAN != K_ENDIAN_LITTLE
+  && K_ENDIAN != K_ENDIAN_BIG
+#  error "K_ENDIAN must either be defined as K_ENDIAN_LITTLE or as K_ENDIAN_BIG."
+# endif
+#endif
+
+/** @name Endian Conversion
+ * @{ */
+
+/** @def K_E2E_U16
+ * Convert the endian of an unsigned 16-bit value. */
+# define K_E2E_U16(u16)         ( (KU16) (((u16) >> 8) | ((u16) << 8)) )
+/** @def K_E2E_U32
+ * Convert the endian of an unsigned 32-bit value. */
+# define K_E2E_U32(u32)         (   ( ((u32) & KU32_C(0xff000000)) >> 24 ) \
+                                  | ( ((u32) & KU32_C(0x00ff0000)) >>  8 ) \
+                                  | ( ((u32) & KU32_C(0x0000ff00)) <<  8 ) \
+                                  | ( ((u32) & KU32_C(0x000000ff)) << 24 ) \
+                                )
+/** @def K_E2E_U64
+ * Convert the endian of an unsigned 64-bit value. */
+# define K_E2E_U64(u64)         (   ( ((u64) & KU64_C(0xff00000000000000)) >> 56 ) \
+                                  | ( ((u64) & KU64_C(0x00ff000000000000)) >> 40 ) \
+                                  | ( ((u64) & KU64_C(0x0000ff0000000000)) >> 24 ) \
+                                  | ( ((u64) & KU64_C(0x000000ff00000000)) >>  8 ) \
+                                  | ( ((u64) & KU64_C(0x00000000ff000000)) <<  8 ) \
+                                  | ( ((u64) & KU64_C(0x0000000000ff0000)) << 24 ) \
+                                  | ( ((u64) & KU64_C(0x000000000000ff00)) << 40 ) \
+                                  | ( ((u64) & KU64_C(0x00000000000000ff)) << 56 ) \
+                                )
+
+/** @def K_LE2H_U16
+ * Unsigned 16-bit little-endian to host endian. */
+/** @def K_LE2H_U32
+ * Unsigned 32-bit little-endian to host endian. */
+/** @def K_LE2H_U64
+ * Unsigned 64-bit little-endian to host endian. */
+/** @def K_BE2H_U16
+ * Unsigned 16-bit big-endian to host endian. */
+/** @def K_BE2H_U32
+ * Unsigned 32-bit big-endian to host endian. */
+/** @def K_BE2H_U64
+ * Unsigned 64-bit big-endian to host endian. */
+#if K_ENDIAN == K_ENDIAN_LITTLE
+# define K_LE2H_U16(u16)        ((KU16)(u16))
+# define K_LE2H_U32(u32)        ((KU32)(u32))
+# define K_LE2H_U64(u64)        ((KU64)(u32))
+# define K_BE2H_U16(u16)        K_E2E_U16(u16)
+# define K_BE2H_U32(u32)        K_E2E_U32(u32)
+# define K_BE2H_U64(u64)        K_E2E_U64(u64)
+#else
+# define K_LE2H_U16(u16)        K_E2E_U16(u16)
+# define K_LE2H_U32(u32)        K_E2E_U32(u32)
+# define K_LE2H_U32(u64)        K_E2E_U64(u64)
+# define K_BE2H_U16(u16)        ((KU16)(u16))
+# define K_BE2H_U32(u32)        ((KU32)(u32))
+# define K_BE2H_U64(u64)        ((KU64)(u32))
+#endif
+
+
+
+/** @def K_INLINE
+ * How to say 'inline' in both C and C++ dialects.
+ * @param   type        The return type.
+ */
+#ifdef __cplusplus
+# if defined(__GNUC__)
+#  define K_INLINE              static inline
+# else
+#  define K_INLINE              inline
+# endif
+#else
+# if defined(__GNUC__)
+#  define K_INLINE              static __inline__
+# elif defined(_MSC_VER)
+#  define K_INLINE              static _Inline
+# else
+#  error "Port Me"
+# endif
+#endif
+
+/** @def K_EXPORT
+ * What to put in front of an exported function.
+ */
+#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+# define K_EXPORT               __declspec(dllexport)
+#else
+# define K_EXPORT
+#endif
+
+/** @def K_IMPORT
+ * What to put in front of an imported function.
+ */
+#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+# define K_IMPORT               __declspec(dllimport)
+#else
+# define K_IMPORT               extern
+#endif
+
+/** @def K_DECL_EXPORT
+ * Declare an exported function.
+ * @param type      The return type.
+ */
+#define K_DECL_EXPORT(type)     K_EXPORT type
+
+/** @def K_DECL_IMPORT
+ * Declare an import function.
+ * @param type      The return type.
+ */
+#define K_DECL_IMPORT(type)     K_IMPORT type
+
+/** @def K_DECL_INLINE
+ * Declare an inline function.
+ * @param type      The return type.
+ * @remark  Don't use on (class) methods.
+ */
+#define K_DECL_INLINE(type)     K_INLINE type
+
+
+/** Get the minimum of two values. */
+#define K_MIN(a, b)             ( (a) <= (b) ? (a) : (b) )
+/** Get the maximum of two values. */
+#define K_MAX(a, b)             ( (a) >= (b) ? (a) : (b) )
+/** Calculate the offset of a structure member. */
+#define K_OFFSETOF(strct, memb) ( (KSIZE)( &((strct *)0)->memb ) )
+/** Align a size_t value. */
+#define K_ALIGN_Z(val, align)   ( ((val) + ((align) - 1)) & ~(KSIZE)((align) - 1) )
+/** Align a void * value. */
+#define K_ALIGN_P(pv, align)    ( (void *)( ((KUPTR)(pv) + ((align) - 1)) & ~(KUPTR)((align) - 1) ) )
+/** Number of elements in an array. */
+#define K_ELEMENTS(a)           ( sizeof(a) / sizeof((a)[0]) )
+/** Checks if the specified pointer is a valid address or not. */
+#define K_VALID_PTR(ptr)        ( (KUPTR)(ptr) + 0x1000U >= 0x2000U )
+/** Makes a 32-bit bit mask. */
+#define K_BIT32(bit)            ( KU32_C(1) << (bit))
+/** Makes a 64-bit bit mask. */
+#define K_BIT64(bit)            ( KU64_C(1) << (bit))
+/** Shuts up unused parameter and unused variable warnings. */
+#define K_NOREF(var)            ( (void)(var) )
+
+
+/** @name Parameter validation macros
+ * @{ */
+
+/** Return/Crash validation of a string argument. */
+#define K_VALIDATE_STRING(str) \
+    do { \
+        if (!K_VALID_PTR(str)) \
+            return KERR_INVALID_POINTER; \
+        kHlpStrLen(str); \
+    } while (0)
+
+/** Return/Crash validation of an optional string argument. */
+#define K_VALIDATE_OPTIONAL_STRING(str) \
+    do { \
+        if (str) \
+            K_VALIDATE_STRING(str); \
+    } while (0)
+
+/** Return/Crash validation of an output buffer. */
+#define K_VALIDATE_BUFFER(buf, cb) \
+    do { \
+        if (!K_VALID_PTR(buf)) \
+            return KERR_INVALID_POINTER; \
+        if ((cb) != 0) \
+        { \
+            KU8             __b; \
+            KU8 volatile   *__pb = (KU8 volatile *)(buf); \
+            KSIZE           __cbPage1 = 0x1000 - ((KUPTR)(__pb) & 0xfff); /* ASSUMES page size! */ \
+            __b = *__pb; *__pb = 0xff; *__pb = __b; \
+            if ((cb) > __cbPage1) \
+            { \
+                KSIZE __cb = (cb) - __cbPage1; \
+                __pb -= __cbPage1; \
+                for (;;) \
+                { \
+                    __b = *__pb; *__pb = 0xff; *__pb = __b; \
+                    if (__cb < 0x1000) \
+                        break; \
+                    __pb += 0x1000; \
+                    __cb -= 0x1000; \
+                } \
+            } \
+        } \
+        else \
+            return KERR_INVALID_PARAMETER; \
+    } while (0)
+
+/** Return/Crash validation of an optional output buffer. */
+#define K_VALIDATE_OPTIONAL_BUFFER(buf, cb) \
+    do { \
+        if ((buf) && (cb) != 0) \
+            K_VALIDATE_BUFFER(buf, cb); \
+    } while (0)
+
+/** Return validation of an enum argument. */
+#define K_VALIDATE_ENUM(arg, enumname) \
+    do { \
+        if ((arg) <= enumname##_INVALID || (arg) >= enumname##_END) \
+            return KERR_INVALID_PARAMETER; \
+    } while (0)
+
+/** Return validation of a flags argument. */
+#define K_VALIDATE_FLAGS(arg, AllowedMask) \
+    do { \
+        if ((arg) & ~(AllowedMask)) \
+            return KERR_INVALID_PARAMETER; \
+    } while (0)
+
+/** @} */
+
+/** @def NULL
+ * The nil pointer value. */
+#ifndef NULL
+# ifdef __cplusplus
+#  define NULL          0
+# else
+#  define NULL          ((void *)0)
+# endif
+#endif
+
+/** @} */
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/lib/k/kTypes.h
===================================================================
--- /tags/kBuild-0.1.4/src/lib/k/kTypes.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/k/kTypes.h	(revision 1780)
@@ -0,0 +1,402 @@
+/* $Id: kTypes.h 3610 2007-10-29 03:33:14Z bird $ */
+/** @file
+ *
+ * kTypes - Typedefs And Related Constants And Macros.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kStuff.
+ *
+ * kStuff 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 of the License, or
+ * (at your option) any later version.
+ *
+ * kStuff 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 kStuff; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___k_kTypes_h___
+#define ___k_kTypes_h___
+
+#include <k/kDefs.h>
+
+/** @defgroup grp_kTypes    kTypes - Typedefs And Related Constants And Macros
+ * @{
+ */
+
+/** @typedef KI64
+ * 64-bit signed integer. */
+/** @typedef KU64
+ * 64-bit unsigned integer. */
+/** @def KI64_C
+ * 64-bit signed integer constant.
+ * @param c         The constant value. */
+/** @def KU64_C
+ * 64-bit unsigned integer constant.
+ * @param c         The constant value. */
+/** @def KI64_PRI
+ * 64-bit signed integer printf format. */
+/** @def KU64_PRI
+ * 64-bit unsigned integer printf format. */
+/** @def KX64_PRI
+ * 64-bit signed and unsigned integer hexadecimal printf format. */
+
+/** @typedef KI32
+ * 32-bit signed integer. */
+/** @typedef KU32
+ * 32-bit unsigned integer. */
+/** @def KI32_C
+ * 32-bit signed integer constant.
+ * @param c         The constant value. */
+/** @def KU32_C
+ * 32-bit unsigned integer constant.
+ * @param c         The constant value. */
+/** @def KI32_PRI
+ * 32-bit signed integer printf format. */
+/** @def KU32_PRI
+ * 32-bit unsigned integer printf format. */
+/** @def KX32_PRI
+ * 32-bit signed and unsigned integer hexadecimal printf format. */
+
+/** @typedef KI16
+ * 16-bit signed integer. */
+/** @typedef KU16
+ * 16-bit unsigned integer. */
+/** @def KI16_C
+ * 16-bit signed integer constant.
+ * @param c         The value. */
+/** @def KU16_C
+ * 16-bit unsigned integer constant.
+ * @param c         The value. */
+/** @def KI16_PRI
+ * 16-bit signed integer printf format. */
+/** @def KU16_PRI
+ * 16-bit unsigned integer printf format. */
+/** @def KX16_PRI
+ * 16-bit signed and unsigned integer hexadecimal printf format. */
+
+/** @typedef KI8
+ * 8-bit signed integer. */
+/** @typedef KU8
+ * 8-bit unsigned integer. */
+/** @def KI8_C
+ * 8-bit signed integer constant.
+ * @param c         The constant value. */
+/** @def KU8_C
+ * 8-bit unsigned integer constant.
+ * @param c         The constant value. */
+/** @def KI8_PRI
+ * 8-bit signed integer printf format. */
+/** @def KU8_PRI
+ * 8-bit unsigned integer printf format. */
+/** @def KX8_PRI
+ * 8-bit signed and unsigned integer hexadecimal printf format. */
+
+/** @typedef KSIZE
+ * Memory size type; unsigned integer. */
+/** @typedef KSSIZE
+ * Memory size type; signed integer. */
+/** @def KSIZE_C
+ * Memory size constant.
+ * @param c         The constant value. */
+/** @def KSSIZE_C
+ * Memory size constant.
+ * @param c         The constant value. */
+/** @def KSIZE_MAX
+ * Memory size max constant.*/
+/** @def KSSIZE_MAX
+ * Memory size max constant.*/
+/** @def KSSIZE_MIN
+ * Memory size min constant.*/
+/** @def KSIZE_PRI
+ * Memory size printf format. */
+/** @def KSSIZE_PRI
+ * Memory size printf format. */
+
+/** @typedef KIPTR
+ * Signed integer type capable of containing a pointer value.  */
+/** @typedef KUPTR
+ * Unsigned integer type capable of containing a pointer value.  */
+/** @def KIPTR_C
+ * Signed pointer constant.
+ * @param c         The constant value. */
+/** @def KUPTR_C
+ * Unsigned pointer constant.
+ * @param c         The constant value. */
+/** @def KIPTR_MAX
+ * Signed pointer max constant.*/
+/** @def KIPTR_MIN
+ * Signed pointer min constant.*/
+/** @def KUPTR_MAX
+ * Unsigned pointer max constant.*/
+/** @def KIPTR_PRI
+ * Signed pointer printf format. */
+/** @def KUPTR_PRI
+ * Unsigned pointer printf format. */
+
+
+#if K_ARCH_BITS == 32
+  /* ASSUMES int == long == 32-bit, short == 16-bit, char == 8-bit. */
+# ifdef _MSC_VER
+typedef signed __int64          KI64;
+typedef unsigned __int64        KU64;
+#define KI64_PRI                "I64d"
+#define KU64_PRI                "I64u"
+#define KX64_PRI                "I64x"
+# else
+typedef signed long long int    KI64;
+typedef unsigned long long int  KU64;
+#define KI64_PRI                "lld"
+#define KU64_PRI                "llu"
+#define KX64_PRI                "llx"
+# endif
+typedef signed int              KI32;
+typedef unsigned int            KU32;
+typedef signed short int        KI16;
+typedef unsigned short int      KU16;
+typedef signed char             KI8;
+typedef unsigned char           KU8;
+#define KI64_C(c)               (c ## LL)
+#define KU64_C(c)               (c ## ULL)
+#define KI32_C(c)               (c)
+#define KU32_C(c)               (c)
+#define KI16_C(c)               (c)
+#define KU16_C(c)               (c)
+#define KI8_C(c)                (c)
+#define KU8_C(c)                (c)
+
+#define KI32_PRI                "d"
+#define KU32_PRI                "u"
+#define KX32_PRI                "x"
+#define KI16_PRI                "d"
+#define KU16_PRI                "u"
+#define KX16_PRI                "x"
+#define KI8_PRI                 "d"
+#define KU8_PRI                 "u"
+#define KX8_PRI                 "x"
+
+typedef KI32                    KSSIZE;
+#define KSSIZE(c)               KI32_C(c)
+#define KSSIZE_MAX              KI32_MAX
+#define KSSIZE_MIN              KI32_MIN
+#define KSSIZE_PRI              KX32_PRI
+
+typedef KU32                    KSIZE;
+#define KSIZE_C(c)              KU32_C(c)
+#define KSIZE_MAX               KU32_MAX
+#define KSIZE_PRI               KX32_PRI
+#define KIPTR_C(c)              KI32_C(c)
+
+typedef KI32                    KIPTR;
+#define KIPTR_MAX               KI32_MAX
+#define KIPTR_MIN               KI32_MIN
+#define KIPTR_PRI               KX32_PRI
+
+typedef KU32                    KUPTR;
+#define KUPTR_C(c)              KU32_C(c)
+#define KUPTR_MAX               KU32_MAX
+#define KUPTR_PRI               KX32_PRI
+
+
+#elif K_ARCH_BITS == 64
+
+# if K_OS == K_OS_WINDOWS
+#  if _MSC_VER
+typedef signed __int64          KI64;
+typedef unsigned __int64        KU64;
+#   define KI64_PRI             "I64d"
+#   define KU64_PRI             "I64u"
+#   define KX64_PRI             "I64x"
+#  else
+typedef signed long long int    KI64;
+typedef unsigned long long int  KU64;
+#   define KI64_PRI              "lld"
+#   define KU64_PRI              "llu"
+#   define KX64_PRI              "llx"
+#  endif
+#  define KI64_C(c)             (c ## LL)
+#  define KU64_C(c)             (c ## ULL)
+# else
+typedef signed long int         KI64;
+typedef unsigned long int       KU64;
+#  define KI64_C(c)             (c ## L)
+#  define KU64_C(c)             (c ## UL)
+#  define KI64_PRI              "ld"
+#  define KU64_PRI              "lu"
+#  define KX64_PRI              "lx"
+# endif
+typedef signed int              KI32;
+typedef unsigned int            KU32;
+typedef signed short            KI16;
+typedef unsigned short          KU16;
+typedef signed char             KI8;
+typedef unsigned char           KU8;
+#define KI32_C(c)               (c)
+#define KU32_C(c)               (c)
+#define KI16_C(c)               (c)
+#define KU16_C(c)               (c)
+#define KI8_C(c)                (c)
+#define KU8_C(c)                (c)
+
+#define KI32_PRI                "d"
+#define KU32_PRI                "u"
+#define KX32_PRI                "x"
+#define KI16_PRI                "d"
+#define KU16_PRI                "u"
+#define KX16_PRI                "x"
+#define KI8_PRI                 "d"
+#define KU8_PRI                 "u"
+#define KX8_PRI                 "x"
+
+typedef KI64                    KSSIZE;
+#define KSSIZE(c)               KI64_C(c)
+#define KSSIZE_MAX              KI64_MAX
+#define KSSIZE_MIN              KI64_MIN
+#define KSSIZE_PRI              KX64_PRI
+
+typedef KU64                    KSIZE;
+#define KSIZE_C(c)              KU64_C(c)
+#define KSIZE_MAX               KU64_MAX
+#define KSIZE_PRI               KX64_PRI
+
+typedef KI64                    KIPTR;
+#define KIPTR_C(c)              KI64_C(c)
+#define KIPTR_MAX               KI64_MAX
+#define KIPTR_MIN               KI64_MIN
+#define KIPTR_PRI               KX64_PRI
+
+typedef KU64                    KUPTR;
+#define KUPTR_C(c)              KU64_C(c)
+#define KUPTR_MAX               KU64_MAX
+#define KUPTR_PRI               KX64_PRI
+
+#else
+# error "Port Me"
+#endif
+
+
+/** Min KI8 value. */
+#define KI8_MIN                 (KI8_C(-0x7f) - 1)
+/** Min KI16 value. */
+#define KI16_MIN                (KI16_C(-0x7fff) - 1)
+/** Min KI32 value. */
+#define KI32_MIN                (KI32_C(-0x7fffffff) - 1)
+/** Min KI64 value. */
+#define KI64_MIN                (KI64_C(-0x7fffffffffffffff) - 1)
+/** Max KI8 value. */
+#define KI8_MAX                 KI8_C(0x7f)
+/** Max KI16 value. */
+#define KI16_MAX                KI16_C(0x7fff)
+/** Max KI32 value. */
+#define KI32_MAX                KI32_C(0x7fffffff)
+/** Max KI64 value. */
+#define KI64_MAX                KI64_C(0x7fffffffffffffff)
+/** Max KU8 value. */
+#define KU8_MAX                 KU8_C(0xff)
+/** Max KU16 value. */
+#define KU16_MAX                KU16_C(0xffff)
+/** Max KU32 value. */
+#define KU32_MAX                KU32_C(0xffffffff)
+/** Max KU64 value. */
+#define KU64_MAX                KU64_C(0xffffffffffffffff)
+
+/** File offset. */
+typedef KI64                    KFOFF;
+/** Pointer a file offset. */
+typedef KFOFF                  *PFOFF;
+/** Pointer a const file offset. */
+typedef KFOFF                  *PCFOFF;
+/** The min value for the KFOFF type. */
+#define KFOFF_MIN               KI64_MIN
+/** The max value for the KFOFF type. */
+#define KFOFF_MAX               KI64_MAX
+/** File offset contstant.
+ * @param c         The constant value. */
+#define KFOFF_C(c)              KI64_C(c)
+/** File offset printf format. */
+#define KFOFF_PRI               KI64_PRI
+
+
+/**
+ * Memory Protection.
+ */
+typedef enum KPROT
+{
+    /** The usual invalid 0. */
+    KPROT_INVALID = 0,
+    /** No access (page not present). */
+    KPROT_NOACCESS,
+    /** Read only. */
+    KPROT_READONLY,
+    /** Read & write. */
+    KPROT_READWRITE,
+    /** Read & copy on write. */
+    KPROT_WRITECOPY,
+    /** Execute only. */
+    KPROT_EXECUTE,
+    /** Execute & read. */
+    KPROT_EXECUTE_READ,
+    /** Execute, read & write. */
+    KPROT_EXECUTE_READWRITE,
+    /** Execute, read & copy on write. */
+    KPROT_EXECUTE_WRITECOPY,
+    /** The usual end value. (exclusive) */
+    KPROT_END,
+    /** Blow the type up to 32-bits. */
+    KPROT_32BIT_HACK = 0x7fffffff
+} KPROT;
+/** Pointer to a memory protection enum. */
+typedef KPROT                  *PKPROT;
+/** Pointer to a const memory protection enum. */
+typedef KPROT const            *PCKPROT;
+
+/** Boolean.
+ * This can be used as a tri-state type, but then you *must* do == checks. */
+typedef KI8                     KBOOL;
+/** Pointer to a boolean value. */
+typedef KBOOL                  *PKBOOL;
+/** Pointer to a const boolean value. */
+typedef KBOOL const            *PCKBOOL;
+/** Maxium value the KBOOL type can hold (officially). */
+#define KBOOL_MIN               KI8_C(-1)
+/** Maxium value the KBOOL type can hold (officially). */
+#define KBOOL_MAX               KI8_C(1)
+/** The KBOOL printf format. */
+#define KBOOL_PRI               KU8_PRI
+/** Boolean true constant. */
+#define K_TRUE                  KI8_C(1)
+/** Boolean false constant. */
+#define K_FALSE                 KI8_C(0)
+/** Boolean unknown constant (the third state). */
+#define K_UNKNOWN               KI8_C(-1)
+
+
+
+/** @name   Forward Declarations / Handle Types.
+ * @{ */
+
+/** Pointer to a file provider instance. */
+typedef struct KRDR *PKRDR;
+/** Pointer to a file provider instance pointer. */
+typedef struct KRDR **PPKRDR;
+
+/** Pointer to a loader segment. */
+typedef struct KLDRSEG *PKLDRSEG;
+/** Pointer to a loader segment. */
+typedef const struct KLDRSEG *PCKLDRSEG;
+
+/** @} */
+
+/** @} */
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/lib/kDep.c
===================================================================
--- /tags/kBuild-0.1.4/src/lib/kDep.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/kDep.c	(revision 1780)
@@ -0,0 +1,367 @@
+/* $Id$ */
+/** @file
+ *
+ * kDep - Common Dependency Managemnt Code.
+ *
+ * Copyright (c) 2004-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include "k/kDefs.h"
+#if K_OS == K_OS_WINDOWS
+# include <windows.h>
+ extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull); /* nt_fullpath.c */
+#else
+# include <dirent.h>
+# include <unistd.h>
+# include <stdint.h>
+#endif
+
+#include "kDep.h"
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** List of dependencies. */
+static PDEP g_pDeps = NULL;
+
+
+/**
+ * Corrects all slashes to unix slashes.
+ *
+ * @returns pszFilename.
+ * @param   pszFilename     The filename to correct.
+ */
+static char *fixslash(char *pszFilename)
+{
+    char *psz = pszFilename;
+    while ((psz = strchr(psz, '\\')) != NULL)
+        *psz++ = '/';
+    return pszFilename;
+}
+
+
+#if K_OS == K_OS_OS2
+
+/**
+ * Corrects the case of a path.
+ *
+ * @param   pszPath     Pointer to the path, both input and output.
+ *                      The buffer must be able to hold one more byte than the string length.
+ */
+static void fixcase(char *pszFilename)
+{
+    return;
+}
+
+#elif K_OS != K_OS_WINDOWS
+
+/**
+ * Corrects the case of a path.
+ *
+ * @param   pszPath     Pointer to the path, both input and output.
+ */
+static void fixcase(char *pszFilename)
+{
+    char *psz;
+
+    /*
+     * Skip the root.
+     */
+    psz = pszFilename;
+    while (*psz == '/')
+        psz++;
+
+    /*
+     * Iterate all the components.
+     */
+    while (*psz)
+    {
+        char  chSlash;
+        struct stat s;
+        char   *pszStart = psz;
+
+        /*
+         * Find the next slash (or end of string) and terminate the string there.
+         */
+        while (*psz != '/' && *psz)
+            *psz++;
+        chSlash = *psz;
+        *psz = '\0';
+
+        /*
+         * Does this part exist?
+         * If not we'll enumerate the directory and search for an case-insensitive match.
+         */
+        if (stat(pszFilename, &s))
+        {
+            struct dirent  *pEntry;
+            DIR            *pDir;
+            if (pszStart == pszFilename)
+                pDir = opendir(*pszFilename ? pszFilename : ".");
+            else
+            {
+                pszStart[-1] = '\0';
+                pDir = opendir(pszFilename);
+                pszStart[-1] = '/';
+            }
+            if (!pDir)
+            {
+                *psz = chSlash;
+                break; /* giving up, if we fail to open the directory. */
+            }
+
+            while ((pEntry = readdir(pDir)) != NULL)
+            {
+                if (!strcasecmp(pEntry->d_name, pszStart))
+                {
+                    strcpy(pszStart, pEntry->d_name);
+                    break;
+                }
+            }
+            closedir(pDir);
+            if (!pEntry)
+            {
+                *psz = chSlash;
+                break;  /* giving up if not found. */
+            }
+        }
+
+        /* restore the slash and press on. */
+        *psz = chSlash;
+        while (*psz == '/')
+            psz++;
+    }
+
+    return;
+}
+
+#endif /* !OS/2 && !Windows */
+
+
+/**
+ * 'Optimizes' and corrects the dependencies.
+ */
+void depOptimize(int fFixCase)
+{
+    /*
+     * Walk the list correct the names and re-insert them.
+     */
+    PDEP pDepOrg = g_pDeps;
+    PDEP pDep = g_pDeps;
+    g_pDeps = NULL;
+    for (; pDep; pDep = pDep->pNext)
+    {
+#ifndef PATH_MAX
+        char        szFilename[_MAX_PATH + 1];
+#else
+        char        szFilename[PATH_MAX + 1];
+#endif
+        char       *pszFilename;
+        struct stat s;
+
+        /*
+         * Skip some fictive names like <built-in> and <command line>.
+         */
+        if (    pDep->szFilename[0] == '<'
+            &&  pDep->szFilename[pDep->cchFilename - 1] == '>')
+            continue;
+        pszFilename = pDep->szFilename;
+
+#if K_OS != K_OS_OS2 && K_OS != K_OS_WINDOWS
+        /*
+         * Skip any drive letters from compilers running in wine.
+         */
+        if (pszFilename[1] == ':')
+            pszFilename += 2;
+#endif
+
+        /*
+         * The microsoft compilers are notoriously screwing up the casing.
+         * This will screw up kmk (/ GNU Make).
+         */
+        if (fFixCase)
+        {
+#if K_OS == K_OS_WINDOWS
+            nt_fullpath(pszFilename, szFilename, sizeof(szFilename));
+            fixslash(szFilename);
+#else
+            strcpy(szFilename, pszFilename);
+            fixslash(szFilename);
+            fixcase(szFilename);
+#endif
+            pszFilename = szFilename;
+        }
+
+        /*
+         * Check that the file exists before we start depending on it.
+         */
+        if (stat(pszFilename, &s))
+        {
+            fprintf(stderr, "kDep: Skipping '%s' - %s!\n", pszFilename, strerror(errno));
+            continue;
+        }
+
+        /*
+         * Insert the corrected dependency.
+         */
+        depAdd(pszFilename, strlen(pszFilename));
+    }
+
+    /*
+     * Free the old ones.
+     */
+    while (pDepOrg)
+    {
+        pDep = pDepOrg;
+        pDepOrg = pDepOrg->pNext;
+        free(pDep);
+    }
+}
+
+
+/**
+ * Prints the dependency chain.
+ *
+ * @returns Pointer to the allocated dependency.
+ * @param   pOutput     Output stream.
+ */
+void depPrint(FILE *pOutput)
+{
+    PDEP pDep;
+    for (pDep = g_pDeps; pDep; pDep = pDep->pNext)
+        fprintf(pOutput, " \\\n\t%s", pDep->szFilename);
+    fprintf(pOutput, "\n\n");
+}
+
+
+/**
+ * Prints empty dependency stubs for all dependencies.
+ */
+void depPrintStubs(FILE *pOutput)
+{
+    PDEP pDep;
+    for (pDep = g_pDeps; pDep; pDep = pDep->pNext)
+        fprintf(pOutput, "%s:\n\n", pDep->szFilename);
+}
+
+
+/* sdbm:
+   This algorithm was created for sdbm (a public-domain reimplementation of
+   ndbm) database library. it was found to do well in scrambling bits,
+   causing better distribution of the keys and fewer splits. it also happens
+   to be a good general hashing function with good distribution. the actual
+   function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
+   is the faster version used in gawk. [there is even a faster, duff-device
+   version] the magic constant 65599 was picked out of thin air while
+   experimenting with different constants, and turns out to be a prime.
+   this is one of the algorithms used in berkeley db (see sleepycat) and
+   elsewhere. */
+static unsigned sdbm(const char *str)
+{
+    unsigned hash = 0;
+    int c;
+
+    while ((c = *(unsigned const char *)str++))
+        hash = c + (hash << 6) + (hash << 16) - hash;
+
+    return hash;
+}
+
+
+/**
+ * Adds a dependency.
+ *
+ * @returns Pointer to the allocated dependency.
+ * @param   pszFilename     The filename.
+ * @param   cchFilename     The length of the filename.
+ */
+PDEP depAdd(const char *pszFilename, size_t cchFilename)
+{
+    unsigned uHash = sdbm(pszFilename);
+    PDEP    pDep;
+    PDEP    pDepPrev;
+
+    /*
+     * Check if we've already got this one.
+     */
+    pDepPrev = NULL;
+    for (pDep = g_pDeps; pDep; pDepPrev = pDep, pDep = pDep->pNext)
+        if (    pDep->uHash == uHash
+            &&  pDep->cchFilename == cchFilename
+            &&  !memcmp(pDep->szFilename, pszFilename, cchFilename))
+            return pDep;
+
+    /*
+     * Add it.
+     */
+    pDep = (PDEP)malloc(sizeof(*pDep) + cchFilename);
+    if (!pDep)
+    {
+        fprintf(stderr, "\nOut of memory! (requested %lx bytes)\n\n", 
+                (unsigned long)(sizeof(*pDep) + cchFilename));
+        exit(1);
+    }
+
+    pDep->cchFilename = cchFilename;
+    memcpy(pDep->szFilename, pszFilename, cchFilename + 1);
+    pDep->uHash = uHash;
+
+    if (pDepPrev)
+    {
+        pDep->pNext = pDepPrev->pNext;
+        pDepPrev->pNext = pDep;
+    }
+    else
+    {
+        pDep->pNext = g_pDeps;
+        g_pDeps = pDep;
+    }
+    return pDep;
+}
+
+
+/**
+ * Frees the current dependency chain.
+ */
+void depCleanup(void)
+{
+    PDEP pDep = g_pDeps;
+    g_pDeps = NULL;
+    while (pDep)
+    {
+        PDEP pFree = pDep;
+        pDep = pDep->pNext;
+        free(pFree);
+    }
+}
+
Index: /tags/kBuild-0.1.4/src/lib/kDep.h
===================================================================
--- /tags/kBuild-0.1.4/src/lib/kDep.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/kDep.h	(revision 1780)
@@ -0,0 +1,52 @@
+/* $Id$ */
+/** @file
+ *
+ * kDep - Common Dependency Managemnt Code.
+ *
+ * Copyright (c) 2004-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef __kDep_h__
+#define __kDep_h__
+
+/** A dependency. */
+typedef struct DEP
+{
+    /** Next dependency in the list. */
+    struct DEP *pNext;
+    /** The filename hash. */
+    unsigned    uHash;
+    /** The length of the filename. */
+    size_t      cchFilename;
+    /** The filename. */
+    char        szFilename[4];
+} DEP, *PDEP;
+
+
+extern PDEP depAdd(const char *pszFilename, size_t cchFilename);
+extern void depOptimize(int fFixCase);
+extern void depPrint(FILE *pOutput);
+extern void depPrintStubs(FILE *pOutput);
+extern void depCleanup(void);
+
+#endif
+
Index: /tags/kBuild-0.1.4/src/lib/md5.c
===================================================================
--- /tags/kBuild-0.1.4/src/lib/md5.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/md5.c	(revision 1780)
@@ -0,0 +1,257 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.	This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include <string.h>
+#include "md5.h"
+#define uint32 uint32_t
+
+#if 0 /* don't need 100% correct md5, just fast md5. */
+#ifdef sgi
+#define HIGHFIRST
+#endif
+
+#ifdef sun
+#define HIGHFIRST
+#endif
+#endif /* skip this */
+
+#ifndef HIGHFIRST
+#define byteReverse(buf, len)	/* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+void byteReverse(unsigned char *buf, unsigned longs)
+{
+    uint32 t;
+    do {
+	t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+	    ((unsigned) buf[1] << 8 | buf[0]);
+	*(uint32 *) buf = t;
+	buf += 4;
+    } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bits[0] = 0;
+    ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len)
+{
+    uint32 t;
+
+    /* Update bitcount */
+
+    t = ctx->bits[0];
+    if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
+	ctx->bits[1]++; 	/* Carry from low to high */
+    ctx->bits[1] += len >> 29;
+
+    t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+    /* Handle any leading odd-sized chunks */
+
+    if (t) {
+	unsigned char *p = (unsigned char *) ctx->in + t;
+
+	t = 64 - t;
+	if (len < t) {
+	    memcpy(p, buf, len);
+	    return;
+	}
+	memcpy(p, buf, t);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (uint32 *) ctx->in);
+	buf += t;
+	len -= t;
+    }
+    /* Process data in 64-byte chunks */
+
+    while (len >= 64) {
+	memcpy(ctx->in, buf, 64);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (uint32 *) ctx->in);
+	buf += 64;
+	len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+
+    memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+    unsigned count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->bits[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8) {
+	/* Two lots of padding:  Pad the first block to 64 bytes */
+	memset(p, 0, count);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (uint32 *) ctx->in);
+
+	/* Now fill the next block with 56 bytes */
+	memset(ctx->in, 0, 56);
+    } else {
+	/* Pad block to 56 bytes */
+	memset(p, 0, count - 8);
+    }
+    byteReverse(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ((uint32 *) ctx->in)[14] = ctx->bits[0];
+    ((uint32 *) ctx->in)[15] = ctx->bits[1];
+
+    MD5Transform(ctx->buf, (uint32 *) ctx->in);
+    byteReverse((unsigned char *) ctx->buf, 4);
+    memcpy(digest, ctx->buf, 16);
+    memset(ctx, 0, sizeof(ctx));        /* In case it's sensitive */
+}
+
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void MD5Transform(uint32 buf[4], uint32 in[16])
+{
+    register uint32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
Index: /tags/kBuild-0.1.4/src/lib/md5.h
===================================================================
--- /tags/kBuild-0.1.4/src/lib/md5.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/md5.h	(revision 1780)
@@ -0,0 +1,17 @@
+#ifndef MD5_H
+#define MD5_H
+
+#include "mytypes.h"
+
+struct MD5Context {
+        uint32_t buf[4];
+        uint32_t bits[2];
+        unsigned char in[64];
+};
+
+void MD5Init(struct MD5Context *);
+void MD5Update(struct MD5Context *, const unsigned char *, unsigned);
+void MD5Final(unsigned char digest[16], struct MD5Context *);
+void MD5Transform(uint32_t buf[4], uint32_t in[16]);
+
+#endif /* !MD5_H */
Index: /tags/kBuild-0.1.4/src/lib/mytypes.h
===================================================================
--- /tags/kBuild-0.1.4/src/lib/mytypes.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/mytypes.h	(revision 1780)
@@ -0,0 +1,43 @@
+/* $Id$ */
+/** @file
+ *
+ * mytypes - wrapper that ensures the necessary uintXY_t types are defined.
+ *
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ___mytypes_h__
+#define ___mytypes_h__
+
+#include <stdlib.h>
+#include <sys/types.h>
+
+#if defined(_MSC_VER)
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+#else
+# include <stdint.h>
+#endif
+
+#endif 
+
Index: /tags/kBuild-0.1.4/src/lib/nt_fullpath.c
===================================================================
--- /tags/kBuild-0.1.4/src/lib/nt_fullpath.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/nt_fullpath.c	(revision 1780)
@@ -0,0 +1,565 @@
+/* $Id$ */
+/** @file
+ * fixcase - fixes the case of paths, windows specific.
+ */
+
+/*
+ * Copyright (c) 2004-2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <Windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <direct.h>
+
+/*
+ * Corrects the case of a path.
+ * Expects a fullpath!
+ * Added by bird for the $(abspath ) function and w32ify
+ */
+static void w32_fixcase(char *pszPath)
+{
+    static char     s_szLast[260];
+    size_t          cchLast;
+
+#ifndef NDEBUG
+# define my_assert(expr) \
+    do { \
+        if (!(expr)) { \
+            printf("my_assert: %s, file %s, line %d\npszPath=%s\npsz=%s\n", \
+                   #expr, __FILE__, __LINE__, pszPath, psz); \
+            __debugbreak(); \
+            exit(1); \
+        } \
+    } while (0)
+#else
+# define my_assert(expr) do {} while (0)
+#endif
+
+    char *psz = pszPath;
+    if (*psz == '/' || *psz == '\\')
+    {
+        if (psz[1] == '/' || psz[1] == '\\')
+        {
+            /* UNC */
+            my_assert(psz[1] == '/' || psz[1] == '\\');
+            my_assert(psz[2] != '/' && psz[2] != '\\');
+
+            /* skip server name */
+            psz += 2;
+            while (*psz != '\\' && *psz != '/')
+            {
+                if (!*psz)
+                    return;
+                *psz++ = toupper(*psz);
+            }
+
+            /* skip the share name */
+            psz++;
+            my_assert(*psz != '/' && *psz != '\\');
+            while (*psz != '\\' && *psz != '/')
+            {
+                if (!*psz)
+                    return;
+                *psz++ = toupper(*psz);
+            }
+            my_assert(*psz == '/' || *psz == '\\');
+            psz++;
+        }
+        else
+        {
+            /* Unix spec */
+            psz++;
+        }
+    }
+    else
+    {
+        /* Drive letter */
+        my_assert(psz[1] == ':');
+        *psz = toupper(*psz);
+        my_assert(psz[0] >= 'A' && psz[0] <= 'Z');
+        my_assert(psz[2] == '/' || psz[2] == '\\');
+        psz += 3;
+    }
+
+    /*
+     * Try make use of the result from the previous call.
+     * This is ignorant to slashes and similar, but may help even so.
+     */
+    if (    s_szLast[0] == pszPath[0]
+        &&  (psz - pszPath == 1 || s_szLast[1] == pszPath[1])
+        &&  (psz - pszPath <= 2 || s_szLast[2] == pszPath[2])
+       )
+    {
+        char *pszLast = &s_szLast[psz - pszPath];
+        char *pszCur = psz;
+        char *pszSrc0 = pszLast;
+        char *pszDst0 = pszCur;
+        for (;;)
+        {
+            const char ch1 = *pszCur;
+            const char ch2 = *pszLast;
+            if (    ch1 != ch2
+                &&  (ch1 != '\\' || ch2 != '/')
+                &&  (ch1 != '/'  || ch2 != '\\')
+                &&  tolower(ch1) != tolower(ch2)
+                &&  toupper(ch1) != toupper(ch2))
+                break;
+            if (ch1 == '/' || ch1 == '\\')
+            {
+				psz = pszCur + 1;
+                *pszLast = ch1; /* preserve the slashes */
+            }
+            else if (ch1 == '\0')
+            {
+                psz = pszCur;
+                break;
+            }
+            pszCur++;
+            pszLast++;
+        }
+        if (psz != pszDst0)
+            memcpy(pszDst0, pszSrc0, psz - pszDst0);
+    }
+
+    /*
+     * Pointing to the first char after the unc or drive specifier,
+     * or in case of a cache hit, the first non-matching char (following a slash of course).
+     */
+    while (*psz)
+    {
+        WIN32_FIND_DATA FindFileData;
+        HANDLE hDir;
+        char chSaved0;
+        char chSaved1;
+        char *pszEnd;
+        int iLongNameDiff;
+        size_t cch;
+
+
+        /* find the end of the component. */
+        pszEnd = psz;
+        while (*pszEnd && *pszEnd != '/' && *pszEnd != '\\')
+            pszEnd++;
+        cch = pszEnd - psz;
+
+        /* replace the end with "?\0" */
+        chSaved0 = pszEnd[0];
+        chSaved1 = pszEnd[1];
+        pszEnd[0] = '?';
+        pszEnd[1] = '\0';
+
+        /* find the right filename. */
+        hDir = FindFirstFile(pszPath, &FindFileData);
+        pszEnd[1] = chSaved1;
+        if (!hDir)
+        {
+            cchLast = psz - pszPath;
+            memcpy(s_szLast, pszPath, cchLast + 1);
+            s_szLast[cchLast + 1] = '\0';
+            pszEnd[0] = chSaved0;
+            return;
+        }
+        pszEnd[0] = '\0';
+        while (   (iLongNameDiff = stricmp(FindFileData.cFileName, psz))
+               && stricmp(FindFileData.cAlternateFileName, psz))
+        {
+            if (!FindNextFile(hDir, &FindFileData))
+            {
+                cchLast = psz - pszPath;
+                memcpy(s_szLast, pszPath, cchLast + 1);
+                s_szLast[cchLast + 1] = '\0';
+                pszEnd[0] = chSaved0;
+                return;
+            }
+        }
+        pszEnd[0] = chSaved0;
+        if (    iLongNameDiff                           /* matched the short name */
+            ||  !FindFileData.cAlternateFileName[0]     /* no short name */
+            || !memchr(psz, ' ', cch))                  /* no spaces in the matching name */
+            memcpy(psz, !iLongNameDiff ? FindFileData.cFileName : FindFileData.cAlternateFileName, cch);
+        else
+        {
+            /* replace spacy name with the short name. */
+            const size_t cchAlt = strlen(FindFileData.cAlternateFileName);
+            const size_t cchDelta = cch - cchAlt;
+            my_assert(cchAlt > 0);
+            if (!cchDelta)
+                memcpy(psz, FindFileData.cAlternateFileName, cch);
+            else
+            {
+                size_t cbLeft = strlen(pszEnd) + 1;
+                if ((psz - pszPath) + cbLeft + cchAlt <= _MAX_PATH)
+                {
+                    memmove(psz + cchAlt, pszEnd, cbLeft);
+                    pszEnd -= cchDelta;
+                    memcpy(psz, FindFileData.cAlternateFileName, cchAlt);
+                }
+                else
+                    fprintf(stderr, "kBuild: case & space fixed filename is growing too long (%d bytes)! '%s'\n",
+                            (psz - pszPath) + cbLeft + cchAlt, pszPath);
+            }
+        }
+        my_assert(pszEnd[0] == chSaved0);
+        FindClose(hDir);
+
+        /* advance to the next component */
+        if (!chSaved0)
+        {
+            psz = pszEnd;
+            break;
+        }
+        psz = pszEnd + 1;
+        my_assert(*psz != '/' && *psz != '\\');
+    }
+
+    /* *psz == '\0', the end. */
+    cchLast = psz - pszPath;
+    memcpy(s_szLast, pszPath, cchLast + 1);
+#undef my_assert
+}
+
+#define MY_FileNameInformation 9
+typedef struct _MY_FILE_NAME_INFORMATION
+{
+    ULONG FileNameLength;
+    WCHAR FileName[1];
+} MY_FILE_NAME_INFORMATION, *PMY_FILE_NAME_INFORMATION;
+
+#define MY_FileInternalInformation 6
+typedef struct _MY_FILE_INTERNAL_INFORMATION {
+    LARGE_INTEGER IndexNumber;
+} MY_FILE_INTERNAL_INFORMATION, *PMY_FILE_INTERNAL_INFORMATION;
+
+#define MY_FileFsVolumeInformation 1
+typedef struct _MY_FILE_FS_VOLUME_INFORMATION
+{
+    LARGE_INTEGER VolumeCreationTime;
+    ULONG VolumeSerialNumber;
+    ULONG VolumeLabelLength;
+    BOOLEAN SupportsObjects;
+    WCHAR VolumeLabel[/*1*/128];
+} MY_FILE_FS_VOLUME_INFORMATION, *PMY_FILE_FS_VOLUME_INFORMATION;
+
+#define MY_FileFsAttributeInformation 5
+typedef struct _MY_FILE_FS_ATTRIBUTE_INFORMATION
+{
+    ULONG FileSystemAttributes;
+    LONG MaximumComponentNameLength;
+    ULONG FileSystemNameLength;
+    WCHAR FileSystemName[/*1*/64];
+} MY_FILE_FS_ATTRIBUTE_INFORMATION, *PMY_FILE_FS_ATTRIBUTE_INFORMATION;
+
+#define MY_FileFsDeviceInformation 4
+typedef struct MY_FILE_FS_DEVICE_INFORMATION
+{
+    ULONG DeviceType;
+    ULONG Characteristics;
+} MY_FILE_FS_DEVICE_INFORMATION, *PMY_FILE_FS_DEVICE_INFORMATION;
+#define MY_FILE_DEVICE_DISK              7
+#define MY_FILE_DEVICE_DISK_FILE_SYSTEM  8
+#define MY_FILE_DEVICE_FILE_SYSTEM       9
+#define MY_FILE_DEVICE_VIRTUAL_DISK     36
+
+
+typedef struct _IO_STATUS_BLOCK
+{
+    union
+    {
+        LONG Status;
+        PVOID Pointer;
+    };
+    ULONG_PTR Information;
+} MY_IO_STATUS_BLOCK, *PMY_IO_STATUS_BLOCK;
+
+static BOOL                             g_fInitialized = FALSE;
+static int                              g_afNtfsDrives['Z' - 'A' + 1];
+static MY_FILE_FS_VOLUME_INFORMATION    g_aVolumeInfo['Z' - 'A' + 1];
+
+static LONG (NTAPI *g_pfnNtQueryInformationFile)(HANDLE FileHandle,
+    PMY_IO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation,
+    ULONG Length, ULONG FileInformationClass);
+static LONG (NTAPI *g_pfnNtQueryVolumeInformationFile)(HANDLE FileHandle,
+    PMY_IO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation,
+    ULONG Length, ULONG FsInformationClass);
+
+
+int
+nt_get_filename_info(const char *pszPath, char *pszFull, size_t cchFull)
+{
+    static char                     abBuf[8192];
+    PMY_FILE_NAME_INFORMATION       pFileNameInfo = (PMY_FILE_NAME_INFORMATION)abBuf;
+    PMY_FILE_FS_VOLUME_INFORMATION  pFsVolInfo = (PMY_FILE_FS_VOLUME_INFORMATION)abBuf;
+    MY_IO_STATUS_BLOCK              Ios;
+    LONG                            rcNt;
+    HANDLE                      hFile;
+    int                             cchOut;
+    char                           *psz;
+    int                             iDrv;
+    int                             rc;
+
+    /*
+     * Check for NtQueryInformationFile the first time around.
+     */
+    if (!g_fInitialized)
+    {
+        g_fInitialized = TRUE;
+        if (!getenv("KMK_DONT_USE_NT_QUERY_INFORMATION_FILE"))
+        {
+            *(FARPROC *)&g_pfnNtQueryInformationFile =
+                GetProcAddress(LoadLibrary("ntdll.dll"), "NtQueryInformationFile");
+            *(FARPROC *)&g_pfnNtQueryVolumeInformationFile =
+                GetProcAddress(LoadLibrary("ntdll.dll"), "NtQueryVolumeInformationFile");
+        }
+        if (    g_pfnNtQueryInformationFile
+            &&  g_pfnNtQueryVolumeInformationFile)
+        {
+            unsigned i;
+            for (i = 0; i < sizeof(g_afNtfsDrives) / sizeof(g_afNtfsDrives[0]); i++ )
+                g_afNtfsDrives[i] = -1;
+        }
+        else
+        {
+            g_pfnNtQueryVolumeInformationFile = NULL;
+            g_pfnNtQueryInformationFile = NULL;
+        }
+    }
+    if (!g_pfnNtQueryInformationFile)
+        return -1;
+
+    /*
+     * The FileNameInformation we get is relative to where the volume is mounted,
+     * so we have to extract the driveletter prefix ourselves.
+     *
+     * FIXME: This will probably not work for volumes mounted in NTFS sub-directories.
+     */
+    psz = pszFull;
+    if (pszPath[0] == '\\' || pszPath[0] == '/')
+    {
+        /* unc or root of volume */
+        if (    (pszPath[1] == '\\' || pszPath[1] == '/')
+            &&  (pszPath[2] != '\\' || pszPath[2] == '/'))
+        {
+#if 0 /* don't bother with unc yet. */
+            /* unc - we get the server + name back */
+            *psz++ = '\\';
+#endif
+            return -1;
+        }
+        /* root slash */
+        *psz++ = _getdrive() + 'A' - 1;
+        *psz++ = ':';
+    }
+    else if (pszPath[1] == ':' && isalpha(pszPath[0]))
+    {
+        /* drive letter */
+        *psz++ = toupper(pszPath[0]);
+        *psz++ = ':';
+    }
+    else
+    {
+        /* relative */
+        *psz++ = _getdrive() + 'A' - 1;
+        *psz++ = ':';
+    }
+    iDrv = *pszFull - 'A';
+
+    /*
+     * Fat32 doesn't return filenames with the correct case, so restrict it
+     * to NTFS volumes for now.
+     */
+    if (g_afNtfsDrives[iDrv] == -1)
+    {
+        /* FSCTL_GET_REPARSE_POINT? Enumerate mount points? */
+        g_afNtfsDrives[iDrv] = 0;
+        psz[0] = '\\';
+        psz[1] = '\0';
+#if 1
+        hFile = CreateFile(pszFull,
+                           GENERIC_READ,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                           NULL,
+                           OPEN_EXISTING,
+                           FILE_FLAG_BACKUP_SEMANTICS,
+                           NULL);
+        if (hFile != INVALID_HANDLE_VALUE)
+        {
+            PMY_FILE_FS_ATTRIBUTE_INFORMATION pFsAttrInfo = (PMY_FILE_FS_ATTRIBUTE_INFORMATION)abBuf;
+
+            memset(&Ios, 0, sizeof(Ios));
+            rcNt = g_pfnNtQueryVolumeInformationFile(hFile, &Ios, abBuf, sizeof(abBuf),
+                                                     MY_FileFsAttributeInformation);
+            if (    rcNt >= 0
+                //&&  pFsAttrInfo->FileSystemNameLength == 4
+                &&  pFsAttrInfo->FileSystemName[0] == 'N'
+                &&  pFsAttrInfo->FileSystemName[1] == 'T'
+                &&  pFsAttrInfo->FileSystemName[2] == 'F'
+                &&  pFsAttrInfo->FileSystemName[3] == 'S'
+                &&  pFsAttrInfo->FileSystemName[4] == '\0')
+            {
+                memset(&Ios, 0, sizeof(Ios));
+                rcNt = g_pfnNtQueryVolumeInformationFile(hFile, &Ios, &g_aVolumeInfo[iDrv],
+                                                         sizeof(MY_FILE_FS_VOLUME_INFORMATION),
+                                                         MY_FileFsVolumeInformation);
+                if (rcNt >= 0)
+                {
+                    DWORD dwDriveType = GetDriveType(pszFull);
+                    if (    dwDriveType == DRIVE_FIXED
+                        ||  dwDriveType == DRIVE_RAMDISK)
+                        g_afNtfsDrives[iDrv] = 1;
+                }
+            }
+            CloseHandle(hFile);
+        }
+#else
+        {
+            char szFSName[32];
+            if (    GetVolumeInformation(pszFull,
+                                         NULL, 0,   /* volume name */
+                                         NULL,      /* serial number */
+                                         NULL,      /* max component */
+                                         NULL,      /* volume attribs */
+                                         szFSName,
+                                         sizeof(szFSName))
+                &&  !strcmp(szFSName, "NTFS"))
+            {
+                g_afNtfsDrives[iDrv] = 1;
+            }
+        }
+#endif
+    }
+    if (!g_afNtfsDrives[iDrv])
+        return -1;
+
+    /*
+     * Try open the path and query its file name information.
+     */
+    hFile = CreateFile(pszPath,
+                       GENERIC_READ,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                       NULL,
+                       OPEN_EXISTING,
+                       FILE_FLAG_BACKUP_SEMANTICS,
+                       NULL);
+    if (hFile != INVALID_HANDLE_VALUE)
+    {
+        /* check that the driver letter is correct first (reparse / symlink issues). */
+        memset(&Ios, 0, sizeof(Ios));
+        rcNt = g_pfnNtQueryVolumeInformationFile(hFile, &Ios, pFsVolInfo, sizeof(*pFsVolInfo), MY_FileFsVolumeInformation);
+        if (rcNt >= 0)
+        {
+            /** @todo do a quick search and try correct the drive letter? */
+            if (    pFsVolInfo->VolumeCreationTime.QuadPart == g_aVolumeInfo[iDrv].VolumeCreationTime.QuadPart
+                &&  pFsVolInfo->VolumeSerialNumber == g_aVolumeInfo[iDrv].VolumeSerialNumber)
+            {
+                memset(&Ios, 0, sizeof(Ios));
+                rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, abBuf, sizeof(abBuf), MY_FileNameInformation);
+                if (rcNt >= 0)
+                {
+                    cchOut = WideCharToMultiByte(CP_ACP, 0,
+                                                 pFileNameInfo->FileName, pFileNameInfo->FileNameLength / sizeof(WCHAR),
+                                                 psz, (int)(cchFull - (psz - pszFull) - 2), NULL, NULL);
+                    if (cchOut > 0)
+                    {
+                        const char *pszEnd;
+#if 0
+                        /* upper case the server and share */
+                        if (fUnc)
+                        {
+                            for (psz++; *psz != '/' && *psz != '\\'; psz++)
+                                *psz = toupper(*psz);
+                            for (psz++; *psz != '/' && *psz != '\\'; psz++)
+                                *psz = toupper(*psz);
+                        }
+#endif
+                        /* add trailing slash on directories if input has it. */
+                        pszEnd = strchr(pszPath, '\0');
+                        if (    (pszEnd[-1] == '/' || pszEnd[-1] == '\\')
+                            &&  psz[cchOut - 1] != '\\'
+                            &&  psz[cchOut - 1] != '//')
+                            psz[cchOut++] = '\\';
+
+                        /* make sure it's terminated */
+                        psz[cchOut] = '\0';
+                        rc = 0;
+                    }
+                    else
+                        rc = -3;
+                }
+                else
+                    rc = -4;
+            }
+            else
+                rc = -5;
+        }
+        else
+            rc = -6;
+        CloseHandle(hFile);
+    }
+    else
+        rc = -7;
+    return rc;
+}
+
+/**
+ * Somewhat similar to fullpath, except that it will fix
+ * the case of existing path components.
+ */
+void
+nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull)
+{
+#if 0
+    static int s_cHits = 0;
+    static int s_cFallbacks = 0;
+#endif
+
+    /*
+     * The simple case, the file / dir / whatever exists and can be
+     * queried without problems and spaces.
+     */
+    if (nt_get_filename_info(pszPath, pszFull, cchFull) == 0)
+    {
+        /** @todo make nt_get_filename_info return spaceless path. */
+        if (strchr(pszFull, ' '))
+            w32_fixcase(pszFull);
+#if 0
+        fprintf(stdout, "nt #%d - %s\n", ++s_cHits, pszFull);
+        fprintf(stdout, "   #%d - %s\n", s_cHits, pszPath);
+#endif
+        return;
+    }
+    if (g_pfnNtQueryInformationFile)
+    {
+        /* do _fullpath and drop off path elements until we get a hit... - later */
+    }
+
+    /*
+     * For now, simply fall back on the old method.
+     */
+    _fullpath(pszFull, pszPath, cchFull);
+    w32_fixcase(pszFull);
+#if 0
+    fprintf(stderr, "fb #%d - %s\n", ++s_cFallbacks, pszFull);
+    fprintf(stderr, "   #%d - %s\n", s_cFallbacks, pszPath);
+#endif
+}
+
Index: /tags/kBuild-0.1.4/src/lib/startuphacks-win.c
===================================================================
--- /tags/kBuild-0.1.4/src/lib/startuphacks-win.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/startuphacks-win.c	(revision 1780)
@@ -0,0 +1,203 @@
+/* $Id$ */
+/** @file
+ *
+ * kBuild - Alternative argument parser for the windows startup code.
+ *
+ * Copyright (c) 2006-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+ *
+ * parse_args(): Copyright (c) 1992-1998 by Eberhard Mattes
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <stdlib.h>
+#include <malloc.h>
+#include <Windows.h>
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static int parse_args(const char *pszSrc, char **argv, char *pchPool);
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** argument count found by parse_args(). */
+static int  g_cArgs = 0;
+/** the argument vector, for __getmainargs(). */
+static char **g_papszArgs = NULL;
+
+
+
+int __cdecl _setargv(void)
+{
+    static char s_szProgramName[MAX_PATH + 1];
+    const char *pszCmdLine;
+    char       *pszCmdLineBuf;
+    int         cb;
+
+    /*
+     * Set the program name.
+     */
+    GetModuleFileName(NULL, s_szProgramName, MAX_PATH);
+    s_szProgramName[MAX_PATH] = '\0';
+#if _MSC_VER >= 1400 && !defined(CRTDLL) && !defined(_DLL)
+    _set_pgmptr(s_szProgramName);
+#endif
+
+    /*
+     * Get the commandline, use the program name if nothings available.
+     */
+    pszCmdLine = (const char *)GetCommandLineA();
+    if (!pszCmdLine || !*pszCmdLine)
+        pszCmdLine = s_szProgramName;
+
+    /*
+     * Parse the argument commandline emitting the unix argument vector.
+     */
+    cb = parse_args(pszCmdLine, NULL, NULL);
+    g_papszArgs = malloc(sizeof(*g_papszArgs) * (g_cArgs + 2));
+    if (!g_papszArgs)
+        return -1;
+    pszCmdLineBuf = malloc(cb);
+    if (!pszCmdLineBuf)
+        return -1;
+    parse_args(pszCmdLine, g_papszArgs, pszCmdLineBuf);
+    g_papszArgs[g_cArgs] = g_papszArgs[g_cArgs + 1] = NULL;
+
+    /* set return variables */
+    __argc = g_cArgs;
+    __argv = g_papszArgs;
+    return 0;
+}
+
+
+/* when linking with the crtexe.c, the __getmainargs() call will redo the _setargv job inside the msvc*.dll. */
+int __cdecl __getmainargs(int *pargc, char ***pargv, char ***penvp, int dowildcard, /*_startupinfo*/ void *startinfo)
+{
+    __argc = *pargc = g_cArgs;
+    __argv = *pargv = g_papszArgs;
+    *penvp = _environ;
+    return 0;
+}
+
+#if defined(_M_IX86)
+int (__cdecl * _imp____getmainargs)(int *, char ***, char ***, int, /*_startupinfo*/ void *) = __getmainargs;
+#else
+int (__cdecl * __imp___getmainargs)(int *, char ***, char ***, int, /*_startupinfo*/ void *) = __getmainargs;
+#endif
+
+
+
+/**
+ * Parses the argument string passed in as pszSrc.
+ *
+ * @returns size of the processed arguments.
+ * @param   pszSrc  Pointer to the commandline that's to be parsed.
+ * @param   argv    Pointer to argument vector to put argument pointers in. NULL allowed.
+ * @param   pchPool Pointer to memory pchPool to put the arguments into. NULL allowed.
+ */
+static int parse_args(const char *pszSrc, char **argv, char *pchPool)
+{
+    int   bs;
+    char  chQuote;
+    char *pfFlags;
+    int   cbArgs;
+
+#define PUTC(c) do { ++cbArgs; if (pchPool != NULL) *pchPool++ = (c); } while (0)
+#define PUTV    do { ++g_cArgs; if (argv != NULL) *argv++ = pchPool; } while (0)
+#define WHITE(c) ((c) == ' ' || (c) == '\t')
+
+#define _ARG_DQUOTE   0x01          /* Argument quoted (")                  */
+#define _ARG_RESPONSE 0x02          /* Argument read from response file     */
+#define _ARG_WILDCARD 0x04          /* Argument expanded from wildcard      */
+#define _ARG_ENV      0x08          /* Argument from environment            */
+#define _ARG_NONZERO  0x80          /* Always set, to avoid end of string   */
+
+    g_cArgs = 0; cbArgs = 0;
+
+#if 0
+    /* argv[0] */
+    PUTC((char)_ARG_NONZERO);
+    PUTV;
+    for (;;)
+    {
+        PUTC(*pszSrc);
+        if (*pszSrc == 0)
+            break;
+        ++pszSrc;
+    }
+    ++pszSrc;
+#endif
+
+    for (;;)
+    {
+        while (WHITE(*pszSrc))
+            ++pszSrc;
+        if (*pszSrc == 0)
+            break;
+        pfFlags = pchPool;
+        PUTC((char)_ARG_NONZERO);
+        PUTV;
+        bs = 0; chQuote = 0;
+        for (;;)
+        {
+            if (!chQuote ? (*pszSrc == '"' || *pszSrc == '\'') : *pszSrc == chQuote)
+            {
+                while (bs >= 2)
+                {
+                    PUTC('\\');
+                    bs -= 2;
+                }
+                if (bs & 1)
+                    PUTC(*pszSrc);
+                else
+                {
+                    chQuote = chQuote ? 0 : *pszSrc;
+                    if (pfFlags != NULL)
+                        *pfFlags |= _ARG_DQUOTE;
+                }
+                bs = 0;
+            }
+            else if (*pszSrc == '\\')
+                ++bs;
+            else
+            {
+                while (bs != 0)
+                {
+                    PUTC('\\');
+                    --bs;
+                }
+                if (*pszSrc == 0 || (WHITE(*pszSrc) && !chQuote))
+                    break;
+                PUTC(*pszSrc);
+            }
+            ++pszSrc;
+        }
+        PUTC(0);
+    }
+    return cbArgs;
+}
+
Index: /tags/kBuild-0.1.4/src/lib/wrapper.c
===================================================================
--- /tags/kBuild-0.1.4/src/lib/wrapper.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/lib/wrapper.c	(revision 1780)
@@ -0,0 +1,88 @@
+/* $Id$ */
+/** @file
+ * Wrapper program for various debugging purposes.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <process.h>
+#else
+# include <unistd.h>
+#endif
+
+int main(int argc, char **argv, char **envp)
+{
+    const char *pszLogTo        = getenv("WRAPPER_LOGTO");
+    const char *pszLogFileArgs  = getenv("WRAPPER_LOGFILEARGS");
+    const char *pszLogEnv       = getenv("WRAPPER_LOGENV");
+    const char *pszExec         = getenv("WRAPPER_EXEC");
+    const char *pszSigSegv      = getenv("WRAPPER_SIGSEGV");
+    const char *pszRetVal       = getenv("WRAPPER_RETVAL");
+    int i;
+
+    if (pszLogTo)
+    {
+        FILE *pLog = fopen(pszLogTo, "a");
+        if (pLog)
+        {
+            fprintf(pLog, "+++ %s pid=%ld +++\n", argv[0], (long)getpid());
+            for (i = 1; i < argc; i++)
+            {
+                fprintf(pLog, "argv[%d]: '%s'\n", i, argv[i]);
+                if (pszLogFileArgs)
+                {
+                    FILE *pArg = fopen(argv[i], "r");
+                    if (pArg)
+                    {
+                        int iLine = 0;
+                        static char szLine[64*1024];
+                        while (fgets(szLine, sizeof(szLine), pArg) && iLine++ < 42)
+                            fprintf(pLog, "%2d: %s", iLine, szLine);
+                        fclose(pArg);
+                    }
+                }
+            }
+            if (pszLogEnv)
+                for (i = 0; envp[i]; i++)
+                    fprintf(pLog, "envp[%d]: '%s'\n", i, envp[i]);
+            fprintf(pLog, "--- %s pid=%ld ---\n", argv[0], (long)getpid());
+            fclose(pLog);
+        }
+    }
+
+    if (pszSigSegv)
+    {
+        char *pchIllegal = (char *)1;
+        pchIllegal[0] = '\0';
+    }
+
+    if (pszExec)
+    {
+        /** @todo */
+    }
+
+    return pszRetVal ? atol(pszRetVal) : 1;
+}
Index: /tags/kBuild-0.1.4/src/sed/ABOUT-NLS
===================================================================
--- /tags/kBuild-0.1.4/src/sed/ABOUT-NLS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/ABOUT-NLS	(revision 1780)
@@ -0,0 +1,393 @@
+Notes on the Free Translation Project
+*************************************
+
+   Free software is going international!  The Free Translation Project
+is a way to get maintainers of free software, translators, and users all
+together, so that will gradually become able to speak many languages.
+A few packages already provide translations for their messages.
+
+   If you found this `ABOUT-NLS' file inside a distribution, you may
+assume that the distributed package does use GNU `gettext' internally,
+itself available at your nearest GNU archive site.  But you do _not_
+need to install GNU `gettext' prior to configuring, installing or using
+this package with messages translated.
+
+   Installers will find here some useful hints.  These notes also
+explain how users should proceed for getting the programs to use the
+available translations.  They tell how people wanting to contribute and
+work at translations should contact the appropriate team.
+
+   When reporting bugs in the `intl/' directory or bugs which may be
+related to internationalization, you should tell about the version of
+`gettext' which is used.  The information can be found in the
+`intl/VERSION' file, in internationalized packages.
+
+Quick configuration advice
+==========================
+
+   If you want to exploit the full power of internationalization, you
+should configure it using
+
+     ./configure --with-included-gettext
+
+to force usage of internationalizing routines provided within this
+package, despite the existence of internationalizing capabilities in the
+operating system where this package is being installed.  So far, only
+the `gettext' implementation in the GNU C library version 2 provides as
+many features (such as locale alias, message inheritance, automatic
+charset conversion or plural form handling) as the implementation here.
+It is also not possible to offer this additional functionality on top
+of a `catgets' implementation.  Future versions of GNU `gettext' will
+very likely convey even more functionality.  So it might be a good idea
+to change to GNU `gettext' as soon as possible.
+
+   So you need _not_ provide this option if you are using GNU libc 2 or
+you have installed a recent copy of the GNU gettext package with the
+included `libintl'.
+
+INSTALL Matters
+===============
+
+   Some packages are "localizable" when properly installed; the
+programs they contain can be made to speak your own native language.
+Most such packages use GNU `gettext'.  Other packages have their own
+ways to internationalization, predating GNU `gettext'.
+
+   By default, this package will be installed to allow translation of
+messages.  It will automatically detect whether the system already
+provides the GNU `gettext' functions.  If not, the GNU `gettext' own
+library will be used.  This library is wholly contained within this
+package, usually in the `intl/' subdirectory, so prior installation of
+the GNU `gettext' package is _not_ required.  Installers may use
+special options at configuration time for changing the default
+behaviour.  The commands:
+
+     ./configure --with-included-gettext
+     ./configure --disable-nls
+
+will respectively bypass any pre-existing `gettext' to use the
+internationalizing routines provided within this package, or else,
+_totally_ disable translation of messages.
+
+   When you already have GNU `gettext' installed on your system and run
+configure without an option for your new package, `configure' will
+probably detect the previously built and installed `libintl.a' file and
+will decide to use this.  This might be not what is desirable.  You
+should use the more recent version of the GNU `gettext' library.  I.e.
+if the file `intl/VERSION' shows that the library which comes with this
+package is more recent, you should use
+
+     ./configure --with-included-gettext
+
+to prevent auto-detection.
+
+   The configuration process will not test for the `catgets' function
+and therefore it will not be used.  The reason is that even an
+emulation of `gettext' on top of `catgets' could not provide all the
+extensions of the GNU `gettext' library.
+
+   Internationalized packages have usually many `po/LL.po' files, where
+LL gives an ISO 639 two-letter code identifying the language.  Unless
+translations have been forbidden at `configure' time by using the
+`--disable-nls' switch, all available translations are installed
+together with the package.  However, the environment variable `LINGUAS'
+may be set, prior to configuration, to limit the installed set.
+`LINGUAS' should then contain a space separated list of two-letter
+codes, stating which languages are allowed.
+
+Using This Package
+==================
+
+   As a user, if your language has been installed for this package, you
+only have to set the `LANG' environment variable to the appropriate
+`LL_CC' combination.  Here `LL' is an ISO 639 two-letter language code,
+and `CC' is an ISO 3166 two-letter country code.  For example, let's
+suppose that you speak German and live in Germany.  At the shell
+prompt, merely execute `setenv LANG de_DE' (in `csh'),
+`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
+This can be done from your `.login' or `.profile' file, once and for
+all.
+
+   You might think that the country code specification is redundant.
+But in fact, some languages have dialects in different countries.  For
+example, `de_AT' is used for Austria, and `pt_BR' for Brazil.  The
+country code serves to distinguish the dialects.
+
+   The locale naming convention of `LL_CC', with `LL' denoting the
+language and `CC' denoting the country, is the one use on systems based
+on GNU libc.  On other systems, some variations of this scheme are
+used, such as `LL' or `LL_CC.ENCODING'.  You can get the list of
+locales supported by your system for your country by running the command
+`locale -a | grep '^LL''.
+
+   Not all programs have translations for all languages.  By default, an
+English message is shown in place of a nonexistent translation.  If you
+understand other languages, you can set up a priority list of languages.
+This is done through a different environment variable, called
+`LANGUAGE'.  GNU `gettext' gives preference to `LANGUAGE' over `LANG'
+for the purpose of message handling, but you still need to have `LANG'
+set to the primary language; this is required by other parts of the
+system libraries.  For example, some Swedish users who would rather
+read translations in German than English for when Swedish is not
+available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
+
+   In the `LANGUAGE' environment variable, but not in the `LANG'
+environment variable, `LL_CC' combinations can be abbreviated as `LL'
+to denote the language's main dialect.  For example, `de' is equivalent
+to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
+(Portuguese as spoken in Portugal) in this context.
+
+Translating Teams
+=================
+
+   For the Free Translation Project to be a success, we need interested
+people who like their own language and write it well, and who are also
+able to synergize with other translators speaking the same language.
+Each translation team has its own mailing list.  The up-to-date list of
+teams can be found at the Free Translation Project's homepage,
+`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams"
+area.
+
+   If you'd like to volunteer to _work_ at translating messages, you
+should become a member of the translating team for your own language.
+The subscribing address is _not_ the same as the list itself, it has
+`-request' appended.  For example, speakers of Swedish can send a
+message to `sv-request@li.org', having this message body:
+
+     subscribe
+
+   Keep in mind that team members are expected to participate
+_actively_ in translations, or at solving translational difficulties,
+rather than merely lurking around.  If your team does not exist yet and
+you want to start one, or if you are unsure about what to do or how to
+get started, please write to `translation@iro.umontreal.ca' to reach the
+coordinator for all translator teams.
+
+   The English team is special.  It works at improving and uniformizing
+the terminology in use.  Proven linguistic skill are praised more than
+programming skill, here.
+
+Available Packages
+==================
+
+   Languages are not equally supported in all packages.  The following
+matrix shows the current state of internationalization, as of January
+2002.  The matrix shows, in regard of each package, for which languages
+PO files have been submitted to translation coordination, with a
+translation percentage of at least 50%.
+
+     Ready PO files    bg ca cs da de el en eo es et fi fr
+                     +-------------------------------------+
+     a2ps            |          [] []             []    [] |
+     bash            |             []       [] []       [] |
+     bfd             |                         []       [] |
+     binutils        |                         []       [] |
+     bison           |             []             []    [] |
+     clisp           |             []    []    []       [] |
+     cpio            |          [] []          []       [] |
+     diffutils       |       [] [] []       [] []       [] |
+     enscript        |             []                   [] |
+     error           |                         []       [] |
+     fetchmail       |       () [] []          []       () |
+     fileutils       |          [] []          [] []    [] |
+     findutils       |          [] []          [] []    [] |
+     flex            |          []             []       [] |
+     gas             |                                  [] |
+     gawk            |                         []       [] |
+     gcal            |    []                            [] |
+     gcc             |                         []       [] |
+     gettext         |    []    [] []          []       [] |
+     gnupg           |             [] []    [] [] []    [] |
+     gprof           |                         []       [] |
+     grep            |       []    []       [] [] []    [] |
+     hello           |          [] [] []    [] [] [] [] [] |
+     id-utils        |          [] []                   [] |
+     indent          |             []       []    []    [] |
+     jpilot          |       () [] []                   [] |
+     jwhois          |                         []       [] |
+     kbd             |                                  [] |
+     ld              |                         []       [] |
+     libc            |    [] [] [] [] []       []       [] |
+     lilypond        |          []                      [] |
+     lynx            |       [] [] []             []       |
+     m4              |       [] [] [] []                [] |
+     make            |          [] []          []       [] |
+     mysecretdiary   |             []                   [] |
+     nano            |    [] () [] []          []       [] |
+     nano_1_0        |    [] () [] []          []       [] |
+     opcodes         |          []             []       [] |
+     parted          |    []    [] []                   [] |
+     ptx             |          [] []          [] []    [] |
+     python          |                                     |
+     recode          |          [] [] []    [] []       [] |
+     sed             |       [] [] [] []    [] [] []    [] |
+     sh-utils        |    [] [] [] [] []       [] []    [] |
+     sharutils       |       [] [] [] []       []       [] |
+     sketch          |             ()          []       () |
+     soundtracker    |             []          []       [] |
+     sp              |                                     |
+     tar             |       [] [] []          [] []    [] |
+     texinfo         |       [] [] []       []          [] |
+     textutils       |          [] []          []       [] |
+     util-linux      |       [] []             []       [] |
+     wdiff           |          [] []          [] []    [] |
+     wget            |    [] [] [] [] []       [] []    [] |
+                     +-------------------------------------+
+                       bg ca cs da de el en eo es et fi fr
+                        0  8 12 31 36  9  1  9 37 15  1 49
+     
+                       gl he hr hu id it ja ko lv nb nl nn
+                     +-------------------------------------+
+     a2ps            |                ()    ()       []    |
+     bash            |                                     |
+     bfd             |                   []                |
+     binutils        |                   []                |
+     bison           |                   []                |
+     clisp           |                               []    |
+     cpio            | []                   []       []    |
+     diffutils       | [] []                               |
+     enscript        |                               []    |
+     error           |          []                         |
+     fetchmail       |                                     |
+     fileutils       |                [] []                |
+     findutils       | []          [] [] [] []       []    |
+     flex            |                      []             |
+     gas             |                                     |
+     gawk            |    []                               |
+     gcal            |                                     |
+     gcc             |                   []                |
+     gettext         |                      []             |
+     gnupg           | []             [] []                |
+     gprof           |                                     |
+     grep            | []             []                   |
+     hello           | []       []    [] [] [] [] [] [] [] |
+     id-utils        |                               []    |
+     indent          | []                []          []    |
+     jpilot          |                   ()          ()    |
+     jwhois          |                                     |
+     kbd             |                                     |
+     ld              |                                     |
+     libc            | []                [] []    []       |
+     lilypond        |                   []          []    |
+     lynx            |                   []          []    |
+     m4              | []          []    []          []    |
+     make            | []                [] []       []    |
+     mysecretdiary   |                                     |
+     nano            | []          [] [] ()          () [] |
+     nano_1_0        | []          [] [] ()          () [] |
+     opcodes         |                                     |
+     parted          | []                []             [] |
+     ptx             | []          []             [] []    |
+     python          |                                     |
+     recode          | [] []          []                   |
+     sed             | [] []       [] [] [] []       []    |
+     sh-utils        | []             [] []       [] []    |
+     sharutils       | []                []          []    |
+     sketch          |                ()                   |
+     soundtracker    | []                                  |
+     sp              |                                     |
+     tar             |                [] []       []       |
+     texinfo         |    [] []          []                |
+     textutils       |                      []    []       |
+     util-linux      |                () []                |
+     wdiff           |                                     |
+     wget            | [] []    []       []          []    |
+                     +-------------------------------------+
+                       gl he hr hu id it ja ko lv nb nl nn
+                       20  6  1  3  6 11 22  9  1  6 17  4
+     
+                       no pl pt pt_BR ru sk sl sv tr uk zh
+                     +-------------------------------------+
+     a2ps            | () () ()       []    [] [] ()       |  8
+     bash            |                                     |  4
+     bfd             |                         [] []       |  5
+     binutils        |                            []       |  4
+     bison           |                []       [] []       |  7
+     clisp           |                                     |  5
+     cpio            |    []     []   []       []          | 11
+     diffutils       |                []       [] []       | 11
+     enscript        |           []   []       []          |  6
+     error           |                   []       []       |  5
+     fetchmail       |    ()     ()                        |  3
+     fileutils       |                []    [] [] []       | 11
+     findutils       |    []     []   []    [] [] []       | 17
+     flex            |                []       []          |  6
+     gas             |                            []       |  2
+     gawk            |                         [] []       |  5
+     gcal            |                         []          |  3
+     gcc             |                            []       |  4
+     gettext         |                   [] [] [] []       | 10
+     gnupg           |    []                   [] []       | 12
+     gprof           |                         [] []       |  4
+     grep            |    []          []    [] [] []       | 13
+     hello           | [] []          [] []    [] [] []    | 24
+     id-utils        |                []       []          |  6
+     indent          |                [] []    [] []       | 11
+     jpilot          | ()                      ()          |  3
+     jwhois          |                ()       ()          |  2
+     kbd             |                         [] []       |  3
+     ld              |                         [] []       |  4
+     libc            | [] []     []      []    [] []       | 17
+     lilypond        |                         []          |  5
+     lynx            |           []   []       []          |  9
+     m4              |    []          []       []          | 12
+     make            |    []     []   []          []       | 12
+     mysecretdiary   |                         []          |  3
+     nano            | ()             []       []    []    | 12
+     nano_1_0        | ()             []       []    []    | 12
+     opcodes         |                         [] []       |  5
+     parted          |       []  []            []          | 10
+     ptx             | [] [] []       []       [] []       | 15
+     python          |                                     |  0
+     recode          |    []          []    [] []          | 13
+     sed             |           []   [] [] [] [] []       | 21
+     sh-utils        | [] []     []   [] [] [] [] []    [] | 22
+     sharutils       |                []       []          | 11
+     sketch          |                ()                   |  1
+     soundtracker    |                                     |  4
+     sp              |                                     |  0
+     tar             | [] []     []      [] [] [] []       | 16
+     texinfo         |                []       []          | 10
+     textutils       |                      []    []       |  8
+     util-linux      |           []            [] []       |  8
+     wdiff           |                [] []    [] []       |  9
+     wget            |                [] [] [] [] [] []    | 19
+                     +-------------------------------------+
+       35 teams        no pl pt pt_BR ru sk sl sv tr uk zh
+       54 domains       5 12  2  11   25 10 11 39 29  4  1  463
+
+   Some counters in the preceding matrix are higher than the number of
+visible blocks let us expect.  This is because a few extra PO files are
+used for implementing regional variants of languages, or language
+dialects.
+
+   For a PO file in the matrix above to be effective, the package to
+which it applies should also have been internationalized and
+distributed as such by its maintainer.  There might be an observable
+lag between the mere existence a PO file and its wide availability in a
+distribution.
+
+   If January 2002 seems to be old, you may fetch a more recent copy of
+this `ABOUT-NLS' file on most GNU archive sites.  The most up-to-date
+matrix with full percentage details can be found at
+`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'.
+
+Using `gettext' in new packages
+===============================
+
+   If you are writing a freely available program and want to
+internationalize it you are welcome to use GNU `gettext' in your
+package.  Of course you have to respect the GNU Library General Public
+License which covers the use of the GNU `gettext' library.  This means
+in particular that even non-free programs can use `libintl' as a shared
+library, whereas only free software can use `libintl' as a static
+library or use modified versions of `libintl'.
+
+   Once the sources are changed appropriately and the setup can handle
+to use of `gettext' the only thing missing are the translations.  The
+Free Translation Project is also available for packages which are not
+developed inside the GNU project.  Therefore the information given above
+applies also for every other Free Software Project.  Contact
+`translation@iro.umontreal.ca' to make the `.pot' files available to
+the translation teams.
+
Index: /tags/kBuild-0.1.4/src/sed/AUTHORS
===================================================================
--- /tags/kBuild-0.1.4/src/sed/AUTHORS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/AUTHORS	(revision 1780)
@@ -0,0 +1,5 @@
+GNU Sed was first authored by Jay Fenlason (hack@gnu.org)
+and later modified by Tom Lord (lord@gnu.org).
+
+It is currently being maintained by Ken Pizzini (ken@gnu.org)
+and Paolo Bonzini (bonzini@gnu.org).
Index: /tags/kBuild-0.1.4/src/sed/BUGS
===================================================================
--- /tags/kBuild-0.1.4/src/sed/BUGS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/BUGS	(revision 1780)
@@ -0,0 +1,122 @@
+* ABOUT BUGS
+
+Before reporting a bug, please check the list of known bugs
+and the list of oft-reported non-bugs (below).
+
+Bugs and comments may be sent to bonzini@gnu.org; please
+include in the Subject: header the first line of the output of
+``sed --version''.
+
+Please do not send a bug report like this:
+
+	[while building frobme-1.3.4] 
+	$ configure 
+	sed: file sedscr line 1: Unknown option to 's'
+
+If sed doesn't configure your favorite package, take a few extra
+minutes to identify the specific problem and make a stand-alone test
+case.
+
+A stand-alone test case includes all the data necessary to perform the
+test, and the specific invocation of sed that causes the problem.  The
+smaller a stand-alone test case is, the better.  A test case should
+not involve something as far removed from sed as ``try to configure
+frobme-1.3.4''.  Yes, that is in principle enough information to look
+for the bug, but that is not a very practical prospect.
+
+
+
+* NON-BUGS
+
+`N' command on the last line
+
+  Most versions of sed exit without printing anything when the `N'
+  command is issued on the last line of a file.  GNU sed instead
+  prints pattern space before exiting unless of course the `-n'
+  command switch has been specified.  More information on the reason
+  behind this choice can be found in the Info manual.
+
+
+regex syntax clashes (problems with backslashes)
+
+  sed uses the Posix basic regular expression syntax.  According to
+  the standard, the meaning of some escape sequences is undefined in
+  this syntax;  notable in the case of GNU sed are `\|', `\+', `\?',
+  `\`', `\'', `\<', `\>', `\b', `\B', `\w', and `\W'.
+
+  As in all GNU programs that use Posix basic regular expressions, sed
+  interprets these escape sequences as meta-characters.  So, `x\+'
+  matches one or more occurrences of `x'.   `abc\|def' matches either
+  `abc' or `def'.
+
+  This syntax may cause problems when running scripts written for other
+  seds.  Some sed programs have been written with the assumption that
+  `\|' and `\+' match the literal characters `|' and `+'.  Such scripts
+  must be modified by removing the spurious backslashes if they are to
+  be used with recent versions of sed (not only GNU sed).
+
+  On the other hand, some scripts use `s|abc\|def||g' to remove occurrences
+  of _either_ `abc' or `def'.  While this worked until sed 4.0.x, newer
+  versions interpret this as removing the string `abc|def'.  This is
+  again undefined behavior according to POSIX, but this interpretation
+  is arguably more robust: the older one, for example, required that
+  the regex matcher parsed `\/' as `/' in the common case of escaping
+  a slash, which is again undefined behavior; the new behavior avoids
+  this, and this is good because the regex matcher is only partially
+  under our control.
+
+  In addition, GNU sed supports several escape characters (some of
+  which are multi-character) to insert non-printable characters
+  in scripts (`\a', `\c', `\d', `\o', `\r', `\t', `\v', `\x').  These
+  can cause similar problems with scripts written for other seds.
+
+
+-i clobbers read-only files
+
+  In short, `sed d -i' will let one delete the contents of
+  a read-only file, and in general the `-i' option will let
+  one clobber protected files.  This is not a bug, but rather a
+  consequence of how the Unix filesystem works.
+
+  The permissions on a file say what can happen to the data
+  in that file, while the permissions on a directory say what can
+  happen to the list of files in that directory.  `sed -i'
+  will not ever open for writing  a file that is already on disk,
+  rather, it will work on a temporary file that is finally renamed
+  to the original name: if you rename or delete files, you're actually
+  modifying the contents of the directory, so the operation depends on
+  the permissions of the directory, not of the file).  For this same
+  reason, sed will not let one use `-i' on a writeable file in a
+  read-only directory (but unbelievably nobody reports that as a
+  bug...).
+
+
+`0a' does not work (gives an error)
+
+  There is no line 0.  0 is a special address that is only used to treat
+  addresses like `0,/RE/' as active when the script starts: if you
+  write `1,/abc/d' and the first line includes the word `abc', then
+  that match would be ignored because address ranges must span at least
+  two lines (barring the end of the file); but what you probably wanted is
+  to delete every line up to the first one including `abc', and this
+  is obtained with `0,/abc/d'.
+
+
+`[a-z]' is case insensitive
+
+  You are encountering problems with locales.  POSIX mandates that `[a-z]'
+  uses the current locale's collation order -- in C parlance, that means
+  strcoll(3) instead of strcmp(3).  Some locales have a case insensitive
+  strcoll, others don't: one of those that have problems is Estonian.
+
+  Another problem is that [a-z] tries to use collation symbols.  This
+  only happens if you are on the GNU system, using GNU libc's regular
+  expression matcher instead of compiling the one supplied with GNU sed.
+  In a Danish locale, for example, the regular expression `^[a-z]$'
+  matches the string `aa', because aa is a single collating symbol that
+  comes after `a' and before `b'; `ll' behaves similarly in Spanish
+  locales, or `ij' in Dutch locales.
+
+  To work around these problems, which may cause bugs in shell scripts,
+  set the LC_ALL environment variable to `C', or set the locale on a
+  more fine-grained basis with the other LC_* environment variables.
Index: /tags/kBuild-0.1.4/src/sed/COPYING
===================================================================
--- /tags/kBuild-0.1.4/src/sed/COPYING	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/COPYING	(revision 1780)
@@ -0,0 +1,345 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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.
+
+
+		    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.)
+
+
+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.
+
+
+  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.
+
+
+  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
+
+
+	    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) <year>  <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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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) year  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.
Index: /tags/kBuild-0.1.4/src/sed/COPYING.DOC
===================================================================
--- /tags/kBuild-0.1.4/src/sed/COPYING.DOC	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/COPYING.DOC	(revision 1780)
@@ -0,0 +1,355 @@
+		GNU Free Documentation License
+		   Version 1.1, March 2000
+
+ Copyright (C) 2000  Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+0. PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+written document "free" in the sense of freedom: to assure everyone
+the effective freedom to copy and redistribute it, with or without
+modifying it, either commercially or noncommercially.  Secondarily,
+this License preserves for the author and publisher a way to get
+credit for their work, while not being considered responsible for
+modifications made by others.
+
+This License is a kind of "copyleft", which means that derivative
+works of the document must themselves be free in the same sense.  It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does.  But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book.  We recommend this License
+principally for works whose purpose is instruction or reference.
+
+
+1. APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work that contains a
+notice placed by the copyright holder saying it can be distributed
+under the terms of this License.  The "Document", below, refers to any
+such manual or work.  Any member of the public is a licensee, and is
+addressed as "you".
+
+A "Modified Version" of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A "Secondary Section" is a named appendix or a front-matter section of
+the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall subject
+(or to related matters) and contains nothing that could fall directly
+within that overall subject.  (For example, if the Document is in part a
+textbook of mathematics, a Secondary Section may not explain any
+mathematics.)  The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The "Invariant Sections" are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License.
+
+The "Cover Texts" are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License.
+
+A "Transparent" copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, whose contents can be viewed and edited directly and
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters.  A copy made in an otherwise Transparent file
+format whose markup has been designed to thwart or discourage
+subsequent modification by readers is not Transparent.  A copy that is
+not "Transparent" is called "Opaque".
+
+Examples of suitable formats for Transparent copies include plain
+ASCII without markup, Texinfo input format, LaTeX input format, SGML
+or XML using a publicly available DTD, and standard-conforming simple
+HTML designed for human modification.  Opaque formats include
+PostScript, PDF, proprietary formats that can be read and edited only
+by proprietary word processors, SGML or XML for which the DTD and/or
+processing tools are not generally available, and the
+machine-generated HTML produced by some word processors for output
+purposes only.
+
+The "Title Page" means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page.  For works in
+formats which do not have any title page as such, "Title Page" means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+
+2. VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License.  You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute.  However, you may accept
+compensation in exchange for copies.  If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+
+3. COPYING IN QUANTITY
+
+If you publish printed copies of the Document numbering more than 100,
+and the Document's license notice requires Cover Texts, you must enclose
+the copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover.  Both covers must also clearly and legibly identify
+you as the publisher of these copies.  The front cover must present
+the full title with all words of the title equally prominent and
+visible.  You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a publicly-accessible computer-network location containing a complete
+Transparent copy of the Document, free of added material, which the
+general network-using public has access to download anonymously at no
+charge using public-standard network protocols.  If you use the latter
+option, you must take reasonably prudent steps, when you begin
+distribution of Opaque copies in quantity, to ensure that this
+Transparent copy will remain thus accessible at the stated location
+until at least one year after the last time you distribute an Opaque
+copy (directly or through your agents or retailers) of that edition to
+the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+
+4. MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it.  In addition, you must do these things in the Modified Version:
+
+A. Use in the Title Page (and on the covers, if any) a title distinct
+   from that of the Document, and from those of previous versions
+   (which should, if there were any, be listed in the History section
+   of the Document).  You may use the same title as a previous version
+   if the original publisher of that version gives permission.
+B. List on the Title Page, as authors, one or more persons or entities
+   responsible for authorship of the modifications in the Modified
+   Version, together with at least five of the principal authors of the
+   Document (all of its principal authors, if it has less than five).
+C. State on the Title page the name of the publisher of the
+   Modified Version, as the publisher.
+D. Preserve all the copyright notices of the Document.
+E. Add an appropriate copyright notice for your modifications
+   adjacent to the other copyright notices.
+F. Include, immediately after the copyright notices, a license notice
+   giving the public permission to use the Modified Version under the
+   terms of this License, in the form shown in the Addendum below.
+G. Preserve in that license notice the full lists of Invariant Sections
+   and required Cover Texts given in the Document's license notice.
+H. Include an unaltered copy of this License.
+I. Preserve the section entitled "History", and its title, and add to
+   it an item stating at least the title, year, new authors, and
+   publisher of the Modified Version as given on the Title Page.  If
+   there is no section entitled "History" in the Document, create one
+   stating the title, year, authors, and publisher of the Document as
+   given on its Title Page, then add an item describing the Modified
+   Version as stated in the previous sentence.
+J. Preserve the network location, if any, given in the Document for
+   public access to a Transparent copy of the Document, and likewise
+   the network locations given in the Document for previous versions
+   it was based on.  These may be placed in the "History" section.
+   You may omit a network location for a work that was published at
+   least four years before the Document itself, or if the original
+   publisher of the version it refers to gives permission.
+K. In any section entitled "Acknowledgements" or "Dedications",
+   preserve the section's title, and preserve in the section all the
+   substance and tone of each of the contributor acknowledgements
+   and/or dedications given therein.
+L. Preserve all the Invariant Sections of the Document,
+   unaltered in their text and in their titles.  Section numbers
+   or the equivalent are not considered part of the section titles.
+M. Delete any section entitled "Endorsements".  Such a section
+   may not be included in the Modified Version.
+N. Do not retitle any existing section as "Endorsements"
+   or to conflict in title with any Invariant Section.
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant.  To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section entitled "Endorsements", provided it contains
+nothing but endorsements of your Modified Version by various
+parties--for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version.  Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity.  If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+
+5. COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy.  If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections entitled "History"
+in the various original documents, forming one section entitled
+"History"; likewise combine any sections entitled "Acknowledgements",
+and any sections entitled "Dedications".  You must delete all sections
+entitled "Endorsements."
+
+
+6. COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+
+7. AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, does not as a whole count as a Modified Version
+of the Document, provided no compilation copyright is claimed for the
+compilation.  Such a compilation is called an "aggregate", and this
+License does not apply to the other self-contained works thus compiled
+with the Document, on account of their being thus compiled, if they
+are not themselves derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one quarter
+of the entire aggregate, the Document's Cover Texts may be placed on
+covers that surround only the Document within the aggregate.
+Otherwise they must appear on covers around the whole aggregate.
+
+
+8. TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections.  You may include a
+translation of this License provided that you also include the
+original English version of this License.  In case of a disagreement
+between the translation and the original English version of this
+License, the original English version will prevail.
+
+
+9. TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License.  Any other attempt to
+copy, modify, sublicense or distribute the Document 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.
+
+
+10. FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation 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.  See
+http://www.gnu.org/copyleft/.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License "or any later version" applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation.  If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+
+
+ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+      Copyright (c)  YEAR  YOUR NAME.
+      Permission is granted to copy, distribute and/or modify this document
+      under the terms of the GNU Free Documentation License, Version 1.1
+      or any later version published by the Free Software Foundation;
+      with the Invariant Sections being LIST THEIR TITLES, with the
+      Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
+      A copy of the license is included in the section entitled "GNU
+      Free Documentation License".
+
+If you have no Invariant Sections, write "with no Invariant Sections"
+instead of saying which ones are invariant.  If you have no
+Front-Cover Texts, write "no Front-Cover Texts" instead of
+"Front-Cover Texts being LIST"; likewise for Back-Cover Texts.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
Index: /tags/kBuild-0.1.4/src/sed/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/src/sed/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/ChangeLog	(revision 1780)
@@ -0,0 +1,2748 @@
+2006-02-03  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (compile_program) <case 'y'>: Pass false to match_slash.
+
+2005-09-07  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/regcomp.c: Update from upstream.
+	* lib/regex.c: Update from upstream.
+	* lib/regex_.h: Update from upstream.
+	* lib/regex_internal.c: Update from upstream.
+	* lib/regex_internal.h: Update from upstream.
+	* lib/regexec.c: Update from upstream.
+
+2005-08-30  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/execute.c (reset_addresses): Never activate ADDR_IS_NUM_MOD
+	addresses.
+	* testsuite/modulo.good, testsuite/modulo.inp, testsuite/modulo.sed:
+	New.
+	* testsuite/Makefile.tests: Add new testcase.
+	* testsuite/Makefile.am: Add new testcase.
+	* testsuite/Makefile.in: Regenerate.
+
+2005-05-18  Maciej W. Rozycki  <macro@linux-mips.org>
+
+	* configure.ac: Use a cache variable for the libcP test.
+	* configure: Regenerate.
+
+2005-05-16  Eero Hakkinen  <eero17@bigfoot.com>
+
+	* sed/compile.c (snarf_char_class): Fix handling of 
+	[^]xyz].
+
+2005-04-04  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/execute.c (process_files): Do not add a default
+	command-line in in-place editing mode.
+
+2005-02-10  Paolo Bonzini  <bonzini@gnu.org>
+
+	* testsuite/Makefile.tests: Add new testcase.
+	* testsuite/Makefile.am: Add new testcase.
+	* testsuite/Makefile.in: Regenerate.
+	* testsuite/appquit.good, testsuite/appquit.inp,
+	testsuite/appquit.sed: New testcase.
+	* testsuite/readin.sed: Quit after the last r command.
+	* testsuite/readin.good: Adjust.
+	* sed/execute.c (execute_program): Dump the results of the
+	a/r/R commands just before quitting.
+
+2005-02-10  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/regexp.c: Fix off-by-one error in the "invalid reference
+	to subexpression" message.  Debian bug 294339.
+
+2005-02-08  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/obstack.h: include config.h.
+
+2005-02-01  Paolo Bonzini  <bonzini@gnu.org>
+
+	* doc/Makefile.am: Don't enable MAKEINFO_HTML and TEXI2HTML_HTML
+	rules unless BUILD_HTML.
+
+2005-01-25  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/regexp.c: Fix building on GCC 2.95 and earlier.
+
+2004-12-26  Paolo Bonzini  <bonzini@gnu.org>
+
+	Do not use leftmost-longest matching for addresses.
+
+	* NEWS: Add a note about this.
+	* testsuite/recall2.good, testsuite/recall2.inp,
+	testsuite/recall2.sed: New test.
+	* testsuite/Makefile.am, testsuite/Makefile.tests: Add the
+	recall2 test.
+	* sed/sed.h (struct regex): New.
+	(struct addr, struct subst, compile_regex, match_regex,
+	release_regex): Use it instead of regex_t.
+	* sed/compile.c (compile_program): Update for new meaning of
+	the third parameter of compile_regex.
+	* sed/execute.c (do_subst): Pass less conservative value to
+	the regsize parameter of match_regex.
+	* sed/regexp.c (compile_regex_1): New, extracted out of
+	compile_regex.  The third parameter, needed_sub, now includes
+	\0 (so 10 means that \0 .. \9 are needed).  Pass RE_NO_SUB
+	if needed_sub is zero.
+	(compile_regex): Accept a struct regex instead of a regex_t.
+	Save the regular expression's text.
+	(match_regex): Accept a struct regex instead of a regex_t.
+	Recompile the pattern if it was compiled with RE_NO_SUB.
+	(release_regex): Accept a struct regex instead of a regex_t.
+
+	* doc/Makefile.am: Generate sed.texi correctly when
+	building outside srcdir.
+
+2004-12-26  Paolo Bonzini  <bonzini@gnu.org>
+
+	* BUGS: Add section about [a-z] matching uppercase characters,
+	and other locale issues.
+	* doc/sed-in.texi [!PERL]: Likewise.
+
+2004-11-15  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/execute.c (str_append_modified): Copy the first character
+	when using \l or \u in a multi-byte configuration.  Use
+	WCRTOMB instead of wcrtomb.
+	* sed/sed.h (WCRTOMB): New.
+
+2004-11-11  Paolo Bonzini  <bonzini@gnu.org>
+
+	* tst-rxspecer.c: Do not mix instructions and
+	declarations.
+	* basicdefs.h: Include locale.h before #defining
+	gettext, to avoid breakage under Solaris.
+	* sed/sed.c: do not include locale.h.
+
+2004-11-03  Paolo Bonzini  <bonzini@gnu.org>
+
+	* bug-regex11.c: Improve portability.
+	* bug-regex12.c: Improve portability.
+	* bug-regex13.c: Improve portability.
+	* bug-regex14.c: Improve portability.
+	* bug-regex21.c: Improve portability.
+	* bug-regex9.c: Improve portability.
+	* tst-boost.c: Improve portability.
+	* tst-pcre.c: Improve portability.
+	* tst-regex.c: Improve portability.
+	* tst-rxspencer.c: Improve portability.
+
+2004-10-08  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/utils.c (utils_id_s): Renamed to open_files.
+	(struct id): Renamed to struct open_file.
+
+2004-10-08  Jakub Jelinek  <jakub@redhat.com>
+
+	* testsuite/Makefile.tests (bug-regex*, run-tests,
+	run-ptests): Use $(SED).
+	(version): Likewise; prepend $(SED) invocation with $(SEDENV).
+
+2004-08-16  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.1.2 released.
+
+2004-08-06  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (bad_command): Fix off-by-one error.
+	(snarf_char_class): Fix problem with [.....[] (i.e.
+	last char in class is a bracket.
+
+2004-06-30  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.1.1 released.
+
+2004-06-29  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (mark_subst_opts): Return int.
+	* sed/execute.c (open_next_file): Fix uninitialized
+	variable.
+
+2004-06-10  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.1 released.
+
+2004-03-25  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/obstack.h: Get current version.
+
+2004-03-13  Paolo Bonzini  <bonzini@gnu.org>
+
+	Exit as soon as possible on an I/O error, and with
+	a better error message.
+
+	* lib/utils.c (ck_mkstemp, ck_rename, ck_getline): New
+	functions.  Save temporary files into utils_id_s.
+	(struct id): Add a field named temp.
+	(ck_fopen): Init the new temp field of struct id.
+	(panic): Unlink temporary files before exiting.
+	* sed/execute.c (read_file_line): Use ck_getline.
+	(closedown): Use ck_rename.
+	(open_next_file): Use ck_mkstemp.
+
+2004-01-20  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/sed.h (enum addr_state): New definition.
+	(enum addr_type): Remove ADDR_IS_NUM2.
+	(struct sed_cmd): Replace a1_matched with range_state.
+	* sed/compile.c (next_cmd_entry): Use range_state.
+	(compile_program): Death to ADDR_IS_NUM2.  Compile
+	N,Mp as Np if N>=M.
+	* sed/execute.c (match_address_p): Rewritten.  Handle
+	ADDR_IS_NUM here.
+	(match_an_address_p): Suit to new match_address_p.
+	(execute_program): Adjust to use range_state in `c'.
+	Handle addr_bang here.
+	(reset_addresses): Use range_state.
+
+	(struct input): New field "reset_at_next_file".
+	(read_pattern_space): Use it instead of "separate_files".
+	(process_files): Initialize it.
+	
+2004-01-17  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/sed.h: Do not include wchar.h and wctype.h, and do
+	not include the alloca stuff.
+	* basicdefs.h: Move all that here.
+
+2004-01-15  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/regexp.c [REG_PERL]: Use REG_STARTEND instead of regexec2.
+
+2004-01-09  Paul Eggert  <eggert@twinsun.com>
+	    Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/sed.h (posixicity): New variable, replaces POSIXLY_CORRECT.
+	* sed/sed.c (main): Set it.
+	* sed/compile.c: Use it instead of POSIXLY_CORRECT.
+	* sed/execute.c: Use it instead of POSIXLY_CORRECT.
+	* doc/sed-in.texi: Document it and --posix.
+
+2004-01-05  Paul Eggert  <eggert@twinsun.com>
+	    Paolo Bonzini  <bonzini@gnu.org>
+
+        * NEWS: Fix [\n] to match either backslash or n in POSIXLY_CORRECT mode.
+        * doc/sed-in.texi: Document this.  Also, document regular expressions
+        a bit better overall, using terminology that's more similar to POSIX.
+	* sed/sed.h (enum text_types): New definition.
+	* sed/compile.c (normalize_text): Replace final parameter with one of
+	type normalize_text.  If TEXT_REGEX and in POSIXLY_CORRECT mode,
+	grok character classes without replacing \n inside them.
+
+2004-01-03  Paolo Bonzini  <bonzini@gnu.org>
+
+        * sed/execute.c (execute_program): print final line
+        after executing N, if not POSIXLY_CORRECT.
+
+2003-12-28  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c: fix "\\\n" in RHS of s command.
+	Reported by Mike Castle.
+	* testsuite/bkslashes.inp, testsuite/bkslashes.good,
+	testsuite/bkslashes.sed: New files.
+	* testsuite/Makefile.am, testsuite/Makefile.tests: Add
+	the bkslashes test.
+
+2003-12-16  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0b released.
+
+	* sed/mbcs.c: New file.
+	* sed/sed.h: Declare macros for mbcs.c.
+	* sed/compile.c: Use them.
+	(brlen): Moved to mbcs.c.
+	* sed/execute.c: Use them.
+	* sed/sed.c: call initialize_mbcs ().
+
+2003-12-14  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/regex.c (match_regex): fix memory leak.
+
+2003-11-27  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/execute.c (reset_addresses): leave addresses 0
+	and 0~STEP enabled.
+
+2003-11-15  Jakub Jelinek  <jakub@redhat.com>
+
+	* sed/regex.c: Use fastmap.
+
+2003-09-21  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0a released.
+
+	* sed/execute.c (struct line): Add mbstate field.
+	(str_append): Keep mbstate up to date.
+	(str_append_modified): Likewise, and use towupper/towlower.
+	(line_init): Initialize mbstate.
+	(line_copy): Copy mbstate.
+	(line_append): Copy mbstate.
+
+2003-07-15  Stepan Kasal  <kasal@ucw.cz>
+	    Paolo Bonzini  <bonzini@fnu.org>
+
+	Change the way we treat lines which are not terminated by a newline.
+	Such lines are printed without the terminating newline (as before)
+	but as soon as more text is sent to the same output stream, the
+	missing newline is printed, so that the two lines don't concatenate.
+
+	* sed/execute.c (output_file): Is now struct output; users adjusted
+	to access the fp field, call output_missing_newline before, and
+	call flush_output afterwards.
+	(read_file_line): Set line.chomped FALSE each time we encounter a
+	line without the newline terminator, no matter whether this is the
+	last input file or not, and no matter whether we are in
+	POSIXLY_CORRECT mode or not.
+	(output_missing_newline): New function which prints the suppressed
+	newline, if necessary.
+	(flush_output): New function for a common pattern.
+	(output_line): Use struct output, set its flag accordingly.
+	(dump_append_queue): Use `ck_fwrite' instead of output_line.
+	(do_list): Flush the output stream at the end.
+	(closedown): The code ``if(separate_files) rewind_read_files();''
+	(read_pattern_space): ... has been moved here.
+	(process_files): Don't do the default `p' at the end, ...
+	(execute_program): ... as this function is now responsible for it;
+	add the code to the end of the function and to the command `q';
+	the commands `d', `D' and `Q' thus no longer have to forge an empty
+	line.
+	(execute_program): Commands `c' and `i' no longer call the
+	function output_line with chomped==FALSE; instead, they chomp
+	the text and call the function with chomped==TRUE.
+	(execute_program): Command `e' no longer uses output_line; it
+	calls ck_fwrite directly.  Commands `e', `L' and `=' flush
+	the output stream at the end.
+	* sed/compile.c (special_files): Use `struct output' instead of the
+	file name.
+	(get_openfile): ... special files are no longer copied to file_read
+	or file_write.
+	(fp_list): Move to sed.h (users adjusted) and rename as...
+	* sed/sed.h (struct output): ...this.  New flag missing_newline
+	associated to the output stream.
+	(struct sed_cmd, struct subst): Use `struct output *' instead of mere
+	`FILE *'; adjust compile.c and execute.c.
+	* testsuite/noeolw.sed, testsuite/noeolw.good, testsuite/noeolw.1good,
+	testsuite/noeolw.2good: New tests
+
+2003-07-15  Stepan Kasal  <kasal@ucw.cz>
+
+        * lib/utils.h, sed/sed.h: #include "basicdefs.h",
+        don't include it from various *.c files.
+        * sed/regex.c: Don't include regex.h as it's included via sed.h.
+
+2003-06-11  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/getline.c: Don't realloc with first param = NULL.
+
+2003-05-07  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/execute.c: Make treatment of ADDR_IS_NUM_MOD
+	simpler, and fix bugs in 0~5,+1
+	* sed/compile.c: Complain about addresses like 0
+	and 0,3 which are sources of misunderstandings.
+	Reported by Akim Demaille <akim@epita.fr>
+
+2003-03-25  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0.7 released
+
+	* sed/execute.c (append_replacement): Extract from
+	do_subst
+	(do_subst): Don't update count when a match was
+	skipped.
+	* testsuite/xbxcx3.good, testsuite/xbxcx3.sed, 
+	testsuite/xbxcx3.inp: Regression tests
+
+2003-03-23  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/execute.c (do_subst): Fix several bugs with
+	numbered matches
+	* testsuite/numsub2.good, testsuite/numsub2.inp,
+	testsuite/numsub2.sed, testsuite/numsub3.good,
+	testsuite/numsub3.inp, testsuite/numsub3.sed,
+	testsuite/numsub4.good, testsuite/numsub4.inp,
+	testsuite/numsub4.sed, testsuite/numsub5.good,
+	testsuite/numsub5.inp, testsuite/numsub5.sed:
+	regression tests for the bugs
+
+2003-03-15  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0.6 released
+
+	* lib/mkstemp.c: Include sys/file.h if available for the
+	benefit of Ultrix
+
+2003-03-14  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c: Replace flagT with bool
+	* sed/execute.c: Replace flagT with bool
+	* sed/fmt.c: Replace flagT with bool
+	* sed/sed.c: Replace flagT with bool
+	* sed/regex.c: Replace flagT with bool
+
+2003-03-13  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (compile_program): Understand parameter
+	of `v'.
+
+	* sed/sed.c (usage): Split help message into multiple
+	strings
+	(main): Don't understand -h and -V
+
+2003-03-12  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (match_slash, snarf_char_class):  More
+	multibyte character support
+	(brlen): New function
+	* testsuite/classes.good, testsuite/classes.inp,
+	testsuite/classes.sed: New files
+
+2003-03-10  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (match_slash): Strip the \ in front of
+	slashes (so that the matcher sees x/ for s/x\///).  Don't
+	match / and [ unless at the start of a character.
+
+2003-02-18  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/regex.c (compile_regex): // matches the last regular
+	expression even in POSIXLY_CORRECT mode.
+	* sed/compile.c (normalize_text): Treat multibyte character
+	sets correctly
+	(read_text): Don't swallow backslash sequences, run text
+	through normalize_text
+	(compile_program): Ditto for y command
+
+	* sed/compile.c (normalize_text): Add parameter that says
+	whether the text will be processed further to remove more
+	backslash escapes.  Callers adjusted
+	(match_slash): Remove same parameter from here.  Callers adjusted.
+
+2003-02-15  Paolo Bonzini  <bonzini@gnu.org>
+
+        * sed/sed.h: Fix prototype for match_regex, declare re_registers
+        if REG_PERL
+        * sed/execute.c (do_subst): Use re_registers
+        * sed/regex.c (copy_regs): New function
+        [REG_PERL]: Use re_registers
+        [!REG_PERL]: Avoid using internal entry points, support pre-glibc
+	2.3 regex for the sake of --without-included-regex.
+
+2003-01-04  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/sed.h: Move some stuff from here...
+	* sed/basicdefs.h: ...to here
+	* lib/utils.c (ck_fopen): Add FAIL parameter
+	* lib/utils.h: Adjust parameter
+	* sed/compile.c, sed/execute.c, sed/sed.c: Adjust callers
+
+	* sed/basicdefs.h: Add TRUE/FALSE
+	* sed/compile.c, sed/execute.c, sed/sed.c: Use them
+	* sed/fmt.c: Do not redefine them
+
+2003-01-02  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/sed.c: Bump copyright year
+
+2002-12-24  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/sed.c: Use bindtextdomain
+	* sed/basicdefs.h [__EMX__]: Define initialize_main
+	* lib/getline.c [__EMX__]: Strip trailing CR
+
+	* sed/regex.c: Don't use N_ on the lines that define
+	error messages, some compilers complain.
+
+2002-12-18  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0.5 released
+
+	* sed/compile.c: Don't use N_ on the lines that define
+	error messages, some compilers complain.
+
+2002-12-16  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c: Improvements to some error messages;
+	`a', `i', `l', `L', `r' accept two addresses except in
+	POSIXLY_CORRECT mode.
+
+2002-12-14  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/regex_internal.c: Fix problem on non-glibc
+	systems, from Jakub Jelinek
+	* lib/regex.c (RE_ENABLE_I18N): Conditionalize on
+	HAVE_MBRTOWC and HAVE_WCRTOMB.
+	* lib/getline.c: Fix compilation on non-glibc system
+	* lib/snprintf.c: Fix compilation on non-glibc system
+	* lib/basicdefs.h [P_]: Make more portable
+
+2002-12-12  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0.4 released
+
+2002-11-21  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0.3 released
+
+2002-11-19  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0.2 released
+
+2002-11-05  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0.1 released
+
+2002-10-23  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 4.0 released
+
+2002-10-28  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/utils.c: Don't fail for EBADF in fflush
+	* src/sed.c: the_program is now a global
+
+2002-10-19  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/sed.c: Print GNU sed in --version for GNU sed,
+	and super-sed for super-sed (thanks to Bruno Haible)
+
+2002-10-17  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 3.96 released
+
+2002-10-16  Isamu Hasegawa  <isamu@yamato.ibm.com>
+
+	* src/execute.c (execute_program): Multibyte 'y'
+	* src/compile.c (compile_program): Likewise
+	* src/sed.h: Likewise
+
+2002-10-08  Paolo Bonzini  <bonzini@gnu.org>
+
+	*** Version 3.95 released
+
+2002-07-15  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/sed.h: rfile --> fname, wfile --> fp
+	* src/compile.c (compile_command): Parse 'R' like 'w', use
+	separate lists for file read and file write
+	* src/compile.c (get_openfile): New name of get_writefile
+	* src/compile.c (rewind_read_files): New function
+	* src/sed.h: Declared here
+	* src/execute.c (closedown): And called here
+	* src/execute.c (append_queue): Added 'free' field
+	* src/execute.c (execute_program): Implement 'R'
+
+2002-06-09  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/execute.c (do_subst): Replaced flag was set on every
+	regexp match, while the first matches should not set it
+	for s///N.
+
+2002-06-08  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/compile.c (compile_file): Open the script in text mode
+	* lib/utils.c (utils_fp_name): Shorten the output
+	* lib/utils.c (ck_fread, ck_fwrite, ck_fflush): Clearerr
+	after printing an error.
+	* lib/utils.c (ck_fclose): Work on stdout as well if stream == NULL
+	and flush before closing to check for errors
+
+2002-05-30  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/compile.c (compile_program): Implement W
+	* src/execute.c (execute_program): Likewise
+
+2002-04-23  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/sed.c (usage, main): Parse -s
+	* src/sed.h (separate_files): New variable
+	* src/execute.c (separate_files): New variable
+	* src/execute.c (reset_addresses): New function to make range
+	addresses work separately on each file when using in-place
+	editing
+	* src/execute.c (execute_program): The `n' and `N' use test_eof
+	so that the script restarts at end of file, not at end of input
+	* src/execute.c (test_dollar_EOF): Make $ work separately
+	on each file when using -s; renamed to test_eof
+	
+2002-02-28  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/sed.h (struct sed_cmd): exit_status -> int_arg
+	* src/compile.c: Likewise
+	* src/execute.c: Likewise
+
+	* src/compile.c (compile_command): Parse `l' like
+	`q' and `Q'; default for int_arg is -1
+	* src/execute.c (do_list): New argument, used instead
+	of lcmd_out_line_len
+	(execute_program): Interpret int_arg for the `l' command;
+	return 0 for `q' and `Q' if int_arg is -1
+
+	* src/fmt.c: New file, looted from GNU textutils
+	* src/compile.c: Parse `L'
+	* src/execute.c: Execute `L'
+	
+2002-02-14  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/execute.c (str_append_modified): Fixed a stupid
+	bug (stop condition was *start == *end, meant to be
+	start == end)
+
+2002-02-05  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/utils.c: Added directory parameter to
+	temp_file_template
+	* lib/utils.h: Adjusted
+	* src/execute.c: Adjusted
+
+2002-01-29  Paolo Bonzini  <bonzini@gnu.org>
+
+	* src/compile.c (mark_subst_opts): Signal an error if
+	there are multiple g or p options
+	* src/compile.c (compile_program): Raise appropriate
+	error if second string in y command is longer than
+	first (used to be "excess junk after command")
+
+2001-12-31  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/getline.c: Strip the terminating \r under Windows
+	or MS-DOS.
+	
+	* testsuite/xemacs.sed, testsuite/xemacs.inp,
+	testsuite/xemacs.good: Submitted by John Fremlin
+	(john@fremlin.de)
+
+2001-12-27  Paolo Bonzini  <bonzini@gnu.org>
+	
+	* sed/execute.c (do_subst): Flags in optimized s/^xx/
+	commands were discarded (see the change below)
+
+2001-12-19  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/execute.c (resize_line): Limit inactive space to two
+	thirds of a buffer
+	* sed/execute.c (line_init): Initialize buf->active
+	* sed/execute.c (str_append, str_append_modified, line_copy,
+	do_list, do_subst, execute_program, process_files): Operate
+	on active space
+
+	* sed/execute.c (do_subst): Optimize s/^xx// by making a part
+	of the buffer inactive and s/xx$// by truncating it.
+	* sed/execute.c (execute_program): Optimize D by making a part
+	of the buffer inactive
+	
+	* testsuite/uniq.sed, testsuite/uniq.inp, testsuite/uniq.good:
+	added to test P and D commands.
+	* testsuite/fasts.sed, testsuite/fasts.inp, testsuite/fasts.good:
+	added to test the new optimization done on the `s' command.
+
+2001-12-17  Paolo Bonzini  <bonzini@gnu.org>
+
+	* testsuite/dc.inp: Also compute Easter of 2002 :-)
+
+	* sed/execute.c [!HAVE_FCHMOD]: Don't chmod the output file
+	if working in-place
+
+2001-11-12  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/sed.h (struct sed_cmd): a1 is a pointer too
+	* sed/compile.c: Likewise
+	* sed/execute.c: Likewise
+
+	* sed/compile.c: Use obstacks
+	* sed/execute.c: Likewise
+
+2001-11-09  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (mark_subst_opts): Parse option `e',
+	preserve two occurrences of the `e' and `p' options.
+	* sed/execute.c (do_subst) [HAVE_POPEN]: Interpret option
+	`e' (evaluate, like Perl's but uses Bourne shell).
+	* sed/sed.h (struct subst): Add an `eval' flag.
+
+	* sed/compile.c (compile_program): Compile command `e'
+	like `c'.
+	* sed/execute.c (execute_program): Execute command `e'.
+
+2001-09-25  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (get_writefile) [!POSIXLY_CORRECT]:
+	support /dev/stdout
+	* sed/execute.c (open_next_file, closedown): Support
+	in-place editing
+	* sed/execute.c (backup_file_name): New function to
+	support in-place editing
+	* sed/main.c (usage, main): Parse -i.
+	* sed/utils.c: Moved to lib directory
+	
+	* lib/utils.c (temp_file_template): New function.
+	* sed/utils.h: Declared temp_file_template.
+
+2001-09-05  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/execute.c (do_subst): `baaac', if passed through
+	s/a*/x/g, gave `xbxxcx' rather than `xbxcx' (because an
+	empty string matched before the `c'.  Fixed.
+
+	* sed/execute.c: Removed mmap support, I/O is done using
+	getline (slower but more bug-proof).
+	* sed/utils.c: Likewise.
+	* lib/getline.c: New file
+
+2001-03-22  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (normalize_text) [POSIXLY_CORRECT]: Enable
+	escapes in modes other than BRE.
+
+2001-03-21  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (normalize_text): Support \XXX in Perl mode,
+	\oXXX in non-Perl mode.
+
+2001-03-18  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (compile_program): Fixed missing break when
+	compiling 'q' and 'Q'.
+
+	* sed/compile.c (check_final_program): Removed now spurious
+	call to compile_regex
+	* sed/regex.c (compile_regex): Don't track the last compiled
+	regex
+	* sed/regex.c (execute_regex): Track here the last compiled
+	regex
+	
+2001-03-02  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (setup_replacement): Support \[lLuUE] like
+	Perl and vi.
+	* sed/compile.c (new_replacement): Accept new parameter
+	to support \[lLUuE].
+	* sed/sed.h (enum replacement_types): New declaration
+	* sed/execute.c (do_subst): Use new function str_append_modified
+	to apply the changes required via \[lLUuE].
+	* sed/execute.c (str_append_modified): New function
+
+2001-03-02  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (setup_replacement): Count the number of backreferences
+	that the RHS needs
+	* sed/regex.c (compile_regex): Check if there is a sufficient number
+	of backreferences (new argument needed_sub replaces nosub)
+	* sed/compile.c (compile_address, compile_program,
+	check_final_program): Callers adjusted
+
+2001-02-08  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (compile_program): Added `Q' (quit without output)
+	* sed/execute.c (execute_program): Ditto
+
+	* sed/compile.c (compile_program): Fill in exit_status for `q' and `Q'
+	* sed/execute.c (execute_program): Return -1 for `go on', 0..255
+	to set the exit status
+	* sed/execute.c (process_files): Interpret new convention for
+	execute_program, return sed's exit code
+	* sed/sed.c (main): Return process_files's exit code
+	* sed/sed.h (struct sed_cmd): Declare exit_status
+	
+2001-01-07  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c (compile_program): Added `T' (branch if failed)
+	* sed/execute.c (shrink_program, execute_program): Ditto
+
+2001-01-04  Paolo Bonzini  <bonzini@gnu.org>
+
+	* testsuite/Makefile.am: Use automake's implementation
+	of `make check'.  Removed the test targets
+	* testsuite/Makefile.tests: Moved the test targets here
+	(new file).
+	* testsuite/runtest: New file
+
+	* testsuite/Makefile.tests: `khadafy' test uses EREs.
+
+	* testsuite/spencer.inp: Removed the ^* test
+
+	* testsuite/spencer.sh: Don't rely on awk; more comments too
+	
+2001-01-03  Paolo Bonzini  <bonzini@gnu.org>
+   
+	* sed/compile.c(snarf_char_class) [REG_PERL]: Don't parse
+	`\n' specially
+	* sed/compile.c(match_slash) [REG_PERL]: Ditto
+
+	* sed/compile.c(read_text) [REG_PERL]: Support [xX] modifiers
+	* sed/compile.c(mark_subst_opts) [REG_PERL]: Ditto
+
+2000-12-21  Paolo Bonzini  <bonzini@gnu.org>
+
+	* lib/snprintf.c [BOOTSTRAP]: Don't include stdio.h
+	* lib/strerror.c [BOOTSTRAP]: Don't include stdio.h
+	* sed/execute.c [!HAVE_ISATTY]: Don't buffer stdin
+
+2000-12-11  Paolo Bonzini  <bonzini@gnu.org>
+
+	* sed/compile.c(mark_subst_opts): Support [mMsS] flags
+	* sed/compile.c(read_text): Support [MS] flags for 
+	addresses
+	* sed/regex.c(compile_regex): Support arbitrary flags for
+	regncomp.
+
+	* sed/regex.c(compile_regex) [REG_PERL]: Don't call
+	normalize_text.
+
+2000-12-08  Paolo Bonzini  <bonzini@gnu.org>
+
+	* basicdefs.h: Moved here from the `sed' subdirectory.
+	
+	* configure.in: Removed crap to pick a regex engine.
+	Added snprintf to the AC_REPLACE_FUNCS call.
+
+	* lib/snprintf.c: New file.
+	
+	* sed/regex.c(compile_regex): Use regncomp
+	* sed/regex.c(match_regex): Use regexec2
+
+	* sed/compile.c(compile_program): Implemented the `v' command.
+
+	* sed/sed.c(main): Implemented the `r' and `R' options
+
+	* sed/sed.h: Replaced use_extended_syntax_t with
+	extended_regexp_flags to support Perl regular expressions.
+
+	* sed/execute.c(open_next_file): Don't mmap stdin (because
+	we cannot seek into it, so a redirected stdin's contents
+	would not be "eaten" by sed)
+
+Mon Aug 30 23:40:08 PDT 1999  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.02.80 released
+	
+	* sed/execute.c(do_subst): lib/regex.c(re_search_2) seems to
+	want one extra backreference register; humor it.
+
+	* sed/regex.c(compile_regex): work around some odd assumptions
+	that lib/regex.c(re_compile_pattern) makes about our desired
+	RE syntax.
+
+	* configure.in: tweaked version to 3.02.80; added new entries
+	to the ALL_LINGUAS definition.
+
+	* doc/sed.1, doc/sed.texi, BUGS: explicitly request the output
+	of sed --version in bug-reporting instructions.
+
+	* doc/sed.texi: the old "informal seders list" is dead; document
+	the new sed-users mailing list instead (under Other Resources).
+
+
+Thu Aug 19 23:27:54 PDT 1999  Ken Pizzini <ken@gnu.org>
+	
+	* sed/sed.h: Add explicit #include of "regex-sed.h" (rather
+	 than relying on parent file doing so); change the "cmd_regex"
+	 member of sed_cmd: make it a pointer (instead of a struct),
+	 and change its name to cmd_subst; add prototypes for newly
+	 exported functions bad_prog(), normalize_text(), compile_regex(),
+	 match_regex(), and release_regex(); drop rx_testing variable.
+
+	* sed/compile.c: move the compile_regex() function to regex.c;
+	export bad_prog() and normalize_text() functions; eliminate the
+	rx_testing debris; rename the NOLEAKS symbol to more descriptive
+	DEBUG_LEAKS; make cmd_regex to cmd_subst fixes (see above);
+	make use of newly abstracted release_regex() function.
+
+	* sed/execute.c: abstract out the regex matching to
+	regex.c:match_regex(); NOLEAKS to DEBUG_LEAKS change;
+	cmd_regex to cmd_subst structure member name change.
+
+	* sed/execute.c(do_subst): use re_registers/regoff_t instead of
+	regmatch_t to hold the backreference registers, make "offset"
+	always be relative to the beginning of the string (rather than
+	a delta from "start"), defer some matching bookkeeping (e.g.,
+	not_bol_p) to match_regex().
+
+	* sed/sed.c(main): loose rx_testing variable; NOLEAKS
+	(aka DEBUG_LEAKS) code attempting to release
+	_nl_current_default_domain is problematic, so omit it.
+
+	* sed/regex.c: new file --- abstracts out the interface to the
+	regex engine so that less conditional code is required in
+	compile.c and execute.c, and so as to make a change of engine
+	easier; implements compile_regex() (which looks an awful lot
+	like the one that used to live in compile.c), match_regex(),
+	and (if DEBUG_LEAKS is set) release_regex().
+
+Sun Apr 18 04:40:46 PDT 1999  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.c(main): conditionalize calls to setlocale() and
+	textdomain() to only occur if their support is needed/wanted.
+
+Sun Apr 18 03:01:46 PDT 1999  Ken Pizzini <ken@gnu.org>
+
+	* bootstrap.sh: "foo || bar && baz" was not grouping like I
+	expected ("foo || (bar && baz)") under at least one shell,
+	so change the test for a pre-existing config.h file to an
+	if statement.
+
+	* bootstrap.sh: added -DUSE_REGEX_GNU_H option to the
+	compiler invocation, to ensure that we get a usable
+	regex library included.
+
+Sun Apr 18 02:59:42 PDT 1999  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.h, sed/utils.c: conditionalized inclusion of <libintl.h>
+	to occur only if ENABLE_NLS is defined.
+
+Sun Apr 18 01:48:45 PDT 1999  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(xofa,normalize_text,convert_number): change
+	name of xofa() function to convert_number(); change semantics
+	to do all of the work of the text->number conversion.
+
+	* sed/compile.c(normalize_text): add new \dDDD decimal
+	and \oOOO octal escapes.
+
+Sun Mar 28 21:05:07 PST 1999  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.c(main): if NOLEAKS is set, free up a word that
+	the call to textdomain() allocated.
+
+	* sed/execute.c(read_file_line): plug up (minor) memory leak:
+	if buffer.alloc==0 we may have malloc()'d 1 byte anyway,
+	so be sure to FREE(buffer.text) before calling line_init();
+
+Fri Mar 26 16:52:10 PST 1999  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(match_slash): somewhere between 3.02
+	and 3.02a we lost the ability to use a newline as
+	the s/// delimiter; restore this ability.
+
+	* sed/compile.c(compile_regex): forget about trying
+	to cache the compiled form of the last RE --- it
+	causes more problems than its worth.  We now only
+	cache the source form.
+
+	* testsuite/help.good: update to reflect output containing
+	new options.
+
+Sun Dec  6 00:51:23 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/utils.c(ck_fwrite): fix i18n bug of using a printf
+	fragment of "item%s" to handle plural text.
+
+Mon Nov 23 11:03:40 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* doc/sed.1, doc/sed.texi: ran ispell over these
+	files to catch the more obvious typos...
+
+Sun Nov  1 00:09:07 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/execute.c(do_list): make a `lcmd_out_line_len'
+	(--line-length) of zero mean "infinite length",
+	i.e., "never wrap".
+
+Sat Oct 31 23:06:50 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* execute.c(match_an_address_p,process_files),
+	compile.c(compile_program): back out the "zero-address"
+	changes of 1998-09-27.  It was a neat idea, but there are
+	too many dark corners which don't work well.  The
+	special code for handling line ranges starting at
+	address zero (from 1998-08-31) are still there though:
+	this seems to work fine with no surprises.
+
+Sat Oct 31 22:18:59 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.c, sed/sed.h, sed/execute.c: added new
+	`lcmd_out_line_len' variable.  (Idea suggested by
+	Carlos J. G. Duarte <l38076@alfa.ist.utl.pt>.)
+	Also added ATOI macro (which uses strtoul() if available,
+	with fall-back to atoi()).
+	* sed/sed.c(main): attempt to use COLS environment variable
+	to set a reasonable `lcmd_out_line_len'; added -l/--line-length
+	command-line options to set the new `lcmd_out_line_len' flag.
+	* sed/sed.c(usage): documented new -l/--line-length options.
+	* sed/execute.c(do_list): use `lcmd_out_line_len' variable
+	instead of `LCMD_OUT_LINE_LEN'.
+	* sed/execute.c: deleted now obsolete LCMD_OUT_LINE_LEN define.
+	* configure.in: added strtoul to the AC_CHECK_FUNCS call.
+
+Sat Oct 31 21:37:17 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.c, sed/sed.h, sed/execute.c: added new `force_unbuffered'
+	flag.  (Idea suggested by Frank Strauss <strauss@escape.de>.)
+	* sed/sed.c(main): added -u/--unbuffered command-line options
+	to set the new `force_unbuffered' flag.
+	* sed/sed.c(usage): documented new -u/--unbuffered options.
+	* sed/execute.c: changed the name of the `is_tty' flag in struct
+	input to a more generic `no_buffering'; also removed HAVE_ISATTY
+	conditional on this member.
+	* sed/execute.c(slow_getline): removed HAVE_ISATTY conditonal
+	compilation of this function.
+	* sed/execute.c(output_line): if force_unbuffered is set,
+	then force a fflush() even if writing to stdout.
+	* sed/execute.c(open_next_file): added handling of the
+	new `force_unbuffered' flag so that slow_getline()
+	will always be used for input.
+	* sed/execute.c(read_file_line): changed the (conditionally
+	compiled) test of `input->is_tty' to (unconditionally)
+	use the new spelling `input->no_buffering'.
+
+Thu Oct 15 12:08:09 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* configure.in: deleted AC_ARG_PROGRAM call; this is already
+	done for us by AM_INIT_AUTOMAKE, and we were winding up
+	with a doubled-transform.
+
+Sun Sep 27 01:42:42 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* compile.c(compile_program): remove special-case code for matching
+	address range with a `0' beginning.
+
+	* compile.c(compile_address): change default addr_number to
+	be a pragmatically impossible countT value, instead of zero.
+
+	* execute.c: spell macro REGNEXEC() unconditionally instead of
+	playing with conditional definition of regnexec() macro.
+
+	* execute.c(match_an_address_p): added third argument (and changed
+	callers in match_address_p).  Added special code to ignore
+	non-numeric matches when processing "line zero".
+
+	* execute.c(process_files): added a "line zero" pass through the
+	commands script.
+
+Sun Sep 27 00:20:53 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* compile.c(xofa,normalize_text): new functions.
+	* compile.c(compile_regex): cache last_compiled_re (with its
+	associated flags); add POSIXLY_CORRECT behavior for empty RE.
+	Make use of the new normalize_text() function.
+	* compile.c(setup_replacement): Make use of the new normalize_text()
+	function.
+
+Sat Sep 26 22:59:13 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* lib/regex-gnu.h: added missing prototype for regncomp().
+
+Mon Sep 14 20:47:23 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.c(main): use EXIT_SUCCESS instead of 0, in case
+	we are built on a system (such as VMS) where EXIT_SUCCESS
+	is distinct from 0.
+
+Wed Sep  9 22:17:28 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/Makefile.am: added -I../intl the INCLUDES line; if we are
+	building in a directory outside the source tree and the system
+	we are building on does not have a <libintl.h> header, then
+	the build was failing, because libintl.h is a build-time
+	constructed source file.
+
+	* configure.in: tweaked version to be 3.02b.
+
+Wed Sep  9 19:28:14 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.02a released
+	
+	* sed/compile.c(mark_subst_opts,read_label,compile_program):
+	wherever we accept a ; as a command terminator, also allow a } or
+	a # to appear.  (This allows for less cluttered-looking scripts,
+	such as: sed '/foo/{x;G}' (instead of: sed '/foo/{x;G;}').)
+
+Wed Sep  9 18:17:07 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(compile_regex): use regncomp() instead
+	of regcomp(), so that a script with NULs in its REs
+	will work in the expected manner.
+
+	* sed/compile.c(ADDNUL,REGNCOMP): added support macros
+	for above.
+
+	* lib/regex.c(regncomp,regcomp): added regncomp() and
+	made regcomp() a simple wrapper function.
+
+Mon Aug 31 21:48:30 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.c(compile_program): if the first address of
+	a range is the number 0 (or a 0~N sequence), start
+	out in the "a1_matched" state.  This allows one
+	to match an initial chunk of a file without undue
+	convolutions for handling the case where the match
+	for the end of the sequence happens to be the first
+	line.
+
+Sun Aug 16 03:34:25 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(snarf_char_class,match_slash): simplify
+	handling of "premature newline" error. Also, get the
+	line number right in the error message if we encounter
+	a "premature newline" during char-class snarfing.
+
+Sun Aug 16 02:59:20 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c: added N_() markers and corresponding gettext()
+	(er, _()) calls.
+
+	* Merged in i18n contribution from Erick Branderhorst
+	<Erick.Branderhorst@asml.nl>.  His ChangeLog entry
+	for the changes I've incorporated so far:
+
+1998-07-24  Erick Branderhorst  <Erick.Branderhorst@asml.nl>
+	* configure.in (ALL_LINGUAS, AM_GNU_GETTEXT): nl
+	* sed/{sed.h,utils.c}: #include <libintl.h> #define _(String)
+	gettext (String)
+	* sed/sed.c: #include <locale.h>
+	* po/POTFILES.in: sed/{compile,execute,sed,utils}.c
+	* run gettextize -f
+	* acconfig.h: #undef LOCALEDIR ENABLE_NLS HAVE_CATGETS
+	HAVE_GETTEXT HAVE_LC_MESSAGES HAVE_STPCPY
+
+Fri Aug 14 13:52:57 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* Merged code from 3.02 with a branched development
+	tree from late May; the following (out-of-order)
+	changelog entry is from the branched tree.
+
+Sat May 30 12:23:16 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c, sed/execute.c: added (conditional on NOLEAKS macro)
+	code to free all dynamically allocated memory.
+
+	* sed/sed.c, sed/compile.c, sed/execute.c: much shuffling
+	of code --- ordered functions such that no forward
+	declarations are necessary, and placed all static prototypes
+	immediately before the actual function definition.
+	This accomplished two things: first, I find the new ordering
+	a more natural way to read the code than the previous
+	ordering, and second, the new ordering give the compiler
+	a better opportunity to discover inlining possibilities.
+	(The odd "prototype declaration+old-style definition"
+	style is used because I feel it is the least ugly way
+	of supporting K&R1 C while still getting the benefit of
+	prototypes when they are available.)
+
+	* sed/basicdefs.h: added MEMCPY() macro to hide the VCAST()s
+	that ought to be used with memcpy().
+
+	* sed/execute.c: Change calls to memcpy() to go through the
+	new MEMCPY() macro.  Various prototypes: elide variable name
+	if it does not add any human-useful documentary information
+	to the bare type.
+
+	* sed/sed.c(main): Updated calls to compile_string() to add third
+	(length) argument.  Changed call to obsolete close_all_files()
+	to a call to the new finish_program().
+
+	* sed/sed.c(map_file): Attempt to clean-up how "size" gets
+	cast and tested; remove spurious S_ISREG test (just let
+	mmap() fail if it doesn't support the underlying file type).
+
+	* sed/sed.c: Deleted old RX library stub declarations.
+
+	* sed/sed.c(map_file,unmap_file): added VCAST()s to the
+	mmap()/munmap() calls.
+
+	* sed/utils.c(ck_fclose): added support for ANSI C
+	functionality where passing a NULL argument means
+	to fclose() _all_ open streams.  (Well, almost.
+	Only closes streams which were previously ck_fopen()ed,
+	as I don't care to figure out how to autoconf-detect
+	whether fclose(NULL) is properly supported on a given
+	platform.)
+
+	* sed/sed.h: Renamed `struct text_buf' member `text_len'
+	to `text_length'.  Abstracted out `enum addr_types'
+	from `struct addr'; added new enum types num2,step,step_mod;
+	renamed mod to num_mod.  De-unionized the regex,number,
+	{modulo-offset/step} components of `struct addr', in
+	anticipation of new features.  Changed type of `a2' member
+	of `struct sed_cmd': now a pointer to save space.
+	Abstracted out `struct replacement' from `struct subst'.
+	Cleaned up declaration of `x' union of `struct addr'.
+	Fixed prototype for compile_string().  Replaced prototype
+	for old close_all_files() with one for new finish_program().
+
+	* sed/sed.h, sed/compile.c, sed/execute.c: changed to
+	simplify the data structures used for branches and
+	command blocks: simplified `struct vector'; made
+	`struct label' local to compile.c; `struct sed_cmd'
+	was modified to support a simpler design for branches
+	and blocks.
+
+	* sed/execute.c: Conditionally added ADDNUL() macro so that
+	the function call overhead is only incurred if nul_append()
+	_must_ be called.  Made some commentary edits, including
+	typo fixes.
+	* sed/execute.c(resize_line): changed semantics of "len" argument
+	from "additional length" to "target length"; made
+	INITIAL_BUFFER_SIZE a minimum allocation length.
+	* sed/execute.c(str_append): adjusted to new resize_line()
+	semantics.
+	* sed/execute.c(line_copy): use FREE()+MALLOC() instead of
+	REALLOC() to avoid unnecessary copying of old text; add the
+	"try doubling first" allocation heuristic (just like
+	resize_line() does).
+	* sed/execute.c(line_exchange): new function.
+	* sed/execute.c(nul_append): make whole function (not just its
+	body) conditional on HAVE_REGNEXEC macro; adjust to new
+	resize_line() semantics.
+	* sed/execute.c(read_mem_line): use str_append() instead if
+	custom in-line code; compensate for new default of
+	"line.chomped = 0" in read_pattern_space() by setting
+	"line.chomped = 1" where appropriate.
+	* sed/execute.c(read_file_line): use different trigger to
+	determine that "buffer" is uninitialized, and do a full
+	initialization if required; use str_append() instead of custom
+	in-line code in two places; compensate for new default of
+	"line.chomped = 0" in read_pattern_space() by setting
+	"line.chomped = 1" where appropriate.
+	* sed/execute.c(output_line): don't bother calling ck_fwrite()
+	if length==0.
+	* sed/execute.c(release_append_queue): new function.
+	* sed/execute.c(dump_append_queue): use release_append_queue()
+	instead of in-line equivalent.
+	* sed/execute.c(read_pattern_space): conditionalize call to
+	dump_append_queue() for alleged performance reasons; changed
+	default "line.chomped" value to more common "1", and added an
+	assignment of "0" where this made a difference.
+	* sed/execute.c(match_an_address_p): deleted "is_addr2_p"
+	argument; reorder cases to match order in enum declaration; add
+	cases for new "addr_is_num2", "addr_is_step", and
+	"addr_is_step_mod" address types; alter nul_append() call to be
+	through ADDNUL() macro; fix to new struct member and enum
+	spellings in (formerly addr_is_mod); addr_is_num_mod case.
+	* sed/execute.c(match_address_p): remove oblsolete third argument
+	to calls to match_address_p(); alter references to sed_cmd
+	member a2 to reflect new pointer status; add new support for
+	a2->addr_type addr_is_step and addr_is_step_mod cases.
+	* sed/execute.c(do_subst): add NOLEAKS support logic; use
+	ADDNUL() wrapper to nul_append(); simplify replacement
+	expansion by using the new "struct replacement" data structure;
+	use line_exchange() function instead of custom in-line code.
+	* sed/execute.c(process_files): added NOLEAKS code.
+	* sed/execute.c(execute_program): updated implementations
+	of the `{', `}', `:', `b', and `t' commands; modified
+	`c' command gratuituosly; fixed potential memory
+	overrun in `D' command.  Simplified how nonstandard
+	`loop increments' work.  Use line_exchange() instead of
+	custom in-line code in 'x' case.
+	* sed/execute.c[EXPERIMENTAL_DASH_N_OPTIMIZATION conditional
+	code]: various modifications intended to keep this
+	code in sync with the new changes, but the code still
+	retains its previous bugs.
+
+	* sed/compile.c: use "exit(EXIT_FAILURE) instead of "exit(1)",
+	just in case we get compiled under VMS.
+	* sed/compile.c: Change type of prog_info.base to decrease needs
+	for casting; then elimiated the casts in question ;-).
+	* sed/compile.c: Added struct sed_label (moved from sed.h, then
+	modified).
+	* sed/compile.c: Removed "readit_p" flag from struct fp_list.
+	* sed/compile.c: Added module-global "blocks" variable.
+	* sed/compile.c: Extracted more error-message constant strings
+	to named variables.
+	* sed/compile.c(check_final_program): updated to
+	reflect new data structures and use new fucntions.
+	Added call to compile_regex() to release unneeded
+	memory.
+	* sed/compile.c: deleted obsolete new_vector() function;
+	abstracted new read_label() function; abstracted new
+	release_label() function; added new `blocks' module-static
+	variable.
+	* sed/compile.c(compile_program): updated implementations
+	of the `{', `}', `:', `b', and `t' commands; modified
+	initialization from NULL vector.
+	* sed/compile.c(compile_regex): added mechanism to
+	release memory consumed by the cached `last' RE.
+	* sed/compile.c(setup_jump,setup_label): updated
+	name (from setup_jump to setup_label) and prototype;
+	changed body to reflect data structure changes.
+	* sed/compile.c: Add OPEN_BRACE and CLOSE_BRACE macros for better
+	"vi" editing behavior.
+	* sed/compile.c(compile_filename,read_filename,get_writefile):
+	Replaced function compile_filename() with more orthogonal functions
+	read_filename(), get_writefile().
+	* sed/compile.c(compile_regex): Added ability to free the remembered
+	"last RE" in compile_regex (for benifit of "NOLEAKS" code).
+	* Made adjustments dictated by the change to struct sed_cmd which made
+	the a2 member a pointer-to-addr instead of an addr.
+	* sed/compile.c(setup_jump,read_label,setup_label,release_label):
+	Added functions read_label(), setup_label(), release_label(); deleted
+	function setup_jump().
+	* sed/compile.c(new_replacement,setup_replacement,release_replacement):
+	new functions.
+	* sed/compile.c: Adjusted to new spelling of text_buf member
+	("text_length" instead of "text_len").
+	* sed/compile.c(new_vector): deleted function.  (Due to new handling
+	of blocks, only one instance remained, and that one was just as
+	clear in-lined.)
+	* sed/compile.c(compile_string): Added third argument; it now
+	takes a counted string instead of a NUL-terminated string.
+	* sed/compile.c(compile_file): added variable "map_base" to
+	compensate for new type of prog_info.base.
+	* sed/compile.c(check_final_program): reflect new style of
+	handling blocks and struct sed_label.
+	* sed/compile.c(close_all_files,finish_program): replaced function
+	close_all_files() with more generic finish_program().
+	* sed/compile.c(read_text): added new feature: if first non-blank
+	character after the {a,i,c} command character is not "\", then
+	use the trailing text on that line as the (first) line of text.
+	Also added code conditional on NO_INPUT_INDENT to support the
+	"feature" of stripping leading blanks from each input line; I
+	do not read POSIX as permitting this behavior, nor do I think
+	it is a good idea, so it is disabled by default, but some have
+	argued that this blank-stripping is the "correct" behavior, so
+	I offer them the option of building their sed that way.
+	* sed/compile.c(compile_address): added xxx,+n and xxx,~n addressing;
+	simplified code.
+	* sed/compile.c(compile_program): added BAD_PLUS error detection;
+	adjusted to new cur_cmd->a2 pointer status; added addr_is_num2
+	detection; deleted pointless "a2->addr_number < a1.addr_number"
+	check (addr_is_num2 semantics handle this just fine); updated
+	code for '{', '}', ':', 'b', and 't' to reflect new design
+	of branch handling, including making use of new functions
+	related to the new design); added support for feature already
+	mentioned in read_text() where {a,i,c} commands are able to have
+	their text start on the same line as the command; changed some
+	error messages (hopefully for the better); localized variables
+	specific to individual commands (particularly 's' and 'y');
+	made use of new setup_replacement() function in 's' command.
+
+Mon Aug 10 19:58:49 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* doc/sed.texi, doc/sed.1: sedtut10.txt is apparently dead.
+	Deleted references to it and added a pointer to
+	http://seders.icheme.org/tutorials/.  (Pointed out by
+	Joerg Heitkoetter <joerg@de.uu.net>.)
+
+Sat Aug  8 18:11:57 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* djgpp/config.btm: per request by Michel de Ruiter
+	 <mdruiter@cs.vu.nl>, added "%1" to "%9" parameters.
+
+Mon Aug  3 11:44:55 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* doc/sed.texi: fix a couple of typos.  (Submitted by
+	Alan Modra <alan@spri.levels.unisa.edu.au>.)
+
+Sat Aug 01 17:49:06 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.02 released
+	
+	* configure.in: Because of code change in 3.01a, bump the
+	minor revision number for the release (now 3.02).
+
+Sun Jul 26 16:07:55 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01a released
+	
+	* sed/compile.c(snarf_char_class):  the POSIX char-class
+	recognition loop forgot to update its concept of "prev"
+	as the loop progressed.
+
+	* testsuite/Makefile.am: The dependency of version.good
+	on [testsuite/]Makefile introduced in the previous
+	release was botched -- it referred to "Makefile"
+	as "$(srcdir)/Makefile, which of course doesn't work
+	if you aren't building in the source tree.
+
+	* djgpp/Makefile.am: add forgotten "config.btm" EXTRA_DIST
+	member.
+
+	* configure.in: update version.
+
+Tue Jul 21 06:04:42 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01 released
+	
+	* configure.in: mark as release version!
+
+	* Makefile.am: add BUGS and THANKS to the EXTRA_DIST target.
+
+	* testsuite/Makefile.am: add dependency of version.good
+	on [testsuite/]Makefile.
+
+Mon Jul 20 12:38:10 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* djgpp/config.btm: New file to support the 4DOS alternative
+	to command.com.  (Sumitted by Eli Zaretskii on behalf of
+	an anonymous 4DOS user.)
+
+Fri Jul 17 00:36:34 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta18 released
+	
+	* djgpp/config.sed: my "tweak" in beta17 was too
+	hastily considered.  Back it out.
+
+	* configure.in: update to beta18.
+
+Wed Jul 15 01:02:15 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta17 released
+	
+        * djgpp/config.sed: tweak/simplify s,,, commands at end.
+
+	* configure.in: update to beta17.
+
+1998-07-14  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* djgpp/config.sed: Edit all the occurences of = in the context of
+	--option=value, including in the help messages, into
+	--option:value, but leave DOS-style d:/foo/bar file names intact.
+
+	* djgpp/config.bat: Use --srcdir:foo instead of --srcdir=foo.
+
+	* testsuite/Makefile.am (help, version): Remove temporary files
+	explicitly, don't use shell wildcards, so it works under DOS 8+3
+	limits.
+
+Thu Jul  9 13:06:00 PDT 1998 16:51:43 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta16 released
+	
+	* djgpp/config.sed: tweak the configure script to use :
+	instead of = for --with-foo=bar option parsing, to
+	work around problems with how command.com handles =s.
+
+Wed Jul  8 16:51:43 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* djgpp/config.bat: correct inappropriate behavior that I
+	introduced in the beta13 changes (if first argument is
+	a directory, it needs to be handled as the --srcdir).
+
+	* testsuite/version.gin, testsuite/version.good, testsuite/Makefile.am:
+	Add target to automake to automatically update version.good
+	from (new file) version.gin, instead of hand-editing the version
+	number each release.
+
+	* testsuite/Makefile.am: miscellaneous gratuitious tweakage --
+	mainly adding $(RM) commands just because I didn't like
+	leaving the tmp* files from successful runs laying about.
+	Also some editorial comments.
+
+	* configure.in: update to beta16.  Added and commented out
+	experiment with AC_OUTPUT() for testsuite/version.good.
+	Added code to properly handle bare (without =xxx)
+	"--with-regex" option.
+
+Sun Jul  5 21:02:16 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta15 released
+	
+	* sed/utils.c(ck_fflush), sed/utils.h, sed/execute.c(output_line):
+	add and use new ck_fflush() function.
+
+Sun Jul  5 15:23:47 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(bad_prog): add more detail to error
+	messages about -e strings.
+
+Sun Jul  5 14:29:45 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(mark_subst_opts), sed/execute.c(do_subst):
+	Define better semantics for interaction of the `g' flag
+	with a numeric flag to the s/// command.  It used to
+	be that the `g' command siezed control; now the first
+	(number-1) matches are skipped and then `g' gets control
+	after that.  (It is not clear whether this is a feature
+	sneaking in during late beta, or a bug fix; the changes
+	involved were trivial, so I decided to treat it as a bug
+	fix.)
+
+	* configure.in, testsuite/version.good: update to beta15.
+
+Sat Jul  4 09:54:45 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta14 released
+	
+	* sed/basicdefs.h, sed/compile.c, sed/execute.c:
+	per report by "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu>,
+	copied the ISXXX macros from lib/regex.c so that
+	silly machines which require isascii() to be true
+	before the other isXXX() macros are valid will
+	still work.
+
+	* configure.in, testsuite/version.good: update to beta14.
+
+Thu Jul  2 23:46:13 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta13 released
+	
+	* configure.in, acconfig.h: set USE_REGEX_GNU_H symbol if we
+	are going to be using lib/regex.c.
+
+	* lib/Makefile.am, lib/regex.h, lib/regex-gnu.h, lib/regex.c:
+	rename lib/regex.h to lib/regex-gnu.h, so that those who
+	choose to use a different regex implementation will not
+	pick-up lib/regex.h when doing "#include <regex.h>".
+
+	* sed/regex-sed.h, sed/Makefile.am, sed/compile.c, sed/execute.c,
+	sed/sed.c: create sed/regex-sed.h which acts as a switch
+	to choose either lib/regex.h or the user-supplied <regex.h>,
+	depending on the value passed to configure's --with-regex=
+	option.
+
+Thu Jul  2 17:22:31 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* configure.in: if an alternative --with-regex= is given,
+	do an AC_CHECK_FUNCS(regnexec regexec) to ensure that
+	at least one of these functions is available.  Also,
+	parallel changes for the default case.
+
+	* sed/execute.c, acconfig.h: retire use of the WITH_REGNEXEC
+	test macro in favor of HAVE_REGNEXEC test macro created
+	by above change.
+
+	* djgpp/config.bat: Play games to handle "install-sh",
+	DOS filename restrictions, GNU makefile default rules,
+	and getting a correct run of "configure" (contributed
+	by Eli Zaretskii <eliz@is.elta.co.il>).
+
+	* djgpp/Makefile.am, testsuite/Makefile.am, testsuite/Makefile.in,
+	Makefile.am, configure.in: Various automake targets
+	(such as distcheck) failed with old configuration.
+	The simplest solution was to just add these .am
+	files.  (The testsuite/Makefile.in was just renamed to
+	testsuite/Makefile.am, then various redundant defines and
+	targets were deleted.)  (Reported by Erick Branderhorst
+	<Erick.Branderhorst@asml.nl>.)
+
+	* testsuite/dc.good, testsuite/dc.inp: per suggestion from
+	Greg Ubben <gsu@romulus.ncsc.mil>, use base 16 output to
+	exercise even more of the dc.sed script.
+
+	* configure.in, testsuite/version.good: update to beta13.
+
+Sun Jun 28 16:21:02 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta12 released
+	
+	* doc/sed.texi: Avoid mixing @code and @samp markups together:
+	they look ugly in Info.  Use @url and @email instead of @example.
+	Add indexes.  (Basis of changes contributed by Eli Zaretskii.)
+
+	* djgpp/*, Makefile.am: add support for the DJGPP compiler,
+	contributed by Eli Zaretskii <eliz@is.elta.co.il>.
+
+	* dc.sed, testsuite/Makefile.in, testsuite/dc.inp, testsuite/dc.good:
+	added this remarkable script, written and contributed
+	by Greg Ubben <gsu@romulus.ncsc.mil>, both as a work of
+	art for general admiration, and also for use in regression
+	testing.
+
+	* configure.in, lib/Makefile.am: add --with-regex=regexlib
+	option, which overrides the use of lib/regex.c.
+
+	* configure.in, testsuite/version.good: update to beta12.
+
+Fri Jun 12 16:41:48 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta11 released
+	
+	* sed/compile.c: add module-static variables first_script
+	(for #n change below) and pending_text (for a/c/i change
+	below).
+
+	* sed/compile.c(compile_file), sed/compile.c(compile_program):
+	Instead of having #n trigger the -n option in *any file*,
+	have #n trigger the -n option only if they are the first
+	two bytes of the first script or script-file.
+
+	* sed/compile.c(compile_string), sed/compile.c(compile_file):
+	clear the first_script variable at end of these functions.
+
+	* sed/sed.h: tease out the struct text_buf declaration from
+	struct sed_cmd, so that a pointer to such can be passed
+	to new sed/compile.c(read_text) function.
+
+	* sed/compile.c(compile_program), sed/compile.c(read_text):
+	Tease out handling of text to a/c/i commands to new
+	read_text() function.  Handle (via aid of pending_text
+	variable) texts which span more than one script/script-file
+	option.  In particular, restore the ability to have this
+	work:  sed -e '1i\' -e 'foo'
+
+	* sed/compile.c(check_final_program): close off any dangling
+	pending_text allocation.
+
+Thu Jun 11 11:17:46 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/execute.c(do_subst): fixed two bugs: s/ */X/g was failing
+	to match the final empty string after the end of the pattern
+	space; and /^foo$/s/o/x/3p was printing, despite the failure
+	to do a substition.
+
+Fri Jun  5 04:40:24 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* configure.in: change the AC_ARG_WITH(regnexec, ...)
+	to be the more appropriate AC_ARG_ENABLE(regnexec, ...).
+
+	* configure.in, testsuite/version.good: update to beta11.
+
+Fri Jun  5 00:54:25 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta10 released
+	
+	* sed/execute.c: forgot to P_() the prototype and
+	old-style the declaration for bootstrap_memchr()!
+
+Thu Jun  4 18:42:30 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(snarf_char_class): added code to
+	recognize \n or \<newline> sequence within a
+	char-class as the newline character.
+
+Tue Jun  2 11:56:02 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* configure.in: added check for <sys/types.h> and
+	a AC_ARG_WITH(regnexec,...) check, to simplify use
+	of other regex libraries which have regexec() but
+	not regnexec(), with the corresponding loss of
+	functionality (regexps will not work right against
+	input lines which contain NULs).
+
+	* sed/execute.c: add nul_append() function, a #define
+	for a regnexec() -> regexec() macro (conditional on
+	the lack of the WITH_REGNEXEC symbol), and a couple
+	of calls to nul_append() (in match_an_address_p()
+	and do_subst()) to permit the use of the POSIX standard
+	regexec() function call instead of the suggested
+	regnexec() call.
+
+	* sed/compile.c, sed/execute.c, sed/sed.c: check for
+	<sys/types.h> and include it (before "regex.h") if
+	available.  This makes it simpler to use the system's
+	regex library instead of the one in lib/regex.c, should
+	that be desired.
+
+Tue Jun  2 08:41:05 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/basicdefs.h: define VCAST macros to allow sed to
+	compile on systems which predate the definition
+	of "void *", and yet still get feedback about
+	stupid programming errors from systems which *do*
+	know about "void *"s.  Also define MALLOC, REALLOC,
+	MEMDUP, and FREE macros to keep under control the
+	degree of code ugliness which would otherwise be
+	introduced in making use of the VCAST macro.
+
+	* sed/compile.c, sed/execute.c, sed/sed.c, sed/utils.c:
+	pervasively use the new VCAST, MALLOC, REALLOC, MEMDUP,
+	and FREE macros wherever appropriate.
+
+	* sed/utils.c, sed/utils.h: correct type of first arguments
+	to ck_fread() and ck_fwrite() to be [const] VOID *.
+
+	* sed/basicdefs.h, sed/execute.c: protect against
+	the rumored systems which stupidly #define __STDC__ 0.
+
+	* testsuite/help.good, testsuite/Makefile.in: make
+	the ``help'' test insensitive to the spelling of
+	the executable's name.  Also, enhanced `make clean'
+	target.
+
+	* doc/sed.texi, doc/sed.1: correct documentation of `q'
+	command; fix typos.
+
+	* configure, testsuite/version.good: update to beta10.
+
+Sat May 30 17:28:00 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta9 released
+	
+	* Makefile.am: make testsuite a normal SUBDIR.
+
+	* configure.in: discontinue using AC_ISC_POSIX --
+	check for -lcposix library instead; added
+	testsuite/Makefile to AC_OUTPUT list.
+
+	* lib/memmove.c(memmove): fixed wrong sense used
+	for HAVE_BCOPY test.
+
+	* sed/execute.c: checked more specifically for a version
+	of gcc which supports __attribute__ (i.e., >= 2.7).
+
+	* testsuite/*: renamed files to fit 14 char limit.
+
+	* testsuite/Makefile, testsuite/Makefile.in: Makefile
+	renamed to Makefile.in and then modified so that
+	"make -j check" from top directory will work.
+
+	* testsuite/subwrite.sed, testsuite/writeout.sed: changed
+	file name of the "w" command to be consistent with the
+	new naming used in testsuite/Makefile.in.
+
+	* doc/sed.1, doc/sed.texi: fixed some typos, formatting
+	glitches, and poor wordings.
+
+Sat May 30 04:02:29 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* configure.in: specify that config.h is to be derived
+	from config_h.in in order to avoid the braindead
+	DOS filesystem limitations.
+
+Fri May 29 21:56:30 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(compile_address), doc/sed.texi: gave
+	a better definition to the meaning of N~0 address
+	forms -- N~M addresses now mean that lines match
+	when there exists a non-negative x such that
+	lineno == N+x*M.
+
+Fri May 29 12:07:38 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(compile_address),
+	sed/execute.c(match_an_address_p): update semantics of
+	N~M address form: now N is the first line which will
+	match and M is the step between succeeding matches.
+	If N<M this works out to the same as before, but the
+	new behavior for N>=M seems more useful.
+
+	* doc/sed.1, doc/sed.texi: update documentation of N~M
+	address form; added "Other Resources" node to sed.texi;
+	minor formatting changes to some items in sed.1 with
+	an eye to improving clarity.
+
+	* configure.in, testsuite/version.good: update to beta9.
+
+Sat May 23 20:04:31 HST 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta8 released
+	
+	* sed/compile.c(compile_regex): forgot to make last_re be
+	a *copy* of the buffered text in today's earlier fix.
+
+	* sed/execute.c(read_file_line): EOF check was wrong --
+	it forgot to allow for the possibility that we were
+	appending to the end of the ``line'' (instead of merely
+	reading a fresh line).
+
+Sat May 23 18:07:18 HST 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c(compile_regex): don't track compiled version
+	of regex -- the modifiers may change.  Track the regex
+	source instead.  (For "last regex" (aka //) notation.)
+
+	* configure.in, testsuite/version.good: update to beta8.
+
+Sat May 23 16:07:09 HST 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta7 released
+	
+	* sed/execute.c: #undef'd EXPERIMENTAL_DASH_N_OPTIMIZATION
+	because its code is buggy.
+
+Tue May 19 17:03:52 HST 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.c: label rx library code as such with #ifdefs
+	(instead of just #if 0).
+
+	* sed/compile.c(compile_program): make incremental
+	improvement to the "Unknown command" error message.
+
+Sat May 16 23:16:26 HST 1998  Ken Pizzini <ken@gnu.org>
+
+	* testsuite/Makefile: simplify: get rid of automatic run
+	against system's sed; don't time by default; allow for
+	alternative comparison command.
+
+	* configure.in, testsuite/version.good: update to beta7.
+
+Wed May 13 21:44:28 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta6 released
+	
+	* lib/Makefile.am: fix spelling of libsed_a_LIBADD in
+	libsed_a_DEPENDENCIES.
+
+	* configure.in, testsuite/version.good: update to beta6.
+
+Wed May 13 14:38:08 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta5 released
+	
+	* sed/execute.c(do_subst): added not_bol_p variable to track when
+	we have iterated past the beginning of the pattern.
+	[Thanks to Jim Meyering <meyering@ascend.com> for the bug report.]
+
+Wed May 13 13:54:04 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/execute.c(bootstrap_memchr): new function.  When
+	bootstrapping we don't know if we are on a 64-bit machine,
+	so lib/memchr.c breaks.  Supply this (slow) implementation
+	just to get us bootstrapped.
+
+	* bootstrap.sh: add a #define BOOTSTRAP symbol; add -I.
+	for emphasis for the compiles in sed/; be explicit
+	about what files we're bothering to compile.
+
+	* configure.in, testsuite/version.good: update version
+	to beta5.
+
+Wed May 13 06:39:06 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta4 released
+	
+	* rename writeout.good? to wrtout?.good and subwrite.good? to
+	subwrt?.good to comply with DOS 8+3 file name restrictions.
+	[Eli Zaretskii <eliz@is.elta.co.il> suggested this to
+	simplify DJGPP ports, and it was easy.]
+
+	* testsuite/Makefile: reflect above name changes.
+
+Wed May 12 21:09:32 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/sed.c(usage): fix non-portable omission of \n\ at end of
+	lines within long string.
+
+	* sed/sed.c(main): remove spurious argument to fprintf() in the
+	'V'ersion output.
+
+	* sed/execute.c(line_append): embed newline between the two
+	text fragments unconditionally.
+
+	* sed/execute.c(do_subst): change structure assignment to memcpy()
+	(for portability reasons).
+
+	* README.bootstrap: suggest using -w option.
+
+Tue May 12 10:02:37 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* configure.in: use AC_REPLACE_FUNCS where appropriate.
+
+	* lib/Makefile.am: updated to reflect AC_REPLACE_FUNCS change in
+	configure.in.
+
+	* lib/memchr.c lib/memcmp.c: revert to standard GNU versions.
+
+	* lib/alloca.c: added this missing file.
+
+	* testsuite/version.good: updated for new version identifier.
+
+Mon May 11 18:50:56 PDT 1998  Ken Pizzini <ken@gnu.org>
+	
+	*** Version 3.01-beta3 released
+	
+	* sed/Makefile.am: fix INCLUDES to work right with VPATH.
+	[Thanks to Jim Meyering <meyering@ascend.com> for the bug report.]
+
+	* sed/sed.c(usage): make --help output more user-friendly?
+
+	* sed/execute.c(execute_program): fix bug in 'x' command introduced
+	in the alleged portability fix of May 9.
+
+	* configure.in: update version to 3.01-beta3.
+
+	* testsuite/version.good, testsuite/help.good: freshen with
+	latest output.
+
+Sat May  9 22:35:45 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta2 released
+	
+	* sed/sed.c: add #include <sys/types.h> in HAVE_MMAP
+	block (needed on some machines).
+
+	* lib/memmove.c: #include <memory.h>, if HAVE_MEMORY_H.
+
+Sat May  9 21:29:00 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* configure.in: remove dangling references to rx library;
+	added HEADER and FUNC checks for items used by source in
+	lib/.
+
+	* lib/ansidecl.h, lib/memcopy.h, lib/pagecopy.h, lib/string.h
+	lib/memcpy.c, lib/memmove.c: deletes these files.  There
+	are still pieces of glibc missing to support these, and
+	it isn't worth the headache right now.
+
+	* lib/memmove.c: de novo, simpler version.  Uses bcopy()
+	if available, and slow-but-simple code if not.
+
+	* lib/Makefile.am: remove references to deleted files.
+	Added forgotten reference to memcpy.c.  Re-ordered
+	SOURCE entries to reflect dependencies for systems
+	which lack ranlib.
+
+	* sed/basicdefs.h: updated to reflect above changes to lib/,
+	and experience with non-STDC compilers.
+
+	* lib/regex.c: made regerror() function publicly visible.
+
+	* lib/strerror.c: use old-style function declaration.
+
+	* sed/compile.c, sed/execute.c, sed/sed.c, sed/utils.c,
+	sed/sed.h, sed/utils.h: ensure that private definitions of
+	some symbols do not cause problems when #include'ing system
+	headers (mainly by re-ordering the #include directives).
+	(This is particularly an issue for bootstrap.sh runs.)
+
+	* sed/execute.c (execute_program): use memcpy() instead of
+	structure assingment ('x' command), for portablility to
+	old compilers.
+
+	* sed/execute.c (slow_getline): use old-style function
+	declaration, with a P_ prototype.
+
+	* sed/sed.c: change the type of the fallback MAP_FAILED
+	definition to work on archaic systems.  (Modern systems
+	should be defining it themselves, so the change from
+	void * shouldn't be a problem.)
+
+	* bootstrap.sh, README.bootstrap: actual testing of bootstrap
+	code revealed that I was too optimistic.  Redesigned and
+	replaced implementation.
+
+	* testsuite/Makefile: ignore errors from reference-implementation
+	seds that aren't up to snuff.
+
+	* testsuite/help.good, testsuite/version.good: update to
+	current version's output.
+
+Fri May  8 15:08:28 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	*** Version 3.01-beta1 released
+	
+	* sed/sed.c (main, usage): once again tweak the --help and
+	--version output to bettery comply with GNU coding standards.
+
+	* testsuite/help.good, testsuite/version.good: update to
+	reflect above change.
+
+	* doc/sed.texi: fix "Invoking" node's spelling to comply
+	with GNU standards.
+
+Fri May  8 11:43:10 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* doc/sed.1, doc/Makefile.am: wrote (very basic) man page.
+
+Thu May  7 20:40:21 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* lib/Makefile.am, lib/memmove.c, lib/memchr.c, lib/regex.c,
+	lib/memcpy.c, lib/regex.h, lib/memcopy.h, lib/string.h,
+	lib/pagecopy.h, lib/ansidecl.h: grab yet-another-version
+	from gnu.org for baseline and/or edit copyright boilerplate
+	using official lgpl2gpl.sed script.  Take care not to
+	loose regnexec() interface or special conditional-compilation
+	code.
+
+Wed May  6 23:35:12 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* lib/regex.c, lib/regex.h: take from grep-2.1 distribution,
+	then trivially added the regnexec() interface.
+
+	* sed/sed.c, sed/compile.c, sed/execute.c: made modifications
+	to work with regex instead of rx.
+
+	* rx/*: deleted directory; the code is just too slow.
+	I think it will be easier to extend regex to fully
+	support POSIX.2 than to tune rx to be reasonable.
+	Even if this supposition is wrong, I'd rather make
+	the 3.01 release with the slightly deficient regex.
+
+	* Makefile.am lib/Makefile.am, sed/Makefile.am: made changes
+	related to the substitution of regex for rx.
+
+	* lib/Makefile.am, sed/Makefile.am: since regex is not a
+	``compatability'' module, changed name of library to
+	``libsed.a''.
+
+	* lib/memchr.c, lib/memcpy.c, lib/memmove.c: add conditional
+	compilation code to leave zero-sized .o file if system
+	already supports the implemented function.
+
+	* testsuite/help.good, testsuite/version.good: brought
+	up-to-date (once again).
+
+	* NEWS, ANNOUNCE: changes to reflect this batch of changes.
+
+Wed May  6 18:40:47 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/execute.c: discovered awful bug in '}' handling:
+	it could read past the end of vec (because `n' was
+	being decremented below zero)!  Needed to "continue"
+	instead of "break".
+
+Tue May  5 14:34:38 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* doc/sed.texi, doc/version.texi: wrote some rudimentary
+	texinfo documentation.
+
+	* ANNOUNCE, NEWS, README, README.rx, Makefile.am:
+	more updates for the upcoming beta-release.
+
+	* sed/compile.c, sed/execute.c, sed/sed.c, sed/utils.c,
+	sed/sed.h, lib/strerror.c: update copyright notice text.
+
+Fri May  1 15:41:37 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/execute.c (match_an_address_p, match_address_p): if
+	the second element of an address range is a line number,
+	and that line number is *less than* (or equal to) the
+	current line number, we only match the one line (per
+	POSIX.2, section 4.55.7.1).  [Bug discovered as reported
+	in the seders mailing list FAQ.]
+
+	* AUTHORS, NEWS, acconfig.h, configure.in, doc/Makefile.am,
+	lib/Makefile.am, sed/Makefile.am, lib/README,
+	testsuite/help.good, testsuite/version.good:
+	Updated in anticipation of the 3.01-beta1 release.
+	Reorganized development source tree to make creation
+	of a distribution simpler.  Most notable changes were
+	to the various Makefile.am files and configure.in, but
+	some minor edits (such as deleting or changing #include
+	directives) have been made in many other source files.
+
+	* bootstrap.sh, README.bootstrap: created a mechanism for
+	creating sed on a system which lacks a working sed.
+
+Thu Apr 16 23:52:11 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed.h, sed.c, execute.c, compile.c: did a spell-check on
+	the comments; fixed several typos.
+
+Thu Apr 16 13:43:01 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* execute.c (do_subst): fixed bug where the "replaced" flag
+	was being set to one inappropriately when at least one
+	but fewer than sub->numb matches of the regexp were found.
+	(Thanks to Simon Taylor <staylor@hermes.iaccess.com.au>
+	for the bug report.)
+
+Wed Apr 15 11:35:31 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed.h, sed.c, compile.c, execute.c: having a concern that
+	a cast was being done inappropriately, and realizing that
+	there is no quick way to locate all casts in a program, I
+	went through and marked all casts with a simple macro.
+	Now it is a simple matter to locate the casts, and it is
+	also a simple matter to turn of casts for a lint session
+	(if it should be desired).
+
+Wed Apr 15 10:29:21 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* compile.c, sed.c: redo compile phase so that brace
+	expressions can be spread across multiple files.
+	For example:
+	  printf '{' >a; printf 'l;d' >b; printf '}' >c
+	  sed -f a -f b -f c foo
+	will now compile (and work), instead of complaining
+	about an unmatched '{'.  The mess created in compile.c
+	allowed a little simplification to the command-line
+	processing of "-e" options in sed.c.
+
+	sed.h: added (opaque) err_info member to struct vector;
+	added comments to the members of struct vector.
+
+Wed Apr 14 23:50:50 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed.h, sed.c, compile.c, execute.c: added types countT and
+	flagT in order to clarify what various "int"s were doing.
+	Also makes it easy to change the type used for counts
+	(for example, to "unsigned long long") if desired, although
+	there are still some gotchas (such as the printf() format
+	for the '=' command).
+
+Tue Apr 14 17:34:54 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* execute.c (execute_program, process_files, count_branches,
+	shrink_program): Added a first attempt at program optimization.
+	We now can quit early if we are running with the "-n"
+	and all of the commands are known to be valid only for
+	lines less than the current line.  Thus the "sed" in
+	"foo | sed -n 1,2p" will print read three lines, printint
+	the first two, and then quit, regardless of how much longer
+	"foo" might run or output.  This optimization does not buy
+	much in most cases (it sometimes even costs a little),
+	but when it does help it can help big.  The code is
+	all conditionally compiled based on the
+	EXPERIMENTAL_DASH_N_OPTIMIZATION symbol being #defined,
+	so it can be easily omitted if it causes problems.
+
+Tue Apr 14 12:25:06 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* execute.c (test_dollar_EOF, last_file_with_data_p):
+	test_dollar_EOF() was incorrectly returning a false (0)
+	when there were unprocessed files, none of which had any
+	data (either unopenable or zero-length).  Created
+	last_file_with_data_p() to detect this situation, and
+	modified test_dollar_EOF() to make use of it.
+
+Thu Apr  2 23:02:18 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* compile.c (match_slash): match_slash() did not handle
+	[.coll.], [=equiv=], and [:class:] sequences within a
+	character class.  Added snarf_char_class() [which is a
+	remote derivative of parse_char_class() from GNU ed-0.2]
+	to deal with the details, and altered match_slash()
+	to make use of it.  Also created the trivial
+	add_then_next() to avoid clutter in snarf_char_class().
+
+Thu Apr  2 20:34:42 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* execute.c, sed.c, sed.h: There was a severe bug in
+	how the code handled "sed 5n a b" when "a" consists
+	of exactly five lines -- it behaved like "sed 5q a b"!
+
+	Rearranged where files get opened -- large scale
+	changes primarily involving main(), process_files(),
+	and read_pattern_space(), but also touching on several
+	other parts of execute.c.  The read_pattern_space()
+	function became unwieldly and parts were split into
+	open_next_file(), closedown(), read_always_fail(),
+	read_mem_line(), and read_file_line().  The
+	at_end_of_file_p() function became obsolete and was
+	eliminated; test_dollar_EOF_p() was updated.  A few
+	global and module-static variables were elminated, and
+	"struct line" was extended; comments were added to the
+	"struct line" declartation to document some important
+	dependencies in it.
+
+	I undertook the reorganization with dread, but I
+	feel that the new organization is an improvement
+	well beyond just fixing the bug that inspired it.
+
+Thu Apr  2 01:16:25 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* execute.c (read_file_line, slow_getline): the fread()
+	buffering code gives insufficient feedback to a user
+	running sed with a tty input device, so I created
+	slow_getline() for reading from a tty device.
+	Additionally, EOF detection has been made a little more
+	sensitive to avoid requiring multiple EOFs to be entered
+	from a tty.
+
+	* configure.in: added isatty() check.
+
+Wed Apr  1 11:04:30 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* configure.in (CPPFLAGS, LDFLAGS, LIBS):
+	Set to appropriate values if large file support needs
+	explicit enabling.  Code fragment taken from a 1997-10-25
+	patch to gawk by Paul Eggert <eggert@twinsun.com>
+
+Thu Aug 14 17:43:27 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* utils.c (ck_fclose): modified to ignore NULL parameter.
+
+Thu Aug 14 12:08:45 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* execute.c: tweaked execute_program() to eliminate
+	gratuitous "goto" usage.
+
+Thu Aug 14 11:30:04 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* compile.c: added case-insensitive modifier ('I') to
+	address and s/// regexps.  The s/// case also accepts
+	the more popular 'i' modifier.  (The address regexp
+	cannot use 'i' as a modifier, as that conflicts with
+	the use of the 'i'nsert command.)
+
+Thu Aug 14 09:29:06 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* compile.c: abstracted out match_slash() from the s///, y///,
+	and address-regexp special-case codes.
+
+	* execute.c: made dump_append_queue() use ck_fread() instead
+	of hand-rolled error checking.
+
+Mon Jul 28 10:50:41 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* sed.c, sed.h, execute.c: POSIX.2, section 4.55.7, says that
+	a newline must end *every* output line.  But I think that
+	it is useful (when seding a binary file) to omit a trailing
+	newline if the input lacks one.  Thus the addition of
+	POSIXLY_CORRECT behavior.
+
+	* execute.c: however, when seding multiple files my feeling
+	is that it makes sense to have each file but the last
+	behave as-if it ended in a newline.  Modified read_pattern_space()
+	accordingly.
+
+	* utils.c: realized that add1_buffer(), for performance reasons,
+	shouldn't be calling memcpy() (indirectly via add_buffer()),
+	so rewrote it.
+
+Sat Jul 26 23:08:28 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* execute.c: attempted to make read_pattern_space more
+	efficient for the the non-mmap() case.
+
+	* utils.c, utils.h, execute.c: new function ck_fread()
+	created and used.
+
+Sat Jul 26 20:22:14 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* execute.c, compile.c, sed.c: abstracted the mmap()
+	interface into map_file()/unmap_file() [sed.c], and
+	changed the ad-hoc code in compile_file() [compile.c]
+	and process_file() [execute.c] to make use of the new
+	interface.
+
+Sat Jul 26 19:45:46 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* execute.c, compile.c, configure.in: Check to see if mmap()
+	is available; if so make use of it on regular files.
+
+	* compile.c: compile_file() now closes the input file
+	when it is through!
+
+Sun Jul 20 23:57:02 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* compile.c: modified parsing to permit whitespace in more
+	places where it makes sense;
+	added backslash escaping to the y/// command, per POSIX.
+
+	* execute.c: Merged append_pattern_space() into read_pattern_space();
+	moved body of 's' command to new function do_subst();
+	moved body of 'l' command to new function do_list();
+	changed output of 'l' command to conform to POSIX.2;
+	made line handling conform to POSIX; added output_line() function;
+	redesigned append-space algorithm; added append_queue structure and
+	the next_append_slot() and dump_append_queue() functions.
+
+	* sed.h: moved the definition of what is now struct subst
+	outside of the definition of struct sed_cmd.
+
+Sat Jul 19 16:29:09 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* sed.c, execute.c, sed.h, Makefile.am: Separated out the
+	pieces dealing with executing the program from the top-level
+	parameter parsing and control.
+
+Sat Jul 19 01:16:35 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* sed.c, compile.c, sed.h, Makefile.am: separate out the
+	pieces dealing with compiling the program from the pieces
+	dealing with interpreting the result.
+
+	* compile.c: add functions in_nonblank() and in_integer(),
+	and change interface to compile_address() with an eye
+	to making code clearer.
+
+Fri Jul 18 13:35:50 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* utils.c: attempt at a quasi-unification of the
+	STDC and traditional C approaches to panic().
+
+	* sed.c: eliminate some gratuitous bit twiddling.
+	(Using flag bits can be a useful technique, but
+	this code is cleaner without them.)
+
+	* sed.c: place mutually exclusive members of struct addr
+	within a union, mainly to document the exclusivity;
+	eliminate unused structure members from struct fp_list;
+	eliminate unnecessary module-global variables;
+	remove some #if 0 code that is too odd to keep;
+	allegedly simplified the 'l' case of execute_program();
+	allegedly simplified inchar();
+	localized some static variables;
+	renamed some variables to better document their purpose;
+	removed some goto-s rendered obsolete by other changes.
+
+Thu Jul 17 15:30:44 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* utils.c, utils.h, sed.c: added and made use of
+	ck_free() function.
+
+	* utils.c, utils.h, sed.c: changed all the *_buffer()
+	functions to take/return an incomplete type
+	"struct buffer *" instead of using VOID *.
+
+	* utils.c, utils.h, sed.c: renamed "finish_buffer()"
+	to "free_buffer()", on the premise that the new
+	name better describes the function's purpose.
+
+Wed Jul 16 13:52:14 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* utils.c, utils.h, sed.c: added and made use of
+	ck_memdup() function.
+
+	* sed.c: protected a call to add1_buffer() in
+	compile_program() which could have tried to
+	push an EOF if a a/i/c command ended with
+	a '\', EOF sequence.
+
+	* utils.c: added sanity check to add1_buffer() so that
+	EOF will not be added to the buffer.
+
+Wed Jul 16 03:56:26 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* configure.in, compat.h, compat.c: added memchr.
+
+	* sed.c: got rid of arbitrary NUM_FPS limit;
+	made global functions and variables "static" where appropriate;
+	make various cosmetic changes, hopefully improving readability;
+	simplified some redundant predicates;
+	simplified some code, but nothing fundamental (yet?).
+
+Wed Jul 16 00:24:54 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* alloca.c, getopt.c, getopt.h, getopt1.c: updated from
+	versions in textutils-1.22.
+
+	* Makefile.in, Makefile.am, configure.in: put in automake support.
+
+	* basicdefs.h, compat.h, compat.c [, sed.c, utils.c]: took out
+	some very ugly compatibility #ifdefs and packaged into one
+	place.
+
+	* sed.c, utils.c: some gratuitous formatting changes.
+
+	* utils.c: changed datatype of utils_id_s in order to
+	eliminate arbitrary array size.
+
+Sun Jul 13 17:00:26 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* sed.c, utils.c, utils.h: de-linting oriented cleanup.
+
+Sun Jul 13 00:46:48 PDT 1997  Ken Pizzini <ken@gnu.org>
+
+	* sed.c: fixed bug which caused SEGV for files missing a
+	final newline.  Corrected calls to regnexec to pass the
+	proper parameters, in the proper order.
+
+Sat Dec 30 20:16:59 1995  Tom Lord  <lord@beehive>
+
+	*** Version 3.00 released
+	
+	* sed.c: Use posix entry points to regexp functions.
+	Fix enough bugs to pass the test-suite.
+
+....... Jason Molenda  <crash@cygnus.com>
+
+	* testsuite/: trippy test suite.
+
+
+Wed May 11 07:46:24 1994  Chip Salzenberg  (chip@fin.uucp)
+
+	*** Version 2.05 released
+	
+	* sed.c (compile_address): Recognize numeric addresses.
+	Fixes typo made during installation of "~" feature.
+
+Sat Apr 30 17:17:38 1994  Tom Lord  (lord@x1.cygnus.com)
+
+	*** Version 2.04 released
+
+	* sed.c: applied a patch from
+	 From: kap1@tao.cpe.uchicago.edu (Dietrich Kappe)
+
+	 Dietrich writes:
+
+	 As my contribution to the creeping feature creature in sed,
+	 here is a new type of address. The address has form n~m,
+	 which means "the line number is equal to n modulo m." The
+	 modifications to sed are trivial, and the general
+	 usefulness of this address should be obvious. If m is 0 or
+	 missing, 1 is used in its place (could be a bug or a
+	 feature :-).
+
+Sat Apr 30 17:17:38 1994  Tom Lord  (lord@x1.cygnus.com)
+
+	* rx.c (solve_destination): protect `solution' more carefully.
+	This is a cleanup of a patch from Kevin Buettner
+	 (kev@cujo.geg.mot.com).
+
+Sat Apr 30 17:17:38 1994  Tom Lord  (lord@x1.cygnus.com)
+
+	* rx.c: make translation tables unsigned chars
+
+	* sed.c (main): Compile accumulated -e commands as
+	soon as a -f command comes along.  This ensures that
+	the commands are executed in the right order.
+
+Mon Oct 25 14:41:47 1993  Tom Lord  (lord@rtl.cygnus.com)
+
+	* sed.c (execute_program): 'w' flushes the buffer after it
+	writes -- diagnosed by doug@research.att.com.  'r' and 'w' to
+	the same file is now supported -- hopefully even in a way that
+	satisfies Posix (it now behaves differently from some
+	/bin/sed's and the spec is hard to read so i'm not sure).
+
+	Also, 'r' of a non-existent file is now permitted.
+
+Mon Oct 11 21:06:10 1993  Tom Lord  (lord@cygnus.com)
+
+	* sed.c (execute_program): remember that 'b' and 't' are more
+	like longjmp than goto.  Patch from tom@basil.icce.rug.nl (Tom
+	R.Hageman)
+
+	* rx.c: patch from From: fin!chip@rutgers.edu (Chip
+	Salzenberg) to get rid of compiler warnings.
+
+
+Sat Aug  7 01:04:59 1993  Tom Lord  (lord@unix7.andrew.cmu.edu)
+
+	*** Version 2.03 released
+	
+	* sed.c (compile_regex): report error messages for bogus
+	regexps.
+
+	SEE ALSO:  ChangeLog.rx
+
+
+
+Wed Jul 21 00:28:03 1993  Tom Lord  (lord@unix8.andrew.cmu.edu)
+
+	* alloca.c: upgraded to a more recent version
+
+	* rx.c (re_search_2): prefer matches with longer
+	subexpressions to those with shorter ones, giving precedence
+	to low numbered subexpressions.
+
+	* rx.c (re_compile): don't free `params' if its null.
+
+Fri Jul 16 01:12:08 1993  Tom Lord  (lord@unix8.andrew.cmu.edu)
+
+	* rx.[ch], sed.c: rx replaces regex.
+
+
+
+Thu May 27 11:13:03 1993  Tom Lord  (lord@unix3.andrew.cmu.edu)
+
+	* sed.c (execute_program, match_addr): caught more cases
+	that need to be sensitive to a missing \n at EOF.
+
+Fri May 21 00:39:22 1993  Tom Lord  (lord@unix8.andrew.cmu.edu)
+
+	* sed.c (execute_program): apply gaumondp's patch
+	to fix '\xabcxs/foo/bar/'.
+
+	* sed.c (execute_program):
+	If a second address is a regexp, never match it on the
+	same line as the first address.
+
+	* sed.c (compile_regexp):
+	Numeric ranges  x,y s.t. y < x are now treated as x,x.
+	There was a bug in that they were being handled like x,x+1.
+
+	* sed.c (execute_program, read_pattern_space,
+	append_pattern_space) don't add newlines to lines
+	that don't have them.
+
+Wed May 19 13:34:45 1993  Tom Lord  (lord@unix9.andrew.cmu.edu)
+
+	* sed.c (compile_program): grok \\n in comments.
+
+Mon May 17 16:34:50 1993  Tom Lord  (lord@unix9.andrew.cmu.edu)
+
+	* alloca.c: new (standard) file
+
+	* configure.in: AC_CONSTified
+
+	* sed.c (compile_program): properly diagnose the error of
+	a missing command (e.g. sed /x/). (thanks gaumondp)
+
+	* sed.c (compile_regexp): handle character classes correctly.
+	Thanks gaumondp@ERE.UMontreal.CA
+	and  schwab@issan.informatik.uni-dortmund.de.
+
+Thu May  6 12:37:18 1993  Tom Lord  (lord@unix10.andrew.cmu.edu)
+
+	* sed.c (compile_filename, execute_program): don't use
+	`access' or `/dev/null'.
+
+	* sed.c (execute_program): 'N' at EOF should delete the pat buf.
+
+	* sed.c (compile_filename): truncate, don't append files
+	being openned for `w' or `s///w'
+
+	* sed.c (execute_program): -n switch shouldn't effect `i' or `c'.
+
+	* sed.c (compile_program): don't compile unescaped newlines
+	into the substitution string of an `s' command (they are an error).
+
+	* sed.c (compile_regex): correctly skip over character
+	sets that contain `]'.
+
+	* sed.c (execute_program): patch from gaumondp
+	Correctly handle empty-string matches in the case of an `s'
+	command with a repeat count.
+
+	* sed.c (compile_program): patch from gaumondp@ere.UMontreal.ca.
+	Don't consume characters after the label of a `b', `t' or `:' command.
+
+	* sed.c (compile_program): unmatched open braces are an error.
+
+	* sed.c (compile_file): when consuming an initial comment,
+	count lines correctly.
+
+Wed Nov 18 02:10:58 1992  Tom Lord  (lord@unix2.andrew.cmu.edu)
+
+	* sed.c (execute_program): Made s///p print even if -n was
+	specified.
+
+	* sed.c (compile_string): Changed the type of this function to
+	fix a compile warning.
+
+Wed Nov  4 17:15:34 1992  Tom Lord  (lord@unix7.andrew.cmu.edu)
+
+	* sed.c (main): Initialize the hold area to contain "\n"
+	instead of "".  In execute_program, all lines are expected
+	to be newline terminated.  Also, if H is the first command
+	in the script, the result is a pattern buffer that begins
+	with a blank line.  Thanks to pinard@iro.umontreal.ca
+	(Francois Pinard) for pointing out this and many other bugs.
+
+	* sed.c (execute_program): Fixed a case of `D' command.
+	Thanks Chris Weber <weber@bucknell.edu>
+
+	* sed.c: added new tests of no_default_output to make -n work.
+	Thanks Andrew Herbert <andrew@werple.apana.org.au>
+
+	* sed.c, configure.in,Makefile.in: autoconfed bcopy and const.
+	Thanks "J.T. Conklin" <jtc@gain.com>
+
+	* sed.c: made prog_cur, prog_start, and prog_end unsigned so
+	that users could write  `sed -e s/ÿ/foo/g'.
+
+Tue Oct 13 00:04:05 1992  Tom Lord  (lord@unix3.andrew.cmu.edu)
+
+	* sed.c (execute_program): fixed the cycling behavior of 'D'
+
+	* sed.c: integrated patch that closes files
+
+	* sed.c: changed regexp syntax
+
+Fri May 22 15:11:12 1992  Tom Lord  (lord at moriarty.bh.andrew.cmu.edu)
+
+	* regex.c:  this is not my change, but a pointer to the fact
+	that karl@gnu fixed some regexp bugs that were plaguing sed.
+
+Thu Apr 30 13:02:21 1992  Tom Lord  (lord at unix3.andrew.cmu.edu)
+
+	* sed.c (compile_program, execute_program)
+	subprograms are now compiled with an explicit continuation ;)
+	return_v and return_i in struct vector.  execute_program
+	no longer recurses to execute subprograms (case '{') and now
+	understands a return instruction (case '{').
+
+Tue Apr 28 17:13:04 1992  Tom Lord  (lord at unix7.andrew.cmu.edu)
+
+	* sed.c (compile_address) added \?regexp? syntax for addresses.
+
+	* sed.c (main) added {} intervals to the obscure regexp
+	syntax.
+
+	* sed.c (compile_program)  after calling compile_address,
+	normalize numeric addresses (make a2.addr_number > a1.addr_number).
+	This is necessary because line numbers must match exactly,
+	but sed does not try to match a2 until after a1 has matched,
+	yet a1,a2 where a2 <= a1 is defined to be equivelent to
+	a1,a1+1
+
+Sat Feb 29 10:55:54 1992  David J. MacKenzie  (djm@nutrimat)
+
+	* sed.c (usage): Document long options as starting with `--'.
+
+Mon Dec  9 23:56:40 1991  David J. MacKenzie  (djm at wookumz.gnu.ai.mit.edu)
+
+	* sed.c: Include sys/types.h, for new regex.h.
+
+Tue Nov  5 02:16:01 1991  David J. MacKenzie  (djm at wookumz.gnu.ai.mit.edu)
+
+	* utils.c: Change NO_VFPRINTF to VPRINTF_MISSING, for
+	compatibility with autoconf.
+
+Mon Sep  2 22:02:40 1991  David J. MacKenzie  (djm at apple-gunkies)
+
+	* sed.c (compile_regex): Treat \ as a normal character when in
+	a char class.
+
+Thu Aug  8 00:15:33 1991  David J. MacKenzie  (djm at bleen)
+
+	* Version 1.08.
+
+	* sed.c (compile_filename): If reading a file fails, read
+	/dev/null instead.  It's what Unix and POSIX do, effectively.
+
+	* sed.c (compile_regex): The 'slash' character doesn't
+	terminate the regex if it's in a character class.
+
+	* sed.c (main): If given no args, or bad option, print usage
+	message.
+	(usage): New function.
+
+	* sed.c (execute_program): Amount written for 'P' command was
+	wrong.  From stephend@ksr.com (Stephen Davis).
+
+Wed Aug  7 16:51:14 1991  David J. MacKenzie  (djm at apple-gunkies)
+
+	* sed.c (append_pattern_space): Check for buffer full before
+	instead of after writing to buffer.  Don't need to test for
+	EOF initially anymore, due to the next change.
+	(execute_program): For 'n' and 'N' commands, if eof is reached
+	in input, quit the script like Unix sed does.
+	Fix memory allocation problems for 'a' and 'r' commands.
+	(compile_program): Fix off by one error in processing comments.
+	All of the above are from Tapani Tarvainen, tarvaine@tukki.jyu.fi.
+
+	* sed.c (setup_jump): Use isblank instead of testing for ' '
+	or '\t', for POSIX locales.
+
+	* utils.c (ck_strdup): Renamed from strdup.
+	* sed.c: Change callers.
+
+	* sed.c, utils.c: Clean up declarations and includes to get
+	rid of compiler warnings.
+
+	* sed.c (main): Add long-named options.  Don't complain if -n
+	is given twice.
+
+Fri Aug  2 12:33:16 1991  David J. MacKenzie  (djm at apple-gunkies)
+
+	* configure: Support +srcdir arg.  Create config.status and
+	remove it and Makefile if interrupted while creating them.
+	* Makefile.in: Change DESTDIR to prefix.
+
+Mon Jul 15 13:07:39 1991  David J. MacKenzie  (djm at wookumz.gnu.ai.mit.edu)
+
+	* sed.c (main): Add -V option to print version number.
+	(USAGE): Mention -V.
+
+Mon Jul  8 01:42:22 1991  David J. MacKenzie  (djm at geech.gnu.ai.mit.edu)
+
+	* sed.c: Define bcopy in terms of memcpy if STDC_HEADERS as
+	well as if USG.
+	(compile_filename): Don't glob filename (for 'r' and 'w'
+	commands).  Unix sed doesn't do it and it's not very useful,
+	since it can only match 0 or 1 files.
+	(execute_program): Change '\a' to 007 since some compilers
+	don't recognize \a.
+	* utils.c: New file; code moved from sed.c.
+	* Replace Makefile with Makefile.in and configure.
+	Update README.
+
+Tue Mar 26 13:00:48 EST 1991	Jay Fenlason (hack@gnu.ai.mit.edu)
+
+	* sed.c (match_address)  Added a trivial cast for portability.
+
+Mon Feb 25 13:23:29 EST 1991	Jay Fenlason (hack@ai.mit.edu)
+
+	* sed.c  Changed 's' command to work with latest version of regex()
+	routines, which mysteriously changed somewhere in there. . .
+	A one-line patch from David Eckelkamp (eckelkamp@mcc.com).
+
+	Initialize the fastmap in the hopes that it'll make sed faster.
+
+Thu Feb 21 13:42:27 EST 1991	Jay Fenlason (hack@ai.mti.edu)
+
+	* sed.c Change panic to compile with other __STDC__ compilers.
+
+Wed Jan 30 10:46:38 EST 1991	Jay Fenlason (hack@ai.mit.edu)
+
+	* sed.c  Changed version number.  Made new release.
+
+Tue Nov 27 15:34:51 EST 1990	Jay Fenlason (hack@ai.mit.edu)
+
+	* sed.c (setup_jump)  Don't blow chunks if there isn't a label
+	after a b or t command.
+
+		(main) Don't panic if it a branch command doesn't have
+	a label to branch to.
+
+		(main)  Collect all the -e arguments together and parse them
+	all at once.  This way, -e { -e mumble -e } will work.
+
+	All these small patches from David Schmidt (davids@isc-br.isc-br.com)
+
+Tue Sep 11 12:51:37 EDT 1990	Jay Fenlason (hack@ai.mit.edu)
+
+	* sed.c Changed some function forward declarations to use VOID *
+	instead of char *
+
+Mon Jul 16 11:12:54 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
+
+	* sed.c (ck_malloc)  Use malloc(1) instead of malloc(0) if given
+	a request for zero bytes.
+
+Tue Jun  5 02:05:37 1990  David J. MacKenzie  (djm at albert.ai.mit.edu)
+
+	* sed.c: Remove excess newlines from calls to panic.
+	Reformat some comments to fit in 79 columns.
+	Base whether to use void * on __STDC__, not __GNU__.
+	(main): Add missing arg when printing usage message.
+	Print usage if given invalid arg.
+	(panic) [__STDC__]: Add missing ", ...".
+	(compile_filename): Print correct error message if glob_filename
+	returns NULL.
+
+Thu Apr  5 21:41:12 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+	* sed.c (execute_program, case 'r'): When need to realloc append.text,
+	multiply append.alloc by 2 instead of adding
+	cur_cmd->x.cmd_txt.text_len.
+
+Tue Mar  6 15:55:35 EST 1990 Jay Fenlason (hack@ai.mit.edu)
+
+	* sed.c (compile_regex)  Allocate 10 bytes extra space needed by
+	re_compile_pattern.
+
+Sun Feb 25 16:32:10 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
+
+	* sed.c (execute_program, case 'l'): Print \00 instead of \0.
+	Print backslash as \\ not \.
+	Print \xx instead of /xx.
+
+Thu Feb  1 14:02:28 EST 1990		hack@wookumz
+
+	* sed.c (memchr)  Use () inside inner loop so it will work correctly.
+	A two character patch from Robert A Bruce (rab@allspice.berkeley.edu)
+
+Wed Sep 27 18:47:39 EDT 1989		hack@ai.mit.edu
+
+	* sed.c (compile_regex)  New function.  When compiling regex,
+	turn ^ into \` and $ into \' so that they won't match on embedded
+	newlines.  UN*X	pattern matching is a crock.
+	(compile_program, compile_address) call compile_regex.
+
+Mon Sep 18 10:15:32 EDT 1989		hack@ai.mit.edu
+
+	* sed.c (compile_program):  define translate as unsigned char * so
+	that y command will work on non-ascii characters.
+
+	Changed version number to 1.06.
+
+Thu Sep 14 15:57:08 EDT 1989		hack@ai.mit.edu
+
+	* sed.c  (compile_program)  Let programs use ; to terminate } as
+	well as newline.
+
+	(read_file) Print an error msg to stderr if it can't open an
+	input file.
+
+Thu Mar 23 18:04:46 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
+
+	* Makefile, sed.c: Added new copyright notice.
+
+	* Makefile: Make distributions which follow the symlinks.
+
+hack@ai.mit.edu
+
+	1.05	Fixed error in 'r' (now does things in the right order)
+
+	1.04	Fixed s/re/rep/[number]
+
+	1.03	Fixes from Mike Haertel for regexps that match the
+		empty string, and for Ritchie stdio (non-sticky EOF)
+
+	1.02	Fixed 't', 'b', ':' to trim leading spaces and tabs
+		Fixed \\ in replacement of 's' command
+		Added comments
+
+	1.01	Added s/re/rep/[digits]
+		added #n as first line of script
+		added filename globbing
+		added 'l' command
+		All in the name of POSIX
+
+	1.00	Began (thinking about) distributing this file
+
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+version-control: never
+End:
Index: /tags/kBuild-0.1.4/src/sed/INSTALL
===================================================================
--- /tags/kBuild-0.1.4/src/sed/INSTALL	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/INSTALL	(revision 1780)
@@ -0,0 +1,229 @@
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+   This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   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, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   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 you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+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.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+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.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `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 `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+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 other than `/usr/local' 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'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+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.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
Index: /tags/kBuild-0.1.4/src/sed/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/sed/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/Makefile.am	(revision 1780)
@@ -0,0 +1,42 @@
+## Process this file with automake to produce Makefile.in
+
+# Automake requirements
+AUTOMAKE_OPTIONS = gnits 1.8
+ACLOCAL_AMFLAGS = -I config
+
+PACKAGE = sed
+
+SUBDIRS = intl lib po sed doc testsuite
+
+noinst_DATA = bootstrap.sh
+noinst_HEADERS = basicdefs.h
+
+EXTRA_DIST = BUGS THANKS COPYING.DOC README.boot bootstrap.sh 	      \
+	config/texi2dvi    config/help2man
+
+html:
+	cd doc && make html
+
+DISTCHECK_CONFIGURE_FLAGS = XGETTEXT='$(SHELL) -c : dummy' $(EXTRA_DC_FLAGS)
+EXTRA_DC_FLAGS = 
+
+full-distcheck:
+	make distcheck EXTRA_DC_FLAGS='--enable-html'
+	make distcheck EXTRA_DC_FLAGS='--disable-i18n'
+	make distcheck EXTRA_DC_FLAGS='--disable-nls'
+	make distcheck EXTRA_DC_FLAGS='--without-included-regex'
+	make distcheck EXTRA_DC_FLAGS='--without-included-gettext'
+
+update-regex:
+	HOST=sources.redhat.com && \
+	BASEURL="http://$$HOST/cgi-bin/cvsweb.cgi/~checkout~/libc/posix" && \
+	QUERY='cvsroot=glibc&content-type=text/plain' && \
+	wget -O lib/regcomp.c "$$BASEURL/regcomp.c?$$QUERY" && \
+	wget -O lib/regexec.c "$$BASEURL/regexec.c?$$QUERY" && \
+	wget -O lib/regex.c "$$BASEURL/regex.c?$$QUERY" && \
+	wget -O lib/regex_.h "$$BASEURL/regex.h?$$QUERY" && \
+	wget -O lib/regex_internal.c "$$BASEURL/regex_internal.c?$$QUERY" && \
+	wget -O lib/regex_internal.h "$$BASEURL/regex_internal.h?$$QUERY" && \
+	wget -O testsuite/BOOST.tests "$$BASEURL/BOOST.tests?$$QUERY" && \
+	wget -O testsuite/PCRE.tests "$$BASEURL/PCRE.tests?$$QUERY" && \
+	wget -O testsuite/SPENCER.tests "$$BASEURL/rxspencer/tests?$$QUERY"
Index: /tags/kBuild-0.1.4/src/sed/Makefile.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/Makefile.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/Makefile.in	(revision 1780)
@@ -0,0 +1,680 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# 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_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = README $(am__configure_deps) $(noinst_HEADERS) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+	$(srcdir)/bootstrap.sh.in $(srcdir)/config_h.in \
+	$(top_srcdir)/configure $(top_srcdir)/intl/Makefile.in \
+	ABOUT-NLS AUTHORS COPYING COPYING.DOC ChangeLog INSTALL NEWS \
+	README-alpha THANKS config/config.guess config/config.rpath \
+	config/config.sub config/depcomp config/install-sh \
+	config/mdate-sh config/missing config/texinfo.tex
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \
+	$(top_srcdir)/config/getline.m4 \
+	$(top_srcdir)/config/gettext-ver.m4 \
+	$(top_srcdir)/config/gettext.m4 \
+	$(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \
+	$(top_srcdir)/config/lcmessage.m4 \
+	$(top_srcdir)/config/lib-ld.m4 \
+	$(top_srcdir)/config/lib-link.m4 \
+	$(top_srcdir)/config/lib-prefix.m4 \
+	$(top_srcdir)/config/progtest.m4 \
+	$(top_srcdir)/config/stdbool.m4 \
+	$(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = bootstrap.sh intl/Makefile
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-exec-recursive install-info-recursive \
+	install-recursive installcheck-recursive installdirs-recursive \
+	pdf-recursive ps-recursive uninstall-info-recursive \
+	uninstall-recursive
+DATA = $(noinst_DATA)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_HTML_FALSE = @BUILD_HTML_FALSE@
+BUILD_HTML_TRUE = @BUILD_HTML_TRUE@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
+GMSGFMT = @GMSGFMT@
+HAVE__BOOL = @HAVE__BOOL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@
+MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+OBJEXT = @OBJEXT@
+PACKAGE = sed
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SED_FEATURE_VERSION = @SED_FEATURE_VERSION@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEST_REGEX_FALSE = @TEST_REGEX_FALSE@
+TEST_REGEX_TRUE = @TEST_REGEX_TRUE@
+TEXI2HTML = @TEXI2HTML@
+TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@
+TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+# Automake requirements
+AUTOMAKE_OPTIONS = gnits 1.8
+ACLOCAL_AMFLAGS = -I config
+SUBDIRS = intl lib po sed doc testsuite
+noinst_DATA = bootstrap.sh
+noinst_HEADERS = basicdefs.h
+EXTRA_DIST = BUGS THANKS COPYING.DOC README.boot bootstrap.sh 	      \
+	config/texi2dvi    config/help2man
+
+DISTCHECK_CONFIGURE_FLAGS = XGETTEXT='$(SHELL) -c : dummy' $(EXTRA_DC_FLAGS)
+EXTRA_DC_FLAGS = 
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh:
+	@:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --gnits '; \
+	      cd $(srcdir) && $(AUTOMAKE) --gnits  \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits  Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnits  Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config_h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config_h.in:  $(am__configure_deps) 
+	cd $(top_srcdir) && $(AUTOHEADER)
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+bootstrap.sh: $(top_builddir)/config.status $(srcdir)/bootstrap.sh.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+intl/Makefile: $(top_builddir)/config.status $(top_srcdir)/intl/Makefile.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config_h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS) config_h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config_h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS) config_h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@case `sed 15q $(srcdir)/NEWS` in \
+	*"$(VERSION)"*) : ;; \
+	*) \
+	  echo "NEWS not updated; not releasing" 1>&2; \
+	  exit 1;; \
+	esac
+	$(am__remove_distdir)
+	mkdir $(distdir)
+	$(mkdir_p) $(distdir)/. $(distdir)/config $(distdir)/intl $(distdir)/lib $(distdir)/po
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(mkdir_p) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r $(distdir)
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+	$(am__remove_distdir)
+
+dist-tarZ: distdir
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__remove_distdir)
+
+dist-shar: distdir
+	shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+	$(am__remove_distdir)
+
+dist-zip: distdir
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__remove_distdir)
+
+dist dist-all: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	esac
+	chmod -R a-w $(distdir); chmod a+w $(distdir)
+	mkdir $(distdir)/_build
+	mkdir $(distdir)/_inst
+	chmod a-w $(distdir)
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && cd $(distdir)/_build \
+	  && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+	    --with-included-gettext \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+	$(am__remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+	@cd $(distuninstallcheck_dir) \
+	&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(DATA) $(HEADERS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
+	check-am clean clean-generic clean-recursive ctags \
+	ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-shar \
+	dist-tarZ dist-zip distcheck distclean distclean-generic \
+	distclean-hdr distclean-recursive distclean-tags \
+	distcleancheck distdir distuninstallcheck dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic maintainer-clean-recursive \
+	mostlyclean mostlyclean-generic mostlyclean-recursive pdf \
+	pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+	uninstall-info-am
+
+
+html:
+	cd doc && make html
+
+full-distcheck:
+	make distcheck EXTRA_DC_FLAGS='--enable-html'
+	make distcheck EXTRA_DC_FLAGS='--disable-i18n'
+	make distcheck EXTRA_DC_FLAGS='--disable-nls'
+	make distcheck EXTRA_DC_FLAGS='--without-included-regex'
+	make distcheck EXTRA_DC_FLAGS='--without-included-gettext'
+
+update-regex:
+	HOST=sources.redhat.com && \
+	BASEURL="http://$$HOST/cgi-bin/cvsweb.cgi/~checkout~/libc/posix" && \
+	QUERY='cvsroot=glibc&content-type=text/plain' && \
+	wget -O lib/regcomp.c "$$BASEURL/regcomp.c?$$QUERY" && \
+	wget -O lib/regexec.c "$$BASEURL/regexec.c?$$QUERY" && \
+	wget -O lib/regex.c "$$BASEURL/regex.c?$$QUERY" && \
+	wget -O lib/regex_.h "$$BASEURL/regex.h?$$QUERY" && \
+	wget -O lib/regex_internal.c "$$BASEURL/regex_internal.c?$$QUERY" && \
+	wget -O lib/regex_internal.h "$$BASEURL/regex_internal.h?$$QUERY" && \
+	wget -O testsuite/BOOST.tests "$$BASEURL/BOOST.tests?$$QUERY" && \
+	wget -O testsuite/PCRE.tests "$$BASEURL/PCRE.tests?$$QUERY" && \
+	wget -O testsuite/SPENCER.tests "$$BASEURL/rxspencer/tests?$$QUERY"
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /tags/kBuild-0.1.4/src/sed/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/src/sed/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/Makefile.kmk	(revision 1780)
@@ -0,0 +1,96 @@
+# $Id$
+## @file
+# Sub-Makefile for kmk_sed.
+#
+
+#
+# Copyright (c) 2006-2008 knut st. osmundsen <bird-kBuild-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+SUB_DEPTH = ../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# kmk_sed
+#
+PROGRAMS += kmk_sed
+
+kmk_sed_TEMPLATE = BIN
+kmk_sed_DEPS = \
+	$(PATH_kmk_sed)/config.h \
+	$(PATH_kmk_sed)/regex.h
+kmk_sed_CLEAN = $(kmk_sed_DEPS)
+kmk_sed_INCS = \
+	$(PATH_kmk_sed) \
+	. \
+	lib \
+	intl
+kmk_sed_DEFS = \
+	HAVE_CONFIG_H
+kmk_sed_SOURCES = \
+	sed/sed.c \
+	lib/regex.c \
+	sed/compile.c \
+	sed/execute.c \
+	sed/regexp.c \
+	sed/fmt.c \
+	sed/mbcs.c \
+	lib/getopt1.c \
+	lib/getopt.c \
+	lib/utils.c
+kmk_sed_SOURCES.darwin = \
+	lib/strverscmp.c \
+	lib/obstack.c \
+	lib/getline.c
+kmk_sed_SOURCES.dragonfly = \
+	lib/strverscmp.c \
+	lib/obstack.c \
+	lib/getline.c
+kmk_sed_SOURCES.freebsd = \
+	lib/strverscmp.c \
+	lib/obstack.c \
+	lib/getline.c
+kmk_sed_SOURCES.solaris = \
+	lib/strverscmp.c \
+	lib/obstack.c \
+	lib/getline.c
+kmk_sed_SOURCES.win = \
+	lib/strverscmp.c \
+	lib/obstack.c \
+	lib/mkstemp.c \
+	lib/getline.c \
+	../lib/startuphacks-win.c
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
+#
+# Use checked in config.h instead of running ./configure for it.
+#
+kmk_sed_config.h.$(KBUILD_TARGET) := $(kmk_sed_PATH)/config.h.$(KBUILD_TARGET)
+
+$(PATH_kmk_sed)/config.h: $(kmk_sed_config.h.$(KBUILD_TARGET)) | $(call DIRDEP,$(PATH_kmk_sed))
+	$(CP) -f $^ $@
+
+#
+# Use the regex lib shipped with sed and not anything installed on the system.
+#
+$(PATH_kmk_sed)/regex.h: $(kmk_sed_PATH)/lib/regex_.h | $(call DIRDEP,$(PATH_kmk_sed))
+	$(CP) -f $^ $@
+
Index: /tags/kBuild-0.1.4/src/sed/NEWS
===================================================================
--- /tags/kBuild-0.1.4/src/sed/NEWS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/NEWS	(revision 1780)
@@ -0,0 +1,454 @@
+Sed 4.1.5
+
+* fix parsing of a negative character class not including a closed bracket,
+  like [^]] or [^]a-z].
+
+* fix parsing of [ inside an y command, like y/[/A/.
+
+* output the result of commands a, r, R when a q command is found.
+
+----------------------------------------------------------------------------
+Sed 4.1.4
+
+* \B correctly means "not on a word boundary" rather than "inside a word"
+
+* bugfixes for platform without internationalization
+
+* more thorough testing framework for tarballs (`make full-distcheck')
+
+----------------------------------------------------------------------------
+Sed 4.1.3
+
+* regex addresses do not use leftmost-longest matching.  In other words,
+  /.\+/ only looks for a single character, and does not try to find as
+  many of them as possible like it used to do.
+
+* added a note to BUGS and the manual about changed interpretation
+  of `s|abc\|def||', and about localization issues.
+
+* fixed --disable-nls build problems on Solaris.
+
+* fixed `make check' in non-English locales.
+
+* `make check' tests the regex library by default if the included regex
+  is used (regex tests had to be enabled separately up to now).
+
+----------------------------------------------------------------------------
+Sed 4.1.2
+
+* fix bug in 'y' command in multi-byte character sets
+
+* fix severe bug in parsing of ranges with an embedded open bracket
+
+* fix off-by-one error when printing a "bad command" error
+
+----------------------------------------------------------------------------
+Sed 4.1.1
+
+* preserve permissions of in-place edited files
+
+* yield an error when running -i on terminals or other non regular files
+
+* do not interpret - as stdin when running in in-place editing mode
+
+* fix bug that prevented 's' command modifiers from working
+
+----------------------------------------------------------------------------
+Sed 4.1
+
+* // matches the last regular expression even in POSIXLY_CORRECT mode.
+
+* change the way we treat lines which are not terminated by a newline.
+Such lines are printed without the terminating newline (as before)
+but as soon as more text is sent to the same output stream, the
+missing newline is printed, so that the two lines don't concatenate.
+The behavior is now independent from POSIXLY_CORRECT because POSIX
+actually has undefined behavior in this case, and the new implementation
+arguably gives the ``least expected surprise''.  Thanks to Stepan
+Kasal for the implementation.
+
+* documentation improvements, with updated references to the POSIX.2
+specification
+
+* error messages on I/O errors are better, and -i does not leave temporary
+files around (e.g. when running ``sed -i'' on a directory).
+
+* escapes are accepted in the y command (for example: y/o/\n/ transforms
+o's into newlines)
+
+* -i option tries to set the owner and group to the same as the input file
+
+* `L' command is deprecated and will be removed in sed 4.2.
+
+* line number addresses are processed differently -- this is supposedly
+conformant to POSIX and surely more idiot-proof.  Line number addresses
+are not affected by jumping around them: they are activated and
+deactivated exactly where the script says, while previously
+    5,8b
+    1,5d
+would actually delete lines 1,2,3,4 and 9 (!).
+
+* multibyte characters are taken in consideration to compute the
+operands of s and y, provided you set LC_CTYPE correctly.  They are
+also considered by \l, \L, \u, \U, \E.
+
+* [\n] matches either backslash or 'n' when POSIXLY_CORRECT.
+
+* new option --posix, disables all GNU extensions.  POSIXLY_CORRECT only
+disables GNU extensions that violate the POSIX standard.
+
+* options -h and -V are not supported anymore, use --help and --version.
+
+* removed documentation for \s and \S which worked incorrectly
+
+* restored correct behavior for \w and \W: match [[:alnum:]_] and
+[^[:alnum:]_] (they used to match [[:alpha:]_] and [^[:alpha:]_]
+
+* the special address 0 can only be used in 0,/RE/ or 0~STEP addresses;
+other cases give an error (you are hindering portability for no reason
+if specifying 0,N and you are giving a dead command if specifying 0
+alone).
+
+* when a \ is used to escape the character that would terminate an operand
+of the s or y commands, the backslash is removed before the regex is
+compiled.  This is left undefined by POSIX; this behavior makes `s+x\+++g'
+remove occurrences of `x+', consistently with `s/x\///g'.  (However, if
+you enjoy yourself trying `s*x\***g', sed will use the `x*' regex, and you
+won't be able to pass down `x\*' while using * as the delimiter; ideas on
+how to simplify the parser in this respect, and/or gain more coherent
+semantics, are welcome).
+
+
+----------------------------------------------------------------------------
+Sed 4.0.9
+
+* 0 address behaves correctly in single-file (-i and -s) mode.
+
+* documentation improvements.
+
+* tested with many hosts and compilers.
+
+* updated regex matcher from upstream, with many bugfixes and speedups.
+
+* the `N' command's feature that is detailed in the BUGS file was disabled
+by the first change below in sed 4.0.8.  The behavior has now been
+restored, and is only enabled if POSIXLY_CORRECT behavior is not
+requested.
+
+----------------------------------------------------------------------------
+Sed 4.0.8
+
+* fix `sed n' printing the last line twice.
+
+* fix incorrect error message for invalid character classes.
+
+* fix segmentation violation with repeated empty subexpressions.
+
+* fix incorrect parsing of ^ after escaped (.
+
+* more comprehensive test suite (and with many expected failures...)
+
+----------------------------------------------------------------------------
+Sed 4.0.7
+
+* VPATH builds working on non-glibc machines
+
+* fixed bug in s///Np: was printing even if less than N matches were
+found.
+
+* fixed infinite loop on s///N when LHS matched a null string and
+there were not enough matches in pattern space
+
+* behavior of s///N is consistent with s///g when the LHS can match
+a null string (and the infinite loop did not happen :-)
+
+* updated some translations
+
+----------------------------------------------------------------------------
+Sed 4.0.6
+
+* added parameter to `v' for the version of sed that is expected.
+
+* configure switch --without-included-regex to use the system regex matcher
+
+* fix for -i option under Cygwin
+
+----------------------------------------------------------------------------
+Sed 4.0.5
+
+* portability fixes
+
+* improvements to some error messages (e.g. y/abc/defg/ incorrectly said
+`excess characters after command' instead of `y arguments have different
+lengths')
+
+* `a', `i', `l', `L', `r' accept two addresses except in POSIXLY_CORRECT
+mode.  Only `q' and `Q' do not accept two addresses in standard (GNU) mode.
+
+----------------------------------------------------------------------------
+Sed 4.0.4
+
+* documentation fixes
+
+* update regex matcher
+
+----------------------------------------------------------------------------
+Sed 4.0.3
+
+* fix packaging problem (two missing translation catalogs)
+
+----------------------------------------------------------------------------
+Sed 4.0.2
+
+* more translations
+
+* fix build problems (vpath builds and bootstrap builds)
+
+----------------------------------------------------------------------------
+Sed 4.0.1
+
+* Remove last vestiges of super-sed
+
+* man page automatically built
+
+* more translations provided
+
+* portability improvements
+
+----------------------------------------------------------------------------
+Sed 4.0
+
+* Update regex matcher
+
+----------------------------------------------------------------------------
+Sed 3.96
+
+* `y' command supports multibyte character sets
+
+* Update regex matcher
+
+----------------------------------------------------------------------------
+Sed 3.95
+
+* `R' command reads a single line from a file.
+
+* CR-LF pairs are always ignored under Windows, even if (under Cygwin)
+a disk is mounted as binary.
+
+* More attention to errors on stdout
+
+* New `W' command to write first line of pattern space to a file
+
+* Can customize line wrap width on single `l' commands
+
+* `L' command formats and reflows paragraphs like `fmt' does.
+
+* The test suite makefiles are better organized (this change is
+transparent however).
+
+* Compiles and bootstraps out-of-the-box under MinGW32 and Cygwin.
+
+* Optimizes cases when pattern space is truncated at its start or at
+its end by `D' or by a substitution command with an empty RHS.
+For example scripts like this,
+
+    seq 1 10000 | tr \\n \  | ./sed ':a; s/^[0-9][0-9]* //; ta'
+
+whose behavior was quadratic with previous versions of sed, have
+now linear behavior.
+
+* New command `e' to pipe the output of a command into the output
+of sed.
+
+* New option `e' to pass the output of the `s' command through the
+Bourne shell and get the result into pattern space.
+
+* Switched to obstacks in the parser -- less memory-related bugs
+(there were none AFAIK but you never know) and less memory usage.
+
+* New option -i, to support in-place editing a la Perl.  Usually one
+had to use ed or, for more complex tasks, resort to Perl; this is
+not necessary anymore.
+
+* Dumped buffering code.  The performance loss is 10%, but it caused
+bugs in systems with CRLF termination.  The current solution is
+not definitive, though.
+
+* Bug fix: Made the behavior of s/A*/x/g (i.e. `s' command with a
+possibly empty LHS) more consistent:
+
+       pattern               GNU sed 3.x       GNU sed 4.x
+        B                      xBx               xBx
+        BC                     xBxCx             xBxCx
+        BAC                    xBxxCx            xBxCx
+        BAAC                   xBxxCx            xBxCx
+
+* Bug fix: the // empty regular expressions now refers to the last
+regular expression that was matched, rather than to the last
+regular expression that was compiled.  This richer behavior seems
+to be the correct one (albeit neither one is POSIXLY_CORRECT).
+
+* Check for invalid backreferences in the RHS of the `s' command
+(e.g. s/1234/\1/)
+
+* Support for \[lLuUE] in the RHS of the `s' command like in Perl.
+
+* New regular expression matcher
+
+* Bug fix: if a file was redirected to be stdin, sed did not consume
+it.  So
+      (sed d; sed G) < TESTFILE
+
+double-spaced TESTFILE, while the equivalent `useless use of cat'
+      cat TESTFILE | (sed d; sed G)
+
+printed nothing (which is the correct behavior).  A test for this
+bug was added to the test suite.
+
+* The documentation is now much better, with a few examples provided,
+and a thorough description of regular expressions.  The manual often
+refers to "GNU extensions", but if they are described here they are
+specific to this version.
+
+* Documented command-line option:
+  -r, --regexp-extended
+    Use extended regexps -- e.g. (abc+) instead of \(abc\+\)
+
+* Added feature to the `w' command and to the `w' option of the `s'
+command: if the file name is /dev/stderr, it means the standard
+error (inspired by awk); and similarly for /dev/stdout.  This is
+disabled if POSIXLY_CORRECT is set.
+
+* Added `m' and `M' modifiers to `s' command for multi-line
+matching (Perl-style); in addresses, only `M' works.
+
+* Added `Q' command for `silent quit'; added ability to pass
+an exit code from a sed script to the caller.
+
+* Added `T' command for `branch if failed'.
+
+* Added `v' command, which is a do-nothing intended to fail on
+seds that do not support GNU sed 4.0's extensions.
+
+----------------------------------------------------------------------------
+Sed 3.02.80
+
+* Started new version nomenclature for pre-3.03 releases.  (I'm being
+pessimistic in assuming that .90 won't give me enough breathing room.)
+
+* Bug fixes: the regncomp()/regnexec() interfaces proved to be inadequate to
+properly handle expressions such as "s/\</#/g".  Re-abstracted the regex
+code in the sed/ tree, and now use the re_search_2() interface to the GNU
+regex routines.  This change also fixed a bug where /./ did not match the
+NUL character.  Had the glibc folk fix a bug in lib/regex.c where
+'s/0*\([0-9][0-9]\)/X\1X/' failed to match on input "002".
+
+* Added new command-line options:
+  -u, --unbuffered
+    Do not attempt to read-ahead more than required; do not buffer stdout.
+  -l N, --line-length=N
+    Specify the desired line-wrap length for the `l' command.
+    A length of "0" means "never wrap".
+
+* New internationalization translations added: fr ru de it el sk pt_BR sv
+(plus nl from 3.02a).
+
+* The s/// command now understands the following escapes
+(in both halves):
+	\a	an "alert" (BEL)
+	\f	a form-feed
+	\n	a newline
+	\r	a carriage-return
+	\t	a horizontal tab
+	\v	a vertical tab
+	\oNNN	a character with the octal value NNN
+	\dNNN	a character with the decimal value NNN
+	\xNN	a character with the hexadecimal value NN
+This behavior is disabled if POSIXLY_CORRECT is set, at least for the
+time being (until I can be convinced that this behavior does not violate
+the POSIX standard).  (Incidentally, \b (backspace) was omitted because
+of the conflict with the existing "word boundary" meaning. \ooo octal
+format was omitted because of the conflict with backreference syntax.)
+
+* If POSIXLY_CORRECT is set, the empty RE // now is the null match
+instead of "repeat the last REmatch".  As far as I can tell
+this behavior is mandated by POSIX, but it would break too many
+legacy sed scripts to blithely change GNU sed's default behavior.
+
+----------------------------------------------------------------------------
+Sed 3.02a
+
+* Added internationalization support, and an initial (already out of date)
+set of Dutch message translations (both provided by Erick Branderhorst).
+
+* Added support for scripts like:
+ sed -e 1ifoo -e '$abar'
+(note no need for \ <newline> after a, i, and c commands).
+Also, conditionally (on NO_INPUT_INDENT) added
+experimental support for skipping leading whitespace on
+each {a,i,c} input line.
+
+* Added addressing of the form:
+ /foo/,+5 p (print from foo to 5th line following)
+ /foo/,~5 p (print from foo to next line whose line number is a multiple of 5)
+The first address of these can be any of the previously existing
+addressing types; the +N and ~N forms are only allowed as the
+second address of a range.
+
+* Added support for pseudo-address "0" as the first address in an
+address-range, simplifying scripts which happen to match the end
+address on the first line of input.  For example, a script
+which deletes all lines from the beginning of the file to the
+first line which contains "foo" is now simply "sed 0,/foo/d",
+whereas before one had to go through contortions to deal with
+the possibility that "foo" might appear on the first line of
+the input.
+
+* Made NUL characters in regexps work "correctly" --- i.e., a NUL
+in a RE matches a NUL; it does not prematurely terminate the RE.
+(This only works in -f scripts, as the POSIX.1 exec*() interface
+only passes NUL-terminated strings, and so sed will only be able
+to see up to the first NUL in any -e scriptlet.)
+
+* Wherever a `;' is accepted as a command terminator, also allow a `}'
+or a `#' to appear.  (This allows for less cluttered-looking scripts.)
+
+* Lots of internal changes that are only relevant to source junkies
+and development testing.  Some of which might cause imperceptible
+performance improvements.
+
+----------------------------------------------------------------------------
+Sed 3.02
+
+* Fixed a bug in the parsing of character classes (e.g., /[[:space:]]/).
+Corrected an omission in djgpp/Makefile.am and an improper dependency
+in testsuite/Makefile.am.
+
+----------------------------------------------------------------------------
+Sed 3.01
+
+* This version of sed mainly contains bug fixes and portability
+enhancements, plus performance enhancements related to sed's handling
+of input files.  Due to excess performance penalties, I have reverted
+(relative to 3.00) to using regex.c instead of the rx package for
+regular expression handling, at the expense of losing true POSIX.2
+BRE compatibility.  However, performance related to regular expression
+handling *still* needs a fair bit of work.
+
+* One new feature has been added: regular expressions may be followed
+with an "I" directive ("i" was taken [the "i"nsert command]) to
+indicate that the regexp should be matched in a case-insensitive
+manner.  Also of note are a new organization to the source code,
+new documentation, and a new maintainer.
+
+----------------------------------------------------------------------------
+Sed 3.0
+
+* This version of sed passes the new test-suite donated by
+Jason Molenda.
+
+* Overall performance has been improved in the following sense: Sed 3.0
+is often slightly slower than sed 2.05.  On a few scripts, though, sed
+2.05 was so slow as to be nearly useless or to use up unreasonable
+amounts of memory.  These problems have been fixed and in such cases,
+sed 3.0 should have acceptable performance.
Index: /tags/kBuild-0.1.4/src/sed/README
===================================================================
--- /tags/kBuild-0.1.4/src/sed/README	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/README	(revision 1780)
@@ -0,0 +1,13 @@
+This is the GNU implementation of sed, the Unix stream editor.
+
+See the NEWS file for a brief summary and the ChangeLog for 
+more detailed descriptions of changes.
+
+See the file INSTALL for generic compilation and installation
+instructions.
+
+See the file BUGS for instructions about reporting bugs.
+
+The file README.boot gives instructions for making a "bootstrap"
+version of sed on systems which lack any pre-existing and working
+version of sed.
Index: /tags/kBuild-0.1.4/src/sed/README-alpha
===================================================================
--- /tags/kBuild-0.1.4/src/sed/README-alpha	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/README-alpha	(revision 1780)
@@ -0,0 +1,8 @@
+This is an alpha version of GNU sed.  Please try it on a wide
+range of scripts (especially configure scripts) and submit
+bug reports to bonzini@gnu.org.
+
+Thanks,
+
+Paolo Bonzini
+GNU sed maintainer
Index: /tags/kBuild-0.1.4/src/sed/README.boot
===================================================================
--- /tags/kBuild-0.1.4/src/sed/README.boot	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/README.boot	(revision 1780)
@@ -0,0 +1,23 @@
+Because a working sed is a prerequisite for running the ``configure''
+script, I have provided the script ``bootstrap.sh'' which will attempt
+to build a version of sed adequate for running ``configure''.  If it
+fails, edit the ``config.h'' file that was created according to the
+comments found therein, and then try running ``bootstrap.sh'' again.
+
+The bootstrap build is quite likely to babble on and on with
+various compiler warnings.  You may want to tell bootstrap.sh
+how to invoke your compiler with warnings disabled.  For example,
+with a Bourne-like shell and gcc one could use:
+  $ CC='gcc -w' sh bootstrap.sh
+or with a csh-like shell, one could try:
+  % env CC='gcc -w' sh bootstrap.sh
+
+Once you get a working version of sed, temporarily install sed/sed
+somewhere in your $PATH, and then really re-build the normal way
+(starting with ``sh configure''); the bootstrap version is almost
+certainly more crippled than it needs to be on your machine.
+
+I don't much care to hear about any bugs in ``bootstrap'' versions
+of sed beyond those which actually keep the ``bootstrap'' version from
+building, or sed's configure script from running properly.  I am
+especially uninterested in compiler warnings from the bootstrap build.
Index: /tags/kBuild-0.1.4/src/sed/THANKS
===================================================================
--- /tags/kBuild-0.1.4/src/sed/THANKS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/THANKS	(revision 1780)
@@ -0,0 +1,49 @@
+Akim Demaille <akim@epita.fr>
+Alan Modra <alan@spri.levels.unisa.edu.au>
+Arnold Robbins <arnold@skeeve.com>
+Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Andrew Herbert <andrew@werple.apana.org.au>
+Bruno Haible <haible@ilog.fr>
+Chip Salzenberg <chip@fin.uucp>
+Chris Weber <weber@bucknell.edu>
+David Eckelkamp <eckelkamp@mcc.com>
+David J. MacKenzie <djm@nutrimat>
+David Schmidt <davids@isc-br.isc-br.com>
+Dietrich Kappe <kap1@tao.cpe.uchicago.edu>
+Doug McIlroy <doug@research.att.com>
+Eero Hakkinen <eero17@bigfoot.com>
+Eli Zaretskii <eliz@is.elta.co.il>
+Eric Pement <epement@moody.edu>
+Erick Branderhorst <Erick.Branderhorst@asml.nl>
+Francois Pinard <pinard@iro.umontreal.ca>
+Gaumond Pierre <gaumondp@ERE.UMontreal.CA>
+Greg Ubben <gsu@romulus.ncsc.mil>
+Isamu Hasegawa <isamu@yamato.ibm.com>
+J.T. Conklin <jtc@gain.com>
+Jakub Jelinek <jakub@redhat.com>
+Jason Molenda <crash@cygnus.com>
+Jim Meyering <meyering@ascend.com>
+Laurent Vogel <lvl@club-internet.fr>
+Karl Berry <karl@freefriends.org>
+Karl Heuer <kwzh@gnu.org>
+Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Kevin Buettner <kev@cujo.geg.mot.com>
+Maciej W. Rozycki <macro@linux-mips.org>
+Mark Kettenis <kettenis@phys.uva.nl>
+Michael De La Rue <delarue@NTCCSC01WA.ntc.nokia.com>
+Michel de Ruiter <mdruiter@cs.vu.nl>
+Paul Eggert <eggert@twinsun.com>
+Robert A Bruce <rab@allspice.berkeley.edu>
+Ronnie Glasscock <Ronnie.N.Glasscock@bridge.bellsouth.com>
+Simon Taylor <simon@unisolve.com.au>
+Stepan Kasal <kasal@ucw.cz>
+Stephen Davis <stephend@ksr.com>
+Steve Ingram <si@maps-r-us.com>
+Tapani Tarvainen <tarvaine@tukki.jyu.fi>
+Timothy J Luoma <luomat@peak.org>
+Tom R.Hageman <tom@basil.icce.rug.nl>
+Ulrich Drepper <drepper@redhat.com>
+Vladimir Volovich <vvv@vvv.vsu.ru>
+Wichert Akkerman <wakkerma@debian.org>
+
+And the GNU translation teams.
Index: /tags/kBuild-0.1.4/src/sed/aclocal.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/aclocal.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/aclocal.m4	(revision 1780)
@@ -0,0 +1,875 @@
+# generated automatically by aclocal 1.9.5 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# 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.
+
+# Copyright (C) 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION so it can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+	 [AM_AUTOMAKE_VERSION([1.9.5])])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 7
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # So let's grep whole file.
+  if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+    dirpart=`AS_DIRNAME("$mf")`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`AS_DIRNAME(["$file"])`
+    AS_MKDIR_P([$dirpart/$fdir])
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONFIG_HEADER is obsolete.  It has been replaced by AC_CONFIG_HEADERS.
+AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 12
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.58])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+              [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+	      		     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_CC],
+                          defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_CXX],
+                          defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $1 | $1:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
+#
+# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
+# created by `make install' are always world readable, even if the
+# installer happens to have an overly restrictive umask (e.g. 077).
+# This was a mistake.  There are at least two reasons why we must not
+# use `-m 0755':
+#   - it causes special bits like SGID to be ignored,
+#   - it may be too restrictive (some setups expect 775 directories).
+#
+# Do not use -m 0755 and let people choose whatever they expect by
+# setting umask.
+#
+# We cannot accept any implementation of `mkdir' that recognizes `-p'.
+# Some implementations (such as Solaris 8's) are not thread-safe: if a
+# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
+# concurrently, both version can detect that a/ is missing, but only
+# one can create it and the other will error out.  Consequently we
+# restrict ourselves to GNU make (using the --version option ensures
+# this.)
+AC_DEFUN([AM_PROG_MKDIR_P],
+[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+  # We used to keeping the `.' as first argument, in order to
+  # allow $(mkdir_p) to be used without argument.  As in
+  #   $(mkdir_p) $(somedir)
+  # where $(somedir) is conditionally defined.  However this is wrong
+  # for two reasons:
+  #  1. if the package is installed by a user who cannot write `.'
+  #     make install will fail,
+  #  2. the above comment should most certainly read
+  #     $(mkdir_p) $(DESTDIR)$(somedir)
+  #     so it does not work when $(somedir) is undefined and
+  #     $(DESTDIR) is not.
+  #  To support the latter case, we have to write
+  #     test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+  #  so the `.' trick is pointless.
+  mkdir_p='mkdir -p --'
+else
+  # On NextStep and OpenStep, the `mkdir' command does not
+  # recognize any option.  It will interpret all options as
+  # directories to create, and then abort because `.' already
+  # exists.
+  for d in ./-p ./--version;
+  do
+    test -d $d && rmdir $d
+  done
+  # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+  if test -f "$ac_aux_dir/mkinstalldirs"; then
+    mkdir_p='$(mkinstalldirs)'
+  else
+    mkdir_p='$(install_sh) -d'
+  fi
+fi
+AC_SUBST([mkdir_p])])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([config/codeset.m4])
+m4_include([config/getline.m4])
+m4_include([config/gettext-ver.m4])
+m4_include([config/gettext.m4])
+m4_include([config/glibc21.m4])
+m4_include([config/iconv.m4])
+m4_include([config/lcmessage.m4])
+m4_include([config/lib-ld.m4])
+m4_include([config/lib-link.m4])
+m4_include([config/lib-prefix.m4])
+m4_include([config/progtest.m4])
+m4_include([config/stdbool.m4])
+m4_include([config/strverscmp.m4])
Index: /tags/kBuild-0.1.4/src/sed/basicdefs.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/basicdefs.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/basicdefs.h	(revision 1780)
@@ -0,0 +1,207 @@
+/*  GNU SED, a batch stream editor.
+    Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef BASICDEFS_H
+#define BASICDEFS_H
+
+#if defined(_AIX)
+#pragma alloca
+#else
+# if !defined(alloca)           /* predefined by HP cc +Olibcalls */
+#  ifdef __GNUC__
+#   define alloca(size) __builtin_alloca(size)
+#  else
+#   if HAVE_ALLOCA_H
+#    include <alloca.h>
+#   else
+#    if defined(__hpux)
+        void *alloca ();
+#    else
+#     if !defined(__OS2__) && !defined(WIN32)
+	char *alloca ();
+#     else
+#      include <malloc.h>       /* OS/2 defines alloca in here */
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+#ifdef HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+#ifdef HAVE_WCTYPE_H
+# include <wctype.h>
+#endif
+
+
+#ifdef BOOTSTRAP
+# define false 0
+# define true 1
+# define bool unsigned
+# define __bool_true_false_are_defined 1
+#else
+# if HAVE_STDBOOL_H
+#  include <stdbool.h>
+# endif
+#endif
+
+#if ENABLE_NLS
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+# define ngettext(sing, plur, n) ((n) == 1 ? (sing) : (plur))
+#endif
+#define _(String) gettext(String)
+
+#ifdef gettext_noop
+# define N_(String) gettext_noop(String)
+#else
+# define N_(String) (String)
+#endif
+
+/* type countT is used to keep track of line numbers, etc. */
+typedef unsigned long countT;
+
+/* Oftentimes casts are used as an ugly hack to silence warnings
+ * from the compiler.  However, sometimes those warnings really
+ * do point to something worth avoiding.  I define this
+ * dummy marker to make searching for them with a text editor
+ * much easier, in case I want to verify that they are all
+ * legitimate.  It is defined in the way it is so that it is
+ * easy to disable all casts so that the compiler (or lint)
+ * can tell me potentially interesting things about what would
+ * happen to the code without the explicit casts.
+ */
+#ifdef LOUD_LINT
+# define CAST(x)
+#else
+# define CAST(x) (x)
+#endif
+
+
+/* Can the compiler grok function prototypes? */
+#if (defined __STDC__ && __STDC__-0) || defined __GNUC__ || defined __SUNPRO_C || __PROTOTYPES
+# define P_(s)		s
+#else
+# define P_(s)		()
+#endif
+
+/* (VOID *) is the generic pointer type; some ancient compilers
+   don't know about (void *), and typically use (char *) instead.
+   VCAST() is used to cast to and from (VOID *)s --- but if the
+   compiler *does* support (void *) make this a no-op, so that
+   the compiler can detect if we omitted an essential function
+   declaration somewhere.
+ */
+#ifndef VOID
+# define VOID		void
+# define VCAST(t)	
+#else
+# define VCAST(t)	(t)
+#endif
+
+/* some basic definitions to avoid undue promulgating of VCAST ugliness */
+#define MALLOC(n,t)	 (VCAST(t *)ck_malloc((n)*sizeof(t)))
+#define REALLOC(x,n,t)	 (VCAST(t *)ck_realloc(VCAST(VOID *)(x),(n)*sizeof(t)))
+#define MEMDUP(x,n,t)	 (VCAST(t *)ck_memdup(VCAST(VOID *)(x),(n)*sizeof(t)))
+#define FREE(x)		 (ck_free(VCAST(VOID *)x))
+#define MEMCPY(d,s,l)	 (memcpy(VCAST(VOID *)(d),VCAST(const VOID *)(s),l))
+#define MEMMOVE(d,s,l)	 (memmove(VCAST(VOID *)(d),VCAST(const VOID *)(s),l))
+#define OB_MALLOC(o,n,t) (VCAST(t *)obstack_alloc(o,(n)*sizeof(t)))
+
+#define obstack_chunk_alloc  ck_malloc
+#define obstack_chunk_free   ck_free
+
+
+#ifdef HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#ifndef HAVE_MEMMOVE
+# ifndef memmove
+   /* ../lib/libsed.a provides a memmove() if the system doesn't.
+      Here is where we declare its return type; we don't prototype
+      it because that sometimes causes problems when we're running in
+      bootstrap mode on a system which really does support memmove(). */
+   extern VOID *memmove();
+# endif
+#endif
+
+#ifndef HAVE_MEMCPY
+# ifndef memcpy
+#  define memcpy(d, s, n)	memmove(d, s, n)
+# endif
+#endif
+
+#ifndef HAVE_STRERROR
+ extern char *strerror P_((int e));
+#endif
+
+
+/* handle misdesigned <ctype.h> macros (snarfed from lib/regex.c) */
+/* Jim Meyering writes:
+
+   "... Some ctype macros are valid only for character codes that
+   isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+   using /bin/cc or gcc but without giving an ansi option).  So, all
+   ctype uses should be through macros like ISPRINT...  If
+   STDC_HEADERS is defined, then autoconf has verified that the ctype
+   macros don't need to be guarded with references to isascii. ...
+   Defining isascii to 1 should let any compiler worth its salt
+   eliminate the && through constant folding."
+   Solaris defines some of these symbols so we must undefine them first. */
+
+#undef ISASCII
+#if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+# define ISASCII(c) 1
+#else
+# define ISASCII(c) isascii(c)
+#endif
+
+#if defined isblank || defined HAVE_ISBLANK
+# define ISBLANK(c) (ISASCII (c) && isblank (c))
+#else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+
+#undef ISPRINT
+#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+#define ISALNUM(c) (ISASCII (c) && isalnum (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+#define ISLOWER(c) (ISASCII (c) && islower (c))
+#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+#ifndef initialize_main
+# ifdef __EMX__
+#  define initialize_main(argcp, argvp) \
+  { _response(argcp, argvp); _wildcard(argcp, argvp); }
+# else /* NOT __EMX__ */
+#  define initialize_main(argcp, argvp)
+# endif
+#endif
+
+#endif /*!BASICDEFS_H*/
Index: /tags/kBuild-0.1.4/src/sed/bootstrap.sh
===================================================================
--- /tags/kBuild-0.1.4/src/sed/bootstrap.sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/bootstrap.sh	(revision 1780)
@@ -0,0 +1,82 @@
+#! /bin/sh
+
+# edit this to taste; note that you can also override via the environment:
+case "$CC" in
+  "") CC=cc
+esac
+
+if test -f config.h; then :; else
+  echo "Creating basic config.h..."
+  cat >config.h <<'END_OF_CONFIG_H'
+/* A bootstrap version of config.h, for systems which can't
+   auto-configure due to a lack of a working sed.  If you are on
+   a sufficiently odd machine you may need to hand-tweak this file.
+
+   Regardless, once you get a working version of sed you really should
+   re-build starting with a run of "configure", as the bootstrap
+   version is almost certainly more crippled than it needs to be on
+   your machine.
+*/
+
+#define PACKAGE "sed"
+#define VERSION "4.1.5-boot"
+#define SED_FEATURE_VERSION "4.1"
+#define BOOTSTRAP 1
+
+/* Define if your compiler/headers don't support const. */
+#undef const
+
+/* Undefine if headers have conflicting definition.  */
+#define mbstate_t int
+
+/* Toggle if you encounter errors in lib/mkstemp.c.  */
+#define HAVE_UNISTD_H
+#define HAVE_FCNTL_H
+#undef HAVE_SYS_FILE_H
+#undef HAVE_IO_H
+
+/* Undefine if <stdio.h> or <sys/types.h> has conflicting definition.  */
+#define size_t unsigned
+#define ssize_t int
+
+/* If your antique compiler doesn't grok ``void *'', then #define VOID char */
+#undef VOID
+
+
+/* All other config.h.in options intentionally omitted.  Report as a
+   bug if you need extra "#define"s in here. */
+END_OF_CONFIG_H
+fi
+
+# tell the user what we're doing from here on...
+set -x -e
+
+# the ``|| exit 1''s are for fail-stop; set -e doesn't work on some systems
+
+rm -f lib/*.o sed/*.o sed/sed
+cd lib || exit 1
+rm -f regex.h
+cp regex_.h regex.h
+${CC} -DHAVE_CONFIG_H -I.. -I. -c alloca.c
+${CC} -DHAVE_CONFIG_H -I.. -I. -c getline.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c getopt.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c getopt1.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c memchr.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c memcmp.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c memmove.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c mkstemp.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c strverscmp.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c obstack.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c regex.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c strerror.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c utils.c || exit 1
+
+cd ../sed || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c sed.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c fmt.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c compile.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c execute.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c mbcs.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c regexp.c || exit 1
+
+${CC} -o sed *.o ../lib/*.o || exit 1
Index: /tags/kBuild-0.1.4/src/sed/bootstrap.sh.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/bootstrap.sh.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/bootstrap.sh.in	(revision 1780)
@@ -0,0 +1,82 @@
+#! /bin/sh
+
+# edit this to taste; note that you can also override via the environment:
+case "$CC" in
+  "") CC=cc
+esac
+
+if test -f config.h; then :; else
+  echo "Creating basic config.h..."
+  cat >config.h <<'END_OF_CONFIG_H'
+/* A bootstrap version of config.h, for systems which can't
+   auto-configure due to a lack of a working sed.  If you are on
+   a sufficiently odd machine you may need to hand-tweak this file.
+
+   Regardless, once you get a working version of sed you really should
+   re-build starting with a run of "configure", as the bootstrap
+   version is almost certainly more crippled than it needs to be on
+   your machine.
+*/
+
+#define PACKAGE "sed"
+#define VERSION "@VERSION@-boot"
+#define SED_FEATURE_VERSION "@SED_FEATURE_VERSION@"
+#define BOOTSTRAP 1
+
+/* Define if your compiler/headers don't support const. */
+#undef const
+
+/* Undefine if headers have conflicting definition.  */
+#define mbstate_t int
+
+/* Toggle if you encounter errors in lib/mkstemp.c.  */
+#define HAVE_UNISTD_H
+#define HAVE_FCNTL_H
+#undef HAVE_SYS_FILE_H
+#undef HAVE_IO_H
+
+/* Undefine if <stdio.h> or <sys/types.h> has conflicting definition.  */
+#define size_t unsigned
+#define ssize_t int
+
+/* If your antique compiler doesn't grok ``void *'', then #define VOID char */
+#undef VOID
+
+
+/* All other config.h.in options intentionally omitted.  Report as a
+   bug if you need extra "#define"s in here. */
+END_OF_CONFIG_H
+fi
+
+# tell the user what we're doing from here on...
+set -x -e
+
+# the ``|| exit 1''s are for fail-stop; set -e doesn't work on some systems
+
+rm -f lib/*.o sed/*.o sed/sed
+cd lib || exit 1
+rm -f regex.h
+cp regex_.h regex.h
+${CC} -DHAVE_CONFIG_H -I.. -I. -c alloca.c
+${CC} -DHAVE_CONFIG_H -I.. -I. -c getline.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c getopt.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c getopt1.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c memchr.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c memcmp.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c memmove.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c mkstemp.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c strverscmp.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c obstack.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c regex.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c strerror.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -c utils.c || exit 1
+
+cd ../sed || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c sed.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c fmt.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c compile.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c execute.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c mbcs.c || exit 1
+${CC} -DHAVE_CONFIG_H -I.. -I. -I../lib -c regexp.c || exit 1
+
+${CC} -o sed *.o ../lib/*.o || exit 1
Index: /tags/kBuild-0.1.4/src/sed/config.h.darwin
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config.h.darwin	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config.h.darwin	(revision 1780)
@@ -0,0 +1,374 @@
+/* config.h.  Generated by configure.  */
+/* config_h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define to 1 if you have the `bcopy' function. */
+#define HAVE_BCOPY 1
+
+/* Define to 1 if you have the `btowc' function. */
+#define HAVE_BTOWC 1
+
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#define HAVE_FCHMOD 1
+
+/* Define to 1 if you have the `fchown' function. */
+#define HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+#define HAVE_FEOF_UNLOCKED 1
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+/* #undef HAVE_FGETS_UNLOCKED */
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+#define HAVE_GETC_UNLOCKED 1
+
+/* Define to 1 if you have the `getegid' function. */
+#define HAVE_GETEGID 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `isatty' function. */
+#define HAVE_ISATTY 1
+
+/* Define to 1 if you have the `isblank' function. */
+#define HAVE_ISBLANK 1
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if you have the `regex' library (-lregex). */
+/* #undef HAVE_LIBREGEX */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#define HAVE_MBRTOWC 1
+
+/* Define to 1 if <wchar.h> declares mbstate_t. */
+#define HAVE_MBSTATE_T 1
+
+/* Define to 1 if you have the <mcheck.h> header file. */
+/* #undef HAVE_MCHECK_H */
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mempcpy' function. */
+/* #undef HAVE_MEMPCPY */
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define to 1 if libc includes obstacks. */
+/* #undef HAVE_OBSTACK */
+
+/* Define to 1 if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+/* #undef HAVE_REGEX_H */
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `stpcpy' function. */
+#define HAVE_STPCPY 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strverscmp' function. */
+/* #undef HAVE_STRVERSCMP */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#define HAVE_WCRTOMB 1
+
+/* Define to 1 if you have the `wcscoll' function. */
+#define HAVE_WCSCOLL 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to 1 if you have the `__argz_count' function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define to 1 if you have the `__argz_next' function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST const
+
+/* Name of package */
+#define PACKAGE "sed"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bonzini@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "sed"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "sed 4.1.5"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "sed"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.1.5"
+
+/* Define to the version of GNU sed whose features are supported by this sed.
+   */
+#define SED_FEATURE_VERSION "4.1"
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "4.1.5"
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Include BSD functions in regex, used by the testsuite */
+#define _REGEX_RE_COMP 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
Index: /tags/kBuild-0.1.4/src/sed/config.h.freebsd
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config.h.freebsd	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config.h.freebsd	(revision 1780)
@@ -0,0 +1,374 @@
+/* config.h.  Generated by configure.  */
+/* config_h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define to 1 if you have the `bcopy' function. */
+#define HAVE_BCOPY 1
+
+/* Define to 1 if you have the `btowc' function. */
+#define HAVE_BTOWC 1
+
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#define HAVE_FCHMOD 1
+
+/* Define to 1 if you have the `fchown' function. */
+#define HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+#define HAVE_FEOF_UNLOCKED 1
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+/* #undef HAVE_FGETS_UNLOCKED */
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+#define HAVE_GETC_UNLOCKED 1
+
+/* Define to 1 if you have the `getegid' function. */
+#define HAVE_GETEGID 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `isatty' function. */
+#define HAVE_ISATTY 1
+
+/* Define to 1 if you have the `isblank' function. */
+#define HAVE_ISBLANK 1
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if you have the `regex' library (-lregex). */
+/* #undef HAVE_LIBREGEX */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#define HAVE_MBRTOWC 1
+
+/* Define to 1 if <wchar.h> declares mbstate_t. */
+#define HAVE_MBSTATE_T 1
+
+/* Define to 1 if you have the <mcheck.h> header file. */
+/* #undef HAVE_MCHECK_H */
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mempcpy' function. */
+/* #undef HAVE_MEMPCPY */
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define to 1 if libc includes obstacks. */
+/* #undef HAVE_OBSTACK */
+
+/* Define to 1 if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+/* #undef HAVE_REGEX_H */
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `stpcpy' function. */
+#define HAVE_STPCPY 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strverscmp' function. */
+/* #undef HAVE_STRVERSCMP */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#define HAVE_WCRTOMB 1
+
+/* Define to 1 if you have the `wcscoll' function. */
+#define HAVE_WCSCOLL 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to 1 if you have the `__argz_count' function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define to 1 if you have the `__argz_next' function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST const
+
+/* Name of package */
+#define PACKAGE "sed"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bonzini@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "sed"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "sed 4.1.5"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "sed"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.1.5"
+
+/* Define to the version of GNU sed whose features are supported by this sed.
+   */
+#define SED_FEATURE_VERSION "4.1"
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "4.1.5"
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Include BSD functions in regex, used by the testsuite */
+#define _REGEX_RE_COMP 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
Index: /tags/kBuild-0.1.4/src/sed/config.h.linux
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config.h.linux	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config.h.linux	(revision 1780)
@@ -0,0 +1,374 @@
+/* config.h.  Generated by configure.  */
+/* config_h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <argz.h> header file. */
+#define HAVE_ARGZ_H 1
+
+/* Define to 1 if you have the `bcopy' function. */
+#define HAVE_BCOPY 1
+
+/* Define to 1 if you have the `btowc' function. */
+#define HAVE_BTOWC 1
+
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#define HAVE_FCHMOD 1
+
+/* Define to 1 if you have the `fchown' function. */
+#define HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+#define HAVE_FEOF_UNLOCKED 1
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+#define HAVE_FGETS_UNLOCKED 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+#define HAVE_GETC_UNLOCKED 1
+
+/* Define to 1 if you have the `getegid' function. */
+#define HAVE_GETEGID 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `isatty' function. */
+#define HAVE_ISATTY 1
+
+/* Define to 1 if you have the `isblank' function. */
+#define HAVE_ISBLANK 1
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if you have the `regex' library (-lregex). */
+/* #undef HAVE_LIBREGEX */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#define HAVE_MBRTOWC 1
+
+/* Define to 1 if <wchar.h> declares mbstate_t. */
+#define HAVE_MBSTATE_T 1
+
+/* Define to 1 if you have the <mcheck.h> header file. */
+#define HAVE_MCHECK_H 1
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mempcpy' function. */
+#define HAVE_MEMPCPY 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define to 1 if libc includes obstacks. */
+#define HAVE_OBSTACK 1
+
+/* Define to 1 if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+/* #undef HAVE_REGEX_H */
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `stpcpy' function. */
+#define HAVE_STPCPY 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strverscmp' function. */
+#define HAVE_STRVERSCMP 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#define HAVE_WCRTOMB 1
+
+/* Define to 1 if you have the `wcscoll' function. */
+#define HAVE_WCSCOLL 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to 1 if you have the `__argz_count' function. */
+#define HAVE___ARGZ_COUNT 1
+
+/* Define to 1 if you have the `__argz_next' function. */
+#define HAVE___ARGZ_NEXT 1
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+#define HAVE___ARGZ_STRINGIFY 1
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST 
+
+/* Name of package */
+#define PACKAGE "sed"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bonzini@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "sed"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "sed 4.1.5"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "sed"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.1.5"
+
+/* Define to the version of GNU sed whose features are supported by this sed.
+   */
+#define SED_FEATURE_VERSION "4.1"
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "4.1.5"
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Include BSD functions in regex, used by the testsuite */
+#define _REGEX_RE_COMP 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
Index: /tags/kBuild-0.1.4/src/sed/config.h.os2
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config.h.os2	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config.h.os2	(revision 1780)
@@ -0,0 +1,374 @@
+/* config.h.  Generated by configure.  */
+/* config_h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <argz.h> header file. */
+#define HAVE_ARGZ_H 1
+
+/* Define to 1 if you have the `bcopy' function. */
+#define HAVE_BCOPY 1
+
+/* Define to 1 if you have the `btowc' function. */
+#define HAVE_BTOWC 1
+
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#define HAVE_FCHMOD 1
+
+/* Define to 1 if you have the `fchown' function. */
+#define HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+#define HAVE_FEOF_UNLOCKED 1
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+#define HAVE_FGETS_UNLOCKED 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+#define HAVE_GETC_UNLOCKED 1
+
+/* Define to 1 if you have the `getegid' function. */
+#define HAVE_GETEGID 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `isatty' function. */
+#define HAVE_ISATTY 1
+
+/* Define to 1 if you have the `isblank' function. */
+#define HAVE_ISBLANK 1
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if you have the `regex' library (-lregex). */
+/* #undef HAVE_LIBREGEX */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#define HAVE_MBRTOWC 1
+
+/* Define to 1 if <wchar.h> declares mbstate_t. */
+#define HAVE_MBSTATE_T 1
+
+/* Define to 1 if you have the <mcheck.h> header file. */
+/* #undef HAVE_MCHECK_H */
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mempcpy' function. */
+#define HAVE_MEMPCPY 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+/* #undef HAVE_MMAP */
+
+/* Define to 1 if you have the `munmap' function. */
+/* #undef HAVE_MUNMAP */
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define to 1 if libc includes obstacks. */
+#define HAVE_OBSTACK 1
+
+/* Define to 1 if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+/* #undef HAVE_REGEX_H */
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `stpcpy' function. */
+#define HAVE_STPCPY 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strverscmp' function. */
+#define HAVE_STRVERSCMP 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#define HAVE_WCRTOMB 1
+
+/* Define to 1 if you have the `wcscoll' function. */
+#define HAVE_WCSCOLL 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to 1 if you have the `__argz_count' function. */
+#define HAVE___ARGZ_COUNT 1
+
+/* Define to 1 if you have the `__argz_next' function. */
+#define HAVE___ARGZ_NEXT 1
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+#define HAVE___ARGZ_STRINGIFY 1
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST const
+
+/* Name of package */
+#define PACKAGE "sed"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bonzini@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "sed"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "sed 4.1.5"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "sed"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.1.5"
+
+/* Define to the version of GNU sed whose features are supported by this sed.
+   */
+#define SED_FEATURE_VERSION "4.1"
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "4.1.5"
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Include BSD functions in regex, used by the testsuite */
+#define _REGEX_RE_COMP 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
Index: /tags/kBuild-0.1.4/src/sed/config.h.solaris
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config.h.solaris	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config.h.solaris	(revision 1780)
@@ -0,0 +1,374 @@
+/* config.h.  Generated by configure.  */
+/* config_h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define to 1 if you have the `bcopy' function. */
+#define HAVE_BCOPY 1
+
+/* Define to 1 if you have the `btowc' function. */
+#define HAVE_BTOWC 1
+
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#define HAVE_DOPRNT 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#define HAVE_FCHMOD 1
+
+/* Define to 1 if you have the `fchown' function. */
+#define HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+/* #undef HAVE_FEOF_UNLOCKED */
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+/* #undef HAVE_FGETS_UNLOCKED */
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+#define HAVE_GETC_UNLOCKED 1
+
+/* Define to 1 if you have the `getegid' function. */
+#define HAVE_GETEGID 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `isatty' function. */
+#define HAVE_ISATTY 1
+
+/* Define to 1 if you have the `isblank' function. */
+#define HAVE_ISBLANK 1
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if you have the `regex' library (-lregex). */
+/* #undef HAVE_LIBREGEX */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#define HAVE_MBRTOWC 1
+
+/* Define to 1 if <wchar.h> declares mbstate_t. */
+#define HAVE_MBSTATE_T 1
+
+/* Define to 1 if you have the <mcheck.h> header file. */
+/* #undef HAVE_MCHECK_H */
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mempcpy' function. */
+/* #undef HAVE_MEMPCPY */
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define to 1 if libc includes obstacks. */
+/* #undef HAVE_OBSTACK */
+
+/* Define to 1 if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+/* #undef HAVE_REGEX_H */
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `stpcpy' function. */
+/* #undef HAVE_STPCPY */
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strverscmp' function. */
+/* #undef HAVE_STRVERSCMP */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#define HAVE_WCRTOMB 1
+
+/* Define to 1 if you have the `wcscoll' function. */
+#define HAVE_WCSCOLL 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to 1 if you have the `__argz_count' function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define to 1 if you have the `__argz_next' function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST const
+
+/* Name of package */
+#define PACKAGE "sed"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bonzini@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "sed"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "sed 4.1.5"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "sed"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.1.5"
+
+/* Define to the version of GNU sed whose features are supported by this sed.
+   */
+#define SED_FEATURE_VERSION "4.1"
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "4.1.5"
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Include BSD functions in regex, used by the testsuite */
+#define _REGEX_RE_COMP 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
Index: /tags/kBuild-0.1.4/src/sed/config.h.win
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config.h.win	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config.h.win	(revision 1780)
@@ -0,0 +1,413 @@
+/* config.h.win  Maintaind by hand.  */
+/* config_h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/*#define HAVE_ALLOCA_H 1*/
+
+/* Define to 1 if you have the <argz.h> header file. */
+/*#define HAVE_ARGZ_H 1*/
+
+/* Define to 1 if you have the `bcopy' function. */
+/*#define HAVE_BCOPY 1*/
+
+/* Define to 1 if you have the `btowc' function. */
+/*#define HAVE_BTOWC 1 - bird don't drag in msvcp71.dll */
+
+/* Define to 1 if you have the `bzero' function. */
+/*#define HAVE_BZERO 1*/
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1 /* unused */
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `fchmod' function. */
+/*#define HAVE_FCHMOD 1*/
+
+/* Define to 1 if you have the `fchown' function. */
+/*#define HAVE_FCHOWN 1*/
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+/*#define HAVE_FEOF_UNLOCKED 1*/
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+/*#define HAVE_FGETS_UNLOCKED 1*/
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+/*#define HAVE_GETC_UNLOCKED 1*/
+
+/* Define to 1 if you have the `getegid' function. */
+/*#define HAVE_GETEGID 1*/
+
+/* Define to 1 if you have the `geteuid' function. */
+/*#define HAVE_GETEUID 1*/
+
+/* Define to 1 if you have the `getgid' function. */
+/*#define HAVE_GETGID 1*/
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1 /* unused */
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1 /* unused (intl) */
+
+/* Define if you have the iconv() function. */
+#define HAVE_ICONV 1 /* unused (intl?) */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/*#define HAVE_INTTYPES_H 1*/
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the `isascii' function. */
+/*#define HAVE_ISASCII 1*/ /* don't think we've got this... */
+
+/* Define to 1 if you have the `isatty' function. */
+#define HAVE_ISATTY 1
+
+/* Define to 1 if you have the `isblank' function. */
+/*#define HAVE_ISBLANK 1*/ /* don't think we've got this... */
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+/*#define HAVE_LANGINFO_CODESET 1*/
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1 /* ??? */
+
+/* Define to 1 if you have the `regex' library (-lregex). */
+/* #undef HAVE_LIBREGEX */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+/*#define HAVE_MBRTOWC 1 - bird don't drag in msvcp71.dll */
+
+/* Define to 1 if <wchar.h> declares mbstate_t. */
+#define HAVE_MBSTATE_T 1
+
+/* Define to 1 if you have the <mcheck.h> header file. */
+/*#define HAVE_MCHECK_H 1*/
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mempcpy' function. */
+/*#define HAVE_MEMPCPY 1*/
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+/*#define HAVE_MKSTEMP 1*/
+
+/* Define to 1 if you have a working `mmap' system call. */
+/*#define HAVE_MMAP 1*/
+
+/* Define to 1 if you have the `munmap' function. */
+/*#define HAVE_MUNMAP 1*/
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+/*#define HAVE_NL_TYPES_H 1*/
+
+/* Define to 1 if libc includes obstacks. */
+/*#define HAVE_OBSTACK 1*/
+
+/* Define to 1 if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1 /* ?? */
+
+/* Define to 1 if you have the `popen' function. */
+/*#define HAVE_POPEN 1*/  /** @todo popen */
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+/* #undef HAVE_REGEX_H */
+
+/* Define to 1 if you have the `setenv' function. */
+/*#define HAVE_SETENV 1*/
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+/*#define HAVE_STDBOOL_H 1*/
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `stpcpy' function. */
+/*#define HAVE_STPCPY 1*/
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+#define strcasecmp(__a,__b) stricmp((__a),(__b))
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+/*#define HAVE_STRINGS_H 1*/
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strverscmp' function. */
+/*#define HAVE_STRVERSCMP 1*/
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+/*#define HAVE_SYS_FILE_H 1*/
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+/*#define HAVE_SYS_PARAM_H 1*/
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1 /* ??? */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/*#define HAVE_UNISTD_H 1*/
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+/*#define HAVE_WCRTOMB 1  - bird don't drag in msvcp71.dll */
+
+/* Define to 1 if you have the `wcscoll' function. */
+/*#define HAVE_WCSCOLL 1 - bird don't drag in msvcp71.dll */
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+/*#define HAVE__BOOL 1*/
+
+/* Define to 1 if you have the `__argz_count' function. */
+/*#define HAVE___ARGZ_COUNT 1*/
+
+/* Define to 1 if you have the `__argz_next' function. */
+/*#define HAVE___ARGZ_NEXT 1*/
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+/*#define HAVE___ARGZ_STRINGIFY 1*/
+
+/* Define as const if the declaration of iconv() needs const. */
+/*#define ICONV_CONST */
+
+/* Name of package */
+#define PACKAGE "sed"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bonzini@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "sed"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "sed 4.1.5"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "sed"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.1.5"
+
+/* Define to the version of GNU sed whose features are supported by this sed.
+   */
+#define SED_FEATURE_VERSION "4.1"
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "4.1.5"
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Include BSD functions in regex, used by the testsuite */
+#define _REGEX_RE_COMP 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+#define ssize_t int /* does 14.0 have this? */
+
+/* Additional defines and includes to make it work with the microsoft compiler */
+#ifndef __config_h_included_already
+#define __config_h_included_already
+
+#define HAVE_FCNTL_H 1 /* no idea why this isn't in config.h.in... */
+
+#define VOID void
+#define inline _inline
+#include <io.h> /* isatty ++ */
+#include <sys/stat.h>
+#define S_ISDIR(m)  (((m) & _S_IFMT) == _S_IFDIR)
+#define S_ISREG(m)  (((m) & _S_IFMT) == _S_IFREG)
+#define S_ISLNK(m)  0
+#include <string.h> /* memory.h != string.h it seem even if the code assumes so. */
+
+/* stdbool.h replacement */
+  typedef char bool;
+#define false 0
+#define true 1
+
+#include <wchar.h>
+/* mbsinit isn't defined until 2005 / v8.0. */
+#if _MSC_VER < 1400
+int _inline mbsinit(const mbstate_t *_p)
+{
+    return (_p) == (const mbstate_t *)0 || *(_p) == 0;
+}
+#endif
+
+#if _MSC_VER >= 1400
+/* crtdefs.h contains a typedef int errcode which collides with regcomp.c,
+   try avoid it. */
+#define errcode _errcode
+#endif
+
+/* mkstemp, getline */
+#endif
Index: /tags/kBuild-0.1.4/src/sed/config/codeset.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/codeset.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/codeset.m4	(revision 1780)
@@ -0,0 +1,23 @@
+# codeset.m4 serial AM1 (gettext-0.10.40)
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_LANGINFO_CODESET],
+[
+  AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset,
+    [AC_TRY_LINK([#include <langinfo.h>],
+      [char* cs = nl_langinfo(CODESET);],
+      am_cv_langinfo_codeset=yes,
+      am_cv_langinfo_codeset=no)
+    ])
+  if test $am_cv_langinfo_codeset = yes; then
+    AC_DEFINE(HAVE_LANGINFO_CODESET, 1,
+      [Define if you have <langinfo.h> and nl_langinfo(CODESET).])
+  fi
+])
Index: /tags/kBuild-0.1.4/src/sed/config/config.guess
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/config.guess	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/config.guess	(revision 1780)
@@ -0,0 +1,1450 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+timestamp='2004-08-11'
+
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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, 2002, 2003, 2004
+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
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	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
+	    armeb) machine=armeb-unknown ;;
+	    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
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# 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 ;;
+    amd64:OpenBSD:*:*)
+	echo x86_64-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    cats:OpenBSD:*:*)
+	echo arm-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    luna88k:OpenBSD:*:*)
+    	echo m88k-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 ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit 0 ;;
+    macppc:MirBSD:*:*)
+	echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# 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.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | 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 ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	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 ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit 0 ;;
+    DRS?6000:UNIX_SV:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7 && exit 0 ;;
+	esac ;;
+    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 ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${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 -o $dummy $dummy.c \
+	  && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && exit 0
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-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 -o $dummy $dummy.c && $dummy && exit 0
+		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 -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    # avoid double evaluation of $set_cc_for_build
+	    test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	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 -o $dummy $dummy.c && $dummy && exit 0
+	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*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 ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${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 ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-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*:[34]*)
+	echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+	exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	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 i586-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:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    m32r*: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=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-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 ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	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
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	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:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit 0 ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit 0 ;;
+	i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	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|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	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 ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit 0 ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit 0 ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*: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 ;;
+    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 ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-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:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    *86) UNAME_PROCESSOR=i686 ;;
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-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-?: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 ;;
+    *: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 ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit 0 ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit 0 ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms && exit 0 ;;
+	    I*) echo ia64-dec-vms && exit 0 ;;
+	    V*) echo vax-dec-vms && exit 0 ;;
+	esac
+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 -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# 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:
Index: /tags/kBuild-0.1.4/src/sed/config/config.rpath
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/config.rpath	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/config.rpath	(revision 1780)
@@ -0,0 +1,497 @@
+#! /bin/sh
+# Output a system dependent set of variables, describing how to set the
+# run time search path of shared libraries in an executable.
+#
+#   Copyright 1996-2002 Free Software Foundation, Inc.
+#   Taken from GNU libtool, 2001
+#   Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.
+#
+# The first argument passed to this file is the canonical host specification,
+#    CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+#    CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
+# should be set by the caller.
+#
+# The set of defined variables is at the end of this script.
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+shlibext=
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+wl=
+if test "$GCC" = yes; then
+  wl='-Wl,'
+else
+  case "$host_os" in
+    aix3* | aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+        wl='-Wl,'
+      fi
+      ;;
+    hpux9* | hpux10* | hpux11*)
+      wl='-Wl,'
+      ;;
+    irix5* | irix6*)
+      wl='-Wl,'
+      ;;
+    linux*)
+      echo '__INTEL_COMPILER' > conftest.$ac_ext
+      if $CC -E conftest.$ac_ext >/dev/null | grep __INTEL_COMPILER >/dev/null
+      then
+        :
+      else
+        # Intel icc
+        wl='-Qoption,ld,'
+      fi
+      ;;
+    osf3* | osf4* | osf5*)
+      wl='-Wl,'
+      ;;
+    solaris*)
+      wl='-Wl,'
+      ;;
+    sunos4*)
+      wl='-Qoption ld '
+      ;;
+    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+      if test "x$host_vendor" = xsni; then
+        wl='-LD'
+      else
+        wl='-Wl,'
+      fi
+      ;;
+  esac
+fi
+
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+
+case "$host_os" in
+  cygwin* | mingw* | pw32* )
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+  case "$host_os" in
+    aix3* | aix4* | aix5*)
+      # On AIX, the GNU linker is very broken
+      ld_shlibs=no
+      ;;
+    amigaos*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can use
+      # them.
+      ld_shlibs=no
+      ;;
+    beos*)
+      if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+    cygwin* | mingw* | pw32*)
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      ;;
+    solaris* | sysv5*)
+      if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+        ld_shlibs=no
+      elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+    sunos4*)
+      hardcode_direct=yes
+      ;;
+    *)
+      if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+  esac
+  if test "$ld_shlibs" = yes; then
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+  fi
+else
+  case "$host_os" in
+    aix3*)
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes; then
+        # Neither direct hardcoding nor static linking is supported with a
+        # broken collect2.
+        hardcode_direct=unsupported
+      fi
+      ;;
+    aix4* | aix5*)
+      hardcode_libdir_separator=':'
+      if test "$GCC" = yes; then
+        collect2name=`${CC} -print-prog-name=collect2`
+        if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+        then
+          # We have reworked collect2
+          hardcode_direct=yes
+        else
+          # We have old collect2
+          hardcode_direct=unsupported
+          hardcode_minus_L=yes
+          hardcode_libdir_flag_spec='-L$libdir'
+          hardcode_libdir_separator=
+        fi
+      else
+        hardcode_direct=yes
+      fi
+      if test "$host_cpu" = ia64; then
+        # On IA64, the linker does run time linking by default, so we don't
+        # have to do anything special.
+        aix_use_runtimelinking=no
+      else
+        # Test if we are trying to use run time linking, or normal AIX style linking.
+        # If -brtl is somewhere in LDFLAGS, we need to do run time linking.
+        aix_use_runtimelinking=no
+        for ld_flag in $LDFLAGS; do
+          if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl" ); then
+            aix_use_runtimelinking=yes
+            break
+          fi
+        done
+      fi
+      if test "$aix_use_runtimelinking" = yes; then
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib'
+      else
+        if test "$host_cpu" = ia64; then
+          hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+        else
+          hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib'
+        fi
+      fi
+      ;;
+    amigaos*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      # see comment about different semantics on the GNU ld section
+      ld_shlibs=no
+      ;;
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      libext=lib
+      ;;
+    darwin* | rhapsody*)
+      hardcode_direct=yes
+      ;;
+    freebsd1*)
+      ld_shlibs=no
+      ;;
+    freebsd2.2*)
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      ;;
+    freebsd2*)
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      ;;
+    freebsd*)
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      ;;
+    hpux9* | hpux10* | hpux11*)
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+      hardcode_minus_L=yes # Not in the search PATH, but as the default
+                           # location of the library.
+      ;;
+    irix5* | irix6*)
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+    netbsd*)
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      ;;
+    newsos6)
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+    openbsd*)
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      ;;
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      ;;
+    osf3*)
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+    osf4* | osf5*)
+      if test "$GCC" = yes; then
+        hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+        # Both cc and cxx compiler support -rpath directly
+        hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      hardcode_libdir_separator=:
+      ;;
+    sco3.2v5*)
+      ;;
+    solaris*)
+      hardcode_libdir_flag_spec='-R$libdir'
+      ;;
+    sunos4*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      ;;
+    sysv4)
+      if test "x$host_vendor" = xsno; then
+        hardcode_direct=yes # is this really true???
+      else
+        hardcode_direct=no # Motorola manual says yes, but my tests say they lie
+      fi
+      ;;
+    sysv4.3*)
+      ;;
+    sysv5*)
+      hardcode_libdir_flag_spec=
+      ;;
+    uts4*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      ;;
+    dgux*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+        ld_shlibs=yes
+      fi
+      ;;
+    sysv4.2uw2*)
+      hardcode_direct=yes
+      hardcode_minus_L=no
+      ;;
+    sysv5uw7* | unixware7*)
+      ;;
+    *)
+      ld_shlibs=no
+      ;;
+  esac
+fi
+
+# Check dynamic linker characteristics
+libname_spec='lib$name'
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+case "$host_os" in
+  aix3*)
+    shlibext=so
+    ;;
+  aix4* | aix5*)
+    shlibext=so
+    ;;
+  amigaos*)
+    shlibext=ixlibrary
+    ;;
+  beos*)
+    shlibext=so
+    ;;
+  bsdi4*)
+    shlibext=so
+    sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+    sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+    ;;
+  cygwin* | mingw* | pw32*)
+    case $GCC,$host_os in
+      yes,cygwin*)
+        shlibext=dll.a
+        ;;
+      yes,mingw*)
+        shlibext=dll
+        sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"`
+        ;;
+      yes,pw32*)
+        shlibext=dll
+        ;;
+      *)
+        shlibext=dll
+        ;;
+    esac
+    ;;
+  darwin* | rhapsody*)
+    shlibext=dylib
+    ;;
+  freebsd1*)
+    ;;
+  freebsd*)
+    shlibext=so
+    ;;
+  gnu*)
+    shlibext=so
+    ;;
+  hpux9* | hpux10* | hpux11*)
+    shlibext=sl
+    ;;
+  irix5* | irix6*)
+    shlibext=so
+    case "$host_os" in
+      irix5*)
+        libsuff= shlibsuff=
+        ;;
+      *)
+        case $LD in
+          *-32|*"-32 ") libsuff= shlibsuff= ;;
+          *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 ;;
+          *-64|*"-64 ") libsuff=64 shlibsuff=64 ;;
+          *) libsuff= shlibsuff= ;;
+        esac
+        ;;
+    esac
+    sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+    sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+    ;;
+  linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+    ;;
+  linux-gnu*)
+    shlibext=so
+    ;;
+  netbsd*)
+    shlibext=so
+    ;;
+  newsos6)
+    shlibext=so
+    ;;
+  openbsd*)
+    shlibext=so
+    ;;
+  os2*)
+    libname_spec='$name'
+    shlibext=dll
+    ;;
+  osf3* | osf4* | osf5*)
+    shlibext=so
+    sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+    sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+    ;;
+  sco3.2v5*)
+    shlibext=so
+    ;;
+  solaris*)
+    shlibext=so
+    ;;
+  sunos4*)
+    shlibext=so
+    ;;
+  sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+    shlibext=so
+    case "$host_vendor" in
+      motorola)
+        sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+        ;;
+    esac
+    ;;
+  uts4*)
+    shlibext=so
+    ;;
+  dgux*)
+    shlibext=so
+    ;;
+  sysv4*MP*)
+    if test -d /usr/nec; then
+      shlibext=so
+    fi
+    ;;
+esac
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_sys_lib_search_path_spec=`echo "X$sys_lib_search_path_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_sys_lib_dlsearch_path_spec=`echo "X$sys_lib_dlsearch_path_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+
+sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
+
+# How to pass a linker flag through the compiler.
+wl="$escaped_wl"
+
+# Static library suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally "so").
+shlibext="$shlibext"
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct="$hardcode_direct"
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L="$hardcode_minus_L"
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec="$escaped_sys_lib_search_path_spec"
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec="$escaped_sys_lib_dlsearch_path_spec"
+
+EOF
Index: /tags/kBuild-0.1.4/src/sed/config/config.sub
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/config.sub	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/config.sub	(revision 1780)
@@ -0,0 +1,1552 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+timestamp='2004-06-24'
+
+# 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., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, 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, 2002, 2003, 2004
+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* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+  kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | 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 | -knuth | -cray)
+		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] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32r | m32rle | m68000 | m68k | m88k | mcore \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| msp430 \
+	| ns16k | ns32k \
+	| openrisc | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
+	| strongarm \
+	| tahoe | thumb | tic4x | 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-* | armeb-* | armv*-* \
+	| avr-* \
+	| bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| msp430-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | 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
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	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
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	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
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16c)
+		basic_machine=cr16c-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	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
+		;;
+	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
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	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 | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-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-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`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
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	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
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-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
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	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
+		;;
+	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
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	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 | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparc | sparcv8 | 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
+		;;
+	*-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* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+	      | -ekkobsd* | -kfreebsd* | -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* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -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* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|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-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-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
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-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
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-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
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-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
+		;;
+    c4x-* | tic4x-*)
+        os=-coff
+        ;;
+	# 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
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-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
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-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:
Index: /tags/kBuild-0.1.4/src/sed/config/depcomp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/depcomp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/depcomp	(revision 1780)
@@ -0,0 +1,522 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2004-05-31.23
+
+# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# 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 Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by `PROGRAMS ARGS'.
+  object      Object file output by `PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputing dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit 0
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit 0
+    ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+  "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> $depfile
+    echo >> $depfile
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> $depfile
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
+  tmpdepfile="$stripped.u"
+  if test "$libtool" = yes; then
+    "$@" -Wc,-M
+  else
+    "$@" -M
+  fi
+  stat=$?
+
+  if test -f "$tmpdepfile"; then :
+  else
+    stripped=`echo "$stripped" | sed 's,^.*/,,'`
+    tmpdepfile="$stripped.u"
+  fi
+
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+
+  if test -f "$tmpdepfile"; then
+    outname="$stripped.o"
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+    sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Intel's C compiler understands `-MD -MF file'.  However on
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # ICC 7.0 will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+  # ICC 7.1 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using \ :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+    sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+tru64)
+   # The Tru64 compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+   test "x$dir" = "x$object" && dir=
+   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+   if test "$libtool" = yes; then
+      # Dependencies are output in .lo.d with libtool 1.4.
+      # With libtool 1.5 they are output both in $dir.libs/$base.o.d
+      # and in $dir.libs/$base.o.d and $dir$base.o.d.  We process the
+      # latter, because the former will be cleaned when $dir.libs is
+      # erased.
+      tmpdepfile1="$dir.libs/$base.lo.d"
+      tmpdepfile2="$dir$base.o.d"
+      tmpdepfile3="$dir.libs/$base.d"
+      "$@" -Wc,-MD
+   else
+      tmpdepfile1="$dir$base.o.d"
+      tmpdepfile2="$dir$base.d"
+      tmpdepfile3="$dir$base.d"
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+      exit $stat
+   fi
+
+   if test -f "$tmpdepfile1"; then
+      tmpdepfile="$tmpdepfile1"
+   elif test -f "$tmpdepfile2"; then
+      tmpdepfile="$tmpdepfile2"
+   else
+      tmpdepfile="$tmpdepfile3"
+   fi
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a tab and a space in the [].
+      sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for `:'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  "$@" $dashmflag |
+    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no
+  for arg in "$@"; do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix="`echo $object | sed 's/^.*\././'`"
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E |
+    sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  "$@" || exit $?
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+	set fnord "$@"
+	shift
+	shift
+	;;
+    *)
+	set fnord "$@" "$arg"
+	shift
+	shift
+	;;
+    esac
+  done
+  "$@" -E |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::	\1 \\:p' >> "$depfile"
+  echo "	" >> "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /tags/kBuild-0.1.4/src/sed/config/getline.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/getline.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/getline.m4	(revision 1780)
@@ -0,0 +1,41 @@
+#serial 4
+
+dnl See if there's a working, system-supplied version of the getline function.
+dnl We can't just do AC_REPLACE_FUNCS(getline) because some systems
+dnl have a function by that name in -linet that doesn't have anything
+dnl to do with the function we need.
+AC_DEFUN([AM_FUNC_GETLINE],
+[dnl
+  am_getline_needs_run_time_check=no
+  AC_CHECK_FUNC(getline,
+		dnl Found it in some library.  Verify that it works.
+		am_getline_needs_run_time_check=yes,
+		am_cv_func_working_getline=no)
+  if test $am_getline_needs_run_time_check = yes; then
+    AC_CACHE_CHECK([for working getline function], am_cv_func_working_getline,
+    [echo fooN |tr -d '\012'|tr N '\012' > conftest.data
+    AC_TRY_RUN([
+#    include <stdio.h>
+#    include <sys/types.h>
+#    include <string.h>
+    int main ()
+    { /* Based on a test program from Karl Heuer.  */
+      char *line = NULL;
+      size_t siz = 0;
+      int len;
+      FILE *in = fopen ("./conftest.data", "r");
+      if (!in)
+	return 1;
+      len = getline (&line, &siz, in);
+      exit ((len == 4 && line && strcmp (line, "foo\n") == 0) ? 0 : 1);
+    }
+    ], am_cv_func_working_getline=yes dnl The library version works.
+    , am_cv_func_working_getline=no dnl The library version does NOT work.
+    , am_cv_func_working_getline=no dnl We're cross compiling.
+    )])
+  fi
+
+  if test $am_cv_func_working_getline = no; then
+    AC_LIBOBJ(getline)
+  fi
+])
Index: /tags/kBuild-0.1.4/src/sed/config/gettext-ver.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/gettext-ver.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/gettext-ver.m4	(revision 1780)
@@ -0,0 +1,1 @@
+AC_DEFUN([AM_GNU_GETTEXT_VERSION], [])
Index: /tags/kBuild-0.1.4/src/sed/config/gettext.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/gettext.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/gettext.m4	(revision 1780)
@@ -0,0 +1,523 @@
+# gettext.m4 serial 12 (gettext-0.11)
+dnl Copyright (C) 1995-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
+dnl   Bruno Haible <haible@clisp.cons.org>, 2000-2002.
+
+dnl Macro to add for using GNU gettext.
+
+dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]).
+dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The
+dnl    default (if it is not specified or empty) is 'no-libtool'.
+dnl    INTLSYMBOL should be 'external' for packages with no intl directory,
+dnl    and 'no-libtool' or 'use-libtool' for packages with an intl directory.
+dnl    If INTLSYMBOL is 'use-libtool', then a libtool library
+dnl    $(top_builddir)/intl/libintl.la will be created (shared and/or static,
+dnl    depending on --{enable,disable}-{shared,static} and on the presence of
+dnl    AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library
+dnl    $(top_builddir)/intl/libintl.a will be created.
+dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext
+dnl    implementations (in libc or libintl) without the ngettext() function
+dnl    will be ignored.
+dnl INTLDIR is used to find the intl libraries.  If empty,
+dnl    the value `$(top_builddir)/intl/' is used.
+dnl
+dnl The result of the configuration is one of three cases:
+dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled
+dnl    and used.
+dnl    Catalog format: GNU --> install in $(datadir)
+dnl    Catalog extension: .mo after installation, .gmo in source tree
+dnl 2) GNU gettext has been found in the system's C library.
+dnl    Catalog format: GNU --> install in $(datadir)
+dnl    Catalog extension: .mo after installation, .gmo in source tree
+dnl 3) No internationalization, always use English msgid.
+dnl    Catalog format: none
+dnl    Catalog extension: none
+dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur.
+dnl The use of .gmo is historical (it was needed to avoid overwriting the
+dnl GNU format catalogs when building on a platform with an X/Open gettext),
+dnl but we keep it in order not to force irrelevant filename changes on the
+dnl maintainers.
+dnl
+AC_DEFUN([AM_GNU_GETTEXT],
+[
+  dnl Argument checking.
+  ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], ,
+    [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT
+])])])])])
+  ifelse([$2], [], , [ifelse([$2], [need-ngettext], ,
+    [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT
+])])])
+  define(gt_included_intl, ifelse([$1], [external], [no], [yes]))
+  define(gt_libtool_suffix_prefix, ifelse([$1], [use-libtool], [l], []))
+
+  AC_REQUIRE([AM_PO_SUBDIRS])dnl
+  ifelse(gt_included_intl, yes, [
+    AC_REQUIRE([AM_INTL_SUBDIR])dnl
+  ])
+
+  dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+
+  AC_MSG_CHECKING([whether NLS is requested])
+  dnl Default is enabled NLS
+  AC_ARG_ENABLE(nls,
+    [  --disable-nls           do not use Native Language Support],
+    USE_NLS=$enableval, USE_NLS=yes)
+  AC_MSG_RESULT($USE_NLS)
+  AC_SUBST(USE_NLS)
+
+  ifelse(gt_included_intl, yes, [
+    BUILD_INCLUDED_LIBINTL=no
+    USE_INCLUDED_LIBINTL=no
+  ])
+  LIBINTL=
+  LTLIBINTL=
+  POSUB=
+
+  dnl If we use NLS figure out what method
+  if test "$USE_NLS" = "yes"; then
+    gt_use_preinstalled_gnugettext=no
+    ifelse(gt_included_intl, yes, [
+      AC_MSG_CHECKING([whether included gettext is requested])
+      AC_ARG_WITH(included-gettext,
+        [  --with-included-gettext use the GNU gettext library included here],
+        nls_cv_force_use_gnu_gettext=$withval,
+        nls_cv_force_use_gnu_gettext=no)
+      AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+      nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+      if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+    ])
+        dnl User does not insist on using GNU NLS library.  Figure out what
+        dnl to use.  If GNU gettext is available we use this.  Else we have
+        dnl to fall back to GNU NLS library.
+
+        dnl Add a version number to the cache macros.
+        define([gt_api_version], ifelse([$2], [need-ngettext], 2, 1))
+        define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc])
+        define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl])
+
+        AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc,
+         [AC_TRY_LINK([#include <libintl.h>
+extern int _nl_msg_cat_cntr;],
+            [bindtextdomain ("", "");
+return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr],
+            gt_cv_func_gnugettext_libc=yes,
+            gt_cv_func_gnugettext_libc=no)])
+
+        if test "$gt_cv_func_gnugettext_libc" != "yes"; then
+          dnl Sometimes libintl requires libiconv, so first search for libiconv.
+          ifelse(gt_included_intl, yes, , [
+            AM_ICONV_LINK
+          ])
+          dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL
+          dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv])
+          dnl because that would add "-liconv" to LIBINTL and LTLIBINTL
+          dnl even if libiconv doesn't exist.
+          AC_LIB_LINKFLAGS_BODY([intl])
+          AC_CACHE_CHECK([for GNU gettext in libintl],
+            gt_cv_func_gnugettext_libintl,
+           [gt_save_CPPFLAGS="$CPPFLAGS"
+            CPPFLAGS="$CPPFLAGS $INCINTL"
+            gt_save_LIBS="$LIBS"
+            LIBS="$LIBS $LIBINTL"
+            dnl Now see whether libintl exists and does not depend on libiconv.
+            AC_TRY_LINK([#include <libintl.h>
+extern int _nl_msg_cat_cntr;],
+              [bindtextdomain ("", "");
+return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr],
+              gt_cv_func_gnugettext_libintl=yes,
+              gt_cv_func_gnugettext_libintl=no)
+            dnl Now see whether libintl exists and depends on libiconv.
+            if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then
+              LIBS="$LIBS $LIBICONV"
+              AC_TRY_LINK([#include <libintl.h>
+extern int _nl_msg_cat_cntr;],
+                [bindtextdomain ("", "");
+return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr],
+               [LIBINTL="$LIBINTL $LIBICONV"
+                LTLIBINTL="$LTLIBINTL $LTLIBICONV"
+                gt_cv_func_gnugettext_libintl=yes
+               ])
+            fi
+            CPPFLAGS="$gt_save_CPPFLAGS"
+            LIBS="$gt_save_LIBS"])
+        fi
+
+        dnl If an already present or preinstalled GNU gettext() is found,
+        dnl use it.  But if this macro is used in GNU gettext, and GNU
+        dnl gettext is already preinstalled in libintl, we update this
+        dnl libintl.  (Cf. the install rule in intl/Makefile.in.)
+        if test "$gt_cv_func_gnugettext_libc" = "yes" \
+           || { test "$gt_cv_func_gnugettext_libintl" = "yes" \
+                && test "$PACKAGE" != gettext; }; then
+          gt_use_preinstalled_gnugettext=yes
+        fi
+
+    ifelse(gt_included_intl, yes, [
+        if test "$gt_use_preinstalled_gnugettext" != "yes"; then
+          dnl GNU gettext is not found in the C library.
+          dnl Fall back on included GNU gettext library.
+          nls_cv_use_gnu_gettext=yes
+        fi
+      fi
+
+      if test "$nls_cv_use_gnu_gettext" = "yes"; then
+        dnl Mark actions used to generate GNU NLS library.
+        INTLOBJS="\$(GETTOBJS)"
+        BUILD_INCLUDED_LIBINTL=yes
+        USE_INCLUDED_LIBINTL=yes
+        LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV"
+        LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV"
+        LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
+      fi
+
+      if test "$gt_use_preinstalled_gnugettext" = "yes" \
+         || test "$nls_cv_use_gnu_gettext" = "yes"; then
+        dnl Mark actions to use GNU gettext tools.
+        CATOBJEXT=.gmo
+      fi
+    ])
+
+    if test "$gt_use_preinstalled_gnugettext" = "yes" \
+       || test "$nls_cv_use_gnu_gettext" = "yes"; then
+      AC_DEFINE(ENABLE_NLS, 1,
+        [Define to 1 if translation of program messages to the user's native language
+   is requested.])
+    else
+      USE_NLS=no
+    fi
+  fi
+
+  if test "$USE_NLS" = "yes"; then
+
+    if test "$gt_use_preinstalled_gnugettext" = "yes"; then
+      if test "$gt_cv_func_gnugettext_libintl" = "yes"; then
+        AC_MSG_CHECKING([how to link with libintl])
+        AC_MSG_RESULT([$LIBINTL])
+        AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL])
+      fi
+
+      dnl For backward compatibility. Some packages may be using this.
+      AC_DEFINE(HAVE_GETTEXT, 1,
+       [Define if the GNU gettext() function is already present or preinstalled.])
+      AC_DEFINE(HAVE_DCGETTEXT, 1,
+       [Define if the GNU dcgettext() function is already present or preinstalled.])
+    fi
+
+    dnl We need to process the po/ directory.
+    POSUB=po
+  fi
+
+  ifelse(gt_included_intl, yes, [
+    dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL
+    dnl to 'yes' because some of the testsuite requires it.
+    if test "$PACKAGE" = gettext; then
+      BUILD_INCLUDED_LIBINTL=yes
+    fi
+
+    dnl Make all variables we use known to autoconf.
+    AC_SUBST(BUILD_INCLUDED_LIBINTL)
+    AC_SUBST(USE_INCLUDED_LIBINTL)
+    AC_SUBST(CATOBJEXT)
+    AC_SUBST(INTLOBJS)
+
+    dnl For backward compatibility. Some configure.ins may be using this.
+    nls_cv_header_intl=
+    nls_cv_header_libgt=
+
+    dnl For backward compatibility. Some Makefiles may be using this.
+    DATADIRNAME=share
+    AC_SUBST(DATADIRNAME)
+
+    dnl For backward compatibility. Some Makefiles may be using this.
+    INSTOBJEXT=.mo
+    AC_SUBST(INSTOBJEXT)
+
+    dnl For backward compatibility. Some Makefiles may be using this.
+    GENCAT=gencat
+    AC_SUBST(GENCAT)
+
+    dnl Enable libtool support if the surrounding package wishes it.
+    INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix
+    AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX)
+  ])
+
+  dnl For backward compatibility. Some Makefiles may be using this.
+  INTLLIBS="$LIBINTL"
+  AC_SUBST(INTLLIBS)
+
+  dnl Make all documented variables known to autoconf.
+  AC_SUBST(LIBINTL)
+  AC_SUBST(LTLIBINTL)
+  AC_SUBST(POSUB)
+])
+
+
+dnl Checks for all prerequisites of the po subdirectory,
+dnl except for USE_NLS.
+AC_DEFUN([AM_PO_SUBDIRS],
+[
+  AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+  AC_REQUIRE([AC_PROG_INSTALL])dnl
+  AC_REQUIRE([AM_MKINSTALLDIRS])dnl
+
+  dnl Perform the following tests also if --disable-nls has been given,
+  dnl because they are needed for "make dist" to work.
+
+  dnl Search for GNU msgfmt in the PATH.
+  dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions.
+  dnl The second test excludes FreeBSD msgfmt.
+  AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+    [$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 &&
+     (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
+    :)
+  AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+
+  dnl Search for GNU xgettext 0.11 or newer in the PATH.
+  dnl The first test excludes Solaris xgettext and early GNU xgettext versions.
+  dnl The second test excludes FreeBSD xgettext.
+  AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+    [$ac_dir/$ac_word --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 &&
+     (if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
+    :)
+  dnl Remove leftover from FreeBSD xgettext call.
+  rm -f messages.po
+
+  dnl Search for GNU msgmerge 0.11 or newer in the PATH.
+  AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge,
+    [$ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1], :)
+
+  dnl This could go away some day; the PATH_PROG_WITH_TEST already does it.
+  dnl Test whether we really found GNU msgfmt.
+  if test "$GMSGFMT" != ":"; then
+    dnl If it is no GNU msgfmt we define it as : so that the
+    dnl Makefiles still can work.
+    if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 &&
+       (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then
+      : ;
+    else
+      GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'`
+      AC_MSG_RESULT(
+        [found $GMSGFMT program is not GNU msgfmt; ignore it])
+      GMSGFMT=":"
+    fi
+  fi
+
+  dnl This could go away some day; the PATH_PROG_WITH_TEST already does it.
+  dnl Test whether we really found GNU xgettext.
+  if test "$XGETTEXT" != ":"; then
+    dnl If it is no GNU xgettext we define it as : so that the
+    dnl Makefiles still can work.
+    if $XGETTEXT --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 &&
+       (if $XGETTEXT --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then
+      : ;
+    else
+      AC_MSG_RESULT(
+        [found xgettext program is not GNU xgettext; ignore it])
+      XGETTEXT=":"
+    fi
+    dnl Remove leftover from FreeBSD xgettext call.
+    rm -f messages.po
+  fi
+
+  AC_OUTPUT_COMMANDS([
+    for ac_file in $CONFIG_FILES; do
+      # Support "outfile[:infile[:infile...]]"
+      case "$ac_file" in
+        *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+      esac
+      # PO directories have a Makefile.in generated from Makefile.in.in.
+      case "$ac_file" in */Makefile.in)
+        # Adjust a relative srcdir.
+        ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
+        ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`"
+        ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
+        # In autoconf-2.13 it is called $ac_given_srcdir.
+        # In autoconf-2.50 it is called $srcdir.
+        test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
+        case "$ac_given_srcdir" in
+          .)  top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
+          /*) top_srcdir="$ac_given_srcdir" ;;
+          *)  top_srcdir="$ac_dots$ac_given_srcdir" ;;
+        esac
+        if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then
+          rm -f "$ac_dir/POTFILES"
+          test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES"
+          cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ 	]*\$/d" -e "s,.*,     $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES"
+          # ALL_LINGUAS, POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES depend
+          # on $ac_dir but don't depend on user-specified configuration
+          # parameters.
+          if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
+            # The LINGUAS file contains the set of available languages.
+            if test -n "$ALL_LINGUAS"; then
+              test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
+            fi
+            ALL_LINGUAS_=`sed -e "/^#/d" "$ac_given_srcdir/$ac_dir/LINGUAS"`
+            # Hide the ALL_LINGUAS assigment from automake.
+            eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
+          fi
+          case "$ac_given_srcdir" in
+            .) srcdirpre= ;;
+            *) srcdirpre='$(srcdir)/' ;;
+          esac
+          POFILES=
+          GMOFILES=
+          UPDATEPOFILES=
+          DUMMYPOFILES=
+          for lang in $ALL_LINGUAS; do
+            POFILES="$POFILES $srcdirpre$lang.po"
+            GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
+            UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
+            DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
+          done
+          # CATALOGS depends on both $ac_dir and the user's LINGUAS
+          # environment variable.
+          INST_LINGUAS=
+          if test -n "$ALL_LINGUAS"; then
+            for presentlang in $ALL_LINGUAS; do
+              useit=no
+              if test "%UNSET%" != "$LINGUAS"; then
+                desiredlanguages="$LINGUAS"
+              else
+                desiredlanguages="$ALL_LINGUAS"
+              fi
+              for desiredlang in $desiredlanguages; do
+                # Use the presentlang catalog if desiredlang is
+                #   a. equal to presentlang, or
+                #   b. a variant of presentlang (because in this case,
+                #      presentlang can be used as a fallback for messages
+                #      which are not translated in the desiredlang catalog).
+                case "$desiredlang" in
+                  "$presentlang"*) useit=yes;;
+                esac
+              done
+              if test $useit = yes; then
+                INST_LINGUAS="$INST_LINGUAS $presentlang"
+              fi
+            done
+          fi
+          CATALOGS=
+          if test -n "$INST_LINGUAS"; then
+            for lang in $INST_LINGUAS; do
+              CATALOGS="$CATALOGS $lang.gmo"
+            done
+          fi
+          test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile"
+          sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile"
+          for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do
+            if test -f "$f"; then
+              case "$f" in
+                *.orig | *.bak | *~) ;;
+                *) cat "$f" >> "$ac_dir/Makefile" ;;
+              esac
+            fi
+          done
+        fi
+        ;;
+      esac
+    done],
+   [# Capture the value of obsolete $ALL_LINGUAS because we need it to compute
+    # POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES, CATALOGS. But hide it
+    # from automake.
+    eval 'ALL_LINGUAS''="$ALL_LINGUAS"'
+    # Capture the value of LINGUAS because we need it to compute CATALOGS.
+    LINGUAS="${LINGUAS-%UNSET%}"
+   ])
+])
+
+
+dnl Checks for all prerequisites of the intl subdirectory,
+dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS,
+dnl            USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL.
+AC_DEFUN([AM_INTL_SUBDIR],
+[
+  AC_REQUIRE([AC_PROG_INSTALL])dnl
+  AC_REQUIRE([AM_MKINSTALLDIRS])dnl
+  AC_REQUIRE([AC_PROG_CC])dnl
+  AC_REQUIRE([AC_CANONICAL_HOST])dnl
+  AC_REQUIRE([AC_PROG_RANLIB])dnl
+  AC_REQUIRE([AC_ISC_POSIX])dnl
+  AC_REQUIRE([AC_HEADER_STDC])dnl
+  AC_REQUIRE([AC_C_CONST])dnl
+  AC_REQUIRE([AC_C_INLINE])dnl
+  AC_REQUIRE([AC_TYPE_OFF_T])dnl
+  AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+  AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+  AC_REQUIRE([AC_FUNC_MMAP])dnl
+  AC_REQUIRE([jm_GLIBC21])dnl
+
+  AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \
+stdlib.h string.h unistd.h sys/param.h])
+  AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \
+geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \
+strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next])
+
+  AM_ICONV
+  AM_LANGINFO_CODESET
+  AM_LC_MESSAGES
+
+  dnl intl/plural.c is generated from intl/plural.y. It requires bison,
+  dnl because plural.y uses bison specific features. It requires at least
+  dnl bison-1.26 because earlier versions generate a plural.c that doesn't
+  dnl compile.
+  dnl bison is only needed for the maintainer (who touches plural.y). But in
+  dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put
+  dnl the rule in general Makefile. Now, some people carelessly touch the
+  dnl files or have a broken "make" program, hence the plural.c rule will
+  dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not
+  dnl present or too old.
+  AC_CHECK_PROGS([INTLBISON], [bison])
+  if test -z "$INTLBISON"; then
+    ac_verc_fail=yes
+  else
+    dnl Found it, now check the version.
+    AC_MSG_CHECKING([version of bison])
+changequote(<<,>>)dnl
+    ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'`
+    case $ac_prog_version in
+      '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+      1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*)
+changequote([,])dnl
+         ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+      *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+    esac
+    AC_MSG_RESULT([$ac_prog_version])
+  fi
+  if test $ac_verc_fail = yes; then
+    INTLBISON=:
+  fi
+])
+
+
+AC_DEFUN([AM_MKINSTALLDIRS],
+[
+  dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
+  dnl find the mkinstalldirs script in another subdir but $(top_srcdir).
+  dnl Try to locate is.
+  MKINSTALLDIRS=
+  if test -n "$ac_aux_dir"; then
+    MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
+  fi
+  if test -z "$MKINSTALLDIRS"; then
+    MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
+  fi
+  AC_SUBST(MKINSTALLDIRS)
+])
Index: /tags/kBuild-0.1.4/src/sed/config/glibc21.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/glibc21.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/glibc21.m4	(revision 1780)
@@ -0,0 +1,32 @@
+# glibc21.m4 serial 2 (fileutils-4.1.3, gettext-0.10.40)
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+# Test for the GNU C Library, version 2.1 or newer.
+# From Bruno Haible.
+
+AC_DEFUN([jm_GLIBC21],
+  [
+    AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer,
+      ac_cv_gnu_library_2_1,
+      [AC_EGREP_CPP([Lucky GNU user],
+	[
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
+  Lucky GNU user
+ #endif
+#endif
+	],
+	ac_cv_gnu_library_2_1=yes,
+	ac_cv_gnu_library_2_1=no)
+      ]
+    )
+    AC_SUBST(GLIBC21)
+    GLIBC21="$ac_cv_gnu_library_2_1"
+  ]
+)
Index: /tags/kBuild-0.1.4/src/sed/config/help2man
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/help2man	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/help2man	(revision 1780)
@@ -0,0 +1,559 @@
+#!/usr/bin/env perl
+
+# Generate a short man page from --help and --version output.
+# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+# Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Written by Brendan O'Dea <bod@debian.org>
+# Available from ftp://ftp.gnu.org/gnu/help2man/
+
+use 5.005;
+use strict;
+use Getopt::Long;
+use Text::Tabs qw(expand);
+use POSIX qw(strftime setlocale LC_TIME);
+
+my $this_program = 'help2man';
+my $this_version = '1.28';
+my $version_info = <<EOT;
+GNU $this_program $this_version
+
+Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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.
+
+Written by Brendan O'Dea <bod\@debian.org>
+EOT
+
+my $help_info = <<EOT;
+`$this_program' generates a man page out of `--help' and `--version' output.
+
+Usage: $this_program [OPTION]... EXECUTABLE
+
+ -n, --name=STRING       description for the NAME paragraph
+ -s, --section=SECTION   section number for manual page (1, 6, 8)
+ -m, --manual=TEXT       name of manual (User Commands, ...)
+ -S, --source=TEXT       source of program (FSF, Debian, ...)
+ -i, --include=FILE      include material from `FILE'
+ -I, --opt-include=FILE  include material from `FILE' if it exists
+ -o, --output=FILE       send output to `FILE'
+ -p, --info-page=TEXT    name of Texinfo manual
+ -N, --no-info           suppress pointer to Texinfo manual
+     --help              print this help, then exit
+     --version           print version number, then exit
+
+EXECUTABLE should accept `--help' and `--version' options although
+alternatives may be specified using:
+
+ -h, --help-option=STRING     help option string
+ -v, --version-option=STRING  version option string
+
+Report bugs to <bug-help2man\@gnu.org>.
+EOT
+
+my $section = 1;
+my $manual = '';
+my $source = '';
+my $help_option = '--help';
+my $version_option = '--version';
+my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info);
+
+my %opt_def = (
+    'n|name=s'		 => \$opt_name,
+    's|section=s'	 => \$section,
+    'm|manual=s'	 => \$manual,
+    'S|source=s'	 => \$source,
+    'i|include=s'	 => sub { push @opt_include, [ pop, 1 ] },
+    'I|opt-include=s'	 => sub { push @opt_include, [ pop, 0 ] },
+    'o|output=s'	 => \$opt_output,
+    'p|info-page=s'	 => \$opt_info,
+    'N|no-info'		 => \$opt_no_info,
+    'h|help-option=s'	 => \$help_option,
+    'v|version-option=s' => \$version_option,
+);
+
+# Parse options.
+Getopt::Long::config('bundling');
+GetOptions (%opt_def,
+    help    => sub { print $help_info; exit },
+    version => sub { print $version_info; exit },
+) or die $help_info;
+
+die $help_info unless @ARGV == 1;
+
+my %include = ();
+my %append = ();
+my @include = (); # retain order given in include file
+
+# Process include file (if given).  Format is:
+#
+#   [section name]
+#   verbatim text
+#
+# or
+#
+#   /pattern/
+#   verbatim text
+#
+
+while (@opt_include)
+{
+    my ($inc, $required) = @{shift @opt_include};
+
+    next unless -f $inc or $required;
+    die "$this_program: can't open `$inc' ($!)\n"
+	unless open INC, $inc;
+
+    my $key;
+    my $hash = \%include;
+
+    while (<INC>)
+    {
+	# [section]
+	if (/^\[([^]]+)\]/)
+	{
+	    $key = uc $1;
+	    $key =~ s/^\s+//;
+	    $key =~ s/\s+$//;
+	    $hash = \%include;
+	    push @include, $key unless $include{$key};
+	    next;
+	}
+
+	# /pattern/
+	if (m!^/(.*)/([ims]*)!)
+	{
+	    my $pat = $2 ? "(?$2)$1" : $1;
+
+	    # Check pattern.
+	    eval { $key = qr($pat) };
+	    if ($@)
+	    {
+		$@ =~ s/ at .*? line \d.*//;
+		die "$inc:$.:$@";
+	    }
+
+	    $hash = \%append;
+	    next;
+	}
+
+	# Check for options before the first section--anything else is
+	# silently ignored, allowing the first for comments and
+	# revision info.
+	unless ($key)
+	{
+	    # handle options
+	    if (/^-/)
+	    {
+		local @ARGV = split;
+		GetOptions %opt_def;
+	    }
+
+	    next;
+	}
+
+	$hash->{$key} ||= '';
+	$hash->{$key} .= $_;
+    }
+
+    close INC;
+
+    die "$this_program: no valid information found in `$inc'\n"
+	unless $key;
+}
+
+# Compress trailing blank lines.
+for my $hash (\(%include, %append))
+{
+    for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
+}
+
+# Turn off localisation of executable's ouput.
+@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
+
+# Turn off localisation of date (for strftime).
+setlocale LC_TIME, 'C';
+
+# Grab help and version info from executable.
+my ($help_text, $version_text) = map {
+    join '', map { s/ +$//; expand $_ } `$ARGV[0] $_ 2>/dev/null`
+	or die "$this_program: can't get `$_' info from $ARGV[0]\n"
+} $help_option, $version_option;
+
+my $date = strftime "%B %Y", localtime;
+(my $program = $ARGV[0]) =~ s!.*/!!;
+my $package = $program;
+my $version;
+
+if ($opt_output)
+{
+    unlink $opt_output
+	or die "$this_program: can't unlink $opt_output ($!)\n"
+	if -e $opt_output;
+
+    open STDOUT, ">$opt_output"
+	or die "$this_program: can't create $opt_output ($!)\n";
+}
+
+# The first line of the --version information is assumed to be in one
+# of the following formats:
+#
+#   <version>
+#   <program> <version>
+#   {GNU,Free} <program> <version>
+#   <program> ({GNU,Free} <package>) <version>
+#   <program> - {GNU,Free} <package> <version>
+#
+# and seperated from any copyright/author details by a blank line.
+
+($_, $version_text) = split /\n+/, $version_text, 2;
+
+if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
+    /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
+{
+    $program = $1;
+    $package = $2;
+    $version = $3;
+}
+elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
+{
+    $program = $2;
+    $package = $1 ? "$1$2" : $2;
+    $version = $3;
+}
+else
+{
+    $version = $_;
+}
+
+$program =~ s!.*/!!;
+
+# No info for `info' itself.
+$opt_no_info = 1 if $program eq 'info';
+
+# --name overrides --include contents.
+$include{NAME} = "$program \\- $opt_name\n" if $opt_name;
+
+# Default (useless) NAME paragraph.
+$include{NAME} ||= "$program \\- manual page for $program $version\n";
+
+# Man pages traditionally have the page title in caps.
+my $PROGRAM = uc $program;
+
+# Set default page head/footers
+$source ||= "$program $version";
+unless ($manual)
+{
+    for ($section)
+    {
+	if (/^(1[Mm]|8)/) { $manual = 'System Administration Utilities' }
+	elsif (/^6/)	  { $manual = 'Games' }
+	else		  { $manual = 'User Commands' }
+    }
+}
+
+# Extract usage clause(s) [if any] for SYNOPSIS.
+if ($help_text =~ s/^Usage:( +(\S+))(.*)((?:\n(?: {6}\1| *or: +\S).*)*)//m)
+{
+    my @syn = $2 . $3;
+
+    if ($_ = $4)
+    {
+	s/^\n//;
+	for (split /\n/) { s/^ *(or: +)?//; push @syn, $_ }
+    }
+
+    my $synopsis = '';
+    for (@syn)
+    {
+	$synopsis .= ".br\n" if $synopsis;
+	s!^\S*/!!;
+	s/^(\S+) *//;
+	$synopsis .= ".B $1\n";
+	s/\s+$//;
+	s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
+	s/^/\\fI/ unless s/^\\fR//;
+	$_ .= '\fR';
+	s/(\\fI)( *)/$2$1/g;
+	s/\\fI\\fR//g;
+	s/^\\fR//;
+	s/\\fI$//;
+	s/^\./\\&./;
+
+	$synopsis .= "$_\n";
+    }
+
+    $include{SYNOPSIS} ||= $synopsis;
+}
+
+# Process text, initial section is DESCRIPTION.
+my $sect = 'DESCRIPTION';
+$_ = "$help_text\n\n$version_text";
+
+# Normalise paragraph breaks.
+s/^\n+//;
+s/\n*$/\n/;
+s/\n\n+/\n\n/g;
+
+# Temporarily exchange leading dots, apostrophes and backslashes for
+# tokens.
+s/^\./\x80/mg;
+s/^'/\x81/mg;
+s/\\/\x82/g;
+
+# Start a new paragraph (if required) for these.
+s/([^\n])\n(Report +bugs|Email +bug +reports +to|Written +by)/$1\n\n$2/g;
+
+sub convert_option;
+
+while (length)
+{
+    # Convert some standard paragraph names.
+    if (s/^(Options|Examples): *\n//)
+    {
+	$sect = uc $1;
+	next;
+    }
+
+    # Copyright section
+    if (/^Copyright +[(\xa9]/)
+    {
+	$sect = 'COPYRIGHT';
+	$include{$sect} ||= '';
+	$include{$sect} .= ".PP\n" if $include{$sect};
+
+	my $copy;
+	($copy, $_) = split /\n\n/, $_, 2;
+
+	for ($copy)
+	{
+	    # Add back newline
+	    s/\n*$/\n/;
+
+	    # Convert iso9959-1 copyright symbol or (c) to nroff
+	    # character.
+	    s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
+
+	    # Insert line breaks before additional copyright messages
+	    # and the disclaimer.
+	    s/(.)\n(Copyright |This +is +free +software)/$1\n.br\n$2/g;
+
+	    # Join hyphenated lines.
+	    s/([A-Za-z])-\n */$1/g;
+	}
+
+	$include{$sect} .= $copy;
+	$_ ||= '';
+	next;
+    }
+
+    # Catch bug report text.
+    if (/^(Report +bugs|Email +bug +reports +to) /)
+    {
+	$sect = 'REPORTING BUGS';
+    }
+
+    # Author section.
+    elsif (/^Written +by/)
+    {
+	$sect = 'AUTHOR';
+    }
+
+    # Examples, indicated by an indented leading $, % or > are
+    # rendered in a constant width font.
+    if (/^( +)([\$\%>] )\S/)
+    {
+	my $indent = $1;
+	my $prefix = $2;
+	my $break = '.IP';
+	$include{$sect} ||= '';
+	while (s/^$indent\Q$prefix\E(\S.*)\n*//)
+	{
+	    $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
+	    $break = '.br';
+	}
+
+	next;
+    }
+
+    my $matched = '';
+    $include{$sect} ||= '';
+
+    # Sub-sections have a trailing colon and the second line indented.
+    if (s/^(\S.*:) *\n / /)
+    {
+	$matched .= $& if %append;
+	$include{$sect} .= qq(.SS "$1"\n);
+    }
+
+    my $indent = 0;
+    my $content = '';
+
+    # Option with description.
+    if (s/^( {1,10}([+-]\S.*?))(?:(  +(?!-))|\n( {20,}))(\S.*)\n//)
+    {
+	$matched .= $& if %append;
+	$indent = length ($4 || "$1$3");
+	$content = ".TP\n\x83$2\n\x83$5\n";
+	unless ($4)
+	{
+	    # Indent may be different on second line.
+	    $indent = length $& if /^ {20,}/;
+	}
+    }
+
+    # Option without description.
+    elsif (s/^ {1,10}([+-]\S.*)\n//)
+    {
+	$matched .= $& if %append;
+	$content = ".HP\n\x83$1\n";
+	$indent = 80; # not continued
+    }
+
+    # Indented paragraph with tag.
+    elsif (s/^( +(\S.*?)  +)(\S.*)\n//)
+    {
+	$matched .= $& if %append;
+	$indent = length $1;
+	$content = ".TP\n\x83$2\n\x83$3\n";
+    }
+
+    # Indented paragraph.
+    elsif (s/^( +)(\S.*)\n//)
+    {
+	$matched .= $& if %append;
+	$indent = length $1;
+	$content = ".IP\n\x83$2\n";
+    }
+
+    # Left justified paragraph.
+    else
+    {
+	s/(.*)\n//;
+	$matched .= $& if %append;
+	$content = ".PP\n" if $include{$sect};
+	$content .= "$1\n";
+    }
+
+    # Append continuations.
+    while (s/^ {$indent}(\S.*)\n//)
+    {
+	$matched .= $& if %append;
+	$content .= "\x83$1\n"
+    }
+
+    # Move to next paragraph.
+    s/^\n+//;
+
+    for ($content)
+    {
+	# Leading dot and apostrophe protection.
+	s/\x83\./\x80/g;
+	s/\x83'/\x81/g;
+	s/\x83//g;
+
+	# Convert options.
+	s/(^| )(-[][\w=-]+)/$1 . convert_option $2/mge;
+    }
+
+    # Check if matched paragraph contains /pat/.
+    if (%append)
+    {
+	for my $pat (keys %append)
+	{
+	    if ($matched =~ $pat)
+	    {
+		$content .= ".PP\n" unless $append{$pat} =~ /^\./;
+		$content .= $append{$pat};
+	    }
+	}
+    }
+
+    $include{$sect} .= $content;
+}
+
+# Refer to the real documentation.
+unless ($opt_no_info)
+{
+    my $info_page = $opt_info || $program;
+
+    $sect = 'SEE ALSO';
+    $include{$sect} ||= '';
+    $include{$sect} .= ".PP\n" if $include{$sect};
+    $include{$sect} .= <<EOT;
+The full documentation for
+.B $program
+is maintained as a Texinfo manual.  If the
+.B info
+and
+.B $program
+programs are properly installed at your site, the command
+.IP
+.B info $info_page
+.PP
+should give you access to the complete manual.
+EOT
+}
+
+# Output header.
+print <<EOT;
+.\\" DO NOT MODIFY THIS FILE!  It was generated by $this_program $this_version.
+.TH $PROGRAM "$section" "$date" "$source" "$manual"
+EOT
+
+# Section ordering.
+my @pre = qw(NAME SYNOPSIS DESCRIPTION OPTIONS EXAMPLES);
+my @post = ('AUTHOR', 'REPORTING BUGS', 'COPYRIGHT', 'SEE ALSO');
+my $filter = join '|', @pre, @post;
+
+# Output content.
+for (@pre, (grep ! /^($filter)$/o, @include), @post)
+{
+    if ($include{$_})
+    {
+	my $quote = /\W/ ? '"' : '';
+	print ".SH $quote$_$quote\n";
+	
+	for ($include{$_})
+	{
+	    # Replace leading dot, apostrophe and backslash tokens.
+	    s/\x80/\\&./g;
+	    s/\x81/\\&'/g;
+	    s/\x82/\\e/g;
+	    print;
+	}
+    }
+}
+
+exit;
+
+# Convert option dashes to \- to stop nroff from hyphenating 'em, and
+# embolden.  Option arguments get italicised.
+sub convert_option
+{
+    local $_ = '\fB' . shift;
+
+    s/-/\\-/g;
+    unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
+    {
+	s/=(.)/\\fR=\\fI$1/;
+	s/ (.)/ \\fI$1/;
+	$_ .= '\fR';
+    }
+
+    $_;
+}
Index: /tags/kBuild-0.1.4/src/sed/config/iconv.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/iconv.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/iconv.m4	(revision 1780)
@@ -0,0 +1,96 @@
+# iconv.m4 serial AM3 (gettext-0.11)
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+  dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+  dnl those with the standalone portable GNU libiconv installed).
+
+  dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([iconv])
+
+  dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed libiconv and not disabled its use
+  dnl via --without-libiconv-prefix, he wants to use it. The first
+  dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed.
+  am_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+  AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+      [iconv_t cd = iconv_open("","");
+       iconv(cd,NULL,NULL,NULL,NULL);
+       iconv_close(cd);],
+      am_cv_func_iconv=yes)
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBICONV"
+      AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+        [iconv_t cd = iconv_open("","");
+         iconv(cd,NULL,NULL,NULL,NULL);
+         iconv_close(cd);],
+        am_cv_lib_iconv=yes
+        am_cv_func_iconv=yes)
+      LIBS="$am_save_LIBS"
+    fi
+  ])
+  if test "$am_cv_func_iconv" = yes; then
+    AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
+  fi
+  if test "$am_cv_lib_iconv" = yes; then
+    AC_MSG_CHECKING([how to link with libiconv])
+    AC_MSG_RESULT([$LIBICONV])
+  else
+    dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+    dnl either.
+    CPPFLAGS="$am_save_CPPFLAGS"
+    LIBICONV=
+    LTLIBICONV=
+  fi
+  AC_SUBST(LIBICONV)
+  AC_SUBST(LTLIBICONV)
+])
+
+AC_DEFUN([AM_ICONV],
+[
+  AC_REQUIRE([AM_ICONV_LINK])
+  if test "$am_cv_func_iconv" = yes; then
+    AC_MSG_CHECKING([for iconv declaration])
+    AC_CACHE_VAL(am_cv_proto_iconv, [
+      AC_TRY_COMPILE([
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+    am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    AC_MSG_RESULT([$]{ac_t:-
+         }[$]am_cv_proto_iconv)
+    AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
+      [Define as const if the declaration of iconv() needs const.])
+  fi
+])
Index: /tags/kBuild-0.1.4/src/sed/config/install-sh
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/install-sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/install-sh	(revision 1780)
@@ -0,0 +1,322 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2004-07-05.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# 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}"
+
+chmodcmd="$chmodprog 0755"
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c         (ignored)
+-d         create directories instead of installing files.
+-g GROUP   $chgrpprog installed files to GROUP.
+-m MODE    $chmodprog installed files to MODE.
+-o USER    $chownprog installed files to USER.
+-s         $stripprog installed files.
+-t DIRECTORY  install into DIRECTORY.
+-T         report an error if DSTFILE is a directory.
+--help     display this help and exit.
+--version  display version info and exit.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test -n "$1"; do
+  case $1 in
+    -c) shift
+        continue;;
+
+    -d) dir_arg=true
+        shift
+        continue;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift
+        shift
+        continue;;
+
+    --help) echo "$usage"; exit 0;;
+
+    -m) chmodcmd="$chmodprog $2"
+        shift
+        shift
+        continue;;
+
+    -o) chowncmd="$chownprog $2"
+        shift
+        shift
+        continue;;
+
+    -s) stripcmd=$stripprog
+        shift
+        continue;;
+
+    -t) dstarg=$2
+	shift
+	shift
+	continue;;
+
+    -T) no_target_directory=true
+	shift
+	continue;;
+
+    --version) echo "$0 $scriptversion"; exit 0;;
+
+    *)  # When -d is used, all remaining arguments are directories to create.
+	# When -t is used, the destination is already specified.
+	test -n "$dir_arg$dstarg" && break
+        # Otherwise, the last argument is the destination.  Remove it from $@.
+	for arg
+	do
+          if test -n "$dstarg"; then
+	    # $@ is not empty: it contains at least $arg.
+	    set fnord "$@" "$dstarg"
+	    shift # fnord
+	  fi
+	  shift # arg
+	  dstarg=$arg
+	done
+	break;;
+  esac
+done
+
+if test -z "$1"; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src ;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    src=
+
+    if test -d "$dst"; then
+      mkdircmd=:
+      chmodcmd=
+    else
+      mkdircmd=$mkdirprog
+    fi
+  else
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dstarg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dstarg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst ;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dstarg: Is a directory" >&2
+	exit 1
+      fi
+      dst=$dst/`basename "$src"`
+    fi
+  fi
+
+  # This sed command emulates the dirname command.
+  dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+  # Make sure that the destination directory exists.
+
+  # Skip lots of stat calls in the usual case.
+  if test ! -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 test $# -ne 0 ; do
+      pathcomp=$pathcomp$1
+      shift
+      if test ! -d "$pathcomp"; then
+        $mkdirprog "$pathcomp"
+	# mkdir can fail with a `File exist' error in case several
+	# install-sh are creating the directory concurrently.  This
+	# is OK.
+	test -d "$pathcomp" || exit
+      fi
+      pathcomp=$pathcomp/
+    done
+  fi
+
+  if test -n "$dir_arg"; then
+    $doit $mkdircmd "$dst" \
+      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
+      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
+      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
+      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
+
+  else
+    dstfile=`basename "$dst"`
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
+    trap '(exit $?); exit' 1 2 13 15
+
+    # Copy the file name to the temp name.
+    $doit $cpprog "$src" "$dsttmp" &&
+
+    # 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 $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
+
+    # Now rename the file to the real destination.
+    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
+      || {
+	   # The rename failed, perhaps because mv can't rename something else
+	   # to itself, or perhaps because mv is so ancient that it does not
+	   # support -f.
+
+	   # Now remove or move aside any old file at destination location.
+	   # We try this two ways since rm can't unlink itself on some
+	   # systems and the destination file might be busy for other
+	   # reasons.  In this case, the final cleanup might fail but the new
+	   # file should still install successfully.
+	   {
+	     if test -f "$dstdir/$dstfile"; then
+	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
+	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
+	       || {
+		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+		 (exit 1); exit
+	       }
+	     else
+	       :
+	     fi
+	   } &&
+
+	   # Now rename the file to the real destination.
+	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+	 }
+    }
+  fi || { (exit 1); exit; }
+done
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+{
+  (exit 0); exit
+}
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /tags/kBuild-0.1.4/src/sed/config/lcmessage.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/lcmessage.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/lcmessage.m4	(revision 1780)
@@ -0,0 +1,32 @@
+# lcmessage.m4 serial 2 (gettext-0.10.40)
+dnl Copyright (C) 1995-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+
+AC_DEFUN([AM_LC_MESSAGES],
+  [if test $ac_cv_header_locale_h = yes; then
+    AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+      [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+       am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+    if test $am_cv_val_LC_MESSAGES = yes; then
+      AC_DEFINE(HAVE_LC_MESSAGES, 1,
+        [Define if your <locale.h> file defines LC_MESSAGES.])
+    fi
+  fi])
Index: /tags/kBuild-0.1.4/src/sed/config/lib-ld.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/lib-ld.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/lib-ld.m4	(revision 1780)
@@ -0,0 +1,97 @@
+# lib-ld.m4 serial 1 (gettext-0.11)
+dnl Copyright (C) 1996-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
+dnl with libtool.m4.
+
+dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  acl_cv_prog_gnu_ld=yes
+else
+  acl_cv_prog_gnu_ld=no
+fi])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-1.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]* | [A-Za-z]:[\\/]*)]
+      [re_direlt='/[^/][^/]*/\.\./']
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(acl_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      acl_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+	test "$with_gnu_ld" != no && break
+      else
+	test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
Index: /tags/kBuild-0.1.4/src/sed/config/lib-link.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/lib-link.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/lib-link.m4	(revision 1780)
@@ -0,0 +1,521 @@
+# lib-link.m4 serial 1 (gettext-0.11)
+dnl Copyright (C) 2001-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  define([Name],[translit([$1],[./-], [___])])
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+  AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+    AC_LIB_LINKFLAGS_BODY([$1], [$2])
+    ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+    ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+    ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+  ])
+  LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+  LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+  INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+  dnl results of this search when this library appears as a dependency.
+  HAVE_LIB[]NAME=yes
+  undefine([Name])
+  undefine([NAME])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. If found, it
+dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
+dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  define([Name],[translit([$1],[./-], [___])])
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+
+  dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+  dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed lib[]Name and not disabled its use
+  dnl via --without-lib[]Name-prefix, he wants to use it.
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+  AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+    ac_save_LIBS="$LIBS"
+    LIBS="$LIBS $LIB[]NAME"
+    AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
+    LIBS="$ac_save_LIBS"
+  ])
+  if test "$ac_cv_lib[]Name" = yes; then
+    HAVE_LIB[]NAME=yes
+    AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
+    AC_MSG_CHECKING([how to link with lib[]$1])
+    AC_MSG_RESULT([$LIB[]NAME])
+  else
+    HAVE_LIB[]NAME=no
+    dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+    dnl $INC[]NAME either.
+    CPPFLAGS="$ac_save_CPPFLAGS"
+    LIB[]NAME=
+    LTLIB[]NAME=
+  fi
+  AC_SUBST([HAVE_LIB]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  undefine([Name])
+  undefine([NAME])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator,
+dnl hardcode_direct, hardcode_minus_L,
+dnl sys_lib_search_path_spec, sys_lib_dlsearch_path_spec.
+AC_DEFUN([AC_LIB_RPATH],
+[
+  AC_REQUIRE([AC_PROG_CC])                dnl we use $CC, $GCC, $LDFLAGS
+  AC_REQUIRE([AC_LIB_PROG_LD])            dnl we use $LD, $with_gnu_ld
+  AC_REQUIRE([AC_CANONICAL_HOST])         dnl we use $host
+  AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+  AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
+    CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+    ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+    . ./conftest.sh
+    rm -f ./conftest.sh
+    acl_cv_rpath=done
+  ])
+  wl="$acl_cv_wl"
+  libext="$acl_cv_libext"
+  shlibext="$acl_cv_shlibext"
+  hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+  hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+  hardcode_direct="$acl_cv_hardcode_direct"
+  hardcode_minus_L="$acl_cv_hardcode_minus_L"
+  sys_lib_search_path_spec="$acl_cv_sys_lib_search_path_spec"
+  sys_lib_dlsearch_path_spec="$acl_cv_sys_lib_dlsearch_path_spec"
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_ARG_WITH([lib$1-prefix],
+[  --with-lib$1-prefix[=DIR]  search for lib$1 in DIR/include and DIR/lib
+  --without-lib$1-prefix     don't search for lib$1 in includedir and libdir],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/lib"
+      fi
+    fi
+])
+  dnl Search the library and its dependencies in $additional_libdir and
+  dnl $LDFLAGS. Using breadth-first-seach.
+  LIB[]NAME=
+  LTLIB[]NAME=
+  INC[]NAME=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='$1 $2'
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+        dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+        dnl or AC_LIB_HAVE_LINKFLAGS call.
+        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+          else
+            dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+            dnl that this library doesn't exist. So just drop it.
+            :
+          fi
+        else
+          dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+          dnl and the already constructed $LIBNAME/$LTLIBNAME.
+          found_dir=
+          found_la=
+          found_so=
+          found_a=
+          if test $use_additional = yes; then
+            if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
+              found_dir="$additional_libdir"
+              found_so="$additional_libdir/lib$name.$shlibext"
+              if test -f "$additional_libdir/lib$name.la"; then
+                found_la="$additional_libdir/lib$name.la"
+              fi
+            else
+              if test -f "$additional_libdir/lib$name.$libext"; then
+                found_dir="$additional_libdir"
+                found_a="$additional_libdir/lib$name.$libext"
+                if test -f "$additional_libdir/lib$name.la"; then
+                  found_la="$additional_libdir/lib$name.la"
+                fi
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIB[]NAME; do
+              AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
+                    found_dir="$dir"
+                    found_so="$dir/lib$name.$shlibext"
+                    if test -f "$dir/lib$name.la"; then
+                      found_la="$dir/lib$name.la"
+                    fi
+                  else
+                    if test -f "$dir/lib$name.$libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/lib$name.$libext"
+                      if test -f "$dir/lib$name.la"; then
+                        found_la="$dir/lib$name.la"
+                      fi
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+            dnl Found the library.
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+              dnl Linking with a shared library. We attempt to hardcode its
+              dnl directory into the executable's runpath, unless it's the
+              dnl standard /usr/lib.
+              if test "X$found_dir" = "X/usr/lib"; then
+                dnl No hardcoding is needed.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+              else
+                dnl Use an explicit option to hardcode DIR into the resulting
+                dnl binary.
+                dnl Potentially add DIR to ltrpathdirs.
+                dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                dnl The hardcoding into $LIBNAME is system dependent.
+                if test "$hardcode_direct" = yes; then
+                  dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+                  dnl resulting binary.
+                  LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                    dnl Use an explicit option to hardcode DIR into the resulting
+                    dnl binary.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    dnl Potentially add DIR to rpathdirs.
+                    dnl The rpathdirs will be appended to $LIBNAME at the end.
+                    haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                    dnl Rely on "-L$found_dir".
+                    dnl But don't add it if it's already contained in the LDFLAGS
+                    dnl or the already constructed $LIBNAME
+                    haveit=
+                    for x in $LDFLAGS $LIB[]NAME; do
+                      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    else
+                      dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH
+                      dnl here, because this doesn't fit in flags passed to the
+                      dnl compiler. So give up. No hardcoding. This affects only
+                      dnl very old systems.
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                dnl Linking with a static library.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+              else
+                dnl We shouldn't come here, but anyway it's good to have a
+                dnl fallback.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+              fi
+            fi
+            dnl Assume the include files are nearby.
+            additional_includedir=
+            case "$found_dir" in
+              */lib | */lib/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+              dnl Potentially add $additional_includedir to $INCNAME.
+              dnl But don't add it
+              dnl   1. if it's the standard /usr/include,
+              dnl   2. if it's /usr/local/include and we are using GCC on Linux,
+              dnl   3. if it's already present in $CPPFLAGS or the already
+              dnl      constructed $INCNAME,
+              dnl   4. if it doesn't exist as a directory.
+              if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux*) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INC[]NAME; do
+                    AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                      dnl Really add $additional_includedir to $INCNAME.
+                      INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+            dnl Look for dependencies.
+            if test -n "$found_la"; then
+              dnl Read the .la file. It defines the variables
+              dnl dlname, library_names, old_library, dependency_libs, current,
+              dnl age, revision, installed, dlopen, dlpreopen, libdir.
+              save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+              dnl We use only dependency_libs.
+              for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                    dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+                    dnl But don't add it
+                    dnl   1. if it's the standard /usr/lib,
+                    dnl   2. if it's /usr/local/lib and we are using GCC on Linux,
+                    dnl   3. if it's already present in $LDFLAGS or the already
+                    dnl      constructed $LIBNAME,
+                    dnl   4. if it doesn't exist as a directory.
+                    if test "X$additional_libdir" != "X/usr/lib"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/lib"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux*) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LIBNAME.
+                            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LTLIBNAME.
+                            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                    dnl Handle this in the next round.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                    dnl Handle this in the next round. Throw away the .la's
+                    dnl directory; it is already contained in a preceding -L
+                    dnl option.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                    dnl Most likely an immediate library name.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+                    LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+            dnl Didn't find the library; assume it is in the system directories
+            dnl known to the linker and runtime loader. (All the system
+            dnl directories known to the linker should also be known to the
+            dnl runtime loader, otherwise the system is severely misconfigured.)
+            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$hardcode_libdir_separator"; then
+      dnl Weird platform: only the last -rpath option counts, the user must
+      dnl pass all path elements in one option. We can arrange that for a
+      dnl single library, but not when more than one $LIBNAMEs are used.
+      alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+      done
+      dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl.
+      acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+    else
+      dnl The -rpath options are cumulative.
+      for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+    dnl When using libtool, the option that works for both libraries and
+    dnl executables is -R. The -R options are cumulative.
+    for found_dir in $ltrpathdirs; do
+      LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+    done
+  fi
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+  for element in [$2]; do
+    haveit=
+    for x in $[$1]; do
+      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      [$1]="${[$1]}${[$1]:+ }$element"
+    fi
+  done
+])
Index: /tags/kBuild-0.1.4/src/sed/config/lib-prefix.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/lib-prefix.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/lib-prefix.m4	(revision 1780)
@@ -0,0 +1,148 @@
+# lib-prefix.m4 serial 1 (gettext-0.11)
+dnl Copyright (C) 2001-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+  AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_ARG_WITH([lib-prefix],
+[  --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+  --without-lib-prefix    don't search for libraries in includedir and libdir],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/lib"
+      fi
+    fi
+])
+  if test $use_additional = yes; then
+    dnl Potentially add $additional_includedir to $CPPFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/include,
+    dnl   2. if it's already present in $CPPFLAGS,
+    dnl   3. if it's /usr/local/include and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_includedir" != "X/usr/include"; then
+      haveit=
+      for x in $CPPFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-I$additional_includedir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_includedir" = "X/usr/local/include"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux*) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_includedir"; then
+            dnl Really add $additional_includedir to $CPPFLAGS.
+            CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+          fi
+        fi
+      fi
+    fi
+    dnl Potentially add $additional_libdir to $LDFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/lib,
+    dnl   2. if it's already present in $LDFLAGS,
+    dnl   3. if it's /usr/local/lib and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_libdir" != "X/usr/lib"; then
+      haveit=
+      for x in $LDFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-L$additional_libdir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_libdir" = "X/usr/local/lib"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux*) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_libdir"; then
+            dnl Really add $additional_libdir to $LDFLAGS.
+            LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+          fi
+        fi
+      fi
+    fi
+  fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+  dnl Unfortunately, prefix and exec_prefix get only finally determined
+  dnl at the end of configure.
+  if test "X$prefix" = "XNONE"; then
+    acl_final_prefix="$ac_default_prefix"
+  else
+    acl_final_prefix="$prefix"
+  fi
+  if test "X$exec_prefix" = "XNONE"; then
+    acl_final_exec_prefix='${prefix}'
+  else
+    acl_final_exec_prefix="$exec_prefix"
+  fi
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+  prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  $1
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+])
Index: /tags/kBuild-0.1.4/src/sed/config/mdate-sh
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/mdate-sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/mdate-sh	(revision 1780)
@@ -0,0 +1,170 @@
+#!/bin/sh
+# Get modification time of a file or directory and pretty-print it.
+
+scriptversion=2003-11-09.00
+
+# Copyright (C) 1995, 1996, 1997, 2003  Free Software Foundation, Inc.
+# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# 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.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+  '')
+     echo "$0: No file.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: mdate-sh [--help] [--version] FILE
+
+Pretty-print the modification time of FILE.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit 0
+    ;;
+  -v | --v*)
+    echo "mdate-sh $scriptversion"
+    exit 0
+    ;;
+esac
+
+# Prevent date giving response in another language.
+LANG=C
+export LANG
+LC_ALL=C
+export LC_ALL
+LC_TIME=C
+export LC_TIME
+
+save_arg1="$1"
+
+# Find out how to get the extended ls output of a file or directory.
+if ls -L /dev/null 1>/dev/null 2>&1; then
+  ls_command='ls -L -l -d'
+else
+  ls_command='ls -l -d'
+fi
+
+# A `ls -l' line looks as follows on OS/2.
+#  drwxrwx---        0 Aug 11  2001 foo
+# This differs from Unix, which adds ownership information.
+#  drwxrwx---   2 root  root      4096 Aug 11  2001 foo
+#
+# To find the date, we split the line on spaces and iterate on words
+# until we find a month.  This cannot work with files whose owner is a
+# user named `Jan', or `Feb', etc.  However, it's unlikely that `/'
+# will be owned by a user whose name is a month.  So we first look at
+# the extended ls output of the root directory to decide how many
+# words should be skipped to get the date.
+
+# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
+set - x`$ls_command /`
+
+# Find which argument is the month.
+month=
+command=
+until test $month
+do
+  shift
+  # Add another shift to the command.
+  command="$command shift;"
+  case $1 in
+    Jan) month=January; nummonth=1;;
+    Feb) month=February; nummonth=2;;
+    Mar) month=March; nummonth=3;;
+    Apr) month=April; nummonth=4;;
+    May) month=May; nummonth=5;;
+    Jun) month=June; nummonth=6;;
+    Jul) month=July; nummonth=7;;
+    Aug) month=August; nummonth=8;;
+    Sep) month=September; nummonth=9;;
+    Oct) month=October; nummonth=10;;
+    Nov) month=November; nummonth=11;;
+    Dec) month=December; nummonth=12;;
+  esac
+done
+
+# Get the extended ls output of the file or directory.
+set - x`eval "$ls_command \"\$save_arg1\""`
+
+# Remove all preceding arguments
+eval $command
+
+# Get the month.  Next argument is day, followed by the year or time.
+case $1 in
+  Jan) month=January; nummonth=1;;
+  Feb) month=February; nummonth=2;;
+  Mar) month=March; nummonth=3;;
+  Apr) month=April; nummonth=4;;
+  May) month=May; nummonth=5;;
+  Jun) month=June; nummonth=6;;
+  Jul) month=July; nummonth=7;;
+  Aug) month=August; nummonth=8;;
+  Sep) month=September; nummonth=9;;
+  Oct) month=October; nummonth=10;;
+  Nov) month=November; nummonth=11;;
+  Dec) month=December; nummonth=12;;
+esac
+
+day=$2
+
+# Here we have to deal with the problem that the ls output gives either
+# the time of day or the year.
+case $3 in
+  *:*) set `date`; eval year=\$$#
+       case $2 in
+	 Jan) nummonthtod=1;;
+	 Feb) nummonthtod=2;;
+	 Mar) nummonthtod=3;;
+	 Apr) nummonthtod=4;;
+	 May) nummonthtod=5;;
+	 Jun) nummonthtod=6;;
+	 Jul) nummonthtod=7;;
+	 Aug) nummonthtod=8;;
+	 Sep) nummonthtod=9;;
+	 Oct) nummonthtod=10;;
+	 Nov) nummonthtod=11;;
+	 Dec) nummonthtod=12;;
+       esac
+       # For the first six month of the year the time notation can also
+       # be used for files modified in the last year.
+       if (expr $nummonth \> $nummonthtod) > /dev/null;
+       then
+	 year=`expr $year - 1`
+       fi;;
+  *) year=$3;;
+esac
+
+# The result.
+echo $day $month $year
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /tags/kBuild-0.1.4/src/sed/config/missing
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/missing	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/missing	(revision 1780)
@@ -0,0 +1,360 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2003-09-02.23
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 
+#   Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, 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.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case "$1" in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  # Exit code 63 means version mismatch.  This often happens
+  # when the user try to use an ancient version of a tool on
+  # a file that requires a minimum version.  In this case we
+  # we should proceed has if the program had been absent, or
+  # if --run hadn't been passed.
+  if test $? = 63; then
+    run=:
+    msg="probably too old"
+  fi
+  ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake@gnu.org>."
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal*)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  autom4te)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
+    test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo "#! /bin/sh"
+	echo "# Created by GNU Automake missing as a replacement of"
+	echo "#  $ $@"
+	echo "exit 0"
+	chmod +x $file
+	exit 1
+    fi
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' $msg.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+	case "$LASTARG" in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if [ ! -f y.tab.h ]; then
+	echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+	case "$LASTARG" in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+	 you modified a dependency of a manual page.  You may need the
+	 \`Help2man' package in order for those modifications to take
+	 effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+	file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+    fi
+    if [ -f "$file" ]; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo ".ab help2man is required to generate this page"
+	exit 1
+    fi
+    ;;
+
+  makeinfo)
+    if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
+       # We have makeinfo, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  tar)
+    shift
+    if test -n "$run"; then
+      echo 1>&2 "ERROR: \`tar' requires --run"
+      exit 1
+    fi
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+	case "$firstarg" in
+	*o*)
+	    firstarg=`echo "$firstarg" | sed s/o//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+	case "$firstarg" in
+	*h*)
+	    firstarg=`echo "$firstarg" | sed s/h//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /tags/kBuild-0.1.4/src/sed/config/progtest.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/progtest.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/progtest.m4	(revision 1780)
@@ -0,0 +1,59 @@
+# progtest.m4 serial 2 (gettext-0.10.40)
+dnl Copyright (C) 1996-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+# Search path for a program which passes the given test.
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl   TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN([AM_PATH_PROG_WITH_TEST],
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+  /*)
+  ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in ifelse([$5], , $PATH, [$5]); do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if [$3]; then
+	ac_cv_path_$1="$ac_dir/$ac_word"
+	break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [  test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+  ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
+  AC_MSG_RESULT([$]$1)
+else
+  AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
Index: /tags/kBuild-0.1.4/src/sed/config/stdbool.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/stdbool.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/stdbool.m4	(revision 1780)
@@ -0,0 +1,66 @@
+# Check for stdbool.h that conforms to C99.
+
+# Copyright (C) 2002-2003 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# This macro is only needed in autoconf <= 2.54.  Newer versions of autoconf
+# have this macro built-in.
+
+AC_DEFUN([AC_HEADER_STDBOOL],
+  [AC_CACHE_CHECK([for stdbool.h that conforms to C99],
+     [ac_cv_header_stdbool_h],
+     [AC_TRY_COMPILE(
+	[
+	  #include <stdbool.h>
+	  #ifndef bool
+	   "error: bool is not defined"
+	  #endif
+	  #ifndef false
+	   "error: false is not defined"
+	  #endif
+	  #if false
+	   "error: false is not 0"
+	  #endif
+	  #ifndef true
+	   "error: false is not defined"
+	  #endif
+	  #if true != 1
+	   "error: true is not 1"
+	  #endif
+	  #ifndef __bool_true_false_are_defined
+	   "error: __bool_true_false_are_defined is not defined"
+	  #endif
+
+	  struct s { _Bool s: 1; _Bool t; } s;
+
+	  char a[true == 1 ? 1 : -1];
+	  char b[false == 0 ? 1 : -1];
+	  char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+	  char d[(bool) -0.5 == true ? 1 : -1];
+	  bool e = &s;
+	  char f[(_Bool) -0.0 == false ? 1 : -1];
+	  char g[true];
+	  char h[sizeof (_Bool)];
+	  char i[sizeof s.t];
+	],
+	[ return !a + !b + !c + !d + !e + !f + !g + !h + !i; ],
+	[ac_cv_header_stdbool_h=yes],
+	[ac_cv_header_stdbool_h=no])])
+   AC_CHECK_TYPES([_Bool])
+   if test $ac_cv_header_stdbool_h = yes; then
+     AC_DEFINE(HAVE_STDBOOL_H, 1, [Define to 1 if stdbool.h conforms to C99.])
+   fi])
Index: /tags/kBuild-0.1.4/src/sed/config/strverscmp.m4
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/strverscmp.m4	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/strverscmp.m4	(revision 1780)
@@ -0,0 +1,24 @@
+# strverscmp.m4 serial 1
+dnl Copyright (C) 2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+AC_DEFUN([gl_FUNC_STRVERSCMP],
+[
+  dnl Persuade glibc <string.h> to declare strverscmp().
+  AC_REQUIRE([AC_GNU_SOURCE])
+
+  AC_REPLACE_FUNCS(strverscmp)
+  if test $ac_cv_func_strverscmp = no; then
+    gl_PREREQ_STRVERSCMP
+  fi
+])
+
+# Prerequisites of lib/strverscmp.c.
+AC_DEFUN([gl_PREREQ_STRVERSCMP], [
+  :
+])
+
Index: /tags/kBuild-0.1.4/src/sed/config/texi2dvi
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/texi2dvi	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/texi2dvi	(revision 1780)
@@ -0,0 +1,658 @@
+#! /bin/sh
+# texi2dvi --- produce DVI (or PDF) files from Texinfo (or LaTeX) sources.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001,
+# 2002, 2003 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, you can either send email to this
+# program's maintainer or write to: The Free Software Foundation,
+# Inc.; 51 Franklin Street, Fifth Floor; Boston, MA 02110-1301, USA.
+#
+# Original author: Noah Friedman <friedman@gnu.org>.
+#
+# Please send bug reports, etc. to bug-texinfo@gnu.org.
+# If possible, please send a copy of the output of the script called with
+# the `--debug' option when making a bug report.
+
+program=`echo $0 | sed -e 's!.*/!!'`
+version="texi2dvi (GNU Texinfo 4.5)
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+There is NO warranty.  You may redistribute this software
+under the terms of the GNU General Public License.
+For more information about these matters, see the files named COPYING."
+
+usage="Usage: $program [OPTION]... FILE...
+
+Run each Texinfo or LaTeX FILE through TeX in turn until all
+cross-references are resolved, building all indices.  The directory
+containing each FILE is searched for included files.  The suffix of FILE
+is used to determine its language (LaTeX or Texinfo).
+
+Makeinfo is used to perform Texinfo macro expansion before running TeX
+when needed.
+
+Operation modes:
+  -b, --batch         no interaction
+  -c, --clean         remove all auxiliary files
+  -D, --debug         turn on shell debugging (set -x)
+  -h, --help          display this help and exit successfully
+  -o, --output=OFILE  leave output in OFILE (implies --clean);
+                      Only one input FILE may be specified in this case
+  -q, --quiet         no output unless errors (implies --batch)
+  -s, --silent        same as --quiet
+  -v, --version       display version information and exit successfully
+  -V, --verbose       report on what is done
+
+TeX tuning:
+  -@                   use @input instead of \input; for preloaded Texinfo
+  -e, -E, --expand     force macro expansion using makeinfo
+  -I DIR               search DIR for Texinfo files
+  -l, --language=LANG  specify the LANG of FILE (LaTeX or Texinfo)
+  -p, --pdf            use pdftex or pdflatex for processing
+  -t, --texinfo=CMD    insert CMD after @setfilename in copy of input file
+                       multiple values accumulate
+
+The values of the BIBTEX, LATEX (or PDFLATEX), MAKEINDEX, MAKEINFO,
+TEX (or PDFTEX), and TEXINDEX environment variables are used to run
+those commands, if they are set.
+
+Email bug reports to <bug-texinfo@gnu.org>,
+general questions and discussion to <help-texinfo@gnu.org>.
+Texinfo home page: http://www.gnu.org/software/texinfo/"
+
+# Initialize variables for option overriding and otherwise.
+# Don't use `unset' since old bourne shells don't have this command.
+# Instead, assign them an empty value.
+batch=false     # eval for batch mode
+clean=
+debug=
+escape='\'
+expand=         # t for expansion via makeinfo
+miincludes=     # makeinfo include path
+oformat=dvi
+oname=          # --output
+quiet=          # by default let the tools' message be displayed
+set_language=
+textra=
+tmpdir=${TMPDIR:-/tmp}/t2d$$  # avoid collisions on 8.3 filesystems.
+txincludes=     # TEXINPUTS extensions, with trailing colon
+txiprereq=19990129 # minimum texinfo.tex version to have macro expansion
+verbose=false   # echo for verbose mode
+
+orig_pwd=`pwd`
+
+# Systems which define $COMSPEC or $ComSpec use semicolons to separate
+# directories in TEXINPUTS.
+if test -n "$COMSPEC$ComSpec"; then
+  path_sep=";"
+else
+  path_sep=":"
+fi
+
+# Pacify verbose cds.
+CDPATH=${ZSH_VERSION+.}$path_sep
+
+# In case someone crazy insists on using grep -E.
+: ${EGREP=egrep}
+
+# Save this so we can construct a new TEXINPUTS path for each file.
+TEXINPUTS_orig="$TEXINPUTS"
+# Unfortunately makeindex does not read TEXINPUTS.
+INDEXSTYLE_orig="$INDEXSTYLE"
+export TEXINPUTS INDEXSTYLE
+
+# Push a token among the arguments that will be used to notice when we
+# ended options/arguments parsing.
+# Use "set dummy ...; shift" rather than 'set - ..." because on
+# Solaris set - turns off set -x (but keeps set -e).
+# Use ${1+"$@"} rather than "$@" because Digital Unix and Ultrix 4.3
+# still expand "$@" to a single argument (the empty string) rather
+# than nothing at all.
+arg_sep="$$--$$"
+set dummy ${1+"$@"} "$arg_sep"; shift
+
+# 
+
+# Parse command line arguments.
+while test x"$1" != x"$arg_sep"; do
+
+  # Handle --option=value by splitting apart and putting back on argv.
+  case "$1" in
+    --*=*)
+      opt=`echo "$1" | sed -e 's/=.*//'`
+      val=`echo "$1" | sed -e 's/[^=]*=//'`
+      shift
+      set dummy "$opt" "$val" ${1+"$@"}; shift
+      ;;
+  esac
+
+  # This recognizes --quark as --quiet.  So what.
+  case "$1" in
+    -@ ) escape=@;;
+    # Silently and without documentation accept -b and --b[atch] as synonyms.
+    -b | --b*) batch=eval;;
+    -q | -s | --q* | --s*) quiet=t; batch=eval;;
+    -c | --c*) clean=t;;
+    -D | --d*) debug=t;;
+    -e | -E | --e*) expand=t;;
+    -h | --h*) echo "$usage"; exit 0;;
+    -I | --I*)
+      shift
+      miincludes="$miincludes -I $1"
+      txincludes="$txincludes$1$path_sep"
+      ;;
+    -l | --l*) shift; set_language=$1;;
+    -o | --o*)
+      shift
+      clean=t
+      case "$1" in
+        /* | ?:/*) oname=$1;;
+                *) oname="$orig_pwd/$1";;
+      esac;;
+    -p | --p*) oformat=pdf;;
+    -t | --t*) shift; textra="$textra\\
+$1";;
+    -v | --vers*) echo "$version"; exit 0;;
+    -V | --verb*) verbose=echo;;
+    --) # What remains are not options.
+      shift
+      while test x"$1" != x"$arg_sep"; do
+        set dummy ${1+"$@"} "$1"; shift
+        shift
+      done
+      break;;
+    -*)
+      echo "$0: Unknown or ambiguous option \`$1'." >&2
+      echo "$0: Try \`--help' for more information." >&2
+      exit 1;;
+    *) set dummy ${1+"$@"} "$1"; shift;;
+   esac
+   shift
+done
+# Pop the token
+shift
+
+# Interpret remaining command line args as filenames.
+case $# in
+ 0)
+  echo "$0: Missing file arguments." >&2
+  echo "$0: Try \`--help' for more information." >&2
+  exit 2
+  ;;
+ 1) ;;
+ *)
+  if test -n "$oname"; then
+    echo "$0: Can't use option \`--output' with more than one argument." >&2
+    exit 2
+  fi
+  ;;
+esac
+
+# Prepare the temporary directory.  Remove it at exit, unless debugging.
+if test -z "$debug"; then
+  trap "cd / && rm -rf $tmpdir" 0 1 2 15
+fi
+
+# Create the temporary directory with strict rights
+(umask 077 && mkdir $tmpdir) || exit 1
+
+# Prepare the tools we might need.  This may be extra work in some
+# cases, but improves the readibility of the script.
+utildir=$tmpdir/utils
+mkdir $utildir || exit 1
+
+# A sed script that preprocesses Texinfo sources in order to keep the
+# iftex sections only.  We want to remove non TeX sections, and
+# comment (with `@c texi2dvi') TeX sections so that makeinfo does not
+# try to parse them.  Nevertheless, while commenting TeX sections,
+# don't comment @macro/@end macro so that makeinfo does propagate
+# them.  Unfortunately makeinfo --iftex --no-ifhtml --no-ifinfo
+# doesn't work well enough (yet) to use that, so work around with sed.
+comment_iftex_sed=$utildir/comment.sed
+cat <<EOF >$comment_iftex_sed
+/^@tex/,/^@end tex/{
+  s/^/@c texi2dvi/
+}
+/^@iftex/,/^@end iftex/{
+  s/^/@c texi2dvi/
+  /^@c texi2dvi@macro/,/^@c texi2dvi@end macro/{
+    s/^@c texi2dvi//
+  }
+}
+/^@html/,/^@end html/{
+  s/^/@c (texi2dvi)/
+}
+/^@ifhtml/,/^@end ifhtml/{
+  s/^/@c (texi2dvi)/
+}
+/^@ifnottex/,/^@end ifnottex/{
+  s/^/@c (texi2dvi)/
+}
+/^@ifinfo/,/^@end ifinfo/{
+  /^@node/p
+  /^@menu/,/^@end menu/p
+  t
+  s/^/@c (texi2dvi)/
+}
+s/^@ifnotinfo/@c texi2dvi@ifnotinfo/
+s/^@end ifnotinfo/@c texi2dvi@end ifnotinfo/
+EOF
+# Uncommenting is simple: Remove any leading `@c texi2dvi'.
+uncomment_iftex_sed=$utildir/uncomment.sed
+cat <<EOF >$uncomment_iftex_sed
+s/^@c texi2dvi//
+EOF
+
+# A shell script that computes the list of xref files.
+# Takes the filename (without extension) of which we look for xref
+# files as argument.  The index files must be reported last.
+get_xref_files=$utildir/get_xref.sh
+cat <<\EOF >$get_xref_files
+#! /bin/sh
+
+# Get list of xref files (indexes, tables and lists).
+# Find all files having root filename with a two-letter extension,
+# saves the ones that are really Texinfo-related files.  .?o? catches
+# many files: .toc, .log, LaTeX tables and lists, FiXme's .lox, maybe more.
+for this_file in "$1".?o? "$1".aux "$1".?? "$1".idx; do
+  # If file is empty, skip it.
+  test -s "$this_file" || continue
+  # If the file is not suitable to be an index or xref file, don't
+  # process it.  The file can't be if its first character is not a
+  # backslash or single quote.
+  first_character=`sed -n '1s/^\(.\).*$/\1/p;q' $this_file`
+  if test "x$first_character" = "x\\" \
+     || test "x$first_character" = "x'"; then
+    xref_files="$xref_files ./$this_file"
+  fi
+done
+echo "$xref_files"
+EOF
+chmod 500 $get_xref_files
+
+# File descriptor usage:
+# 0 standard input
+# 1 standard output (--verbose messages)
+# 2 standard error
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 5 tools output (turned off by --quiet)
+
+# Tools' output.  If quiet, discard, else redirect to the message flow.
+if test "$quiet" = t; then
+  exec 5>/dev/null
+else
+  exec 5>&1
+fi
+
+# Enable tracing
+test "$debug" = t && set -x
+
+# 
+
+# TeXify files.
+
+for command_line_filename in ${1+"$@"}; do
+  $verbose "Processing $command_line_filename ..."
+
+  # If the COMMAND_LINE_FILENAME is not absolute (e.g., --debug.tex),
+  # prepend `./' in order to avoid that the tools take it as an option.
+  echo "$command_line_filename" | $EGREP '^(/|[A-z]:/)' >/dev/null \
+  || command_line_filename="./$command_line_filename"
+
+  # See if the file exists.  If it doesn't we're in trouble since, even
+  # though the user may be able to reenter a valid filename at the tex
+  # prompt (assuming they're attending the terminal), this script won't
+  # be able to find the right xref files and so forth.
+  if test ! -r "$command_line_filename"; then
+    echo "$0: Could not read $command_line_filename, skipping." >&2
+    continue
+  fi
+
+  # Get the name of the current directory.  We want the full path
+  # because in clean mode we are in tmp, in which case a relative
+  # path has no meaning.
+  filename_dir=`echo $command_line_filename | sed 's!/[^/]*$!!;s!^$!.!'`
+  filename_dir=`cd "$filename_dir" >/dev/null && pwd`
+
+  # Strip directory part but leave extension.
+  filename_ext=`basename "$command_line_filename"`
+  # Strip extension.
+  filename_noext=`echo "$filename_ext" | sed 's/\.[^.]*$//'`
+  ext=`echo "$filename_ext" | sed 's/^.*\.//'`
+
+  # _src.  Use same basename since we want to generate aux files with
+  # the same basename as the manual.  If --expand, then output the
+  # macro-expanded file to here, else copy the original file.
+  tmpdir_src=$tmpdir/src
+  filename_src=$tmpdir_src/$filename_noext.$ext
+
+  # _xtr.  The file with the user's extra commands.
+  tmpdir_xtr=$tmpdir/xtr
+  filename_xtr=$tmpdir_xtr/$filename_noext.$ext
+
+  # _bak.  Copies of the previous xref files (another round is run if
+  # they differ from the new one).
+  tmpdir_bak=$tmpdir/bak
+
+  # Make all those directories and give up if we can't succeed.
+  mkdir $tmpdir_src $tmpdir_xtr $tmpdir_bak || exit 1
+
+  # Source file might include additional sources.
+  # We want `.:$orig_pwd' before anything else.  (We'll add `.:' later
+  # after all other directories have been turned into absolute paths.)
+  # `.' goes first to ensure that any old .aux, .cps,
+  # etc. files in ${directory} don't get used in preference to fresher
+  # files in `.'.  Include orig_pwd in case we are in clean mode, where
+  # we've cd'd to a temp directory.
+  common="$orig_pwd$path_sep$filename_dir$path_sep$txincludes"
+   TEXINPUTS="$common$TEXINPUTS_orig"
+  INDEXSTYLE="$common$INDEXSTYLE_orig"
+
+  # Convert relative paths to absolute paths, so we can run in another
+  # directory (e.g., in --clean mode, or during the macro-support
+  # detection.)
+  #
+  # Empty path components are meaningful to tex.  We rewrite them
+  # as `EMPTY' so they don't get lost when we split on $path_sep.
+   TEXINPUTS=`echo $TEXINPUTS  |sed 's/^:/EMPTY:/;s/:$/:EMPTY/;s/::/:EMPTY:/g'`
+  INDEXSTYLE=`echo $INDEXSTYLE |sed 's/^:/EMPTY:/;s/:$/:EMPTY/;s/::/:EMPTY:/g'`
+  save_IFS=$IFS
+  IFS=$path_sep
+  set x $TEXINPUTS; shift
+  TEXINPUTS=.
+  for dir
+  do
+    case $dir in
+      EMPTY)
+        TEXINPUTS=$TEXINPUTS$path_sep
+        ;;
+      [\\/]* | ?:[\\/]*)        # Absolute paths don't need to be expansed.
+        TEXINPUTS=$TEXINPUTS$path_sep$dir
+        ;;
+      *)
+        abs=`cd "$dir" && pwd` && TEXINPUTS=$TEXINPUTS$path_sep$abs
+        ;;
+    esac
+  done
+  set x $INDEXSTYLE; shift
+  INDEXSTYLE=.
+  for dir
+  do
+    case $dir in
+      EMPTY)
+        INDEXSTYLE=$INDEXSTYLE$path_sep
+        ;;
+      [\\/]* | ?:[\\/]*)        # Absolute paths don't need to be expansed.
+        INDEXSTYLE=$INDEXSTYLE$path_sep$dir
+        ;;
+      *)
+        abs=`cd "$dir" && pwd` && INDEXSTYLE=$INDEXSTYLE$path_sep$abs
+        ;;
+    esac
+  done
+  IFS=$save_IFS
+
+  # If the user explicitly specified the language, use that.
+  # Otherwise, if the first line is \input texinfo, assume it's texinfo.
+  # Otherwise, guess from the file extension.
+  if test -n "$set_language"; then
+    language=$set_language
+  elif sed 1q "$command_line_filename" | grep 'input texinfo' >/dev/null; then
+    language=texinfo
+  else
+    language=
+  fi
+
+  # Get the type of the file (latex or texinfo) from the given language
+  # we just guessed, or from the file extension if not set yet.
+  case ${language:-$filename_ext} in
+    [lL]a[tT]e[xX] | *.ltx | *.tex)
+      # Assume a LaTeX file.  LaTeX needs bibtex and uses latex for
+      # compilation.  No makeinfo.
+      bibtex=${BIBTEX:-bibtex}
+      makeinfo= # no point in running makeinfo on latex source.
+      texindex=${MAKEINDEX:-makeindex}
+      if test $oformat = dvi; then
+        tex=${LATEX:-latex}
+      else
+        tex=${PDFLATEX:-pdflatex}
+      fi
+      ;;
+
+    *)
+      # Assume a Texinfo file.  Texinfo files need makeinfo, texindex and tex.
+      bibtex=
+      texindex=${TEXINDEX:-texindex}
+      if test $oformat = dvi; then
+        tex=${TEX:-tex}
+      else
+        tex=${PDFTEX:-pdftex}
+      fi
+      # Unless required by the user, makeinfo expansion is wanted only
+      # if texinfo.tex is too old.
+      if test "$expand" = t; then
+        makeinfo=${MAKEINFO:-makeinfo}
+      else
+        # Check if texinfo.tex performs macro expansion by looking for
+        # its version.  The version is a date of the form YEAR-MO-DA.
+        # We don't need to use [0-9] to match the digits since anyway
+        # the comparison with $txiprereq, a number, will fail with non
+        # digits.
+        txiversion_tex=txiversion.tex
+        echo '\input texinfo.tex @bye' >$tmpdir/$txiversion_tex
+        # Run in the tmpdir to avoid leaving files.
+        eval `cd $tmpdir >/dev/null &&
+              $tex $txiversion_tex 2>/dev/null |
+              sed -n 's/^.*\[\(.*\)version \(....\)-\(..\)-\(..\).*$/txiformat=\1 txiversion="\2\3\4"/p'`
+        $verbose "texinfo.tex preloaded as \`$txiformat', version is \`$txiversion' ..."
+        if test "$txiprereq" -le "$txiversion" >/dev/null 2>&1; then
+          makeinfo=
+        else
+          makeinfo=${MAKEINFO:-makeinfo}
+        fi
+        # As long as we had to run TeX, offer the user this convenience
+        if test "$txiformat" = Texinfo; then
+          escape=@
+        fi
+      fi
+      ;;
+  esac
+
+  # Expand macro commands in the original source file using Makeinfo.
+  # Always use `end' footnote style, since the `separate' style
+  #   generates different output (arguably this is a bug in -E).
+  # Discard main info output, the user asked to run TeX, not makeinfo.
+  if test -n "$makeinfo"; then
+    $verbose "Macro-expanding $command_line_filename to $filename_src ..."
+    sed -f $comment_iftex_sed "$command_line_filename" \
+      | $makeinfo --footnote-style=end -I "$filename_dir" $miincludes \
+        -o /dev/null --macro-expand=- \
+      | sed -f $uncomment_iftex_sed >"$filename_src"
+    filename_input=$filename_src
+  fi
+
+  # If makeinfo failed (or was not even run), use the original file as input.
+  if test $? -ne 0 \
+     || test ! -r "$filename_src"; then
+    $verbose "Reverting to $command_line_filename ..."
+    filename_input=$filename_dir/$filename_ext
+  fi
+
+  # Used most commonly for @finalout, @smallbook, etc.
+  if test -n "$textra"; then
+    $verbose "Inserting extra commands: $textra"
+    sed '/^@setfilename/a\
+'"$textra" "$filename_input" >$filename_xtr
+    filename_input=$filename_xtr
+  fi
+
+  # If clean mode was specified, then move to the temporary directory.
+  if test "$clean" = t; then
+    $verbose "cd $tmpdir_src"
+    cd "$tmpdir_src" || exit 1
+  fi
+
+  while :; do # will break out of loop below
+    orig_xref_files=`$get_xref_files "$filename_noext"`
+
+    # Save copies of originals for later comparison.
+    if test -n "$orig_xref_files"; then
+      $verbose "Backing up xref files: `echo $orig_xref_files | sed 's|\./||g'`"
+      cp $orig_xref_files $tmpdir_bak
+    fi
+
+    # Run bibtex on current file.
+    # - If its input (AUX) exists.
+    # - If AUX contains both `\bibdata' and `\bibstyle'.
+    # - If some citations are missing (LOG contains `Citation').
+    #   or the LOG complains of a missing .bbl
+    #
+    # We run bibtex first, because I can see reasons for the indexes
+    # to change after bibtex is run, but I see no reason for the
+    # converse.
+    #
+    # Don't try to be too smart.  Running bibtex only if the bbl file
+    # exists and is older than the LaTeX file is wrong, since the
+    # document might include files that have changed.  Because there
+    # can be several AUX (if there are \include's), but a single LOG,
+    # looking for missing citations in LOG is easier, though we take
+    # the risk to match false messages.
+    if test -n "$bibtex" \
+       && test -r "$filename_noext.aux" \
+       && test -r "$filename_noext.log" \
+       && (grep '^\\bibdata[{]'  "$filename_noext.aux" \
+           && grep '^\\bibstyle[{]' "$filename_noext.aux" \
+           && (grep 'Warning:.*Citation.*undefined' "$filename_noext.log" \
+               || grep 'No file .*\.bbl\.' "$filename_noext.log")) \
+          >/dev/null 2>&1; \
+    then
+      $verbose "Running $bibtex $filename_noext ..."
+      if $bibtex "$filename_noext" >&5; then :; else
+        echo "$0: $bibtex exited with bad status, quitting." >&2
+        exit 1
+      fi
+    fi
+
+    # What we'll run texindex on -- exclude non-index files.
+    # Since we know index files are last, it is correct to remove everything
+    # before .aux and .?o?.  But don't really do <anything>o<anything>
+    # -- don't match whitespace as <anything>.
+    # Otherwise, if orig_xref_files contains something like
+    #   foo.xo foo.whatever
+    # the space after the o will get matched.
+    index_files=`echo "$orig_xref_files" \
+                 | sed "s!.*\.aux!!g;
+                        s!./$filename_noext\.[^ ]o[^ ]!!g;
+                        s/^[ ]*//;s/[ ]*$//"`
+    # Run texindex (or makeindex) on current index files.  If they
+    # already exist, and after running TeX a first time the index
+    # files don't change, then there's no reason to run TeX again.
+    # But we won't know that if the index files are out of date or
+    # nonexistent.
+    if test -n "$texindex" && test -n "$index_files"; then
+      $verbose "Running $texindex $index_files ..."
+      if $texindex $index_files 2>&5 1>&2; then :; else
+         echo "$0: $texindex exited with bad status, quitting." >&2
+         exit 1
+      fi
+    fi
+
+    # Finally, run TeX.
+    # Prevent $ESCAPE from being interpreted by the shell if it happens
+    # to be `/'.
+    $batch tex_args="\\${escape}nonstopmode\ \\${escape}input"
+    cmd="$tex $tex_args $filename_input"
+    $verbose "Running $cmd ..."
+    if $cmd >&5; then :; else
+      echo "$0: $tex exited with bad status, quitting." >&2
+      echo "$0: see $filename_noext.log for errors." >&2
+      test "$clean" = t \
+        && cp "$filename_noext.log" "$orig_pwd"
+      exit 1
+    fi
+
+
+    # Decide if looping again is needed.
+    finished=t
+
+    # LaTeX (and the package changebar) report in the LOG file if it
+    # should be rerun.  This is needed for files included from
+    # subdirs, since texi2dvi does not try to compare xref files in
+    # subdirs.  Performing xref files test is still good since LaTeX
+    # does not report changes in xref files.
+    if grep "Rerun to get" "$filename_noext.log" >/dev/null 2>&1; then
+      finished=
+    fi
+
+    # Check if xref files changed.
+    new_xref_files=`$get_xref_files "$filename_noext"`
+    $verbose "Original xref files = `echo $orig_xref_files | sed 's|\./||g'`"
+    $verbose "New xref files      = `echo $new_xref_files | sed 's|\./||g'`"
+
+    # If old and new lists don't at least have the same file list,
+    # then one file or another has definitely changed.
+    test "x$orig_xref_files" != "x$new_xref_files" && finished=
+
+    # File list is the same.  We must compare each file until we find
+    # a difference.
+    if test -n "$finished"; then
+      for this_file in $new_xref_files; do
+        $verbose "Comparing xref file `echo $this_file | sed 's|\./||g'` ..."
+        # cmp -s returns nonzero exit status if files differ.
+        if cmp -s "$this_file" "$tmpdir_bak/$this_file"; then :; else
+          # We only need to keep comparing until we find one that
+          # differs, because we'll have to run texindex & tex again no
+          # matter how many more there might be.
+          finished=
+          $verbose "xref file `echo $this_file | sed 's|\./||g'` differed ..."
+          test "$debug" = t && diff -c "$tmpdir_bak/$this_file" "$this_file"
+          break
+        fi
+      done
+    fi
+
+    # If finished, exit the loop, else rerun the loop.
+    test -n "$finished" && break
+  done
+
+  # If we were in clean mode, compilation was in a tmp directory.
+  # Copy the DVI (or PDF) file into the directory where the compilation
+  # has been done.  (The temp dir is about to get removed anyway.)
+  # We also return to the original directory so that
+  # - the next file is processed in correct conditions
+  # - the temporary file can be removed
+  if test -n "$clean"; then
+    if test -n "$oname"; then
+       dest=$oname
+    else
+       dest=$orig_pwd
+    fi
+    $verbose "Copying $oformat file from `pwd` to $dest"
+    cp -p "./$filename_noext.$oformat" "$dest"
+    cd / # in case $orig_pwd is on a different drive (for DOS)
+    cd $orig_pwd || exit 1
+  fi
+
+  # Remove temporary files.
+  if test "x$debug" = "x"; then
+    $verbose "Removing $tmpdir_src $tmpdir_xtr $tmpdir_bak ..."
+    cd /
+    rm -rf $tmpdir_src $tmpdir_xtr $tmpdir_bak
+  fi
+done
+
+$verbose "$0 done."
+exit 0 # exit successfully, not however we ended the loop.
Index: /tags/kBuild-0.1.4/src/sed/config/texinfo.tex
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config/texinfo.tex	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config/texinfo.tex	(revision 1780)
@@ -0,0 +1,6996 @@
+% texinfo.tex -- TeX macros to handle Texinfo files.
+%
+% Load plain if necessary, i.e., if running under initex.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+%
+\def\texinfoversion{2004-07-31.11}
+%
+% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
+% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+% Foundation, Inc.
+%
+% This texinfo.tex 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, or (at
+% your option) any later version.
+%
+% This texinfo.tex file 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 texinfo.tex file; see the file COPYING.  If not, write
+% to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+% Boston, MA 02110-1301, USA.
+%
+% As a special exception, when this file is read by TeX when processing
+% a Texinfo source document, you may use the result without
+% restriction.  (This has been our intent since Texinfo was invented.)
+%
+% Please try the latest version of texinfo.tex before submitting bug
+% reports; you can get the latest version from:
+%   http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
+%   ftp://tug.org/tex/texinfo.tex
+%     (and all CTAN mirrors, see http://www.ctan.org).
+% The texinfo.tex in any given distribution could well be out
+% of date, so if that's what you're using, please check.
+%
+% Send bug reports to bug-texinfo@gnu.org.  Please include including a
+% complete document in each bug report with which we can reproduce the
+% problem.  Patches are, of course, greatly appreciated.
+%
+% To process a Texinfo manual with TeX, it's most reliable to use the
+% texi2dvi shell script that comes with the distribution.  For a simple
+% manual foo.texi, however, you can get away with this:
+%   tex foo.texi
+%   texindex foo.??
+%   tex foo.texi
+%   tex foo.texi
+%   dvips foo.dvi -o  # or whatever; this makes foo.ps.
+% The extra TeX runs get the cross-reference information correct.
+% Sometimes one run after texindex suffices, and sometimes you need more
+% than two; texi2dvi does it as many times as necessary.
+%
+% It is possible to adapt texinfo.tex for other languages, to some
+% extent.  You can get the existing language-specific files from the
+% full Texinfo distribution.
+%
+% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.
+
+
+\message{Loading texinfo [version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}%
+  \catcode`+=\active \catcode`\_=\active}
+
+\message{Basics,}
+\chardef\other=12
+
+% We never want plain's \outer definition of \+ in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
+% Save some plain tex macros whose names we will redefine.
+\let\ptexb=\b
+\let\ptexbullet=\bullet
+\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv=\equiv
+\let\ptexexclam=\!
+\let\ptexfootnote=\footnote
+\let\ptexgtr=>
+\let\ptexhat=^
+\let\ptexi=\i
+\let\ptexindent=\indent
+\let\ptexnoindent=\noindent
+\let\ptexinsert=\insert
+\let\ptexlbrace=\{
+\let\ptexless=<
+\let\ptexplus=+
+\let\ptexrbrace=\}
+\let\ptexslash=\/
+\let\ptexstar=\*
+\let\ptext=\t
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+  \let\linenumber = \empty % Pre-3.0.
+\else
+  \def\linenumber{l.\the\inputlineno:\space}
+\fi
+
+% Set up fixed words for English if not already set.
+\ifx\putwordAppendix\undefined  \gdef\putwordAppendix{Appendix}\fi
+\ifx\putwordChapter\undefined   \gdef\putwordChapter{Chapter}\fi
+\ifx\putwordfile\undefined      \gdef\putwordfile{file}\fi
+\ifx\putwordin\undefined        \gdef\putwordin{in}\fi
+\ifx\putwordIndexIsEmpty\undefined     \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
+\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
+\ifx\putwordInfo\undefined      \gdef\putwordInfo{Info}\fi
+\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
+\ifx\putwordMethodon\undefined  \gdef\putwordMethodon{Method on}\fi
+\ifx\putwordNoTitle\undefined   \gdef\putwordNoTitle{No Title}\fi
+\ifx\putwordof\undefined        \gdef\putwordof{of}\fi
+\ifx\putwordon\undefined        \gdef\putwordon{on}\fi
+\ifx\putwordpage\undefined      \gdef\putwordpage{page}\fi
+\ifx\putwordsection\undefined   \gdef\putwordsection{section}\fi
+\ifx\putwordSection\undefined   \gdef\putwordSection{Section}\fi
+\ifx\putwordsee\undefined       \gdef\putwordsee{see}\fi
+\ifx\putwordSee\undefined       \gdef\putwordSee{See}\fi
+\ifx\putwordShortTOC\undefined  \gdef\putwordShortTOC{Short Contents}\fi
+\ifx\putwordTOC\undefined       \gdef\putwordTOC{Table of Contents}\fi
+%
+\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
+\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
+\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
+\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
+\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
+\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
+\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
+\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
+\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
+\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
+\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
+\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
+%
+\ifx\putwordDefmac\undefined    \gdef\putwordDefmac{Macro}\fi
+\ifx\putwordDefspec\undefined   \gdef\putwordDefspec{Special Form}\fi
+\ifx\putwordDefvar\undefined    \gdef\putwordDefvar{Variable}\fi
+\ifx\putwordDefopt\undefined    \gdef\putwordDefopt{User Option}\fi
+\ifx\putwordDeffunc\undefined   \gdef\putwordDeffunc{Function}\fi
+
+% In some macros, we cannot use the `\? notation---the left quote is
+% in some cases the escape char.
+\chardef\colonChar = `\:
+\chardef\commaChar = `\,
+\chardef\dotChar   = `\.
+\chardef\exclamChar= `\!
+\chardef\questChar = `\?
+\chardef\semiChar  = `\;
+\chardef\underChar = `\_
+
+\chardef\spaceChar = `\ %
+\chardef\spacecat = 10
+\def\spaceisspace{\catcode\spaceChar=\spacecat}
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+% The following is used inside several \edef's.
+\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname}
+
+% Hyphenation fixes.
+\hyphenation{
+  Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script
+  ap-pen-dix bit-map bit-maps
+  data-base data-bases eshell fall-ing half-way long-est man-u-script
+  man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm
+  par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces
+  spell-ing spell-ings
+  stand-alone strong-est time-stamp time-stamps which-ever white-space
+  wide-spread wrap-around
+}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen\bindingoffset
+\newdimen\normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+% @| inserts a changebar to the left of the current line.  It should
+% surround any changed text.  This approach does *not* work if the
+% change spans more than two lines of output.  To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+  % \vadjust can only be used in horizontal mode.
+  \leavevmode
+  %
+  % Append this vertical mode material after the current line in the output.
+  \vadjust{%
+    % We want to insert a rule with the height and depth of the current
+    % leading; that is exactly what \strutbox is supposed to record.
+    \vskip-\baselineskip
+    %
+    % \vadjust-items are inserted at the left edge of the type.  So
+    % the \llap here moves out into the left-hand margin.
+    \llap{%
+      %
+      % For a thicker or thinner bar, change the `1pt'.
+      \vrule height\baselineskip width1pt
+      %
+      % This is the space between the bar and the text.
+      \hskip 12pt
+    }%
+  }%
+}
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal.  We don't just call \tracingall here,
+% since that produces some useless output on the terminal.  We also make
+% some effort to order the tracing commands to reduce output in the log
+% file; cf. trace.sty in LaTeX.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{%
+  \tracingstats2
+  \tracingpages1
+  \tracinglostchars2  % 2 gives us more in etex
+  \tracingparagraphs1
+  \tracingoutput1
+  \tracingmacros2
+  \tracingrestores1
+  \showboxbreadth\maxdimen \showboxdepth\maxdimen
+  \ifx\eTeXversion\undefined\else % etex gives us more logging
+    \tracingscantokens1
+    \tracingifs1
+    \tracinggroups1
+    \tracingnesting2
+    \tracingassigns1
+  \fi
+  \tracingcommands3  % 3 gives us more in etex
+  \errorcontextlines16
+}%
+
+% add check for \lastpenalty to plain's definitions.  If the last thing
+% we did was a \nobreak, we don't want to insert more space.
+%
+\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount
+  \removelastskip\penalty-50\smallskip\fi\fi}
+\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount
+  \removelastskip\penalty-100\medskip\fi\fi}
+\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
+  \removelastskip\penalty-200\bigskip\fi\fi}
+
+% For @cropmarks command.
+% Do @cropmarks to get crop marks.
+%
+\newif\ifcropmarks
+\let\cropmarks = \cropmarkstrue
+%
+% Dimensions to add cropmarks at corners.
+% Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
+\newdimen\cornerlong  \cornerlong=1pc
+\newdimen\cornerthick \cornerthick=.3pt
+\newdimen\topandbottommargin \topandbottommargin=.75in
+
+% Main output routine.
+\chardef\PAGE = 255
+\output = {\onepageout{\pagecontents\PAGE}}
+
+\newbox\headlinebox
+\newbox\footlinebox
+
+% \onepageout takes a vbox as an argument.  Note that \pagecontents
+% does insertions, but you have to call it yourself.
+\def\onepageout#1{%
+  \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
+  %
+  \ifodd\pageno  \advance\hoffset by \bindingoffset
+  \else \advance\hoffset by -\bindingoffset\fi
+  %
+  % Do this outside of the \shipout so @code etc. will be expanded in
+  % the headline as they should be, not taken literally (outputting ''code).
+  \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+  \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+  %
+  {%
+    % Have to do this stuff outside the \shipout because we want it to
+    % take effect in \write's, yet the group defined by the \vbox ends
+    % before the \shipout runs.
+    %
+    \escapechar = `\\     % use backslash in output files.
+    \indexdummies         % don't expand commands in the output.
+    \normalturnoffactive  % \ in index entries must not stay \, e.g., if
+                   % the page break happens to be in the middle of an example.
+    \shipout\vbox{%
+      % Do this early so pdf references go to the beginning of the page.
+      \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
+      %
+      \ifcropmarks \vbox to \outervsize\bgroup
+        \hsize = \outerhsize
+        \vskip-\topandbottommargin
+        \vtop to0pt{%
+          \line{\ewtop\hfil\ewtop}%
+          \nointerlineskip
+          \line{%
+            \vbox{\moveleft\cornerthick\nstop}%
+            \hfill
+            \vbox{\moveright\cornerthick\nstop}%
+          }%
+          \vss}%
+        \vskip\topandbottommargin
+        \line\bgroup
+          \hfil % center the page within the outer (page) hsize.
+          \ifodd\pageno\hskip\bindingoffset\fi
+          \vbox\bgroup
+      \fi
+      %
+      \unvbox\headlinebox
+      \pagebody{#1}%
+      \ifdim\ht\footlinebox > 0pt
+        % Only leave this space if the footline is nonempty.
+        % (We lessened \vsize for it in \oddfootingxxx.)
+        % The \baselineskip=24pt in plain's \makefootline has no effect.
+        \vskip 2\baselineskip
+        \unvbox\footlinebox
+      \fi
+      %
+      \ifcropmarks
+          \egroup % end of \vbox\bgroup
+        \hfil\egroup % end of (centering) \line\bgroup
+        \vskip\topandbottommargin plus1fill minus1fill
+        \boxmaxdepth = \cornerthick
+        \vbox to0pt{\vss
+          \line{%
+            \vbox{\moveleft\cornerthick\nsbot}%
+            \hfill
+            \vbox{\moveright\cornerthick\nsbot}%
+          }%
+          \nointerlineskip
+          \line{\ewbot\hfil\ewbot}%
+        }%
+      \egroup % \vbox from first cropmarks clause
+      \fi
+    }% end of \shipout\vbox
+  }% end of group with \normalturnoffactive
+  \advancepageno
+  \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+  \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+% Here are the rules for the cropmarks.  Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+  {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+  {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.  The argument is the rest of
+% the input line (except we remove a trailing comment).  #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg{\parseargusing{}}
+\def\parseargusing#1#2{%
+  \def\next{#2}%
+  \begingroup
+    \obeylines
+    \spaceisspace
+    #1%
+    \parseargline\empty% Insert the \empty token, see \finishparsearg below.
+}
+
+{\obeylines %
+  \gdef\parseargline#1^^M{%
+    \endgroup % End of the group started in \parsearg.
+    \argremovecomment #1\comment\ArgTerm%
+  }%
+}
+
+% First remove any @comment, then any @c comment.
+\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
+\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}
+
+% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space.
+%
+% \argremovec might leave us with trailing space, e.g.,
+%    @end itemize  @c foo
+% This space token undergoes the same procedure and is eventually removed
+% by \finishparsearg.
+%
+\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M}
+\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M}
+\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{%
+  \def\temp{#3}%
+  \ifx\temp\empty
+    % We cannot use \next here, as it holds the macro to run;
+    % thus we reuse \temp.
+    \let\temp\finishparsearg
+  \else
+    \let\temp\argcheckspaces
+  \fi
+  % Put the space token in:
+  \temp#1 #3\ArgTerm
+}
+
+% If a _delimited_ argument is enclosed in braces, they get stripped; so
+% to get _exactly_ the rest of the line, we had to prevent such situation.
+% We prepended an \empty token at the very beginning and we expand it now,
+% just before passing the control to \next.
+% (Similarily, we have to think about #3 of \argcheckspacesY above: it is
+% either the null string, or it ends with \^^M---thus there is no danger
+% that a pair of braces would be stripped.
+%
+% But first, we have to remove the trailing space token.
+%
+\def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}}
+
+% \parseargdef\foo{...}
+%	is roughly equivalent to
+% \def\foo{\parsearg\Xfoo}
+% \def\Xfoo#1{...}
+%
+% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my
+% favourite TeX trick.  --kasal, 16nov03
+
+\def\parseargdef#1{%
+  \expandafter \doparseargdef \csname\string#1\endcsname #1%
+}
+\def\doparseargdef#1#2{%
+  \def#2{\parsearg#1}%
+  \def#1##1%
+}
+
+% Several utility definitions with active space:
+{
+  \obeyspaces
+  \gdef\obeyedspace{ }
+
+  % Make each space character in the input produce a normal interword
+  % space in the output.  Don't allow a line break at this space, as this
+  % is used only in environments like @example, where each line of input
+  % should produce a line of output anyway.
+  %
+  \gdef\sepspaces{\obeyspaces\let =\tie}
+
+  % If an index command is used in an @example environment, any spaces
+  % therein should become regular spaces in the raw index file, not the
+  % expansion of \tie (\leavevmode \penalty \@M \ ).
+  \gdef\unsepspaces{\let =\space}
+}
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+% Define the framework for environments in texinfo.tex.  It's used like this:
+%
+%   \envdef\foo{...}
+%   \def\Efoo{...}
+%
+% It's the responsibility of \envdef to insert \begingroup before the
+% actual body; @end closes the group after calling \Efoo.  \envdef also
+% defines \thisenv, so the current environment is known; @end checks
+% whether the environment name matches.  The \checkenv macro can also be
+% used to check whether the current environment is the one expected.
+%
+% Non-false conditionals (@iftex, @ifset) don't fit into this, so they
+% are not treated as enviroments; they don't open a group.  (The
+% implementation of @end takes care not to call \endgroup in this
+% special case.)
+
+
+% At runtime, environments start with this:
+\def\startenvironment#1{\begingroup\def\thisenv{#1}}
+% initialize
+\let\thisenv\empty
+
+% ... but they get defined via ``\envdef\foo{...}'':
+\long\def\envdef#1#2{\def#1{\startenvironment#1#2}}
+\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}}
+
+% Check whether we're in the right environment:
+\def\checkenv#1{%
+  \def\temp{#1}%
+  \ifx\thisenv\temp
+  \else
+    \badenverr
+  \fi
+}
+
+% Evironment mismatch, #1 expected:
+\def\badenverr{%
+  \errhelp = \EMsimple
+  \errmessage{This command can appear only \inenvironment\temp,
+    not \inenvironment\thisenv}%
+}
+\def\inenvironment#1{%
+  \ifx#1\empty
+    out of any environment%
+  \else
+    in environment \expandafter\string#1%
+  \fi
+}
+
+% @end foo executes the definition of \Efoo.
+% But first, it executes a specialized version of \checkenv
+%
+\parseargdef\end{%
+  \if 1\csname iscond.#1\endcsname
+  \else
+    % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03
+    \expandafter\checkenv\csname#1\endcsname
+    \csname E#1\endcsname
+    \endgroup
+  \fi
+}
+
+\newhelp\EMsimple{Press RETURN to continue.}
+
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt\char64}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt\char123}}
+\def\myrbrace {{\tt\char125}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+  % Definitions to produce \{ and \} commands for indices,
+  % and @{ and @} for the aux file.
+  \catcode`\{ = \other \catcode`\} = \other
+  \catcode`\[ = 1 \catcode`\] = 2
+  \catcode`\! = 0 \catcode`\\ = \other
+  !gdef!lbracecmd[\{]%
+  !gdef!rbracecmd[\}]%
+  !gdef!lbraceatcmd[@{]%
+  !gdef!rbraceatcmd[@}]%
+!endgroup
+
+% @comma{} to avoid , parsing problems.
+\let\comma = ,
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown @ordf @ordm
+% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
+\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+  \def\temp{#1}%
+  \ifx\temp\imacro \ptexi
+  \else\ifx\temp\jmacro \j
+  \else \errmessage{@dotless can be used only with i or j}%
+  \fi\fi
+}
+
+% The \TeX{} logo, as in plain, but resetting the spacing so that a
+% period following counts as ending a sentence.  (Idea found in latex.)
+%
+\edef\TeX{\TeX \spacefactor=1000 }
+
+% @LaTeX{} logo.  Not quite the same results as the definition in
+% latex.ltx, since we use a different font for the raised A; it's most
+% convenient for us to use an explicitly smaller font, rather than using
+% the \scriptstyle font (since we don't reset \scriptstyle and
+% \scriptscriptstyle).
+%
+\def\LaTeX{%
+  L\kern-.36em
+  {\setbox0=\hbox{T}%
+   \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}%
+  \kern-.15em
+  \TeX
+}
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @/ allows a line break.
+\let\/=\allowbreak
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @! is an end-of-sentence bang.
+\def\!{!\spacefactor=3000 }
+
+% @? is an end-of-sentence query.
+\def\?{?\spacefactor=3000 }
+
+% @w prevents a word break.  Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox.  We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line.  According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0).  If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+% Another complication is that the group might be very large.  This can
+% cause the glue on the previous page to be unduly stretched, because it
+% does not have much material.  In this case, it's better to add an
+% explicit \vfill so that the extra space is at the bottom.  The
+% threshold for doing this is if the group is more than \vfilllimit
+% percent of a page (\vfilllimit can be changed inside of @tex).
+%
+\newbox\groupbox
+\def\vfilllimit{0.7}
+%
+\envdef\group{%
+  \ifnum\catcode`\^^M=\active \else
+    \errhelp = \groupinvalidhelp
+    \errmessage{@group invalid in context where filling is enabled}%
+  \fi
+  \startsavinginserts
+  %
+  \setbox\groupbox = \vtop\bgroup
+    % Do @comment since we are called inside an environment such as
+    % @example, where each end-of-line in the input causes an
+    % end-of-line in the output.  We don't want the end-of-line after
+    % the `@group' to put extra space in the output.  Since @group
+    % should appear on a line by itself (according to the Texinfo
+    % manual), we don't worry about eating any user text.
+    \comment
+}
+%
+% The \vtop produces a box with normal height and large depth; thus, TeX puts
+% \baselineskip glue before it, and (when the next line of text is done)
+% \lineskip glue after it.  Thus, space below is not quite equal to space
+% above.  But it's pretty close.
+\def\Egroup{%
+    % To get correct interline space between the last line of the group
+    % and the first line afterwards, we have to propagate \prevdepth.
+    \endgraf % Not \par, as it may have been set to \lisppar.
+    \global\dimen1 = \prevdepth
+  \egroup           % End the \vtop.
+  % \dimen0 is the vertical size of the group's box.
+  \dimen0 = \ht\groupbox  \advance\dimen0 by \dp\groupbox
+  % \dimen2 is how much space is left on the page (more or less).
+  \dimen2 = \pageheight   \advance\dimen2 by -\pagetotal
+  % if the group doesn't fit on the current page, and it's a big big
+  % group, force a page break.
+  \ifdim \dimen0 > \dimen2
+    \ifdim \pagetotal < \vfilllimit\pageheight
+      \page
+    \fi
+  \fi
+  \box\groupbox
+  \prevdepth = \dimen1
+  \checkinserts
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil  \mil=0.001in
+
+% Old definition--didn't work.
+%\parseargdef\need{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
+%\prevdepth=-1000pt
+%}}
+
+\parseargdef\need{%
+  % Ensure vertical mode, so we don't make a big box in the middle of a
+  % paragraph.
+  \par
+  %
+  % If the @need value is less than one line space, it's useless.
+  \dimen0 = #1\mil
+  \dimen2 = \ht\strutbox
+  \advance\dimen2 by \dp\strutbox
+  \ifdim\dimen0 > \dimen2
+    %
+    % Do a \strut just to make the height of this box be normal, so the
+    % normal leading is inserted relative to the preceding line.
+    % And a page break here is fine.
+    \vtop to #1\mil{\strut\vfil}%
+    %
+    % TeX does not even consider page breaks if a penalty added to the
+    % main vertical list is 10000 or more.  But in order to see if the
+    % empty box we just added fits on the page, we must make it consider
+    % page breaks.  On the other hand, we don't want to actually break the
+    % page after the empty box.  So we use a penalty of 9999.
+    %
+    % There is an extremely small chance that TeX will actually break the
+    % page at this \penalty, if there are no other feasible breakpoints in
+    % sight.  (If the user is using lots of big @group commands, which
+    % almost-but-not-quite fill up a page, TeX will have a hard time doing
+    % good page breaking, for example.)  However, I could not construct an
+    % example where a page broke at this \penalty; if it happens in a real
+    % document, then we can reconsider our strategy.
+    \penalty9999
+    %
+    % Back up by the size of the box, whether we did a page break or not.
+    \kern -#1\mil
+    %
+    % Do not allow a page break right after this kern.
+    \nobreak
+  \fi
+}
+
+% @br   forces paragraph break (and is undocumented).
+
+\let\br = \par
+
+% @page forces the start of a new page.
+%
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}
+
+% This defn is used inside nofill environments such as @example.
+\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount
+  \leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
+% paragraph.  For more general purposes, use the \margin insertion
+% class.  WHICH is `l' or `r'.
+%
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+%
+\def\doinmargin#1#2{\strut\vadjust{%
+  \nobreak
+  \kern-\strutdepth
+  \vtop to \strutdepth{%
+    \baselineskip=\strutdepth
+    \vss
+    % if you have multiple lines of stuff to put here, you'll need to
+    % make the vbox yourself of the appropriate size.
+    \ifx#1l%
+      \llap{\ignorespaces #2\hskip\inmarginspacing}%
+    \else
+      \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}%
+    \fi
+    \null
+  }%
+}}
+\def\inleftmargin{\doinmargin l}
+\def\inrightmargin{\doinmargin r}
+%
+% @inmargin{TEXT [, RIGHT-TEXT]}
+% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right;
+% else use TEXT for both).
+%
+\def\inmargin#1{\parseinmargin #1,,\finish}
+\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing.
+  \setbox0 = \hbox{\ignorespaces #2}%
+  \ifdim\wd0 > 0pt
+    \def\lefttext{#1}%  have both texts
+    \def\righttext{#2}%
+  \else
+    \def\lefttext{#1}%  have only one text
+    \def\righttext{#1}%
+  \fi
+  %
+  \ifodd\pageno
+    \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin
+  \else
+    \def\temp{\inleftmargin\lefttext}%
+  \fi
+  \temp
+}
+
+% @include file    insert text of that file as input.
+%
+\def\include{\parseargusing\filenamecatcodes\includezzz}
+\def\includezzz#1{%
+  \pushthisfilestack
+  \def\thisfile{#1}%
+  {%
+    \makevalueexpandable
+    \def\temp{\input #1 }%
+    \expandafter
+  }\temp
+  \popthisfilestack
+}
+\def\filenamecatcodes{%
+  \catcode`\\=\other
+  \catcode`~=\other
+  \catcode`^=\other
+  \catcode`_=\other
+  \catcode`|=\other
+  \catcode`<=\other
+  \catcode`>=\other
+  \catcode`+=\other
+  \catcode`-=\other
+}
+
+\def\pushthisfilestack{%
+  \expandafter\pushthisfilestackX\popthisfilestack\StackTerm
+}
+\def\pushthisfilestackX{%
+  \expandafter\pushthisfilestackY\thisfile\StackTerm
+}
+\def\pushthisfilestackY #1\StackTerm #2\StackTerm {%
+  \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}%
+}
+
+\def\popthisfilestack{\errthisfilestackempty}
+\def\errthisfilestackempty{\errmessage{Internal error:
+  the stack of filenames is empty.}}
+
+\def\thisfile{}
+
+% @center line
+% outputs that line, centered.
+%
+\parseargdef\center{%
+  \ifhmode
+    \let\next\centerH
+  \else
+    \let\next\centerV
+  \fi
+  \next{\hfil \ignorespaces#1\unskip \hfil}%
+}
+\def\centerH#1{%
+  {%
+    \hfil\break
+    \advance\hsize by -\leftskip
+    \advance\hsize by -\rightskip
+    \line{#1}%
+    \break
+  }%
+}
+\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}}
+
+% @sp n   outputs n lines of vertical space
+
+\parseargdef\sp{\vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore  is another way to write a comment
+
+\def\comment{\begingroup \catcode`\^^M=\other%
+\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
+\commentxxx}
+{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
+
+\let\c=\comment
+
+% @paragraphindent NCHARS
+% We'll use ems for NCHARS, close enough.
+% NCHARS can also be the word `asis' or `none'.
+% We cannot feasibly implement @paragraphindent asis, though.
+%
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
+%
+\parseargdef\paragraphindent{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \defaultparindent = 0pt
+    \else
+      \defaultparindent = #1em
+    \fi
+  \fi
+  \parindent = \defaultparindent
+}
+
+% @exampleindent NCHARS
+% We'll use ems for NCHARS like @paragraphindent.
+% It seems @exampleindent asis isn't necessary, but
+% I preserve it to make it similar to @paragraphindent.
+\parseargdef\exampleindent{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \lispnarrowing = 0pt
+    \else
+      \lispnarrowing = #1em
+    \fi
+  \fi
+}
+
+% @firstparagraphindent WORD
+% If WORD is `none', then suppress indentation of the first paragraph
+% after a section heading.  If WORD is `insert', then do indent at such
+% paragraphs.
+%
+% The paragraph indentation is suppressed or not by calling
+% \suppressfirstparagraphindent, which the sectioning commands do.
+% We switch the definition of this back and forth according to WORD.
+% By default, we suppress indentation.
+%
+\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent}
+\def\insertword{insert}
+%
+\parseargdef\firstparagraphindent{%
+  \def\temp{#1}%
+  \ifx\temp\noneword
+    \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent
+  \else\ifx\temp\insertword
+    \let\suppressfirstparagraphindent = \relax
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @firstparagraphindent option `\temp'}%
+  \fi\fi
+}
+
+% Here is how we actually suppress indentation.  Redefine \everypar to
+% \kern backwards by \parindent, and then reset itself to empty.
+%
+% We also make \indent itself not actually do anything until the next
+% paragraph.
+%
+\gdef\dosuppressfirstparagraphindent{%
+  \gdef\indent{%
+    \restorefirstparagraphindent
+    \indent
+  }%
+  \gdef\noindent{%
+    \restorefirstparagraphindent
+    \noindent
+  }%
+  \global\everypar = {%
+    \kern -\parindent
+    \restorefirstparagraphindent
+  }%
+}
+
+\gdef\restorefirstparagraphindent{%
+  \global \let \indent = \ptexindent
+  \global \let \noindent = \ptexnoindent
+  \global \everypar = {}%
+}
+
+
+% @asis just yields its argument.  Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math outputs its argument in math mode.
+%
+% One complication: _ usually means subscripts, but it could also mean
+% an actual _ character, as in @math{@var{some_variable} + 1}.  So make
+% _ active, and distinguish by seeing if the current family is \slfam,
+% which is what @var uses.
+{
+  \catcode\underChar = \active
+  \gdef\mathunderscore{%
+    \catcode\underChar=\active
+    \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
+  }
+}
+% Another complication: we want \\ (and @\) to output a \ character.
+% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
+% this is not advertised and we don't care.  Texinfo does not
+% otherwise define @\.
+%
+% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
+\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
+%
+\def\math{%
+  \tex
+  \mathunderscore
+  \let\\ = \mathbackslash
+  \mathactive
+  $\finishmath
+}
+\def\finishmath#1{#1$\endgroup}  % Close the group opened by \tex.
+
+% Some active characters (such as <) are spaced differently in math.
+% We have to reset their definitions in case the @math was an argument
+% to a command which sets the catcodes (such as @item or @section).
+%
+{
+  \catcode`^ = \active
+  \catcode`< = \active
+  \catcode`> = \active
+  \catcode`+ = \active
+  \gdef\mathactive{%
+    \let^ = \ptexhat
+    \let< = \ptexless
+    \let> = \ptexgtr
+    \let+ = \ptexplus
+  }
+}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+% @dots{} outputs an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in a typewriter
+% font as three actual period characters.
+%
+\def\dots{%
+  \leavevmode
+  \hbox to 1.5em{%
+    \hskip 0pt plus 0.25fil
+    .\hfil.\hfil.%
+    \hskip 0pt plus 0.5fil
+  }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+  \dots
+  \spacefactor=3000
+}
+
+% @comma{} is so commas can be inserted into text without messing up
+% Texinfo's parsing.
+%
+\let\comma = ,
+
+% @refill is a no-op.
+\let\refill=\relax
+
+% If working on a large document in chapters, it is convenient to
+% be able to disable indexing, cross-referencing, and contents, for test runs.
+% This is done with @novalidate (before @setfilename).
+%
+\newif\iflinks \linkstrue % by default we want the aux files.
+\let\novalidate = \linksfalse
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+   \fixbackslash  % Turn off hack to swallow `\input texinfo'.
+   \iflinks
+     \tryauxfile
+     % Open the new aux file.  TeX will close it automatically at exit.
+     \immediate\openout\auxfile=\jobname.aux
+   \fi % \openindices needs to do some work in any case.
+   \openindices
+   \let\setfilename=\comment % Ignore extra @setfilename cmds.
+   %
+   % If texinfo.cnf is present on the system, read it.
+   % Useful for site-wide @afourpaper, etc.
+   \openin 1 texinfo.cnf
+   \ifeof 1 \else \input texinfo.cnf \fi
+   \closein 1
+   %
+   \comment % Ignore the actual filename.
+}
+
+% Called from \setfilename.
+%
+\def\openindices{%
+  \newindex{cp}%
+  \newcodeindex{fn}%
+  \newcodeindex{vr}%
+  \newcodeindex{tp}%
+  \newcodeindex{ky}%
+  \newcodeindex{pg}%
+}
+
+% @bye.
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+
+\message{pdf,}
+% adobe `portable' document format
+\newcount\tempnum
+\newcount\lnkcount
+\newtoks\filename
+\newcount\filenamelength
+\newcount\pgn
+\newtoks\toksA
+\newtoks\toksB
+\newtoks\toksC
+\newtoks\toksD
+\newbox\boxA
+\newcount\countA
+\newif\ifpdf
+\newif\ifpdfmakepagedest
+
+% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1
+% can be set).  So we test for \relax and 0 as well as \undefined,
+% borrowed from ifpdf.sty.
+\ifx\pdfoutput\undefined
+\else
+  \ifx\pdfoutput\relax
+  \else
+    \ifcase\pdfoutput
+    \else
+      \pdftrue
+    \fi
+  \fi
+\fi
+%
+\ifpdf
+  \input pdfcolor
+  \pdfcatalog{/PageMode /UseOutlines}%
+  \def\dopdfimage#1#2#3{%
+    \def\imagewidth{#2}%
+    \def\imageheight{#3}%
+    % without \immediate, pdftex seg faults when the same image is
+    % included twice.  (Version 3.14159-pre-1.0-unofficial-20010704.)
+    \ifnum\pdftexversion < 14
+      \immediate\pdfimage
+    \else
+      \immediate\pdfximage
+    \fi
+      \ifx\empty\imagewidth\else width \imagewidth \fi
+      \ifx\empty\imageheight\else height \imageheight \fi
+      \ifnum\pdftexversion<13
+         #1.pdf%
+       \else
+         {#1.pdf}%
+       \fi
+    \ifnum\pdftexversion < 14 \else
+      \pdfrefximage \pdflastximage
+    \fi}
+  \def\pdfmkdest#1{{%
+    % We have to set dummies so commands such as @code in a section title
+    % aren't expanded.
+    \atdummies
+    \normalturnoffactive
+    \pdfdest name{#1} xyz%
+  }}
+  \def\pdfmkpgn#1{#1}
+  \let\linkcolor = \Blue  % was Cyan, but that seems light?
+  \def\endlink{\Black\pdfendlink}
+  % Adding outlines to PDF; macros for calculating structure of outlines
+  % come from Petr Olsak
+  \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
+    \else \csname#1\endcsname \fi}
+  \def\advancenumber#1{\tempnum=\expnumber{#1}\relax
+    \advance\tempnum by 1
+    \expandafter\xdef\csname#1\endcsname{\the\tempnum}}
+  %
+  % #1 is the section text.  #2 is the pdf expression for the number
+  % of subentries (or empty, for subsubsections).  #3 is the node
+  % text, which might be empty if this toc entry had no
+  % corresponding node.  #4 is the page number.
+  %
+  \def\dopdfoutline#1#2#3#4{%
+    % Generate a link to the node text if that exists; else, use the
+    % page number.  We could generate a destination for the section
+    % text in the case where a section has no node, but it doesn't
+    % seem worthwhile, since most documents are normally structured.
+    \def\pdfoutlinedest{#3}%
+    \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}\fi
+    %
+    \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{#1}%
+  }
+  %
+  \def\pdfmakeoutlines{%
+    \begingroup
+      % Thanh's hack / proper braces in bookmarks
+      \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
+      \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
+      %
+      % Read toc silently, to get counts of subentries for \pdfoutline.
+      \def\numchapentry##1##2##3##4{%
+	\def\thischapnum{##2}%
+	\let\thissecnum\empty
+	\let\thissubsecnum\empty
+      }%
+      \def\numsecentry##1##2##3##4{%
+	\advancenumber{chap\thischapnum}%
+	\def\thissecnum{##2}%
+	\let\thissubsecnum\empty
+      }%
+      \def\numsubsecentry##1##2##3##4{%
+	\advancenumber{sec\thissecnum}%
+	\def\thissubsecnum{##2}%
+      }%
+      \def\numsubsubsecentry##1##2##3##4{%
+	\advancenumber{subsec\thissubsecnum}%
+      }%
+      \let\thischapnum\empty
+      \let\thissecnum\empty
+      \let\thissubsecnum\empty
+      %
+      % use \def rather than \let here because we redefine \chapentry et
+      % al. a second time, below.
+      \def\appentry{\numchapentry}%
+      \def\appsecentry{\numsecentry}%
+      \def\appsubsecentry{\numsubsecentry}%
+      \def\appsubsubsecentry{\numsubsubsecentry}%
+      \def\unnchapentry{\numchapentry}%
+      \def\unnsecentry{\numsecentry}%
+      \def\unnsubsecentry{\numsubsecentry}%
+      \def\unnsubsubsecentry{\numsubsubsecentry}%
+      \input \jobname.toc
+      %
+      % Read toc second time, this time actually producing the outlines.
+      % The `-' means take the \expnumber as the absolute number of
+      % subentries, which we calculated on our first read of the .toc above.
+      %
+      % We use the node names as the destinations.
+      \def\numchapentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}%
+      \def\numsecentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}%
+      \def\numsubsecentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}%
+      \def\numsubsubsecentry##1##2##3##4{% count is always zero
+        \dopdfoutline{##1}{}{##3}{##4}}%
+      %
+      % PDF outlines are displayed using system fonts, instead of
+      % document fonts.  Therefore we cannot use special characters,
+      % since the encoding is unknown.  For example, the eogonek from
+      % Latin 2 (0xea) gets translated to a | character.  Info from
+      % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100.
+      %
+      % xx to do this right, we have to translate 8-bit characters to
+      % their "best" equivalent, based on the @documentencoding.  Right
+      % now, I guess we'll just let the pdf reader have its way.
+      \indexnofonts
+      \turnoffactive
+      \input \jobname.toc
+    \endgroup
+  }
+  %
+  \def\makelinks #1,{%
+    \def\params{#1}\def\E{END}%
+    \ifx\params\E
+      \let\nextmakelinks=\relax
+    \else
+      \let\nextmakelinks=\makelinks
+      \ifnum\lnkcount>0,\fi
+      \picknum{#1}%
+      \startlink attr{/Border [0 0 0]}
+        goto name{\pdfmkpgn{\the\pgn}}%
+      \linkcolor #1%
+      \advance\lnkcount by 1%
+      \endlink
+    \fi
+    \nextmakelinks
+  }
+  \def\picknum#1{\expandafter\pn#1}
+  \def\pn#1{%
+    \def\p{#1}%
+    \ifx\p\lbrace
+      \let\nextpn=\ppn
+    \else
+      \let\nextpn=\ppnn
+      \def\first{#1}
+    \fi
+    \nextpn
+  }
+  \def\ppn#1{\pgn=#1\gobble}
+  \def\ppnn{\pgn=\first}
+  \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,}
+  \def\skipspaces#1{\def\PP{#1}\def\D{|}%
+    \ifx\PP\D\let\nextsp\relax
+    \else\let\nextsp\skipspaces
+      \ifx\p\space\else\addtokens{\filename}{\PP}%
+        \advance\filenamelength by 1
+      \fi
+    \fi
+    \nextsp}
+  \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+  \ifnum\pdftexversion < 14
+    \let \startlink \pdfannotlink
+  \else
+    \let \startlink \pdfstartlink
+  \fi
+  \def\pdfurl#1{%
+    \begingroup
+      \normalturnoffactive\def\@{@}%
+      \makevalueexpandable
+      \leavevmode\Red
+      \startlink attr{/Border [0 0 0]}%
+        user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
+    \endgroup}
+  \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}}
+  \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+  \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
+  \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}}
+  \def\maketoks{%
+    \expandafter\poptoks\the\toksA|ENDTOKS|\relax
+    \ifx\first0\adn0
+    \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3
+    \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6
+    \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9
+    \else
+      \ifnum0=\countA\else\makelink\fi
+      \ifx\first.\let\next=\done\else
+        \let\next=\maketoks
+        \addtokens{\toksB}{\the\toksD}
+        \ifx\first,\addtokens{\toksB}{\space}\fi
+      \fi
+    \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+    \next}
+  \def\makelink{\addtokens{\toksB}%
+    {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
+  \def\pdflink#1{%
+    \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
+    \linkcolor #1\endlink}
+  \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
+\else
+  \let\pdfmkdest = \gobble
+  \let\pdfurl = \gobble
+  \let\endlink = \relax
+  \let\linkcolor = \relax
+  \let\pdfmakeoutlines = \relax
+\fi  % \ifx\pdfoutput
+
+
+\message{fonts,}
+
+% Change the current font style to #1, remembering it in \curfontstyle.
+% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in
+% italics, not bold italics.
+%
+\def\setfontstyle#1{%
+  \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd.
+  \csname ten#1\endcsname  % change the current font
+}
+
+% Select #1 fonts with the current style.
+%
+\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname}
+
+\def\rm{\fam=0 \setfontstyle{rm}}
+\def\it{\fam=\itfam \setfontstyle{it}}
+\def\sl{\fam=\slfam \setfontstyle{sl}}
+\def\bf{\fam=\bffam \setfontstyle{bf}}
+\def\tt{\fam=\ttfam \setfontstyle{tt}}
+
+% Texinfo sort of supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf.
+\newfam\sffam
+\def\sf{\fam=\sffam \setfontstyle{sf}}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this font style.
+\def\ttsl{\setfontstyle{ttsl}}
+
+% Default leading.
+\newdimen\textleading  \textleading = 13.2pt
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly.  There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+  \normalbaselineskip = #1\relax
+  \normallineskip = \lineskipfactor\normalbaselineskip
+  \normalbaselines
+  \setbox\strutbox =\hbox{%
+    \vrule width0pt height\strutheightpercent\baselineskip
+                    depth \strutdepthpercent \baselineskip
+  }%
+}
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx}               %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+% Text fonts (11.2pt, magstep1).
+\newcount\mainmagstep
+\ifx\bigger\relax
+  % not really supported.
+  \mainmagstep=\magstep1
+  \setfont\textrm\rmshape{12}{1000}
+  \setfont\texttt\ttshape{12}{1000}
+\else
+  \mainmagstep=\magstephalf
+  \setfont\textrm\rmshape{10}{\mainmagstep}
+  \setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun names and args.
+\setfont\defbf\bfshape{10}{\magstep1}
+\setfont\deftt\ttshape{10}{\magstep1}
+\setfont\defttsl\ttslshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
+
+% Fonts for indices, footnotes, small examples (9pt).
+\setfont\smallrm\rmshape{9}{1000}
+\setfont\smalltt\ttshape{9}{1000}
+\setfont\smallbf\bfshape{10}{900}
+\setfont\smallit\itshape{9}{1000}
+\setfont\smallsl\slshape{9}{1000}
+\setfont\smallsf\sfshape{9}{1000}
+\setfont\smallsc\scshape{10}{900}
+\setfont\smallttsl\ttslshape{10}{900}
+\font\smalli=cmmi9
+\font\smallsy=cmsy9
+
+% Fonts for small examples (8pt).
+\setfont\smallerrm\rmshape{8}{1000}
+\setfont\smallertt\ttshape{8}{1000}
+\setfont\smallerbf\bfshape{10}{800}
+\setfont\smallerit\itshape{8}{1000}
+\setfont\smallersl\slshape{8}{1000}
+\setfont\smallersf\sfshape{8}{1000}
+\setfont\smallersc\scshape{10}{800}
+\setfont\smallerttsl\ttslshape{10}{800}
+\font\smalleri=cmmi8
+\font\smallersy=cmsy8
+
+% Fonts for title page (20.4pt):
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\setfont\titleit\itbshape{10}{\magstep4}
+\setfont\titlesl\slbshape{10}{\magstep4}
+\setfont\titlett\ttbshape{12}{\magstep3}
+\setfont\titlettsl\ttslshape{10}{\magstep4}
+\setfont\titlesf\sfbshape{17}{\magstep1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+\def\authortt{\sectt}
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{17}{1000}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+% Section fonts (14.4pt).
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% Subsection fonts (13.15pt).
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{1315}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{1315}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled 1315
+
+% Reduced fonts for @acro in text (10pt).
+\setfont\reducedrm\rmshape{10}{1000}
+\setfont\reducedtt\ttshape{10}{1000}
+\setfont\reducedbf\bfshape{10}{1000}
+\setfont\reducedit\itshape{10}{1000}
+\setfont\reducedsl\slshape{10}{1000}
+\setfont\reducedsf\sfshape{10}{1000}
+\setfont\reducedsc\scshape{10}{1000}
+\setfont\reducedttsl\ttslshape{10}{1000}
+\font\reducedi=cmmi10
+\font\reducedsy=cmsy10
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families.  Since
+% texinfo doesn't allow for producing subscripts and superscripts except
+% in the main text, we don't bother to reset \scriptfont and
+% \scriptscriptfont (which would also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+  \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy
+  \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf
+  \textfont\ttfam=\tentt \textfont\sffam=\tensf
+}
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE.  We do this because \STYLE needs to also set the
+% current \fam for math mode.  Our \STYLE (e.g., \rm) commands hardwire
+% \tenSTYLE to set the current font.
+%
+% Each font-changing command also sets the names \lsize (one size lower)
+% and \lllsize (three sizes lower).  These relative commands are used in
+% the LaTeX logo and acronyms.
+%
+% This all needs generalizing, badly.
+%
+\def\textfonts{%
+  \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+  \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+  \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+  \let\tenttsl=\textttsl
+  \def\lsize{reduced}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{\textleading}}
+\def\titlefonts{%
+  \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
+  \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
+  \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
+  \let\tenttsl=\titlettsl
+  \def\lsize{chap}\def\lllsize{subsec}%
+  \resetmathfonts \setleading{25pt}}
+\def\titlefont#1{{\titlefonts\rm #1}}
+\def\chapfonts{%
+  \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+  \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+  \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+  \def\lsize{sec}\def\lllsize{text}%
+  \resetmathfonts \setleading{19pt}}
+\def\secfonts{%
+  \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+  \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+  \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+  \let\tenttsl=\secttsl
+  \def\lsize{subsec}\def\lllsize{reduced}%
+  \resetmathfonts \setleading{16pt}}
+\def\subsecfonts{%
+  \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+  \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+  \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+  \let\tenttsl=\ssecttsl
+  \def\lsize{text}\def\lllsize{small}%
+  \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts
+\def\reducedfonts{%
+  \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl
+  \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc
+  \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy
+  \let\tenttsl=\reducedttsl
+  \def\lsize{small}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{10.5pt}}
+\def\smallfonts{%
+  \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl
+  \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc
+  \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy
+  \let\tenttsl=\smallttsl
+  \def\lsize{smaller}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{10.5pt}}
+\def\smallerfonts{%
+  \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl
+  \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc
+  \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy
+  \let\tenttsl=\smallerttsl
+  \def\lsize{smaller}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{9.5pt}}
+
+% Set the fonts to use with the @small... environments.
+\let\smallexamplefonts = \smallfonts
+
+% About \smallexamplefonts.  If we use \smallfonts (9pt), @smallexample
+% can fit this many characters:
+%   8.5x11=86   smallbook=72  a4=90  a5=69
+% If we use \scriptfonts (8pt), then we can fit this many characters:
+%   8.5x11=90+  smallbook=80  a4=90+  a5=77
+% For me, subjectively, the few extra characters that fit aren't worth
+% the additional smallness of 8pt.  So I'm making the default 9pt.
+%
+% By the way, for comparison, here's what fits with @example (10pt):
+%   8.5x11=71  smallbook=60  a4=75  a5=58
+%
+% I wish the USA used A4 paper.
+% --karl, 24jan03.
+
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts \rm
+
+% Define these so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bfshape{10}{\magstep1}  % no cmb12
+\setfont\shortcontsl\slshape{12}{1000}
+\setfont\shortconttt\ttshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else
+                    \ptexslash\fi\fi\fi}
+\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
+
+% like \smartslanted except unconditionally uses \ttsl.
+% @var is set to this for defun arguments.
+\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx}
+
+% like \smartslanted except unconditionally use \sl.  We never want
+% ttsl for book titles, do we?
+\def\cite#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\slanted=\smartslanted
+\let\var=\smartslanted
+\let\dfn=\smartslanted
+\let\emph=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph.  Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1  \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+% Set sfcode to normal for the chars that usually have another value.
+% Can't use plain's \frenchspacing because it uses the `\x notation, and
+% sometimes \x has an active definition that messes things up.
+%
+\catcode`@=11
+  \def\frenchspacing{%
+    \sfcode\dotChar  =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m
+    \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m
+  }
+\catcode`@=\other
+
+\def\t#1{%
+  {\tt \rawbackslash \frenchspacing #1}%
+  \null
+}
+\def\samp#1{`\tclose{#1}'\null}
+\setfont\keyrm\rmshape{8}{1000}
+\font\keysy=cmsy9
+\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
+  \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+    \vbox{\hrule\kern-0.4pt
+     \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+    \kern-0.4pt\hrule}%
+  \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @file, @option are the same as @samp.
+\let\file=\samp
+\let\option=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+  {%
+    % Change normal interword space to be same as for the current font.
+    \spaceskip = \fontdimen2\font
+    %
+    % Switch to typewriter.
+    \tt
+    %
+    % But `\ ' produces the large typewriter interword space.
+    \def\ {{\spaceskip = 0pt{} }}%
+    %
+    % Turn off hyphenation.
+    \nohyphenation
+    %
+    \rawbackslash
+    \frenchspacing
+    #1%
+  }%
+  \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in @code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate at a dash.
+%  -- rms.
+{
+  \catcode`\-=\active
+  \catcode`\_=\active
+  %
+  \global\def\code{\begingroup
+    \catcode`\-=\active \let-\codedash
+    \catcode`\_=\active \let_\codeunder
+    \codex
+  }
+}
+
+\def\realdash{-}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{%
+  % this is all so @math{@code{var_name}+1} can work.  In math mode, _
+  % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.)
+  % will therefore expand the active definition of _, which is us
+  % (inside @code that is), therefore an endless loop.
+  \ifusingtt{\ifmmode
+               \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_.
+             \else\normalunderscore \fi
+             \discretionary{}{}{}}%
+            {\_}%
+}
+\def\codex #1{\tclose{#1}\endgroup}
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+%   `example' (@kbd uses ttsl only inside of @example and friends),
+%   or `code' (@kbd uses normal tty font always).
+\parseargdef\kbdinputstyle{%
+  \def\arg{#1}%
+  \ifx\arg\worddistinct
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+  \else\ifx\arg\wordexample
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+  \else\ifx\arg\wordcode
+    \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @kbdinputstyle option `\arg'}%
+  \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is `distinct.'
+\kbdinputstyle distinct
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\kbdfont\look}}\fi
+\else{\tclose{\kbdfont\look}}\fi}
+
+% For @indicateurl, @env, @command quotes seem unnecessary, so use \code.
+\let\indicateurl=\code
+\let\env=\code
+\let\command=\code
+
+% @uref (abbreviation for `urlref') takes an optional (comma-separated)
+% second argument specifying the text to display and an optional third
+% arg as text to display instead of (rather than in addition to) the url
+% itself.  First (mandatory) arg is the url.  Perhaps eventually put in
+% a hypertex \special here.
+%
+\def\uref#1{\douref #1,,,\finish}
+\def\douref#1,#2,#3,#4\finish{\begingroup
+  \unsepspaces
+  \pdfurl{#1}%
+  \setbox0 = \hbox{\ignorespaces #3}%
+  \ifdim\wd0 > 0pt
+    \unhbox0 % third arg given, show only that
+  \else
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0 > 0pt
+      \ifpdf
+        \unhbox0             % PDF: 2nd arg given, show only it
+      \else
+        \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url
+      \fi
+    \else
+      \code{#1}% only url given, so show it
+    \fi
+  \fi
+  \endlink
+\endgroup}
+
+% @url synonym for @uref, since that's how everyone uses it.
+%
+\let\url=\uref
+
+% rms does not like angle brackets --karl, 17may97.
+% So now @email is just like @uref, unless we are pdf.
+%
+%\def\email#1{\angleleft{\tt #1}\angleright}
+\ifpdf
+  \def\email#1{\doemail#1,,\finish}
+  \def\doemail#1,#2,#3\finish{\begingroup
+    \unsepspaces
+    \pdfurl{mailto:#1}%
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
+    \endlink
+  \endgroup}
+\else
+  \let\email=\uref
+\fi
+
+% Check if we are currently using a typewriter font.  Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'.  The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find.  We need it for
+% Polish suppressed-l.  --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
+
+% Explicit font changes: @r, @sc, undocumented @ii.
+\def\r#1{{\rm #1}}              % roman font
+\def\sc#1{{\smallcaps#1}}       % smallcaps font
+\def\ii#1{{\it #1}}             % italic font
+
+% @acronym for "FBI", "NATO", and the like.
+% We print this one point size smaller, since it's intended for
+% all-uppercase.
+% 
+\def\acronym#1{\doacronym #1,,\finish}
+\def\doacronym#1,#2,#3\finish{%
+  {\selectfonts\lsize #1}%
+  \def\temp{#2}%
+  \ifx\temp\empty \else
+    \space ({\unsepspaces \ignorespaces \temp \unskip})%
+  \fi
+}
+
+% @abbr for "Comput. J." and the like.
+% No font change, but don't do end-of-sentence spacing.
+% 
+\def\abbr#1{\doabbr #1,,\finish}
+\def\doabbr#1,#2,#3\finish{%
+  {\frenchspacing #1}%
+  \def\temp{#2}%
+  \ifx\temp\empty \else
+    \space ({\unsepspaces \ignorespaces \temp \unskip})%
+  \fi
+}
+
+% @pounds{} is a sterling sign, which Knuth put in the CM italic font.
+%
+\def\pounds{{\it\$}}
+
+% @registeredsymbol - R in a circle.  The font for the R should really
+% be smaller yet, but lllsize is the best we can do for now.
+% Adapted from the plain.tex definition of \copyright.
+%
+\def\registeredsymbol{%
+  $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}%
+               \hfil\crcr\Orb}}%
+    }$%
+}
+
+% Laurent Siebenmann reports \Orb undefined with:
+%  Textures 1.7.7 (preloaded format=plain 93.10.14)  (68K)  16 APR 2004 02:38
+% so we'll define it if necessary.
+% 
+\ifx\Orb\undefined
+\def\Orb{\mathhexbox20D}
+\fi
+
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page.  Must do @settitle before @titlepage.
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+% Do an implicit @contents or @shortcontents after @end titlepage if the
+% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
+%
+\newif\ifsetcontentsaftertitlepage
+ \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
+\newif\ifsetshortcontentsaftertitlepage
+ \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
+
+\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+        \endgroup\page\hbox{}\page}
+
+\envdef\titlepage{%
+  % Open one extra group, as we want to close it in the middle of \Etitlepage.
+  \begingroup
+    \parindent=0pt \textfonts
+    % Leave some space at the very top of the page.
+    \vglue\titlepagetopglue
+    % No rule at page bottom unless we print one at the top with @title.
+    \finishedtitlepagetrue
+    %
+    % Most title ``pages'' are actually two pages long, with space
+    % at the top of the second.  We don't want the ragged left on the second.
+    \let\oldpage = \page
+    \def\page{%
+      \iffinishedtitlepage\else
+	 \finishtitlepage
+      \fi
+      \let\page = \oldpage
+      \page
+      \null
+    }%
+}
+
+\def\Etitlepage{%
+    \iffinishedtitlepage\else
+	\finishtitlepage
+    \fi
+    % It is important to do the page break before ending the group,
+    % because the headline and footline are only empty inside the group.
+    % If we use the new definition of \page, we always get a blank page
+    % after the title page, which we certainly don't want.
+    \oldpage
+  \endgroup
+  %
+  % Need this before the \...aftertitlepage checks so that if they are
+  % in effect the toc pages will come out with page numbers.
+  \HEADINGSon
+  %
+  % If they want short, they certainly want long too.
+  \ifsetshortcontentsaftertitlepage
+    \shortcontents
+    \contents
+    \global\let\shortcontents = \relax
+    \global\let\contents = \relax
+  \fi
+  %
+  \ifsetcontentsaftertitlepage
+    \contents
+    \global\let\contents = \relax
+    \global\let\shortcontents = \relax
+  \fi
+}
+
+\def\finishtitlepage{%
+  \vskip4pt \hrule height 2pt width \hsize
+  \vskip\titlepagebottomglue
+  \finishedtitlepagetrue
+}
+
+%%% Macros to be used within @titlepage:
+
+\let\subtitlerm=\tenrm
+\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}
+
+\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines
+		\let\tt=\authortt}
+
+\parseargdef\title{%
+  \checkenv\titlepage
+  \leftline{\titlefonts\rm #1}
+  % print a rule at the page bottom also.
+  \finishedtitlepagefalse
+  \vskip4pt \hrule height 4pt width \hsize \vskip4pt
+}
+
+\parseargdef\subtitle{%
+  \checkenv\titlepage
+  {\subtitlefont \rightline{#1}}%
+}
+
+% @author should come last, but may come many times.
+% It can also be used inside @quotation.
+%
+\parseargdef\author{%
+  \def\temp{\quotation}%
+  \ifx\thisenv\temp
+    \def\quotationauthor{#1}% printed in \Equotation.
+  \else
+    \checkenv\titlepage
+    \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi
+    {\authorfont \leftline{#1}}%
+  \fi
+}
+
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks\evenheadline    % headline on even pages
+\newtoks\oddheadline     % headline on odd pages
+\newtoks\evenfootline    % footline on even pages
+\newtoks\oddfootline     % footline on odd pages
+
+% Now make TeX use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+                            \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+                            \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what  @headings on  does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish}
+\def\evenheadingyyy #1\|#2\|#3\|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish}
+\def\oddheadingyyy #1\|#2\|#3\|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish}
+\def\evenfootingyyy #1\|#2\|#3\|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish}
+\def\oddfootingyyy #1\|#2\|#3\|#4\finish{%
+  \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
+  %
+  % Leave some space for the footline.  Hopefully ok to assume
+  % @evenfooting will not be used by itself.
+  \global\advance\pageheight by -\baselineskip
+  \global\advance\vsize by -\baselineskip
+}
+
+\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+
+
+% @headings double      turns headings on for double-sided printing.
+% @headings single      turns headings on for single-sided printing.
+% @headings off         turns them off.
+% @headings on          same as @headings double, retained for compatibility.
+% @headings after       turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{%
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{%
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+\let\contentsalignmacro = \chappager
+
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{%
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+
+% Subroutines used in generating headings
+% This produces Day Month Year style of output.
+% Only define if not already defined, in case a txi-??.tex file has set
+% up a different format (e.g., txi-cs.tex does this).
+\ifx\today\undefined
+\def\today{%
+  \number\day\space
+  \ifcase\month
+  \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr
+  \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug
+  \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec
+  \fi
+  \space\number\year}
+\fi
+
+% @settitle line...  specifies the title of the document, for headings.
+% It generates no output of its own.
+\def\thistitle{\putwordNoTitle}
+\def\settitle{\parsearg{\gdef\thistitle}}
+
+
+\message{tables,}
+% Tables -- @table, @ftable, @vtable, @item(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent  \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin  \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @ftable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\itemzzz #1{\begingroup %
+  \advance\hsize by -\rightskip
+  \advance\hsize by -\tableindent
+  \setbox0=\hbox{\itemindicate{#1}}%
+  \itemindex{#1}%
+  \nobreak % This prevents a break before @itemx.
+  %
+  % If the item text does not fit in the space we have, put it on a line
+  % by itself, and do not allow a page break either before or after that
+  % line.  We do not start a paragraph here because then if the next
+  % command is, e.g., @kindex, the whatsit would get put into the
+  % horizontal list on a line by itself, resulting in extra blank space.
+  \ifdim \wd0>\itemmax
+    %
+    % Make this a paragraph so we get the \parskip glue and wrapping,
+    % but leave it ragged-right.
+    \begingroup
+      \advance\leftskip by-\tableindent
+      \advance\hsize by\tableindent
+      \advance\rightskip by0pt plus1fil
+      \leavevmode\unhbox0\par
+    \endgroup
+    %
+    % We're going to be starting a paragraph, but we don't want the
+    % \parskip glue -- logically it's part of the @item we just started.
+    \nobreak \vskip-\parskip
+    %
+    % Stop a page break at the \parskip glue coming up.  However, if
+    % what follows is an environment such as @example, there will be no
+    % \parskip glue; then the negative vskip we just inserted would
+    % cause the example and the item to crash together.  So we use this
+    % bizarre value of 10001 as a signal to \aboveenvbreak to insert
+    % \parskip glue after all.  Section titles are handled this way also.
+    % 
+    \penalty 10001
+    \endgroup
+    \itemxneedsnegativevskipfalse
+  \else
+    % The item text fits into the space.  Start a paragraph, so that the
+    % following text (if any) will end up on the same line.
+    \noindent
+    % Do this with kerns and \unhbox so that if there is a footnote in
+    % the item text, it can migrate to the main vertical list and
+    % eventually be printed.
+    \nobreak\kern-\tableindent
+    \dimen0 = \itemmax  \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
+    \unhbox0
+    \nobreak\kern\dimen0
+    \endgroup
+    \itemxneedsnegativevskiptrue
+  \fi
+}
+
+\def\item{\errmessage{@item while not in a list environment}}
+\def\itemx{\errmessage{@itemx while not in a list environment}}
+
+% @table, @ftable, @vtable.
+\envdef\table{%
+  \let\itemindex\gobble
+  \tablex
+}
+\envdef\ftable{%
+  \def\itemindex ##1{\doind {fn}{\code{##1}}}%
+  \tablex
+}
+\envdef\vtable{%
+  \def\itemindex ##1{\doind {vr}{\code{##1}}}%
+  \tablex
+}
+\def\tablex#1{%
+  \def\itemindicate{#1}%
+  \parsearg\tabley
+}
+\def\tabley#1{%
+  {%
+    \makevalueexpandable
+    \edef\temp{\noexpand\tablez #1\space\space\space}%
+    \expandafter
+  }\temp \endtablez
+}
+\def\tablez #1 #2 #3 #4\endtablez{%
+  \aboveenvbreak
+  \ifnum 0#1>0 \advance \leftskip by #1\mil \fi
+  \ifnum 0#2>0 \tableindent=#2\mil \fi
+  \ifnum 0#3>0 \advance \rightskip by #3\mil \fi
+  \itemmax=\tableindent
+  \advance \itemmax by -\itemmargin
+  \advance \leftskip by \tableindent
+  \exdentamount=\tableindent
+  \parindent = 0pt
+  \parskip = \smallskipamount
+  \ifdim \parskip=0pt \parskip=2pt \fi
+  \let\item = \internalBitem
+  \let\itemx = \internalBitemx
+}
+\def\Etable{\endgraf\afterenvbreak}
+\let\Eftable\Etable
+\let\Evtable\Etable
+\let\Eitemize\Etable
+\let\Eenumerate\Etable
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\envdef\itemize{\parsearg\doitemize}
+
+\def\doitemize#1{%
+  \aboveenvbreak
+  \itemmax=\itemindent
+  \advance\itemmax by -\itemmargin
+  \advance\leftskip by \itemindent
+  \exdentamount=\itemindent
+  \parindent=0pt
+  \parskip=\smallskipamount
+  \ifdim\parskip=0pt \parskip=2pt \fi
+  \def\itemcontents{#1}%
+  % @itemize with no arg is equivalent to @itemize @bullet.
+  \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi
+  \let\item=\itemizeitem
+}
+
+% Definition of @item while inside @itemize and @enumerate.
+%
+\def\itemizeitem{%
+  \advance\itemno by 1  % for enumerations
+  {\let\par=\endgraf \smallbreak}% reasonable place to break
+  {%
+   % If the document has an @itemize directly after a section title, a
+   % \nobreak will be last on the list, and \sectionheading will have
+   % done a \vskip-\parskip.  In that case, we don't want to zero
+   % parskip, or the item text will crash with the heading.  On the
+   % other hand, when there is normal text preceding the item (as there
+   % usually is), we do want to zero parskip, or there would be too much
+   % space.  In that case, we won't have a \nobreak before.  At least
+   % that's the theory.
+   \ifnum\lastpenalty<10000 \parskip=0in \fi
+   \noindent
+   \hbox to 0pt{\hss \itemcontents \kern\itemmargin}%
+   \vadjust{\penalty 1200}}% not good to break after first line of item.
+  \flushcr
+}
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list.  No
+% argument is the same as `1'.
+%
+\envparseargdef\enumerate{\enumeratey #1  \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+  % If we were given no argument, pretend we were given `1'.
+  \def\thearg{#1}%
+  \ifx\thearg\empty \def\thearg{1}\fi
+  %
+  % Detect if the argument is a single token.  If so, it might be a
+  % letter.  Otherwise, the only valid thing it can be is a number.
+  % (We will always have one token, because of the test we just made.
+  % This is a good thing, since \splitoff doesn't work given nothing at
+  % all -- the first parameter is undelimited.)
+  \expandafter\splitoff\thearg\endmark
+  \ifx\rest\empty
+    % Only one token in the argument.  It could still be anything.
+    % A ``lowercase letter'' is one whose \lccode is nonzero.
+    % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+    %   not equal to itself.
+    % Otherwise, we assume it's a number.
+    %
+    % We need the \relax at the end of the \ifnum lines to stop TeX from
+    % continuing to look for a <number>.
+    %
+    \ifnum\lccode\expandafter`\thearg=0\relax
+      \numericenumerate % a number (we hope)
+    \else
+      % It's a letter.
+      \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+        \lowercaseenumerate % lowercase letter
+      \else
+        \uppercaseenumerate % uppercase letter
+      \fi
+    \fi
+  \else
+    % Multiple tokens in the argument.  We hope it's a number.
+    \numericenumerate
+  \fi
+}
+
+% An @enumerate whose labels are integers.  The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+  \itemno = \thearg
+  \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more lowercase letters in @enumerate; get a bigger
+                  alphabet}%
+    \fi
+    \char\lccode\itemno
+  }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more uppercase letters in @enumerate; get a bigger
+                  alphabet}
+    \fi
+    \char\uccode\itemno
+  }%
+}
+
+% Call \doitemize, adding a period to the first argument and supplying the
+% common last two arguments.  Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+  \advance\itemno by -1
+  \doitemize{#1.}\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble.  Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+%   @multitable @columnfractions .25 .3 .45
+%   @item ...
+%
+%   Numbers following @columnfractions are the percent of the total
+%   current hsize to be used for each column. You may use as many
+%   columns as desired.
+
+
+% Or use a template:
+%   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+%   @item ...
+%   using the widest term desired in each column.
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab do not need to be on their own lines, but it will not hurt
+% if they are.
+
+% Sample multitable:
+
+%   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+%   @item first col stuff @tab second col stuff @tab third col
+%   @item
+%   first col stuff
+%   @tab
+%   second col stuff
+%   @tab
+%   third col
+%   @item first col stuff @tab second col stuff
+%   @tab Many paragraphs of text may be used in any column.
+%
+%         They will wrap at the width determined by the template.
+%   @item@tab@tab This will be in third column.
+%   @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+%                                                            to baseline.
+%   0pt means it depends on current normal line spacing.
+%
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+% Macros used to set up halign preamble:
+%
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+% #1 is the @columnfraction, usually a decimal number like .5, but might
+% be just 1.  We just use it, whatever it is.
+%
+\def\pickupwholefraction#1 {%
+  \global\advance\colcount by 1
+  \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}%
+  \setuptable
+}
+
+\newcount\colcount
+\def\setuptable#1{%
+  \def\firstarg{#1}%
+  \ifx\firstarg\xendsetuptable
+    \let\go = \relax
+  \else
+    \ifx\firstarg\xcolumnfractions
+      \global\setpercenttrue
+    \else
+      \ifsetpercent
+         \let\go\pickupwholefraction
+      \else
+         \global\advance\colcount by 1
+         \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a
+                   % separator; typically that is always in the input, anyway.
+         \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+      \fi
+    \fi
+    \ifx\go\pickupwholefraction
+      % Put the argument back for the \pickupwholefraction call, so
+      % we'll always have a period there to be parsed.
+      \def\go{\pickupwholefraction#1}%
+    \else
+      \let\go = \setuptable
+    \fi%
+  \fi
+  \go
+}
+
+% multitable-only commands.
+%
+% @headitem starts a heading row, which we typeset in bold.
+% Assignments have to be global since we are inside the implicit group
+% of an alignment entry.  Note that \everycr resets \everytab.
+\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}%
+%
+% A \tab used to include \hskip1sp.  But then the space in a template
+% line is not enough.  That is bad.  So let's go back to just `&' until
+% we encounter the problem it was intended to solve again.
+%					--karl, nathan@acm.org, 20apr99.
+\def\tab{\checkenv\multitable &\the\everytab}%
+
+% @multitable ... @end multitable definitions:
+%
+\newtoks\everytab  % insert after every tab.
+%
+\envdef\multitable{%
+  \vskip\parskip
+  \startsavinginserts
+  %
+  % @item within a multitable starts a normal row.
+  \let\item\crcr
+  %
+  \tolerance=9500
+  \hbadness=9500
+  \setmultitablespacing
+  \parskip=\multitableparskip
+  \parindent=\multitableparindent
+  \overfullrule=0pt
+  \global\colcount=0
+  %
+  \everycr = {%
+    \noalign{%
+      \global\everytab={}%
+      \global\colcount=0 % Reset the column counter.
+      % Check for saved footnotes, etc.
+      \checkinserts
+      % Keeps underfull box messages off when table breaks over pages.
+      %\filbreak
+	% Maybe so, but it also creates really weird page breaks when the
+	% table breaks over pages. Wouldn't \vfil be better?  Wait until the
+	% problem manifests itself, so it can be fixed for real --karl.
+    }%
+  }%
+  %
+  \parsearg\domultitable
+}
+\def\domultitable#1{%
+  % To parse everything between @multitable and @item:
+  \setuptable#1 \endsetuptable
+  %
+  % This preamble sets up a generic column definition, which will
+  % be used as many times as user calls for columns.
+  % \vtop will set a single line and will also let text wrap and
+  % continue for many paragraphs if desired.
+  \halign\bgroup &%
+    \global\advance\colcount by 1
+    \multistrut
+    \vtop{%
+      % Use the current \colcount to find the correct column width:
+      \hsize=\expandafter\csname col\the\colcount\endcsname
+      %
+      % In order to keep entries from bumping into each other
+      % we will add a \leftskip of \multitablecolspace to all columns after
+      % the first one.
+      %
+      % If a template has been used, we will add \multitablecolspace
+      % to the width of each template entry.
+      %
+      % If the user has set preamble in terms of percent of \hsize we will
+      % use that dimension as the width of the column, and the \leftskip
+      % will keep entries from bumping into each other.  Table will start at
+      % left margin and final column will justify at right margin.
+      %
+      % Make sure we don't inherit \rightskip from the outer environment.
+      \rightskip=0pt
+      \ifnum\colcount=1
+	% The first column will be indented with the surrounding text.
+	\advance\hsize by\leftskip
+      \else
+	\ifsetpercent \else
+	  % If user has not set preamble in terms of percent of \hsize
+	  % we will advance \hsize by \multitablecolspace.
+	  \advance\hsize by \multitablecolspace
+	\fi
+       % In either case we will make \leftskip=\multitablecolspace:
+      \leftskip=\multitablecolspace
+      \fi
+      % Ignoring space at the beginning and end avoids an occasional spurious
+      % blank line, when TeX decides to break the line at the space before the
+      % box from the multistrut, so the strut ends up on a line by itself.
+      % For example:
+      % @multitable @columnfractions .11 .89
+      % @item @code{#}
+      % @tab Legal holiday which is valid in major parts of the whole country.
+      % Is automatically provided with highlighting sequences respectively
+      % marking characters.
+      \noindent\ignorespaces##\unskip\multistrut
+    }\cr
+}
+\def\Emultitable{%
+  \crcr
+  \egroup % end the \halign
+  \global\setpercentfalse
+}
+
+\def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\ifdim\multitablelinespace=0pt
+\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
+\global\advance\multitablelinespace by-\ht0
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\let\multistrut = \strut
+\else
+%% FIXME: what is \box0 supposed to be?
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \fi
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%%        If so, set to same dimension as multitablelinespace.
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+                                      %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+                                      %% than skip between lines in the table.
+\fi}
+
+
+\message{conditionals,}
+
+% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext,
+% @ifnotxml always succeed.  They currently do nothing; we don't
+% attempt to check whether the conditionals are properly nested.  But we
+% have to remember that they are conditionals, so that @end doesn't
+% attempt to close an environment group.
+%
+\def\makecond#1{%
+  \expandafter\let\csname #1\endcsname = \relax
+  \expandafter\let\csname iscond.#1\endcsname = 1
+}
+\makecond{iftex}
+\makecond{ifnotdocbook}
+\makecond{ifnothtml}
+\makecond{ifnotinfo}
+\makecond{ifnotplaintext}
+\makecond{ifnotxml}
+
+% Ignore @ignore, @ifhtml, @ifinfo, and the like.
+%
+\def\direntry{\doignore{direntry}}
+\def\documentdescription{\doignore{documentdescription}}
+\def\docbook{\doignore{docbook}}
+\def\html{\doignore{html}}
+\def\ifdocbook{\doignore{ifdocbook}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifnottex{\doignore{ifnottex}}
+\def\ifplaintext{\doignore{ifplaintext}}
+\def\ifxml{\doignore{ifxml}}
+\def\ignore{\doignore{ignore}}
+\def\menu{\doignore{menu}}
+\def\xml{\doignore{xml}}
+
+% Ignore text until a line `@end #1', keeping track of nested conditionals.
+%
+% A count to remember the depth of nesting.
+\newcount\doignorecount
+
+\def\doignore#1{\begingroup
+  % Scan in ``verbatim'' mode:
+  \catcode`\@ = \other
+  \catcode`\{ = \other
+  \catcode`\} = \other
+  %
+  % Make sure that spaces turn into tokens that match what \doignoretext wants.
+  \spaceisspace
+  %
+  % Count number of #1's that we've seen.
+  \doignorecount = 0
+  %
+  % Swallow text until we reach the matching `@end #1'.
+  \dodoignore{#1}%
+}
+
+{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source.
+  \obeylines %
+  %
+  \gdef\dodoignore#1{%
+    % #1 contains the command name as a string, e.g., `ifinfo'.
+    %
+    % Define a command to find the next `@end #1', which must be on a line
+    % by itself.
+    \long\def\doignoretext##1^^M@end #1{\doignoretextyyy##1^^M@#1\_STOP_}%
+    % And this command to find another #1 command, at the beginning of a
+    % line.  (Otherwise, we would consider a line `@c @ifset', for
+    % example, to count as an @ifset for nesting.)
+    \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}%
+    %
+    % And now expand that command.
+    \obeylines %
+    \doignoretext ^^M%
+  }%
+}
+
+\def\doignoreyyy#1{%
+  \def\temp{#1}%
+  \ifx\temp\empty			% Nothing found.
+    \let\next\doignoretextzzz
+  \else					% Found a nested condition, ...
+    \advance\doignorecount by 1
+    \let\next\doignoretextyyy		% ..., look for another.
+    % If we're here, #1 ends with ^^M\ifinfo (for example).
+  \fi
+  \next #1% the token \_STOP_ is present just after this macro.
+}
+
+% We have to swallow the remaining "\_STOP_".
+%
+\def\doignoretextzzz#1{%
+  \ifnum\doignorecount = 0	% We have just found the outermost @end.
+    \let\next\enddoignore
+  \else				% Still inside a nested condition.
+    \advance\doignorecount by -1
+    \let\next\doignoretext      % Look for the next @end.
+  \fi
+  \next
+}
+
+% Finish off ignored text.
+\def\enddoignore{\endgroup\ignorespaces}
+
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+% We rely on the fact that \parsearg sets \catcode`\ =10.
+%
+\parseargdef\set{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+  {%
+    \makevalueexpandable
+    \def\temp{#2}%
+    \edef\next{\gdef\makecsname{SET#1}}%
+    \ifx\temp\empty
+      \next{}%
+    \else
+      \setzzz#2\endsetzzz
+    \fi
+  }%
+}
+% Remove the trailing space \setxxx inserted.
+\def\setzzz#1 \endsetzzz{\next{#1}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\parseargdef\clear{%
+  {%
+    \makevalueexpandable
+    \global\expandafter\let\csname SET#1\endcsname=\relax
+  }%
+}
+
+% @value{foo} gets the text saved in variable foo.
+\def\value{\begingroup\makevalueexpandable\valuexxx}
+\def\valuexxx#1{\expandablevalue{#1}\endgroup}
+{
+  \catcode`\- = \active \catcode`\_ = \active
+  %
+  \gdef\makevalueexpandable{%
+    \let\value = \expandablevalue
+    % We don't want these characters active, ...
+    \catcode`\-=\other \catcode`\_=\other
+    % ..., but we might end up with active ones in the argument if
+    % we're called from @code, as @code{@value{foo-bar_}}, though.
+    % So \let them to their normal equivalents.
+    \let-\realdash \let_\normalunderscore
+  }
+}
+
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we call \makevalueexpandable in \indexdummies).
+% The command has to be fully expandable (if the variable is set), since
+% the result winds up in the index file.  This means that if the
+% variable's value contains other Texinfo commands, it's almost certain
+% it will fail (although perhaps we could fix that with sufficient work
+% to do a one-level expansion on the result, instead of complete).
+%
+\def\expandablevalue#1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    {[No value for ``#1'']}%
+    \message{Variable `#1', used in @value, is not set.}%
+  \else
+    \csname SET#1\endcsname
+  \fi
+}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+% To get special treatment of `@end ifset,' call \makeond and the redefine.
+%
+\makecond{ifset}
+\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}}
+\def\doifset#1#2{%
+  {%
+    \makevalueexpandable
+    \let\next=\empty
+    \expandafter\ifx\csname SET#2\endcsname\relax
+      #1% If not set, redefine \next.
+    \fi
+    \expandafter
+  }\next
+}
+\def\ifsetfail{\doignore{ifset}}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+% The `\else' inside the `\doifset' parameter is a trick to reuse the
+% above code: if the variable is not set, do nothing, if it is set,
+% then redefine \next to \ifclearfail.
+%
+\makecond{ifclear}
+\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}}
+\def\ifclearfail{\doignore{ifclear}}
+
+% @dircategory CATEGORY  -- specify a category of the dir file
+% which this file should belong to.  Ignore this in TeX.
+\let\dircategory=\comment
+
+% @defininfoenclose.
+\let\definfoenclose=\comment
+
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index.  The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+%
+\def\newindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%     % Define @#1index
+    \noexpand\doindex{#1}}
+}
+
+% @defindex foo  ==  \newindex{foo}
+%
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+%
+\def\defcodeindex{\parsearg\newcodeindex}
+%
+\def\newcodeindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%
+    \noexpand\docodeindex{#1}}%
+}
+
+
+% @synindex foo bar    makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+%
+% @syncodeindex foo bar   similar, but put all entries made for index foo
+% inside @code.
+%
+\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}}
+\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}}
+
+% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo),
+% #3 the target index (bar).
+\def\dosynindex#1#2#3{%
+  % Only do \closeout if we haven't already done it, else we'll end up
+  % closing the target index.
+  \expandafter \ifx\csname donesynindex#2\endcsname \undefined
+    % The \closeout helps reduce unnecessary open files; the limit on the
+    % Acorn RISC OS is a mere 16 files.
+    \expandafter\closeout\csname#2indfile\endcsname
+    \expandafter\let\csname\donesynindex#2\endcsname = 1
+  \fi
+  % redefine \fooindfile:
+  \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname
+  \expandafter\let\csname#2indfile\endcsname=\temp
+  % redefine \fooindex:
+  \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+%  and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+% Take care of Texinfo commands that can appear in an index entry.
+% Since there are some commands we want to expand, and others we don't,
+% we have to laboriously prevent expansion for those that we don't.
+%
+\def\indexdummies{%
+  \def\@{@}% change to @@ when we switch to @ as escape char in index files.
+  \def\ {\realbackslash\space }%
+  % Need these in case \tex is in effect and \{ is a \delimiter again.
+  % But can't use \lbracecmd and \rbracecmd because texindex assumes
+  % braces and backslashes are used only as delimiters.
+  \let\{ = \mylbrace
+  \let\} = \myrbrace
+  %
+  % \definedummyword defines \#1 as \realbackslash #1\space, thus
+  % effectively preventing its expansion.  This is used only for control
+  % words, not control letters, because the \space would be incorrect
+  % for control characters, but is needed to separate the control word
+  % from whatever follows.
+  %
+  % For control letters, we have \definedummyletter, which omits the
+  % space.
+  %
+  % These can be used both for control words that take an argument and
+  % those that do not.  If it is followed by {arg} in the input, then
+  % that will dutifully get written to the index (or wherever).
+  %
+  \def\definedummyword##1{%
+    \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}%
+  }%
+  \def\definedummyletter##1{%
+    \expandafter\def\csname ##1\endcsname{\realbackslash ##1}%
+  }%
+  \let\definedummyaccent\definedummyletter
+  %
+  % Do the redefinitions.
+  \commondummies
+}
+
+% For the aux file, @ is the escape character.  So we want to redefine
+% everything using @ instead of \realbackslash.  When everything uses
+% @, this will be simpler.
+%
+\def\atdummies{%
+  \def\@{@@}%
+  \def\ {@ }%
+  \let\{ = \lbraceatcmd
+  \let\} = \rbraceatcmd
+  %
+  % (See comments in \indexdummies.)
+  \def\definedummyword##1{%
+    \expandafter\def\csname ##1\endcsname{@##1\space}%
+  }%
+  \def\definedummyletter##1{%
+    \expandafter\def\csname ##1\endcsname{@##1}%
+  }%
+  \let\definedummyaccent\definedummyletter
+  %
+  % Do the redefinitions.
+  \commondummies
+}
+
+% Called from \indexdummies and \atdummies.  \definedummyword and
+% \definedummyletter must be defined first.
+%
+\def\commondummies{%
+  %
+  \normalturnoffactive
+  %
+  \commondummiesnofonts
+  %
+  \definedummyletter{_}%
+  %
+  % Non-English letters.
+  \definedummyword{AA}%
+  \definedummyword{AE}%
+  \definedummyword{L}%
+  \definedummyword{OE}%
+  \definedummyword{O}%
+  \definedummyword{aa}%
+  \definedummyword{ae}%
+  \definedummyword{l}%
+  \definedummyword{oe}%
+  \definedummyword{o}%
+  \definedummyword{ss}%
+  \definedummyword{exclamdown}%
+  \definedummyword{questiondown}%
+  \definedummyword{ordf}%
+  \definedummyword{ordm}%
+  %
+  % Although these internal commands shouldn't show up, sometimes they do.
+  \definedummyword{bf}%
+  \definedummyword{gtr}%
+  \definedummyword{hat}%
+  \definedummyword{less}%
+  \definedummyword{sf}%
+  \definedummyword{sl}%
+  \definedummyword{tclose}%
+  \definedummyword{tt}%
+  %
+  \definedummyword{LaTeX}%
+  \definedummyword{TeX}%
+  %
+  % Assorted special characters.
+  \definedummyword{bullet}%
+  \definedummyword{comma}%
+  \definedummyword{copyright}%
+  \definedummyword{registeredsymbol}%
+  \definedummyword{dots}%
+  \definedummyword{enddots}%
+  \definedummyword{equiv}%
+  \definedummyword{error}%
+  \definedummyword{expansion}%
+  \definedummyword{minus}%
+  \definedummyword{pounds}%
+  \definedummyword{point}%
+  \definedummyword{print}%
+  \definedummyword{result}%
+  %
+  % Handle some cases of @value -- where it does not contain any
+  % (non-fully-expandable) commands.
+  \makevalueexpandable
+  %
+  % Normal spaces, not active ones.
+  \unsepspaces
+  %
+  % No macro expansion.
+  \turnoffmacros
+}
+
+% \commondummiesnofonts: common to \commondummies and \indexnofonts.
+%
+% Better have this without active chars.
+{
+  \catcode`\~=\other
+  \gdef\commondummiesnofonts{%
+    % Control letters and accents.
+    \definedummyletter{!}%
+    \definedummyaccent{"}%
+    \definedummyaccent{'}%
+    \definedummyletter{*}%
+    \definedummyaccent{,}%
+    \definedummyletter{.}%
+    \definedummyletter{/}%
+    \definedummyletter{:}%
+    \definedummyaccent{=}%
+    \definedummyletter{?}%
+    \definedummyaccent{^}%
+    \definedummyaccent{`}%
+    \definedummyaccent{~}%
+    \definedummyword{u}%
+    \definedummyword{v}%
+    \definedummyword{H}%
+    \definedummyword{dotaccent}%
+    \definedummyword{ringaccent}%
+    \definedummyword{tieaccent}%
+    \definedummyword{ubaraccent}%
+    \definedummyword{udotaccent}%
+    \definedummyword{dotless}%
+    %
+    % Texinfo font commands.
+    \definedummyword{b}%
+    \definedummyword{i}%
+    \definedummyword{r}%
+    \definedummyword{sc}%
+    \definedummyword{t}%
+    %
+    % Commands that take arguments.
+    \definedummyword{acronym}%
+    \definedummyword{cite}%
+    \definedummyword{code}%
+    \definedummyword{command}%
+    \definedummyword{dfn}%
+    \definedummyword{emph}%
+    \definedummyword{env}%
+    \definedummyword{file}%
+    \definedummyword{kbd}%
+    \definedummyword{key}%
+    \definedummyword{math}%
+    \definedummyword{option}%
+    \definedummyword{samp}%
+    \definedummyword{strong}%
+    \definedummyword{tie}%
+    \definedummyword{uref}%
+    \definedummyword{url}%
+    \definedummyword{var}%
+    \definedummyword{verb}%
+    \definedummyword{w}%
+  }
+}
+
+% \indexnofonts is used when outputting the strings to sort the index
+% by, and when constructing control sequence names.  It eliminates all
+% control sequences and just writes whatever the best ASCII sort string
+% would be for a given command (usually its argument).
+%
+\def\indexnofonts{%
+  % Accent commands should become @asis.
+  \def\definedummyaccent##1{%
+    \expandafter\let\csname ##1\endcsname\asis
+  }%
+  % We can just ignore other control letters.
+  \def\definedummyletter##1{%
+    \expandafter\def\csname ##1\endcsname{}%
+  }%
+  % Hopefully, all control words can become @asis.
+  \let\definedummyword\definedummyaccent
+  %
+  \commondummiesnofonts
+  %
+  % Don't no-op \tt, since it isn't a user-level command
+  % and is used in the definitions of the active chars like <, >, |, etc.
+  % Likewise with the other plain tex font commands.
+  %\let\tt=\asis
+  %
+  \def\ { }%
+  \def\@{@}%
+  % how to handle braces?
+  \def\_{\normalunderscore}%
+  %
+  % Non-English letters.
+  \def\AA{AA}%
+  \def\AE{AE}%
+  \def\L{L}%
+  \def\OE{OE}%
+  \def\O{O}%
+  \def\aa{aa}%
+  \def\ae{ae}%
+  \def\l{l}%
+  \def\oe{oe}%
+  \def\o{o}%
+  \def\ss{ss}%
+  \def\exclamdown{!}%
+  \def\questiondown{?}%
+  \def\ordf{a}%
+  \def\ordm{o}%
+  %
+  \def\LaTeX{LaTeX}%
+  \def\TeX{TeX}%
+  %
+  % Assorted special characters.
+  % (The following {} will end up in the sort string, but that's ok.)
+  \def\bullet{bullet}%
+  \def\comma{,}%
+  \def\copyright{copyright}%
+  \def\registeredsymbol{R}%
+  \def\dots{...}%
+  \def\enddots{...}%
+  \def\equiv{==}%
+  \def\error{error}%
+  \def\expansion{==>}%
+  \def\minus{-}%
+  \def\pounds{pounds}%
+  \def\point{.}%
+  \def\print{-|}%
+  \def\result{=>}%
+  %
+  % Don't write macro names.
+  \emptyusermacros
+}
+
+\let\indexbackslash=0  %overridden during \printindex.
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+% Most index entries go through here, but \dosubind is the general case.
+% #1 is the index name, #2 is the entry text.
+\def\doind#1#2{\dosubind{#1}{#2}{}}
+
+% Workhorse for all \fooindexes.
+% #1 is name of index, #2 is stuff to put there, #3 is subentry --
+% empty if called from \doind, as we usually are (the main exception
+% is with most defuns, which call us directly).
+%
+\def\dosubind#1#2#3{%
+  \iflinks
+  {%
+    % Store the main index entry text (including the third arg).
+    \toks0 = {#2}%
+    % If third arg is present, precede it with a space.
+    \def\thirdarg{#3}%
+    \ifx\thirdarg\empty \else
+      \toks0 = \expandafter{\the\toks0 \space #3}%
+    \fi
+    %
+    \edef\writeto{\csname#1indfile\endcsname}%
+    %
+    \ifvmode
+      \dosubindsanitize
+    \else
+      \dosubindwrite
+    \fi
+  }%
+  \fi
+}
+
+% Write the entry in \toks0 to the index file:
+%
+\def\dosubindwrite{%
+  % Put the index entry in the margin if desired.
+  \ifx\SETmarginindex\relax\else
+    \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}%
+  \fi
+  %
+  % Remember, we are within a group.
+  \indexdummies % Must do this here, since \bf, etc expand at this stage
+  \escapechar=`\\
+  \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now
+      % so it will be output as is; and it will print as backslash.
+  %
+  % Process the index entry with all font commands turned off, to
+  % get the string to sort by.
+  {\indexnofonts
+   \edef\temp{\the\toks0}% need full expansion
+   \xdef\indexsorttmp{\temp}%
+  }%
+  %
+  % Set up the complete index entry, with both the sort key and
+  % the original text, including any font commands.  We write
+  % three arguments to \entry to the .?? file (four in the
+  % subentry case), texindex reduces to two when writing the .??s
+  % sorted result.
+  \edef\temp{%
+    \write\writeto{%
+      \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}%
+  }%
+  \temp
+}
+
+% Take care of unwanted page breaks:
+%
+% If a skip is the last thing on the list now, preserve it
+% by backing up by \lastskip, doing the \write, then inserting
+% the skip again.  Otherwise, the whatsit generated by the
+% \write will make \lastskip zero.  The result is that sequences
+% like this:
+% @end defun
+% @tindex whatever
+% @defun ...
+% will have extra space inserted, because the \medbreak in the
+% start of the @defun won't see the skip inserted by the @end of
+% the previous defun.
+%
+% But don't do any of this if we're not in vertical mode.  We
+% don't want to do a \vskip and prematurely end a paragraph.
+%
+% Avoid page breaks due to these extra skips, too.
+%
+% But wait, there is a catch there:
+% We'll have to check whether \lastskip is zero skip.  \ifdim is not
+% sufficient for this purpose, as it ignores stretch and shrink parts
+% of the skip.  The only way seems to be to check the textual
+% representation of the skip.
+%
+% The following is almost like \def\zeroskipmacro{0.0pt} except that
+% the ``p'' and ``t'' characters have catcode \other, not 11 (letter).
+%
+\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname}
+%
+% ..., ready, GO:
+%
+\def\dosubindsanitize{%
+  % \lastskip and \lastpenalty cannot both be nonzero simultaneously.
+  \skip0 = \lastskip
+  \edef\lastskipmacro{\the\lastskip}%
+  \count255 = \lastpenalty
+  %
+  % If \lastskip is nonzero, that means the last item was a
+  % skip.  And since a skip is discardable, that means this
+  % -\skip0 glue we're inserting is preceded by a
+  % non-discardable item, therefore it is not a potential
+  % breakpoint, therefore no \nobreak needed.
+  \ifx\lastskipmacro\zeroskipmacro
+  \else
+    \vskip-\skip0
+  \fi
+  %
+  \dosubindwrite
+  %
+  \ifx\lastskipmacro\zeroskipmacro
+    % If \lastskip was zero, perhaps the last item was a penalty, and
+    % perhaps it was >=10000, e.g., a \nobreak.  In that case, we want
+    % to re-insert the same penalty (values >10000 are used for various
+    % signals); since we just inserted a non-discardable item, any
+    % following glue (such as a \parskip) would be a breakpoint.  For example:
+    % 
+    %   @deffn deffn-whatever
+    %   @vindex index-whatever
+    %   Description.
+    % would allow a break between the index-whatever whatsit
+    % and the "Description." paragraph.
+    \ifnum\count255>9999 \penalty\count255 \fi
+  \else
+    % On the other hand, if we had a nonzero \lastskip,
+    % this make-up glue would be preceded by a non-discardable item
+    % (the whatsit from the \write), so we must insert a \nobreak.
+    \nobreak\vskip\skip0
+  \fi
+}
+
+% The index entry written in the file actually looks like
+%  \entry {sortstring}{page}{topic}
+% or
+%  \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+%  \initial {c}
+%     before the first topic whose initial is c
+%  \entry {topic}{pagelist}
+%     for a topic that is used without subtopics
+%  \primary {topic}
+%     for the beginning of a topic that is used with subtopics
+%  \secondary {subtopic}{pagelist}
+%     for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% @printindex causes a particular index (the ??s file) to get printed.
+% It does not print any chapter heading (usually an @unnumbered).
+%
+\parseargdef\printindex{\begingroup
+  \dobreak \chapheadingskip{10000}%
+  %
+  \smallfonts \rm
+  \tolerance = 9500
+  \everypar = {}% don't want the \kern\-parindent from indentation suppression.
+  %
+  % See if the index file exists and is nonempty.
+  % Change catcode of @ here so that if the index file contains
+  % \initial {@}
+  % as its first line, TeX doesn't complain about mismatched braces
+  % (because it thinks @} is a control sequence).
+  \catcode`\@ = 11
+  \openin 1 \jobname.#1s
+  \ifeof 1
+    % \enddoublecolumns gets confused if there is no text in the index,
+    % and it loses the chapter title and the aux file entries for the
+    % index.  The easiest way to prevent this problem is to make sure
+    % there is some text.
+    \putwordIndexNonexistent
+  \else
+    %
+    % If the index file exists but is empty, then \openin leaves \ifeof
+    % false.  We have to make TeX try to read something from the file, so
+    % it can discover if there is anything in it.
+    \read 1 to \temp
+    \ifeof 1
+      \putwordIndexIsEmpty
+    \else
+      % Index files are almost Texinfo source, but we use \ as the escape
+      % character.  It would be better to use @, but that's too big a change
+      % to make right now.
+      \def\indexbackslash{\backslashcurfont}%
+      \catcode`\\ = 0
+      \escapechar = `\\
+      \begindoublecolumns
+      \input \jobname.#1s
+      \enddoublecolumns
+    \fi
+  \fi
+  \closein 1
+\endgroup}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+\def\initial#1{{%
+  % Some minor font changes for the special characters.
+  \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+  %
+  % Remove any glue we may have, we'll be inserting our own.
+  \removelastskip
+  %
+  % We like breaks before the index initials, so insert a bonus.
+  \penalty -300
+  %
+  % Typeset the initial.  Making this add up to a whole number of
+  % baselineskips increases the chance of the dots lining up from column
+  % to column.  It still won't often be perfect, because of the stretch
+  % we need before each entry, but it's better.
+  %
+  % No shrink because it confuses \balancecolumns.
+  \vskip 1.67\baselineskip plus .5\baselineskip
+  \leftline{\secbf #1}%
+  \vskip .33\baselineskip plus .1\baselineskip
+  %
+  % Do our best not to break after the initial.
+  \nobreak
+}}
+
+% \entry typesets a paragraph consisting of the text (#1), dot leaders, and
+% then page number (#2) flushed to the right margin.  It is used for index
+% and table of contents entries.  The paragraph is indented by \leftskip.
+%
+% A straightforward implementation would start like this:
+%	\def\entry#1#2{...
+% But this frozes the catcodes in the argument, and can cause problems to
+% @code, which sets - active.  This problem was fixed by a kludge---
+% ``-'' was active throughout whole index, but this isn't really right.
+%
+% The right solution is to prevent \entry from swallowing the whole text.
+%                                 --kasal, 21nov03
+\def\entry{%
+  \begingroup
+    %
+    % Start a new paragraph if necessary, so our assignments below can't
+    % affect previous text.
+    \par
+    %
+    % Do not fill out the last line with white space.
+    \parfillskip = 0in
+    %
+    % No extra space above this paragraph.
+    \parskip = 0in
+    %
+    % Do not prefer a separate line ending with a hyphen to fewer lines.
+    \finalhyphendemerits = 0
+    %
+    % \hangindent is only relevant when the entry text and page number
+    % don't both fit on one line.  In that case, bob suggests starting the
+    % dots pretty far over on the line.  Unfortunately, a large
+    % indentation looks wrong when the entry text itself is broken across
+    % lines.  So we use a small indentation and put up with long leaders.
+    %
+    % \hangafter is reset to 1 (which is the value we want) at the start
+    % of each paragraph, so we need not do anything with that.
+    \hangindent = 2em
+    %
+    % When the entry text needs to be broken, just fill out the first line
+    % with blank space.
+    \rightskip = 0pt plus1fil
+    %
+    % A bit of stretch before each entry for the benefit of balancing
+    % columns.
+    \vskip 0pt plus1pt
+    %
+    % Swallow the left brace of the text (first parameter):
+    \afterassignment\doentry
+    \let\temp =
+}
+\def\doentry{%
+    \bgroup % Instead of the swallowed brace.
+      \noindent
+      \aftergroup\finishentry
+      % And now comes the text of the entry.
+}
+\def\finishentry#1{%
+    % #1 is the page number.
+    %
+    % The following is kludged to not output a line of dots in the index if
+    % there are no page numbers.  The next person who breaks this will be
+    % cursed by a Unix daemon.
+    \def\tempa{{\rm }}%
+    \def\tempb{#1}%
+    \edef\tempc{\tempa}%
+    \edef\tempd{\tempb}%
+    \ifx\tempc\tempd
+      \ %
+    \else
+      %
+      % If we must, put the page number on a line of its own, and fill out
+      % this line with blank space.  (The \hfil is overwhelmed with the
+      % fill leaders glue in \indexdotfill if the page number does fit.)
+      \hfil\penalty50
+      \null\nobreak\indexdotfill % Have leaders before the page number.
+      %
+      % The `\ ' here is removed by the implicit \unskip that TeX does as
+      % part of (the primitive) \par.  Without it, a spurious underfull
+      % \hbox ensues.
+      \ifpdf
+	\pdfgettoks#1.%
+	\ \the\toksA
+      \else
+	\ #1%
+      \fi
+    \fi
+    \par
+  \endgroup
+}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+  \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+\def\secondary#1#2{{%
+  \parfillskip=0in
+  \parskip=0in
+  \hangindent=1in
+  \hangafter=1
+  \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill
+  \ifpdf
+    \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
+  \else
+    #2
+  \fi
+  \par
+}}
+
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
+
+\newbox\partialpage
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+  % Grab any single-column material above us.
+  \output = {%
+    %
+    % Here is a possibility not foreseen in manmac: if we accumulate a
+    % whole lot of material, we might end up calling this \output
+    % routine twice in a row (see the doublecol-lose test, which is
+    % essentially a couple of indexes with @setchapternewpage off).  In
+    % that case we just ship out what is in \partialpage with the normal
+    % output routine.  Generally, \partialpage will be empty when this
+    % runs and this will be a no-op.  See the indexspread.tex test case.
+    \ifvoid\partialpage \else
+      \onepageout{\pagecontents\partialpage}%
+    \fi
+    %
+    \global\setbox\partialpage = \vbox{%
+      % Unvbox the main output page.
+      \unvbox\PAGE
+      \kern-\topskip \kern\baselineskip
+    }%
+  }%
+  \eject % run that output routine to set \partialpage
+  %
+  % Use the double-column output routine for subsequent pages.
+  \output = {\doublecolumnout}%
+  %
+  % Change the page size parameters.  We could do this once outside this
+  % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+  % format, but then we repeat the same computation.  Repeating a couple
+  % of assignments once per index is clearly meaningless for the
+  % execution time, so we may as well do it in one place.
+  %
+  % First we halve the line length, less a little for the gutter between
+  % the columns.  We compute the gutter based on the line length, so it
+  % changes automatically with the paper format.  The magic constant
+  % below is chosen so that the gutter has the same value (well, +-<1pt)
+  % as it did when we hard-coded it.
+  %
+  % We put the result in a separate register, \doublecolumhsize, so we
+  % can restore it in \pagesofar, after \hsize itself has (potentially)
+  % been clobbered.
+  %
+  \doublecolumnhsize = \hsize
+    \advance\doublecolumnhsize by -.04154\hsize
+    \divide\doublecolumnhsize by 2
+  \hsize = \doublecolumnhsize
+  %
+  % Double the \vsize as well.  (We don't need a separate register here,
+  % since nobody clobbers \vsize.)
+  \vsize = 2\vsize
+}
+
+% The double-column output routine for all double-column pages except
+% the last.
+%
+\def\doublecolumnout{%
+  \splittopskip=\topskip \splitmaxdepth=\maxdepth
+  % Get the available space for the double columns -- the normal
+  % (undoubled) page height minus any material left over from the
+  % previous page.
+  \dimen@ = \vsize
+  \divide\dimen@ by 2
+  \advance\dimen@ by -\ht\partialpage
+  %
+  % box0 will be the left-hand column, box2 the right.
+  \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+  \onepageout\pagesofar
+  \unvbox255
+  \penalty\outputpenalty
+}
+%
+% Re-output the contents of the output page -- any previous material,
+% followed by the two boxes we just split, in box0 and box2.
+\def\pagesofar{%
+  \unvbox\partialpage
+  %
+  \hsize = \doublecolumnhsize
+  \wd0=\hsize \wd2=\hsize
+  \hbox to\pagewidth{\box0\hfil\box2}%
+}
+%
+% All done with double columns.
+\def\enddoublecolumns{%
+  \output = {%
+    % Split the last of the double-column material.  Leave it on the
+    % current page, no automatic page break.
+    \balancecolumns
+    %
+    % If we end up splitting too much material for the current page,
+    % though, there will be another page break right after this \output
+    % invocation ends.  Having called \balancecolumns once, we do not
+    % want to call it again.  Therefore, reset \output to its normal
+    % definition right away.  (We hope \balancecolumns will never be
+    % called on to balance too much material, but if it is, this makes
+    % the output somewhat more palatable.)
+    \global\output = {\onepageout{\pagecontents\PAGE}}%
+  }%
+  \eject
+  \endgroup % started in \begindoublecolumns
+  %
+  % \pagegoal was set to the doubled \vsize above, since we restarted
+  % the current page.  We're now back to normal single-column
+  % typesetting, so reset \pagegoal to the normal \vsize (after the
+  % \endgroup where \vsize got restored).
+  \pagegoal = \vsize
+}
+%
+% Called at the end of the double column material.
+\def\balancecolumns{%
+  \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
+  \dimen@ = \ht0
+  \advance\dimen@ by \topskip
+  \advance\dimen@ by-\baselineskip
+  \divide\dimen@ by 2 % target to split to
+  %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}%
+  \splittopskip = \topskip
+  % Loop until we get a decent breakpoint.
+  {%
+    \vbadness = 10000
+    \loop
+      \global\setbox3 = \copy0
+      \global\setbox1 = \vsplit3 to \dimen@
+    \ifdim\ht3>\dimen@
+      \global\advance\dimen@ by 1pt
+    \repeat
+  }%
+  %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}%
+  \setbox0=\vbox to\dimen@{\unvbox1}%
+  \setbox2=\vbox to\dimen@{\unvbox3}%
+  %
+  \pagesofar
+}
+\catcode`\@ = \other
+
+
+\message{sectioning,}
+% Chapters, sections, etc.
+
+% \unnumberedno is an oxymoron, of course.  But we count the unnumbered
+% sections so that we can refer to them unambiguously in the pdf
+% outlines by their "section number".  We avoid collisions with chapter
+% numbers by starting them at 10000.  (If a document ever has 10000
+% chapters, we're in trouble anyway, I'm sure.)
+\newcount\unnumberedno \unnumberedno = 10000
+\newcount\chapno
+\newcount\secno        \secno=0
+\newcount\subsecno     \subsecno=0
+\newcount\subsubsecno  \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount\appendixno  \appendixno = `\@
+%
+% \def\appendixletter{\char\the\appendixno}
+% We do the following ugly conditional instead of the above simple
+% construct for the sake of pdftex, which needs the actual
+% letter in the expansion, not just typeset.
+%
+\def\appendixletter{%
+  \ifnum\appendixno=`A A%
+  \else\ifnum\appendixno=`B B%
+  \else\ifnum\appendixno=`C C%
+  \else\ifnum\appendixno=`D D%
+  \else\ifnum\appendixno=`E E%
+  \else\ifnum\appendixno=`F F%
+  \else\ifnum\appendixno=`G G%
+  \else\ifnum\appendixno=`H H%
+  \else\ifnum\appendixno=`I I%
+  \else\ifnum\appendixno=`J J%
+  \else\ifnum\appendixno=`K K%
+  \else\ifnum\appendixno=`L L%
+  \else\ifnum\appendixno=`M M%
+  \else\ifnum\appendixno=`N N%
+  \else\ifnum\appendixno=`O O%
+  \else\ifnum\appendixno=`P P%
+  \else\ifnum\appendixno=`Q Q%
+  \else\ifnum\appendixno=`R R%
+  \else\ifnum\appendixno=`S S%
+  \else\ifnum\appendixno=`T T%
+  \else\ifnum\appendixno=`U U%
+  \else\ifnum\appendixno=`V V%
+  \else\ifnum\appendixno=`W W%
+  \else\ifnum\appendixno=`X X%
+  \else\ifnum\appendixno=`Y Y%
+  \else\ifnum\appendixno=`Z Z%
+  % The \the is necessary, despite appearances, because \appendixletter is
+  % expanded while writing the .toc file.  \char\appendixno is not
+  % expandable, thus it is written literally, thus all appendixes come out
+  % with the same letter (or @) in the toc without it.
+  \else\char\the\appendixno
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it.  @section does likewise.
+% However, they are not reliable, because we don't use marks.
+\def\thischapter{}
+\def\thissection{}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% we only have subsub.
+\chardef\maxseclevel = 3
+%
+% A numbered section within an unnumbered changes to unnumbered too.
+% To achive this, remember the "biggest" unnum. sec. we are currently in:
+\chardef\unmlevel = \maxseclevel
+%
+% Trace whether the current chapter is an appendix or not:
+% \chapheadtype is "N" or "A", unnumbered chapters are ignored.
+\def\chapheadtype{N}
+
+% Choose a heading macro
+% #1 is heading type
+% #2 is heading level
+% #3 is text for heading
+\def\genhead#1#2#3{%
+  % Compute the abs. sec. level:
+  \absseclevel=#2
+  \advance\absseclevel by \secbase
+  % Make sure \absseclevel doesn't fall outside the range:
+  \ifnum \absseclevel < 0
+    \absseclevel = 0
+  \else
+    \ifnum \absseclevel > 3
+      \absseclevel = 3
+    \fi
+  \fi
+  % The heading type:
+  \def\headtype{#1}%
+  \if \headtype U%
+    \ifnum \absseclevel < \unmlevel
+      \chardef\unmlevel = \absseclevel
+    \fi
+  \else
+    % Check for appendix sections:
+    \ifnum \absseclevel = 0
+      \edef\chapheadtype{\headtype}%
+    \else
+      \if \headtype A\if \chapheadtype N%
+	\errmessage{@appendix... within a non-appendix chapter}%
+      \fi\fi
+    \fi
+    % Check for numbered within unnumbered:
+    \ifnum \absseclevel > \unmlevel
+      \def\headtype{U}%
+    \else
+      \chardef\unmlevel = 3
+    \fi
+  \fi
+  % Now print the heading:
+  \if \headtype U%
+    \ifcase\absseclevel
+	\unnumberedzzz{#3}%
+    \or \unnumberedseczzz{#3}%
+    \or \unnumberedsubseczzz{#3}%
+    \or \unnumberedsubsubseczzz{#3}%
+    \fi
+  \else
+    \if \headtype A%
+      \ifcase\absseclevel
+	  \appendixzzz{#3}%
+      \or \appendixsectionzzz{#3}%
+      \or \appendixsubseczzz{#3}%
+      \or \appendixsubsubseczzz{#3}%
+      \fi
+    \else
+      \ifcase\absseclevel
+	  \chapterzzz{#3}%
+      \or \seczzz{#3}%
+      \or \numberedsubseczzz{#3}%
+      \or \numberedsubsubseczzz{#3}%
+      \fi
+    \fi
+  \fi
+  \suppressfirstparagraphindent
+}
+
+% an interface:
+\def\numhead{\genhead N}
+\def\apphead{\genhead A}
+\def\unnmhead{\genhead U}
+
+% @chapter, @appendix, @unnumbered.  Increment top-level counter, reset
+% all lower-level sectioning counters to zero.
+%
+% Also set \chaplevelprefix, which we prepend to @float sequence numbers
+% (e.g., figures), q.v.  By default (before any chapter), that is empty.
+\let\chaplevelprefix = \empty
+%
+\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz#1{%
+  % section resetting is \global in case the chapter is in a group, such
+  % as an @include file.
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\chapno by 1
+  %
+  % Used for \float.
+  \gdef\chaplevelprefix{\the\chapno.}%
+  \resetallfloatnos
+  %
+  \message{\putwordChapter\space \the\chapno}%
+  %
+  % Write the actual heading.
+  \chapmacro{#1}{Ynumbered}{\the\chapno}%
+  %
+  % So @section and the like are numbered underneath this chapter.
+  \global\let\section = \numberedsec
+  \global\let\subsection = \numberedsubsec
+  \global\let\subsubsection = \numberedsubsubsec
+}
+
+\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz#1{%
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\appendixno by 1
+  \gdef\chaplevelprefix{\appendixletter.}%
+  \resetallfloatnos
+  %
+  \def\appendixnum{\putwordAppendix\space \appendixletter}%
+  \message{\appendixnum}%
+  %
+  \chapmacro{#1}{Yappendix}{\appendixletter}%
+  %
+  \global\let\section = \appendixsec
+  \global\let\subsection = \appendixsubsec
+  \global\let\subsubsection = \appendixsubsubsec
+}
+
+\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz#1{%
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\unnumberedno by 1
+  %
+  % Since an unnumbered has no number, no prefix for figures.
+  \global\let\chaplevelprefix = \empty
+  \resetallfloatnos
+  %
+  % This used to be simply \message{#1}, but TeX fully expands the
+  % argument to \message.  Therefore, if #1 contained @-commands, TeX
+  % expanded them.  For example, in `@unnumbered The @cite{Book}', TeX
+  % expanded @cite (which turns out to cause errors because \cite is meant
+  % to be executed, not expanded).
+  %
+  % Anyway, we don't want the fully-expanded definition of @cite to appear
+  % as a result of the \message, we just want `@cite' itself.  We use
+  % \the<toks register> to achieve this: TeX expands \the<toks> only once,
+  % simply yielding the contents of <toks register>.  (We also do this for
+  % the toc entries.)
+  \toks0 = {#1}%
+  \message{(\the\toks0)}%
+  %
+  \chapmacro{#1}{Ynothing}{\the\unnumberedno}%
+  %
+  \global\let\section = \unnumberedsec
+  \global\let\subsection = \unnumberedsubsec
+  \global\let\subsubsection = \unnumberedsubsubsec
+}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\parseargdef\centerchap{%
+  % Well, we could do the following in a group, but that would break
+  % an assumption that \chapmacro is called at the outermost level.
+  % Thus we are safer this way:		--kasal, 24feb04
+  \let\centerparametersmaybe = \centerparameters
+  \unnmhead0{#1}%
+  \let\centerparametersmaybe = \relax
+}
+
+% @top is like @unnumbered.
+\let\top\unnumbered
+
+% Sections.
+\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz
+\def\seczzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}%
+}
+
+\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}%
+}
+\let\appendixsec\appendixsection
+
+\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}%
+}
+
+% Subsections.
+\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}%
+}
+
+\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Yappendix}%
+                 {\appendixletter.\the\secno.\the\subsecno}%
+}
+
+\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Ynothing}%
+                 {\the\unnumberedno.\the\secno.\the\subsecno}%
+}
+
+% Subsubsections.
+\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Ynumbered}%
+                 {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Yappendix}%
+                 {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Ynothing}%
+                 {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\let\section = \numberedsec
+\let\subsection = \numberedsubsec
+\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and such:
+%       1) We use \vbox rather than the earlier \line to permit
+%          overlong headings to fold.
+%       2) \hyphenpenalty is set to 10000 because hyphenation in a
+%          heading is obnoxious; this forbids it.
+%       3) Likewise, headings look best if no \parindent is used, and
+%          if justification is not attempted.  Hence \raggedright.
+
+
+\def\majorheading{%
+  {\advance\chapheadingskip by 10pt \chapbreak }%
+  \parsearg\chapheadingzzz
+}
+
+\def\chapheading{\chapbreak \parsearg\chapheadingzzz}
+\def\chapheadingzzz#1{%
+  {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                    \parindent=0pt\raggedright
+                    \rm #1\hfill}}%
+  \bigskip \par\penalty 200\relax
+  \suppressfirstparagraphindent
+}
+
+% @heading, @subheading, @subsubheading.
+\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{%
+\global\let\contentsalignmacro = \chapoddpage
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+% Chapter opening.
+%
+% #1 is the text, #2 is the section type (Ynumbered, Ynothing,
+% Yappendix, Yomitfromtoc), #3 the chapter number.
+%
+% To test against our argument.
+\def\Ynothingkeyword{Ynothing}
+\def\Yomitfromtockeyword{Yomitfromtoc}
+\def\Yappendixkeyword{Yappendix}
+%
+\def\chapmacro#1#2#3{%
+  \pchapsepmacro
+  {%
+    \chapfonts \rm
+    %
+    % Have to define \thissection before calling \donoderef, because the
+    % xref code eventually uses it.  On the other hand, it has to be called
+    % after \pchapsepmacro, or the headline will change too soon.
+    \gdef\thissection{#1}%
+    \gdef\thischaptername{#1}%
+    %
+    % Only insert the separating space if we have a chapter/appendix
+    % number, and don't print the unnumbered ``number''.
+    \def\temptype{#2}%
+    \ifx\temptype\Ynothingkeyword
+      \setbox0 = \hbox{}%
+      \def\toctype{unnchap}%
+      \def\thischapter{#1}%
+    \else\ifx\temptype\Yomitfromtockeyword
+      \setbox0 = \hbox{}% contents like unnumbered, but no toc entry
+      \def\toctype{omit}%
+      \xdef\thischapter{}%
+    \else\ifx\temptype\Yappendixkeyword
+      \setbox0 = \hbox{\putwordAppendix{} #3\enspace}%
+      \def\toctype{app}%
+      % We don't substitute the actual chapter name into \thischapter
+      % because we don't want its macros evaluated now.  And we don't
+      % use \thissection because that changes with each section.
+      %
+      \xdef\thischapter{\putwordAppendix{} \appendixletter:
+                        \noexpand\thischaptername}%
+    \else
+      \setbox0 = \hbox{#3\enspace}%
+      \def\toctype{numchap}%
+      \xdef\thischapter{\putwordChapter{} \the\chapno:
+                        \noexpand\thischaptername}%
+    \fi\fi\fi
+    %
+    % Write the toc entry for this chapter.  Must come before the
+    % \donoderef, because we include the current node name in the toc
+    % entry, and \donoderef resets it to empty.
+    \writetocentry{\toctype}{#1}{#3}%
+    %
+    % For pdftex, we have to write out the node definition (aka, make
+    % the pdfdest) after any page break, but before the actual text has
+    % been typeset.  If the destination for the pdf outline is after the
+    % text, then jumping from the outline may wind up with the text not
+    % being visible, for instance under high magnification.
+    \donoderef{#2}%
+    %
+    % Typeset the actual heading.
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent=\wd0 \centerparametersmaybe
+          \unhbox0 #1\par}%
+  }%
+  \nobreak\bigskip % no page break after a chapter title
+  \nobreak
+}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerparameters{%
+  \advance\rightskip by 3\rightskip
+  \leftskip = \rightskip
+  \parfillskip = 0pt
+}
+
+
+% I don't think this chapter style is supported any more, so I'm not
+% updating it with the new noderef stuff.  We'll see.  --karl, 11aug03.
+%
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+%
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt\raggedright
+                       \rm #1\hfill}}\bigskip \par\nobreak
+}
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt
+                       \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+}
+\def\CHAPFopen{%
+  \global\let\chapmacro=\chfopen
+  \global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.  These macros combine the section number parts and
+% call the generic \sectionheading to do the printing.
+%
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip{-1000}}
+
+% Subsection titles.
+\newskip\subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}}
+
+% Subsubsection titles.
+\def\subsubsecheadingskip{\subsecheadingskip}
+\def\subsubsecheadingbreak{\subsecheadingbreak}
+
+
+% Print any size, any type, section title.
+%
+% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is
+% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the
+% section number.
+%
+\def\sectionheading#1#2#3#4{%
+  {%
+    % Switch to the right set of fonts.
+    \csname #2fonts\endcsname \rm
+    %
+    % Insert space above the heading.
+    \csname #2headingbreak\endcsname
+    %
+    % Only insert the space after the number if we have a section number.
+    \def\sectionlevel{#2}%
+    \def\temptype{#3}%
+    %
+    \ifx\temptype\Ynothingkeyword
+      \setbox0 = \hbox{}%
+      \def\toctype{unn}%
+      \gdef\thissection{#1}%
+    \else\ifx\temptype\Yomitfromtockeyword
+      % for @headings -- no section number, don't include in toc,
+      % and don't redefine \thissection.
+      \setbox0 = \hbox{}%
+      \def\toctype{omit}%
+      \let\sectionlevel=\empty
+    \else\ifx\temptype\Yappendixkeyword
+      \setbox0 = \hbox{#4\enspace}%
+      \def\toctype{app}%
+      \gdef\thissection{#1}%
+    \else
+      \setbox0 = \hbox{#4\enspace}%
+      \def\toctype{num}%
+      \gdef\thissection{#1}%
+    \fi\fi\fi
+    %
+    % Write the toc entry (before \donoderef).  See comments in \chfplain.
+    \writetocentry{\toctype\sectionlevel}{#1}{#4}%
+    %
+    % Write the node reference (= pdf destination for pdftex).
+    % Again, see comments in \chfplain.
+    \donoderef{#3}%
+    %
+    % Output the actual section heading.
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent=\wd0  % zero if no section number
+          \unhbox0 #1}%
+  }%
+  % Add extra space after the heading -- half of whatever came above it.
+  % Don't allow stretch, though.
+  \kern .5 \csname #2headingskip\endcsname
+  %
+  % Do not let the kern be a potential breakpoint, as it would be if it
+  % was followed by glue.
+  \nobreak
+  %
+  % We'll almost certainly start a paragraph next, so don't let that
+  % glue accumulate.  (Not a breakpoint because it's preceded by a
+  % discardable item.)
+  \vskip-\parskip
+  % 
+  % This is purely so the last item on the list is a known \penalty >
+  % 10000.  This is so \startdefun can avoid allowing breakpoints after
+  % section headings.  Otherwise, it would insert a valid breakpoint between:
+  % 
+  %   @section sec-whatever
+  %   @deffn def-whatever
+  \penalty 10001
+}
+
+
+\message{toc,}
+% Table of contents.
+\newwrite\tocfile
+
+% Write an entry to the toc file, opening it if necessary.
+% Called from @chapter, etc.
+%
+% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno}
+% We append the current node name (if any) and page number as additional
+% arguments for the \{chap,sec,...}entry macros which will eventually
+% read this.  The node name is used in the pdf outlines as the
+% destination to jump to.
+%
+% We open the .toc file for writing here instead of at @setfilename (or
+% any other fixed time) so that @contents can be anywhere in the document.
+% But if #1 is `omit', then we don't do anything.  This is used for the
+% table of contents chapter openings themselves.
+%
+\newif\iftocfileopened
+\def\omitkeyword{omit}%
+%
+\def\writetocentry#1#2#3{%
+  \edef\writetoctype{#1}%
+  \ifx\writetoctype\omitkeyword \else
+    \iftocfileopened\else
+      \immediate\openout\tocfile = \jobname.toc
+      \global\tocfileopenedtrue
+    \fi
+    %
+    \iflinks
+      \toks0 = {#2}%
+      \toks2 = \expandafter{\lastnode}%
+      \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}{#3}%
+                               {\the\toks2}{\noexpand\folio}}}%
+      \temp
+    \fi
+  \fi
+  %
+  % Tell \shipout to create a pdf destination on each page, if we're
+  % writing pdf.  These are used in the table of contents.  We can't
+  % just write one on every page because the title pages are numbered
+  % 1 and 2 (the page numbers aren't printed), and so are the first
+  % two pages of the document.  Thus, we'd have two destinations named
+  % `1', and two named `2'.
+  \ifpdf \global\pdfmakepagedesttrue \fi
+}
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\newcount\savepageno
+\newcount\lastnegativepageno \lastnegativepageno = -1
+
+% Prepare to read what we've written to \tocfile.
+%
+\def\startcontents#1{%
+  % If @setchapternewpage on, and @headings double, the contents should
+  % start on an odd page, unlike chapters.  Thus, we maintain
+  % \contentsalignmacro in parallel with \pagealignmacro.
+  % From: Torbjorn Granlund <tege@matematik.su.se>
+  \contentsalignmacro
+  \immediate\closeout\tocfile
+  %
+  % Don't need to put `Contents' or `Short Contents' in the headline.
+  % It is abundantly clear what they are.
+  \def\thischapter{}%
+  \chapmacro{#1}{Yomitfromtoc}{}%
+  %
+  \savepageno = \pageno
+  \begingroup                  % Set up to handle contents files properly.
+    \catcode`\\=0  \catcode`\{=1  \catcode`\}=2  \catcode`\@=11
+    % We can't do this, because then an actual ^ in a section
+    % title fails, e.g., @chapter ^ -- exponentiation.  --karl, 9jul97.
+    %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+    \raggedbottom             % Worry more about breakpoints than the bottom.
+    \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+    %
+    % Roman numerals for page numbers.
+    \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
+}
+
+
+% Normal (long) toc.
+\def\contents{%
+  \startcontents{\putwordTOC}%
+    \openin 1 \jobname.toc
+    \ifeof 1 \else
+      \input \jobname.toc
+    \fi
+    \vfill \eject
+    \contentsalignmacro % in case @setchapternewpage odd is in effect
+    \ifeof 1 \else
+      \pdfmakeoutlines
+    \fi
+    \closein 1
+  \endgroup
+  \lastnegativepageno = \pageno
+  \global\pageno = \savepageno
+}
+
+% And just the chapters.
+\def\summarycontents{%
+  \startcontents{\putwordShortTOC}%
+    %
+    \let\numchapentry = \shortchapentry
+    \let\appentry = \shortchapentry
+    \let\unnchapentry = \shortunnchapentry
+    % We want a true roman here for the page numbers.
+    \secfonts
+    \let\rm=\shortcontrm \let\bf=\shortcontbf
+    \let\sl=\shortcontsl \let\tt=\shortconttt
+    \rm
+    \hyphenpenalty = 10000
+    \advance\baselineskip by 1pt % Open it up a little.
+    \def\numsecentry##1##2##3##4{}
+    \let\appsecentry = \numsecentry
+    \let\unnsecentry = \numsecentry
+    \let\numsubsecentry = \numsecentry
+    \let\appsubsecentry = \numsecentry
+    \let\unnsubsecentry = \numsecentry
+    \let\numsubsubsecentry = \numsecentry
+    \let\appsubsubsecentry = \numsecentry
+    \let\unnsubsubsecentry = \numsecentry
+    \openin 1 \jobname.toc
+    \ifeof 1 \else
+      \input \jobname.toc
+    \fi
+    \closein 1
+    \vfill \eject
+    \contentsalignmacro % in case @setchapternewpage odd is in effect
+  \endgroup
+  \lastnegativepageno = \pageno
+  \global\pageno = \savepageno
+}
+\let\shortcontents = \summarycontents
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g., `A' for an appendix, or `3' for a chapter.
+%
+\def\shortchaplabel#1{%
+  % This space should be enough, since a single number is .5em, and the
+  % widest letter (M) is 1em, at least in the Computer Modern fonts.
+  % But use \hss just in case.
+  % (This space doesn't include the extra space that gets added after
+  % the label; that gets put in by \shortchapentry above.)
+  %
+  % We'd like to right-justify chapter numbers, but that looks strange
+  % with appendix letters.  And right-justifying numbers and
+  % left-justifying letters looks strange when there is less than 10
+  % chapters.  Have to read the whole toc once to know how many chapters
+  % there are before deciding ...
+  \hbox to 1em{#1\hss}%
+}
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapters, in the main contents.
+\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}}
+%
+% Chapters, in the short toc.
+% See comments in \dochapentry re vbox and related settings.
+\def\shortchapentry#1#2#3#4{%
+  \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}%
+}
+
+% Appendices, in the main contents.
+% Need the word Appendix, and a fixed-size box.
+%
+\def\appendixbox#1{%
+  % We use M since it's probably the widest letter.
+  \setbox0 = \hbox{\putwordAppendix{} M}%
+  \hbox to \wd0{\putwordAppendix{} #1\hss}}
+%
+\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}}
+
+% Unnumbered chapters.
+\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}}
+\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}}
+
+% Sections.
+\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}}
+\let\appsecentry=\numsecentry
+\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}}
+
+% Subsections.
+\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsecentry=\numsubsecentry
+\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}}
+
+% And subsubsections.
+\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsubsecentry=\numsubsubsecentry
+\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}}
+
+% This parameter controls the indentation of the various levels.
+% Same as \defaultparindent.
+\newdimen\tocindent \tocindent = 15pt
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we want it to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+   \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+   \begingroup
+     \chapentryfonts
+     \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+   \endgroup
+   \nobreak\vskip .25\baselineskip plus.1\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+  \secentryfonts \leftskip=\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+  \subsecentryfonts \leftskip=2\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+  \subsubsecentryfonts \leftskip=3\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+% We use the same \entry macro as for the index entries.
+\let\tocentry = \entry
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\def\subsecentryfonts{\textfonts}
+\def\subsubsecentryfonts{\textfonts}
+
+
+\message{environments,}
+% @foo ... @end foo.
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+%
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+%
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% The @error{} command.
+% Adapted from the TeXbook's \boxit.
+%
+\newbox\errorbox
+%
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+%
+\setbox\errorbox=\hbox to \dimen0{\hfil
+   \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+   \advance\hsize by -2\dimen2 % Rules.
+   \vbox{%
+      \hrule height\dimen2
+      \hbox{\vrule width\dimen2 \kern3pt          % Space to left of text.
+         \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+         \kern3pt\vrule width\dimen2}% Space to right.
+      \hrule height\dimen2}
+    \hfil}
+%
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex    escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\envdef\tex{%
+  \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+  \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+  \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
+  \catcode `\%=14
+  \catcode `\+=\other
+  \catcode `\"=\other
+  \catcode `\|=\other
+  \catcode `\<=\other
+  \catcode `\>=\other
+  \escapechar=`\\
+  %
+  \let\b=\ptexb
+  \let\bullet=\ptexbullet
+  \let\c=\ptexc
+  \let\,=\ptexcomma
+  \let\.=\ptexdot
+  \let\dots=\ptexdots
+  \let\equiv=\ptexequiv
+  \let\!=\ptexexclam
+  \let\i=\ptexi
+  \let\indent=\ptexindent
+  \let\noindent=\ptexnoindent
+  \let\{=\ptexlbrace
+  \let\+=\tabalign
+  \let\}=\ptexrbrace
+  \let\/=\ptexslash
+  \let\*=\ptexstar
+  \let\t=\ptext
+  %
+  \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+  \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+  \def\@{@}%
+}
+% There is no need to define \Etex.
+
+% Define @lisp ... @end lisp.
+% @lisp environment forms a group so it can rebind things,
+% including the definition of @end lisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments.  \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical.  We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip.
+%
+\def\aboveenvbreak{{%
+  % =10000 instead of <10000 because of a special case in \itemzzz and
+  % \sectionheading, q.v.
+  \ifnum \lastpenalty=10000 \else
+    \advance\envskipamount by \parskip
+    \endgraf
+    \ifdim\lastskip<\envskipamount
+      \removelastskip
+      % it's not a good place to break if the last penalty was \nobreak
+      % or better ...
+      \ifnum\lastpenalty<10000 \penalty-50 \fi
+      \vskip\envskipamount
+    \fi
+  \fi
+}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag.  If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+% @cartouche ... @end cartouche: draw rectangle w/rounded corners around
+% environment contents.
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+        \ctl\leaders\hrule height\circthick\hfil\ctr
+        \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+        \cbl\leaders\hrule height\circthick\hfil\cbr
+        \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\envdef\cartouche{%
+  \ifhmode\par\fi  % can't be in the midst of a paragraph.
+  \startsavinginserts
+  \lskip=\leftskip \rskip=\rightskip
+  \leftskip=0pt\rightskip=0pt % we want these *outside*.
+  \cartinner=\hsize \advance\cartinner by-\lskip
+  \advance\cartinner by-\rskip
+  \cartouter=\hsize
+  \advance\cartouter by 18.4pt	% allow for 3pt kerns on either
+				% side, and for 6pt waste from
+				% each corner char, and rule thickness
+  \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+  % Flag to tell @lisp, etc., not to narrow margin.
+  \let\nonarrowing=\comment
+  \vbox\bgroup
+      \baselineskip=0pt\parskip=0pt\lineskip=0pt
+      \carttop
+      \hbox\bgroup
+	  \hskip\lskip
+	  \vrule\kern3pt
+	  \vbox\bgroup
+	      \kern3pt
+	      \hsize=\cartinner
+	      \baselineskip=\normbskip
+	      \lineskip=\normlskip
+	      \parskip=\normpskip
+	      \vskip -\parskip
+	      \comment % For explanation, see the end of \def\group.
+}
+\def\Ecartouche{%
+              \ifhmode\par\fi
+	      \kern3pt
+	  \egroup
+	  \kern3pt\vrule
+	  \hskip\rskip
+      \egroup
+      \cartbot
+  \egroup
+  \checkinserts
+}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+  \aboveenvbreak
+  \hfuzz = 12pt % Don't be fussy
+  \sepspaces % Make spaces be word-separators rather than space tokens.
+  \let\par = \lisppar % don't ignore blank lines
+  \obeylines % each line of input is a line of output
+  \parskip = 0pt
+  \parindent = 0pt
+  \emergencystretch = 0pt % don't try to avoid overfull boxes
+  % @cartouche defines \nonarrowing to inhibit narrowing
+  % at next level down.
+  \ifx\nonarrowing\relax
+    \advance \leftskip by \lispnarrowing
+    \exdentamount=\lispnarrowing
+  \fi
+  \let\exdent=\nofillexdent
+}
+
+% If you want all examples etc. small: @set dispenvsize small.
+% If you want even small examples the full size: @set dispenvsize nosmall.
+% This affects the following displayed environments:
+%    @example, @display, @format, @lisp
+%
+\def\smallword{small}
+\def\nosmallword{nosmall}
+\let\SETdispenvsize\relax
+\def\setnormaldispenv{%
+  \ifx\SETdispenvsize\smallword
+    \smallexamplefonts \rm
+  \fi
+}
+\def\setsmalldispenv{%
+  \ifx\SETdispenvsize\nosmallword
+  \else
+    \smallexamplefonts \rm
+  \fi
+}
+
+% We often define two environments, @foo and @smallfoo.
+% Let's do it by one command:
+\def\makedispenv #1#2{
+  \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}
+  \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}
+  \expandafter\let\csname E#1\endcsname \afterenvbreak
+  \expandafter\let\csname Esmall#1\endcsname \afterenvbreak
+}
+
+% Define two synonyms:
+\def\maketwodispenvs #1#2#3{
+  \makedispenv{#1}{#3}
+  \makedispenv{#2}{#3}
+}
+
+% @lisp: indented, narrowed, typewriter font; @example: same as @lisp.
+%
+% @smallexample and @smalllisp: use smaller fonts.
+% Originally contributed by Pavel@xerox.
+%
+\maketwodispenvs {lisp}{example}{%
+  \nonfillstart
+  \tt
+  \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+  \gobble       % eat return
+}
+
+% @display/@smalldisplay: same as @lisp except keep current font.
+%
+\makedispenv {display}{%
+  \nonfillstart
+  \gobble
+}
+
+% @format/@smallformat: same as @display except don't narrow margins.
+%
+\makedispenv{format}{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \gobble
+}
+
+% @flushleft: same as @format, but doesn't obey \SETdispenvsize.
+\envdef\flushleft{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \gobble
+}
+\let\Eflushleft = \afterenvbreak
+
+% @flushright.
+%
+\envdef\flushright{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \advance\leftskip by 0pt plus 1fill
+  \gobble
+}
+\let\Eflushright = \afterenvbreak
+
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.  We keep \parskip nonzero in general, since
+% we're doing normal filling.  So, when using \aboveenvbreak and
+% \afterenvbreak, temporarily make \parskip 0.
+%
+\envdef\quotation{%
+  {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+  \parindent=0pt
+  %
+  % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+  \ifx\nonarrowing\relax
+    \advance\leftskip by \lispnarrowing
+    \advance\rightskip by \lispnarrowing
+    \exdentamount = \lispnarrowing
+    \let\nonarrowing = \relax
+  \fi
+  \parsearg\quotationlabel
+}
+
+% We have retained a nonzero parskip for the environment, since we're
+% doing normal filling.
+%
+\def\Equotation{%
+  \par
+  \ifx\quotationauthor\undefined\else
+    % indent a bit.
+    \leftline{\kern 2\leftskip \sl ---\quotationauthor}%
+  \fi
+  {\parskip=0pt \afterenvbreak}%
+}
+
+% If we're given an argument, typeset it in bold with a colon after.
+\def\quotationlabel#1{%
+  \def\temp{#1}%
+  \ifx\temp\empty \else
+    {\bf #1: }%
+  \fi
+}
+
+
+% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>}
+% If we want to allow any <char> as delimiter,
+% we need the curly braces so that makeinfo sees the @verb command, eg:
+% `@verbx...x' would look like the '@verbx' command.  --janneke@gnu.org
+%
+% [Knuth]: Donald Ervin Knuth, 1996.  The TeXbook.
+%
+% [Knuth] p.344; only we need to do the other characters Texinfo sets
+% active too.  Otherwise, they get lost as the first character on a
+% verbatim line.
+\def\dospecials{%
+  \do\ \do\\\do\{\do\}\do\$\do\&%
+  \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
+  \do\<\do\>\do\|\do\@\do+\do\"%
+}
+%
+% [Knuth] p. 380
+\def\uncatcodespecials{%
+  \def\do##1{\catcode`##1=\other}\dospecials}
+%
+% [Knuth] pp. 380,381,391
+% Disable Spanish ligatures ?` and !` of \tt font
+\begingroup
+  \catcode`\`=\active\gdef`{\relax\lq}
+\endgroup
+%
+% Setup for the @verb command.
+%
+% Eight spaces for a tab
+\begingroup
+  \catcode`\^^I=\active
+  \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }}
+\endgroup
+%
+\def\setupverb{%
+  \tt  % easiest (and conventionally used) font for verbatim
+  \def\par{\leavevmode\endgraf}%
+  \catcode`\`=\active
+  \tabeightspaces
+  % Respect line breaks,
+  % print special symbols as themselves, and
+  % make each space count
+  % must do in this order:
+  \obeylines \uncatcodespecials \sepspaces
+}
+
+% Setup for the @verbatim environment
+%
+% Real tab expansion
+\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
+%
+\def\starttabbox{\setbox0=\hbox\bgroup}
+\begingroup
+  \catcode`\^^I=\active
+  \gdef\tabexpand{%
+    \catcode`\^^I=\active
+    \def^^I{\leavevmode\egroup
+      \dimen0=\wd0 % the width so far, or since the previous tab
+      \divide\dimen0 by\tabw
+      \multiply\dimen0 by\tabw % compute previous multiple of \tabw
+      \advance\dimen0 by\tabw  % advance to next multiple of \tabw
+      \wd0=\dimen0 \box0 \starttabbox
+    }%
+  }
+\endgroup
+\def\setupverbatim{%
+  \nonfillstart
+  \advance\leftskip by -\defbodyindent
+  % Easiest (and conventionally used) font for verbatim
+  \tt
+  \def\par{\leavevmode\egroup\box0\endgraf}%
+  \catcode`\`=\active
+  \tabexpand
+  % Respect line breaks,
+  % print special symbols as themselves, and
+  % make each space count
+  % must do in this order:
+  \obeylines \uncatcodespecials \sepspaces
+  \everypar{\starttabbox}%
+}
+
+% Do the @verb magic: verbatim text is quoted by unique
+% delimiter characters.  Before first delimiter expect a
+% right brace, after last delimiter expect closing brace:
+%
+%    \def\doverb'{'<char>#1<char>'}'{#1}
+%
+% [Knuth] p. 382; only eat outer {}
+\begingroup
+  \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other
+  \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next]
+\endgroup
+%
+\def\verb{\begingroup\setupverb\doverb}
+%
+%
+% Do the @verbatim magic: define the macro \doverbatim so that
+% the (first) argument ends when '@end verbatim' is reached, ie:
+%
+%     \def\doverbatim#1@end verbatim{#1}
+%
+% For Texinfo it's a lot easier than for LaTeX,
+% because texinfo's \verbatim doesn't stop at '\end{verbatim}':
+% we need not redefine '\', '{' and '}'.
+%
+% Inspired by LaTeX's verbatim command set [latex.ltx]
+%
+\begingroup
+  \catcode`\ =\active
+  \obeylines %
+  % ignore everything up to the first ^^M, that's the newline at the end
+  % of the @verbatim input line itself.  Otherwise we get an extra blank
+  % line in the output.
+  \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}%
+  % We really want {...\end verbatim} in the body of the macro, but
+  % without the active space; thus we have to use \xdef and \gobble.
+\endgroup
+%
+\envdef\verbatim{%
+    \setupverbatim\doverbatim
+}
+\let\Everbatim = \afterenvbreak
+
+
+% @verbatiminclude FILE - insert text of file in verbatim environment.
+%
+\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude}
+%
+\def\doverbatiminclude#1{%
+  {%
+    \makevalueexpandable
+    \setupverbatim
+    \input #1
+    \afterenvbreak
+  }%
+}
+
+% @copying ... @end copying.
+% Save the text away for @insertcopying later.
+%
+% We save the uninterpreted tokens, rather than creating a box.
+% Saving the text in a box would be much easier, but then all the
+% typesetting commands (@smallbook, font changes, etc.) have to be done
+% beforehand -- and a) we want @copying to be done first in the source
+% file; b) letting users define the frontmatter in as flexible order as
+% possible is very desirable.
+%
+\def\copying{\checkenv{}\begingroup\scanargctxt\docopying}
+\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}}
+%
+\def\insertcopying{%
+  \begingroup
+    \parindent = 0pt  % paragraph indentation looks wrong on title page
+    \scanexp\copyingtext
+  \endgroup
+}
+
+\message{defuns,}
+% @defun etc.
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+% Start the processing of @deffn:
+\def\startdefun{%
+  \ifnum\lastpenalty<10000
+    \medbreak
+  \else
+    % If there are two @def commands in a row, we'll have a \nobreak,
+    % which is there to keep the function description together with its
+    % header.  But if there's nothing but headers, we need to allow a
+    % break somewhere.  Check specifically for penalty 10002, inserted
+    % by \defargscommonending, instead of 10000, since the sectioning
+    % commands also insert a nobreak penalty, and we don't want to allow
+    % a break between a section heading and a defun.
+    % 
+    \ifnum\lastpenalty=10002 \penalty2000 \fi
+    %
+    % Similarly, after a section heading, do not allow a break.
+    % But do insert the glue.
+    \medskip  % preceded by discardable penalty, so not a breakpoint
+  \fi
+  %
+  \parindent=0in
+  \advance\leftskip by \defbodyindent
+  \exdentamount=\defbodyindent
+}
+
+\def\dodefunx#1{%
+  % First, check whether we are in the right environment:
+  \checkenv#1%
+  %
+  % As above, allow line break if we have multiple x headers in a row.
+  % It's not a great place, though.
+  \ifnum\lastpenalty=10002 \penalty3000 \fi
+  %
+  % And now, it's time to reuse the body of the original defun:
+  \expandafter\gobbledefun#1%
+}
+\def\gobbledefun#1\startdefun{}
+
+% \printdefunline \deffnheader{text}
+%
+\def\printdefunline#1#2{%
+  \begingroup
+    % call \deffnheader:
+    #1#2 \endheader
+    % common ending:
+    \interlinepenalty = 10000
+    \advance\rightskip by 0pt plus 1fil
+    \endgraf
+    \nobreak\vskip -\parskip
+    \penalty 10002  % signal to \startdefun and \dodefunx
+    % Some of the @defun-type tags do not enable magic parentheses,
+    % rendering the following check redundant.  But we don't optimize.
+    \checkparencounts
+  \endgroup
+}
+
+\def\Edefun{\endgraf\medbreak}
+
+% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn;
+% the only thing remainnig is to define \deffnheader.
+%
+\def\makedefun#1{%
+  \expandafter\let\csname E#1\endcsname = \Edefun
+  \edef\temp{\noexpand\domakedefun
+    \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}%
+  \temp
+}
+
+% \domakedefun \deffn \deffnx \deffnheader
+%
+% Define \deffn and \deffnx, without parameters.
+% \deffnheader has to be defined explicitly.
+%
+\def\domakedefun#1#2#3{%
+  \envdef#1{%
+    \startdefun
+    \parseargusing\activeparens{\printdefunline#3}%
+  }%
+  \def#2{\dodefunx#1}%
+  \def#3%
+}
+
+%%% Untyped functions:
+
+% @deffn category name args
+\makedefun{deffn}{\deffngeneral{}}
+
+% @deffn category class name args
+\makedefun{defop}#1 {\defopon{#1\ \putwordon}}
+
+% \defopon {category on}class name args
+\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
+
+% \deffngeneral {subind}category name args
+%
+\def\deffngeneral#1#2 #3 #4\endheader{%
+  % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}.
+  \dosubind{fn}{\code{#3}}{#1}%
+  \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}%
+}
+
+%%% Typed functions:
+
+% @deftypefn category type name args
+\makedefun{deftypefn}{\deftypefngeneral{}}
+
+% @deftypeop category class type name args
+\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}}
+
+% \deftypeopon {category on}class type name args
+\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
+
+% \deftypefngeneral {subind}category type name args
+%
+\def\deftypefngeneral#1#2 #3 #4 #5\endheader{%
+  \dosubind{fn}{\code{#4}}{#1}%
+  \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
+}
+
+%%% Typed variables:
+
+% @deftypevr category type var args
+\makedefun{deftypevr}{\deftypecvgeneral{}}
+
+% @deftypecv category class type var args
+\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}}
+
+% \deftypecvof {category of}class type var args
+\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} }
+
+% \deftypecvgeneral {subind}category type var args
+%
+\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{%
+  \dosubind{vr}{\code{#4}}{#1}%
+  \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
+}
+
+%%% Untyped variables:
+
+% @defvr category var args
+\makedefun{defvr}#1 {\deftypevrheader{#1} {} }
+
+% @defcv category class var args
+\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}}
+
+% \defcvof {category of}class var args
+\def\defcvof#1#2 {\deftypecvof{#1}#2 {} }
+
+%%% Type:
+% @deftp category name args
+\makedefun{deftp}#1 #2 #3\endheader{%
+  \doind{tp}{\code{#2}}%
+  \defname{#1}{}{#2}\defunargs{#3\unskip}%
+}
+
+% Remaining @defun-like shortcuts:
+\makedefun{defun}{\deffnheader{\putwordDeffunc} }
+\makedefun{defmac}{\deffnheader{\putwordDefmac} }
+\makedefun{defspec}{\deffnheader{\putwordDefspec} }
+\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} }
+\makedefun{defvar}{\defvrheader{\putwordDefvar} }
+\makedefun{defopt}{\defvrheader{\putwordDefopt} }
+\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} }
+\makedefun{defmethod}{\defopon\putwordMethodon}
+\makedefun{deftypemethod}{\deftypeopon\putwordMethodon}
+\makedefun{defivar}{\defcvof\putwordInstanceVariableof}
+\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof}
+
+% \defname, which formats the name of the @def (not the args).
+% #1 is the category, such as "Function".
+% #2 is the return type, if any.
+% #3 is the function name.
+%
+% We are followed by (but not passed) the arguments, if any.
+%
+\def\defname#1#2#3{%
+  % Get the values of \leftskip and \rightskip as they were outside the @def...
+  \advance\leftskip by -\defbodyindent
+  %
+  % How we'll format the type name.  Putting it in brackets helps
+  % distinguish it from the body text that may end up on the next line
+  % just below it.
+  \def\temp{#1}%
+  \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi}
+  %
+  % Figure out line sizes for the paragraph shape.
+  % The first line needs space for \box0; but if \rightskip is nonzero,
+  % we need only space for the part of \box0 which exceeds it:
+  \dimen0=\hsize  \advance\dimen0 by -\wd0  \advance\dimen0 by \rightskip
+  % The continuations:
+  \dimen2=\hsize  \advance\dimen2 by -\defargsindent
+  % (plain.tex says that \dimen1 should be used only as global.)
+  \parshape 2 0in \dimen0 \defargsindent \dimen2
+  %
+  % Put the type name to the right margin.
+  \noindent
+  \hbox to 0pt{%
+    \hfil\box0 \kern-\hsize
+    % \hsize has to be shortened this way:
+    \kern\leftskip
+    % Intentionally do not respect \rightskip, since we need the space.
+  }%
+  %
+  % Allow all lines to be underfull without complaint:
+  \tolerance=10000 \hbadness=10000
+  \exdentamount=\defbodyindent
+  {%
+    % defun fonts. We use typewriter by default (used to be bold) because:
+    % . we're printing identifiers, they should be in tt in principle.
+    % . in languages with many accents, such as Czech or French, it's
+    %   common to leave accents off identifiers.  The result looks ok in
+    %   tt, but exceedingly strange in rm.
+    % . we don't want -- and --- to be treated as ligatures.
+    % . this still does not fix the ?` and !` ligatures, but so far no
+    %   one has made identifiers using them :).
+    \df \tt
+    \def\temp{#2}% return value type
+    \ifx\temp\empty\else \tclose{\temp} \fi
+    #3% output function name
+  }%
+  {\rm\enskip}% hskip 0.5 em of \tenrm
+  %
+  \boldbrax
+  % arguments will be output next, if any.
+}
+
+% Print arguments in slanted roman (not ttsl), inconsistently with using
+% tt for the name.  This is because literal text is sometimes needed in
+% the argument list (groff manual), and ttsl and tt are not very
+% distinguishable.  Prevent hyphenation at `-' chars.
+%
+\def\defunargs#1{%
+  % use sl by default (not ttsl),
+  % tt for the names.
+  \df \sl \hyphenchar\font=0
+  %
+  % On the other hand, if an argument has two dashes (for instance), we
+  % want a way to get ttsl.  Let's try @var for that.
+  \let\var=\ttslanted
+  #1%
+  \sl\hyphenchar\font=45
+}
+
+% We want ()&[] to print specially on the defun line.
+%
+\def\activeparens{%
+  \catcode`\(=\active \catcode`\)=\active
+  \catcode`\[=\active \catcode`\]=\active
+  \catcode`\&=\active
+}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+% Be sure that we always have a definition for `(', etc.  For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+{
+  \activeparens
+  \global\let(=\lparen \global\let)=\rparen
+  \global\let[=\lbrack \global\let]=\rbrack
+  \global\let& = \&
+
+  \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+  \gdef\magicamp{\let&=\amprm}
+}
+
+\newcount\parencount
+
+% If we encounter &foo, then turn on ()-hacking afterwards
+\newif\ifampseen
+\def\amprm#1 {\ampseentrue{\bf\&#1 }}
+
+\def\parenfont{%
+  \ifampseen
+    % At the first level, print parens in roman,
+    % otherwise use the default font.
+    \ifnum \parencount=1 \rm \fi
+  \else
+    % The \sf parens (in \boldbrax) actually are a little bolder than
+    % the contained text.  This is especially needed for [ and ] .
+    \sf
+  \fi
+}
+\def\infirstlevel#1{%
+  \ifampseen
+    \ifnum\parencount=1
+      #1%
+    \fi
+  \fi
+}
+\def\bfafterword#1 {#1 \bf}
+
+\def\opnr{%
+  \global\advance\parencount by 1
+  {\parenfont(}%
+  \infirstlevel \bfafterword
+}
+\def\clnr{%
+  {\parenfont)}%
+  \infirstlevel \sl
+  \global\advance\parencount by -1
+}
+
+\newcount\brackcount
+\def\lbrb{%
+  \global\advance\brackcount by 1
+  {\bf[}%
+}
+\def\rbrb{%
+  {\bf]}%
+  \global\advance\brackcount by -1
+}
+
+\def\checkparencounts{%
+  \ifnum\parencount=0 \else \badparencount \fi
+  \ifnum\brackcount=0 \else \badbrackcount \fi
+}
+\def\badparencount{%
+  \errmessage{Unbalanced parentheses in @def}%
+  \global\parencount=0
+}
+\def\badbrackcount{%
+  \errmessage{Unbalanced square braces in @def}%
+  \global\brackcount=0
+}
+
+
+\message{macros,}
+% @macro.
+
+% To do this right we need a feature of e-TeX, \scantokens,
+% which we arrange to emulate with a temporary file in ordinary TeX.
+\ifx\eTeXversion\undefined
+  \newwrite\macscribble
+  \def\scantokens#1{%
+    \toks0={#1}%
+    \immediate\openout\macscribble=\jobname.tmp
+    \immediate\write\macscribble{\the\toks0}%
+    \immediate\closeout\macscribble
+    \input \jobname.tmp
+  }
+\fi
+
+\def\scanmacro#1{%
+  \begingroup
+    \newlinechar`\^^M
+    \let\xeatspaces\eatspaces
+    % Undo catcode changes of \startcontents and \doprintindex
+    \catcode`\@=0 \catcode`\\=\other \escapechar=`\@
+    % ... and \example
+    \spaceisspace
+    %
+    % Append \endinput to make sure that TeX does not see the ending newline.
+    %
+    % I've verified that it is necessary both for e-TeX and for ordinary TeX
+    %							--kasal, 29nov03
+    \scantokens{#1\endinput}%
+  \endgroup
+}
+
+\def\scanexp#1{%
+  \edef\temp{\noexpand\scanmacro{#1}}%
+  \temp
+}
+
+\newcount\paramno   % Count of parameters
+\newtoks\macname    % Macro name
+\newif\ifrecursive  % Is it recursive?
+\def\macrolist{}    % List of all defined macros in the form
+                    % \do\macro1\do\macro2...
+
+% Utility routines.
+% This does \let #1 = #2, except with \csnames.
+\def\cslet#1#2{%
+\expandafter\expandafter
+\expandafter\let
+\expandafter\expandafter
+\csname#1\endcsname
+\csname#2\endcsname}
+
+% Trim leading and trailing spaces off a string.
+% Concepts from aro-bend problem 15 (see CTAN).
+{\catcode`\@=11
+\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
+\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
+\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
+\def\unbrace#1{#1}
+\unbrace{\gdef\trim@@@ #1 } #2@{#1}
+}
+
+% Trim a single trailing ^^M off a string.
+{\catcode`\^^M=\other \catcode`\Q=3%
+\gdef\eatcr #1{\eatcra #1Q^^MQ}%
+\gdef\eatcra#1^^MQ{\eatcrb#1Q}%
+\gdef\eatcrb#1Q#2Q{#1}%
+}
+
+% Macro bodies are absorbed as an argument in a context where
+% all characters are catcode 10, 11 or 12, except \ which is active
+% (as in normal texinfo). It is necessary to change the definition of \.
+
+% It's necessary to have hard CRs when the macro is executed. This is
+% done by  making ^^M (\endlinechar) catcode 12 when reading the macro
+% body, and then making it the \newlinechar in \scanmacro.
+
+\def\scanctxt{%
+  \catcode`\~=\other
+  \catcode`\^=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\+=\other
+  \catcode`\@=\other
+}
+
+\def\scanargctxt{%
+  \scanctxt
+  \catcode`\\=\other
+  \catcode`\^^M=\other
+}
+
+\def\macrobodyctxt{%
+  \scanctxt
+  \catcode`\{=\other
+  \catcode`\}=\other
+  \catcode`\^^M=\other
+  \usembodybackslash
+}
+
+\def\macroargctxt{%
+  \scanctxt
+  \catcode`\\=\other
+}
+
+% \mbodybackslash is the definition of \ in @macro bodies.
+% It maps \foo\ => \csname macarg.foo\endcsname => #N
+% where N is the macro parameter number.
+% We define \csname macarg.\endcsname to be \realbackslash, so
+% \\ in macro replacement text gets you a backslash.
+
+{\catcode`@=0 @catcode`@\=@active
+ @gdef@usembodybackslash{@let\=@mbodybackslash}
+ @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname}
+}
+\expandafter\def\csname macarg.\endcsname{\realbackslash}
+
+\def\macro{\recursivefalse\parsearg\macroxxx}
+\def\rmacro{\recursivetrue\parsearg\macroxxx}
+
+\def\macroxxx#1{%
+  \getargs{#1}%           now \macname is the macname and \argl the arglist
+  \ifx\argl\empty       % no arguments
+     \paramno=0%
+  \else
+     \expandafter\parsemargdef \argl;%
+  \fi
+  \if1\csname ismacro.\the\macname\endcsname
+     \message{Warning: redefining \the\macname}%
+  \else
+     \expandafter\ifx\csname \the\macname\endcsname \relax
+     \else \errmessage{Macro name \the\macname\space already defined}\fi
+     \global\cslet{macsave.\the\macname}{\the\macname}%
+     \global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
+     % Add the macroname to \macrolist
+     \toks0 = \expandafter{\macrolist\do}%
+     \xdef\macrolist{\the\toks0
+       \expandafter\noexpand\csname\the\macname\endcsname}%
+  \fi
+  \begingroup \macrobodyctxt
+  \ifrecursive \expandafter\parsermacbody
+  \else \expandafter\parsemacbody
+  \fi}
+
+\parseargdef\unmacro{%
+  \if1\csname ismacro.#1\endcsname
+    \global\cslet{#1}{macsave.#1}%
+    \global\expandafter\let \csname ismacro.#1\endcsname=0%
+    % Remove the macro name from \macrolist:
+    \begingroup
+      \expandafter\let\csname#1\endcsname \relax
+      \let\do\unmacrodo
+      \xdef\macrolist{\macrolist}%
+    \endgroup
+  \else
+    \errmessage{Macro #1 not defined}%
+  \fi
+}
+
+% Called by \do from \dounmacro on each macro.  The idea is to omit any
+% macro definitions that have been changed to \relax.
+%
+\def\unmacrodo#1{%
+  \ifx#1\relax
+    % remove this
+  \else
+    \noexpand\do \noexpand #1%
+  \fi
+}
+
+% This makes use of the obscure feature that if the last token of a
+% <parameter list> is #, then the preceding argument is delimited by
+% an opening brace, and that opening brace is not consumed.
+\def\getargs#1{\getargsxxx#1{}}
+\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
+\def\getmacname #1 #2\relax{\macname={#1}}
+\def\getmacargs#1{\def\argl{#1}}
+
+% Parse the optional {params} list.  Set up \paramno and \paramlist
+% so \defmacro knows what to do.  Define \macarg.blah for each blah
+% in the params list, to be ##N where N is the position in that list.
+% That gets used by \mbodybackslash (above).
+
+% We need to get `macro parameter char #' into several definitions.
+% The technique used is stolen from LaTeX:  let \hash be something
+% unexpandable, insert that wherever you need a #, and then redefine
+% it to # just before using the token list produced.
+%
+% The same technique is used to protect \eatspaces till just before
+% the macro is used.
+
+\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
+        \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+\def\parsemargdefxxx#1,{%
+  \if#1;\let\next=\relax
+  \else \let\next=\parsemargdefxxx
+    \advance\paramno by 1%
+    \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
+        {\xeatspaces{\hash\the\paramno}}%
+    \edef\paramlist{\paramlist\hash\the\paramno,}%
+  \fi\next}
+
+% These two commands read recursive and nonrecursive macro bodies.
+% (They're different since rec and nonrec macros end differently.)
+
+\long\def\parsemacbody#1@end macro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+\long\def\parsermacbody#1@end rmacro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+
+% This defines the macro itself. There are six cases: recursive and
+% nonrecursive macros of zero, one, and many arguments.
+% Much magic with \expandafter here.
+% \xdef is used so that macro definitions will survive the file
+% they're defined in; @include reads the file inside a group.
+\def\defmacro{%
+  \let\hash=##% convert placeholders to macro parameter chars
+  \ifrecursive
+    \ifcase\paramno
+    % 0
+      \expandafter\xdef\csname\the\macname\endcsname{%
+        \noexpand\scanmacro{\temp}}%
+    \or % 1
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+      \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+         \egroup\noexpand\scanmacro{\temp}}%
+    \else % many
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\csname\the\macname xx\endcsname}%
+      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+      \expandafter\expandafter
+      \expandafter\xdef
+      \expandafter\expandafter
+        \csname\the\macname xxx\endcsname
+          \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+    \fi
+  \else
+    \ifcase\paramno
+    % 0
+      \expandafter\xdef\csname\the\macname\endcsname{%
+        \noexpand\norecurse{\the\macname}%
+        \noexpand\scanmacro{\temp}\egroup}%
+    \or % 1
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+      \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+        \egroup
+        \noexpand\norecurse{\the\macname}%
+        \noexpand\scanmacro{\temp}\egroup}%
+    \else % many
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \expandafter\noexpand\csname\the\macname xx\endcsname}%
+      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+      \expandafter\expandafter
+      \expandafter\xdef
+      \expandafter\expandafter
+      \csname\the\macname xxx\endcsname
+      \paramlist{%
+          \egroup
+          \noexpand\norecurse{\the\macname}%
+          \noexpand\scanmacro{\temp}\egroup}%
+    \fi
+  \fi}
+
+\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
+
+% \braceorline decides whether the next nonwhitespace character is a
+% {.  If so it reads up to the closing }, if not, it reads the whole
+% line.  Whatever was read is then fed to the next control sequence
+% as an argument (by \parsebrace or \parsearg)
+\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx}
+\def\braceorlinexxx{%
+  \ifx\nchar\bgroup\else
+    \expandafter\parsearg
+  \fi \next}
+
+% We want to disable all macros during \shipout so that they are not
+% expanded by \write.
+\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}%
+  \edef\next{\macrolist}\expandafter\endgroup\next}
+
+% For \indexnofonts, we need to get rid of all macros, leaving only the
+% arguments (if present).  Of course this is not nearly correct, but it
+% is the best we can do for now.  makeinfo does not expand macros in the
+% argument to @deffn, which ends up writing an index entry, and texindex
+% isn't prepared for an index sort entry that starts with \.
+% 
+% Since macro invocations are followed by braces, we can just redefine them
+% to take a single TeX argument.  The case of a macro invocation that
+% goes to end-of-line is not handled.
+% 
+\def\emptyusermacros{\begingroup
+  \def\do##1{\let\noexpand##1=\noexpand\asis}%
+  \edef\next{\macrolist}\expandafter\endgroup\next}
+
+
+% @alias.
+% We need some trickery to remove the optional spaces around the equal
+% sign.  Just make them active and then expand them all to nothing.
+\def\alias{\parseargusing\obeyspaces\aliasxxx}
+\def\aliasxxx #1{\aliasyyy#1\relax}
+\def\aliasyyy #1=#2\relax{%
+  {%
+    \expandafter\let\obeyedspace=\empty
+    \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}%
+  }%
+  \next
+}
+
+
+\message{cross references,}
+
+\newwrite\auxfile
+
+\newif\ifhavexrefs    % True if xref values are known.
+\newif\ifwarnedxrefs  % True if we warned once that they aren't known.
+
+% @inforef is relatively simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+  node \samp{\ignorespaces#1{}}}
+
+% @node's only job in TeX is to define \lastnode, which is used in
+% cross-references.  The @node line might or might not have commas, and
+% might or might not have spaces before the first comma, like:
+% @node foo , bar , ...
+% We don't want such trailing spaces in the node name.
+%
+\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse}
+%
+% also remove a trailing comma, in case of something like this:
+% @node Help-Cross,  ,  , Cross-refs
+\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse}
+\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}}
+
+\let\nwnode=\node
+\let\lastnode=\empty
+
+% Write a cross-reference definition for the current node.  #1 is the
+% type (Ynumbered, Yappendix, Ynothing).
+%
+\def\donoderef#1{%
+  \ifx\lastnode\empty\else
+    \setref{\lastnode}{#1}%
+    \global\let\lastnode=\empty
+  \fi
+}
+
+% @anchor{NAME} -- define xref target at arbitrary point.
+%
+\newcount\savesfregister
+%
+\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
+\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
+\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
+
+% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an
+% anchor), which consists of three parts:
+% 1) NAME-title - the current sectioning name taken from \thissection,
+%                 or the anchor name.
+% 2) NAME-snt   - section number and type, passed as the SNT arg, or
+%                 empty for anchors.
+% 3) NAME-pg    - the page number.
+%
+% This is called from \donoderef, \anchor, and \dofloat.  In the case of
+% floats, there is an additional part, which is not written here:
+% 4) NAME-lof   - the text as it should appear in a @listoffloats.
+%
+\def\setref#1#2{%
+  \pdfmkdest{#1}%
+  \iflinks
+    {%
+      \atdummies  % preserve commands, but don't expand them
+      \turnoffactive
+      \otherbackslash
+      \edef\writexrdef##1##2{%
+	\write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef
+	  ##1}{##2}}% these are parameters of \writexrdef
+      }%
+      \toks0 = \expandafter{\thissection}%
+      \immediate \writexrdef{title}{\the\toks0 }%
+      \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
+      \writexrdef{pg}{\folio}% will be written later, during \shipout
+    }%
+  \fi
+}
+
+% @xref, @pxref, and @ref generate cross-references.  For \xrefX, #1 is
+% the node name, #2 the name of the Info cross-reference, #3 the printed
+% node name, #4 the name of the Info file, #5 the name of the printed
+% manual.  All but the node name can be omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+  \unsepspaces
+  \def\printedmanual{\ignorespaces #5}%
+  \def\printedrefname{\ignorespaces #3}%
+  \setbox1=\hbox{\printedmanual\unskip}%
+  \setbox0=\hbox{\printedrefname\unskip}%
+  \ifdim \wd0 = 0pt
+    % No printed node name was explicitly given.
+    \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+      % Use the node name inside the square brackets.
+      \def\printedrefname{\ignorespaces #1}%
+    \else
+      % Use the actual chapter/section title appear inside
+      % the square brackets.  Use the real section title if we have it.
+      \ifdim \wd1 > 0pt
+        % It is in another manual, so we don't have it.
+        \def\printedrefname{\ignorespaces #1}%
+      \else
+        \ifhavexrefs
+          % We know the real title if we have the xref values.
+          \def\printedrefname{\refx{#1-title}{}}%
+        \else
+          % Otherwise just copy the Info node name.
+          \def\printedrefname{\ignorespaces #1}%
+        \fi%
+      \fi
+    \fi
+  \fi
+  %
+  % Make link in pdf output.
+  \ifpdf
+    \leavevmode
+    \getfilename{#4}%
+    {\turnoffactive \otherbackslash
+     \ifnum\filenamelength>0
+       \startlink attr{/Border [0 0 0]}%
+         goto file{\the\filename.pdf} name{#1}%
+     \else
+       \startlink attr{/Border [0 0 0]}%
+         goto name{\pdfmkpgn{#1}}%
+     \fi
+    }%
+    \linkcolor
+  \fi
+  %
+  % Float references are printed completely differently: "Figure 1.2"
+  % instead of "[somenode], p.3".  We distinguish them by the
+  % LABEL-title being set to a magic string.
+  {%
+    % Have to otherify everything special to allow the \csname to
+    % include an _ in the xref name, etc.
+    \indexnofonts
+    \turnoffactive
+    \otherbackslash
+    \expandafter\global\expandafter\let\expandafter\Xthisreftitle
+      \csname XR#1-title\endcsname
+  }%
+  \iffloat\Xthisreftitle
+    % If the user specified the print name (third arg) to the ref,
+    % print it instead of our usual "Figure 1.2".
+    \ifdim\wd0 = 0pt
+      \refx{#1-snt}%
+    \else
+      \printedrefname
+    \fi
+    %
+    % if the user also gave the printed manual name (fifth arg), append
+    % "in MANUALNAME".
+    \ifdim \wd1 > 0pt
+      \space \putwordin{} \cite{\printedmanual}%
+    \fi
+  \else
+    % node/anchor (non-float) references.
+    %
+    % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+    % insert empty discretionaries after hyphens, which means that it will
+    % not find a line break at a hyphen in a node names.  Since some manuals
+    % are best written with fairly long node names, containing hyphens, this
+    % is a loss.  Therefore, we give the text of the node name again, so it
+    % is as if TeX is seeing it for the first time.
+    \ifdim \wd1 > 0pt
+      \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}%
+    \else
+      % _ (for example) has to be the character _ for the purposes of the
+      % control sequence corresponding to the node, but it has to expand
+      % into the usual \leavevmode...\vrule stuff for purposes of
+      % printing. So we \turnoffactive for the \refx-snt, back on for the
+      % printing, back off for the \refx-pg.
+      {\turnoffactive \otherbackslash
+       % Only output a following space if the -snt ref is nonempty; for
+       % @unnumbered and @anchor, it won't be.
+       \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+       \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
+      }%
+      % output the `[mynode]' via a macro so it can be overridden.
+      \xrefprintnodename\printedrefname
+      %
+      % But we always want a comma and a space:
+      ,\space
+      %
+      % output the `page 3'.
+      \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}%
+    \fi
+  \fi
+  \endlink
+\endgroup}
+
+% This macro is called from \xrefX for the `[nodename]' part of xref
+% output.  It's a separate macro only so it can be changed more easily,
+% since square brackets don't work well in some documents.  Particularly
+% one that Bob is working on :).
+%
+\def\xrefprintnodename#1{[#1]}
+
+% Things referred to by \setref.
+%
+\def\Ynothing{}
+\def\Yomitfromtoc{}
+\def\Ynumbered{%
+  \ifnum\secno=0
+    \putwordChapter@tie \the\chapno
+  \else \ifnum\subsecno=0
+    \putwordSection@tie \the\chapno.\the\secno
+  \else \ifnum\subsubsecno=0
+    \putwordSection@tie \the\chapno.\the\secno.\the\subsecno
+  \else
+    \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno
+  \fi\fi\fi
+}
+\def\Yappendix{%
+  \ifnum\secno=0
+     \putwordAppendix@tie @char\the\appendixno{}%
+  \else \ifnum\subsecno=0
+     \putwordSection@tie @char\the\appendixno.\the\secno
+  \else \ifnum\subsubsecno=0
+    \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno
+  \else
+    \putwordSection@tie
+      @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno
+  \fi\fi\fi
+}
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+%
+\def\refx#1#2{%
+  {%
+    \indexnofonts
+    \otherbackslash
+    \expandafter\global\expandafter\let\expandafter\thisrefX
+      \csname XR#1\endcsname
+  }%
+  \ifx\thisrefX\relax
+    % If not defined, say something at least.
+    \angleleft un\-de\-fined\angleright
+    \iflinks
+      \ifhavexrefs
+        \message{\linenumber Undefined cross reference `#1'.}%
+      \else
+        \ifwarnedxrefs\else
+          \global\warnedxrefstrue
+          \message{Cross reference values unknown; you must run TeX again.}%
+        \fi
+      \fi
+    \fi
+  \else
+    % It's defined, so just use it.
+    \thisrefX
+  \fi
+  #2% Output the suffix in any case.
+}
+
+% This is the macro invoked by entries in the aux file.  Usually it's
+% just a \def (we prepend XR to the control sequence name to avoid
+% collisions).  But if this is a float type, we have more work to do.
+%
+\def\xrdef#1#2{%
+  \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value.
+  %
+  % Was that xref control sequence that we just defined for a float?
+  \expandafter\iffloat\csname XR#1\endcsname
+    % it was a float, and we have the (safe) float type in \iffloattype.
+    \expandafter\let\expandafter\floatlist
+      \csname floatlist\iffloattype\endcsname
+    %
+    % Is this the first time we've seen this float type?
+    \expandafter\ifx\floatlist\relax
+      \toks0 = {\do}% yes, so just \do
+    \else
+      % had it before, so preserve previous elements in list.
+      \toks0 = \expandafter{\floatlist\do}%
+    \fi
+    %
+    % Remember this xref in the control sequence \floatlistFLOATTYPE,
+    % for later use in \listoffloats.
+    \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}%
+  \fi
+}
+
+% Read the last existing aux file, if any.  No error if none exists.
+%
+\def\tryauxfile{%
+  \openin 1 \jobname.aux
+  \ifeof 1 \else
+    \readauxfile
+    \global\havexrefstrue
+  \fi
+  \closein 1
+}
+
+\def\readauxfile{\begingroup
+  \catcode`\^^@=\other
+  \catcode`\^^A=\other
+  \catcode`\^^B=\other
+  \catcode`\^^C=\other
+  \catcode`\^^D=\other
+  \catcode`\^^E=\other
+  \catcode`\^^F=\other
+  \catcode`\^^G=\other
+  \catcode`\^^H=\other
+  \catcode`\^^K=\other
+  \catcode`\^^L=\other
+  \catcode`\^^N=\other
+  \catcode`\^^P=\other
+  \catcode`\^^Q=\other
+  \catcode`\^^R=\other
+  \catcode`\^^S=\other
+  \catcode`\^^T=\other
+  \catcode`\^^U=\other
+  \catcode`\^^V=\other
+  \catcode`\^^W=\other
+  \catcode`\^^X=\other
+  \catcode`\^^Z=\other
+  \catcode`\^^[=\other
+  \catcode`\^^\=\other
+  \catcode`\^^]=\other
+  \catcode`\^^^=\other
+  \catcode`\^^_=\other
+  % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc.
+  % in xref tags, i.e., node names.  But since ^^e4 notation isn't
+  % supported in the main text, it doesn't seem desirable.  Furthermore,
+  % that is not enough: for node names that actually contain a ^
+  % character, we would end up writing a line like this: 'xrdef {'hat
+  % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+  % argument, and \hat is not an expandable control sequence.  It could
+  % all be worked out, but why?  Either we support ^^ or we don't.
+  %
+  % The other change necessary for this was to define \auxhat:
+  % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+  % and then to call \auxhat in \setq.
+  %
+  \catcode`\^=\other
+  %
+  % Special characters.  Should be turned off anyway, but...
+  \catcode`\~=\other
+  \catcode`\[=\other
+  \catcode`\]=\other
+  \catcode`\"=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\$=\other
+  \catcode`\#=\other
+  \catcode`\&=\other
+  \catcode`\%=\other
+  \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
+  %
+  % This is to support \ in node names and titles, since the \
+  % characters end up in a \csname.  It's easier than
+  % leaving it active and making its active definition an actual \
+  % character.  What I don't understand is why it works in the *value*
+  % of the xrdef.  Seems like it should be a catcode12 \, and that
+  % should not typeset properly.  But it works, so I'm moving on for
+  % now.  --karl, 15jan04.
+  \catcode`\\=\other
+  %
+  % Make the characters 128-255 be printing characters.
+  {%
+    \count 1=128
+    \def\loop{%
+      \catcode\count 1=\other
+      \advance\count 1 by 1
+      \ifnum \count 1<256 \loop \fi
+    }%
+  }%
+  %
+  % @ is our escape character in .aux files, and we need braces.
+  \catcode`\{=1
+  \catcode`\}=2
+  \catcode`\@=0
+  %
+  \input \jobname.aux
+\endgroup}
+
+
+\message{insertions,}
+% including footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only.
+\let\footnotestyle=\comment
+
+{\catcode `\@=11
+%
+% Auto-number footnotes.  Otherwise like plain.
+\gdef\footnote{%
+  \let\indent=\ptexindent
+  \let\noindent=\ptexnoindent
+  \global\advance\footnoteno by \@ne
+  \edef\thisfootno{$^{\the\footnoteno}$}%
+  %
+  % In case the footnote comes at the end of a sentence, preserve the
+  % extra spacing after we do the footnote number.
+  \let\@sf\empty
+  \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi
+  %
+  % Remove inadvertent blank space before typesetting the footnote number.
+  \unskip
+  \thisfootno\@sf
+  \dofootnote
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter.  Our footnotes don't need to be so general.
+%
+% Oh yes, they do; otherwise, @ifset (and anything else that uses
+% \parseargline) fails inside footnotes because the tokens are fixed when
+% the footnote is read.  --karl, 16nov96.
+%
+\gdef\dofootnote{%
+  \insert\footins\bgroup
+  % We want to typeset this text as a normal paragraph, even if the
+  % footnote reference occurs in (for example) a display environment.
+  % So reset some parameters.
+  \hsize=\pagewidth
+  \interlinepenalty\interfootnotelinepenalty
+  \splittopskip\ht\strutbox % top baseline for broken footnotes
+  \splitmaxdepth\dp\strutbox
+  \floatingpenalty\@MM
+  \leftskip\z@skip
+  \rightskip\z@skip
+  \spaceskip\z@skip
+  \xspaceskip\z@skip
+  \parindent\defaultparindent
+  %
+  \smallfonts \rm
+  %
+  % Because we use hanging indentation in footnotes, a @noindent appears
+  % to exdent this text, so make it be a no-op.  makeinfo does not use
+  % hanging indentation so @noindent can still be needed within footnote
+  % text after an @example or the like (not that this is good style).
+  \let\noindent = \relax
+  %
+  % Hang the footnote text off the number.  Use \everypar in case the
+  % footnote extends for more than one paragraph.
+  \everypar = {\hang}%
+  \textindent{\thisfootno}%
+  %
+  % Don't crash into the line above the footnote text.  Since this
+  % expands into a box, it must come within the paragraph, lest it
+  % provide a place where TeX can split the footnote.
+  \footstrut
+  \futurelet\next\fo@t
+}
+}%end \catcode `\@=11
+
+% In case a @footnote appears in a vbox, save the footnote text and create
+% the real \insert just after the vbox finished.  Otherwise, the insertion
+% would be lost.
+% Similarily, if a @footnote appears inside an alignment, save the footnote
+% text to a box and make the \insert when a row of the table is finished.
+% And the same can be done for other insert classes.  --kasal, 16nov03.
+
+% Replace the \insert primitive by a cheating macro.
+% Deeper inside, just make sure that the saved insertions are not spilled
+% out prematurely.
+%
+\def\startsavinginserts{%
+  \ifx \insert\ptexinsert
+    \let\insert\saveinsert
+  \else
+    \let\checkinserts\relax
+  \fi
+}
+
+% This \insert replacement works for both \insert\footins{foo} and
+% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}.
+%
+\def\saveinsert#1{%
+  \edef\next{\noexpand\savetobox \makeSAVEname#1}%
+  \afterassignment\next
+  % swallow the left brace
+  \let\temp =
+}
+\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}}
+\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1}
+
+\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi}
+
+\def\placesaveins#1{%
+  \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname
+    {\box#1}%
+}
+
+% eat @SAVE -- beware, all of them have catcode \other:
+{
+  \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials  %  ;-)
+  \gdef\gobblesave @SAVE{}
+}
+
+% initialization:
+\def\newsaveins #1{%
+  \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}%
+  \next
+}
+\def\newsaveinsX #1{%
+  \csname newbox\endcsname #1%
+  \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts
+    \checksaveins #1}%
+}
+
+% initialize:
+\let\checkinserts\empty
+\newsaveins\footins
+\newsaveins\margin
+
+
+% @image.  We use the macros from epsf.tex to support this.
+% If epsf.tex is not installed and @image is used, we complain.
+%
+% Check for and read epsf.tex up front.  If we read it only at @image
+% time, we might be inside a group, and then its definitions would get
+% undone and the next image would fail.
+\openin 1 = epsf.tex
+\ifeof 1 \else
+  % Do not bother showing banner with epsf.tex v2.7k (available in
+  % doc/epsf.tex and on ctan).
+  \def\epsfannounce{\toks0 = }%
+  \input epsf.tex
+\fi
+\closein 1
+%
+% We will only complain once about lack of epsf.tex.
+\newif\ifwarnednoepsf
+\newhelp\noepsfhelp{epsf.tex must be installed for images to
+  work.  It is also included in the Texinfo distribution, or you can get
+  it from ftp://tug.org/tex/epsf.tex.}
+%
+\def\image#1{%
+  \ifx\epsfbox\undefined
+    \ifwarnednoepsf \else
+      \errhelp = \noepsfhelp
+      \errmessage{epsf.tex not found, images will be ignored}%
+      \global\warnednoepsftrue
+    \fi
+  \else
+    \imagexxx #1,,,,,\finish
+  \fi
+}
+%
+% Arguments to @image:
+% #1 is (mandatory) image filename; we tack on .eps extension.
+% #2 is (optional) width, #3 is (optional) height.
+% #4 is (ignored optional) html alt text.
+% #5 is (ignored optional) extension.
+% #6 is just the usual extra ignored arg for parsing this stuff.
+\newif\ifimagevmode
+\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
+  \catcode`\^^M = 5     % in case we're inside an example
+  \normalturnoffactive  % allow _ et al. in names
+  % If the image is by itself, center it.
+  \ifvmode
+    \imagevmodetrue
+    \nobreak\bigskip
+    % Usually we'll have text after the image which will insert
+    % \parskip glue, so insert it here too to equalize the space
+    % above and below.
+    \nobreak\vskip\parskip
+    \nobreak
+    \line\bgroup\hss
+  \fi
+  %
+  % Output the image.
+  \ifpdf
+    \dopdfimage{#1}{#2}{#3}%
+  \else
+    % \epsfbox itself resets \epsf?size at each figure.
+    \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
+    \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
+    \epsfbox{#1.eps}%
+  \fi
+  %
+  \ifimagevmode \hss \egroup \bigbreak \fi  % space after the image
+\endgroup}
+
+
+% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables,
+% etc.  We don't actually implement floating yet, we always include the
+% float "here".  But it seemed the best name for the future.
+%
+\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish}
+
+% There may be a space before second and/or third parameter; delete it.
+\def\eatcommaspace#1, {#1,}
+
+% #1 is the optional FLOATTYPE, the text label for this float, typically
+% "Figure", "Table", "Example", etc.  Can't contain commas.  If omitted,
+% this float will not be numbered and cannot be referred to.
+%
+% #2 is the optional xref label.  Also must be present for the float to
+% be referable.
+%
+% #3 is the optional positioning argument; for now, it is ignored.  It
+% will somehow specify the positions allowed to float to (here, top, bottom).
+%
+% We keep a separate counter for each FLOATTYPE, which we reset at each
+% chapter-level command.
+\let\resetallfloatnos=\empty
+%
+\def\dofloat#1,#2,#3,#4\finish{%
+  \let\thiscaption=\empty
+  \let\thisshortcaption=\empty
+  %
+  % don't lose footnotes inside @float.
+  %
+  % BEWARE: when the floats start float, we have to issue warning whenever an
+  % insert appears inside a float which could possibly float. --kasal, 26may04
+  %
+  \startsavinginserts
+  %
+  % We can't be used inside a paragraph.
+  \par
+  %
+  \vtop\bgroup
+    \def\floattype{#1}%
+    \def\floatlabel{#2}%
+    \def\floatloc{#3}% we do nothing with this yet.
+    %
+    \ifx\floattype\empty
+      \let\safefloattype=\empty
+    \else
+      {%
+        % the floattype might have accents or other special characters,
+        % but we need to use it in a control sequence name.
+        \indexnofonts
+        \turnoffactive
+        \xdef\safefloattype{\floattype}%
+      }%
+    \fi
+    %
+    % If label is given but no type, we handle that as the empty type.
+    \ifx\floatlabel\empty \else
+      % We want each FLOATTYPE to be numbered separately (Figure 1,
+      % Table 1, Figure 2, ...).  (And if no label, no number.)
+      %
+      \expandafter\getfloatno\csname\safefloattype floatno\endcsname
+      \global\advance\floatno by 1
+      %
+      {%
+        % This magic value for \thissection is output by \setref as the
+        % XREFLABEL-title value.  \xrefX uses it to distinguish float
+        % labels (which have a completely different output format) from
+        % node and anchor labels.  And \xrdef uses it to construct the
+        % lists of floats.
+        %
+        \edef\thissection{\floatmagic=\safefloattype}%
+        \setref{\floatlabel}{Yfloat}%
+      }%
+    \fi
+    %
+    % start with \parskip glue, I guess.
+    \vskip\parskip
+    %
+    % Don't suppress indentation if a float happens to start a section.
+    \restorefirstparagraphindent
+}
+
+% we have these possibilities:
+% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap
+% @float Foo,lbl & no caption:    Foo 1.1
+% @float Foo & @caption{Cap}:     Foo: Cap
+% @float Foo & no caption:        Foo
+% @float ,lbl & Caption{Cap}:     1.1: Cap
+% @float ,lbl & no caption:       1.1
+% @float & @caption{Cap}:         Cap
+% @float & no caption:
+%
+\def\Efloat{%
+    \let\floatident = \empty
+    %
+    % In all cases, if we have a float type, it comes first.
+    \ifx\floattype\empty \else \def\floatident{\floattype}\fi
+    %
+    % If we have an xref label, the number comes next.
+    \ifx\floatlabel\empty \else
+      \ifx\floattype\empty \else % if also had float type, need tie first.
+        \appendtomacro\floatident{\tie}%
+      \fi
+      % the number.
+      \appendtomacro\floatident{\chaplevelprefix\the\floatno}%
+    \fi
+    %
+    % Start the printed caption with what we've constructed in
+    % \floatident, but keep it separate; we need \floatident again.
+    \let\captionline = \floatident
+    %
+    \ifx\thiscaption\empty \else
+      \ifx\floatident\empty \else
+	\appendtomacro\captionline{: }% had ident, so need a colon between
+      \fi
+      %
+      % caption text.
+      \appendtomacro\captionline{\scanexp\thiscaption}%
+    \fi
+    %
+    % If we have anything to print, print it, with space before.
+    % Eventually this needs to become an \insert.
+    \ifx\captionline\empty \else
+      \vskip.5\parskip
+      \captionline
+    \fi
+    %
+    % If have an xref label, write the list of floats info.  Do this
+    % after the caption, to avoid chance of it being a breakpoint.
+    \ifx\floatlabel\empty \else
+      % Write the text that goes in the lof to the aux file as
+      % \floatlabel-lof.  Besides \floatident, we include the short
+      % caption if specified, else the full caption if specified, else nothing.
+      {%
+        \atdummies \turnoffactive \otherbackslash
+        \immediate\write\auxfile{@xrdef{\floatlabel-lof}{%
+          \floatident
+          \ifx\thisshortcaption\empty
+            \ifx\thiscaption\empty \else : \thiscaption \fi
+          \else
+            : \thisshortcaption
+          \fi
+        }}%
+      }%
+    \fi
+    %
+    % Space below caption, if we printed anything.
+    \ifx\printedsomething\empty \else \vskip\parskip \fi
+  \egroup  % end of \vtop
+  %
+  % place the captured inserts
+  %
+  % BEWARE: when the floats start float, we have to issue warning whenever an
+  % insert appears inside a float which could possibly float. --kasal, 26may04
+  %
+  \checkinserts
+}
+
+% Append the tokens #2 to the definition of macro #1, not expanding either.
+%
+\def\appendtomacro#1#2{%
+  \expandafter\def\expandafter#1\expandafter{#1#2}%
+}
+
+% @caption, @shortcaption
+%
+\def\caption{\docaption\thiscaption}
+\def\shortcaption{\docaption\thisshortcaption}
+\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption}
+\def\defcaption#1#2{\egroup \def#1{#2}}
+
+% The parameter is the control sequence identifying the counter we are
+% going to use.  Create it if it doesn't exist and assign it to \floatno.
+\def\getfloatno#1{%
+  \ifx#1\relax
+      % Haven't seen this figure type before.
+      \csname newcount\endcsname #1%
+      %
+      % Remember to reset this floatno at the next chap.
+      \expandafter\gdef\expandafter\resetallfloatnos
+        \expandafter{\resetallfloatnos #1=0 }%
+  \fi
+  \let\floatno#1%
+}
+
+% \setref calls this to get the XREFLABEL-snt value.  We want an @xref
+% to the FLOATLABEL to expand to "Figure 3.1".  We call \setref when we
+% first read the @float command.
+%
+\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}%
+
+% Magic string used for the XREFLABEL-title value, so \xrefX can
+% distinguish floats from other xref types.
+\def\floatmagic{!!float!!}
+
+% #1 is the control sequence we are passed; we expand into a conditional
+% which is true if #1 represents a float ref.  That is, the magic
+% \thissection value which we \setref above.
+%
+\def\iffloat#1{\expandafter\doiffloat#1==\finish}
+%
+% #1 is (maybe) the \floatmagic string.  If so, #2 will be the
+% (safe) float type for this float.  We set \iffloattype to #2.
+%
+\def\doiffloat#1=#2=#3\finish{%
+  \def\temp{#1}%
+  \def\iffloattype{#2}%
+  \ifx\temp\floatmagic
+}
+
+% @listoffloats FLOATTYPE - print a list of floats like a table of contents.
+%
+\parseargdef\listoffloats{%
+  \def\floattype{#1}% floattype
+  {%
+    % the floattype might have accents or other special characters,
+    % but we need to use it in a control sequence name.
+    \indexnofonts
+    \turnoffactive
+    \xdef\safefloattype{\floattype}%
+  }%
+  %
+  % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE.
+  \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax
+    \ifhavexrefs
+      % if the user said @listoffloats foo but never @float foo.
+      \message{\linenumber No `\safefloattype' floats to list.}%
+    \fi
+  \else
+    \begingroup
+      \leftskip=\tocindent  % indent these entries like a toc
+      \let\do=\listoffloatsdo
+      \csname floatlist\safefloattype\endcsname
+    \endgroup
+  \fi
+}
+
+% This is called on each entry in a list of floats.  We're passed the
+% xref label, in the form LABEL-title, which is how we save it in the
+% aux file.  We strip off the -title and look up \XRLABEL-lof, which
+% has the text we're supposed to typeset here.
+%
+% Figures without xref labels will not be included in the list (since
+% they won't appear in the aux file).
+%
+\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish}
+\def\listoffloatsdoentry#1-title\finish{{%
+  % Can't fully expand XR#1-lof because it can contain anything.  Just
+  % pass the control sequence.  On the other hand, XR#1-pg is just the
+  % page number, and we want to fully expand that so we can get a link
+  % in pdf output.
+  \toksA = \expandafter{\csname XR#1-lof\endcsname}%
+  %
+  % use the same \entry macro we use to generate the TOC and index.
+  \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}%
+  \writeentry
+}}
+
+\message{localization,}
+% and i18n.
+
+% @documentlanguage is usually given very early, just after
+% @setfilename.  If done too late, it may not override everything
+% properly.  Single argument is the language abbreviation.
+% It would be nice if we could set up a hyphenation file here.
+%
+\parseargdef\documentlanguage{%
+  \tex % read txi-??.tex file in plain TeX.
+    % Read the file if it exists.
+    \openin 1 txi-#1.tex
+    \ifeof 1
+      \errhelp = \nolanghelp
+      \errmessage{Cannot read language file txi-#1.tex}%
+    \else
+      \input txi-#1.tex
+    \fi
+    \closein 1
+  \endgroup
+}
+\newhelp\nolanghelp{The given language definition file cannot be found or
+is empty.  Maybe you need to install it?  In the current directory
+should work if nowhere else does.}
+
+
+% @documentencoding should change something in TeX eventually, most
+% likely, but for now just recognize it.
+\let\documentencoding = \comment
+
+
+% Page size parameters.
+%
+\newdimen\defaultparindent \defaultparindent = 15pt
+
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
+% Prevent underfull vbox error messages.
+\vbadness = 10000
+
+% Don't be so finicky about underfull hboxes, either.
+\hbadness = 2000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything.  We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize.  We call this whenever the paper size is set.
+%
+\def\setemergencystretch{%
+  \ifx\emergencystretch\thisisundefined
+    % Allow us to assign to \emergencystretch anyway.
+    \def\emergencystretch{\dimen0}%
+  \else
+    \emergencystretch = .15\hsize
+  \fi
+}
+
+% Parameters in order: 1) textheight; 2) textwidth; 3) voffset;
+% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8)
+% physical page width.
+%
+% We also call \setleading{\textleading}, so the caller should define
+% \textleading.  The caller should also set \parskip.
+%
+\def\internalpagesizes#1#2#3#4#5#6#7#8{%
+  \voffset = #3\relax
+  \topskip = #6\relax
+  \splittopskip = \topskip
+  %
+  \vsize = #1\relax
+  \advance\vsize by \topskip
+  \outervsize = \vsize
+  \advance\outervsize by 2\topandbottommargin
+  \pageheight = \vsize
+  %
+  \hsize = #2\relax
+  \outerhsize = \hsize
+  \advance\outerhsize by 0.5in
+  \pagewidth = \hsize
+  %
+  \normaloffset = #4\relax
+  \bindingoffset = #5\relax
+  %
+  \ifpdf
+    \pdfpageheight #7\relax
+    \pdfpagewidth #8\relax
+  \fi
+  %
+  \setleading{\textleading}
+  %
+  \parindent = \defaultparindent
+  \setemergencystretch
+}
+
+% @letterpaper (the default).
+\def\letterpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
+  %
+  % If page is nothing but text, make it come out even.
+  \internalpagesizes{46\baselineskip}{6in}%
+                    {\voffset}{.25in}%
+                    {\bindingoffset}{36pt}%
+                    {11in}{8.5in}%
+}}
+
+% Use @smallbook to reset parameters for 7x9.5 (or so) format.
+\def\smallbook{{\globaldefs = 1
+  \parskip = 2pt plus 1pt
+  \textleading = 12pt
+  %
+  \internalpagesizes{7.5in}{5in}%
+                    {\voffset}{.25in}%
+                    {\bindingoffset}{16pt}%
+                    {9.25in}{7in}%
+  %
+  \lispnarrowing = 0.3in
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = .5cm
+}}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
+  %
+  % Double-side printing via postscript on Laserjet 4050
+  % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm.
+  % To change the settings for a different printer or situation, adjust
+  % \normaloffset until the front-side and back-side texts align.  Then
+  % do the same for \bindingoffset.  You can set these for testing in
+  % your texinfo source file like this:
+  % @tex
+  % \global\normaloffset = -6mm
+  % \global\bindingoffset = 10mm
+  % @end tex
+  \internalpagesizes{51\baselineskip}{160mm}
+                    {\voffset}{\hoffset}%
+                    {\bindingoffset}{44pt}%
+                    {297mm}{210mm}%
+  %
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = 5mm
+}}
+
+% Use @afivepaper to print on European A5 paper.
+% From romildo@urano.iceb.ufop.br, 2 July 2000.
+% He also recommends making @example and @lisp be small.
+\def\afivepaper{{\globaldefs = 1
+  \parskip = 2pt plus 1pt minus 0.1pt
+  \textleading = 12.5pt
+  %
+  \internalpagesizes{160mm}{120mm}%
+                    {\voffset}{\hoffset}%
+                    {\bindingoffset}{8pt}%
+                    {210mm}{148mm}%
+  %
+  \lispnarrowing = 0.2in
+  \tolerance = 800
+  \hfuzz = 1.2pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = 2mm
+  \tableindent = 12mm
+}}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper.
+\def\afourlatex{{\globaldefs = 1
+  \afourpaper
+  \internalpagesizes{237mm}{150mm}%
+                    {\voffset}{4.6mm}%
+                    {\bindingoffset}{7mm}%
+                    {297mm}{210mm}%
+  %
+  % Must explicitly reset to 0 because we call \afourpaper.
+  \globaldefs = 0
+}}
+
+% Use @afourwide to print on A4 paper in landscape format.
+\def\afourwide{{\globaldefs = 1
+  \afourpaper
+  \internalpagesizes{241mm}{165mm}%
+                    {\voffset}{-2.95mm}%
+                    {\bindingoffset}{7mm}%
+                    {297mm}{210mm}%
+  \globaldefs = 0
+}}
+
+% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
+% Perhaps we should allow setting the margins, \topskip, \parskip,
+% and/or leading, also. Or perhaps we should compute them somehow.
+%
+\parseargdef\pagesizes{\pagesizesyyy #1,,\finish}
+\def\pagesizesyyy#1,#2,#3\finish{{%
+  \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
+  \globaldefs = 1
+  %
+  \parskip = 3pt plus 2pt minus 1pt
+  \setleading{\textleading}%
+  %
+  \dimen0 = #1
+  \advance\dimen0 by \voffset
+  %
+  \dimen2 = \hsize
+  \advance\dimen2 by \normaloffset
+  %
+  \internalpagesizes{#1}{\hsize}%
+                    {\voffset}{\normaloffset}%
+                    {\bindingoffset}{44pt}%
+                    {\dimen0}{\dimen2}%
+}}
+
+% Set default to letter.
+%
+\letterpaper
+
+
+\message{and turning on texinfo input format.}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\catcode`\$=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+\def\normaldollar{$}%$ font-lock fix
+
+% This macro is used to make a character print one way in \tt
+% (where it can probably be output as-is), and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise.  Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi}
+
+% Same as above, but check for italic font.  Actually this also catches
+% non-italic slanted fonts since it is impossible to distinguish them from
+% italic fonts.  But since this is only used by $ and it uses \sl anyway
+% this is not a problem.
+\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt\char34}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt\char126}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
+
+\catcode`\|=\active
+\def|{{\tt\char124}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+\catcode`\$=\active
+\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+\catcode`\@=0
+
+% \backslashcurfont outputs one backslash character in current font,
+% as in \char`\\.
+\global\chardef\backslashcurfont=`\\
+\global\let\rawbackslashxx=\backslashcurfont  % let existing .??s files work
+
+% \rawbackslash defines an active \ to do \backslashcurfont.
+% \otherbackslash defines an active \ to be a literal `\' character with
+% catcode other.
+{\catcode`\\=\active
+ @gdef@rawbackslash{@let\=@backslashcurfont}
+ @gdef@otherbackslash{@let\=@realbackslash}
+}
+
+% \realbackslash is an actual character `\' with catcode other.
+{\catcode`\\=\other @gdef@realbackslash{\}}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\backslashcurfont}}
+
+\catcode`\\=\active
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+@def@turnoffactive{%
+  @let"=@normaldoublequote
+  @let\=@realbackslash
+  @let~=@normaltilde
+  @let^=@normalcaret
+  @let_=@normalunderscore
+  @let|=@normalverticalbar
+  @let<=@normalless
+  @let>=@normalgreater
+  @let+=@normalplus
+  @let$=@normaldollar %$ font-lock fix
+  @unsepspaces
+}
+
+% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of
+% the literal character `\'.  (Thus, \ is not expandable when this is in
+% effect.)
+%
+@def@normalturnoffactive{@turnoffactive @let\=@normalbackslash}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also back turn on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{%
+  @ifx\@eatinput @let\ = @normalbackslash @fi
+  @catcode`+=@active
+  @catcode`@_=@active
+}
+
+% Say @foo, not \foo, in error messages.
+@escapechar = `@@
+
+% These look ok in all fonts, so just make them not special.
+@catcode`@& = @other
+@catcode`@# = @other
+@catcode`@% = @other
+
+
+@c Local variables:
+@c eval: (add-hook 'write-file-hooks 'time-stamp)
+@c page-delimiter: "^\\\\message"
+@c time-stamp-start: "def\\\\texinfoversion{"
+@c time-stamp-format: "%:y-%02m-%02d.%02H"
+@c time-stamp-end: "}"
+@c End:
+
+@c vim:sw=2:
+
+@ignore
+   arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115
+@end ignore
Index: /tags/kBuild-0.1.4/src/sed/config_h.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/config_h.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/config_h.in	(revision 1780)
@@ -0,0 +1,373 @@
+/* config_h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#undef ENABLE_NLS
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define to 1 if you have the `bcopy' function. */
+#undef HAVE_BCOPY
+
+/* Define to 1 if you have the `btowc' function. */
+#undef HAVE_BTOWC
+
+/* Define to 1 if you have the `bzero' function. */
+#undef HAVE_BZERO
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#undef HAVE_DCGETTEXT
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the `fchmod' function. */
+#undef HAVE_FCHMOD
+
+/* Define to 1 if you have the `fchown' function. */
+#undef HAVE_FCHOWN
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+#undef HAVE_FEOF_UNLOCKED
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+#undef HAVE_FGETS_UNLOCKED
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+#undef HAVE_GETC_UNLOCKED
+
+/* Define to 1 if you have the `getegid' function. */
+#undef HAVE_GETEGID
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the `getgid' function. */
+#undef HAVE_GETGID
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#undef HAVE_GETTEXT
+
+/* Define to 1 if you have the `getuid' function. */
+#undef HAVE_GETUID
+
+/* Define if you have the iconv() function. */
+#undef HAVE_ICONV
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define to 1 if you have the `isascii' function. */
+#undef HAVE_ISASCII
+
+/* Define to 1 if you have the `isatty' function. */
+#undef HAVE_ISATTY
+
+/* Define to 1 if you have the `isblank' function. */
+#undef HAVE_ISBLANK
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#undef HAVE_LANGINFO_CODESET
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define to 1 if you have the `regex' library (-lregex). */
+#undef HAVE_LIBREGEX
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#undef HAVE_LONG_FILE_NAMES
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#undef HAVE_MBRTOWC
+
+/* Define to 1 if <wchar.h> declares mbstate_t. */
+#undef HAVE_MBSTATE_T
+
+/* Define to 1 if you have the <mcheck.h> header file. */
+#undef HAVE_MCHECK_H
+
+/* Define to 1 if you have the `memchr' function. */
+#undef HAVE_MEMCHR
+
+/* Define to 1 if you have the `memcmp' function. */
+#undef HAVE_MEMCMP
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mempcpy' function. */
+#undef HAVE_MEMPCPY
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkstemp' function. */
+#undef HAVE_MKSTEMP
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#undef HAVE_NL_TYPES_H
+
+/* Define to 1 if libc includes obstacks. */
+#undef HAVE_OBSTACK
+
+/* Define to 1 if you have the `pathconf' function. */
+#undef HAVE_PATHCONF
+
+/* Define to 1 if you have the `popen' function. */
+#undef HAVE_POPEN
+
+/* Define to 1 if you have the `putenv' function. */
+#undef HAVE_PUTENV
+
+/* Define to 1 if you have the <regex.h> header file. */
+#undef HAVE_REGEX_H
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_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 `stpcpy' function. */
+#undef HAVE_STPCPY
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* 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 `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if you have the `strverscmp' function. */
+#undef HAVE_STRVERSCMP
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_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 `tsearch' function. */
+#undef HAVE_TSEARCH
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#undef HAVE_WCHAR_H
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#undef HAVE_WCRTOMB
+
+/* Define to 1 if you have the `wcscoll' function. */
+#undef HAVE_WCSCOLL
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#undef HAVE_WCTYPE_H
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to 1 if you have the `__argz_count' function. */
+#undef HAVE___ARGZ_COUNT
+
+/* Define to 1 if you have the `__argz_next' function. */
+#undef HAVE___ARGZ_NEXT
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+#undef HAVE___ARGZ_STRINGIFY
+
+/* Define as const if the declaration of iconv() needs const. */
+#undef ICONV_CONST
+
+/* Name of package */
+#undef PACKAGE
+
+/* 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
+
+/* Define to the version of GNU sed whose features are supported by this sed.
+   */
+#undef SED_FEATURE_VERSION
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Include BSD functions in regex, used by the testsuite */
+#undef _REGEX_RE_COMP
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to a type if <wchar.h> does not define. */
+#undef mbstate_t
+
+/* Define to `long' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
Index: /tags/kBuild-0.1.4/src/sed/configure
===================================================================
--- /tags/kBuild-0.1.4/src/sed/configure	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/configure	(revision 1780)
@@ -0,0 +1,11310 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59 for sed 4.1.5.
+#
+# Report bugs to <bonzini@gnu.org>.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$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" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.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
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     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
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval 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="eval 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
+
+
+# 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
+ac_config_libobj_dir=.
+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='sed'
+PACKAGE_TARNAME='sed'
+PACKAGE_VERSION='4.1.5'
+PACKAGE_STRING='sed 4.1.5'
+PACKAGE_BUGREPORT='bonzini@gnu.org'
+
+ac_unique_file="sed/sed.c"
+# 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"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar SED_FEATURE_VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE RANLIB ac_ct_RANLIB CPP EGREP HAVE__BOOL ALLOCA LIBOBJS TEST_REGEX_TRUE TEST_REGEX_FALSE BUILD_HTML_TRUE BUILD_HTML_FALSE TEXI2HTML MAKEINFO_HTML_TRUE MAKEINFO_HTML_FALSE TEXI2HTML_HTML_TRUE TEXI2HTML_HTML_FALSE MKINSTALLDIRS MSGFMT GMSGFMT XGETTEXT MSGMERGE build build_cpu build_vendor build_os host host_cpu host_vendor host_os GLIBC21 LIBICONV LTLIBICONV INTLBISON USE_NLS BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT INTLOBJS DATADIRNAME INSTOBJEXT GENCAT INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB LTLIBOBJS'
+ac_subst_files=''
+
+# 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
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+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 sed 4.1.5 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
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+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 sed 4.1.5:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --disable-largefile     omit support for large files
+  --disable-i18n          disable internationalization (default=yes)
+  --enable-regex-tests    enable regex matcher regression tests (default=yes)
+  --enable-html           build HTML manual (default=no)
+  --disable-nls           do not use Native Language Support
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-included-regex   use included regex matcher (default=yes)
+  --with-gnu-ld           assume the C compiler uses GNU ld default=no
+  --with-libiconv-prefix=DIR  search for libiconv in DIR/include and DIR/lib
+  --without-libiconv-prefix     don't search for libiconv in includedir and libdir
+  --with-included-gettext use the GNU gettext library included here
+  --with-libintl-prefix=DIR  search for libintl in DIR/include and DIR/lib
+  --without-libintl-prefix     don't search for libintl in includedir and libdir
+
+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 <bonzini@gnu.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
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    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
+sed configure 4.1.5
+generated by GNU Autoconf 2.59
+
+Copyright (C) 2003 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 sed $as_me 4.1.5, which was
+generated by GNU Autoconf 2.59.  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.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# 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
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+	echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f 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_aux_dir=
+for ac_dir in config $srcdir/config; 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 config $srcdir/config" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in config $srcdir/config" >&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.
+
+
+          ac_config_headers="$ac_config_headers config.h:config_h.in"
+
+
+am__api_version="1.9"
+# 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"
+# OS/2's system install, which has a completely different semantic
+# ./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/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /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 build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+  # We used to keeping the `.' as first argument, in order to
+  # allow $(mkdir_p) to be used without argument.  As in
+  #   $(mkdir_p) $(somedir)
+  # where $(somedir) is conditionally defined.  However this is wrong
+  # for two reasons:
+  #  1. if the package is installed by a user who cannot write `.'
+  #     make install will fail,
+  #  2. the above comment should most certainly read
+  #     $(mkdir_p) $(DESTDIR)$(somedir)
+  #     so it does not work when $(somedir) is undefined and
+  #     $(DESTDIR) is not.
+  #  To support the latter case, we have to write
+  #     test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+  #  so the `.' trick is pointless.
+  mkdir_p='mkdir -p --'
+else
+  # On NextStep and OpenStep, the `mkdir' command does not
+  # recognize any option.  It will interpret all options as
+  # directories to create, and then abort because `.' already
+  # exists.
+  for d in ./-p ./--version;
+  do
+    test -d $d && rmdir $d
+  done
+  # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+  if test -f "$ac_aux_dir/mkinstalldirs"; then
+    mkdir_p='$(mkinstalldirs)'
+  else
+    mkdir_p='$(install_sh) -d'
+  fi
+fi
+
+for ac_prog in gawk mawk nawk awk
+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_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # 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_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$AWK" && break
+done
+
+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
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='sed'
+ VERSION='4.1.5'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  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
+
+  test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+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
+
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+SED_FEATURE_VERSION=4.1
+
+cat >>confdefs.h <<_ACEOF
+#define SED_FEATURE_VERSION "$SED_FEATURE_VERSION"
+_ACEOF
+
+
+
+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
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  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
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# 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 file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $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=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+	;;
+    conftest.$ac_ext )
+	# This is the source file.
+	;;
+    [ab].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,
+	# but it would be cool to find out if it's true.  Does anybody
+	# maintain Libtool? --akim.
+	export ac_cv_exeext
+	break;;
+    * )
+	break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&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'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&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 b.out
+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 conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) 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
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+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 | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err 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
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX 10.20 and later	-Ae
+# HP-UX older versions	-Aa -D_HPUX_SOURCE
+# SVR4			-Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# 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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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 \
+   '' \
+   '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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err 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
+DEPDIR="${am__leading_dot}deps"
+
+          ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+
+
+echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval="$enable_dependency_tracking"
+
+fi;
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+
+
+if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+
+depcc="$CC"   am_compiler_list=
+
+echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+
+
+if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; 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_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # 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_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; 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_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # 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_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _GNU_SOURCE 1
+_ACEOF
+
+
+
+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.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     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=$?
+  grep -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
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_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
+sed 's/^/| /' 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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=$?
+  grep -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
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_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
+sed 's/^/| /' 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.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     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=$?
+  grep -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
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_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
+sed 's/^/| /' 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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=$?
+  grep -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
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_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
+sed 's/^/| /' 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
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&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 egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+
+echo "$as_me:$LINENO: checking for AIX" >&5
+echo $ECHO_N "checking for AIX... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef _AIX
+  yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+cat >>confdefs.h <<\_ACEOF
+#define _ALL_SOURCE 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out 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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err 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
+
+
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for minix/config.h" >&5
+echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking minix/config.h usability" >&5
+echo $ECHO_N "checking minix/config.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <minix/config.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking minix/config.h presence" >&5
+echo $ECHO_N "checking minix/config.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <minix/config.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=$?
+  grep -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
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: minix/config.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: minix/config.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: minix/config.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: minix/config.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: minix/config.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: minix/config.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: minix/config.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to bonzini@gnu.org ##
+## ------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for minix/config.h" >&5
+echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_minix_config_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+
+fi
+if test $ac_cv_header_minix_config_h = yes; then
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+if test "$MINIX" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define _POSIX_SOURCE 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _POSIX_1_SOURCE 2
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _MINIX 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for library containing strerror" >&5
+echo $ECHO_N "checking for library containing strerror... $ECHO_C" >&6
+if test "${ac_cv_search_strerror+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_strerror=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+int
+main ()
+{
+strerror ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_search_strerror="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_strerror" = no; then
+  for ac_lib in cposix; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+int
+main ()
+{
+strerror ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_search_strerror="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_strerror" >&5
+echo "${ECHO_T}$ac_cv_search_strerror" >&6
+if test "$ac_cv_search_strerror" != no; then
+  test "$ac_cv_search_strerror" = "none required" || LIBS="$ac_cv_search_strerror $LIBS"
+
+fi
+
+# Check whether --enable-largefile or --disable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+  enableval="$enable_largefile"
+
+fi;
+if test "$enable_largefile" != no; then
+
+  echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+     	 # IRIX 6.2 and later do not support large files by default,
+     	 # so use the C compiler's -n32 option if that helps.
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+     	 rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+     	 CC="$CC -n32"
+     	 rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_sys_largefile_CC=' -n32'; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+	 break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  ac_cv_sys_file_offset_bits=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_sys_file_offset_bits=64; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  break
+done
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6
+if test "$ac_cv_sys_file_offset_bits" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+
+fi
+rm -f conftest*
+  echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_large_files+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  ac_cv_sys_large_files=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_sys_large_files=1; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  break
+done
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6
+if test "$ac_cv_sys_large_files" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+
+fi
+rm -f conftest*
+fi
+
+echo "$as_me:$LINENO: checking for long file names" >&5
+echo $ECHO_N "checking for long file names... $ECHO_C" >&6
+if test "${ac_cv_sys_long_file_names+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_sys_long_file_names=yes
+# Test for long file names in all the places we know might matter:
+#      .		the current directory, where building will happen
+#      $prefix/lib	where we will be installing things
+#      $exec_prefix/lib	likewise
+# eval it to expand exec_prefix.
+#      $TMPDIR		if set, where it might want to write temporary files
+# if $TMPDIR is not set:
+#      /tmp		where it might want to write temporary files
+#      /var/tmp		likewise
+#      /usr/tmp		likewise
+if test -n "$TMPDIR" && test -d "$TMPDIR" && test -w "$TMPDIR"; then
+  ac_tmpdirs=$TMPDIR
+else
+  ac_tmpdirs='/tmp /var/tmp /usr/tmp'
+fi
+for ac_dir in  . $ac_tmpdirs `eval echo $prefix/lib $exec_prefix/lib` ; do
+  test -d $ac_dir || continue
+  test -w $ac_dir || continue # It is less confusing to not echo anything here.
+  ac_xdir=$ac_dir/cf$$
+  (umask 077 && mkdir $ac_xdir 2>/dev/null) || continue
+  ac_tf1=$ac_xdir/conftest9012345
+  ac_tf2=$ac_xdir/conftest9012346
+  (echo 1 >$ac_tf1) 2>/dev/null
+  (echo 2 >$ac_tf2) 2>/dev/null
+  ac_val=`cat $ac_tf1 2>/dev/null`
+  if test ! -f $ac_tf1 || test "$ac_val" != 1; then
+    ac_cv_sys_long_file_names=no
+    rm -rf $ac_xdir 2>/dev/null
+    break
+  fi
+  rm -rf $ac_xdir 2>/dev/null
+done
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_long_file_names" >&5
+echo "${ECHO_T}$ac_cv_sys_long_file_names" >&6
+if test $ac_cv_sys_long_file_names = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LONG_FILE_NAMES 1
+_ACEOF
+
+fi
+
+
+echo "$as_me:$LINENO: checking whether -lcP is needed" >&5
+echo $ECHO_N "checking whether -lcP is needed... $ECHO_C" >&6
+if test "${sed_cv_libcp_needed+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+if test "$cross_compiling" = yes; then
+  sed_cv_libcp_needed="assuming no"
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <errno.h>
+
+int main()
+{
+  FILE *fp;
+  int result;
+  errno = 0;
+  fp = fopen ("conftest.c", "r");
+  if (!fp) return 0;	   /* error, assume not needed */
+  result = fflush (fp) == EOF && errno == 0;
+  fclose (fp);
+  return result;
+}
+_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
+  sed_cv_libcp_needed=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+sed_cv_libcp_needed=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $sed_cv_libcp_needed" >&5
+echo "${ECHO_T}$sed_cv_libcp_needed" >&6
+if test "$sed_cv_libcp_needed" = yes; then
+  LIBS="-lcP $LIBS"
+fi
+
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err 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_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in dir; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+else
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in x; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in io.h limits.h locale.h stdarg.h alloca.h stddef.h errno.h \
+		 wchar.h wctype.h sys/file.h mcheck.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
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err 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 an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset x;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *ccp;
+  char **p;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  ccp = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++ccp;
+  p = (char**) ccp;
+  ccp = (char const *const *) p;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+  }
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+  return 0;
+if (sizeof (size_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for ssize_t" >&5
+echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6
+if test "${ac_cv_type_ssize_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((ssize_t *) 0)
+  return 0;
+if (sizeof (ssize_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_ssize_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_ssize_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5
+echo "${ECHO_T}$ac_cv_type_ssize_t" >&6
+if test $ac_cv_type_ssize_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+
+echo "$as_me:$LINENO: checking for stdbool.h that conforms to C99" >&5
+echo $ECHO_N "checking for stdbool.h that conforms to C99... $ECHO_C" >&6
+if test "${ac_cv_header_stdbool_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+	  #include <stdbool.h>
+	  #ifndef bool
+	   "error: bool is not defined"
+	  #endif
+	  #ifndef false
+	   "error: false is not defined"
+	  #endif
+	  #if false
+	   "error: false is not 0"
+	  #endif
+	  #ifndef true
+	   "error: false is not defined"
+	  #endif
+	  #if true != 1
+	   "error: true is not 1"
+	  #endif
+	  #ifndef __bool_true_false_are_defined
+	   "error: __bool_true_false_are_defined is not defined"
+	  #endif
+
+	  struct s { _Bool s: 1; _Bool t; } s;
+
+	  char a[true == 1 ? 1 : -1];
+	  char b[false == 0 ? 1 : -1];
+	  char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+	  char d[(bool) -0.5 == true ? 1 : -1];
+	  bool e = &s;
+	  char f[(_Bool) -0.0 == false ? 1 : -1];
+	  char g[true];
+	  char h[sizeof (_Bool)];
+	  char i[sizeof s.t];
+
+int
+main ()
+{
+ return !a + !b + !c + !d + !e + !f + !g + !h + !i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_header_stdbool_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdbool_h=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6
+   echo "$as_me:$LINENO: checking for _Bool" >&5
+echo $ECHO_N "checking for _Bool... $ECHO_C" >&6
+if test "${ac_cv_type__Bool+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((_Bool *) 0)
+  return 0;
+if (sizeof (_Bool))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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__Bool=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type__Bool=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type__Bool" >&5
+echo "${ECHO_T}$ac_cv_type__Bool" >&6
+if test $ac_cv_type__Bool = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+   if test $ac_cv_header_stdbool_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STDBOOL_H 1
+_ACEOF
+
+   fi
+if test "$ac_cv_type__Bool" = no; then
+  HAVE__BOOL=0
+else
+  HAVE__BOOL=1
+fi
+
+if test "$ac_cv_header_stdbool_h" = no; then
+            ac_config_files="$ac_config_files lib/stdbool.h:lib/stdbool_.h"
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6
+if test "${ac_cv_working_alloca_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_working_alloca_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_working_alloca_h=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6
+if test "${ac_cv_func_alloca_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_func_alloca_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_alloca_works=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6
+if test "${ac_cv_os_cray+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6
+if test "${ac_cv_c_stack_direction+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+  exit (find_stack_direction () < 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_c_stack_direction=1
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
+if test "${ac_cv_func__doprnt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+char (*f) () = _doprnt;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != _doprnt;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_func__doprnt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func__doprnt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+  am_getline_needs_run_time_check=no
+  echo "$as_me:$LINENO: checking for getline" >&5
+echo $ECHO_N "checking for getline... $ECHO_C" >&6
+if test "${ac_cv_func_getline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define getline to an innocuous variant, in case <limits.h> declares getline.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define getline innocuous_getline
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char getline (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getline
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char getline ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_getline) || defined (__stub___getline)
+choke me
+#else
+char (*f) () = getline;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != getline;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_func_getline=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getline=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getline" >&5
+echo "${ECHO_T}$ac_cv_func_getline" >&6
+if test $ac_cv_func_getline = yes; then
+  		am_getline_needs_run_time_check=yes
+else
+  am_cv_func_working_getline=no
+fi
+
+  if test $am_getline_needs_run_time_check = yes; then
+    echo "$as_me:$LINENO: checking for working getline function" >&5
+echo $ECHO_N "checking for working getline function... $ECHO_C" >&6
+if test "${am_cv_func_working_getline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  echo fooN |tr -d '\012'|tr N '\012' > conftest.data
+    if test "$cross_compiling" = yes; then
+  am_cv_func_working_getline=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#    include <stdio.h>
+#    include <sys/types.h>
+#    include <string.h>
+    int main ()
+    { /* Based on a test program from Karl Heuer.  */
+      char *line = NULL;
+      size_t siz = 0;
+      int len;
+      FILE *in = fopen ("./conftest.data", "r");
+      if (!in)
+	return 1;
+      len = getline (&line, &siz, in);
+      exit ((len == 4 && line && strcmp (line, "foo\n") == 0) ? 0 : 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
+  am_cv_func_working_getline=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+am_cv_func_working_getline=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $am_cv_func_working_getline" >&5
+echo "${ECHO_T}$am_cv_func_working_getline" >&6
+  fi
+
+  if test $am_cv_func_working_getline = no; then
+    case $LIBOBJS in
+    "getline.$ac_objext"   | \
+  *" getline.$ac_objext"   | \
+    "getline.$ac_objext "* | \
+  *" getline.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS getline.$ac_objext" ;;
+esac
+
+  fi
+
+echo "$as_me:$LINENO: checking for obstacks" >&5
+echo $ECHO_N "checking for obstacks... $ECHO_C" >&6
+if test "${ac_cv_func_obstack+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include "obstack.h"
+int
+main ()
+{
+struct obstack *mem; obstack_free(mem,(char *) 0)
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_func_obstack=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_obstack=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_obstack" >&5
+echo "${ECHO_T}$ac_cv_func_obstack" >&6
+if test $ac_cv_func_obstack = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_OBSTACK 1
+_ACEOF
+
+else
+  case $LIBOBJS in
+    "obstack.$ac_objext"   | \
+  *" obstack.$ac_objext"   | \
+    "obstack.$ac_objext "* | \
+  *" obstack.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS obstack.$ac_objext" ;;
+esac
+
+fi
+
+
+  echo "$as_me:$LINENO: checking whether mbrtowc and mbstate_t are properly declared" >&5
+echo $ECHO_N "checking whether mbrtowc and mbstate_t are properly declared... $ECHO_C" >&6
+if test "${ac_cv_func_mbrtowc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <wchar.h>
+int
+main ()
+{
+mbstate_t state; return ! (sizeof state && mbrtowc);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_func_mbrtowc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_mbrtowc=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mbrtowc" >&5
+echo "${ECHO_T}$ac_cv_func_mbrtowc" >&6
+  if test $ac_cv_func_mbrtowc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MBRTOWC 1
+_ACEOF
+
+  fi
+
+echo "$as_me:$LINENO: checking for mbstate_t" >&5
+echo $ECHO_N "checking for mbstate_t... $ECHO_C" >&6
+if test "${ac_cv_type_mbstate_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#	    include <wchar.h>
+int
+main ()
+{
+mbstate_t x; return sizeof x;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_mbstate_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_mbstate_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_mbstate_t" >&5
+echo "${ECHO_T}$ac_cv_type_mbstate_t" >&6
+   if test $ac_cv_type_mbstate_t = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MBSTATE_T 1
+_ACEOF
+
+   else
+
+cat >>confdefs.h <<\_ACEOF
+#define mbstate_t int
+_ACEOF
+
+   fi
+
+
+
+
+for ac_func in strverscmp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case $LIBOBJS in
+    "$ac_func.$ac_objext"   | \
+  *" $ac_func.$ac_objext"   | \
+    "$ac_func.$ac_objext "* | \
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+  if test $ac_cv_func_strverscmp = no; then
+
+  :
+
+  fi
+
+
+
+
+
+
+for ac_func in memchr memcmp memmove strerror mkstemp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case $LIBOBJS in
+    "$ac_func.$ac_objext"   | \
+  *" $ac_func.$ac_objext"   | \
+    "$ac_func.$ac_objext "* | \
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in isatty bcopy bzero isascii memcpy memset strchr strtoul popen \
+		pathconf isblank fchown fchmod setlocale wcrtomb wcscoll btowc
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check whether --enable-i18n or --disable-i18n was given.
+if test "${enable_i18n+set}" = set; then
+  enableval="$enable_i18n"
+
+else
+  enable_i18n=yes
+fi;
+if test "x$enable_i18n" = xno; then
+  ac_cv_func_wcscoll=false
+fi
+
+
+# Check whether --with-included-regex or --without-included-regex was given.
+if test "${with_included_regex+set}" = set; then
+  withval="$with_included_regex"
+
+else
+  with_included_regex=yes
+fi;
+
+if test "x$with_included_regex" = xno; then
+
+for ac_header in regex.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  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
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -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
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to bonzini@gnu.org ##
+## ------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+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
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+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 re_search in -lregex" >&5
+echo $ECHO_N "checking for re_search in -lregex... $ECHO_C" >&6
+if test "${ac_cv_lib_regex_re_search+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lregex  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char re_search ();
+int
+main ()
+{
+re_search ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_lib_regex_re_search=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_regex_re_search=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_regex_re_search" >&5
+echo "${ECHO_T}$ac_cv_lib_regex_re_search" >&6
+if test $ac_cv_lib_regex_re_search = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBREGEX 1
+_ACEOF
+
+  LIBS="-lregex $LIBS"
+
+fi
+
+  echo "$as_me:$LINENO: checking for re_search" >&5
+echo $ECHO_N "checking for re_search... $ECHO_C" >&6
+if test "${ac_cv_func_re_search+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define re_search to an innocuous variant, in case <limits.h> declares re_search.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define re_search innocuous_re_search
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char re_search (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef re_search
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char re_search ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_re_search) || defined (__stub___re_search)
+choke me
+#else
+char (*f) () = re_search;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != re_search;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  ac_cv_func_re_search=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_re_search=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_re_search" >&5
+echo "${ECHO_T}$ac_cv_func_re_search" >&6
+
+  if test $ac_cv_header_regex_h = no || test $ac_cv_func_re_search = no; then
+    { echo "$as_me:$LINENO: WARNING: GNU regex not found, falling back to the included version" >&5
+echo "$as_me: WARNING: GNU regex not found, falling back to the included version" >&2;}
+    with_included_regex=yes
+  fi
+fi
+
+# Check whether --enable-regex-tests or --disable-regex-tests was given.
+if test "${enable_regex_tests+set}" = set; then
+  enableval="$enable_regex_tests"
+  if test "x$with_included_regex" = xno; then
+  enable_regex_tests=no
+fi
+else
+  enable_regex_tests=$with_included_regex
+fi;
+
+
+
+if test "x$enable_regex_tests" != xno; then
+  TEST_REGEX_TRUE=
+  TEST_REGEX_FALSE='#'
+else
+  TEST_REGEX_TRUE='#'
+  TEST_REGEX_FALSE=
+fi
+
+if test "x$with_included_regex" != xno; then
+            ac_config_links="$ac_config_links lib/regex.h:lib/regex_.h"
+
+  case $LIBOBJS in
+    "regex.$ac_objext"   | \
+  *" regex.$ac_objext"   | \
+    "regex.$ac_objext "* | \
+  *" regex.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS regex.$ac_objext" ;;
+esac
+
+fi
+if test "x$enable_regex_tests" = xyes; then
+
+cat >>confdefs.h <<_ACEOF
+#define _REGEX_RE_COMP 1
+_ACEOF
+
+fi
+
+# Check whether --enable-html or --disable-html was given.
+if test "${enable_html+set}" = set; then
+  enableval="$enable_html"
+
+else
+  enable_html=no
+fi;
+
+
+
+if test "x$enable_html" != xno; then
+  BUILD_HTML_TRUE=
+  BUILD_HTML_FALSE='#'
+else
+  BUILD_HTML_TRUE='#'
+  BUILD_HTML_FALSE=
+fi
+
+
+: ${TEXI2HTML=texi2html -monolithic}
+
+
+echo "$as_me:$LINENO: checking how to build HTML documentation" >&5
+echo $ECHO_N "checking how to build HTML documentation... $ECHO_C" >&6
+if eval $am_missing_run makeinfo --help 2>&1 | grep .-html > /dev/null; then
+  echo "$as_me:$LINENO: result: with makeinfo" >&5
+echo "${ECHO_T}with makeinfo" >&6
+  enable_html=makeinfo
+else
+  if $TEXI2HTML --help 2>&1 | grep monolithic > /dev/null; then
+    echo "$as_me:$LINENO: result: with texi2html" >&5
+echo "${ECHO_T}with texi2html" >&6
+    enable_html=texi2html
+  else
+    echo "$as_me:$LINENO: result: not built" >&5
+echo "${ECHO_T}not built" >&6
+    if test "x$enable_html" != xno; then
+      { { echo "$as_me:$LINENO: error: cannot build HTML documentation" >&5
+echo "$as_me: error: cannot build HTML documentation" >&2;}
+   { (exit install makeinfo 4.0 or texi2html); exit install makeinfo 4.0 or texi2html; }; }
+    fi
+    enable_html=no
+  fi
+fi
+
+
+
+if test "x$enable_html" = xmakeinfo; then
+  MAKEINFO_HTML_TRUE=
+  MAKEINFO_HTML_FALSE='#'
+else
+  MAKEINFO_HTML_TRUE='#'
+  MAKEINFO_HTML_FALSE=
+fi
+
+
+
+if test "x$enable_html" = xtexi2html; then
+  TEXI2HTML_HTML_TRUE=
+  TEXI2HTML_HTML_FALSE='#'
+else
+  TEXI2HTML_HTML_TRUE='#'
+  TEXI2HTML_HTML_FALSE=
+fi
+
+
+
+
+
+MKINSTALLDIRS="$mkdir_p"
+
+
+
+        # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; 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_MSGFMT+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case "$MSGFMT" in
+  /*)
+  ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if $ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 &&
+     (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then
+	ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+	break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":"
+  ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test "$MSGFMT" != ":"; then
+  echo "$as_me:$LINENO: result: $MSGFMT" >&5
+echo "${ECHO_T}$MSGFMT" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; 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_GMSGFMT+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $GMSGFMT in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GMSGFMT="$GMSGFMT" # 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_GMSGFMT="$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
+
+  test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+  ;;
+esac
+fi
+GMSGFMT=$ac_cv_path_GMSGFMT
+
+if test -n "$GMSGFMT"; then
+  echo "$as_me:$LINENO: result: $GMSGFMT" >&5
+echo "${ECHO_T}$GMSGFMT" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+        # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; 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_XGETTEXT+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case "$XGETTEXT" in
+  /*)
+  ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 &&
+     (if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then
+	ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+	break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+  ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test "$XGETTEXT" != ":"; then
+  echo "$as_me:$LINENO: result: $XGETTEXT" >&5
+echo "${ECHO_T}$XGETTEXT" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    rm -f messages.po
+
+    # Extract the first word of "msgmerge", so it can be a program name with args.
+set dummy msgmerge; 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_MSGMERGE+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case "$MSGMERGE" in
+  /*)
+  ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if $ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1; then
+	ac_cv_path_MSGMERGE="$ac_dir/$ac_word"
+	break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":"
+  ;;
+esac
+fi
+MSGMERGE="$ac_cv_path_MSGMERGE"
+if test "$MSGMERGE" != ":"; then
+  echo "$as_me:$LINENO: result: $MSGMERGE" >&5
+echo "${ECHO_T}$MSGMERGE" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+      if test "$GMSGFMT" != ":"; then
+            if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 &&
+       (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then
+      : ;
+    else
+      GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'`
+      echo "$as_me:$LINENO: result: found $GMSGFMT program is not GNU msgfmt; ignore it" >&5
+echo "${ECHO_T}found $GMSGFMT program is not GNU msgfmt; ignore it" >&6
+      GMSGFMT=":"
+    fi
+  fi
+
+      if test "$XGETTEXT" != ":"; then
+            if $XGETTEXT --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 &&
+       (if $XGETTEXT --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then
+      : ;
+    else
+      echo "$as_me:$LINENO: result: found xgettext program is not GNU xgettext; ignore it" >&5
+echo "${ECHO_T}found xgettext program is not GNU xgettext; ignore it" >&6
+      XGETTEXT=":"
+    fi
+        rm -f messages.po
+  fi
+
+            ac_config_commands="$ac_config_commands default-1"
+
+
+# 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/'`
+
+
+echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6
+if test "${ac_cv_c_inline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_inline=$ac_kw; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6
+
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((off_t *) 0)
+  return 0;
+if (sizeof (off_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_off_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+if test $ac_cv_type_off_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long
+_ACEOF
+
+fi
+
+
+
+for ac_header in stdlib.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  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
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -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
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to bonzini@gnu.org ##
+## ------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+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
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+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
+
+
+for ac_func in getpagesize
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+echo "$as_me:$LINENO: checking for working mmap" >&5
+echo $ECHO_N "checking for working mmap... $ECHO_C" >&6
+if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_mmap_fixed_mapped=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+   Here is a matrix of mmap possibilities:
+	mmap private not fixed
+	mmap private fixed at somewhere currently unmapped
+	mmap private fixed at somewhere already mapped
+	mmap shared not fixed
+	mmap shared fixed at somewhere currently unmapped
+	mmap shared fixed at somewhere already mapped
+   For private mappings, we should verify that changes cannot be read()
+   back from the file, nor mmap's back from the file at a different
+   address.  (There have been systems where private was not correctly
+   implemented like the infamous i386 svr4.0, and systems where the
+   VM page cache was not coherent with the file system buffer cache
+   like early versions of FreeBSD and possibly contemporary NetBSD.)
+   For shared mappings, we should conversely verify that changes get
+   propagated back to all the places they're supposed to be.
+
+   Grep wants private fixed already mapped.
+   The main things grep needs to know about mmap are:
+   * does it exist and is it safe to write into the mmap'd area
+   * how to use it (BSD variants)  */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !STDC_HEADERS && !HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h.  */
+#if !HAVE_GETPAGESIZE
+/* Assume that all systems that can run configure have sys/param.h.  */
+# if !HAVE_SYS_PARAM_H
+#  define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+#  define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+#  if HAVE_SYS_PARAM_H
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else /* no EXEC_PAGESIZE */
+#    ifdef NBPG
+#     define getpagesize() NBPG * CLSIZE
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif /* no CLSIZE */
+#    else /* no NBPG */
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     else /* no NBPC */
+#      ifdef PAGESIZE
+#       define getpagesize() PAGESIZE
+#      endif /* PAGESIZE */
+#     endif /* no NBPC */
+#    endif /* no NBPG */
+#   endif /* no EXEC_PAGESIZE */
+#  else /* no HAVE_SYS_PARAM_H */
+#   define getpagesize() 8192	/* punt totally */
+#  endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+  char *data, *data2, *data3;
+  int i, pagesize;
+  int fd;
+
+  pagesize = getpagesize ();
+
+  /* First, make a file with some known garbage in it. */
+  data = (char *) malloc (pagesize);
+  if (!data)
+    exit (1);
+  for (i = 0; i < pagesize; ++i)
+    *(data + i) = rand ();
+  umask (0);
+  fd = creat ("conftest.mmap", 0600);
+  if (fd < 0)
+    exit (1);
+  if (write (fd, data, pagesize) != pagesize)
+    exit (1);
+  close (fd);
+
+  /* Next, try to mmap the file at a fixed address which already has
+     something else allocated at it.  If we can, also make sure that
+     we see the same garbage.  */
+  fd = open ("conftest.mmap", O_RDWR);
+  if (fd < 0)
+    exit (1);
+  data2 = (char *) malloc (2 * pagesize);
+  if (!data2)
+    exit (1);
+  data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1);
+  if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+		     MAP_PRIVATE | MAP_FIXED, fd, 0L))
+    exit (1);
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data2 + i))
+      exit (1);
+
+  /* Finally, make sure that changes to the mapped area do not
+     percolate back to the file as seen by read().  (This is a bug on
+     some variants of i386 svr4.0.)  */
+  for (i = 0; i < pagesize; ++i)
+    *(data2 + i) = *(data2 + i) + 1;
+  data3 = (char *) malloc (pagesize);
+  if (!data3)
+    exit (1);
+  if (read (fd, data3, pagesize) != pagesize)
+    exit (1);
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data3 + i))
+      exit (1);
+  close (fd);
+  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
+  ac_cv_func_mmap_fixed_mapped=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+fi
+rm -f conftest.mmap
+
+
+    echo "$as_me:$LINENO: checking whether we are using the GNU C Library 2.1 or newer" >&5
+echo $ECHO_N "checking whether we are using the GNU C Library 2.1 or newer... $ECHO_C" >&6
+if test "${ac_cv_gnu_library_2_1+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
+  Lucky GNU user
+ #endif
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "Lucky GNU user" >/dev/null 2>&1; then
+  ac_cv_gnu_library_2_1=yes
+else
+  ac_cv_gnu_library_2_1=no
+fi
+rm -f conftest*
+
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_gnu_library_2_1" >&5
+echo "${ECHO_T}$ac_cv_gnu_library_2_1" >&6
+
+    GLIBC21="$ac_cv_gnu_library_2_1"
+
+
+
+      if test "X$prefix" = "XNONE"; then
+    acl_final_prefix="$ac_default_prefix"
+  else
+    acl_final_prefix="$prefix"
+  fi
+  if test "X$exec_prefix" = "XNONE"; then
+    acl_final_exec_prefix='${prefix}'
+  else
+    acl_final_exec_prefix="$exec_prefix"
+  fi
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+  prefix="$acl_save_prefix"
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${acl_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      acl_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+	test "$with_gnu_ld" != no && break
+      else
+	test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+  echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${acl_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  acl_cv_prog_gnu_ld=yes
+else
+  acl_cv_prog_gnu_ld=no
+fi
+fi
+echo "$as_me:$LINENO: result: $acl_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$acl_cv_prog_gnu_ld" >&6
+with_gnu_ld=$acl_cv_prog_gnu_ld
+
+
+
+                                                echo "$as_me:$LINENO: checking for shared library run path origin" >&5
+echo $ECHO_N "checking for shared library run path origin... $ECHO_C" >&6
+if test "${acl_cv_rpath+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+    CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+    ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+    . ./conftest.sh
+    rm -f ./conftest.sh
+    acl_cv_rpath=done
+
+fi
+echo "$as_me:$LINENO: result: $acl_cv_rpath" >&5
+echo "${ECHO_T}$acl_cv_rpath" >&6
+  wl="$acl_cv_wl"
+  libext="$acl_cv_libext"
+  shlibext="$acl_cv_shlibext"
+  hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+  hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+  hardcode_direct="$acl_cv_hardcode_direct"
+  hardcode_minus_L="$acl_cv_hardcode_minus_L"
+  sys_lib_search_path_spec="$acl_cv_sys_lib_search_path_spec"
+  sys_lib_dlsearch_path_spec="$acl_cv_sys_lib_dlsearch_path_spec"
+
+
+
+
+
+
+
+
+    use_additional=yes
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+
+# Check whether --with-libiconv-prefix or --without-libiconv-prefix was given.
+if test "${with_libiconv_prefix+set}" = set; then
+  withval="$with_libiconv_prefix"
+
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/lib"
+      fi
+    fi
+
+fi;
+      LIBICONV=
+  LTLIBICONV=
+  INCICONV=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='iconv '
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+                        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value"
+          else
+                                    :
+          fi
+        else
+                              found_dir=
+          found_la=
+          found_so=
+          found_a=
+          if test $use_additional = yes; then
+            if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
+              found_dir="$additional_libdir"
+              found_so="$additional_libdir/lib$name.$shlibext"
+              if test -f "$additional_libdir/lib$name.la"; then
+                found_la="$additional_libdir/lib$name.la"
+              fi
+            else
+              if test -f "$additional_libdir/lib$name.$libext"; then
+                found_dir="$additional_libdir"
+                found_a="$additional_libdir/lib$name.$libext"
+                if test -f "$additional_libdir/lib$name.la"; then
+                  found_la="$additional_libdir/lib$name.la"
+                fi
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
+                    found_dir="$dir"
+                    found_so="$dir/lib$name.$shlibext"
+                    if test -f "$dir/lib$name.la"; then
+                      found_la="$dir/lib$name.la"
+                    fi
+                  else
+                    if test -f "$dir/lib$name.$libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/lib$name.$libext"
+                      if test -f "$dir/lib$name.la"; then
+                        found_la="$dir/lib$name.la"
+                      fi
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+                        LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+                                                        if test "X$found_dir" = "X/usr/lib"; then
+                                LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+              else
+                                                                                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                                if test "$hardcode_direct" = yes; then
+                                                      LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                                                            LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                                                            haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                                                                                haveit=
+                    for x in $LDFLAGS $LIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                                                                                        LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                    else
+                                                                                                                                                                                LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                                LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a"
+              else
+                                                LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name"
+              fi
+            fi
+                        additional_includedir=
+            case "$found_dir" in
+              */lib | */lib/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+                                                                                                                if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux*) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INCICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                                            INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+                        if test -n "$found_la"; then
+                                                        save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+                            for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                                                                                                                                                                if test "X$additional_libdir" != "X/usr/lib"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/lib"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux*) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                                        names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                                                                                names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                                        LIBICONV="${LIBICONV}${LIBICONV:+ }$dep"
+                    LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+                                                            LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+            LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$hardcode_libdir_separator"; then
+                        alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+      done
+            acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+    else
+            for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+            for found_dir in $ltrpathdirs; do
+      LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir"
+    done
+  fi
+
+
+          am_save_CPPFLAGS="$CPPFLAGS"
+
+  for element in $INCICONV; do
+    haveit=
+    for x in $CPPFLAGS; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+    fi
+  done
+
+
+  echo "$as_me:$LINENO: checking for iconv" >&5
+echo $ECHO_N "checking for iconv... $ECHO_C" >&6
+if test "${am_cv_func_iconv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+       iconv(cd,NULL,NULL,NULL,NULL);
+       iconv_close(cd);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  am_cv_func_iconv=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBICONV"
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+         iconv(cd,NULL,NULL,NULL,NULL);
+         iconv_close(cd);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  am_cv_lib_iconv=yes
+        am_cv_func_iconv=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+      LIBS="$am_save_LIBS"
+    fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5
+echo "${ECHO_T}$am_cv_func_iconv" >&6
+  if test "$am_cv_func_iconv" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ICONV 1
+_ACEOF
+
+  fi
+  if test "$am_cv_lib_iconv" = yes; then
+    echo "$as_me:$LINENO: checking how to link with libiconv" >&5
+echo $ECHO_N "checking how to link with libiconv... $ECHO_C" >&6
+    echo "$as_me:$LINENO: result: $LIBICONV" >&5
+echo "${ECHO_T}$LIBICONV" >&6
+  else
+            CPPFLAGS="$am_save_CPPFLAGS"
+    LIBICONV=
+    LTLIBICONV=
+  fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in argz.h limits.h locale.h nl_types.h malloc.h stddef.h \
+stdlib.h string.h unistd.h sys/param.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  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
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -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
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to bonzini@gnu.org ##
+## ------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+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
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \
+geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \
+strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+  if test "$am_cv_func_iconv" = yes; then
+    echo "$as_me:$LINENO: checking for iconv declaration" >&5
+echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6
+    if test "${am_cv_proto_iconv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  am_cv_proto_iconv_arg1=""
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+am_cv_proto_iconv_arg1="const"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"
+fi
+
+    am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    echo "$as_me:$LINENO: result: ${ac_t:-
+         }$am_cv_proto_iconv" >&5
+echo "${ECHO_T}${ac_t:-
+         }$am_cv_proto_iconv" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define ICONV_CONST $am_cv_proto_iconv_arg1
+_ACEOF
+
+  fi
+
+
+  echo "$as_me:$LINENO: checking for nl_langinfo and CODESET" >&5
+echo $ECHO_N "checking for nl_langinfo and CODESET... $ECHO_C" >&6
+if test "${am_cv_langinfo_codeset+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <langinfo.h>
+int
+main ()
+{
+char* cs = nl_langinfo(CODESET);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  am_cv_langinfo_codeset=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+am_cv_langinfo_codeset=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_langinfo_codeset" >&5
+echo "${ECHO_T}$am_cv_langinfo_codeset" >&6
+  if test $am_cv_langinfo_codeset = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LANGINFO_CODESET 1
+_ACEOF
+
+  fi
+
+  if test $ac_cv_header_locale_h = yes; then
+    echo "$as_me:$LINENO: checking for LC_MESSAGES" >&5
+echo $ECHO_N "checking for LC_MESSAGES... $ECHO_C" >&6
+if test "${am_cv_val_LC_MESSAGES+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <locale.h>
+int
+main ()
+{
+return LC_MESSAGES
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  am_cv_val_LC_MESSAGES=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+am_cv_val_LC_MESSAGES=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $am_cv_val_LC_MESSAGES" >&5
+echo "${ECHO_T}$am_cv_val_LC_MESSAGES" >&6
+    if test $am_cv_val_LC_MESSAGES = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LC_MESSAGES 1
+_ACEOF
+
+    fi
+  fi
+
+                      for ac_prog in bison
+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_INTLBISON+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$INTLBISON"; then
+  ac_cv_prog_INTLBISON="$INTLBISON" # 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_INTLBISON="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+INTLBISON=$ac_cv_prog_INTLBISON
+if test -n "$INTLBISON"; then
+  echo "$as_me:$LINENO: result: $INTLBISON" >&5
+echo "${ECHO_T}$INTLBISON" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$INTLBISON" && break
+done
+
+  if test -z "$INTLBISON"; then
+    ac_verc_fail=yes
+  else
+        echo "$as_me:$LINENO: checking version of bison" >&5
+echo $ECHO_N "checking version of bison... $ECHO_C" >&6
+    ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'`
+    case $ac_prog_version in
+      '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+      1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*)
+         ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+      *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+    esac
+    echo "$as_me:$LINENO: result: $ac_prog_version" >&5
+echo "${ECHO_T}$ac_prog_version" >&6
+  fi
+  if test $ac_verc_fail = yes; then
+    INTLBISON=:
+  fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+  echo "$as_me:$LINENO: checking whether NLS is requested" >&5
+echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6
+    # Check whether --enable-nls or --disable-nls was given.
+if test "${enable_nls+set}" = set; then
+  enableval="$enable_nls"
+  USE_NLS=$enableval
+else
+  USE_NLS=yes
+fi;
+  echo "$as_me:$LINENO: result: $USE_NLS" >&5
+echo "${ECHO_T}$USE_NLS" >&6
+
+
+
+    BUILD_INCLUDED_LIBINTL=no
+    USE_INCLUDED_LIBINTL=no
+
+  LIBINTL=
+  LTLIBINTL=
+  POSUB=
+
+    if test "$USE_NLS" = "yes"; then
+    gt_use_preinstalled_gnugettext=no
+
+      echo "$as_me:$LINENO: checking whether included gettext is requested" >&5
+echo $ECHO_N "checking whether included gettext is requested... $ECHO_C" >&6
+
+# Check whether --with-included-gettext or --without-included-gettext was given.
+if test "${with_included_gettext+set}" = set; then
+  withval="$with_included_gettext"
+  nls_cv_force_use_gnu_gettext=$withval
+else
+  nls_cv_force_use_gnu_gettext=no
+fi;
+      echo "$as_me:$LINENO: result: $nls_cv_force_use_gnu_gettext" >&5
+echo "${ECHO_T}$nls_cv_force_use_gnu_gettext" >&6
+
+      nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+      if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+
+
+
+
+
+
+        echo "$as_me:$LINENO: checking for GNU gettext in libc" >&5
+echo $ECHO_N "checking for GNU gettext in libc... $ECHO_C" >&6
+if test "${gt_cv_func_gnugettext2_libc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <libintl.h>
+extern int _nl_msg_cat_cntr;
+int
+main ()
+{
+bindtextdomain ("", "");
+return (int) gettext ("") + (int) ngettext ("", "", 0) + _nl_msg_cat_cntr
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  gt_cv_func_gnugettext2_libc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+gt_cv_func_gnugettext2_libc=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $gt_cv_func_gnugettext2_libc" >&5
+echo "${ECHO_T}$gt_cv_func_gnugettext2_libc" >&6
+
+        if test "$gt_cv_func_gnugettext2_libc" != "yes"; then
+
+
+
+    use_additional=yes
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+
+# Check whether --with-libintl-prefix or --without-libintl-prefix was given.
+if test "${with_libintl_prefix+set}" = set; then
+  withval="$with_libintl_prefix"
+
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/lib"
+      fi
+    fi
+
+fi;
+      LIBINTL=
+  LTLIBINTL=
+  INCINTL=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='intl '
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+                        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value"
+          else
+                                    :
+          fi
+        else
+                              found_dir=
+          found_la=
+          found_so=
+          found_a=
+          if test $use_additional = yes; then
+            if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
+              found_dir="$additional_libdir"
+              found_so="$additional_libdir/lib$name.$shlibext"
+              if test -f "$additional_libdir/lib$name.la"; then
+                found_la="$additional_libdir/lib$name.la"
+              fi
+            else
+              if test -f "$additional_libdir/lib$name.$libext"; then
+                found_dir="$additional_libdir"
+                found_a="$additional_libdir/lib$name.$libext"
+                if test -f "$additional_libdir/lib$name.la"; then
+                  found_la="$additional_libdir/lib$name.la"
+                fi
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIBINTL; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
+                    found_dir="$dir"
+                    found_so="$dir/lib$name.$shlibext"
+                    if test -f "$dir/lib$name.la"; then
+                      found_la="$dir/lib$name.la"
+                    fi
+                  else
+                    if test -f "$dir/lib$name.$libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/lib$name.$libext"
+                      if test -f "$dir/lib$name.la"; then
+                        found_la="$dir/lib$name.la"
+                      fi
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+                        LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+                                                        if test "X$found_dir" = "X/usr/lib"; then
+                                LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so"
+              else
+                                                                                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                                if test "$hardcode_direct" = yes; then
+                                                      LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                                                            LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so"
+                                                            haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                                                                                haveit=
+                    for x in $LDFLAGS $LIBINTL; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                                                                                        LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so"
+                    else
+                                                                                                                                                                                LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                                LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a"
+              else
+                                                LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name"
+              fi
+            fi
+                        additional_includedir=
+            case "$found_dir" in
+              */lib | */lib/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+                                                                                                                if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux*) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INCINTL; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                                            INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+                        if test -n "$found_la"; then
+                                                        save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+                            for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                                                                                                                                                                if test "X$additional_libdir" != "X/usr/lib"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/lib"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux*) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIBINTL; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIBINTL; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                                        names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                                                                                names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                                        LIBINTL="${LIBINTL}${LIBINTL:+ }$dep"
+                    LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+                                                            LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name"
+            LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$hardcode_libdir_separator"; then
+                        alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+      done
+            acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIBINTL="${LIBINTL}${LIBINTL:+ }$flag"
+    else
+            for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIBINTL="${LIBINTL}${LIBINTL:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+            for found_dir in $ltrpathdirs; do
+      LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir"
+    done
+  fi
+
+          echo "$as_me:$LINENO: checking for GNU gettext in libintl" >&5
+echo $ECHO_N "checking for GNU gettext in libintl... $ECHO_C" >&6
+if test "${gt_cv_func_gnugettext2_libintl+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  gt_save_CPPFLAGS="$CPPFLAGS"
+            CPPFLAGS="$CPPFLAGS $INCINTL"
+            gt_save_LIBS="$LIBS"
+            LIBS="$LIBS $LIBINTL"
+                        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <libintl.h>
+extern int _nl_msg_cat_cntr;
+int
+main ()
+{
+bindtextdomain ("", "");
+return (int) gettext ("") + (int) ngettext ("", "", 0) + _nl_msg_cat_cntr
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  gt_cv_func_gnugettext2_libintl=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+gt_cv_func_gnugettext2_libintl=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+                        if test "$gt_cv_func_gnugettext2_libintl" != yes && test -n "$LIBICONV"; then
+              LIBS="$LIBS $LIBICONV"
+              cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <libintl.h>
+extern int _nl_msg_cat_cntr;
+int
+main ()
+{
+bindtextdomain ("", "");
+return (int) gettext ("") + (int) ngettext ("", "", 0) + _nl_msg_cat_cntr
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (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); }; } &&
+	 { 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
+  LIBINTL="$LIBINTL $LIBICONV"
+                LTLIBINTL="$LTLIBINTL $LTLIBICONV"
+                gt_cv_func_gnugettext2_libintl=yes
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+            fi
+            CPPFLAGS="$gt_save_CPPFLAGS"
+            LIBS="$gt_save_LIBS"
+fi
+echo "$as_me:$LINENO: result: $gt_cv_func_gnugettext2_libintl" >&5
+echo "${ECHO_T}$gt_cv_func_gnugettext2_libintl" >&6
+        fi
+
+                                        if test "$gt_cv_func_gnugettext2_libc" = "yes" \
+           || { test "$gt_cv_func_gnugettext2_libintl" = "yes" \
+                && test "$PACKAGE" != gettext; }; then
+          gt_use_preinstalled_gnugettext=yes
+        fi
+
+
+        if test "$gt_use_preinstalled_gnugettext" != "yes"; then
+                              nls_cv_use_gnu_gettext=yes
+        fi
+      fi
+
+      if test "$nls_cv_use_gnu_gettext" = "yes"; then
+                INTLOBJS="\$(GETTOBJS)"
+        BUILD_INCLUDED_LIBINTL=yes
+        USE_INCLUDED_LIBINTL=yes
+        LIBINTL="../intl/libintl.a $LIBICONV"
+        LTLIBINTL="../intl/libintl.a $LTLIBICONV"
+        LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
+      fi
+
+      if test "$gt_use_preinstalled_gnugettext" = "yes" \
+         || test "$nls_cv_use_gnu_gettext" = "yes"; then
+                CATOBJEXT=.gmo
+      fi
+
+
+    if test "$gt_use_preinstalled_gnugettext" = "yes" \
+       || test "$nls_cv_use_gnu_gettext" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_NLS 1
+_ACEOF
+
+    else
+      USE_NLS=no
+    fi
+  fi
+
+  if test "$USE_NLS" = "yes"; then
+
+    if test "$gt_use_preinstalled_gnugettext" = "yes"; then
+      if test "$gt_cv_func_gnugettext2_libintl" = "yes"; then
+        echo "$as_me:$LINENO: checking how to link with libintl" >&5
+echo $ECHO_N "checking how to link with libintl... $ECHO_C" >&6
+        echo "$as_me:$LINENO: result: $LIBINTL" >&5
+echo "${ECHO_T}$LIBINTL" >&6
+
+  for element in $INCINTL; do
+    haveit=
+    for x in $CPPFLAGS; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+    fi
+  done
+
+      fi
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETTEXT 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DCGETTEXT 1
+_ACEOF
+
+    fi
+
+        POSUB=po
+  fi
+
+
+            if test "$PACKAGE" = gettext; then
+      BUILD_INCLUDED_LIBINTL=yes
+    fi
+
+
+
+
+
+
+        nls_cv_header_intl=
+    nls_cv_header_libgt=
+
+        DATADIRNAME=share
+
+
+        INSTOBJEXT=.mo
+
+
+        GENCAT=gencat
+
+
+        INTL_LIBTOOL_SUFFIX_PREFIX=
+
+
+
+    INTLLIBS="$LIBINTL"
+
+
+
+
+
+
+          ac_config_commands="$ac_config_commands gettext-fix"
+
+
+          ac_config_files="$ac_config_files bootstrap.sh"
+
+                                                                      ac_config_files="$ac_config_files Makefile doc/Makefile lib/Makefile sed/Makefile testsuite/Makefile po/Makefile.in intl/Makefile"
+
+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 overridden 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 diff $cache_file confcache >/dev/null 2>&1; 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
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${TEST_REGEX_TRUE}" && test -z "${TEST_REGEX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"TEST_REGEX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"TEST_REGEX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${BUILD_HTML_TRUE}" && test -z "${BUILD_HTML_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"BUILD_HTML\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"BUILD_HTML\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${MAKEINFO_HTML_TRUE}" && test -z "${MAKEINFO_HTML_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"MAKEINFO_HTML\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"MAKEINFO_HTML\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${TEXI2HTML_HTML_TRUE}" && test -z "${TEXI2HTML_HTML_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"TEXI2HTML_HTML\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"TEXI2HTML_HTML\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+: ${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
+ac_cs_recheck=false
+ac_cs_silent=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=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$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" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.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
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     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
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval 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="eval 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
+
+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 sed $as_me 4.1.5, which was
+generated by GNU Autoconf 2.59.  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
+  -q, --quiet      do not print progress messages
+  -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
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+sed config.status 4.1.5
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 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[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --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 )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # 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
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+# Capture the value of obsolete $ALL_LINGUAS because we need it to compute
+    # POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES, CATALOGS. But hide it
+    # from automake.
+    eval 'ALL_LINGUAS''="$ALL_LINGUAS"'
+    # Capture the value of LINGUAS because we need it to compute CATALOGS.
+    LINGUAS="${LINGUAS-%UNSET%}"
+
+
+  install_sh="$install_sh"
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "lib/stdbool.h" ) CONFIG_FILES="$CONFIG_FILES lib/stdbool.h:lib/stdbool_.h" ;;
+  "bootstrap.sh" ) CONFIG_FILES="$CONFIG_FILES bootstrap.sh" ;;
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+  "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+  "sed/Makefile" ) CONFIG_FILES="$CONFIG_FILES sed/Makefile" ;;
+  "testsuite/Makefile" ) CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
+  "po/Makefile.in" ) CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;;
+  "intl/Makefile" ) CONFIG_FILES="$CONFIG_FILES intl/Makefile" ;;
+  "lib/regex.h" ) CONFIG_LINKS="$CONFIG_LINKS lib/regex.h:lib/regex_.h" ;;
+  "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+  "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+  "gettext-fix" ) CONFIG_COMMANDS="$CONFIG_COMMANDS gettext-fix" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:config_h.in" ;;
+  *) { { 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
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# 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.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&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,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@CYGPATH_W@,$CYGPATH_W,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOMAKE@,$AUTOMAKE,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@install_sh@,$install_sh,;t t
+s,@STRIP@,$STRIP,;t t
+s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t
+s,@mkdir_p@,$mkdir_p,;t t
+s,@AWK@,$AWK,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@am__leading_dot@,$am__leading_dot,;t t
+s,@AMTAR@,$AMTAR,;t t
+s,@am__tar@,$am__tar,;t t
+s,@am__untar@,$am__untar,;t t
+s,@SED_FEATURE_VERSION@,$SED_FEATURE_VERSION,;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,@DEPDIR@,$DEPDIR,;t t
+s,@am__include@,$am__include,;t t
+s,@am__quote@,$am__quote,;t t
+s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t
+s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t
+s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t
+s,@CCDEPMODE@,$CCDEPMODE,;t t
+s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t
+s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@HAVE__BOOL@,$HAVE__BOOL,;t t
+s,@ALLOCA@,$ALLOCA,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@TEST_REGEX_TRUE@,$TEST_REGEX_TRUE,;t t
+s,@TEST_REGEX_FALSE@,$TEST_REGEX_FALSE,;t t
+s,@BUILD_HTML_TRUE@,$BUILD_HTML_TRUE,;t t
+s,@BUILD_HTML_FALSE@,$BUILD_HTML_FALSE,;t t
+s,@TEXI2HTML@,$TEXI2HTML,;t t
+s,@MAKEINFO_HTML_TRUE@,$MAKEINFO_HTML_TRUE,;t t
+s,@MAKEINFO_HTML_FALSE@,$MAKEINFO_HTML_FALSE,;t t
+s,@TEXI2HTML_HTML_TRUE@,$TEXI2HTML_HTML_TRUE,;t t
+s,@TEXI2HTML_HTML_FALSE@,$TEXI2HTML_HTML_FALSE,;t t
+s,@MKINSTALLDIRS@,$MKINSTALLDIRS,;t t
+s,@MSGFMT@,$MSGFMT,;t t
+s,@GMSGFMT@,$GMSGFMT,;t t
+s,@XGETTEXT@,$XGETTEXT,;t t
+s,@MSGMERGE@,$MSGMERGE,;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,@GLIBC21@,$GLIBC21,;t t
+s,@LIBICONV@,$LIBICONV,;t t
+s,@LTLIBICONV@,$LTLIBICONV,;t t
+s,@INTLBISON@,$INTLBISON,;t t
+s,@USE_NLS@,$USE_NLS,;t t
+s,@BUILD_INCLUDED_LIBINTL@,$BUILD_INCLUDED_LIBINTL,;t t
+s,@USE_INCLUDED_LIBINTL@,$USE_INCLUDED_LIBINTL,;t t
+s,@CATOBJEXT@,$CATOBJEXT,;t t
+s,@INTLOBJS@,$INTLOBJS,;t t
+s,@DATADIRNAME@,$DATADIRNAME,;t t
+s,@INSTOBJEXT@,$INSTOBJEXT,;t t
+s,@GENCAT@,$GENCAT,;t t
+s,@INTL_LIBTOOL_SUFFIX_PREFIX@,$INTL_LIBTOOL_SUFFIX_PREFIX,;t t
+s,@INTLLIBS@,$INTLLIBS,;t t
+s,@LIBINTL@,$LIBINTL,;t t
+s,@LTLIBINTL@,$LTLIBINTL,;t t
+s,@POSUB@,$POSUB,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;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'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  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
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  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
+    bootstrap.sh ) chmod +x bootstrap.sh ;;
+  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; }; }
+	 # Do quote $f, to prevent DOS paths from being IFS'd.
+	 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 grep "^[	 ]*#[	 ]*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 # grep' >>$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 diff $ac_file $tmp/config.h >/dev/null 2>&1; 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'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $ac_file | $ac_file:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $ac_file" >`(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'`/stamp-h$_am_stamp_count
+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'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dest_dir"
+  else
+    as_dir="$ac_dest_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dest_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dest_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  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
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dest_dir";;
+*)
+  case "$ac_dest_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dest_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dest_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $srcdir in
+  [\\/$]* | ?:[\\/]* ) ac_rel_source=$srcdir/$ac_source ;;
+      *) ac_rel_source=$ac_top_builddir$srcdir/$ac_source ;;
+  esac
+
+  # Try a symlink, then a hard link, then a copy.
+  ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+    ln $srcdir/$ac_source $ac_dest 2>/dev/null ||
+    cp -p $srcdir/$ac_source $ac_dest ||
+    { { echo "$as_me:$LINENO: error: cannot link or copy $srcdir/$ac_source to $ac_dest" >&5
+echo "$as_me: error: cannot link or copy $srcdir/$ac_source to $ac_dest" >&2;}
+   { (exit 1); exit 1; }; }
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+  ac_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'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  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
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+  case $ac_dest in
+    depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # So let's grep whole file.
+  if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+    dirpart=`(dirname "$mf") 2>/dev/null ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`(dirname "$file") 2>/dev/null ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    { if $as_mkdir_p; then
+    mkdir -p $dirpart/$fdir
+  else
+    as_dir=$dirpart/$fdir
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5
+echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+ ;;
+    default-1 )
+    for ac_file in $CONFIG_FILES; do
+      # Support "outfile[:infile[:infile...]]"
+      case "$ac_file" in
+        *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+      esac
+      # PO directories have a Makefile.in generated from Makefile.in.in.
+      case "$ac_file" in */Makefile.in)
+        # Adjust a relative srcdir.
+        ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
+        ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`"
+        ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
+        # In autoconf-2.13 it is called $ac_given_srcdir.
+        # In autoconf-2.50 it is called $srcdir.
+        test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
+        case "$ac_given_srcdir" in
+          .)  top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
+          /*) top_srcdir="$ac_given_srcdir" ;;
+          *)  top_srcdir="$ac_dots$ac_given_srcdir" ;;
+        esac
+        if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then
+          rm -f "$ac_dir/POTFILES"
+          test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES"
+          cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ 	]*\$/d" -e "s,.*,     $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES"
+          # ALL_LINGUAS, POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES depend
+          # on $ac_dir but don't depend on user-specified configuration
+          # parameters.
+          if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
+            # The LINGUAS file contains the set of available languages.
+            if test -n "$ALL_LINGUAS"; then
+              test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
+            fi
+            ALL_LINGUAS_=`sed -e "/^#/d" "$ac_given_srcdir/$ac_dir/LINGUAS"`
+            # Hide the ALL_LINGUAS assigment from automake.
+            eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
+          fi
+          case "$ac_given_srcdir" in
+            .) srcdirpre= ;;
+            *) srcdirpre='$(srcdir)/' ;;
+          esac
+          POFILES=
+          GMOFILES=
+          UPDATEPOFILES=
+          DUMMYPOFILES=
+          for lang in $ALL_LINGUAS; do
+            POFILES="$POFILES $srcdirpre$lang.po"
+            GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
+            UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
+            DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
+          done
+          # CATALOGS depends on both $ac_dir and the user's LINGUAS
+          # environment variable.
+          INST_LINGUAS=
+          if test -n "$ALL_LINGUAS"; then
+            for presentlang in $ALL_LINGUAS; do
+              useit=no
+              if test "%UNSET%" != "$LINGUAS"; then
+                desiredlanguages="$LINGUAS"
+              else
+                desiredlanguages="$ALL_LINGUAS"
+              fi
+              for desiredlang in $desiredlanguages; do
+                # Use the presentlang catalog if desiredlang is
+                #   a. equal to presentlang, or
+                #   b. a variant of presentlang (because in this case,
+                #      presentlang can be used as a fallback for messages
+                #      which are not translated in the desiredlang catalog).
+                case "$desiredlang" in
+                  "$presentlang"*) useit=yes;;
+                esac
+              done
+              if test $useit = yes; then
+                INST_LINGUAS="$INST_LINGUAS $presentlang"
+              fi
+            done
+          fi
+          CATALOGS=
+          if test -n "$INST_LINGUAS"; then
+            for lang in $INST_LINGUAS; do
+              CATALOGS="$CATALOGS $lang.gmo"
+            done
+          fi
+          test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile"
+          sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile"
+          for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do
+            if test -f "$f"; then
+              case "$f" in
+                *.orig | *.bak | *~) ;;
+                *) cat "$f" >> "$ac_dir/Makefile" ;;
+              esac
+            fi
+          done
+        fi
+        ;;
+      esac
+    done ;;
+    gettext-fix )
+  sed -e '/^mkinstalldirs *=/a\' \
+      -e "install_sh=$install_sh" \
+      -e 's/^mkinstalldirs *=.*/mkinstalldirs=$(MKINSTALLDIRS)/' \
+      intl/Makefile > intl/Makefile.tmp
+  mv intl/Makefile.tmp intl/Makefile
+  sed -e '/^mkinstalldirs *=/a\' \
+      -e "install_sh=$install_sh" \
+      -e 's/^mkinstalldirs *=.*/mkinstalldirs=$(MKINSTALLDIRS)/' \
+      po/Makefile > po/Makefile.tmp
+  mv po/Makefile.tmp po/Makefile ;;
+  esac
+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=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || 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
+
Index: /tags/kBuild-0.1.4/src/sed/configure.ac
===================================================================
--- /tags/kBuild-0.1.4/src/sed/configure.ac	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/configure.ac	(revision 1780)
@@ -0,0 +1,163 @@
+dnl Process this file with -*- autoconf -*- to produce a configure script.
+AC_INIT(sed, 4.1.5, bonzini@gnu.org, sed)
+AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_SRCDIR([sed/sed.c])
+AM_CONFIG_HEADER(config.h:config_h.in)
+AC_PREREQ(2.59)
+AM_INIT_AUTOMAKE
+
+SED_FEATURE_VERSION=4.1
+AC_DEFINE_UNQUOTED(SED_FEATURE_VERSION, "$SED_FEATURE_VERSION",
+  [Define to the version of GNU sed whose features are supported by this sed.])
+AC_SUBST(SED_FEATURE_VERSION)
+
+AC_PROG_CC
+AC_PROG_RANLIB
+AC_GNU_SOURCE
+AC_AIX
+AC_MINIX
+AC_ISC_POSIX
+AC_SYS_LARGEFILE
+AC_SYS_LONG_FILE_NAMES
+
+AC_CACHE_CHECK([whether -lcP is needed], [sed_cv_libcp_needed], [
+AC_TRY_RUN([
+#include <stdio.h>
+#include <errno.h>
+
+int main()
+{
+  FILE *fp;
+  int result;
+  errno = 0;
+  fp = fopen ("conftest.c", "r");
+  if (!fp) return 0;	   /* error, assume not needed */
+  result = fflush (fp) == EOF && errno == 0;
+  fclose (fp);
+  return result;
+}], [sed_cv_libcp_needed=no],
+    [sed_cv_libcp_needed=yes],
+    [sed_cv_libcp_needed="assuming no"])
+])
+if test "$sed_cv_libcp_needed" = yes; then
+  LIBS="-lcP $LIBS"
+fi
+
+AC_HEADER_DIRENT
+AC_CHECK_HEADERS(io.h limits.h locale.h stdarg.h alloca.h stddef.h errno.h \
+		 wchar.h wctype.h sys/file.h mcheck.h, [], [],
+		 [AC_INCLUDES_DEFAULT])
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_CHECK_TYPE(ssize_t, int)
+
+AC_HEADER_STDBOOL
+if test "$ac_cv_type__Bool" = no; then
+  HAVE__BOOL=0
+else
+  HAVE__BOOL=1
+fi
+AC_SUBST(HAVE__BOOL)
+if test "$ac_cv_header_stdbool_h" = no; then
+  AC_CONFIG_FILES(lib/stdbool.h:lib/stdbool_.h)
+fi
+
+AC_FUNC_ALLOCA
+AC_FUNC_VPRINTF
+AM_FUNC_GETLINE
+AC_FUNC_OBSTACK
+AC_FUNC_MBRTOWC
+AC_TYPE_MBSTATE_T
+gl_FUNC_STRVERSCMP
+AC_REPLACE_FUNCS(memchr memcmp memmove strerror mkstemp)
+AC_CHECK_FUNCS(isatty bcopy bzero isascii memcpy memset strchr strtoul popen \
+		pathconf isblank fchown fchmod setlocale wcrtomb wcscoll btowc)
+
+AC_ARG_ENABLE(i18n,
+[  --disable-i18n          disable internationalization (default=yes)], ,
+enable_i18n=yes)
+if test "x$enable_i18n" = xno; then
+  ac_cv_func_wcscoll=false
+fi
+
+AC_ARG_WITH(included-regex, 
+[  --with-included-regex   use included regex matcher (default=yes)], ,
+with_included_regex=yes)
+
+if test "x$with_included_regex" = xno; then
+  AC_CHECK_HEADERS(regex.h)
+  AC_CHECK_LIB(regex, re_search)
+  AC_CHECK_FUNC(re_search)
+  if test $ac_cv_header_regex_h = no || test $ac_cv_func_re_search = no; then
+    AC_MSG_WARN([GNU regex not found, falling back to the included version])
+    with_included_regex=yes
+  fi
+fi
+
+AC_ARG_ENABLE(regex-tests, 
+[  --enable-regex-tests    enable regex matcher regression tests (default=yes)],
+[if test "x$with_included_regex" = xno; then
+  enable_regex_tests=no
+fi],
+enable_regex_tests=$with_included_regex)
+
+AM_CONDITIONAL(TEST_REGEX, test "x$enable_regex_tests" != xno)
+if test "x$with_included_regex" != xno; then
+  AC_CONFIG_LINKS(lib/regex.h:lib/regex_.h)
+  AC_LIBOBJ(regex)
+fi
+if test "x$enable_regex_tests" = xyes; then
+  AC_DEFINE_UNQUOTED(_REGEX_RE_COMP, 1,
+    [Include BSD functions in regex, used by the testsuite])
+fi
+
+AC_ARG_ENABLE(html, 
+[  --enable-html           build HTML manual (default=no)], ,
+enable_html=no)
+
+AM_CONDITIONAL(BUILD_HTML, test "x$enable_html" != xno)
+
+: ${TEXI2HTML=texi2html -monolithic}
+AC_SUBST(TEXI2HTML)
+
+AC_MSG_CHECKING(how to build HTML documentation)
+if eval $am_missing_run makeinfo --help 2>&1 | grep .-html > /dev/null; then
+  AC_MSG_RESULT(with makeinfo)
+  enable_html=makeinfo
+else
+  if $TEXI2HTML --help 2>&1 | grep monolithic > /dev/null; then
+    AC_MSG_RESULT(with texi2html)
+    enable_html=texi2html
+  else
+    AC_MSG_RESULT(not built)
+    if test "x$enable_html" != xno; then
+      AC_MSG_ERROR(cannot build HTML documentation, install makeinfo 4.0 or texi2html)
+    fi
+    enable_html=no
+  fi
+fi 
+
+AM_CONDITIONAL(MAKEINFO_HTML, test "x$enable_html" = xmakeinfo)
+AM_CONDITIONAL(TEXI2HTML_HTML, test "x$enable_html" = xtexi2html)
+
+
+AC_DEFUN([AM_MKINSTALLDIRS], [MKINSTALLDIRS="$mkdir_p" AC_SUBST(MKINSTALLDIRS)])
+AM_GNU_GETTEXT_VERSION(0.14)
+AM_GNU_GETTEXT(no-libtool, need-ngettext, ../intl)
+dnl bird: made the 'expr/a\' stuff work on BSD. a\ only works when scripting there.
+AC_CONFIG_COMMANDS([gettext-fix], [
+  echo '/^mkinstalldirs *=/a\' > tmp.sed
+  echo "install_sh=$install_sh" >> tmp.sed
+  echo 's/^mkinstalldirs *=.*/mkinstalldirs=$(MKINSTALLDIRS)/' >> tmp.sed
+  sed -f tmp.sed intl/Makefile > intl/Makefile.tmp
+  mv intl/Makefile.tmp intl/Makefile
+  sed -f tmp.sed po/Makefile > po/Makefile.tmp
+  mv po/Makefile.tmp po/Makefile
+  rm -f tmp.sed], [
+  install_sh="$install_sh"])
+
+AC_CONFIG_FILES([bootstrap.sh], chmod +x bootstrap.sh)
+AC_CONFIG_FILES([Makefile doc/Makefile \
+lib/Makefile sed/Makefile testsuite/Makefile \
+po/Makefile.in intl/Makefile])
+AC_OUTPUT
Index: /tags/kBuild-0.1.4/src/sed/doc/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/Makefile.am	(revision 1780)
@@ -0,0 +1,55 @@
+## Process this file with automake to produce Makefile.in
+info_TEXINFOS = sed.texi
+sed_TEXINFOS = config.texi version.texi
+dist_man_MANS = sed.1
+dist_noinst_DATA = sed.x sed-in.texi
+dist_noinst_SCRIPTS = groupify.sed
+CLEANFILES = sed.html
+TEXI2DVI = $(top_srcdir)/config/texi2dvi --expand
+HELP2MAN = $(top_srcdir)/config/help2man
+SED = $(top_builddir)/sed/sed
+
+# To produce better quality output, in the example sed
+# scripts we group comments with lines following them;
+# since mantaining the "@group...@end group" manually
+# is a burden, we do this automatically
+$(srcdir)/sed.texi: sed-in.texi $(srcdir)/groupify.sed
+	sed -nf $(srcdir)/groupify.sed \
+	  < $(srcdir)/sed-in.texi > $(srcdir)/sed.texi
+
+sed.1: $(top_srcdir)/sed/sed.c $(top_srcdir)/configure.ac $(srcdir)/sed.x
+	$(HELP2MAN) --name "stream editor for filtering and transforming text" \
+	  -p sed --include $(srcdir)/sed.x $(SED) > $(srcdir)/sed.1
+
+dist-hook:
+	touch $(distdir)/sed.1
+
+# This rule is used if --enable-html is passed
+if BUILD_HTML
+docdir = $(datadir)/doc
+pkgdocdir = $(datadir)/doc/$(PACKAGE)-$(VERSION)
+pkgdoc_DATA = sed.html
+
+all: html
+
+html: sed.html
+
+.PHONY: html
+endif
+
+# Having a dependancy on sed.info automatically makes
+# sed.html dependant on sed.texi and all the included
+# sources
+if MAKEINFO_HTML
+sed.html: sed.texi sed.info
+	builddir=`pwd` && cd $(srcdir) && \
+	  $(MAKEINFO) --html --no-split -o $$builddir/sed.html sed.texi
+endif
+
+# These rules are used together with TEXI2HTML
+if TEXI2HTML_HTML
+sed.html: sed.texi sed.info
+	cp $(srcdir)/*.texi . && \
+	  $(TEXI2HTML) sed.texi && \
+	  rm *.texi
+endif
Index: /tags/kBuild-0.1.4/src/sed/doc/Makefile.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/Makefile.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/Makefile.in	(revision 1780)
@@ -0,0 +1,632 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# 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_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = doc
+DIST_COMMON = $(dist_man_MANS) $(dist_noinst_DATA) \
+	$(dist_noinst_SCRIPTS) $(sed_TEXINFOS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in $(srcdir)/stamp-vti \
+	$(srcdir)/version.texi
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \
+	$(top_srcdir)/config/getline.m4 \
+	$(top_srcdir)/config/gettext-ver.m4 \
+	$(top_srcdir)/config/gettext.m4 \
+	$(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \
+	$(top_srcdir)/config/lcmessage.m4 \
+	$(top_srcdir)/config/lib-ld.m4 \
+	$(top_srcdir)/config/lib-link.m4 \
+	$(top_srcdir)/config/lib-prefix.m4 \
+	$(top_srcdir)/config/progtest.m4 \
+	$(top_srcdir)/config/stdbool.m4 \
+	$(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SCRIPTS = $(dist_noinst_SCRIPTS)
+SOURCES =
+DIST_SOURCES =
+INFO_DEPS = $(srcdir)/sed.info
+TEXINFO_TEX = $(top_srcdir)/config/texinfo.tex
+am__TEXINFO_TEX_DIR = $(top_srcdir)/config
+DVIS = sed.dvi
+PDFS = sed.pdf
+PSS = sed.ps
+HTMLS = sed.html
+TEXINFOS = sed.texi
+TEXI2PDF = $(TEXI2DVI) --pdf --batch
+MAKEINFOHTML = $(MAKEINFO) --html
+AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS)
+DVIPS = dvips
+am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)" \
+	"$(DESTDIR)$(pkgdocdir)"
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(dist_man_MANS)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+pkgdocDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(dist_noinst_DATA) $(pkgdoc_DATA)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_HTML_FALSE = @BUILD_HTML_FALSE@
+BUILD_HTML_TRUE = @BUILD_HTML_TRUE@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
+GMSGFMT = @GMSGFMT@
+HAVE__BOOL = @HAVE__BOOL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@
+MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SED_FEATURE_VERSION = @SED_FEATURE_VERSION@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEST_REGEX_FALSE = @TEST_REGEX_FALSE@
+TEST_REGEX_TRUE = @TEST_REGEX_TRUE@
+TEXI2HTML = @TEXI2HTML@
+TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@
+TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+info_TEXINFOS = sed.texi
+sed_TEXINFOS = config.texi version.texi
+dist_man_MANS = sed.1
+dist_noinst_DATA = sed.x sed-in.texi
+dist_noinst_SCRIPTS = groupify.sed
+CLEANFILES = sed.html
+TEXI2DVI = $(top_srcdir)/config/texi2dvi --expand
+HELP2MAN = $(top_srcdir)/config/help2man
+SED = $(top_builddir)/sed/sed
+
+# This rule is used if --enable-html is passed
+@BUILD_HTML_TRUE@docdir = $(datadir)/doc
+@BUILD_HTML_TRUE@pkgdocdir = $(datadir)/doc/$(PACKAGE)-$(VERSION)
+@BUILD_HTML_TRUE@pkgdoc_DATA = sed.html
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .dvi .html .info .pdf .ps .texi
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits  doc/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnits  doc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+.texi.info:
+	restore=: && backupdir="$(am__leading_dot)am$$$$" && \
+	am__cwd=`pwd` && cd $(srcdir) && \
+	rm -rf $$backupdir && mkdir $$backupdir && \
+	for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \
+	  if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \
+	done; \
+	cd "$$am__cwd"; \
+	if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
+	 -o $@ $<; \
+	then \
+	  rc=0; \
+	  cd $(srcdir); \
+	else \
+	  rc=$$?; \
+	  cd $(srcdir) && \
+	  $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \
+	fi; \
+	rm -rf $$backupdir; exit $$rc
+
+.texi.dvi:
+	TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
+	MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
+	$(TEXI2DVI) $<
+
+.texi.pdf:
+	TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
+	MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
+	$(TEXI2PDF) $<
+
+.texi.html:
+	rm -rf $(@:.html=.htp)
+	if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
+	 -o $(@:.html=.htp) $<; \
+	then \
+	  rm -rf $@; \
+	  if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \
+	    mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \
+	else \
+	  if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \
+	    rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \
+	  exit 1; \
+	fi
+$(srcdir)/sed.info: sed.texi $(srcdir)/version.texi $(sed_TEXINFOS)
+sed.dvi: sed.texi $(srcdir)/version.texi $(sed_TEXINFOS)
+sed.pdf: sed.texi $(srcdir)/version.texi $(sed_TEXINFOS)
+@MAKEINFO_HTML_FALSE@@TEXI2HTML_HTML_FALSE@sed.html: sed.texi $(srcdir)/version.texi $(sed_TEXINFOS)
+$(srcdir)/version.texi:  $(srcdir)/stamp-vti
+$(srcdir)/stamp-vti: sed.texi $(top_srcdir)/configure
+	@(dir=.; test -f ./sed.texi || dir=$(srcdir); \
+	set `$(SHELL) $(top_srcdir)/config/mdate-sh $$dir/sed.texi`; \
+	echo "@set UPDATED $$1 $$2 $$3"; \
+	echo "@set UPDATED-MONTH $$2 $$3"; \
+	echo "@set EDITION $(VERSION)"; \
+	echo "@set VERSION $(VERSION)") > vti.tmp
+	@cmp -s vti.tmp $(srcdir)/version.texi \
+	  || (echo "Updating $(srcdir)/version.texi"; \
+	      cp vti.tmp $(srcdir)/version.texi)
+	-@rm -f vti.tmp
+	@cp $(srcdir)/version.texi $@
+
+mostlyclean-vti:
+	-rm -f vti.tmp
+
+maintainer-clean-vti:
+	-rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi
+.dvi.ps:
+	$(DVIPS) -o $@ $<
+
+uninstall-info-am:
+	@$(PRE_UNINSTALL)
+	@if (install-info --version && \
+	     install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \
+	  list='$(INFO_DEPS)'; \
+	  for file in $$list; do \
+	    relfile=`echo "$$file" | sed 's|^.*/||'`; \
+	    echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \
+	    install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \
+	  done; \
+	else :; fi
+	@$(NORMAL_UNINSTALL)
+	@list='$(INFO_DEPS)'; \
+	for file in $$list; do \
+	  relfile=`echo "$$file" | sed 's|^.*/||'`; \
+	  relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \
+	  (if cd "$(DESTDIR)$(infodir)"; then \
+	     echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \
+	     rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \
+	   else :; fi); \
+	done
+
+dist-info: $(INFO_DEPS)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	list='$(INFO_DEPS)'; \
+	for base in $$list; do \
+	  case $$base in \
+	    $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \
+	  esac; \
+	  if test -f $$base; then d=.; else d=$(srcdir); fi; \
+	  for file in $$d/$$base*; do \
+	    relfile=`expr "$$file" : "$$d/\(.*\)"`; \
+	    test -f $(distdir)/$$relfile || \
+	      cp -p $$file $(distdir)/$$relfile; \
+	  done; \
+	done
+
+mostlyclean-aminfo:
+	-rm -rf sed.aux sed.cp sed.cps sed.fn sed.fns sed.ky sed.log sed.op sed.pg \
+	  sed.tmp sed.toc sed.tp sed.vr sed.vrs sed.dvi sed.pdf sed.ps \
+	  sed.html
+
+maintainer-clean-aminfo:
+	@list='$(INFO_DEPS)'; for i in $$list; do \
+	  i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \
+	  echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \
+	  rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \
+	done
+install-man1: $(man1_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)"
+	@list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.1*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    1*) ;; \
+	    *) ext='1' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+	  $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+	done
+uninstall-man1:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.1*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    1*) ;; \
+	    *) ext='1' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+	  rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+	done
+install-pkgdocDATA: $(pkgdoc_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(pkgdocdir)" || $(mkdir_p) "$(DESTDIR)$(pkgdocdir)"
+	@list='$(pkgdoc_DATA)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(pkgdocDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdocdir)/$$f'"; \
+	  $(pkgdocDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdocdir)/$$f"; \
+	done
+
+uninstall-pkgdocDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkgdoc_DATA)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(pkgdocdir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(pkgdocdir)/$$f"; \
+	done
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) \
+	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
+	  dist-info dist-hook
+check-am: all-am
+check: check-am
+all-am: Makefile $(INFO_DEPS) $(SCRIPTS) $(MANS) $(DATA)
+installdirs:
+	for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(pkgdocdir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am: $(DVIS)
+
+@BUILD_HTML_FALSE@html: html-am
+
+html-am: $(HTMLS)
+
+info: info-am
+
+info-am: $(INFO_DEPS)
+
+install-data-am: install-info-am install-man install-pkgdocDATA
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-info-am: $(INFO_DEPS)
+	@$(NORMAL_INSTALL)
+	test -z "$(infodir)" || $(mkdir_p) "$(DESTDIR)$(infodir)"
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	list='$(INFO_DEPS)'; \
+	for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	  esac; \
+	  if test -f $$file; then d=.; else d=$(srcdir); fi; \
+	  file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \
+	  for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \
+                       $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \
+	    if test -f $$ifile; then \
+	      relfile=`echo "$$ifile" | sed 's|^.*/||'`; \
+	      echo " $(INSTALL_DATA) '$$ifile' '$(DESTDIR)$(infodir)/$$relfile'"; \
+	      $(INSTALL_DATA) "$$ifile" "$(DESTDIR)$(infodir)/$$relfile"; \
+	    else : ; fi; \
+	  done; \
+	done
+	@$(POST_INSTALL)
+	@if (install-info --version && \
+	     install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \
+	  list='$(INFO_DEPS)'; \
+	  for file in $$list; do \
+	    relfile=`echo "$$file" | sed 's|^.*/||'`; \
+	    echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\
+	    install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\
+	  done; \
+	else : ; fi
+install-man: install-man1
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-aminfo \
+	maintainer-clean-generic maintainer-clean-vti
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-aminfo mostlyclean-generic mostlyclean-vti
+
+pdf: pdf-am
+
+pdf-am: $(PDFS)
+
+ps: ps-am
+
+ps-am: $(PSS)
+
+uninstall-am: uninstall-info-am uninstall-man uninstall-pkgdocDATA
+
+uninstall-man: uninstall-man1
+
+.PHONY: all all-am check check-am clean clean-generic dist-hook \
+	dist-info distclean distclean-generic distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-man1 install-pkgdocDATA \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-aminfo \
+	maintainer-clean-generic maintainer-clean-vti mostlyclean \
+	mostlyclean-aminfo mostlyclean-generic mostlyclean-vti pdf \
+	pdf-am ps ps-am uninstall uninstall-am uninstall-info-am \
+	uninstall-man uninstall-man1 uninstall-pkgdocDATA
+
+
+# To produce better quality output, in the example sed
+# scripts we group comments with lines following them;
+# since mantaining the "@group...@end group" manually
+# is a burden, we do this automatically
+$(srcdir)/sed.texi: sed-in.texi $(srcdir)/groupify.sed
+	sed -nf $(srcdir)/groupify.sed \
+	  < $(srcdir)/sed-in.texi > $(srcdir)/sed.texi
+
+sed.1: $(top_srcdir)/sed/sed.c $(top_srcdir)/configure.ac $(srcdir)/sed.x
+	$(HELP2MAN) --name "stream editor for filtering and transforming text" \
+	  -p sed --include $(srcdir)/sed.x $(SED) > $(srcdir)/sed.1
+
+dist-hook:
+	touch $(distdir)/sed.1
+
+@BUILD_HTML_TRUE@all: html
+
+@BUILD_HTML_TRUE@html: sed.html
+
+@BUILD_HTML_TRUE@.PHONY: html
+
+# Having a dependancy on sed.info automatically makes
+# sed.html dependant on sed.texi and all the included
+# sources
+@MAKEINFO_HTML_TRUE@sed.html: sed.texi sed.info
+@MAKEINFO_HTML_TRUE@	builddir=`pwd` && cd $(srcdir) && \
+@MAKEINFO_HTML_TRUE@	  $(MAKEINFO) --html --no-split -o $$builddir/sed.html sed.texi
+
+# These rules are used together with TEXI2HTML
+@TEXI2HTML_HTML_TRUE@sed.html: sed.texi sed.info
+@TEXI2HTML_HTML_TRUE@	cp $(srcdir)/*.texi . && \
+@TEXI2HTML_HTML_TRUE@	  $(TEXI2HTML) sed.texi && \
+@TEXI2HTML_HTML_TRUE@	  rm *.texi
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /tags/kBuild-0.1.4/src/sed/doc/config.texi
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/config.texi	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/config.texi	(revision 1780)
@@ -0,0 +1,9 @@
+@dircategory Text creation and manipulation
+@direntry
+* sed: (sed).                   Stream EDitor.
+
+@end direntry
+
+@clear PERL
+@set SSEDEXT @acronym{GNU} extensions
+@set SSED @acronym{GNU} @command{sed}
Index: /tags/kBuild-0.1.4/src/sed/doc/groupify.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/groupify.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/groupify.sed	(revision 1780)
@@ -0,0 +1,59 @@
+#! /bin/sed -nf
+# Script to add @group...@end group tags to sed.texi.in
+# so that comments are not separated from the instructions
+# that they refer to.
+
+# Step 1: search for the conventional "@c start----" comment
+1a\
+@c Do not edit this file!! It is automatically generated from sed-in.texi.
+p
+/^@c start-*$/! b
+
+# Step 2: loop until we find a @ command
+:a
+n
+p
+/^@/! ba
+
+# Step 3: process everything until a "@end" command
+
+# Step 3.1: Print the blank lines before the group.  If we reach the "@end",
+#           we go back to step 1.
+:b
+n
+/^@end/ {
+  p
+  b
+}
+/^[ 	]*$/ {
+  p
+  bb
+}
+
+# Step 3.2: Add to hold space every line until an empty one or "@end"
+h
+:c
+n
+/^@end example/! {
+  /^[ 	]*$/! {
+    H
+    bc
+  }
+}
+
+# Step 3.3: Working in hold space, add @group...@end group if there are
+#           at least two lines.  Then print the lines we processed and
+#	    switch back to pattern space.
+x
+/\n/ {
+  s/.*/@group\
+&\
+@end group/
+}
+p
+
+# Step 3.4: Switch back to pattern space, print the first blank line
+#           and possibly go back to step 3.1
+x
+p
+/^@end/ !bb
Index: /tags/kBuild-0.1.4/src/sed/doc/sed-in.texi
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/sed-in.texi	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/sed-in.texi	(revision 1780)
@@ -0,0 +1,4052 @@
+\input texinfo  @c -*-texinfo-*-
+@c
+@c -- Stuff that needs adding: ----------------------------------------------
+@c (document the `;' command-separator)
+@c --------------------------------------------------------------------------
+@c Check for consistency: regexps in @code, text that they match in @samp.
+@c 
+@c Tips:
+@c    @command for command
+@c    @samp for command fragments: @samp{cat -s}
+@c    @code for sed commands and flags
+@c    Use ``quote'' not `quote' or "quote".
+@c
+@c %**start of header
+@setfilename sed.info
+@settitle sed, a stream editor
+@c %**end of header
+
+@c @smallbook
+
+@include version.texi
+
+@c Combine indices.
+@syncodeindex ky cp
+@syncodeindex pg cp
+@syncodeindex tp cp
+
+@defcodeindex op
+@syncodeindex op fn
+
+@include config.texi
+
+@copying
+This file documents version @value{VERSION} of
+@value{SSED}, a stream editor.
+
+Copyright @copyright{} 1998, 1999, 2001, 2002, 2003, 2004 Free
+Software Foundation, Inc.
+
+This document is released under the terms of the @acronym{GNU} Free
+Documentation License as published by the Free Software Foundation;
+either version 1.1, or (at your option) any later version.
+
+You should have received a copy of the @acronym{GNU} Free Documentation
+License along with @value{SSED}; see the file @file{COPYING.DOC}.
+If not, write to the Free Software Foundation, 59 Temple Place - Suite
+330, Boston, MA 02110-1301, USA.
+
+There are no Cover Texts and no Invariant Sections; this text, along
+with its equivalent in the printed manual, constitutes the Title Page.
+@end copying
+
+@setchapternewpage off
+
+@titlepage
+@title @command{sed}, a stream editor
+@subtitle version @value{VERSION}, @value{UPDATED}
+@author by Ken Pizzini, Paolo Bonzini
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1998, 1999 Free Software Foundation, Inc.
+
+@insertcopying
+
+Published by the Free Software Foundation, @*
+51 Franklin Street, Fifth Floor @*
+Boston, MA 02110-1301, USA
+@end titlepage
+
+
+@node Top
+@top
+
+@ifnottex
+@insertcopying
+@end ifnottex
+
+@menu
+* Introduction::               Introduction
+* Invoking sed::               Invocation
+* sed Programs::               @command{sed} programs
+* Examples::                   Some sample scripts
+* Limitations::                Limitations and (non-)limitations of @value{SSED}
+* Other Resources::            Other resources for learning about @command{sed}
+* Reporting Bugs::             Reporting bugs
+
+* Extended regexps::           @command{egrep}-style regular expressions
+@ifset PERL
+* Perl regexps::               Perl-style regular expressions
+@end ifset
+
+* Concept Index::              A menu with all the topics in this manual.
+* Command and Option Index::   A menu with all @command{sed} commands and
+                               command-line options.
+
+@detailmenu
+--- The detailed node listing ---
+
+sed Programs:
+* Execution Cycle::                 How @command{sed} works
+* Addresses::                       Selecting lines with @command{sed}
+* Regular Expressions::             Overview of regular expression syntax
+* Common Commands::                 Often used commands
+* The "s" Command::                 @command{sed}'s Swiss Army Knife
+* Other Commands::                  Less frequently used commands
+* Programming Commands::            Commands for @command{sed} gurus
+* Extended Commands::               Commands specific of @value{SSED}
+* Escapes::                         Specifying special characters
+
+Examples:
+* Centering lines::
+* Increment a number::
+* Rename files to lower case::
+* Print bash environment::
+* Reverse chars of lines::
+* tac::                             Reverse lines of files
+* cat -n::                          Numbering lines
+* cat -b::                          Numbering non-blank lines
+* wc -c::                           Counting chars
+* wc -w::                           Counting words
+* wc -l::                           Counting lines
+* head::                            Printing the first lines
+* tail::                            Printing the last lines
+* uniq::                            Make duplicate lines unique
+* uniq -d::                         Print duplicated lines of input
+* uniq -u::                         Remove all duplicated lines
+* cat -s::                          Squeezing blank lines
+
+@ifset PERL
+Perl regexps::                      Perl-style regular expressions
+* Backslash::                       Introduces special sequences
+* Circumflex/dollar sign/period::   Behave specially with regard to new lines
+* Square brackets::                 Are a bit different in strange cases
+* Options setting::                 Toggle modifiers in the middle of a regexp
+* Non-capturing subpatterns::       Are not counted when backreferencing
+* Repetition::                      Allows for non-greedy matching
+* Backreferences::                  Allows for more than 10 back references
+* Assertions::                      Allows for complex look ahead matches
+* Non-backtracking subpatterns::    Often gives more performance
+* Conditional subpatterns::         Allows if/then/else branches
+* Recursive patterns::              For example to match parentheses
+* Comments::                        Because things can get complex...
+@end ifset
+
+@end detailmenu
+@end menu
+
+
+@node Introduction
+@chapter Introduction
+
+@cindex Stream editor
+@command{sed} is a stream editor.
+A stream editor is used to perform basic text
+transformations on an input stream
+(a file or input from a pipeline).
+While in some ways similar to an editor which
+permits scripted edits (such as @command{ed}),
+@command{sed} works by making only one pass over the
+input(s), and is consequently more efficient.
+But it is @command{sed}'s ability to filter text in a pipeline
+which particularly distinguishes it from other types of
+editors.
+
+
+@node Invoking sed
+@chapter Invocation
+
+Normally @command{sed} is invoked like this:
+
+@example
+sed SCRIPT INPUTFILE...
+@end example
+
+The full format for invoking @command{sed} is:
+
+@example
+sed OPTIONS... [SCRIPT] [INPUTFILE...]
+@end example
+
+If you do not specify @var{INPUTFILE}, or if @var{INPUTFILE} is @file{-},
+@command{sed} filters the contents of the standard input.  The @var{script}
+is actually the first non-option parameter, which @command{sed} specially
+considers a script and not an input file if (and only if) none of the
+other @var{options} specifies a script to be executed, that is if neither
+of the @option{-e} and @option{-f} options is specified.
+
+@command{sed} may be invoked with the following command-line options:
+
+@table @code
+@item --version
+@opindex --version
+@cindex Version, printing
+Print out the version of @command{sed} that is being run and a copyright notice,
+then exit.
+
+@item --help
+@opindex --help
+@cindex Usage summary, printing
+Print a usage message briefly summarizing these command-line options
+and the bug-reporting address,
+then exit.
+
+@item -n
+@itemx --quiet
+@itemx --silent
+@opindex -n
+@opindex --quiet
+@opindex --silent
+@cindex Disabling autoprint, from command line
+By default, @command{sed} prints out the pattern space
+at the end of each cycle through the script.
+These options disable this automatic printing,
+and @command{sed} only produces output when explicitly told to
+via the @code{p} command.
+
+@item -i[@var{SUFFIX}]
+@itemx --in-place[=@var{SUFFIX}]
+@opindex -i
+@opindex --in-place
+@cindex In-place editing, activating
+@cindex @value{SSEDEXT}, in-place editing
+This option specifies that files are to be edited in-place.
+@value{SSED} does this by creating a temporary file and
+sending output to this file rather than to the standard
+output.@footnote{This applies to commands such as @code{=},
+@code{a}, @code{c}, @code{i}, @code{l}, @code{p}.  You can
+still write to the standard output by using the @code{w}
+@cindex @value{SSEDEXT}, @file{/dev/stdout} file
+or @code{W} commands together with the @file{/dev/stdout}
+special file}.
+
+This option implies @option{-s}.
+
+When the end of the file is reached, the temporary file is
+renamed to the output file's original name.  The extension,
+if supplied, is used to modify the name of the old file
+before renaming the temporary file, thereby making a backup
+copy@footnote{Note that @value{SSED} creates the backup
+    file whether or not any output is actually changed.}).
+
+@cindex In-place editing, Perl-style backup file names
+This rule is followed: if the extension doesn't contain a @code{*},
+then it is appended to the end of the current filename as a
+suffix; if the extension does contain one or more @code{*}
+characters, then @emph{each} asterisk is replaced with the
+current filename.  This allows you to add a prefix to the
+backup file, instead of (or in addition to) a suffix, or
+even to place backup copies of the original files into another
+directory (provided the directory already exists).
+
+If no extension is supplied, the original file is
+overwritten without making a backup.
+
+@item -l @var{N}
+@itemx --line-length=@var{N}
+@opindex -l
+@opindex --line-length
+@cindex Line length, setting
+Specify the default line-wrap length for the @code{l} command.
+A length of 0 (zero) means to never wrap long lines.  If
+not specified, it is taken to be 70.
+
+@item --posix
+@cindex @value{SSEDEXT}, disabling
+@value{SSED} includes several extensions to @acronym{POSIX}
+sed.  In order to simplify writing portable scripts, this
+option disables all the extensions that this manual documents,
+including additional commands.
+@cindex @code{POSIXLY_CORRECT} behavior, enabling
+Most of the extensions accept @command{sed} programs that
+are outside the syntax mandated by @acronym{POSIX}, but some
+of them (such as the behavior of the @command{N} command
+described in @pxref{Reporting Bugs}) actually violate the
+standard.  If you want to disable only the latter kind of
+extension, you can set the @code{POSIXLY_CORRECT} variable
+to a non-empty value.
+
+@item -r
+@itemx --regexp-extended
+@opindex -r
+@opindex --regexp-extended
+@cindex Extended regular expressions, choosing
+@cindex @acronym{GNU} extensions, extended regular expressions
+Use extended regular expressions rather than basic
+regular expressions.  Extended regexps are those that
+@command{egrep} accepts; they can be clearer because they
+usually have less backslashes, but are a @acronym{GNU} extension
+and hence scripts that use them are not portable.
+@xref{Extended regexps, , Extended regular expressions}.
+
+@ifset PERL
+@item -R
+@itemx --regexp-perl
+@opindex -R
+@opindex --regexp-perl
+@cindex Perl-style regular expressions, choosing
+@cindex @value{SSEDEXT}, Perl-style regular expressions
+Use Perl-style regular expressions rather than basic
+regular expressions.  Perl-style regexps are extremely
+powerful but are a @value{SSED} extension and hence scripts that
+use it are not portable.  @xref{Perl regexps, ,
+Perl-style regular expressions}.
+@end ifset
+
+@item -s
+@itemx --separate
+@cindex Working on separate files
+By default, @command{sed} will consider the files specified on the
+command line as a single continuous long stream.  This @value{SSED}
+extension allows the user to consider them as separate files:
+range addresses (such as @samp{/abc/,/def/}) are not allowed
+to span several files, line numbers are relative to the start
+of each file, @code{$} refers to the last line of each file,
+and files invoked from the @code{R} commands are rewound at the
+start of each file.
+
+@item -u
+@itemx --unbuffered
+@opindex -u
+@opindex --unbuffered
+@cindex Unbuffered I/O, choosing
+Buffer both input and output as minimally as practical.
+(This is particularly useful if the input is coming from
+the likes of @samp{tail -f}, and you wish to see the transformed
+output as soon as possible.)
+
+@item -e @var{script}
+@itemx --expression=@var{script}
+@opindex -e
+@opindex --expression
+@cindex Script, from command line
+Add the commands in @var{script} to the set of commands to be
+run while processing the input.
+
+@item -f @var{script-file}
+@itemx --file=@var{script-file}
+@opindex -f
+@opindex --file
+@cindex Script, from a file
+Add the commands contained in the file @var{script-file}
+to the set of commands to be run while processing the input.
+
+@end table
+
+If no @option{-e}, @option{-f}, @option{--expression}, or @option{--file}
+options are given on the command-line,
+then the first non-option argument on the command line is
+taken to be the @var{script} to be executed.
+
+@cindex Files to be processed as input
+If any command-line parameters remain after processing the above,
+these parameters are interpreted as the names of input files to
+be processed.
+@cindex Standard input, processing as input
+A file name of @samp{-} refers to the standard input stream.
+The standard input will be processed if no file names are specified.
+
+
+@node sed Programs
+@chapter @command{sed} Programs
+
+@cindex @command{sed} program structure
+@cindex Script structure
+A @command{sed} program consists of one or more @command{sed} commands,
+passed in by one or more of the
+@option{-e}, @option{-f}, @option{--expression}, and @option{--file}
+options, or the first non-option argument if zero of these
+options are used.
+This document will refer to ``the'' @command{sed} script;
+this is understood to mean the in-order catenation
+of all of the @var{script}s and @var{script-file}s passed in.
+
+Each @code{sed} command consists of an optional address or
+address range, followed by a one-character command name
+and any additional command-specific code.
+
+@menu
+* Execution Cycle::          How @command{sed} works
+* Addresses::                Selecting lines with @command{sed}
+* Regular Expressions::      Overview of regular expression syntax
+* Common Commands::          Often used commands
+* The "s" Command::          @command{sed}'s Swiss Army Knife
+* Other Commands::           Less frequently used commands
+* Programming Commands::     Commands for @command{sed} gurus
+* Extended Commands::        Commands specific of @value{SSED}
+* Escapes::                  Specifying special characters
+@end menu
+
+
+@node Execution Cycle
+@section How @command{sed} Works
+
+@cindex Buffer spaces, pattern and hold
+@cindex Spaces, pattern and hold
+@cindex Pattern space, definition
+@cindex Hold space, definition
+@command{sed} maintains two data buffers: the active @emph{pattern} space,
+and the auxiliary @emph{hold} space. Both are initially empty.
+
+@command{sed} operates by performing the following cycle on each
+lines of input: first, @command{sed} reads one line from the input
+stream, removes any trailing newline, and places it in the pattern space.
+Then commands are executed; each command can have an address associated
+to it: addresses are a kind of condition code, and a command is only
+executed if the condition is verified before the command is to be
+executed.
+
+When the end of the script is reached, unless the @option{-n} option
+is in use, the contents of pattern space are printed out to the output
+stream, adding back the trailing newline if it was removed.@footnote{Actually,
+  if @command{sed} prints a line without the terminating newline, it will
+  nevertheless print the missing newline as soon as more text is sent to
+  the same output stream, which gives the ``least expected surprise''
+  even though it does not make commands like @samp{sed -n p} exactly
+  identical to @command{cat}.} Then the next cycle starts for the next
+input line.
+
+Unless special commands (like @samp{D}) are used, the pattern space is
+deleted between two cycles. The hold space, on the other hand, keeps
+its data between cycles (see commands @samp{h}, @samp{H}, @samp{x},
+@samp{g}, @samp{G} to move data between both buffers).
+
+
+@node Addresses
+@section Selecting lines with @command{sed}
+@cindex Addresses, in @command{sed} scripts
+@cindex Line selection
+@cindex Selecting lines to process
+
+Addresses in a @command{sed} script can be in any of the following forms:
+@table @code
+@item @var{number}
+@cindex Address, numeric
+@cindex Line, selecting by number
+Specifying a line number will match only that line in the input.
+(Note that @command{sed} counts lines continuously across all input files
+unless @option{-i} or @option{-s} options are specified.)
+
+@item @var{first}~@var{step}
+@cindex @acronym{GNU} extensions, @samp{@var{n}~@var{m}} addresses
+This @acronym{GNU} extension matches every @var{step}th line
+starting with line @var{first}.
+In particular, lines will be selected when there exists
+a non-negative @var{n} such that the current line-number equals
+@var{first} + (@var{n} * @var{step}).
+Thus, to select the odd-numbered lines,
+one would use @code{1~2};
+to pick every third line starting with the second, @samp{2~3} would be used;
+to pick every fifth line starting with the tenth, use @samp{10~5};
+and @samp{50~0} is just an obscure way of saying @code{50}.
+
+@item $
+@cindex Address, last line
+@cindex Last line, selecting
+@cindex Line, selecting last
+This address matches the last line of the last file of input, or
+the last line of each file when the @option{-i} or @option{-s} options
+are specified.
+
+@item /@var{regexp}/
+@cindex Address, as a regular expression
+@cindex Line, selecting by regular expression match
+This will select any line which matches the regular expression @var{regexp}.
+If @var{regexp} itself includes any @code{/} characters,
+each must be escaped by a backslash (@code{\}).
+
+@cindex empty regular expression
+@cindex @value{SSEDEXT}, modifiers and the empty regular expression
+The empty regular expression @samp{//} repeats the last regular
+expression match (the same holds if the empty regular expression is
+passed to the @code{s} command).  Note that modifiers to regular expressions
+are evaluated when the regular expression is compiled, thus it is invalid to
+specify them together with the empty regular expression.
+
+@item \%@var{regexp}%
+(The @code{%} may be replaced by any other single character.)
+
+@cindex Slash character, in regular expressions
+This also matches the regular expression @var{regexp},
+but allows one to use a different delimiter than @code{/}.
+This is particularly useful if the @var{regexp} itself contains
+a lot of slashes, since it avoids the tedious escaping of every @code{/}.
+If @var{regexp} itself includes any delimiter characters,
+each must be escaped by a backslash (@code{\}).
+
+@item /@var{regexp}/I
+@itemx \%@var{regexp}%I
+@cindex @acronym{GNU} extensions, @code{I} modifier
+@ifset PERL
+@cindex Perl-style regular expressions, case-insensitive
+@end ifset
+The @code{I} modifier to regular-expression matching is a @acronym{GNU}
+extension which causes the @var{regexp} to be matched in
+a case-insensitive manner.
+
+@item /@var{regexp}/M
+@itemx \%@var{regexp}%M
+@ifset PERL
+@cindex @value{SSEDEXT}, @code{M} modifier
+@end ifset
+@cindex Perl-style regular expressions, multiline
+The @code{M} modifier to regular-expression matching is a @value{SSED}
+extension which causes @code{^} and @code{$} to match respectively
+(in addition to the normal behavior) the empty string after a newline,
+and the empty string before a newline.  There are special character
+sequences
+@ifset PERL
+(@code{\A} and @code{\Z} in Perl mode, @code{\`} and @code{\'}
+in basic or extended regular expression modes)
+@end ifset
+@ifclear PERL
+(@code{\`} and @code{\'})
+@end ifclear
+which always match the beginning or the end of the buffer.
+@code{M} stands for @cite{multi-line}.
+
+@ifset PERL
+@item /@var{regexp}/S
+@itemx \%@var{regexp}%S
+@cindex @value{SSEDEXT}, @code{S} modifier
+@cindex Perl-style regular expressions, single line
+The @code{S} modifier to regular-expression matching is only valid
+in Perl mode and specifies that the dot character (@code{.}) will
+match the newline character too.  @code{S} stands for @cite{single-line}.
+@end ifset
+
+@ifset PERL
+@item /@var{regexp}/X
+@itemx \%@var{regexp}%X
+@cindex @value{SSEDEXT}, @code{X} modifier
+@cindex Perl-style regular expressions, extended
+The @code{X} modifier to regular-expression matching is also
+valid in Perl mode only.  If it is used, whitespace in the
+pattern (other than in a character class) and
+characters between a @kbd{#} outside a character class and the
+next newline character are ignored. An escaping backslash
+can be used to include a whitespace or @kbd{#} character as part
+of the pattern.
+@end ifset
+@end table
+
+If no addresses are given, then all lines are matched;
+if one address is given, then only lines matching that
+address are matched.
+
+@cindex Range of lines
+@cindex Several lines, selecting
+An address range can be specified by specifying two addresses
+separated by a comma (@code{,}).  An address range matches lines
+starting from where the first address matches, and continues
+until the second address matches (inclusively).
+
+If the second address is a @var{regexp}, then checking for the
+ending match will start with the line @emph{following} the
+line which matched the first address: a range will always
+span at least two lines (except of course if the input stream
+ends).
+
+If the second address is a @var{number} less than (or equal to)
+the line matching the first address, then only the one line is
+matched.
+
+@cindex Special addressing forms
+@cindex Range with start address of zero
+@cindex Zero, as range start address
+@cindex @var{addr1},+N
+@cindex @var{addr1},~N
+@cindex @acronym{GNU} extensions, special two-address forms
+@cindex @acronym{GNU} extensions, @code{0} address
+@cindex @acronym{GNU} extensions, 0,@var{addr2} addressing
+@cindex @acronym{GNU} extensions, @var{addr1},+@var{N} addressing
+@cindex @acronym{GNU} extensions, @var{addr1},~@var{N} addressing
+@value{SSED} also supports some special two-address forms; all these
+are @acronym{GNU} extensions:
+@table @code
+@item 0,/@var{regexp}/
+A line number of @code{0} can be used in an address specification like
+@code{0,/@var{regexp}/} so that @command{sed} will try to match
+@var{regexp} in the first input line too.  In other words,
+@code{0,/@var{regexp}/} is similar to @code{1,/@var{regexp}/},
+except that if @var{addr2} matches the very first line of input the
+@code{0,/@var{regexp}/} form will consider it to end the range, whereas
+the @code{1,/@var{regexp}/} form will match the beginning of its range and
+hence make the range span up to the @emph{second} occurrence of the
+regular expression.
+
+Note that this is the only place where the @code{0} address makes
+sense; there is no 0-th line and commands which are given the @code{0}
+address in any other way will give an error.
+
+@item @var{addr1},+@var{N}
+Matches @var{addr1} and the @var{N} lines following @var{addr1}.
+
+@item @var{addr1},~@var{N}
+Matches @var{addr1} and the lines following @var{addr1}
+until the next line whose input line number is a multiple of @var{N}.
+@end table
+
+@cindex Excluding lines
+@cindex Selecting non-matching lines
+Appending the @code{!} character to the end of an address
+specification negates the sense of the match.
+That is, if the @code{!} character follows an address range,
+then only lines which do @emph{not} match the address range
+will be selected.
+This also works for singleton addresses,
+and, perhaps perversely, for the null address.
+
+
+@node Regular Expressions
+@section Overview of Regular Expression Syntax
+
+To know how to use @command{sed}, people should understand regular
+expressions (@dfn{regexp} for short).  A regular expression
+is a pattern that is matched against a
+subject string from left to right.  Most characters are
+@dfn{ordinary}: they stand for
+themselves in a pattern, and match the corresponding characters
+in the subject.  As a trivial example, the pattern
+
+@example
+     The quick brown fox
+@end example
+
+@noindent
+matches a portion of a subject string that is identical to
+itself.  The power of regular expressions comes from the
+ability to include alternatives and repetitions in the pattern.
+These are encoded in the pattern by the use of @dfn{special characters},
+which do not stand for themselves but instead
+are interpreted in some special way.  Here is a brief description
+of regular expression syntax as used in @command{sed}.
+
+@table @code
+@item @var{char}
+A single ordinary character matches itself.
+
+@item *
+@cindex @acronym{GNU} extensions, to basic regular expressions
+Matches a sequence of zero or more instances of matches for the
+preceding regular expression, which must be an ordinary character, a
+special character preceded by @code{\}, a @code{.}, a grouped regexp
+(see below), or a bracket expression.  As a @acronym{GNU} extension, a
+postfixed regular expression can also be followed by @code{*}; for
+example, @code{a**} is equivalent to @code{a*}.  @acronym{POSIX}
+1003.1-2001 says that @code{*} stands for itself when it appears at
+the start of a regular expression or subexpression, but many
+non@acronym{GNU} implementations do not support this and portable
+scripts should instead use @code{\*} in these contexts.
+
+@item \+
+@cindex @acronym{GNU} extensions, to basic regular expressions
+As @code{*}, but matches one or more.  It is a @acronym{GNU} extension.
+
+@item \?
+@cindex @acronym{GNU} extensions, to basic regular expressions
+As @code{*}, but only matches zero or one.  It is a @acronym{GNU} extension.
+
+@item \@{@var{i}\@}
+As @code{*}, but matches exactly @var{i} sequences (@var{i} is a
+decimal integer; for portability, keep it between 0 and 255
+inclusive).
+
+@item \@{@var{i},@var{j}\@}
+Matches between @var{i} and @var{j}, inclusive, sequences.
+
+@item \@{@var{i},\@}
+Matches more than or equal to @var{i} sequences.
+
+@item \(@var{regexp}\)
+Groups the inner @var{regexp} as a whole, this is used to: 
+
+@itemize @bullet
+@item
+@cindex @acronym{GNU} extensions, to basic regular expressions
+Apply postfix operators, like @code{\(abcd\)*}:
+this will search for zero or more whole sequences 
+of @samp{abcd}, while @code{abcd*} would search
+for @samp{abc} followed by zero or more occurrences
+of @samp{d}.  Note that support for @code{\(abcd\)*} is
+required by @acronym{POSIX} 1003.1-2001, but many non-@acronym{GNU}
+implementations do not support it and hence it is not universally
+portable.         
+
+@item
+Use back references (see below).
+@end itemize
+
+@item .
+Matches any character, including newline.
+
+@item ^
+Matches the null string at beginning of line, i.e. what
+appears after the circumflex must appear at the 
+beginning of line. @code{^#include} will match only 
+lines where @samp{#include} is the first thing on line---if
+there are spaces before, for example, the match fails.
+@code{^} acts as a special character only at the beginning
+of the regular expression or subexpression (that is,
+after @code{\(} or @code{\|}).  Portable scripts should avoid
+@code{^} at the beginning of a subexpression, though, as
+@acronym{POSIX} allows implementations that treat @code{^} as
+an ordinary character in that context.
+
+
+@item $
+It is the same as @code{^}, but refers to end of line.
+@code{$} also acts as a special character only at the end
+of the regular expression or subexpression (that is, before @code{\)}
+or @code{\|}), and its use at the end of a subexpression is not
+portable.
+
+
+@item [@var{list}]
+@itemx [^@var{list}]
+Matches any single character in @var{list}: for example,
+@code{[aeiou]} matches all vowels.  A list may include
+sequences like @code{@var{char1}-@var{char2}}, which
+matches any character between (inclusive) @var{char1}
+and @var{char2}.
+
+A leading @code{^} reverses the meaning of @var{list}, so that
+it matches any single character @emph{not} in @var{list}.  To include
+@code{]} in the list, make it the first character (after
+the @code{^} if needed), to include @code{-} in the list,
+make it the first or last; to include @code{^} put
+it after the first character.
+
+@cindex @code{POSIXLY_CORRECT} behavior, bracket expressions
+The characters @code{$}, @code{*}, @code{.}, @code{[}, and @code{\}
+are normally not special within @var{list}.  For example, @code{[\*]}
+matches either @samp{\} or @samp{*}, because the @code{\} is not
+special here.  However, strings like @code{[.ch.]}, @code{[=a=]}, and
+@code{[:space:]} are special within @var{list} and represent collating
+symbols, equivalence classes, and character classes, respectively, and
+@code{[} is therefore special within @var{list} when it is followed by
+@code{.}, @code{=}, or @code{:}.  Also, when not in
+@env{POSIXLY_CORRECT} mode, special escapes like @code{\n} and
+@code{\t} are recognized within @var{list}.  @xref{Escapes}.
+
+@item @var{regexp1}\|@var{regexp2}
+@cindex @acronym{GNU} extensions, to basic regular expressions
+Matches either @var{regexp1} or @var{regexp2}.  Use
+parentheses to use complex alternative regular expressions.
+The matching process tries each alternative in turn, from
+left to right, and the first one that succeeds is used.
+It is a @acronym{GNU} extension.
+
+@item @var{regexp1}@var{regexp2}
+Matches the concatenation of @var{regexp1} and @var{regexp2}.
+Concatenation binds more tightly than @code{\|}, @code{^}, and
+@code{$}, but less tightly than the other regular expression
+operators.
+
+@item \@var{digit}
+Matches the @var{digit}-th @code{\(@dots{}\)} parenthesized
+subexpression in the regular expression.  This is called a @dfn{back
+reference}.  Subexpressions are implicity numbered by counting
+occurrences of @code{\(} left-to-right.
+
+@item \n
+Matches the newline character.
+
+@item \@var{char}
+Matches @var{char}, where @var{char} is one of @code{$},
+@code{*}, @code{.}, @code{[}, @code{\}, or @code{^}.
+Note that the only C-like
+backslash sequences that you can portably assume to be
+interpreted are @code{\n} and @code{\\}; in particular
+@code{\t} is not portable, and matches a @samp{t} under most
+implementations of @command{sed}, rather than a tab character.
+
+@end table
+
+@cindex Greedy regular expression matching
+Note that the regular expression matcher is greedy, i.e., matches
+are attempted from left to right and, if two or more matches are
+possible starting at the same character, it selects the longest.
+
+@noindent
+Examples:
+@table @samp
+@item abcdef
+Matches @samp{abcdef}.
+
+@item a*b
+Matches zero or more @samp{a}s followed by a single
+@samp{b}.  For example, @samp{b} or @samp{aaaaab}. 
+
+@item a\?b
+Matches @samp{b} or @samp{ab}.
+
+@item a\+b\+
+Matches one or more @samp{a}s followed by one or more
+@samp{b}s: @samp{ab} is the shortest possible match, but
+other examples are @samp{aaaab} or @samp{abbbbb} or
+@samp{aaaaaabbbbbbb}.
+
+@item .*
+@itemx .\+
+These two both match all the characters in a string;
+however, the first matches every string (including the empty
+string), while the second matches only strings containing
+at least one character.
+
+@item ^main.*(.*)
+his matches a string starting with @samp{main},
+followed by an opening and closing
+parenthesis.  The @samp{n}, @samp{(} and @samp{)} need not
+be adjacent.
+
+@item ^#
+This matches a string beginning with @samp{#}.
+
+@item \\$
+This matches a string ending with a single backslash.  The
+regexp contains two backslashes for escaping.
+
+@item \$
+Instead, this matches a string consisting of a single dollar sign,
+because it is escaped.
+
+@item [a-zA-Z0-9]
+In the C locale, this matches any @acronym{ASCII} letters or digits.
+
+@item [^ @kbd{tab}]\+
+(Here @kbd{tab} stands for a single tab character.)
+This matches a string of one or more
+characters, none of which is a space or a tab.
+Usually this means a word.
+
+@item ^\(.*\)\n\1$
+This matches a string consisting of two equal substrings separated by
+a newline.
+
+@item .\@{9\@}A$
+This matches nine characters followed by an @samp{A}.
+
+@item ^.\@{15\@}A
+This matches the start of a string that contains 16 characters,
+the last of which is an @samp{A}.
+
+@end table
+
+
+
+@node Common Commands
+@section Often-Used Commands
+
+If you use @command{sed} at all, you will quite likely want to know
+these commands.
+
+@table @code
+@item #
+[No addresses allowed.]
+
+@findex # (comments)
+@cindex Comments, in scripts
+The @code{#} character begins a comment;
+the comment continues until the next newline.
+
+@cindex Portability, comments
+If you are concerned about portability, be aware that
+some implementations of @command{sed} (which are not @sc{posix}
+conformant) may only support a single one-line comment,
+and then only when the very first character of the script is a @code{#}.
+
+@findex -n, forcing from within a script
+@cindex Caveat --- #n on first line
+Warning: if the first two characters of the @command{sed} script
+are @code{#n}, then the @option{-n} (no-autoprint) option is forced.
+If you want to put a comment in the first line of your script
+and that comment begins with the letter @samp{n}
+and you do not want this behavior,
+then be sure to either use a capital @samp{N},
+or place at least one space before the @samp{n}.
+
+@item q [@var{exit-code}]
+This command only accepts a single address.
+
+@findex q (quit) command
+@cindex @value{SSEDEXT}, returning an exit code
+@cindex Quitting
+Exit @command{sed} without processing any more commands or input.
+Note that the current pattern space is printed if auto-print is
+not disabled with the @option{-n} options.  The ability to return
+an exit code from the @command{sed} script is a @value{SSED} extension.
+
+@item d
+@findex d (delete) command
+@cindex Text, deleting
+Delete the pattern space;
+immediately start next cycle.
+
+@item p
+@findex p (print) command
+@cindex Text, printing
+Print out the pattern space (to the standard output).
+This command is usually only used in conjunction with the @option{-n}
+command-line option.
+
+@item n
+@findex n (next-line) command
+@cindex Next input line, replace pattern space with
+@cindex Read next input line
+If auto-print is not disabled, print the pattern space,
+then, regardless, replace the pattern space with the next line of input.
+If there is no more input then @command{sed} exits without processing
+any more commands.
+
+@item @{ @var{commands} @}
+@findex @{@} command grouping
+@cindex Grouping commands
+@cindex Command groups
+A group of commands may be enclosed between
+@code{@{} and @code{@}} characters.
+This is particularly useful when you want a group of commands
+to be triggered by a single address (or address-range) match.
+
+@end table
+
+@node The "s" Command
+@section The @code{s} Command
+
+The syntax of the @code{s} (as in substitute) command is
+@samp{s/@var{regexp}/@var{replacement}/@var{flags}}.  The @code{/}
+characters may be uniformly replaced by any other single
+character within any given @code{s} command.  The @code{/}
+character (or whatever other character is used in its stead)
+can appear in the @var{regexp} or @var{replacement}
+only if it is preceded by a @code{\} character.
+
+The @code{s} command is probably the most important in @command{sed}
+and has a lot of different options.  Its basic concept is simple:
+the @code{s} command attempts to match the pattern
+space against the supplied @var{regexp}; if the match is
+successful, then that portion of the pattern
+space which was matched is replaced with @var{replacement}.
+
+@cindex Backreferences, in regular expressions
+@cindex Parenthesized substrings
+The @var{replacement} can contain @code{\@var{n}} (@var{n} being
+a number from 1 to 9, inclusive) references, which refer to
+the portion of the match which is contained between the @var{n}th
+@code{\(} and its matching @code{\)}.
+Also, the @var{replacement} can contain unescaped @code{&}
+characters which reference the whole matched portion
+of the pattern space.
+@cindex @value{SSEDEXT}, case modifiers in @code{s} commands
+Finally, as a @value{SSED} extension, you can include a
+special sequence made of a backslash and one of the letters
+@code{L}, @code{l}, @code{U}, @code{u}, or @code{E}.
+The meaning is as follows:
+
+@table @code
+@item \L
+Turn the replacement
+to lowercase until a @code{\U} or @code{\E} is found,
+
+@item \l
+Turn the
+next character to lowercase,
+
+@item \U
+Turn the replacement to uppercase
+until a @code{\L} or @code{\E} is found,
+
+@item \u
+Turn the next character
+to uppercase,
+
+@item \E
+Stop case conversion started by @code{\L} or @code{\U}.
+@end table
+
+To include a literal @code{\}, @code{&}, or newline in the final
+replacement, be sure to precede the desired @code{\}, @code{&},
+or newline in the @var{replacement} with a @code{\}.
+
+@findex s command, option flags
+@cindex Substitution of text, options
+The @code{s} command can be followed by zero or more of the
+following @var{flags}:
+
+@table @code
+@item g
+@cindex Global substitution
+@cindex Replacing all text matching regexp in a line
+Apply the replacement to @emph{all} matches to the @var{regexp},
+not just the first.
+
+@item @var{number}
+@cindex Replacing only @var{n}th match of regexp in a line
+Only replace the @var{number}th match of the @var{regexp}.
+
+@cindex @acronym{GNU} extensions, @code{g} and @var{number} modifier interaction in @code{s} command
+@cindex Mixing @code{g} and @var{number} modifiers in the @code{s} command
+Note: the @sc{posix} standard does not specify what should happen
+when you mix the @code{g} and @var{number} modifiers,
+and currently there is no widely agreed upon meaning
+across @command{sed} implementations.
+For @value{SSED}, the interaction is defined to be:
+ignore matches before the @var{number}th,
+and then match and replace all matches from
+the @var{number}th on.
+
+@item p
+@cindex Text, printing after substitution
+If the substitution was made, then print the new pattern space.
+
+Note: when both the @code{p} and @code{e} options are specified,
+the relative ordering of the two produces very different results.
+In general, @code{ep} (evaluate then print) is what you want,
+but operating the other way round can be useful for debugging.
+For this reason, the current version of @value{SSED} interprets
+specially the presence of @code{p} options both before and after
+@code{e}, printing the pattern space before and after evaluation,
+while in general flags for the @code{s} command show their
+effect just once.  This behavior, although documented, might
+change in future versions.
+
+@item w @var{file-name}
+@cindex Text, writing to a file after substitution
+@cindex @value{SSEDEXT}, @file{/dev/stdout} file
+@cindex @value{SSEDEXT}, @file{/dev/stderr} file
+If the substitution was made, then write out the result to the named file.
+As a @value{SSED} extension, two special values of @var{file-name} are
+supported: @file{/dev/stderr}, which writes the result to the standard
+error, and @file{/dev/stdout}, which writes to the standard
+output.@footnote{This is equivalent to @code{p} unless the @option{-i}
+option is being used.}
+
+@item e
+@cindex Evaluate Bourne-shell commands, after substitution
+@cindex Subprocesses
+@cindex @value{SSEDEXT}, evaluating Bourne-shell commands
+@cindex @value{SSEDEXT}, subprocesses
+This command allows one to pipe input from a shell command
+into pattern space.  If a substitution was made, the command
+that is found in pattern space is executed and pattern space
+is replaced with its output.  A trailing newline is suppressed;
+results are undefined if the command to be executed contains
+a @sc{nul} character.  This is a @value{SSED} extension.
+
+@item I
+@itemx i
+@cindex @acronym{GNU} extensions, @code{I} modifier
+@cindex Case-insensitive matching
+@ifset PERL
+@cindex Perl-style regular expressions, case-insensitive
+@end ifset
+The @code{I} modifier to regular-expression matching is a @acronym{GNU}
+extension which makes @command{sed} match @var{regexp} in a
+case-insensitive manner.
+
+@item M
+@itemx m
+@cindex @value{SSEDEXT}, @code{M} modifier
+@ifset PERL
+@cindex Perl-style regular expressions, multiline
+@end ifset
+The @code{M} modifier to regular-expression matching is a @value{SSED}
+extension which causes @code{^} and @code{$} to match respectively
+(in addition to the normal behavior) the empty string after a newline,
+and the empty string before a newline.  There are special character
+sequences
+@ifset PERL
+(@code{\A} and @code{\Z} in Perl mode, @code{\`} and @code{\'}
+in basic or extended regular expression modes)
+@end ifset
+@ifclear PERL
+(@code{\`} and @code{\'})
+@end ifclear
+which always match the beginning or the end of the buffer.
+@code{M} stands for @cite{multi-line}.
+
+@ifset PERL
+@item S
+@itemx s
+@cindex @value{SSEDEXT}, @code{S} modifier
+@cindex Perl-style regular expressions, single line
+The @code{S} modifier to regular-expression matching is only valid
+in Perl mode and specifies that the dot character (@code{.}) will
+match the newline character too.  @code{S} stands for @cite{single-line}.
+@end ifset
+
+@ifset PERL
+@item X
+@itemx x
+@cindex @value{SSEDEXT}, @code{X} modifier
+@cindex Perl-style regular expressions, extended
+The @code{X} modifier to regular-expression matching is also
+valid in Perl mode only.  If it is used, whitespace in the
+pattern (other than in a character class) and
+characters between a @kbd{#} outside a character class and the
+next newline character are ignored. An escaping backslash
+can be used to include a whitespace or @kbd{#} character as part
+of the pattern.
+@end ifset
+@end table
+
+
+@node Other Commands
+@section Less Frequently-Used Commands
+
+Though perhaps less frequently used than those in the previous
+section, some very small yet useful @command{sed} scripts can be built with
+these commands.
+
+@table @code
+@item y/@var{source-chars}/@var{dest-chars}/
+(The @code{/} characters may be uniformly replaced by
+any other single character within any given @code{y} command.)
+
+@findex y (transliterate) command
+@cindex Transliteration
+Transliterate any characters in the pattern space which match
+any of the @var{source-chars} with the corresponding character
+in @var{dest-chars}.
+
+Instances of the @code{/} (or whatever other character is used in its stead),
+@code{\}, or newlines can appear in the @var{source-chars} or @var{dest-chars}
+lists, provide that each instance is escaped by a @code{\}.
+The @var{source-chars} and @var{dest-chars} lists @emph{must}
+contain the same number of characters (after de-escaping).
+
+@item a\
+@itemx @var{text}
+@cindex @value{SSEDEXT}, two addresses supported by most commands
+As a @acronym{GNU} extension, this command accepts two addresses.
+
+@findex a (append text lines) command
+@cindex Appending text after a line
+@cindex Text, appending
+Queue the lines of text which follow this command
+(each but the last ending with a @code{\},
+which are removed from the output)
+to be output at the end of the current cycle,
+or when the next input line is read.
+
+Escape sequences in @var{text} are processed, so you should
+use @code{\\} in @var{text} to print a single backslash.
+
+As a @acronym{GNU} extension, if between the @code{a} and the newline there is
+other than a whitespace-@code{\} sequence, then the text of this line,
+starting at the first non-whitespace character after the @code{a},
+is taken as the first line of the @var{text} block.
+(This enables a simplification in scripting a one-line add.)
+This extension also works with the @code{i} and @code{c} commands.
+
+@item i\
+@itemx @var{text}
+@cindex @value{SSEDEXT}, two addresses supported by most commands
+As a @acronym{GNU} extension, this command accepts two addresses.
+
+@findex i (insert text lines) command
+@cindex Inserting text before a line
+@cindex Text, insertion
+Immediately output the lines of text which follow this command
+(each but the last ending with a @code{\},
+which are removed from the output).
+
+@item c\
+@itemx @var{text}
+@findex c (change to text lines) command
+@cindex Replacing selected lines with other text
+Delete the lines matching the address or address-range,
+and output the lines of text which follow this command
+(each but the last ending with a @code{\},
+which are removed from the output)
+in place of the last line
+(or in place of each line, if no addresses were specified).
+A new cycle is started after this command is done,
+since the pattern space will have been deleted.
+
+@item =
+@cindex @value{SSEDEXT}, two addresses supported by most commands
+As a @acronym{GNU} extension, this command accepts two addresses.
+
+@findex = (print line number) command
+@cindex Printing line number
+@cindex Line number, printing
+Print out the current input line number (with a trailing newline).
+
+@item l @var{n}
+@findex l (list unambiguously) command
+@cindex List pattern space
+@cindex Printing text unambiguously
+@cindex Line length, setting
+@cindex @value{SSEDEXT}, setting line length
+Print the pattern space in an unambiguous form:
+non-printable characters (and the @code{\} character)
+are printed in C-style escaped form; long lines are split,
+with a trailing @code{\} character to indicate the split;
+the end of each line is marked with a @code{$}.
+
+@var{n} specifies the desired line-wrap length;
+a length of 0 (zero) means to never wrap long lines.  If omitted,
+the default as specified on the command line is used.  The @var{n}
+parameter is a @value{SSED} extension.
+
+@item r @var{filename}
+@cindex @value{SSEDEXT}, two addresses supported by most commands
+As a @acronym{GNU} extension, this command accepts two addresses.
+
+@findex r (read file) command
+@cindex Read text from a file
+@cindex @value{SSEDEXT}, @file{/dev/stdin} file
+Queue the contents of @var{filename} to be read and
+inserted into the output stream at the end of the current cycle,
+or when the next input line is read.
+Note that if @var{filename} cannot be read, it is treated as
+if it were an empty file, without any error indication.
+
+As a @value{SSED} extension, the special value @file{/dev/stdin}
+is supported for the file name, which reads the contents of the
+standard input.
+
+@item w @var{filename}
+@findex w (write file) command
+@cindex Write to a file
+@cindex @value{SSEDEXT}, @file{/dev/stdout} file
+@cindex @value{SSEDEXT}, @file{/dev/stderr} file
+Write the pattern space to @var{filename}.
+As a @value{SSED} extension, two special values of @var{file-name} are
+supported: @file{/dev/stderr}, which writes the result to the standard
+error, and @file{/dev/stdout}, which writes to the standard
+output.@footnote{This is equivalent to @code{p} unless the @option{-i}
+option is being used.}
+
+The file will be created (or truncated) before the
+first input line is read; all @code{w} commands
+(including instances of @code{w} flag on successful @code{s} commands)
+which refer to the same @var{filename} are output without
+closing and reopening the file.
+
+@item D
+@findex D (delete first line) command
+@cindex Delete first line from pattern space
+Delete text in the pattern space up to the first newline.
+If any text is left, restart cycle with the resultant
+pattern space (without reading a new line of input),
+otherwise start a normal new cycle.
+
+@item N
+@findex N (append Next line) command
+@cindex Next input line, append to pattern space
+@cindex Append next input line to pattern space
+Add a newline to the pattern space,
+then append the next line of input to the pattern space.
+If there is no more input then @command{sed} exits without processing
+any more commands.
+
+@item P
+@findex P (print first line) command
+@cindex Print first line from pattern space
+Print out the portion of the pattern space up to the first newline.
+
+@item h
+@findex h (hold) command
+@cindex Copy pattern space into hold space
+@cindex Replace hold space with copy of pattern space
+@cindex Hold space, copying pattern space into
+Replace the contents of the hold space with the contents of the pattern space.
+
+@item H
+@findex H (append Hold) command
+@cindex Append pattern space to hold space
+@cindex Hold space, appending from pattern space
+Append a newline to the contents of the hold space,
+and then append the contents of the pattern space to that of the hold space.
+
+@item g
+@findex g (get) command
+@cindex Copy hold space into pattern space
+@cindex Replace pattern space with copy of hold space
+@cindex Hold space, copy into pattern space
+Replace the contents of the pattern space with the contents of the hold space.
+
+@item G
+@findex G (appending Get) command
+@cindex Append hold space to pattern space
+@cindex Hold space, appending to pattern space
+Append a newline to the contents of the pattern space,
+and then append the contents of the hold space to that of the pattern space.
+
+@item x
+@findex x (eXchange) command
+@cindex Exchange hold space with pattern space
+@cindex Hold space, exchange with pattern space
+Exchange the contents of the hold and pattern spaces.
+
+@end table
+
+
+@node Programming Commands
+@section Commands for @command{sed} gurus
+
+In most cases, use of these commands indicates that you are
+probably better off programming in something like @command{awk}
+or Perl.  But occasionally one is committed to sticking
+with @command{sed}, and these commands can enable one to write
+quite convoluted scripts.
+
+@cindex Flow of control in scripts
+@table @code
+@item : @var{label}
+[No addresses allowed.]
+
+@findex : (label) command
+@cindex Labels, in scripts
+Specify the location of @var{label} for branch commands.
+In all other respects, a no-op.
+
+@item b @var{label}
+@findex b (branch) command
+@cindex Branch to a label, unconditionally
+@cindex Goto, in scripts
+Unconditionally branch to @var{label}.
+The @var{label} may be omitted, in which case the next cycle is started.
+
+@item t @var{label}
+@findex t (test and branch if successful) command
+@cindex Branch to a label, if @code{s///} succeeded
+@cindex Conditional branch
+Branch to @var{label} only if there has been a successful @code{s}ubstitution
+since the last input line was read or conditional branch was taken.
+The @var{label} may be omitted, in which case the next cycle is started.
+
+@end table
+
+@node Extended Commands
+@section Commands Specific to @value{SSED}
+
+These commands are specific to @value{SSED}, so you
+must use them with care and only when you are sure that
+hindering portability is not evil.  They allow you to check
+for @value{SSED} extensions or to do tasks that are required
+quite often, yet are unsupported by standard @command{sed}s.
+
+@table @code
+@item e [@var{command}]
+@findex e (evaluate) command
+@cindex Evaluate Bourne-shell commands
+@cindex Subprocesses
+@cindex @value{SSEDEXT}, evaluating Bourne-shell commands
+@cindex @value{SSEDEXT}, subprocesses
+This command allows one to pipe input from a shell command
+into pattern space.  Without parameters, the @code{e} command
+executes the command that is found in pattern space and
+replaces the pattern space with the output; a trailing newline
+is suppressed.
+
+If a parameter is specified, instead, the @code{e} command
+interprets it as a command and sends its output to the output stream
+(like @code{r} does).  The command can run across multiple
+lines, all but the last ending with a back-slash.
+
+In both cases, the results are undefined if the command to be
+executed contains a @sc{nul} character.
+
+@item L @var{n}
+@findex L (fLow paragraphs) command
+@cindex Reformat pattern space
+@cindex Reformatting paragraphs
+@cindex @value{SSEDEXT}, reformatting paragraphs
+@cindex @value{SSEDEXT}, @code{L} command
+This @value{SSED} extension fills and joins lines in pattern space
+to produce output lines of (at most) @var{n} characters, like
+@code{fmt} does; if @var{n} is omitted, the default as specified
+on the command line is used.  This command is considered a failed
+experiment and unless there is enough request (which seems unlikely)
+will be removed in future versions.
+
+@ignore
+Blank lines, spaces between words, and indentation are
+preserved in the output; successive input lines with different
+indentation are not joined; tabs are expanded to 8 columns.
+
+If the pattern space contains multiple lines, they are joined, but
+since the pattern space usually contains a single line, the behavior
+of a simple @code{L;d} script is the same as @samp{fmt -s} (i.e.,
+it does not join short lines to form longer ones).
+
+@var{n} specifies the desired line-wrap length; if omitted,
+the default as specified on the command line is used.
+@end ignore
+
+@item Q [@var{exit-code}]
+This command only accepts a single address.
+
+@findex Q (silent Quit) command
+@cindex @value{SSEDEXT}, quitting silently
+@cindex @value{SSEDEXT}, returning an exit code
+@cindex Quitting
+This command is the same as @code{q}, but will not print the
+contents of pattern space.  Like @code{q}, it provides the
+ability to return an exit code to the caller.
+
+This command can be useful because the only alternative ways
+to accomplish this apparently trivial function are to use
+the @option{-n} option (which can unnecessarily complicate
+your script) or resorting to the following snippet, which
+wastes time by reading the whole file without any visible effect:
+
+@example
+:eat
+$d       @i{Quit silently on the last line}
+N        @i{Read another line, silently}
+g        @i{Overwrite pattern space each time to save memory}
+b eat
+@end example
+
+@item R @var{filename}
+@findex R (read line) command
+@cindex Read text from a file
+@cindex @value{SSEDEXT}, reading a file a line at a time
+@cindex @value{SSEDEXT}, @code{R} command
+@cindex @value{SSEDEXT}, @file{/dev/stdin} file
+Queue a line of @var{filename} to be read and
+inserted into the output stream at the end of the current cycle,
+or when the next input line is read.
+Note that if @var{filename} cannot be read, or if its end is
+reached, no line is appended, without any error indication.
+
+As with the @code{r} command, the special value @file{/dev/stdin}
+is supported for the file name, which reads a line from the
+standard input.
+
+@item T @var{label}
+@findex T (test and branch if failed) command
+@cindex @value{SSEDEXT}, branch if @code{s///} failed
+@cindex Branch to a label, if @code{s///} failed
+@cindex Conditional branch
+Branch to @var{label} only if there have been no successful
+@code{s}ubstitutions since the last input line was read or
+conditional branch was taken. The @var{label} may be omitted,
+in which case the next cycle is started.
+
+@item v @var{version}
+@findex v (version) command
+@cindex @value{SSEDEXT}, checking for their presence
+@cindex Requiring @value{SSED}
+This command does nothing, but makes @command{sed} fail if
+@value{SSED} extensions are not supported, simply because other
+versions of @command{sed} do not implement it.  In addition, you
+can specify the version of @command{sed} that your script
+requires, such as @code{4.0.5}.  The default is @code{4.0}
+because that is the first version that implemented this command.
+
+This command enables all @value{SSEDEXT} even if
+@env{POSIXLY_CORRECT} is set in the environment.
+
+@item W @var{filename}
+@findex W (write first line) command
+@cindex Write first line to a file
+@cindex @value{SSEDEXT}, writing first line to a file
+Write to the given filename the portion of the pattern space up to
+the first newline.  Everything said under the @code{w} command about
+file handling holds here too.
+@end table
+
+@node Escapes
+@section @acronym{GNU} Extensions for Escapes in Regular Expressions
+
+@cindex @acronym{GNU} extensions, special escapes
+Until this chapter, we have only encountered escapes of the form
+@samp{\^}, which tell @command{sed} not to interpret the circumflex
+as a special character, but rather to take it literally.  For
+example, @samp{\*} matches a single asterisk rather than zero
+or more backslashes.
+
+@cindex @code{POSIXLY_CORRECT} behavior, escapes
+This chapter introduces another kind of escape@footnote{All
+the escapes introduced here are @acronym{GNU}
+extensions, with the exception of @code{\n}.  In basic regular
+expression mode, setting @code{POSIXLY_CORRECT} disables them inside
+bracket expressions.}---that
+is, escapes that are applied to a character or sequence of characters
+that ordinarily are taken literally, and that @command{sed} replaces
+with a special character.  This provides a way
+of encoding non-printable characters in patterns in a visible manner.
+There is no restriction on the appearance of non-printing characters
+in a @command{sed} script but when a script is being prepared in the
+shell or by text editing, it is usually easier to use one of
+the following escape sequences than the binary character it
+represents:
+
+The list of these escapes is:
+
+@table @code
+@item \a
+Produces or matches a @sc{bel} character, that is an ``alert'' (@sc{ascii} 7).
+
+@item \f
+Produces or matches a form feed (@sc{ascii} 12).
+
+@item \n
+Produces or matches a newline (@sc{ascii} 10).
+
+@item \r
+Produces or matches a carriage return (@sc{ascii} 13).
+
+@item \t
+Produces or matches a horizontal tab (@sc{ascii} 9).
+
+@item \v
+Produces or matches a so called ``vertical tab'' (@sc{ascii} 11).
+
+@item \c@var{x}
+Produces or matches @kbd{@sc{Control}-@var{x}}, where @var{x} is
+any character.  The precise effect of @samp{\c@var{x}} is as follows:
+if @var{x} is a lower case letter, it is converted to upper case.
+Then bit 6 of the character (hex 40) is inverted.  Thus @samp{\cz} becomes
+hex 1A, but @samp{\c@{} becomes hex 3B, while @samp{\c;} becomes hex 7B.
+
+@item \d@var{xxx}
+Produces or matches a character whose decimal @sc{ascii} value is @var{xxx}.
+
+@item \o@var{xxx}
+@ifset PERL
+@item \@var{xxx}
+@end ifset
+Produces or matches a character whose octal @sc{ascii} value is @var{xxx}.
+@ifset PERL
+The syntax without the @code{o} is active in Perl mode, while the one
+with the @code{o} is active in the normal or extended @sc{posix} regular
+expression modes.
+@end ifset
+
+@item \x@var{xx}
+Produces or matches a character whose hexadecimal @sc{ascii} value is @var{xx}.
+@end table
+
+@samp{\b} (backspace) was omitted because of the conflict with
+the existing ``word boundary'' meaning.
+
+Other escapes match a particular character class and are valid only in
+regular expressions:
+
+@table @code
+@item \w
+Matches any ``word'' character.  A ``word'' character is any
+letter or digit or the underscore character.
+
+@item \W
+Matches any ``non-word'' character.
+
+@item \b
+Matches a word boundary; that is it matches if the character
+to the left is a ``word'' character and the character to the
+right is a ``non-word'' character, or vice-versa.
+
+@item \B
+Matches everywhere but on a word boundary; that is it matches
+if the character to the left and the character to the right
+are either both ``word'' characters or both ``non-word''
+characters.
+
+@item \`
+Matches only at the start of pattern space.  This is different
+from @code{^} in multi-line mode.
+
+@item \'
+Matches only at the end of pattern space.  This is different
+from @code{$} in multi-line mode.
+
+@ifset PERL
+@item \G
+Match only at the start of pattern space or, when doing a global
+substitution using the @code{s///g} command and option, at
+the end-of-match position of the prior match.  For example,
+@samp{s/\Ga/Z/g} will change an initial run of @code{a}s to
+a run of @code{Z}s
+@end ifset
+@end table
+
+@node Examples
+@chapter Some Sample Scripts
+
+Here are some @command{sed} scripts to guide you in the art of mastering
+@command{sed}.
+
+@menu
+Some exotic examples:
+* Centering lines::
+* Increment a number::
+* Rename files to lower case::
+* Print bash environment::
+* Reverse chars of lines::
+
+Emulating standard utilities:
+* tac::                             Reverse lines of files
+* cat -n::                          Numbering lines
+* cat -b::                          Numbering non-blank lines
+* wc -c::                           Counting chars
+* wc -w::                           Counting words
+* wc -l::                           Counting lines
+* head::                            Printing the first lines
+* tail::                            Printing the last lines
+* uniq::                            Make duplicate lines unique
+* uniq -d::                         Print duplicated lines of input
+* uniq -u::                         Remove all duplicated lines
+* cat -s::                          Squeezing blank lines
+@end menu
+
+@node Centering lines
+@section Centering Lines
+
+This script centers all lines of a file on a 80 columns width.
+To change that width, the number in @code{\@{@dots{}\@}} must be
+replaced, and the number of added spaces also must be changed.
+
+Note how the buffer commands are used to separate parts in
+the regular expressions to be matched---this is a common
+technique.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+# Put 80 spaces in the buffer
+1 @{
+  x
+  s/^$/          /
+  s/^.*$/&&&&&&&&/
+  x
+@}
+
+# del leading and trailing spaces
+y/@kbd{tab}/ /
+s/^ *//
+s/ *$//
+
+# add a newline and 80 spaces to end of line
+G
+
+# keep first 81 chars (80 + a newline)
+s/^\(.\@{81\@}\).*$/\1/
+
+# \2 matches half of the spaces, which are moved to the beginning
+s/^\(.*\)\n\(.*\)\2/\2\1/
+@end example
+@c end---------------------------------------------
+
+@node Increment a number
+@section Increment a Number
+
+This script is one of a few that demonstrate how to do arithmetic
+in @command{sed}.  This is indeed possible,@footnote{@command{sed} guru Greg
+Ubben wrote an implementation of the @command{dc} @sc{rpn} calculator!
+It is distributed together with sed.} but must be done manually.
+
+To increment one number you just add 1 to last digit, replacing
+it by the following digit.  There is one exception: when the digit
+is a nine the previous digits must be also incremented until you
+don't have a nine.
+
+This solution by Bruno Haible is very clever and smart because
+it uses a single buffer; if you don't have this limitation, the
+algorithm used in @ref{cat -n, Numbering lines}, is faster.
+It works by replacing trailing nines with an underscore, then
+using multiple @code{s} commands to increment the last digit,
+and then again substituting underscores with zeros.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+/[^0-9]/ d
+
+# replace all leading 9s by _ (any other character except digits, could
+# be used)
+:d
+s/9\(_*\)$/_\1/
+td
+
+# incr last digit only.  The first line adds a most-significant
+# digit of 1 if we have to add a digit.
+#
+# The @code{tn} commands are not necessary, but make the thing
+# faster
+
+s/^\(_*\)$/1\1/; tn
+s/8\(_*\)$/9\1/; tn
+s/7\(_*\)$/8\1/; tn
+s/6\(_*\)$/7\1/; tn
+s/5\(_*\)$/6\1/; tn
+s/4\(_*\)$/5\1/; tn
+s/3\(_*\)$/4\1/; tn
+s/2\(_*\)$/3\1/; tn
+s/1\(_*\)$/2\1/; tn
+s/0\(_*\)$/1\1/; tn
+
+:n
+y/_/0/
+@end example
+@c end---------------------------------------------
+
+@node Rename files to lower case
+@section Rename Files to Lower Case
+
+This is a pretty strange use of @command{sed}.  We transform text, and
+transform it to be shell commands, then just feed them to shell.
+Don't worry, even worse hacks are done when using @command{sed}; I have
+seen a script converting the output of @command{date} into a @command{bc}
+program!
+ 
+The main body of this is the @command{sed} script, which remaps the name
+from lower to upper (or vice-versa) and even checks out 
+if the remapped name is the same as the original name.
+Note how the script is parameterized using shell
+variables and proper quoting.
+
+@c start-------------------------------------------
+@example
+#! /bin/sh
+# rename files to lower/upper case... 
+#
+# usage: 
+#    move-to-lower * 
+#    move-to-upper * 
+# or
+#    move-to-lower -R .
+#    move-to-upper -R .
+#
+
+help()
+@{
+	cat << eof
+Usage: $0 [-n] [-r] [-h] files...
+
+-n      do nothing, only see what would be done
+-R      recursive (use find)
+-h      this message
+files   files to remap to lower case
+
+Examples:
+       $0 -n *        (see if everything is ok, then...)
+       $0 *
+
+       $0 -R .
+
+eof
+@}
+
+apply_cmd='sh'
+finder='echo "$@@" | tr " " "\n"'
+files_only=
+
+while :
+do
+    case "$1" in 
+        -n) apply_cmd='cat' ;;
+        -R) finder='find "$@@" -type f';;
+        -h) help ; exit 1 ;;
+        *) break ;;
+    esac
+    shift
+done
+
+if [ -z "$1" ]; then
+        echo Usage: $0 [-h] [-n] [-r] files...
+        exit 1
+fi
+
+LOWER='abcdefghijklmnopqrstuvwxyz'
+UPPER='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+case `basename $0` in
+        *upper*) TO=$UPPER; FROM=$LOWER ;;
+        *)       FROM=$UPPER; TO=$LOWER ;;
+esac
+	
+eval $finder | sed -n '
+
+# remove all trailing slashes
+s/\/*$//
+
+# add ./ if there is no path, only a filename
+/\//! s/^/.\//
+
+# save path+filename
+h
+
+# remove path
+s/.*\///
+
+# do conversion only on filename
+y/'$FROM'/'$TO'/
+
+# now line contains original path+file, while
+# hold space contains the new filename
+x
+
+# add converted file name to line, which now contains
+# path/file-name\nconverted-file-name
+G
+
+# check if converted file name is equal to original file name,
+# if it is, do not print nothing
+/^.*\/\(.*\)\n\1/b
+
+# now, transform path/fromfile\n, into
+# mv path/fromfile path/tofile and print it
+s/^\(.*\/\)\(.*\)\n\(.*\)$/mv "\1\2" "\1\3"/p
+
+' | $apply_cmd
+@end example
+@c end---------------------------------------------
+
+@node Print bash environment
+@section Print @command{bash} Environment
+
+This script strips the definition of the shell functions
+from the output of the @command{set} Bourne-shell command.
+
+@c start-------------------------------------------
+@example
+#!/bin/sh
+
+set | sed -n '
+:x
+
+@ifinfo
+# if no occurrence of "=()" print and load next line
+@end ifinfo
+@ifnotinfo
+# if no occurrence of @samp{=()} print and load next line
+@end ifnotinfo
+/=()/! @{ p; b; @}
+/ () $/! @{ p; b; @}
+
+# possible start of functions section
+# save the line in case this is a var like FOO="() "
+h
+
+# if the next line has a brace, we quit because
+# nothing comes after functions
+n
+/^@{/ q
+
+# print the old line
+x; p
+
+# work on the new line now
+x; bx
+'
+@end example
+@c end---------------------------------------------
+
+@node Reverse chars of lines
+@section Reverse Characters of Lines
+
+This script can be used to reverse the position of characters
+in lines.  The technique moves two characters at a time, hence
+it is faster than more intuitive implementations.
+
+Note the @code{tx} command before the definition of the label.
+This is often needed to reset the flag that is tested by
+the @code{t} command.
+
+Imaginative readers will find uses for this script.  An example
+is reversing the output of @command{banner}.@footnote{This requires
+another script to pad the output of banner; for example
+
+@example
+#! /bin/sh
+
+banner -w $1 $2 $3 $4 |
+  sed -e :a -e '/^.\@{0,'$1'\@}$/ @{ s/$/ /; ba; @}' |
+  ~/sedscripts/reverseline.sed
+@end example
+}
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+/../! b
+
+# Reverse a line.  Begin embedding the line between two newlines
+s/^.*$/\
+&\
+/
+
+# Move first character at the end.  The regexp matches until
+# there are zero or one characters between the markers
+tx
+:x
+s/\(\n.\)\(.*\)\(.\n\)/\3\2\1/
+tx
+
+# Remove the newline markers
+s/\n//g
+@end example
+@c end---------------------------------------------
+
+@node tac
+@section Reverse Lines of Files
+
+This one begins a series of totally useless (yet interesting)
+scripts emulating various Unix commands.  This, in particular,
+is a @command{tac} workalike.
+
+Note that on implementations other than @acronym{GNU} @command{sed}
+@ifset PERL
+and @value{SSED}
+@end ifset
+this script might easily overflow internal buffers.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+# reverse all lines of input, i.e. first line became last, ...
+
+# from the second line, the buffer (which contains all previous lines)
+# is *appended* to current line, so, the order will be reversed
+1! G
+
+# on the last line we're done -- print everything
+$ p
+
+# store everything on the buffer again
+h
+@end example
+@c end---------------------------------------------
+
+@node cat -n
+@section Numbering Lines
+
+This script replaces @samp{cat -n}; in fact it formats its output
+exactly like @acronym{GNU} @command{cat} does.
+
+Of course this is completely useless and for two reasons:  first,
+because somebody else did it in C, second, because the following
+Bourne-shell script could be used for the same purpose and would
+be much faster:
+
+@c start-------------------------------------------
+@example
+#! /bin/sh
+sed -e "=" $@@ | sed -e '
+  s/^/      /
+  N
+  s/^ *\(......\)\n/\1  /
+'
+@end example
+@c end---------------------------------------------
+
+It uses @command{sed} to print the line number, then groups lines two
+by two using @code{N}.  Of course, this script does not teach as much as
+the one presented below.
+
+The algorithm used for incrementing uses both buffers, so the line
+is printed as soon as possible and then discarded.  The number
+is split so that changing digits go in a buffer and unchanged ones go
+in the other; the changed digits are modified in a single step
+(using a @code{y} command).  The line number for the next line
+is then composed and stored in the hold space, to be used in the
+next iteration.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+# Prime the pump on the first line
+x
+/^$/ s/^.*$/1/
+
+# Add the correct line number before the pattern
+G
+h
+
+# Format it and print it
+s/^/      /
+s/^ *\(......\)\n/\1  /p
+
+# Get the line number from hold space; add a zero
+# if we're going to add a digit on the next line
+g
+s/\n.*$//
+/^9*$/ s/^/0/
+
+# separate changing/unchanged digits with an x
+s/.9*$/x&/
+
+# keep changing digits in hold space
+h
+s/^.*x//
+y/0123456789/1234567890/
+x
+
+# keep unchanged digits in pattern space
+s/x.*$//
+
+# compose the new number, remove the newline implicitly added by G
+G
+s/\n//
+h
+@end example
+@c end---------------------------------------------
+
+@node cat -b
+@section Numbering Non-blank Lines
+
+Emulating @samp{cat -b} is almost the same as @samp{cat -n}---we only
+have to select which lines are to be numbered and which are not.
+
+The part that is common to this script and the previous one is
+not commented to show how important it is to comment @command{sed}
+scripts properly...
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+/^$/ @{
+  p
+  b
+@}
+
+# Same as cat -n from now
+x
+/^$/ s/^.*$/1/
+G
+h
+s/^/      /
+s/^ *\(......\)\n/\1  /p
+x
+s/\n.*$//
+/^9*$/ s/^/0/
+s/.9*$/x&/
+h
+s/^.*x//
+y/0123456789/1234567890/
+x
+s/x.*$//
+G
+s/\n//
+h
+@end example
+@c end---------------------------------------------
+
+@node wc -c
+@section Counting Characters
+
+This script shows another way to do arithmetic with @command{sed}.
+In this case we have to add possibly large numbers, so implementing
+this by successive increments would not be feasible (and possibly
+even more complicated to contrive than this script).
+
+The approach is to map numbers to letters, kind of an abacus
+implemented with @command{sed}.  @samp{a}s are units, @samp{b}s are
+tens and so on: we simply add the number of characters
+on the current line as units, and then propagate the carry
+to tens, hundreds, and so on.
+
+As usual, running totals are kept in hold space.
+
+On the last line, we convert the abacus form back to decimal.
+For the sake of variety, this is done with a loop rather than
+with some 80 @code{s} commands@footnote{Some implementations
+have a limit of 199 commands per script}: first we
+convert units, removing @samp{a}s from the number; then we
+rotate letters so that tens become @samp{a}s, and so on
+until no more letters remain.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+# Add n+1 a's to hold space (+1 is for the newline)
+s/./a/g
+H
+x
+s/\n/a/
+
+# Do the carry.  The t's and b's are not necessary,
+# but they do speed up the thing
+t a
+: a;  s/aaaaaaaaaa/b/g; t b; b done
+: b;  s/bbbbbbbbbb/c/g; t c; b done
+: c;  s/cccccccccc/d/g; t d; b done
+: d;  s/dddddddddd/e/g; t e; b done
+: e;  s/eeeeeeeeee/f/g; t f; b done
+: f;  s/ffffffffff/g/g; t g; b done
+: g;  s/gggggggggg/h/g; t h; b done
+: h;  s/hhhhhhhhhh//g
+
+: done
+$! @{
+  h
+  b
+@}
+
+# On the last line, convert back to decimal
+
+: loop
+/a/! s/[b-h]*/&0/
+s/aaaaaaaaa/9/
+s/aaaaaaaa/8/
+s/aaaaaaa/7/
+s/aaaaaa/6/
+s/aaaaa/5/
+s/aaaa/4/
+s/aaa/3/
+s/aa/2/
+s/a/1/
+
+: next
+y/bcdefgh/abcdefg/
+/[a-h]/ b loop
+p
+@end example
+@c end---------------------------------------------
+
+@node wc -w
+@section Counting Words
+
+This script is almost the same as the previous one, once each
+of the words on the line is converted to a single @samp{a}
+(in the previous script each letter was changed to an @samp{a}).
+
+It is interesting that real @command{wc} programs have optimized
+loops for @samp{wc -c}, so they are much slower at counting
+words rather than characters.  This script's bottleneck,
+instead, is arithmetic, and hence the word-counting one
+is faster (it has to manage smaller numbers).
+
+Again, the common parts are not commented to show the importance
+of commenting @command{sed} scripts.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+# Convert words to a's
+s/[ @kbd{tab}][ @kbd{tab}]*/ /g
+s/^/ /
+s/ [^ ][^ ]*/a /g
+s/ //g
+
+# Append them to hold space
+H
+x
+s/\n//
+
+# From here on it is the same as in wc -c.
+/aaaaaaaaaa/! bx;   s/aaaaaaaaaa/b/g
+/bbbbbbbbbb/! bx;   s/bbbbbbbbbb/c/g
+/cccccccccc/! bx;   s/cccccccccc/d/g
+/dddddddddd/! bx;   s/dddddddddd/e/g
+/eeeeeeeeee/! bx;   s/eeeeeeeeee/f/g
+/ffffffffff/! bx;   s/ffffffffff/g/g
+/gggggggggg/! bx;   s/gggggggggg/h/g
+s/hhhhhhhhhh//g
+:x
+$! @{ h; b; @}
+:y
+/a/! s/[b-h]*/&0/
+s/aaaaaaaaa/9/
+s/aaaaaaaa/8/
+s/aaaaaaa/7/
+s/aaaaaa/6/
+s/aaaaa/5/
+s/aaaa/4/
+s/aaa/3/
+s/aa/2/
+s/a/1/
+y/bcdefgh/abcdefg/
+/[a-h]/ by
+p
+@end example
+@c end---------------------------------------------
+
+@node wc -l
+@section Counting Lines
+
+No strange things are done now, because @command{sed} gives us
+@samp{wc -l} functionality for free!!! Look:
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+$=
+@end example
+@c end---------------------------------------------
+
+@node head
+@section Printing the First Lines
+
+This script is probably the simplest useful @command{sed} script.
+It displays the first 10 lines of input; the number of displayed
+lines is right before the @code{q} command.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+10q
+@end example
+@c end---------------------------------------------
+
+@node tail
+@section Printing the Last Lines
+
+Printing the last @var{n} lines rather than the first is more complex
+but indeed possible.  @var{n} is encoded in the second line, before
+the bang character.
+
+This script is similar to the @command{tac} script in that it keeps the
+final output in the hold space and prints it at the end:
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+1! @{; H; g; @}
+1,10 !s/[^\n]*\n//
+$p
+h
+@end example
+@c end---------------------------------------------
+
+Mainly, the scripts keeps a window of 10 lines and slides it
+by adding a line and deleting the oldest (the substitution command
+on the second line works like a @code{D} command but does not
+restart the loop).
+
+The ``sliding window'' technique is a very powerful way to write
+efficient and complex @command{sed} scripts, because commands like
+@code{P} would require a lot of work if implemented manually.
+
+To introduce the technique, which is fully demonstrated in the
+rest of this chapter and is based on the @code{N}, @code{P}
+and @code{D} commands, here is an implementation of @command{tail}
+using a simple ``sliding window.''
+
+This looks complicated but in fact the working is the same as
+the last script: after we have kicked in the appropriate number
+of lines, however, we stop using the hold space to keep inter-line
+state, and instead use @code{N} and @code{D} to slide pattern
+space by one line:
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+1h
+2,10 @{; H; g; @}
+$q
+1,9d
+N
+D
+@end example
+@c end---------------------------------------------
+
+Note how the first, second and fourth line are inactive after
+the first ten lines of input.  After that, all the script does
+is: exiting on the last line of input, appending the next input
+line to pattern space, and removing the first line.
+
+@node uniq
+@section Make Duplicate Lines Unique
+
+This is an example of the art of using the @code{N}, @code{P}
+and @code{D} commands, probably the most difficult to master.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+h
+
+:b
+# On the last line, print and exit
+$b
+N
+/^\(.*\)\n\1$/ @{
+    # The two lines are identical.  Undo the effect of
+    # the n command.
+    g
+    bb
+@}
+
+# If the @code{N} command had added the last line, print and exit
+$b
+
+# The lines are different; print the first and go
+# back working on the second.
+P
+D
+@end example
+@c end---------------------------------------------
+
+As you can see, we mantain a 2-line window using @code{P} and @code{D}.
+This technique is often used in advanced @command{sed} scripts.
+
+@node uniq -d
+@section Print Duplicated Lines of Input
+
+This script prints only duplicated lines, like @samp{uniq -d}.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+$b
+N
+/^\(.*\)\n\1$/ @{
+    # Print the first of the duplicated lines
+    s/.*\n//
+    p
+
+    # Loop until we get a different line
+    :b
+    $b
+    N
+    /^\(.*\)\n\1$/ @{
+        s/.*\n//
+        bb
+    @}
+@}
+
+# The last line cannot be followed by duplicates
+$b
+
+# Found a different one.  Leave it alone in the pattern space
+# and go back to the top, hunting its duplicates
+D
+@end example
+@c end---------------------------------------------
+
+@node uniq -u
+@section Remove All Duplicated Lines
+
+This script prints only unique lines, like @samp{uniq -u}.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+# Search for a duplicate line --- until that, print what you find.
+$b
+N
+/^\(.*\)\n\1$/ ! @{
+    P
+    D
+@}
+
+:c
+# Got two equal lines in pattern space.  At the
+# end of the file we simply exit
+$d
+
+# Else, we keep reading lines with @code{N} until we
+# find a different one
+s/.*\n//
+N
+/^\(.*\)\n\1$/ @{
+    bc
+@}
+
+# Remove the last instance of the duplicate line
+# and go back to the top
+D
+@end example
+@c end---------------------------------------------
+
+@node cat -s
+@section Squeezing Blank Lines
+
+As a final example, here are three scripts, of increasing complexity
+and speed, that implement the same function as @samp{cat -s}, that is
+squeezing blank lines.
+
+The first leaves a blank line at the beginning and end if there are
+some already.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+# on empty lines, join with next
+# Note there is a star in the regexp
+:x
+/^\n*$/ @{
+N
+bx
+@}
+
+# now, squeeze all '\n', this can be also done by:
+# s/^\(\n\)*/\1/
+s/\n*/\
+/
+@end example
+@c end---------------------------------------------
+
+This one is a bit more complex and removes all empty lines
+at the beginning.  It does leave a single blank line at end
+if one was there.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+# delete all leading empty lines
+1,/^./@{
+/./!d
+@}
+
+# on an empty line we remove it and all the following
+# empty lines, but one
+:x
+/./!@{
+N
+s/^\n$//
+tx
+@}
+@end example
+@c end---------------------------------------------
+
+This removes leading and trailing blank lines.  It is also the
+fastest.  Note that loops are completely done with @code{n} and
+@code{b}, without relying on @command{sed} to restart the
+the script automatically at the end of a line.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+# delete all (leading) blanks
+/./!d
+
+# get here: so there is a non empty
+:x
+# print it
+p
+# get next
+n
+# got chars? print it again, etc... 
+/./bx
+
+# no, don't have chars: got an empty line
+:z
+# get next, if last line we finish here so no trailing
+# empty lines are written
+n
+# also empty? then ignore it, and get next... this will
+# remove ALL empty lines
+/./!bz
+
+# all empty lines were deleted/ignored, but we have a non empty.  As
+# what we want to do is to squeeze, insert a blank line artificially
+i\
+
+bx
+@end example
+@c end---------------------------------------------
+
+@node Limitations
+@chapter @value{SSED}'s Limitations and Non-limitations
+
+@cindex @acronym{GNU} extensions, unlimited line length
+@cindex Portability, line length limitations
+For those who want to write portable @command{sed} scripts,
+be aware that some implementations have been known to
+limit line lengths (for the pattern and hold spaces)
+to be no more than 4000 bytes.
+The @sc{posix} standard specifies that conforming @command{sed}
+implementations shall support at least 8192 byte line lengths.
+@value{SSED} has no built-in limit on line length;
+as long as it can @code{malloc()} more (virtual) memory,
+you can feed or construct lines as long as you like.
+
+However, recursion is used to handle subpatterns and indefinite
+repetition.  This means that the available stack space may limit
+the size of the buffer that can be processed by certain patterns.
+
+@ifset PERL
+There are some size limitations in the regular expression
+matcher but it is hoped that they will never in practice
+be relevant.  The maximum length of a compiled pattern
+is 65539 (sic) bytes.  All values in repeating quantifiers
+must be less than 65536.  The maximum nesting depth of
+all parenthesized subpatterns, including capturing and
+non-capturing subpatterns@footnote{The
+distinction is meaningful when referring to Perl-style
+regular expressions.}, assertions, and other types of
+subpattern, is 200.
+
+Also, @value{SSED} recognizes the @sc{posix} syntax
+@code{[.@var{ch}.]} and @code{[=@var{ch}=]}
+where @var{ch} is a ``collating element'', but these
+are not supported, and an error is given if they are
+encountered.
+
+Here are a few distinctions between the real Perl-style
+regular expressions and those that @option{-R} recognizes.
+
+@enumerate
+@item
+Lookahead assertions do not allow repeat quantifiers after them
+Perl permits them, but they do not mean what you
+might think. For example, @samp{(?!a)@{3@}} does not assert that the
+next three characters are not @samp{a}. It just asserts three times that the
+next character is not @samp{a} --- a waste of time and nothing else.
+
+@item
+Capturing subpatterns that occur inside  negative  lookahead
+head  assertions  are  counted,  but  their  entries are counted
+as empty in the second half of an @code{s} command.
+Perl sets its numerical variables from any such patterns
+that are matched before the assertion fails to match
+something (thereby succeeding), but only if the negative
+lookahead assertion contains just one branch.
+
+@item
+The following Perl escape sequences are not supported:
+@samp{\l}, @samp{\u}, @samp{\L}, @samp{\U}, @samp{\E},
+@samp{\Q}. In fact these are implemented by Perl's general
+string-handling and are not part of its pattern matching engine.
+
+@item
+The Perl @samp{\G} assertion is not supported as it is not
+relevant to single pattern matches.
+
+@item
+Fairly obviously, @value{SSED} does not support the @samp{(?@{code@})}
+and @samp{(?p@{code@})} constructions. However, there is some experimental
+support for recursive patterns using the non-Perl item @samp{(?R)}.
+
+@item
+There are at the time of writing some oddities in Perl
+5.005_02 concerned with the settings of captured strings
+when part of a pattern is repeated. For example, matching
+@samp{aba} against the pattern @samp{/^(a(b)?)+$/} sets
+@samp{$2}@footnote{@samp{$2} would be @samp{\2} in @value{SSED}.}
+to the value @samp{b}, but matching @samp{aabbaa}
+against @samp{/^(aa(bb)?)+$/} leaves @samp{$2}
+unset.  However, if the pattern is changed to
+@samp{/^(aa(b(b))?)+$/} then @samp{$2} (and @samp{$3}) are set.
+In Perl 5.004 @samp{$2} is set in both cases, and that is also
+true of @value{SSED}.
+
+@item
+Another as yet unresolved discrepancy is that in Perl
+5.005_02 the pattern @samp{/^(a)?(?(1)a|b)+$/} matches
+the string @samp{a}, whereas in @value{SSED} it does not.
+However, in both Perl and @value{SSED} @samp{/^(a)?a/} matched
+against @samp{a} leaves $1 unset.
+@end enumerate
+@end ifset
+
+@node Other Resources
+@chapter Other Resources for Learning About @command{sed}
+
+@cindex Additional reading about @command{sed}
+In addition to several books that have been written about @command{sed}
+(either specifically or as chapters in books which discuss
+shell programming), one can find out more about @command{sed}
+(including suggestions of a few books) from the FAQ
+for the @code{sed-users} mailing list, available from any of:
+@display
+ @uref{http://www.student.northpark.edu/pemente/sed/sedfaq.html}
+ @uref{http://sed.sf.net/grabbag/tutorials/sedfaq.html}
+@end display
+
+Also of interest are
+@uref{http://www.student.northpark.edu/pemente/sed/index.htm}
+and @uref{http://sed.sf.net/grabbag},
+which include @command{sed} tutorials and other @command{sed}-related goodies.
+
+The @code{sed-users} mailing list itself maintained by Sven Guckes.
+To subscribe, visit @uref{http://groups.yahoo.com} and search
+for the @code{sed-users} mailing list.
+
+@node Reporting Bugs
+@chapter Reporting Bugs
+
+@cindex Bugs, reporting
+Email bug reports to @email{bonzini@@gnu.org}.
+Be sure to include the word ``sed'' somewhere in the @code{Subject:} field.
+Also, please include the output of @samp{sed --version} in the body
+of your report if at all possible.
+
+Please do not send a bug report like this:
+
+@example
+@i{while building frobme-1.3.4}
+$ configure 
+@error{} sed: file sedscr line 1: Unknown option to 's'
+@end example
+
+If @value{SSED} doesn't configure your favorite package, take a
+few extra minutes to identify the specific problem and make a stand-alone
+test case.  Unlike other programs such as C compilers, making such test
+cases for @command{sed} is quite simple.
+
+A stand-alone test case includes all the data necessary to perform the
+test, and the specific invocation of @command{sed} that causes the problem.
+The smaller a stand-alone test case is, the better.  A test case should
+not involve something as far removed from @command{sed} as ``try to configure
+frobme-1.3.4''.  Yes, that is in principle enough information to look
+for the bug, but that is not a very practical prospect.
+
+Here are a few commonly reported bugs that are not bugs.
+
+@table @asis
+@item @code{N} command on the last line
+@cindex Portability, @code{N} command on the last line
+@cindex Non-bugs, @code{N} command on the last line
+
+Most versions of @command{sed} exit without printing anything when
+the @command{N} command is issued on the last line of a file.
+@value{SSED} prints pattern space before exiting unless of course
+the @command{-n} command switch has been specified.  This choice is
+by design.
+
+For example, the behavior of
+@example
+sed N foo bar
+@end example
+@noindent
+would depend on whether foo has an even or an odd number of
+lines@footnote{which is the actual ``bug'' that prompted the
+change in behavior}.  Or, when writing a script to read the
+next few lines following a pattern match, traditional
+implementations of @code{sed} would force you to write
+something like
+@example
+/foo/@{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N @}
+@end example
+@noindent
+instead of just
+@example
+/foo/@{ N;N;N;N;N;N;N;N;N; @}
+@end example
+ 
+@cindex @code{POSIXLY_CORRECT} behavior, @code{N} command
+In any case, the simplest workaround is to use @code{$d;N} in
+scripts that rely on the traditional behavior, or to set
+the @code{POSIXLY_CORRECT} variable to a non-empty value.
+
+@item Regex syntax clashes (problems with backslashes)
+@cindex @acronym{GNU} extensions, to basic regular expressions
+@cindex Non-bugs, regex syntax clashes
+@command{sed} uses the @sc{posix} basic regular expression syntax.  According to
+the standard, the meaning of some escape sequences is undefined in
+this syntax;  notable in the case of @command{sed} are @code{\|},
+@code{\+}, @code{\?}, @code{\`}, @code{\'}, @code{\<},
+@code{\>}, @code{\b}, @code{\B}, @code{\w}, and @code{\W}.
+
+As in all @acronym{GNU} programs that use @sc{posix} basic regular
+expressions, @command{sed} interprets these escape sequences as special
+characters.  So, @code{x\+} matches one or more occurrences of @samp{x}.
+@code{abc\|def} matches either @samp{abc} or @samp{def}.
+
+This syntax may cause problems when running scripts written for other
+@command{sed}s.  Some @command{sed} programs have been written with the
+assumption that @code{\|} and @code{\+} match the literal characters
+@code{|} and @code{+}.  Such scripts must be modified by removing the
+spurious backslashes if they are to be used with modern implementations
+of @command{sed}, like
+@ifset PERL
+@value{SSED} or
+@end ifset
+@acronym{GNU} @command{sed}.
+
+On the other hand, some scripts use s|abc\|def||g to remove occurrences
+of @emph{either} @code{abc} or @code{def}.  While this worked until
+@command{sed} 4.0.x, newer versions interpret this as removing the
+string @code{abc|def}.  This is again undefined behavior according to
+@acronym{POSIX}, and this interpretation is arguably more robust: older
+@command{sed}s, for example, required that the regex matcher parsed
+@code{\/} as @code{/} in the common case of escaping a slash, which is
+again undefined behavior; the new behavior avoids this, and this is good
+because the regex matcher is only partially under our control.
+
+@cindex @acronym{GNU} extensions, special escapes
+In addition, this version of @command{sed} supports several escape characters
+(some of which are multi-character) to insert non-printable characters
+in scripts (@code{\a}, @code{\c}, @code{\d}, @code{\o}, @code{\r},
+@code{\t}, @code{\v}, @code{\x}).  These can cause similar problems
+with scripts written for other @command{sed}s.
+
+@item @option{-i} clobbers read-only files
+@cindex In-place editing
+@cindex @value{SSEDEXT}, in-place editing
+@cindex Non-bugs, in-place editing
+
+In short, @samp{sed -i} will let you delete the contents of
+a read-only file, and in general the @option{-i} option
+(@pxref{Invoking sed, , Invocation}) lets you clobber
+protected files.  This is not a bug, but rather a consequence
+of how the Unix filesystem works.
+
+The permissions on a file say what can happen to the data
+in that file, while the permissions on a directory say what can
+happen to the list of files in that directory.  @samp{sed -i}
+will not ever open for writing  a file that is already on disk.
+Rather, it will work on a temporary file that is finally renamed
+to the original name: if you rename or delete files, you're actually
+modifying the contents of the directory, so the operation depends on
+the permissions of the directory, not of the file.  For this same
+reason, @command{sed} does not let you use @option{-i} on a writeable file
+in a read-only directory (but unbelievably nobody reports that as a
+bug@dots{}).
+
+@item @code{0a} does not work (gives an error)
+There is no line 0.  0 is a special address that is only used to treat
+addresses like @code{0,/@var{RE}/} as active when the script starts: if
+you write @code{1,/abc/d} and the first line includes the word @samp{abc},
+then that match would be ignored because address ranges must span at least
+two lines (barring the end of the file); but what you probably wanted is
+to delete every line up to the first one including @samp{abc}, and this
+is obtained with @code{0,/abc/d}.
+
+@ifclear PERL
+@item @code{[a-z]} is case insensitive
+You are encountering problems with locales.  POSIX mandates that @code{[a-z]}
+uses the current locale's collation order -- in C parlance, that means using
+@code{strcoll(3)} instead of @code{strcmp(3)}.  Some locales have a
+case-insensitive collation order, others don't: one of those that have
+problems is Estonian.
+
+Another problem is that @code{[a-z]} tries to use collation symbols.
+This only happens if you are on the @acronym{GNU} system, using
+@acronym{GNU} libc's regular expression matcher instead of compiling the
+one supplied with @acronym{GNU} sed.  In a Danish locale, for example,
+the regular expression @code{^[a-z]$} matches the string @samp{aa},
+because this is a single collating symbol that comes after @samp{a}
+and before @samp{b}; @samp{ll} behaves similarly in Spanish
+locales, or @samp{ij} in Dutch locales.
+
+To work around these problems, which may cause bugs in shell scripts, set
+the @env{LC_COLLATE} and @env{LC_CTYPE} environment variables to @samp{C}.
+@end ifclear
+@end table
+
+
+@node Extended regexps
+@appendix Extended regular expressions
+@cindex Extended regular expressions, syntax
+
+The only difference between basic and extended regular expressions is in
+the behavior of a few characters: @samp{?}, @samp{+}, parentheses,
+and braces (@samp{@{@}}).  While basic regular expressions require
+these to be escaped if you want them to behave as special characters,
+when using extended regular expressions you must escape them if
+you want them @emph{to match a literal character}.
+
+@noindent
+Examples:
+@table @code
+@item abc?
+becomes @samp{abc\?} when using extended regular expressions.  It matches
+the literal string @samp{abc?}.
+
+@item c\+
+becomes @samp{c+} when using extended regular expressions.  It matches
+one or more @samp{c}s.
+
+@item a\@{3,\@}
+becomes @samp{a@{3,@}} when using extended regular expressions.  It matches
+three or more @samp{a}s.
+
+@item \(abc\)\@{2,3\@}
+becomes @samp{(abc)@{2,3@}} when using extended regular expressions.  It
+matches either @samp{abcabc} or @samp{abcabcabc}.
+
+@item \(abc*\)\1
+becomes @samp{(abc*)\1} when using extended regular expressions.
+Backreferences must still be escaped when using extended regular
+expressions.
+@end table
+
+@ifset PERL
+@node Perl regexps
+@appendix Perl-style regular expressions
+@cindex Perl-style regular expressions, syntax
+
+@emph{This part is taken from the @file{pcre.txt} file distributed together
+with the free @sc{pcre} regular expression matcher; it was written by Philip Hazel.}
+
+Perl introduced several extensions to regular expressions, some
+of them incompatible with the syntax of regular expressions
+accepted by Emacs and other @acronym{GNU} tools (whose matcher was
+based on the Emacs matcher).  @value{SSED} implements
+both kinds of extensions.
+
+@iftex
+Summarizing, we have:
+
+@itemize @bullet
+@item
+A backslash can introduce several special sequences
+
+@item
+The circumflex, dollar sign, and period characters behave specially 
+with regard to new lines
+
+@item
+Strange uses of square brackets are parsed differently
+
+@item
+You can toggle modifiers in the middle of a regular expression
+
+@item
+You can specify that a subpattern does not count when numbering backreferences
+
+@item
+@cindex Greedy regular expression matching
+You can specify greedy or non-greedy matching
+
+@item
+You can have more than ten back references
+
+@item
+You can do complex look aheads and look behinds (in the spirit of
+@code{\b}, but with subpatterns).
+
+@item
+You can often improve performance by avoiding that @command{sed} wastes
+time with backtracking
+
+@item
+You can have if/then/else branches
+
+@item
+You can do recursive matches, for example to look for unbalanced parentheses
+
+@item
+You can have comments and non-significant whitespace, because things can
+get complex...
+@end itemize
+
+Most of these extensions are introduced by the special @code{(?}
+sequence, which gives special meanings to parenthesized groups.
+@end iftex
+@menu
+Other extensions can be roughly subdivided in two categories
+On one hand Perl introduces several more escaped sequences
+(that is, sequences introduced by a backslash).  On the other
+hand, it specifies that if a question mark follows an open
+parentheses it should give a special meaning to the parenthesized
+group.
+
+* Backslash::                       Introduces special sequences
+* Circumflex/dollar sign/period::   Behave specially with regard to new lines
+* Square brackets::                 Are a bit different in strange cases
+* Options setting::                 Toggle modifiers in the middle of a regexp
+* Non-capturing subpatterns::       Are not counted when backreferencing
+* Repetition::                      Allows for non-greedy matching
+* Backreferences::                  Allows for more than 10 back references
+* Assertions::                      Allows for complex look ahead matches
+* Non-backtracking subpatterns::    Often gives more performance
+* Conditional subpatterns::         Allows if/then/else branches
+* Recursive patterns::              For example to match parentheses
+* Comments::                        Because things can get complex...
+@end menu
+
+@node Backslash
+@appendixsec Backslash
+@cindex Perl-style regular expressions, escaped sequences
+
+There are a few difference in the handling of backslashed 
+sequences in Perl mode.
+
+First of all, there are no @code{\o} and @code{\d} sequences.
+@sc{ascii} values for characters can be specified in octal
+with a @code{\@var{xxx}} sequence, where @var{xxx} is a
+sequence of up to three octal digits.  If the first digit
+is a zero, the treatment of the sequence is straightforward;
+just note that if the character that follows the escaped digit
+is itself an octal digit, you have to supply three octal digits
+for @var{xxx}.  For example @code{\07} is a @sc{bel} character
+rather than a @sc{nul} and a literal @code{7} (this sequence is
+instead represented by @code{\0007}).
+
+@cindex Perl-style regular expressions, backreferences
+The handling of a backslash followed by a digit other than 0
+is complicated.  Outside a character class, @command{sed} reads it
+and any following digits as a decimal number. If the number
+is less than 10, or if there have been at least that many
+previous capturing left parentheses in the expression, the
+entire sequence is taken as a back reference. A description
+of how this works is given later, following the discussion
+of parenthesized subpatterns.
+
+Inside a character class, or if the decimal number is
+greater than 9 and there have not been that many capturing
+subpatterns, @command{sed} re-reads up to three octal digits following
+the backslash, and generates a single byte from the
+least significant 8 bits of the value. Any subsequent digits
+stand for themselves.  For example:
+
+@example
+     \040  @i{is another way of writing a space}
+     \40   @i{is the same, provided there are fewer than 40}
+           @i{previous capturing subpatterns}
+     \7    @i{is always a back reference}
+     \011  @i{is always a tab}
+     \11   @i{might be a back reference, or another way of}
+           @i{writing a tab}
+     \0113 @i{is a tab followed by the character @samp{3}}
+     \113  @i{is the character with octal code 113 (since there}
+           @i{can be no more than 99 back references)}
+     \377  @i{is a byte consisting entirely of 1 bits (@sc{ascii} 255)}
+     \81   @i{is either a back reference, or a binary zero}
+           @i{followed by the two characters @samp{81}}
+@end example
+
+Note that octal values of 100 or greater must not be introduced
+duced by a leading zero, because no more than three octal
+digits are ever read.
+
+All the sequences that define a single byte value can be
+used both inside and outside character classes. In addition,
+inside a character class, the sequence @code{\b} is interpreted
+as the backspace character (hex 08). Outside a character
+class it has a different meaning (see below).
+
+In addition, there are four additional escapes specifying
+generic character classes (like @code{\w} and @code{\W} do):
+
+@cindex Perl-style regular expressions, character classes
+@table @samp
+@item \d
+Matches any decimal digit
+
+@item \D
+Matches any character that is not a decimal digit
+@end table
+
+In Perl mode, these character type sequences can appear both inside and
+outside character classes. Instead, in @sc{posix} mode these sequences
+(as well as @code{\w} and @code{\W}) are treated as two literal characters
+(a backslash and a letter) inside square brackets.
+
+Escaped sequences specifying assertions are also different in
+Perl mode.  An assertion specifies a condition that has to be met
+at a particular point in a match, without consuming any
+characters from the subject string. The use of subpatterns
+for more complicated assertions is described below.  The
+backslashed assertions are
+
+@cindex Perl-style regular expressions, assertions
+@table @samp
+@item \b
+Asserts that the point is at a word boundary.
+A word boundary is a position in the subject string where
+the current character and the previous character do not both
+match @code{\w} or @code{\W} (i.e. one matches @code{\w} and
+the other matches @code{\W}), or the start or end of the string
+if the first or last character matches @code{\w}, respectively.
+
+@item \B
+Asserts that the point is not at a word boundary.
+
+@item \A
+Asserts the matcher is at the start of pattern space (independent
+of multiline mode).
+
+@item \Z
+Asserts the matcher is at the end of pattern space,
+or at a newline before the end of pattern space (independent of
+multiline mode)
+
+@item \z
+Asserts the matcher is at the end of pattern space (independent
+of multiline mode)
+@end table
+
+These assertions may not appear in character classes (but
+note that @code{\b} has a different meaning, namely the
+backspace character, inside a character class).
+Note that Perl mode does not support directly assertions
+for the beginning and the end of word; the @acronym{GNU} extensions
+@code{\<} and @code{\>} achieve this purpose in @sc{posix} mode
+instead.
+
+The @code{\A}, @code{\Z}, and @code{\z} assertions differ
+from the traditional circumflex and dollar sign (described below)
+in that they only ever match at the very start and end of the
+subject string, whatever options are set; in particular @code{\A}
+and @code{\z} are the same as the @acronym{GNU} extensions
+@code{\`} and @code{\'} that are active in @sc{posix} mode.
+
+@node Circumflex/dollar sign/period
+@appendixsec Circumflex, dollar sign, period
+@cindex Perl-style regular expressions, newlines
+
+Outside a character class, in the default matching mode, the
+circumflex character is an assertion which is true only if
+the current matching point is at the start of the subject
+string.  Inside a character class, the circumflex has an entirely
+different meaning (see below).
+
+The circumflex need not be the first character of the pattern if
+a number of alternatives are involved, but it should be the
+first thing in each alternative in which it appears if the
+pattern is ever to match that branch. If all possible alternatives,
+start with a circumflex, that is, if the pattern is
+constrained to match only at the start of the subject, it is
+said to be an @dfn{anchored} pattern. (There are also other constructs
+structs that can cause a pattern to be anchored.)
+
+A dollar sign is an assertion which is true only if the
+current matching point is at the end of the subject string,
+or immediately before a newline character that is the last
+character in the string (by default).  A dollar sign need not be the
+last character of the pattern if a number of alternatives
+are involved, but it should be the last item in any branch
+in which it appears.  A dollar sign has no special meaning in a
+character class.
+
+@cindex Perl-style regular expressions, multiline
+The meanings of the circumflex and dollar sign characters are
+changed if the @code{M} modifier option is used. When this is
+the case, they match immediately after and immediately
+before an internal @code{\n} character, respectively, in addition
+to matching at the start and end of the subject string.  For
+example, the pattern @code{/^abc$/} matches the subject string
+@samp{def\nabc} in multiline mode, but not otherwise.  Consequently,
+patterns that are anchored in single line mode
+because all branches start with @code{^} are not anchored in
+multiline mode.
+
+@cindex Perl-style regular expressions, multiline
+Note that the sequences @code{\A}, @code{\Z}, and @code{\z}
+can be used to match the start and end of the subject in both
+modes, and if all branches of a pattern start with @code{\A}
+is it always anchored, whether the @code{M} modifier is set or not.
+
+@cindex Perl-style regular expressions, single line
+Outside a character class, a dot in the pattern matches any
+one character in the subject, including a non-printing character,
+but not (by default) newline.  If the @code{S} modifier is used,
+dots match newlines as well.  Actually, the handling of
+dot is entirely independent of the handling of circumflex
+and dollar sign, the only relationship being that they both
+involve newline characters. Dot has no special meaning in a
+character class.
+
+@node Square brackets
+@appendixsec Square brackets
+@cindex Perl-style regular expressions, character classes
+
+An opening square bracket introduces a character class, terminated
+by a closing square bracket.  A closing square bracket on its own
+is not special.  If a closing square bracket is required as a
+member of the class, it should be the first data character in
+the class (after an initial circumflex, if present) or escaped with a backslash.
+
+A character class matches a single character in the subject;
+the character must be in the set of characters defined by
+the class, unless the first character in the class is a circumflex,
+in which case the subject character must not be in
+the set defined by the class. If a circumflex is actually
+required as a member of the class, ensure it is not the
+first character, or escape it with a backslash.
+
+For example, the character class [aeiou] matches any lower
+case vowel, while [^aeiou] matches any character that is not
+a lower case vowel. Note that a circumflex is just a convenient
+venient notation for specifying the characters which are in
+the class by enumerating those that are not. It is not an
+assertion: it still consumes a character from the subject
+string, and fails if the current pointer is at the end of
+the string.
+
+@cindex Perl-style regular expressions, case-insensitive
+When caseless matching is set, any letters in a class
+represent both their upper case and lower case versions, so
+for example, a caseless @code{[aeiou]} matches uppercase
+and lowercase @samp{A}s, and a caseless @code{[^aeiou]}
+does not match @samp{A}, whereas a case-sensitive version would.
+
+@cindex Perl-style regular expressions, single line
+@cindex Perl-style regular expressions, multiline
+The newline character is never treated in any special way in
+character classes, whatever the setting of the @code{S} and
+@code{M} options (modifiers) is.  A class such as @code{[^a]} will
+always match a newline.
+
+The minus (hyphen) character can be used to specify a range
+of characters in a character class.  For example, @code{[d-m]}
+matches any letter between d and m, inclusive.  If a minus
+character is required in a class, it must be escaped with a
+backslash or appear in a position where it cannot be interpreted
+as indicating a range, typically as the first or last
+character in the class.
+
+It is not possible to have the literal character @code{]} as the
+end character of a range.  A pattern such as @code{[W-]46]} is
+interpreted as a class of two characters (@code{W} and @code{-})
+followed by a literal string @code{46]}, so it would match
+@samp{W46]} or @samp{-46]}. However, if the @code{]} is escaped
+with a backslash it is interpreted as the end of range, so
+@code{[W-\]46]} is interpreted as a single class containing a
+range followed by two separate characters. The octal or
+hexadecimal representation of @code{]} can also be used to end a range.
+
+Ranges operate in @sc{ascii} collating sequence. They can also be
+used for characters specified numerically, for example
+@code{[\000-\037]}. If a range that includes letters is used when
+caseless matching is set, it matches the letters in either
+case. For example, a caseless @code{[W-c]} is equivalent to
+@code{[][\^_`wxyzabc]}, matched caselessly, and if character
+tables for the French locale are in use, @code{[\xc8-\xcb]}
+matches accented E characters in both cases.
+
+Unlike in @sc{posix} mode, the character types @code{\d},
+@code{\D}, @code{\s}, @code{\S}, @code{\w}, and @code{\W}
+may also appear in a character class, and add the characters
+that they match to the class. For example, @code{[\dABCDEF]} matches any
+hexadecimal digit.  A circumflex can conveniently be used
+with the upper case character types to specify a more restricted
+set of characters than the matching lower case type.
+For example, the class @code{[^\W_]} matches any letter or digit,
+but not underscore.
+
+All non-alphameric characters other than @code{\}, @code{-},
+@code{^} (at the start) and the terminating @code{]}
+are non-special in character classes, but it does no harm
+if they are escaped.
+
+Perl 5.6 supports the @sc{posix} notation for character classes, which
+uses names enclosed by @code{[:} and @code{:]} within the enclosing
+square brackets, and @value{SSED} supports this notation as well.
+For example,
+
+@example
+     [01[:alpha:]%]
+@end example
+
+@noindent
+matches @samp{0}, @samp{1}, any alphabetic character, or @samp{%}.
+The supported class names are
+
+@table @code
+@item alnum
+Matches letters and digits
+
+@item alpha
+Matches letters
+
+@item ascii
+Matches character codes 0 - 127
+
+@item cntrl
+Matches control characters
+
+@item digit
+Matches decimal digits (same as \d)
+
+@item graph
+Matches printing characters, excluding space
+
+@item lower
+Matches lower case letters
+
+@item print
+Matches printing characters, including space
+
+@item punct
+Matches printing characters, excluding letters and digits
+
+@item space
+Matches white space (same as \s)
+
+@item upper
+Matches upper case letters
+
+@item word
+Matches ``word'' characters (same as \w)
+
+@item xdigit
+Matches hexadecimal digits
+@end table
+
+The names @code{ascii} and @code{word} are extensions valid only in
+Perl mode.  Another Perl extension is negation, which is
+indicated by a circumflex character after the colon. For example,
+
+@example
+     [12[:^digit:]]
+@end example
+
+@noindent
+matches @samp{1}, @samp{2}, or any non-digit.
+
+@node Options setting
+@appendixsec Options setting
+@cindex Perl-style regular expressions, toggling options
+@cindex Perl-style regular expressions, case-insensitive
+@cindex Perl-style regular expressions, multiline
+@cindex Perl-style regular expressions, single line
+@cindex Perl-style regular expressions, extended
+
+The settings of the @code{I}, @code{M}, @code{S}, @code{X}
+modifiers can be changed from within the pattern by
+a sequence of Perl option letters enclosed between @code{(?}
+and @code{)}. The option letters must be lowercase.
+
+For example, @code{(?im)} sets caseless, multiline matching. It is
+also possible to unset these options by preceding the letter
+with a hyphen; you can also have combined settings and unsettings:
+@code{(?im-sx)} sets caseless and multiline matching,
+while unsets single line matching (for dots) and extended
+whitespace interpretation.  If a letter appears both before
+and after the hyphen, the option is unset.
+
+The scope of these option changes depends on where in the
+pattern the setting occurs. For settings that are outside
+any subpattern (defined below), the effect is the same as if
+the options were set or unset at the start of matching. The
+following patterns all behave in exactly the same way:
+
+@example
+     (?i)abc
+     a(?i)bc
+     ab(?i)c
+     abc(?i)
+@end example
+
+which in turn is the same as specifying the pattern abc with
+the @code{I} modifier.  In other words, ``top level'' settings
+apply to the whole pattern (unless there are other
+changes inside subpatterns). If there is more than one setting
+of the same option at top level, the rightmost setting
+is used.
+
+If an option change occurs inside a subpattern, the effect
+is different.  This is a change of behaviour in Perl 5.005.
+An option change inside a subpattern affects only that part
+of the subpattern @emph{that follows} it, so
+
+@example
+     (a(?i)b)c
+@end example
+
+@noindent
+matches abc and aBc and no other  strings  (assuming
+case-sensitive matching is used).  By this means, options can
+be made to have different settings in different parts of the
+pattern.  Any changes made in one alternative do carry on
+into subsequent branches within the same subpattern.  For
+example,
+
+@example
+     (a(?i)b|c)
+@end example
+
+@noindent
+matches @samp{ab}, @samp{aB}, @samp{c}, and @samp{C},
+even though when matching @samp{C} the first branch is
+abandoned before the option setting.
+This is because the effects of option settings happen at
+compile time. There would be some very weird behaviour otherwise.
+
+@ignore
+There are two PCRE-specific options PCRE_UNGREEDY and PCRE_EXTRA
+that can be changed in the same way as the Perl-compatible options by
+using the characters U and X respectively.  The (?X) flag
+setting is special in that it must always occur earlier in
+the pattern than any of the additional features it turns on,
+even when it is at top level. It is best put at the start.
+@end ignore
+
+
+@node Non-capturing subpatterns
+@appendixsec Non-capturing subpatterns
+@cindex Perl-style regular expressions, non-capturing subpatterns
+
+Marking part of a pattern as a subpattern does two things.
+On one hand, it localizes a set of alternatives; on the other
+hand, it sets up the subpattern as a capturing subpattern (as
+defined above).  The subpattern can be backreferenced and
+referenced in the right side of @code{s} commands.
+
+For example, if the string @samp{the red king} is matched against
+the pattern
+
+@example
+     the ((red|white) (king|queen))
+@end example
+
+@noindent
+the captured substrings are @samp{red king}, @samp{red},
+and @samp{king}, and are numbered 1, 2, and 3.
+
+The fact that plain parentheses fulfil two functions is not
+always helpful.  There are often times when a grouping
+subpattern is required without a capturing requirement.  If an
+opening parenthesis is followed by @code{?:}, the subpattern does
+not do any capturing, and is not counted when computing the
+number of any subsequent capturing subpatterns. For example,
+if the string @samp{the white queen} is matched against the pattern
+
+@example
+     the ((?:red|white) (king|queen))
+@end example
+
+@noindent
+the captured substrings are @samp{white queen} and @samp{queen},
+and are numbered 1 and 2. The maximum number of captured
+substrings is 99, while the maximum number of all subpatterns,
+both capturing and non-capturing, is 200.
+
+As a convenient shorthand, if any option settings are
+equired at the start of a non-capturing subpattern, the
+option letters may appear between the @code{?} and the
+@code{:}.  Thus the two patterns
+
+@example
+   (?i:saturday|sunday)
+   (?:(?i)saturday|sunday)
+@end example
+
+@noindent
+match exactly the same set of strings.  Because alternative
+branches are tried from left to right, and options are not
+reset until the end of the subpattern is reached, an option
+setting in one branch does affect subsequent branches, so
+the above patterns match @samp{SUNDAY} as well as @samp{Saturday}.
+
+
+@node Repetition
+@appendixsec Repetition
+@cindex Perl-style regular expressions, repetitions
+
+Repetition is specified by quantifiers, which can follow any
+of the following items:
+
+@itemize @bullet
+@item
+a single character, possibly escaped
+
+@item
+the @code{.} special character
+
+@item
+a character class
+
+@item
+a back reference (see next section)
+
+@item
+a parenthesized subpattern (unless it is an assertion; @pxref{Assertions})
+@end itemize
+
+The general repetition quantifier specifies a minimum and
+maximum number of permitted matches, by giving the two
+numbers in curly brackets (braces), separated by a comma.
+The numbers must be less than 65536, and the first must be
+less than or equal to the second. For example:
+
+@example
+     z@{2,4@}
+@end example
+
+@noindent
+matches @samp{zz}, @samp{zzz}, or @samp{zzzz}. A closing brace on its own
+is not a special character. If the second number is omitted,
+but the comma is present, there is no upper limit; if the
+second number and the comma are both omitted, the quantifier
+specifies an exact number of required matches. Thus
+
+@example
+     [aeiou]@{3,@}
+@end example
+
+@noindent
+matches at least 3 successive vowels, but may match many
+more, while
+
+@example
+     \d@{8@}
+@end example
+
+@noindent
+matches exactly 8 digits.  An opening curly bracket that
+appears in a position where a quantifier is not allowed, or
+one that does not match the syntax of a quantifier, is taken
+as a literal character. For example, @{,6@} is not a quantifier,
+but a literal string of four characters.@footnote{It
+raises an error if @option{-R} is not used.}
+
+The quantifier @samp{@{0@}} is permitted, causing the expression to
+behave as if the previous item and the quantifier were not
+present.
+
+For convenience (and historical compatibility) the three
+most common quantifiers have single-character abbreviations:
+
+@table @code
+@item *
+is equivalent to @{0,@}
+
+@item +
+is equivalent to @{1,@}
+
+@item ?
+is equivalent to @{0,1@}
+@end table
+
+It is possible to construct infinite loops by following a
+subpattern that can match no characters with a quantifier
+that has no upper limit, for example:
+
+@example
+     (a?)*
+@end example
+
+Earlier versions of Perl used to give an error at
+compile time for such patterns. However, because there are
+cases where this can be useful, such patterns are now
+accepted, but if any repetition of the subpattern does in
+fact match no characters, the loop is forcibly broken.
+
+@cindex Greedy regular expression matching
+@cindex Perl-style regular expressions, stingy repetitions
+By default, the quantifiers are @dfn{greedy} like in @sc{posix}
+mode, that is, they match as much as possible (up to the maximum
+number of permitted times), without causing the rest of the
+pattern to fail. The classic example of where this gives problems
+is in trying to match comments in C programs. These appear between
+the sequences @code{/*} and @code{*/} and within the sequence, individual
+@code{*} and @code{/} characters may appear. An attempt to match C
+comments by applying the pattern
+
+@example
+     /\*.*\*/
+@end example
+
+@noindent
+to the string
+
+@example
+     /* first command */ not comment /* second comment */
+@end example
+
+@noindent
+
+fails, because it matches the entire string owing to the
+greediness of the @code{.*} item.
+
+However, if a quantifier is followed by a question mark, it
+ceases to be greedy, and instead matches the minimum number
+of times possible, so the pattern @code{/\*.*?\*/}
+does the right thing with the C comments. The meaning of the
+various quantifiers is not otherwise changed, just the preferred
+number of matches.  Do not confuse this use of question
+mark with its use as a quantifier in its own right.
+Because it has two uses, it can sometimes appear doubled, as in
+
+@example
+     \d??\d
+@end example
+
+which matches one digit by preference, but can match two if
+that is the only way the rest of the pattern matches.
+
+Note that greediness does not matter when specifying addresses,
+but can be nevertheless used to improve performance.
+
+@ignore
+   If the PCRE_UNGREEDY option is set (an option which is not
+   available in Perl), the quantifiers are not greedy by
+   default, but individual ones can be made greedy by following
+   them with a question mark. In other words, it inverts the
+   default behaviour.
+@end ignore
+
+When a parenthesized subpattern is quantified with a minimum
+repeat count that is greater than 1 or with a limited maximum,
+more store is required for the compiled pattern, in
+proportion to the size of the minimum or maximum.
+
+@cindex Perl-style regular expressions, single line
+If a pattern starts with @code{.*} or @code{.@{0,@}} and the
+@code{S} modifier is used, the pattern is implicitly anchored,
+because whatever follows will be tried against every character
+position in the subject string, so there is no point in
+retrying the overall match at any position after the first.
+PCRE treats such a pattern as though it were preceded by \A.
+
+When a capturing subpattern is repeated, the value captured
+is the substring that matched the final iteration. For example,
+after
+
+@example
+     (tweedle[dume]@{3@}\s*)+
+@end example
+
+@noindent
+has matched @samp{tweedledum tweedledee} the value of the
+captured substring is @samp{tweedledee}.  However, if there are
+nested capturing subpatterns, the corresponding captured
+values may have been set in previous iterations. For example,
+after
+
+@example
+     /(a|(b))+/
+@end example
+
+matches @samp{aba}, the value of the second captured substring is
+@samp{b}.
+
+@node Backreferences
+@appendixsec Backreferences
+@cindex Perl-style regular expressions, backreferences
+
+Outside a character class, a backslash followed by a digit
+greater than 0 (and possibly further digits) is a back
+reference to a capturing subpattern earlier (i.e.  to its
+left) in the pattern, provided there have been that many
+previous capturing left parentheses.
+
+However, if the decimal number following the backslash is
+less than 10, it is always taken as a back reference, and
+causes an error only if there are not that many capturing
+left parentheses in the entire pattern. In other words, the
+parentheses that are referenced need not be to the left of
+the reference for numbers less than 10. @ref{Backslash}
+for further details of the handling of digits following a backslash.
+
+A back reference matches whatever actually matched the capturing
+subpattern in the current subject string, rather than
+anything matching the subpattern itself. So the pattern
+
+@example
+     (sens|respons)e and \1ibility
+@end example
+
+@noindent
+matches @samp{sense and sensibility} and @samp{response and responsibility},
+but not @samp{sense and responsibility}. If caseful
+matching is in force at the time of the back reference, the
+case of letters is relevant. For example,
+
+@example
+     ((?i)blah)\s+\1
+@end example
+
+@noindent
+matches @samp{blah blah} and @samp{Blah Blah}, but not
+@samp{BLAH blah}, even though the original capturing
+subpattern is matched caselessly.
+
+There may be more than one back reference to the same subpattern.
+Also, if a subpattern has not actually been used in a
+particular match, any back references to it always fail. For
+example, the pattern
+
+@example
+     (a|(bc))\2
+@end example
+
+@noindent
+always fails if it starts to match @samp{a} rather than
+@samp{bc}.  Because there may be up to 99 back references, all
+digits following the backslash are taken as part of a potential
+back reference number; this is different from what happens
+in @sc{posix} mode. If the pattern continues with a digit
+character, some delimiter must be used to terminate the back
+reference.  If the @code{X} modifier option is set, this can be
+whitespace.  Otherwise an empty comment can be used, or the
+following character can be expressed in hexadecimal or octal.
+
+A back reference that occurs inside the parentheses to which
+it refers fails when the subpattern is first used, so, for
+example, @code{(a\1)} never matches.  However, such references
+can be useful inside repeated subpatterns. For example, the
+pattern
+
+@example
+     (a|b\1)+
+@end example
+
+@noindent
+matches any number of @samp{a}s and also @samp{aba}, @samp{ababbaa},
+etc. At each iteration of the subpattern, the back reference matches
+the character string corresponding to the previous iteration.  In
+order for this to work, the pattern must be such that the first
+iteration does not need to match the back reference.  This can be
+done using alternation, as in the example above, or by a
+quantifier with a minimum of zero.
+
+@node Assertions
+@appendixsec Assertions
+@cindex Perl-style regular expressions, assertions
+@cindex Perl-style regular expressions, asserting subpatterns
+
+An assertion is a test on the characters following or
+preceding the current matching point that does not actually
+consume any characters. The simple assertions coded as @code{\b},
+@code{\B}, @code{\A}, @code{\Z}, @code{\z}, @code{^} and @code{$}
+are described above. More complicated assertions are coded as
+subpatterns.  There are two kinds: those that look ahead of the
+current position in the subject string, and those that look behind it.
+
+@cindex Perl-style regular expressions, lookahead subpatterns
+An assertion subpattern is matched in the normal way, except
+that it does not cause the current matching position to be
+changed. Lookahead assertions start with @code{(?=} for positive
+assertions and @code{(?!} for negative assertions. For example,
+
+@example
+     \w+(?=;)
+@end example
+
+@noindent
+matches a word followed by a semicolon, but does not include
+the semicolon in the match, and
+
+@example
+     foo(?!bar)
+@end example
+
+@noindent
+matches any occurrence of @samp{foo} that is not followed by
+@samp{bar}.
+
+Note that the apparently similar pattern
+
+@example
+     (?!foo)bar
+@end example
+
+@noindent
+@cindex Perl-style regular expressions, lookbehind subpatterns
+finds any occurrence of @samp{bar} even if it is preceded by
+@samp{foo}, because the assertion @code{(?!foo)} is always true
+when the next three characters are @samp{bar}. A lookbehind
+assertion is needed to achieve this effect.
+Lookbehind assertions start with @code{(?<=} for positive
+assertions and @code{(?<!} for negative assertions. So,
+
+@example
+     (?<!foo)bar
+@end example
+
+achieves the required effect of finding an occurrence of
+@samp{bar} that is not preceded by @samp{foo}. The contents of a
+lookbehind assertion are restricted
+such that all the strings it matches must have a fixed
+length.  However, if there are several alternatives, they do
+not all have to have the same fixed length.  This is an extension
+compared with Perl 5.005, which requires all branches to match
+the same length of string. Thus
+
+@example
+     (?<=dogs|cats|)
+@end example
+
+@noindent
+is permitted, but the apparently equivalent regular expression
+
+@example
+     (?<!dogs?|cats?)
+@end example
+
+@noindent
+causes an error at compile time. Branches that match different
+length strings are permitted only at the top level of
+a lookbehind assertion: an assertion such as
+
+@example
+     (?<=ab(c|de))
+@end example
+
+@noindent
+is not permitted, because its single top-level branch can
+match two different lengths, but it is acceptable if rewritten
+to use two top-level branches:
+
+@example
+     (?<=abc|abde)
+@end example
+
+All this is required because lookbehind assertions simply
+move the current position back by the alternative's fixed
+width and then try to match.  If there are
+insufficient characters before the current position, the
+match is deemed to fail.  Lookbehinds, in conjunction with
+non-backtracking subpatterns can be particularly useful for
+matching at the ends of strings; an example is given at the end
+of the section on non-backtracking subpatterns.
+
+Several assertions (of any sort) may occur in succession.
+For example,
+
+@example
+     (?<=\d@{3@})(?<!999)foo
+@end example
+
+@noindent
+matches @samp{foo} preceded by three digits that are not @samp{999}.
+Notice that each of the assertions is applied independently
+at the same point in the subject string. First there is a
+check that the previous three characters are all digits, and
+then there is a check that the same three characters are not
+@samp{999}.  This pattern does not match @samp{foo} preceded by six
+characters, the first of which are digits and the last three
+of which are not @samp{999}.  For example, it doesn't match
+@samp{123abcfoo}. A pattern to do that is
+
+@example
+     (?<=\d@{3@}...)(?<!999)foo
+@end example
+
+@noindent
+This time the first assertion looks at the preceding six
+characters, checking that the first three are digits, and
+then the second assertion checks that the preceding three
+characters are not @samp{999}.  Actually, assertions can be
+nested in any combination, so one can write this as 
+
+@example
+     (?<=\d@{3@}(?!999)...)foo
+@end example
+
+or
+
+@example
+     (?<=\d@{3@}...(?<!999))foo
+@end example
+
+@noindent
+both of which might be considered more readable.
+
+Assertion subpatterns are not capturing subpatterns, and may
+not be repeated, because it makes no sense to assert the
+same thing several times. If any kind of assertion contains
+capturing subpatterns within it, these are counted for the
+purposes of numbering the capturing subpatterns in the whole
+pattern.  However, substring capturing is carried out only
+for positive assertions, because it does not make sense for
+negative assertions.
+
+Assertions count towards the maximum of 200 parenthesized
+subpatterns.
+
+@node Non-backtracking subpatterns
+@appendixsec Non-backtracking subpatterns
+@cindex Perl-style regular expressions, non-backtracking subpatterns
+
+With both maximizing and minimizing repetition, failure of
+what follows normally causes the repeated item to be evaluated
+again to see if a different number of repeats allows the
+rest of the pattern to match. Sometimes it is useful to
+prevent this, either to change the nature of the match, or
+to cause it fail earlier than it otherwise might, when the
+author of the pattern knows there is no point in carrying
+on.
+
+Consider, for example, the pattern @code{\d+foo} when applied to
+the subject line
+
+@example
+     123456bar
+@end example
+
+After matching all 6 digits and then failing to match @samp{foo},
+the normal action of the matcher is to try again with only 5
+digits matching the @code{\d+} item, and then with 4, and so on,
+before ultimately failing. Non-backtracking subpatterns
+provide the means for specifying that once a portion of the
+pattern has matched, it is not to be re-evaluated in this way,
+so the matcher would give up immediately on failing to match
+@samp{foo} the first time.  The notation is another kind of special
+parenthesis, starting with @code{(?>} as in this example:
+
+@example
+     (?>\d+)bar
+@end example
+
+This kind of parenthesis ``locks up'' the part of the pattern
+it contains once it has matched, and a failure further into
+the pattern is prevented from backtracking into it.
+Backtracking past it to previous items, however, works as
+normal.
+
+Non-backtracking subpatterns are not capturing subpatterns.  Simple
+cases such as the above example can be thought of as a maximizing
+repeat that must swallow everything it can.  So,
+while both @code{\d+} and @code{\d+?} are prepared to adjust the number of
+digits they match in order to make the rest of the pattern
+match, @code{(?>\d+)} can only match an entire sequence of digits.
+
+This construction can of course contain arbitrarily complicated
+subpatterns, and it can be nested.
+
+@cindex Perl-style regular expressions, lookbehind subpatterns
+Non-backtracking subpatterns can be used in conjunction with look-behind
+assertions to specify efficient matching at the end
+of the subject string. Consider a simple pattern such as
+
+@example
+     abcd$
+@end example
+
+@noindent
+when applied to a long string which does not match.  Because
+matching proceeds from left to right, @command{sed} will look for
+each @samp{a} in the subject and then see if what follows matches
+the rest of the pattern. If the pattern is specified as
+
+@example
+     ^.*abcd$
+@end example
+
+@noindent
+the initial @code{.*} matches the entire string at first, but when
+this fails (because there is no following @samp{a}), it backtracks
+to match all but the last character, then all but the
+last two characters, and so on. Once again the search for
+@samp{a} covers the entire string, from right to left, so we are
+no better off. However, if the pattern is written as
+
+@example
+     ^(?>.*)(?<=abcd)
+@end example
+
+there can be no backtracking for the .* item; it can match
+only the entire string. The subsequent lookbehind assertion
+does a single test on the last four characters. If it fails,
+the match fails immediately. For long strings, this approach
+makes a significant difference to the processing time.
+
+When a pattern contains an unlimited repeat inside a subpattern
+that can itself be repeated an unlimited number of
+times, the use of a once-only subpattern is the only way to
+avoid some failing matches taking a very long time
+indeed.@footnote{Actually, the matcher embedded in @value{SSED}
+    tries to do something for this in the simplest cases,
+    like @code{([^b]*b)*}.  These cases are actually quite
+    common: they happen for example in a regular expression
+    like @code{\/\*([^*]*\*)*\/} which matches C comments.}
+
+The pattern
+
+@example
+     (\D+|<\d+>)*[!?]
+@end example
+
+([^0-9<]+<(\d+>)?)*[!?]
+
+@noindent
+matches an unlimited number of substrings that either consist
+of non-digits, or digits enclosed in angular brackets, followed by
+an exclamation or question mark. When it matches, it runs quickly.
+However, if it is applied to
+
+@example
+     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+@end example
+
+@noindent
+it takes a long time before reporting failure.  This is
+because the string can be divided between the two repeats in
+a large number of ways, and all have to be tried.@footnote{The
+example used @code{[!?]} rather than a single character at the end,
+because both @value{SSED} and Perl have an optimization that allows
+for fast failure when a single character is used. They
+remember the last single character that is required for a
+match, and fail early if it is not present in the string.}
+
+If the pattern is changed to
+
+@example
+     ((?>\D+)|<\d+>)*[!?]
+@end example
+
+sequences of non-digits cannot be broken, and failure happens
+quickly.
+
+@node Conditional subpatterns
+@appendixsec Conditional subpatterns
+@cindex Perl-style regular expressions, conditional subpatterns
+
+It is possible to cause the matching process to obey a subpattern
+conditionally or to choose between two alternative
+subpatterns, depending on the result of an assertion, or
+whether a previous capturing subpattern matched or not. The
+two possible forms of conditional subpattern are
+
+@example
+     (?(@var{condition})@var{yes-pattern})
+     (?(@var{condition})@var{yes-pattern}|@var{no-pattern})
+@end example
+
+If the condition is satisfied, the yes-pattern is used; otherwise
+the no-pattern (if present) is used. If there are more than two
+alternatives in the subpattern, a compile-time error occurs.
+
+There are two kinds of condition. If the text between the
+parentheses consists of a sequence of digits, the condition
+is satisfied if the capturing subpattern of that number has
+previously matched.  The number must be greater than zero.
+Consider the following pattern, which contains non-significant
+white space to make it more readable (assume the @code{X} modifier)
+and to divide it into three parts for ease of discussion:
+
+@example
+     ( \( )?   [^()]+   (?(1) \) )
+@end example
+
+The first part matches an optional opening parenthesis, and
+if that character is present, sets it as the first captured
+substring. The second part matches one or more characters
+that are not parentheses. The third part is a conditional
+subpattern that tests whether the first set of parentheses
+matched or not.  If they did, that is, if subject started
+with an opening parenthesis, the condition is true, and so
+the yes-pattern is executed and a closing parenthesis is
+required. Otherwise, since no-pattern is not present, the
+subpattern matches nothing.  In other words, this pattern
+matches a sequence of non-parentheses, optionally enclosed
+in parentheses.
+
+@cindex Perl-style regular expressions, lookahead subpatterns
+If the condition is not a sequence of digits, it must be an
+assertion.  This may be a positive or negative lookahead or
+lookbehind assertion. Consider this pattern, again containing
+non-significant white space, and with the two alternatives
+on the second line:
+
+@example
+     (?(?=...[a-z])
+        \d\d-[a-z]@{3@}-\d\d |
+        \d\d-\d\d-\d\d )
+@end example
+
+The condition is a positive lookahead assertion that matches
+a letter that is three characters away from the current point.
+If a letter is found, the subject is matched against the first
+alternative @samp{@var{dd}-@var{aaa}-@var{dd}} (where @var{aaa} are
+letters and @var{dd} are digits); otherwise it is matched against 
+the second alternative, @samp{@var{dd}-@var{dd}-@var{dd}}.
+
+
+@node Recursive patterns
+@appendixsec Recursive patterns
+@cindex Perl-style regular expressions, recursive patterns
+@cindex Perl-style regular expressions, recursion
+
+Consider the problem of matching a string in parentheses,
+allowing for unlimited nested parentheses. Without the use
+of recursion, the best that can be done is to use a pattern
+that matches up to some fixed depth of nesting. It is not
+possible to handle an arbitrary nesting depth. Perl 5.6 has
+provided an experimental facility that allows regular
+expressions to recurse (amongst other things). It does this
+by interpolating Perl code in the expression at run time,
+and the code can refer to the expression itself. A Perl pattern
+tern to solve the parentheses problem can be created like
+this:
+
+@example
+     $re = qr@{\( (?: (?>[^()]+) | (?p@{$re@}) )* \)@}x;
+@end example
+
+The @code{(?p@{...@})} item interpolates Perl code at run time,
+and in this case refers recursively to the pattern in which it
+appears. Obviously, @command{sed} cannot support the interpolation of
+Perl code.  Instead, the special item @code{(?R)} is provided for
+the specific case of recursion. This pattern solves the
+parentheses problem (assume the @code{X} modifier option is used
+so that white space is ignored):
+
+@example
+     \( ( (?>[^()]+) | (?R) )* \)
+@end example
+
+First it matches an opening parenthesis. Then it matches any
+number of substrings which can either be a sequence of
+non-parentheses, or a recursive match of the pattern itself
+(i.e. a correctly parenthesized substring). Finally there is
+a closing parenthesis.
+
+This particular example pattern contains nested unlimited
+repeats, and so the use of a non-backtracking subpattern for
+matching strings of non-parentheses is important when applying
+the pattern to strings that do not match. For example, when
+it is applied to
+
+@example
+     (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
+@end example
+
+it yields a ``no match'' response quickly. However, if a
+standard backtracking subpattern is not used, the match runs
+for a very long time indeed because there are so many different
+ways the @code{+} and @code{*} repeats can carve up the subject,
+and all have to be tested before failure can be reported.
+
+The values set for any capturing subpatterns are those from
+the outermost level of the recursion at which the subpattern
+value is set. If the pattern above is matched against
+
+@example
+     (ab(cd)ef)
+@end example
+
+@noindent
+the value for the capturing parentheses is @samp{ef}, which is
+the last value taken on at the top level.
+
+@node Comments
+@appendixsec Comments
+@cindex Perl-style regular expressions, comments
+
+The sequence (?# marks the start of a comment which continues
+ues up to the next closing parenthesis. Nested parentheses
+are not permitted. The characters that make up a comment
+play no part in the pattern matching at all.
+
+@cindex Perl-style regular expressions, extended
+If the @code{X} modifier option is used, an unescaped @code{#} character
+outside a character class introduces a comment that continues
+up to the next newline character in the pattern.
+@end ifset
+
+
+@page
+@node Concept Index
+@unnumbered Concept Index
+
+This is a general index of all issues discussed in this manual, with the
+exception of the @command{sed} commands and command-line options.
+
+@printindex cp
+
+@page
+@node Command and Option Index
+@unnumbered Command and Option Index
+
+This is an alphabetical list of all @command{sed} commands and command-line
+options.
+
+@printindex fn
+
+@contents
+@bye
+
+@c XXX FIXME: the term "cycle" is never defined...
Index: /tags/kBuild-0.1.4/src/sed/doc/sed.1
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/sed.1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/sed.1	(revision 1780)
@@ -0,0 +1,374 @@
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.28.
+.TH SED "1" "February 2006" "sed version 4.1.4" "User Commands"
+.SH NAME
+sed \- stream editor for filtering and transforming text
+.SH SYNOPSIS
+.B sed
+[\fIOPTION\fR]... \fI{script-only-if-no-other-script} \fR[\fIinput-file\fR]...
+.SH DESCRIPTION
+.ds sd \fIsed\fP
+.ds Sd \fISed\fP
+\*(Sd is a stream editor.
+A stream editor is used to perform basic text
+transformations on an input stream
+(a file or input from a pipeline).
+While in some ways similar to an editor which
+permits scripted edits (such as \fIed\fP),
+\*(sd works by making only one pass over the
+input(s), and is consequently more efficient.
+But it is \*(sd's ability to filter text in a pipeline
+which particularly distinguishes it from other types of
+editors.
+.HP
+\fB\-n\fR, \fB\-\-quiet\fR, \fB\-\-silent\fR
+.IP
+suppress automatic printing of pattern space
+.HP
+\fB\-e\fR script, \fB\-\-expression\fR=\fIscript\fR
+.IP
+add the script to the commands to be executed
+.HP
+\fB\-f\fR script-file, \fB\-\-file\fR=\fIscript\-file\fR
+.IP
+add the contents of script-file to the commands to be executed
+.HP
+\fB\-i[SUFFIX]\fR, \fB\-\-in\-place\fR[=\fISUFFIX\fR]
+.IP
+edit files in place (makes backup if extension supplied)
+.HP
+\fB\-l\fR N, \fB\-\-line\-length\fR=\fIN\fR
+.IP
+specify the desired line-wrap length for the `l' command
+.HP
+\fB\-\-posix\fR
+.IP
+disable all GNU extensions.
+.HP
+\fB\-r\fR, \fB\-\-regexp\-extended\fR
+.IP
+use extended regular expressions in the script.
+.HP
+\fB\-s\fR, \fB\-\-separate\fR
+.IP
+consider files as separate rather than as a single continuous
+long stream.
+.HP
+\fB\-u\fR, \fB\-\-unbuffered\fR
+.IP
+load minimal amounts of data from the input files and flush
+the output buffers more often
+.TP
+\fB\-\-help\fR
+display this help and exit
+.TP
+\fB\-\-version\fR
+output version information and exit
+.PP
+If no \fB\-e\fR, \fB\-\-expression\fR, \fB\-f\fR, or \fB\-\-file\fR option is given, then the first
+non-option argument is taken as the sed script to interpret.  All
+remaining arguments are names of input files; if no input files are
+specified, then the standard input is read.
+.PP
+E-mail bug reports to: bonzini@gnu.org .
+Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.
+.SH "COMMAND SYNOPSIS"
+This is just a brief synopsis of \*(sd commands to serve as
+a reminder to those who already know \*(sd;
+other documentation (such as the texinfo document)
+must be consulted for fuller descriptions.
+.SS
+Zero-address ``commands''
+.TP
+.RI :\  label
+Label for
+.B b
+and
+.B t
+commands.
+.TP
+.RI # comment
+The comment extends until the next newline (or the end of a
+.B -e
+script fragment).
+.TP
+}
+The closing bracket of a { } block.
+.SS
+Zero- or One- address commands
+.TP
+=
+Print the current line number.
+.TP
+a \e
+.TP
+.I text
+Append
+.IR text ,
+which has each embedded newline preceded by a backslash.
+.TP
+i \e
+.TP
+.I text
+Insert
+.IR text ,
+which has each embedded newline preceded by a backslash.
+.TP
+q
+Immediately quit the \*(sd script without processing
+any more input,
+except that if auto-print is not disabled
+the current pattern space will be printed.
+.TP
+Q
+Immediately quit the \*(sd script without processing
+any more input.
+.TP
+.RI r\  filename
+Append text read from
+.IR filename .
+.TP
+.RI R\  filename
+Append a line read from
+.IR filename .
+.SS
+Commands which accept address ranges
+.TP
+{
+Begin a block of commands (end with a }).
+.TP
+.RI b\  label
+Branch to
+.IR label ;
+if
+.I label
+is omitted, branch to end of script.
+.TP
+.RI t\  label
+If a s/// has done a successful substitution since the
+last input line was read and since the last t or T
+command, then branch to
+.IR label ;
+if
+.I label
+is omitted, branch to end of script.
+.TP
+.RI T\  label
+If no s/// has done a successful substitution since the
+last input line was read and since the last t or T
+command, then branch to
+.IR label ;
+if
+.I label
+is omitted, branch to end of script.
+.TP
+c \e
+.TP
+.I text
+Replace the selected lines with
+.IR text ,
+which has each embedded newline preceded by a backslash.
+.TP
+d
+Delete pattern space.
+Start next cycle.
+.TP
+D
+Delete up to the first embedded newline in the pattern space.
+Start next cycle, but skip reading from the input
+if there is still data in the pattern space.
+.TP
+h H
+Copy/append pattern space to hold space.
+.TP
+g G
+Copy/append hold space to pattern space.
+.TP
+x
+Exchange the contents of the hold and pattern spaces.
+.TP
+l
+List out the current line in a ``visually unambiguous'' form.
+.TP
+n N
+Read/append the next line of input into the pattern space.
+.TP
+p
+Print the current pattern space.
+.TP
+P
+Print up to the first embedded newline of the current pattern space.
+.TP
+.RI s/ regexp / replacement /
+Attempt to match
+.I regexp
+against the pattern space.
+If successful, replace that portion matched
+with
+.IR replacement .
+The
+.I replacement
+may contain the special character
+.B &
+to refer to that portion of the pattern space which matched,
+and the special escapes \e1 through \e9 to refer to the
+corresponding matching sub-expressions in the
+.IR regexp .
+.TP
+.RI w\  filename
+Write the current pattern space to
+.IR filename .
+.TP
+.RI W\  filename
+Write the first line of the current pattern space to
+.IR filename .
+.TP
+.RI y/ source / dest /
+Transliterate the characters in the pattern space which appear in
+.I source
+to the corresponding character in
+.IR dest .
+.SH
+Addresses
+\*(Sd commands can be given with no addresses, in which
+case the command will be executed for all input lines;
+with one address, in which case the command will only be executed
+for input lines which match that address; or with two
+addresses, in which case the command will be executed
+for all input lines which match the inclusive range of
+lines starting from the first address and continuing to
+the second address.
+Three things to note about address ranges:
+the syntax is
+.IR addr1 , addr2
+(i.e., the addresses are separated by a comma);
+the line which
+.I addr1
+matched will always be accepted,
+even if
+.I addr2
+selects an earlier line;
+and if
+.I addr2
+is a
+.IR regexp ,
+it will not be tested against the line that
+.I addr1
+matched.
+.PP
+After the address (or address-range),
+and before the command, a
+.B !
+may be inserted,
+which specifies that the command shall only be
+executed if the address (or address-range) does
+.B not
+match.
+.PP
+The following address types are supported:
+.TP
+.I number
+Match only the specified line
+.IR number .
+.TP
+.IR first ~ step
+Match every
+.IR step 'th
+line starting with line
+.IR first .
+For example, ``sed -n 1~2p'' will print all the odd-numbered lines in
+the input stream, and the address 2~5 will match every fifth line,
+starting with the second. (This is an extension.)
+.TP
+$
+Match the last line.
+.TP
+.RI / regexp /
+Match lines matching the regular expression
+.IR regexp .
+.TP
+.BI \fR\e\fPc regexp c
+Match lines matching the regular expression
+.IR regexp .
+The
+.B c
+may be any character.
+.PP
+GNU \*(sd also supports some special 2-address forms:
+.TP
+.RI 0, addr2
+Start out in "matched first address" state, until
+.I addr2
+is found.
+This is similar to
+.RI 1, addr2 ,
+except that if
+.I addr2
+matches the very first line of input the
+.RI 0, addr2
+form will be at the end of its range, whereas the
+.RI 1, addr2
+form will still be at the beginning of its range.
+.TP
+.IR addr1 ,+ N
+Will match
+.I addr1
+and the
+.I N
+lines following
+.IR addr1 .
+.TP
+.IR addr1 ,~ N
+Will match
+.I addr1
+and the lines following
+.I addr1
+until the next line whose input line number is a multiple of
+.IR N .
+.SH "REGULAR EXPRESSIONS"
+POSIX.2 BREs
+.I should
+be supported, but they aren't completely because of performance
+problems.
+The
+.B \en
+sequence in a regular expression matches the newline character,
+and similarly for
+.BR \ea ,
+.BR \et ,
+and other sequences.
+.SH BUGS
+.PP
+E-mail bug reports to
+.BR bonzini@gnu.org .
+Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.
+Also, please include the output of ``sed --version'' in the body
+of your report if at all possible.
+.SH COPYRIGHT
+Copyright \(co 2003 Free Software Foundation, Inc.
+.br
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,
+to the extent permitted by law.
+.SH "SEE ALSO"
+.BR awk (1),
+.BR ed (1),
+.BR grep (1),
+.BR tr (1),
+.BR perlre (1),
+sed.info,
+any of various books on \*(sd,
+.na
+the \*(sd FAQ (http://sed.sf.net/grabbag/tutorials/sedfaq.txt),
+http://sed.sf.net/grabbag/.
+.PP
+The full documentation for
+.B sed
+is maintained as a Texinfo manual.  If the
+.B info
+and
+.B sed
+programs are properly installed at your site, the command
+.IP
+.B info sed
+.PP
+should give you access to the complete manual.
Index: /tags/kBuild-0.1.4/src/sed/doc/sed.info
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/sed.info	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/sed.info	(revision 1780)
@@ -0,0 +1,81 @@
+This is ../../doc/sed.info, produced by makeinfo version 4.5 from
+../../doc/sed.texi.
+
+INFO-DIR-SECTION Text creation and manipulation
+START-INFO-DIR-ENTRY
+* sed: (sed).                   Stream EDitor.
+
+END-INFO-DIR-ENTRY
+
+This file documents version 4.1.5 of GNU `sed', a stream editor.
+
+   Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software
+Foundation, Inc.
+
+   This document is released under the terms of the GNU Free
+Documentation License as published by the Free Software Foundation;
+either version 1.1, or (at your option) any later version.
+
+   You should have received a copy of the GNU Free Documentation
+License along with GNU `sed'; see the file `COPYING.DOC'.  If not,
+write to the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02110-1301, USA.
+
+   There are no Cover Texts and no Invariant Sections; this text, along
+with its equivalent in the printed manual, constitutes the Title Page.
+
+Indirect:
+sed.info-1: 935
+sed.info-2: 50405
+
+Tag Table:
+(Indirect)
+Node: Top935
+Node: Introduction3816
+Node: Invoking sed4370
+Ref: Invoking sed-Footnote-19396
+Ref: Invoking sed-Footnote-29588
+Node: sed Programs9691
+Node: Execution Cycle10838
+Ref: Execution Cycle-Footnote-112011
+Node: Addresses12322
+Node: Regular Expressions17061
+Node: Common Commands24610
+Node: The "s" Command26608
+Ref: The "s" Command-Footnote-130940
+Node: Other Commands31012
+Ref: Other Commands-Footnote-136149
+Node: Programming Commands36221
+Node: Extended Commands37130
+Node: Escapes40705
+Ref: Escapes-Footnote-143711
+Node: Examples43902
+Node: Centering lines44997
+Node: Increment a number45909
+Ref: Increment a number-Footnote-147489
+Node: Rename files to lower case47609
+Node: Print bash environment50405
+Node: Reverse chars of lines51185
+Ref: Reverse chars of lines-Footnote-152202
+Node: tac52424
+Node: cat -n53206
+Node: cat -b55063
+Node: wc -c55815
+Ref: wc -c-Footnote-157748
+Node: wc -w57817
+Node: wc -l59289
+Node: head59526
+Node: tail59850
+Node: uniq61534
+Node: uniq -d62330
+Node: uniq -u63054
+Node: cat -s63778
+Node: Limitations65667
+Node: Other Resources66507
+Node: Reporting Bugs67433
+Ref: Reporting Bugs-Footnote-173962
+Node: Extended regexps74033
+Node: Concept Index75200
+Node: Command and Option Index85215
+
+End Tag Table
Index: /tags/kBuild-0.1.4/src/sed/doc/sed.info-1
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/sed.info-1	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/sed.info-1	(revision 1780)
@@ -0,0 +1,1353 @@
+This is ../../doc/sed.info, produced by makeinfo version 4.5 from
+../../doc/sed.texi.
+
+INFO-DIR-SECTION Text creation and manipulation
+START-INFO-DIR-ENTRY
+* sed: (sed).                   Stream EDitor.
+
+END-INFO-DIR-ENTRY
+
+This file documents version 4.1.5 of GNU `sed', a stream editor.
+
+   Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software
+Foundation, Inc.
+
+   This document is released under the terms of the GNU Free
+Documentation License as published by the Free Software Foundation;
+either version 1.1, or (at your option) any later version.
+
+   You should have received a copy of the GNU Free Documentation
+License along with GNU `sed'; see the file `COPYING.DOC'.  If not,
+write to the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02110-1301, USA.
+
+   There are no Cover Texts and no Invariant Sections; this text, along
+with its equivalent in the printed manual, constitutes the Title Page.
+
+File: sed.info,  Node: Top,  Next: Introduction,  Up: (dir)
+
+
+
+This file documents version 4.1.5 of GNU `sed', a stream editor.
+
+   Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software
+Foundation, Inc.
+
+   This document is released under the terms of the GNU Free
+Documentation License as published by the Free Software Foundation;
+either version 1.1, or (at your option) any later version.
+
+   You should have received a copy of the GNU Free Documentation
+License along with GNU `sed'; see the file `COPYING.DOC'.  If not,
+write to the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02110-1301, USA.
+
+   There are no Cover Texts and no Invariant Sections; this text, along
+with its equivalent in the printed manual, constitutes the Title Page.
+* Menu:
+
+* Introduction::               Introduction
+* Invoking sed::               Invocation
+* sed Programs::               `sed' programs
+* Examples::                   Some sample scripts
+* Limitations::                Limitations and (non-)limitations of GNU `sed'
+* Other Resources::            Other resources for learning about `sed'
+* Reporting Bugs::             Reporting bugs
+
+* Extended regexps::           `egrep'-style regular expressions
+
+* Concept Index::              A menu with all the topics in this manual.
+* Command and Option Index::   A menu with all `sed' commands and
+                               command-line options.
+
+--- The detailed node listing ---
+
+sed Programs:
+* Execution Cycle::                 How `sed' works
+* Addresses::                       Selecting lines with `sed'
+* Regular Expressions::             Overview of regular expression syntax
+* Common Commands::                 Often used commands
+* The "s" Command::                 `sed''s Swiss Army Knife
+* Other Commands::                  Less frequently used commands
+* Programming Commands::            Commands for `sed' gurus
+* Extended Commands::               Commands specific of GNU `sed'
+* Escapes::                         Specifying special characters
+
+Examples:
+* Centering lines::
+* Increment a number::
+* Rename files to lower case::
+* Print bash environment::
+* Reverse chars of lines::
+* tac::                             Reverse lines of files
+* cat -n::                          Numbering lines
+* cat -b::                          Numbering non-blank lines
+* wc -c::                           Counting chars
+* wc -w::                           Counting words
+* wc -l::                           Counting lines
+* head::                            Printing the first lines
+* tail::                            Printing the last lines
+* uniq::                            Make duplicate lines unique
+* uniq -d::                         Print duplicated lines of input
+* uniq -u::                         Remove all duplicated lines
+* cat -s::                          Squeezing blank lines
+
+
+File: sed.info,  Node: Introduction,  Next: Invoking sed,  Prev: Top,  Up: Top
+
+Introduction
+************
+
+   `sed' is a stream editor.  A stream editor is used to perform basic
+text transformations on an input stream (a file or input from a
+pipeline).  While in some ways similar to an editor which permits
+scripted edits (such as `ed'), `sed' works by making only one pass over
+the input(s), and is consequently more efficient.  But it is `sed''s
+ability to filter text in a pipeline which particularly distinguishes
+it from other types of editors.
+
+
+File: sed.info,  Node: Invoking sed,  Next: sed Programs,  Prev: Introduction,  Up: Top
+
+Invocation
+**********
+
+   Normally `sed' is invoked like this:
+
+     sed SCRIPT INPUTFILE...
+
+   The full format for invoking `sed' is:
+
+     sed OPTIONS... [SCRIPT] [INPUTFILE...]
+
+   If you do not specify INPUTFILE, or if INPUTFILE is `-', `sed'
+filters the contents of the standard input.  The SCRIPT is actually the
+first non-option parameter, which `sed' specially considers a script
+and not an input file if (and only if) none of the other OPTIONS
+specifies a script to be executed, that is if neither of the `-e' and
+`-f' options is specified.
+
+   `sed' may be invoked with the following command-line options:
+
+`--version'
+     Print out the version of `sed' that is being run and a copyright
+     notice, then exit.
+
+`--help'
+     Print a usage message briefly summarizing these command-line
+     options and the bug-reporting address, then exit.
+
+`-n'
+`--quiet'
+`--silent'
+     By default, `sed' prints out the pattern space at the end of each
+     cycle through the script.  These options disable this automatic
+     printing, and `sed' only produces output when explicitly told to
+     via the `p' command.
+
+`-i[SUFFIX]'
+`--in-place[=SUFFIX]'
+     This option specifies that files are to be edited in-place.  GNU
+     `sed' does this by creating a temporary file and sending output to
+     this file rather than to the standard output.(1).
+
+     This option implies `-s'.
+
+     When the end of the file is reached, the temporary file is renamed
+     to the output file's original name.  The extension, if supplied,
+     is used to modify the name of the old file before renaming the
+     temporary file, thereby making a backup copy(2)).
+
+     This rule is followed: if the extension doesn't contain a `*',
+     then it is appended to the end of the current filename as a
+     suffix; if the extension does contain one or more `*' characters,
+     then _each_ asterisk is replaced with the current filename.  This
+     allows you to add a prefix to the backup file, instead of (or in
+     addition to) a suffix, or even to place backup copies of the
+     original files into another directory (provided the directory
+     already exists).
+
+     If no extension is supplied, the original file is overwritten
+     without making a backup.
+
+`-l N'
+`--line-length=N'
+     Specify the default line-wrap length for the `l' command.  A
+     length of 0 (zero) means to never wrap long lines.  If not
+     specified, it is taken to be 70.
+
+`--posix'
+     GNU `sed' includes several extensions to POSIX sed.  In order to
+     simplify writing portable scripts, this option disables all the
+     extensions that this manual documents, including additional
+     commands.  Most of the extensions accept `sed' programs that are
+     outside the syntax mandated by POSIX, but some of them (such as
+     the behavior of the `N' command described in *note Reporting
+     Bugs::) actually violate the standard.  If you want to disable
+     only the latter kind of extension, you can set the
+     `POSIXLY_CORRECT' variable to a non-empty value.
+
+`-r'
+`--regexp-extended'
+     Use extended regular expressions rather than basic regular
+     expressions.  Extended regexps are those that `egrep' accepts;
+     they can be clearer because they usually have less backslashes,
+     but are a GNU extension and hence scripts that use them are not
+     portable.  *Note Extended regular expressions: Extended regexps.
+
+`-s'
+`--separate'
+     By default, `sed' will consider the files specified on the command
+     line as a single continuous long stream.  This GNU `sed' extension
+     allows the user to consider them as separate files: range
+     addresses (such as `/abc/,/def/') are not allowed to span several
+     files, line numbers are relative to the start of each file, `$'
+     refers to the last line of each file, and files invoked from the
+     `R' commands are rewound at the start of each file.
+
+`-u'
+`--unbuffered'
+     Buffer both input and output as minimally as practical.  (This is
+     particularly useful if the input is coming from the likes of `tail
+     -f', and you wish to see the transformed output as soon as
+     possible.)
+
+`-e SCRIPT'
+`--expression=SCRIPT'
+     Add the commands in SCRIPT to the set of commands to be run while
+     processing the input.
+
+`-f SCRIPT-FILE'
+`--file=SCRIPT-FILE'
+     Add the commands contained in the file SCRIPT-FILE to the set of
+     commands to be run while processing the input.
+
+
+   If no `-e', `-f', `--expression', or `--file' options are given on
+the command-line, then the first non-option argument on the command
+line is taken to be the SCRIPT to be executed.
+
+   If any command-line parameters remain after processing the above,
+these parameters are interpreted as the names of input files to be
+processed.  A file name of `-' refers to the standard input stream.
+The standard input will be processed if no file names are specified.
+
+   ---------- Footnotes ----------
+
+   (1) This applies to commands such as `=', `a', `c', `i', `l', `p'.
+You can still write to the standard output by using the `w' or `W'
+commands together with the `/dev/stdout' special file
+
+   (2) Note that GNU `sed' creates the backup     file whether or not
+any output is actually changed.
+
+
+File: sed.info,  Node: sed Programs,  Next: Examples,  Prev: Invoking sed,  Up: Top
+
+`sed' Programs
+**************
+
+   A `sed' program consists of one or more `sed' commands, passed in by
+one or more of the `-e', `-f', `--expression', and `--file' options, or
+the first non-option argument if zero of these options are used.  This
+document will refer to "the" `sed' script; this is understood to mean
+the in-order catenation of all of the SCRIPTs and SCRIPT-FILEs passed
+in.
+
+   Each `sed' command consists of an optional address or address range,
+followed by a one-character command name and any additional
+command-specific code.
+
+* Menu:
+
+* Execution Cycle::          How `sed' works
+* Addresses::                Selecting lines with `sed'
+* Regular Expressions::      Overview of regular expression syntax
+* Common Commands::          Often used commands
+* The "s" Command::          `sed''s Swiss Army Knife
+* Other Commands::           Less frequently used commands
+* Programming Commands::     Commands for `sed' gurus
+* Extended Commands::        Commands specific of GNU `sed'
+* Escapes::                  Specifying special characters
+
+
+File: sed.info,  Node: Execution Cycle,  Next: Addresses,  Up: sed Programs
+
+How `sed' Works
+===============
+
+   `sed' maintains two data buffers: the active _pattern_ space, and
+the auxiliary _hold_ space. Both are initially empty.
+
+   `sed' operates by performing the following cycle on each lines of
+input: first, `sed' reads one line from the input stream, removes any
+trailing newline, and places it in the pattern space.  Then commands
+are executed; each command can have an address associated to it:
+addresses are a kind of condition code, and a command is only executed
+if the condition is verified before the command is to be executed.
+
+   When the end of the script is reached, unless the `-n' option is in
+use, the contents of pattern space are printed out to the output
+stream, adding back the trailing newline if it was removed.(1) Then the
+next cycle starts for the next input line.
+
+   Unless special commands (like `D') are used, the pattern space is
+deleted between two cycles. The hold space, on the other hand, keeps
+its data between cycles (see commands `h', `H', `x', `g', `G' to move
+data between both buffers).
+
+   ---------- Footnotes ----------
+
+   (1) Actually,   if `sed' prints a line without the terminating
+newline, it will   nevertheless print the missing newline as soon as
+more text is sent to   the same output stream, which gives the "least
+expected surprise"   even though it does not make commands like `sed -n
+p' exactly   identical to `cat'.
+
+
+File: sed.info,  Node: Addresses,  Next: Regular Expressions,  Prev: Execution Cycle,  Up: sed Programs
+
+Selecting lines with `sed'
+==========================
+
+   Addresses in a `sed' script can be in any of the following forms:
+`NUMBER'
+     Specifying a line number will match only that line in the input.
+     (Note that `sed' counts lines continuously across all input files
+     unless `-i' or `-s' options are specified.)
+
+`FIRST~STEP'
+     This GNU extension matches every STEPth line starting with line
+     FIRST.  In particular, lines will be selected when there exists a
+     non-negative N such that the current line-number equals FIRST + (N
+     * STEP).  Thus, to select the odd-numbered lines, one would use
+     `1~2'; to pick every third line starting with the second, `2~3'
+     would be used; to pick every fifth line starting with the tenth,
+     use `10~5'; and `50~0' is just an obscure way of saying `50'.
+
+`$'
+     This address matches the last line of the last file of input, or
+     the last line of each file when the `-i' or `-s' options are
+     specified.
+
+`/REGEXP/'
+     This will select any line which matches the regular expression
+     REGEXP.  If REGEXP itself includes any `/' characters, each must
+     be escaped by a backslash (`\').
+
+     The empty regular expression `//' repeats the last regular
+     expression match (the same holds if the empty regular expression is
+     passed to the `s' command).  Note that modifiers to regular
+     expressions are evaluated when the regular expression is compiled,
+     thus it is invalid to specify them together with the empty regular
+     expression.
+
+`\%REGEXP%'
+     (The `%' may be replaced by any other single character.)
+
+     This also matches the regular expression REGEXP, but allows one to
+     use a different delimiter than `/'.  This is particularly useful
+     if the REGEXP itself contains a lot of slashes, since it avoids
+     the tedious escaping of every `/'.  If REGEXP itself includes any
+     delimiter characters, each must be escaped by a backslash (`\').
+
+`/REGEXP/I'
+`\%REGEXP%I'
+     The `I' modifier to regular-expression matching is a GNU extension
+     which causes the REGEXP to be matched in a case-insensitive manner.
+
+`/REGEXP/M'
+`\%REGEXP%M'
+     The `M' modifier to regular-expression matching is a GNU `sed'
+     extension which causes `^' and `$' to match respectively (in
+     addition to the normal behavior) the empty string after a newline,
+     and the empty string before a newline.  There are special character
+     sequences (`\`' and `\'') which always match the beginning or the
+     end of the buffer.  `M' stands for `multi-line'.
+
+
+   If no addresses are given, then all lines are matched; if one
+address is given, then only lines matching that address are matched.
+
+   An address range can be specified by specifying two addresses
+separated by a comma (`,').  An address range matches lines starting
+from where the first address matches, and continues until the second
+address matches (inclusively).
+
+   If the second address is a REGEXP, then checking for the ending
+match will start with the line _following_ the line which matched the
+first address: a range will always span at least two lines (except of
+course if the input stream ends).
+
+   If the second address is a NUMBER less than (or equal to) the line
+matching the first address, then only the one line is matched.
+
+   GNU `sed' also supports some special two-address forms; all these
+are GNU extensions:
+`0,/REGEXP/'
+     A line number of `0' can be used in an address specification like
+     `0,/REGEXP/' so that `sed' will try to match REGEXP in the first
+     input line too.  In other words, `0,/REGEXP/' is similar to
+     `1,/REGEXP/', except that if ADDR2 matches the very first line of
+     input the `0,/REGEXP/' form will consider it to end the range,
+     whereas the `1,/REGEXP/' form will match the beginning of its
+     range and hence make the range span up to the _second_ occurrence
+     of the regular expression.
+
+     Note that this is the only place where the `0' address makes
+     sense; there is no 0-th line and commands which are given the `0'
+     address in any other way will give an error.
+
+`ADDR1,+N'
+     Matches ADDR1 and the N lines following ADDR1.
+
+`ADDR1,~N'
+     Matches ADDR1 and the lines following ADDR1 until the next line
+     whose input line number is a multiple of N.
+
+   Appending the `!' character to the end of an address specification
+negates the sense of the match.  That is, if the `!' character follows
+an address range, then only lines which do _not_ match the address range
+will be selected.  This also works for singleton addresses, and,
+perhaps perversely, for the null address.
+
+
+File: sed.info,  Node: Regular Expressions,  Next: Common Commands,  Prev: Addresses,  Up: sed Programs
+
+Overview of Regular Expression Syntax
+=====================================
+
+   To know how to use `sed', people should understand regular
+expressions ("regexp" for short).  A regular expression is a pattern
+that is matched against a subject string from left to right.  Most
+characters are "ordinary": they stand for themselves in a pattern, and
+match the corresponding characters in the subject.  As a trivial
+example, the pattern
+
+          The quick brown fox
+
+matches a portion of a subject string that is identical to itself.  The
+power of regular expressions comes from the ability to include
+alternatives and repetitions in the pattern.  These are encoded in the
+pattern by the use of "special characters", which do not stand for
+themselves but instead are interpreted in some special way.  Here is a
+brief description of regular expression syntax as used in `sed'.
+
+`CHAR'
+     A single ordinary character matches itself.
+
+`*'
+     Matches a sequence of zero or more instances of matches for the
+     preceding regular expression, which must be an ordinary character,
+     a special character preceded by `\', a `.', a grouped regexp (see
+     below), or a bracket expression.  As a GNU extension, a postfixed
+     regular expression can also be followed by `*'; for example, `a**'
+     is equivalent to `a*'.  POSIX 1003.1-2001 says that `*' stands for
+     itself when it appears at the start of a regular expression or
+     subexpression, but many nonGNU implementations do not support this
+     and portable scripts should instead use `\*' in these contexts.
+
+`\+'
+     As `*', but matches one or more.  It is a GNU extension.
+
+`\?'
+     As `*', but only matches zero or one.  It is a GNU extension.
+
+`\{I\}'
+     As `*', but matches exactly I sequences (I is a decimal integer;
+     for portability, keep it between 0 and 255 inclusive).
+
+`\{I,J\}'
+     Matches between I and J, inclusive, sequences.
+
+`\{I,\}'
+     Matches more than or equal to I sequences.
+
+`\(REGEXP\)'
+     Groups the inner REGEXP as a whole, this is used to:
+
+        * Apply postfix operators, like `\(abcd\)*': this will search
+          for zero or more whole sequences of `abcd', while `abcd*'
+          would search for `abc' followed by zero or more occurrences
+          of `d'.  Note that support for `\(abcd\)*' is required by
+          POSIX 1003.1-2001, but many non-GNU implementations do not
+          support it and hence it is not universally portable.
+
+        * Use back references (see below).
+
+`.'
+     Matches any character, including newline.
+
+`^'
+     Matches the null string at beginning of line, i.e. what appears
+     after the circumflex must appear at the beginning of line.
+     `^#include' will match only lines where `#include' is the first
+     thing on line--if there are spaces before, for example, the match
+     fails.  `^' acts as a special character only at the beginning of
+     the regular expression or subexpression (that is, after `\(' or
+     `\|').  Portable scripts should avoid `^' at the beginning of a
+     subexpression, though, as POSIX allows implementations that treat
+     `^' as an ordinary character in that context.
+
+`$'
+     It is the same as `^', but refers to end of line.  `$' also acts
+     as a special character only at the end of the regular expression
+     or subexpression (that is, before `\)' or `\|'), and its use at
+     the end of a subexpression is not portable.
+
+`[LIST]'
+`[^LIST]'
+     Matches any single character in LIST: for example, `[aeiou]'
+     matches all vowels.  A list may include sequences like
+     `CHAR1-CHAR2', which matches any character between (inclusive)
+     CHAR1 and CHAR2.
+
+     A leading `^' reverses the meaning of LIST, so that it matches any
+     single character _not_ in LIST.  To include `]' in the list, make
+     it the first character (after the `^' if needed), to include `-'
+     in the list, make it the first or last; to include `^' put it
+     after the first character.
+
+     The characters `$', `*', `.', `[', and `\' are normally not
+     special within LIST.  For example, `[\*]' matches either `\' or
+     `*', because the `\' is not special here.  However, strings like
+     `[.ch.]', `[=a=]', and `[:space:]' are special within LIST and
+     represent collating symbols, equivalence classes, and character
+     classes, respectively, and `[' is therefore special within LIST
+     when it is followed by `.', `=', or `:'.  Also, when not in
+     `POSIXLY_CORRECT' mode, special escapes like `\n' and `\t' are
+     recognized within LIST.  *Note Escapes::.
+
+`REGEXP1\|REGEXP2'
+     Matches either REGEXP1 or REGEXP2.  Use parentheses to use complex
+     alternative regular expressions.  The matching process tries each
+     alternative in turn, from left to right, and the first one that
+     succeeds is used.  It is a GNU extension.
+
+`REGEXP1REGEXP2'
+     Matches the concatenation of REGEXP1 and REGEXP2.  Concatenation
+     binds more tightly than `\|', `^', and `$', but less tightly than
+     the other regular expression operators.
+
+`\DIGIT'
+     Matches the DIGIT-th `\(...\)' parenthesized subexpression in the
+     regular expression.  This is called a "back reference".
+     Subexpressions are implicity numbered by counting occurrences of
+     `\(' left-to-right.
+
+`\n'
+     Matches the newline character.
+
+`\CHAR'
+     Matches CHAR, where CHAR is one of `$', `*', `.', `[', `\', or `^'.
+     Note that the only C-like backslash sequences that you can
+     portably assume to be interpreted are `\n' and `\\'; in particular
+     `\t' is not portable, and matches a `t' under most implementations
+     of `sed', rather than a tab character.
+
+
+   Note that the regular expression matcher is greedy, i.e., matches
+are attempted from left to right and, if two or more matches are
+possible starting at the same character, it selects the longest.
+
+Examples:
+`abcdef'
+     Matches `abcdef'.
+
+`a*b'
+     Matches zero or more `a's followed by a single `b'.  For example,
+     `b' or `aaaaab'.
+
+`a\?b'
+     Matches `b' or `ab'.
+
+`a\+b\+'
+     Matches one or more `a's followed by one or more `b's: `ab' is the
+     shortest possible match, but other examples are `aaaab' or
+     `abbbbb' or `aaaaaabbbbbbb'.
+
+`.*'
+`.\+'
+     These two both match all the characters in a string; however, the
+     first matches every string (including the empty string), while the
+     second matches only strings containing at least one character.
+
+`^main.*(.*)'
+     his matches a string starting with `main', followed by an opening
+     and closing parenthesis.  The `n', `(' and `)' need not be
+     adjacent.
+
+`^#'
+     This matches a string beginning with `#'.
+
+`\\$'
+     This matches a string ending with a single backslash.  The regexp
+     contains two backslashes for escaping.
+
+`\$'
+     Instead, this matches a string consisting of a single dollar sign,
+     because it is escaped.
+
+`[a-zA-Z0-9]'
+     In the C locale, this matches any ASCII letters or digits.
+
+`[^ tab]\+'
+     (Here `tab' stands for a single tab character.)  This matches a
+     string of one or more characters, none of which is a space or a
+     tab.  Usually this means a word.
+
+`^\(.*\)\n\1$'
+     This matches a string consisting of two equal substrings separated
+     by a newline.
+
+`.\{9\}A$'
+     This matches nine characters followed by an `A'.
+
+`^.\{15\}A'
+     This matches the start of a string that contains 16 characters,
+     the last of which is an `A'.
+
+
+
+File: sed.info,  Node: Common Commands,  Next: The "s" Command,  Prev: Regular Expressions,  Up: sed Programs
+
+Often-Used Commands
+===================
+
+   If you use `sed' at all, you will quite likely want to know these
+commands.
+
+`#'
+     [No addresses allowed.]
+
+     The `#' character begins a comment; the comment continues until
+     the next newline.
+
+     If you are concerned about portability, be aware that some
+     implementations of `sed' (which are not POSIX conformant) may only
+     support a single one-line comment, and then only when the very
+     first character of the script is a `#'.
+
+     Warning: if the first two characters of the `sed' script are `#n',
+     then the `-n' (no-autoprint) option is forced.  If you want to put
+     a comment in the first line of your script and that comment begins
+     with the letter `n' and you do not want this behavior, then be
+     sure to either use a capital `N', or place at least one space
+     before the `n'.
+
+`q [EXIT-CODE]'
+     This command only accepts a single address.
+
+     Exit `sed' without processing any more commands or input.  Note
+     that the current pattern space is printed if auto-print is not
+     disabled with the `-n' options.  The ability to return an exit
+     code from the `sed' script is a GNU `sed' extension.
+
+`d'
+     Delete the pattern space; immediately start next cycle.
+
+`p'
+     Print out the pattern space (to the standard output).  This
+     command is usually only used in conjunction with the `-n'
+     command-line option.
+
+`n'
+     If auto-print is not disabled, print the pattern space, then,
+     regardless, replace the pattern space with the next line of input.
+     If there is no more input then `sed' exits without processing any
+     more commands.
+
+`{ COMMANDS }'
+     A group of commands may be enclosed between `{' and `}' characters.
+     This is particularly useful when you want a group of commands to
+     be triggered by a single address (or address-range) match.
+
+
+
+File: sed.info,  Node: The "s" Command,  Next: Other Commands,  Prev: Common Commands,  Up: sed Programs
+
+The `s' Command
+===============
+
+   The syntax of the `s' (as in substitute) command is
+`s/REGEXP/REPLACEMENT/FLAGS'.  The `/' characters may be uniformly
+replaced by any other single character within any given `s' command.
+The `/' character (or whatever other character is used in its stead)
+can appear in the REGEXP or REPLACEMENT only if it is preceded by a `\'
+character.
+
+   The `s' command is probably the most important in `sed' and has a
+lot of different options.  Its basic concept is simple: the `s' command
+attempts to match the pattern space against the supplied REGEXP; if the
+match is successful, then that portion of the pattern space which was
+matched is replaced with REPLACEMENT.
+
+   The REPLACEMENT can contain `\N' (N being a number from 1 to 9,
+inclusive) references, which refer to the portion of the match which is
+contained between the Nth `\(' and its matching `\)'.  Also, the
+REPLACEMENT can contain unescaped `&' characters which reference the
+whole matched portion of the pattern space.  Finally, as a GNU `sed'
+extension, you can include a special sequence made of a backslash and
+one of the letters `L', `l', `U', `u', or `E'.  The meaning is as
+follows:
+
+`\L'
+     Turn the replacement to lowercase until a `\U' or `\E' is found,
+
+`\l'
+     Turn the next character to lowercase,
+
+`\U'
+     Turn the replacement to uppercase until a `\L' or `\E' is found,
+
+`\u'
+     Turn the next character to uppercase,
+
+`\E'
+     Stop case conversion started by `\L' or `\U'.
+
+   To include a literal `\', `&', or newline in the final replacement,
+be sure to precede the desired `\', `&', or newline in the REPLACEMENT
+with a `\'.
+
+   The `s' command can be followed by zero or more of the following
+FLAGS:
+
+`g'
+     Apply the replacement to _all_ matches to the REGEXP, not just the
+     first.
+
+`NUMBER'
+     Only replace the NUMBERth match of the REGEXP.
+
+     Note: the POSIX standard does not specify what should happen when
+     you mix the `g' and NUMBER modifiers, and currently there is no
+     widely agreed upon meaning across `sed' implementations.  For GNU
+     `sed', the interaction is defined to be: ignore matches before the
+     NUMBERth, and then match and replace all matches from the NUMBERth
+     on.
+
+`p'
+     If the substitution was made, then print the new pattern space.
+
+     Note: when both the `p' and `e' options are specified, the
+     relative ordering of the two produces very different results.  In
+     general, `ep' (evaluate then print) is what you want, but
+     operating the other way round can be useful for debugging.  For
+     this reason, the current version of GNU `sed' interprets specially
+     the presence of `p' options both before and after `e', printing
+     the pattern space before and after evaluation, while in general
+     flags for the `s' command show their effect just once.  This
+     behavior, although documented, might change in future versions.
+
+`w FILE-NAME'
+     If the substitution was made, then write out the result to the
+     named file.  As a GNU `sed' extension, two special values of
+     FILE-NAME are supported: `/dev/stderr', which writes the result to
+     the standard error, and `/dev/stdout', which writes to the standard
+     output.(1)
+
+`e'
+     This command allows one to pipe input from a shell command into
+     pattern space.  If a substitution was made, the command that is
+     found in pattern space is executed and pattern space is replaced
+     with its output.  A trailing newline is suppressed; results are
+     undefined if the command to be executed contains a NUL character.
+     This is a GNU `sed' extension.
+
+`I'
+`i'
+     The `I' modifier to regular-expression matching is a GNU extension
+     which makes `sed' match REGEXP in a case-insensitive manner.
+
+`M'
+`m'
+     The `M' modifier to regular-expression matching is a GNU `sed'
+     extension which causes `^' and `$' to match respectively (in
+     addition to the normal behavior) the empty string after a newline,
+     and the empty string before a newline.  There are special character
+     sequences (`\`' and `\'') which always match the beginning or the
+     end of the buffer.  `M' stands for `multi-line'.
+
+
+   ---------- Footnotes ----------
+
+   (1) This is equivalent to `p' unless the `-i' option is being used.
+
+
+File: sed.info,  Node: Other Commands,  Next: Programming Commands,  Prev: The "s" Command,  Up: sed Programs
+
+Less Frequently-Used Commands
+=============================
+
+   Though perhaps less frequently used than those in the previous
+section, some very small yet useful `sed' scripts can be built with
+these commands.
+
+`y/SOURCE-CHARS/DEST-CHARS/'
+     (The `/' characters may be uniformly replaced by any other single
+     character within any given `y' command.)
+
+     Transliterate any characters in the pattern space which match any
+     of the SOURCE-CHARS with the corresponding character in DEST-CHARS.
+
+     Instances of the `/' (or whatever other character is used in its
+     stead), `\', or newlines can appear in the SOURCE-CHARS or
+     DEST-CHARS lists, provide that each instance is escaped by a `\'.
+     The SOURCE-CHARS and DEST-CHARS lists _must_ contain the same
+     number of characters (after de-escaping).
+
+`a\'
+`TEXT'
+     As a GNU extension, this command accepts two addresses.
+
+     Queue the lines of text which follow this command (each but the
+     last ending with a `\', which are removed from the output) to be
+     output at the end of the current cycle, or when the next input
+     line is read.
+
+     Escape sequences in TEXT are processed, so you should use `\\' in
+     TEXT to print a single backslash.
+
+     As a GNU extension, if between the `a' and the newline there is
+     other than a whitespace-`\' sequence, then the text of this line,
+     starting at the first non-whitespace character after the `a', is
+     taken as the first line of the TEXT block.  (This enables a
+     simplification in scripting a one-line add.)  This extension also
+     works with the `i' and `c' commands.
+
+`i\'
+`TEXT'
+     As a GNU extension, this command accepts two addresses.
+
+     Immediately output the lines of text which follow this command
+     (each but the last ending with a `\', which are removed from the
+     output).
+
+`c\'
+`TEXT'
+     Delete the lines matching the address or address-range, and output
+     the lines of text which follow this command (each but the last
+     ending with a `\', which are removed from the output) in place of
+     the last line (or in place of each line, if no addresses were
+     specified).  A new cycle is started after this command is done,
+     since the pattern space will have been deleted.
+
+`='
+     As a GNU extension, this command accepts two addresses.
+
+     Print out the current input line number (with a trailing newline).
+
+`l N'
+     Print the pattern space in an unambiguous form: non-printable
+     characters (and the `\' character) are printed in C-style escaped
+     form; long lines are split, with a trailing `\' character to
+     indicate the split; the end of each line is marked with a `$'.
+
+     N specifies the desired line-wrap length; a length of 0 (zero)
+     means to never wrap long lines.  If omitted, the default as
+     specified on the command line is used.  The N parameter is a GNU
+     `sed' extension.
+
+`r FILENAME'
+     As a GNU extension, this command accepts two addresses.
+
+     Queue the contents of FILENAME to be read and inserted into the
+     output stream at the end of the current cycle, or when the next
+     input line is read.  Note that if FILENAME cannot be read, it is
+     treated as if it were an empty file, without any error indication.
+
+     As a GNU `sed' extension, the special value `/dev/stdin' is
+     supported for the file name, which reads the contents of the
+     standard input.
+
+`w FILENAME'
+     Write the pattern space to FILENAME.  As a GNU `sed' extension,
+     two special values of FILE-NAME are supported: `/dev/stderr',
+     which writes the result to the standard error, and `/dev/stdout',
+     which writes to the standard output.(1)
+
+     The file will be created (or truncated) before the first input
+     line is read; all `w' commands (including instances of `w' flag on
+     successful `s' commands) which refer to the same FILENAME are
+     output without closing and reopening the file.
+
+`D'
+     Delete text in the pattern space up to the first newline.  If any
+     text is left, restart cycle with the resultant pattern space
+     (without reading a new line of input), otherwise start a normal
+     new cycle.
+
+`N'
+     Add a newline to the pattern space, then append the next line of
+     input to the pattern space.  If there is no more input then `sed'
+     exits without processing any more commands.
+
+`P'
+     Print out the portion of the pattern space up to the first newline.
+
+`h'
+     Replace the contents of the hold space with the contents of the
+     pattern space.
+
+`H'
+     Append a newline to the contents of the hold space, and then
+     append the contents of the pattern space to that of the hold space.
+
+`g'
+     Replace the contents of the pattern space with the contents of the
+     hold space.
+
+`G'
+     Append a newline to the contents of the pattern space, and then
+     append the contents of the hold space to that of the pattern space.
+
+`x'
+     Exchange the contents of the hold and pattern spaces.
+
+
+   ---------- Footnotes ----------
+
+   (1) This is equivalent to `p' unless the `-i' option is being used.
+
+
+File: sed.info,  Node: Programming Commands,  Next: Extended Commands,  Prev: Other Commands,  Up: sed Programs
+
+Commands for `sed' gurus
+========================
+
+   In most cases, use of these commands indicates that you are probably
+better off programming in something like `awk' or Perl.  But
+occasionally one is committed to sticking with `sed', and these
+commands can enable one to write quite convoluted scripts.
+
+`: LABEL'
+     [No addresses allowed.]
+
+     Specify the location of LABEL for branch commands.  In all other
+     respects, a no-op.
+
+`b LABEL'
+     Unconditionally branch to LABEL.  The LABEL may be omitted, in
+     which case the next cycle is started.
+
+`t LABEL'
+     Branch to LABEL only if there has been a successful `s'ubstitution
+     since the last input line was read or conditional branch was taken.
+     The LABEL may be omitted, in which case the next cycle is started.
+
+
+
+File: sed.info,  Node: Extended Commands,  Next: Escapes,  Prev: Programming Commands,  Up: sed Programs
+
+Commands Specific to GNU `sed'
+==============================
+
+   These commands are specific to GNU `sed', so you must use them with
+care and only when you are sure that hindering portability is not evil.
+They allow you to check for GNU `sed' extensions or to do tasks that
+are required quite often, yet are unsupported by standard `sed's.
+
+`e [COMMAND]'
+     This command allows one to pipe input from a shell command into
+     pattern space.  Without parameters, the `e' command executes the
+     command that is found in pattern space and replaces the pattern
+     space with the output; a trailing newline is suppressed.
+
+     If a parameter is specified, instead, the `e' command interprets
+     it as a command and sends its output to the output stream (like
+     `r' does).  The command can run across multiple lines, all but the
+     last ending with a back-slash.
+
+     In both cases, the results are undefined if the command to be
+     executed contains a NUL character.
+
+`L N'
+     This GNU `sed' extension fills and joins lines in pattern space to
+     produce output lines of (at most) N characters, like `fmt' does;
+     if N is omitted, the default as specified on the command line is
+     used.  This command is considered a failed experiment and unless
+     there is enough request (which seems unlikely) will be removed in
+     future versions.
+
+`Q [EXIT-CODE]'
+     This command only accepts a single address.
+
+     This command is the same as `q', but will not print the contents
+     of pattern space.  Like `q', it provides the ability to return an
+     exit code to the caller.
+
+     This command can be useful because the only alternative ways to
+     accomplish this apparently trivial function are to use the `-n'
+     option (which can unnecessarily complicate your script) or
+     resorting to the following snippet, which wastes time by reading
+     the whole file without any visible effect:
+
+          :eat
+          $d       Quit silently on the last line
+          N        Read another line, silently
+          g        Overwrite pattern space each time to save memory
+          b eat
+
+`R FILENAME'
+     Queue a line of FILENAME to be read and inserted into the output
+     stream at the end of the current cycle, or when the next input
+     line is read.  Note that if FILENAME cannot be read, or if its end
+     is reached, no line is appended, without any error indication.
+
+     As with the `r' command, the special value `/dev/stdin' is
+     supported for the file name, which reads a line from the standard
+     input.
+
+`T LABEL'
+     Branch to LABEL only if there have been no successful
+     `s'ubstitutions since the last input line was read or conditional
+     branch was taken. The LABEL may be omitted, in which case the next
+     cycle is started.
+
+`v VERSION'
+     This command does nothing, but makes `sed' fail if GNU `sed'
+     extensions are not supported, simply because other versions of
+     `sed' do not implement it.  In addition, you can specify the
+     version of `sed' that your script requires, such as `4.0.5'.  The
+     default is `4.0' because that is the first version that
+     implemented this command.
+
+     This command enables all GNU extensions even if `POSIXLY_CORRECT'
+     is set in the environment.
+
+`W FILENAME'
+     Write to the given filename the portion of the pattern space up to
+     the first newline.  Everything said under the `w' command about
+     file handling holds here too.
+
+
+File: sed.info,  Node: Escapes,  Prev: Extended Commands,  Up: sed Programs
+
+GNU Extensions for Escapes in Regular Expressions
+=================================================
+
+   Until this chapter, we have only encountered escapes of the form
+`\^', which tell `sed' not to interpret the circumflex as a special
+character, but rather to take it literally.  For example, `\*' matches
+a single asterisk rather than zero or more backslashes.
+
+   This chapter introduces another kind of escape(1)--that is, escapes
+that are applied to a character or sequence of characters that
+ordinarily are taken literally, and that `sed' replaces with a special
+character.  This provides a way of encoding non-printable characters in
+patterns in a visible manner.  There is no restriction on the
+appearance of non-printing characters in a `sed' script but when a
+script is being prepared in the shell or by text editing, it is usually
+easier to use one of the following escape sequences than the binary
+character it represents:
+
+   The list of these escapes is:
+
+`\a'
+     Produces or matches a BEL character, that is an "alert" (ASCII 7).
+
+`\f'
+     Produces or matches a form feed (ASCII 12).
+
+`\n'
+     Produces or matches a newline (ASCII 10).
+
+`\r'
+     Produces or matches a carriage return (ASCII 13).
+
+`\t'
+     Produces or matches a horizontal tab (ASCII 9).
+
+`\v'
+     Produces or matches a so called "vertical tab" (ASCII 11).
+
+`\cX'
+     Produces or matches `CONTROL-X', where X is any character.  The
+     precise effect of `\cX' is as follows: if X is a lower case
+     letter, it is converted to upper case.  Then bit 6 of the
+     character (hex 40) is inverted.  Thus `\cz' becomes hex 1A, but
+     `\c{' becomes hex 3B, while `\c;' becomes hex 7B.
+
+`\dXXX'
+     Produces or matches a character whose decimal ASCII value is XXX.
+
+`\oXXX'
+     Produces or matches a character whose octal ASCII value is XXX.
+
+`\xXX'
+     Produces or matches a character whose hexadecimal ASCII value is
+     XX.
+
+   `\b' (backspace) was omitted because of the conflict with the
+existing "word boundary" meaning.
+
+   Other escapes match a particular character class and are valid only
+in regular expressions:
+
+`\w'
+     Matches any "word" character.  A "word" character is any letter or
+     digit or the underscore character.
+
+`\W'
+     Matches any "non-word" character.
+
+`\b'
+     Matches a word boundary; that is it matches if the character to
+     the left is a "word" character and the character to the right is a
+     "non-word" character, or vice-versa.
+
+`\B'
+     Matches everywhere but on a word boundary; that is it matches if
+     the character to the left and the character to the right are
+     either both "word" characters or both "non-word" characters.
+
+`\`'
+     Matches only at the start of pattern space.  This is different
+     from `^' in multi-line mode.
+
+`\''
+     Matches only at the end of pattern space.  This is different from
+     `$' in multi-line mode.
+
+
+   ---------- Footnotes ----------
+
+   (1) All the escapes introduced here are GNU extensions, with the
+exception of `\n'.  In basic regular expression mode, setting
+`POSIXLY_CORRECT' disables them inside bracket expressions.
+
+
+File: sed.info,  Node: Examples,  Next: Limitations,  Prev: sed Programs,  Up: Top
+
+Some Sample Scripts
+*******************
+
+   Here are some `sed' scripts to guide you in the art of mastering
+`sed'.
+
+* Menu:
+
+Some exotic examples:
+* Centering lines::
+* Increment a number::
+* Rename files to lower case::
+* Print bash environment::
+* Reverse chars of lines::
+
+Emulating standard utilities:
+* tac::                             Reverse lines of files
+* cat -n::                          Numbering lines
+* cat -b::                          Numbering non-blank lines
+* wc -c::                           Counting chars
+* wc -w::                           Counting words
+* wc -l::                           Counting lines
+* head::                            Printing the first lines
+* tail::                            Printing the last lines
+* uniq::                            Make duplicate lines unique
+* uniq -d::                         Print duplicated lines of input
+* uniq -u::                         Remove all duplicated lines
+* cat -s::                          Squeezing blank lines
+
+
+File: sed.info,  Node: Centering lines,  Next: Increment a number,  Up: Examples
+
+Centering Lines
+===============
+
+   This script centers all lines of a file on a 80 columns width.  To
+change that width, the number in `\{...\}' must be replaced, and the
+number of added spaces also must be changed.
+
+   Note how the buffer commands are used to separate parts in the
+regular expressions to be matched--this is a common technique.
+
+     #!/usr/bin/sed -f
+     
+     # Put 80 spaces in the buffer
+     1 {
+       x
+       s/^$/          /
+       s/^.*$/&&&&&&&&/
+       x
+     }
+     
+     # del leading and trailing spaces
+     y/tab/ /
+     s/^ *//
+     s/ *$//
+     
+     # add a newline and 80 spaces to end of line
+     G
+     
+     # keep first 81 chars (80 + a newline)
+     s/^\(.\{81\}\).*$/\1/
+     
+     # \2 matches half of the spaces, which are moved to the beginning
+     s/^\(.*\)\n\(.*\)\2/\2\1/
+
+
+File: sed.info,  Node: Increment a number,  Next: Rename files to lower case,  Prev: Centering lines,  Up: Examples
+
+Increment a Number
+==================
+
+   This script is one of a few that demonstrate how to do arithmetic in
+`sed'.  This is indeed possible,(1) but must be done manually.
+
+   To increment one number you just add 1 to last digit, replacing it
+by the following digit.  There is one exception: when the digit is a
+nine the previous digits must be also incremented until you don't have
+a nine.
+
+   This solution by Bruno Haible is very clever and smart because it
+uses a single buffer; if you don't have this limitation, the algorithm
+used in *Note Numbering lines: cat -n, is faster.  It works by
+replacing trailing nines with an underscore, then using multiple `s'
+commands to increment the last digit, and then again substituting
+underscores with zeros.
+
+     #!/usr/bin/sed -f
+     
+     /[^0-9]/ d
+     
+     # replace all leading 9s by _ (any other character except digits, could
+     # be used)
+     :d
+     s/9\(_*\)$/_\1/
+     td
+     
+     # incr last digit only.  The first line adds a most-significant
+     # digit of 1 if we have to add a digit.
+     #
+     # The `tn' commands are not necessary, but make the thing
+     # faster
+     
+     s/^\(_*\)$/1\1/; tn
+     s/8\(_*\)$/9\1/; tn
+     s/7\(_*\)$/8\1/; tn
+     s/6\(_*\)$/7\1/; tn
+     s/5\(_*\)$/6\1/; tn
+     s/4\(_*\)$/5\1/; tn
+     s/3\(_*\)$/4\1/; tn
+     s/2\(_*\)$/3\1/; tn
+     s/1\(_*\)$/2\1/; tn
+     s/0\(_*\)$/1\1/; tn
+     
+     :n
+     y/_/0/
+
+   ---------- Footnotes ----------
+
+   (1) `sed' guru Greg Ubben wrote an implementation of the `dc' RPN
+calculator!  It is distributed together with sed.
+
+
+File: sed.info,  Node: Rename files to lower case,  Next: Print bash environment,  Prev: Increment a number,  Up: Examples
+
+Rename Files to Lower Case
+==========================
+
+   This is a pretty strange use of `sed'.  We transform text, and
+transform it to be shell commands, then just feed them to shell.  Don't
+worry, even worse hacks are done when using `sed'; I have seen a script
+converting the output of `date' into a `bc' program!
+
+   The main body of this is the `sed' script, which remaps the name
+from lower to upper (or vice-versa) and even checks out if the remapped
+name is the same as the original name.  Note how the script is
+parameterized using shell variables and proper quoting.
+
+     #! /bin/sh
+     # rename files to lower/upper case...
+     #
+     # usage:
+     #    move-to-lower *
+     #    move-to-upper *
+     # or
+     #    move-to-lower -R .
+     #    move-to-upper -R .
+     #
+     
+     help()
+     {
+     	cat << eof
+     Usage: $0 [-n] [-r] [-h] files...
+     
+     -n      do nothing, only see what would be done
+     -R      recursive (use find)
+     -h      this message
+     files   files to remap to lower case
+     
+     Examples:
+            $0 -n *        (see if everything is ok, then...)
+            $0 *
+     
+            $0 -R .
+     
+     eof
+     }
+     
+     apply_cmd='sh'
+     finder='echo "$@" | tr " " "\n"'
+     files_only=
+     
+     while :
+     do
+         case "$1" in
+             -n) apply_cmd='cat' ;;
+             -R) finder='find "$@" -type f';;
+             -h) help ; exit 1 ;;
+             *) break ;;
+         esac
+         shift
+     done
+     
+     if [ -z "$1" ]; then
+             echo Usage: $0 [-h] [-n] [-r] files...
+             exit 1
+     fi
+     
+     LOWER='abcdefghijklmnopqrstuvwxyz'
+     UPPER='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+     
+     case `basename $0` in
+             *upper*) TO=$UPPER; FROM=$LOWER ;;
+             *)       FROM=$UPPER; TO=$LOWER ;;
+     esac
+     
+     eval $finder | sed -n '
+     
+     # remove all trailing slashes
+     s/\/*$//
+     
+     # add ./ if there is no path, only a filename
+     /\//! s/^/.\//
+     
+     # save path+filename
+     h
+     
+     # remove path
+     s/.*\///
+     
+     # do conversion only on filename
+     y/'$FROM'/'$TO'/
+     
+     # now line contains original path+file, while
+     # hold space contains the new filename
+     x
+     
+     # add converted file name to line, which now contains
+     # path/file-name\nconverted-file-name
+     G
+     
+     # check if converted file name is equal to original file name,
+     # if it is, do not print nothing
+     /^.*\/\(.*\)\n\1/b
+     
+     # now, transform path/fromfile\n, into
+     # mv path/fromfile path/tofile and print it
+     s/^\(.*\/\)\(.*\)\n\(.*\)$/mv "\1\2" "\1\3"/p
+     
+     ' | $apply_cmd
+
Index: /tags/kBuild-0.1.4/src/sed/doc/sed.info-2
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/sed.info-2	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/sed.info-2	(revision 1780)
@@ -0,0 +1,1087 @@
+This is ../../doc/sed.info, produced by makeinfo version 4.5 from
+../../doc/sed.texi.
+
+INFO-DIR-SECTION Text creation and manipulation
+START-INFO-DIR-ENTRY
+* sed: (sed).                   Stream EDitor.
+
+END-INFO-DIR-ENTRY
+
+This file documents version 4.1.5 of GNU `sed', a stream editor.
+
+   Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software
+Foundation, Inc.
+
+   This document is released under the terms of the GNU Free
+Documentation License as published by the Free Software Foundation;
+either version 1.1, or (at your option) any later version.
+
+   You should have received a copy of the GNU Free Documentation
+License along with GNU `sed'; see the file `COPYING.DOC'.  If not,
+write to the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02110-1301, USA.
+
+   There are no Cover Texts and no Invariant Sections; this text, along
+with its equivalent in the printed manual, constitutes the Title Page.
+
+File: sed.info,  Node: Print bash environment,  Next: Reverse chars of lines,  Prev: Rename files to lower case,  Up: Examples
+
+Print `bash' Environment
+========================
+
+   This script strips the definition of the shell functions from the
+output of the `set' Bourne-shell command.
+
+     #!/bin/sh
+     
+     set | sed -n '
+     :x
+     
+     # if no occurrence of "=()" print and load next line
+     /=()/! { p; b; }
+     / () $/! { p; b; }
+     
+     # possible start of functions section
+     # save the line in case this is a var like FOO="() "
+     h
+     
+     # if the next line has a brace, we quit because
+     # nothing comes after functions
+     n
+     /^{/ q
+     
+     # print the old line
+     x; p
+     
+     # work on the new line now
+     x; bx
+     '
+
+
+File: sed.info,  Node: Reverse chars of lines,  Next: tac,  Prev: Print bash environment,  Up: Examples
+
+Reverse Characters of Lines
+===========================
+
+   This script can be used to reverse the position of characters in
+lines.  The technique moves two characters at a time, hence it is
+faster than more intuitive implementations.
+
+   Note the `tx' command before the definition of the label.  This is
+often needed to reset the flag that is tested by the `t' command.
+
+   Imaginative readers will find uses for this script.  An example is
+reversing the output of `banner'.(1)
+
+     #!/usr/bin/sed -f
+     
+     /../! b
+     
+     # Reverse a line.  Begin embedding the line between two newlines
+     s/^.*$/\
+     &\
+     /
+     
+     # Move first character at the end.  The regexp matches until
+     # there are zero or one characters between the markers
+     tx
+     :x
+     s/\(\n.\)\(.*\)\(.\n\)/\3\2\1/
+     tx
+     
+     # Remove the newline markers
+     s/\n//g
+
+   ---------- Footnotes ----------
+
+   (1) This requires another script to pad the output of banner; for
+example
+
+     #! /bin/sh
+     
+     banner -w $1 $2 $3 $4 |
+       sed -e :a -e '/^.\{0,'$1'\}$/ { s/$/ /; ba; }' |
+       ~/sedscripts/reverseline.sed
+
+
+File: sed.info,  Node: tac,  Next: cat -n,  Prev: Reverse chars of lines,  Up: Examples
+
+Reverse Lines of Files
+======================
+
+   This one begins a series of totally useless (yet interesting)
+scripts emulating various Unix commands.  This, in particular, is a
+`tac' workalike.
+
+   Note that on implementations other than GNU `sed' this script might
+easily overflow internal buffers.
+
+     #!/usr/bin/sed -nf
+     
+     # reverse all lines of input, i.e. first line became last, ...
+     
+     # from the second line, the buffer (which contains all previous lines)
+     # is *appended* to current line, so, the order will be reversed
+     1! G
+     
+     # on the last line we're done -- print everything
+     $ p
+     
+     # store everything on the buffer again
+     h
+
+
+File: sed.info,  Node: cat -n,  Next: cat -b,  Prev: tac,  Up: Examples
+
+Numbering Lines
+===============
+
+   This script replaces `cat -n'; in fact it formats its output exactly
+like GNU `cat' does.
+
+   Of course this is completely useless and for two reasons:  first,
+because somebody else did it in C, second, because the following
+Bourne-shell script could be used for the same purpose and would be
+much faster:
+
+     #! /bin/sh
+     sed -e "=" $@ | sed -e '
+       s/^/      /
+       N
+       s/^ *\(......\)\n/\1  /
+     '
+
+   It uses `sed' to print the line number, then groups lines two by two
+using `N'.  Of course, this script does not teach as much as the one
+presented below.
+
+   The algorithm used for incrementing uses both buffers, so the line
+is printed as soon as possible and then discarded.  The number is split
+so that changing digits go in a buffer and unchanged ones go in the
+other; the changed digits are modified in a single step (using a `y'
+command).  The line number for the next line is then composed and
+stored in the hold space, to be used in the next iteration.
+
+     #!/usr/bin/sed -nf
+     
+     # Prime the pump on the first line
+     x
+     /^$/ s/^.*$/1/
+     
+     # Add the correct line number before the pattern
+     G
+     h
+     
+     # Format it and print it
+     s/^/      /
+     s/^ *\(......\)\n/\1  /p
+     
+     # Get the line number from hold space; add a zero
+     # if we're going to add a digit on the next line
+     g
+     s/\n.*$//
+     /^9*$/ s/^/0/
+     
+     # separate changing/unchanged digits with an x
+     s/.9*$/x&/
+     
+     # keep changing digits in hold space
+     h
+     s/^.*x//
+     y/0123456789/1234567890/
+     x
+     
+     # keep unchanged digits in pattern space
+     s/x.*$//
+     
+     # compose the new number, remove the newline implicitly added by G
+     G
+     s/\n//
+     h
+
+
+File: sed.info,  Node: cat -b,  Next: wc -c,  Prev: cat -n,  Up: Examples
+
+Numbering Non-blank Lines
+=========================
+
+   Emulating `cat -b' is almost the same as `cat -n'--we only have to
+select which lines are to be numbered and which are not.
+
+   The part that is common to this script and the previous one is not
+commented to show how important it is to comment `sed' scripts
+properly...
+
+     #!/usr/bin/sed -nf
+     
+     /^$/ {
+       p
+       b
+     }
+     
+     # Same as cat -n from now
+     x
+     /^$/ s/^.*$/1/
+     G
+     h
+     s/^/      /
+     s/^ *\(......\)\n/\1  /p
+     x
+     s/\n.*$//
+     /^9*$/ s/^/0/
+     s/.9*$/x&/
+     h
+     s/^.*x//
+     y/0123456789/1234567890/
+     x
+     s/x.*$//
+     G
+     s/\n//
+     h
+
+
+File: sed.info,  Node: wc -c,  Next: wc -w,  Prev: cat -b,  Up: Examples
+
+Counting Characters
+===================
+
+   This script shows another way to do arithmetic with `sed'.  In this
+case we have to add possibly large numbers, so implementing this by
+successive increments would not be feasible (and possibly even more
+complicated to contrive than this script).
+
+   The approach is to map numbers to letters, kind of an abacus
+implemented with `sed'.  `a's are units, `b's are tens and so on: we
+simply add the number of characters on the current line as units, and
+then propagate the carry to tens, hundreds, and so on.
+
+   As usual, running totals are kept in hold space.
+
+   On the last line, we convert the abacus form back to decimal.  For
+the sake of variety, this is done with a loop rather than with some 80
+`s' commands(1): first we convert units, removing `a's from the number;
+then we rotate letters so that tens become `a's, and so on until no
+more letters remain.
+
+     #!/usr/bin/sed -nf
+     
+     # Add n+1 a's to hold space (+1 is for the newline)
+     s/./a/g
+     H
+     x
+     s/\n/a/
+     
+     # Do the carry.  The t's and b's are not necessary,
+     # but they do speed up the thing
+     t a
+     : a;  s/aaaaaaaaaa/b/g; t b; b done
+     : b;  s/bbbbbbbbbb/c/g; t c; b done
+     : c;  s/cccccccccc/d/g; t d; b done
+     : d;  s/dddddddddd/e/g; t e; b done
+     : e;  s/eeeeeeeeee/f/g; t f; b done
+     : f;  s/ffffffffff/g/g; t g; b done
+     : g;  s/gggggggggg/h/g; t h; b done
+     : h;  s/hhhhhhhhhh//g
+     
+     : done
+     $! {
+       h
+       b
+     }
+     
+     # On the last line, convert back to decimal
+     
+     : loop
+     /a/! s/[b-h]*/&0/
+     s/aaaaaaaaa/9/
+     s/aaaaaaaa/8/
+     s/aaaaaaa/7/
+     s/aaaaaa/6/
+     s/aaaaa/5/
+     s/aaaa/4/
+     s/aaa/3/
+     s/aa/2/
+     s/a/1/
+     
+     : next
+     y/bcdefgh/abcdefg/
+     /[a-h]/ b loop
+     p
+
+   ---------- Footnotes ----------
+
+   (1) Some implementations have a limit of 199 commands per script
+
+
+File: sed.info,  Node: wc -w,  Next: wc -l,  Prev: wc -c,  Up: Examples
+
+Counting Words
+==============
+
+   This script is almost the same as the previous one, once each of the
+words on the line is converted to a single `a' (in the previous script
+each letter was changed to an `a').
+
+   It is interesting that real `wc' programs have optimized loops for
+`wc -c', so they are much slower at counting words rather than
+characters.  This script's bottleneck, instead, is arithmetic, and
+hence the word-counting one is faster (it has to manage smaller
+numbers).
+
+   Again, the common parts are not commented to show the importance of
+commenting `sed' scripts.
+
+     #!/usr/bin/sed -nf
+     
+     # Convert words to a's
+     s/[ tab][ tab]*/ /g
+     s/^/ /
+     s/ [^ ][^ ]*/a /g
+     s/ //g
+     
+     # Append them to hold space
+     H
+     x
+     s/\n//
+     
+     # From here on it is the same as in wc -c.
+     /aaaaaaaaaa/! bx;   s/aaaaaaaaaa/b/g
+     /bbbbbbbbbb/! bx;   s/bbbbbbbbbb/c/g
+     /cccccccccc/! bx;   s/cccccccccc/d/g
+     /dddddddddd/! bx;   s/dddddddddd/e/g
+     /eeeeeeeeee/! bx;   s/eeeeeeeeee/f/g
+     /ffffffffff/! bx;   s/ffffffffff/g/g
+     /gggggggggg/! bx;   s/gggggggggg/h/g
+     s/hhhhhhhhhh//g
+     :x
+     $! { h; b; }
+     :y
+     /a/! s/[b-h]*/&0/
+     s/aaaaaaaaa/9/
+     s/aaaaaaaa/8/
+     s/aaaaaaa/7/
+     s/aaaaaa/6/
+     s/aaaaa/5/
+     s/aaaa/4/
+     s/aaa/3/
+     s/aa/2/
+     s/a/1/
+     y/bcdefgh/abcdefg/
+     /[a-h]/ by
+     p
+
+
+File: sed.info,  Node: wc -l,  Next: head,  Prev: wc -w,  Up: Examples
+
+Counting Lines
+==============
+
+   No strange things are done now, because `sed' gives us `wc -l'
+functionality for free!!! Look:
+
+     #!/usr/bin/sed -nf
+     $=
+
+
+File: sed.info,  Node: head,  Next: tail,  Prev: wc -l,  Up: Examples
+
+Printing the First Lines
+========================
+
+   This script is probably the simplest useful `sed' script.  It
+displays the first 10 lines of input; the number of displayed lines is
+right before the `q' command.
+
+     #!/usr/bin/sed -f
+     10q
+
+
+File: sed.info,  Node: tail,  Next: uniq,  Prev: head,  Up: Examples
+
+Printing the Last Lines
+=======================
+
+   Printing the last N lines rather than the first is more complex but
+indeed possible.  N is encoded in the second line, before the bang
+character.
+
+   This script is similar to the `tac' script in that it keeps the
+final output in the hold space and prints it at the end:
+
+     #!/usr/bin/sed -nf
+     
+     1! {; H; g; }
+     1,10 !s/[^\n]*\n//
+     $p
+     h
+
+   Mainly, the scripts keeps a window of 10 lines and slides it by
+adding a line and deleting the oldest (the substitution command on the
+second line works like a `D' command but does not restart the loop).
+
+   The "sliding window" technique is a very powerful way to write
+efficient and complex `sed' scripts, because commands like `P' would
+require a lot of work if implemented manually.
+
+   To introduce the technique, which is fully demonstrated in the rest
+of this chapter and is based on the `N', `P' and `D' commands, here is
+an implementation of `tail' using a simple "sliding window."
+
+   This looks complicated but in fact the working is the same as the
+last script: after we have kicked in the appropriate number of lines,
+however, we stop using the hold space to keep inter-line state, and
+instead use `N' and `D' to slide pattern space by one line:
+
+     #!/usr/bin/sed -f
+     
+     1h
+     2,10 {; H; g; }
+     $q
+     1,9d
+     N
+     D
+
+   Note how the first, second and fourth line are inactive after the
+first ten lines of input.  After that, all the script does is: exiting
+on the last line of input, appending the next input line to pattern
+space, and removing the first line.
+
+
+File: sed.info,  Node: uniq,  Next: uniq -d,  Prev: tail,  Up: Examples
+
+Make Duplicate Lines Unique
+===========================
+
+   This is an example of the art of using the `N', `P' and `D'
+commands, probably the most difficult to master.
+
+     #!/usr/bin/sed -f
+     h
+     
+     :b
+     # On the last line, print and exit
+     $b
+     N
+     /^\(.*\)\n\1$/ {
+         # The two lines are identical.  Undo the effect of
+         # the n command.
+         g
+         bb
+     }
+     
+     # If the `N' command had added the last line, print and exit
+     $b
+     
+     # The lines are different; print the first and go
+     # back working on the second.
+     P
+     D
+
+   As you can see, we mantain a 2-line window using `P' and `D'.  This
+technique is often used in advanced `sed' scripts.
+
+
+File: sed.info,  Node: uniq -d,  Next: uniq -u,  Prev: uniq,  Up: Examples
+
+Print Duplicated Lines of Input
+===============================
+
+   This script prints only duplicated lines, like `uniq -d'.
+
+     #!/usr/bin/sed -nf
+     
+     $b
+     N
+     /^\(.*\)\n\1$/ {
+         # Print the first of the duplicated lines
+         s/.*\n//
+         p
+     
+         # Loop until we get a different line
+         :b
+         $b
+         N
+         /^\(.*\)\n\1$/ {
+             s/.*\n//
+             bb
+         }
+     }
+     
+     # The last line cannot be followed by duplicates
+     $b
+     
+     # Found a different one.  Leave it alone in the pattern space
+     # and go back to the top, hunting its duplicates
+     D
+
+
+File: sed.info,  Node: uniq -u,  Next: cat -s,  Prev: uniq -d,  Up: Examples
+
+Remove All Duplicated Lines
+===========================
+
+   This script prints only unique lines, like `uniq -u'.
+
+     #!/usr/bin/sed -f
+     
+     # Search for a duplicate line --- until that, print what you find.
+     $b
+     N
+     /^\(.*\)\n\1$/ ! {
+         P
+         D
+     }
+     
+     :c
+     # Got two equal lines in pattern space.  At the
+     # end of the file we simply exit
+     $d
+     
+     # Else, we keep reading lines with `N' until we
+     # find a different one
+     s/.*\n//
+     N
+     /^\(.*\)\n\1$/ {
+         bc
+     }
+     
+     # Remove the last instance of the duplicate line
+     # and go back to the top
+     D
+
+
+File: sed.info,  Node: cat -s,  Prev: uniq -u,  Up: Examples
+
+Squeezing Blank Lines
+=====================
+
+   As a final example, here are three scripts, of increasing complexity
+and speed, that implement the same function as `cat -s', that is
+squeezing blank lines.
+
+   The first leaves a blank line at the beginning and end if there are
+some already.
+
+     #!/usr/bin/sed -f
+     
+     # on empty lines, join with next
+     # Note there is a star in the regexp
+     :x
+     /^\n*$/ {
+     N
+     bx
+     }
+     
+     # now, squeeze all '\n', this can be also done by:
+     # s/^\(\n\)*/\1/
+     s/\n*/\
+     /
+
+   This one is a bit more complex and removes all empty lines at the
+beginning.  It does leave a single blank line at end if one was there.
+
+     #!/usr/bin/sed -f
+     
+     # delete all leading empty lines
+     1,/^./{
+     /./!d
+     }
+     
+     # on an empty line we remove it and all the following
+     # empty lines, but one
+     :x
+     /./!{
+     N
+     s/^\n$//
+     tx
+     }
+
+   This removes leading and trailing blank lines.  It is also the
+fastest.  Note that loops are completely done with `n' and `b', without
+relying on `sed' to restart the the script automatically at the end of
+a line.
+
+     #!/usr/bin/sed -nf
+     
+     # delete all (leading) blanks
+     /./!d
+     
+     # get here: so there is a non empty
+     :x
+     # print it
+     p
+     # get next
+     n
+     # got chars? print it again, etc...
+     /./bx
+     
+     # no, don't have chars: got an empty line
+     :z
+     # get next, if last line we finish here so no trailing
+     # empty lines are written
+     n
+     # also empty? then ignore it, and get next... this will
+     # remove ALL empty lines
+     /./!bz
+     
+     # all empty lines were deleted/ignored, but we have a non empty.  As
+     # what we want to do is to squeeze, insert a blank line artificially
+     i\
+     
+     bx
+
+
+File: sed.info,  Node: Limitations,  Next: Other Resources,  Prev: Examples,  Up: Top
+
+GNU `sed''s Limitations and Non-limitations
+*******************************************
+
+   For those who want to write portable `sed' scripts, be aware that
+some implementations have been known to limit line lengths (for the
+pattern and hold spaces) to be no more than 4000 bytes.  The POSIX
+standard specifies that conforming `sed' implementations shall support
+at least 8192 byte line lengths.  GNU `sed' has no built-in limit on
+line length; as long as it can `malloc()' more (virtual) memory, you
+can feed or construct lines as long as you like.
+
+   However, recursion is used to handle subpatterns and indefinite
+repetition.  This means that the available stack space may limit the
+size of the buffer that can be processed by certain patterns.
+
+
+File: sed.info,  Node: Other Resources,  Next: Reporting Bugs,  Prev: Limitations,  Up: Top
+
+Other Resources for Learning About `sed'
+****************************************
+
+   In addition to several books that have been written about `sed'
+(either specifically or as chapters in books which discuss shell
+programming), one can find out more about `sed' (including suggestions
+of a few books) from the FAQ for the `sed-users' mailing list,
+available from any of:
+      `http://www.student.northpark.edu/pemente/sed/sedfaq.html'
+      `http://sed.sf.net/grabbag/tutorials/sedfaq.html'
+
+   Also of interest are
+`http://www.student.northpark.edu/pemente/sed/index.htm' and
+`http://sed.sf.net/grabbag', which include `sed' tutorials and other
+`sed'-related goodies.
+
+   The `sed-users' mailing list itself maintained by Sven Guckes.  To
+subscribe, visit `http://groups.yahoo.com' and search for the
+`sed-users' mailing list.
+
+
+File: sed.info,  Node: Reporting Bugs,  Next: Extended regexps,  Prev: Other Resources,  Up: Top
+
+Reporting Bugs
+**************
+
+   Email bug reports to <bonzini@gnu.org>.  Be sure to include the word
+"sed" somewhere in the `Subject:' field.  Also, please include the
+output of `sed --version' in the body of your report if at all possible.
+
+   Please do not send a bug report like this:
+
+     while building frobme-1.3.4
+     $ configure
+     error--> sed: file sedscr line 1: Unknown option to 's'
+
+   If GNU `sed' doesn't configure your favorite package, take a few
+extra minutes to identify the specific problem and make a stand-alone
+test case.  Unlike other programs such as C compilers, making such test
+cases for `sed' is quite simple.
+
+   A stand-alone test case includes all the data necessary to perform
+the test, and the specific invocation of `sed' that causes the problem.
+The smaller a stand-alone test case is, the better.  A test case should
+not involve something as far removed from `sed' as "try to configure
+frobme-1.3.4".  Yes, that is in principle enough information to look
+for the bug, but that is not a very practical prospect.
+
+   Here are a few commonly reported bugs that are not bugs.
+
+`N' command on the last line
+     Most versions of `sed' exit without printing anything when the `N'
+     command is issued on the last line of a file.  GNU `sed' prints
+     pattern space before exiting unless of course the `-n' command
+     switch has been specified.  This choice is by design.
+
+     For example, the behavior of
+          sed N foo bar
+
+     would depend on whether foo has an even or an odd number of
+     lines(1).  Or, when writing a script to read the next few lines
+     following a pattern match, traditional implementations of `sed'
+     would force you to write something like
+          /foo/{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N }
+
+     instead of just
+          /foo/{ N;N;N;N;N;N;N;N;N; }
+
+     In any case, the simplest workaround is to use `$d;N' in scripts
+     that rely on the traditional behavior, or to set the
+     `POSIXLY_CORRECT' variable to a non-empty value.
+
+Regex syntax clashes (problems with backslashes)
+     `sed' uses the POSIX basic regular expression syntax.  According to
+     the standard, the meaning of some escape sequences is undefined in
+     this syntax;  notable in the case of `sed' are `\|', `\+', `\?',
+     `\`', `\'', `\<', `\>', `\b', `\B', `\w', and `\W'.
+
+     As in all GNU programs that use POSIX basic regular expressions,
+     `sed' interprets these escape sequences as special characters.
+     So, `x\+' matches one or more occurrences of `x'.  `abc\|def'
+     matches either `abc' or `def'.
+
+     This syntax may cause problems when running scripts written for
+     other `sed's.  Some `sed' programs have been written with the
+     assumption that `\|' and `\+' match the literal characters `|' and
+     `+'.  Such scripts must be modified by removing the spurious
+     backslashes if they are to be used with modern implementations of
+     `sed', like GNU `sed'.
+
+     On the other hand, some scripts use s|abc\|def||g to remove
+     occurrences of _either_ `abc' or `def'.  While this worked until
+     `sed' 4.0.x, newer versions interpret this as removing the string
+     `abc|def'.  This is again undefined behavior according to POSIX,
+     and this interpretation is arguably more robust: older `sed's, for
+     example, required that the regex matcher parsed `\/' as `/' in the
+     common case of escaping a slash, which is again undefined
+     behavior; the new behavior avoids this, and this is good because
+     the regex matcher is only partially under our control.
+
+     In addition, this version of `sed' supports several escape
+     characters (some of which are multi-character) to insert
+     non-printable characters in scripts (`\a', `\c', `\d', `\o', `\r',
+     `\t', `\v', `\x').  These can cause similar problems with scripts
+     written for other `sed's.
+
+`-i' clobbers read-only files
+     In short, `sed -i' will let you delete the contents of a read-only
+     file, and in general the `-i' option (*note Invocation: Invoking
+     sed.) lets you clobber protected files.  This is not a bug, but
+     rather a consequence of how the Unix filesystem works.
+
+     The permissions on a file say what can happen to the data in that
+     file, while the permissions on a directory say what can happen to
+     the list of files in that directory.  `sed -i' will not ever open
+     for writing  a file that is already on disk.  Rather, it will work
+     on a temporary file that is finally renamed to the original name:
+     if you rename or delete files, you're actually modifying the
+     contents of the directory, so the operation depends on the
+     permissions of the directory, not of the file.  For this same
+     reason, `sed' does not let you use `-i' on a writeable file in a
+     read-only directory (but unbelievably nobody reports that as a
+     bug...).
+
+`0a' does not work (gives an error)
+     There is no line 0.  0 is a special address that is only used to
+     treat addresses like `0,/RE/' as active when the script starts: if
+     you write `1,/abc/d' and the first line includes the word `abc',
+     then that match would be ignored because address ranges must span
+     at least two lines (barring the end of the file); but what you
+     probably wanted is to delete every line up to the first one
+     including `abc', and this is obtained with `0,/abc/d'.
+
+`[a-z]' is case insensitive
+     You are encountering problems with locales.  POSIX mandates that
+     `[a-z]' uses the current locale's collation order - in C parlance,
+     that means using `strcoll(3)' instead of `strcmp(3)'.  Some
+     locales have a case-insensitive collation order, others don't: one
+     of those that have problems is Estonian.
+
+     Another problem is that `[a-z]' tries to use collation symbols.
+     This only happens if you are on the GNU system, using GNU libc's
+     regular expression matcher instead of compiling the one supplied
+     with GNU sed.  In a Danish locale, for example, the regular
+     expression `^[a-z]$' matches the string `aa', because this is a
+     single collating symbol that comes after `a' and before `b'; `ll'
+     behaves similarly in Spanish locales, or `ij' in Dutch locales.
+
+     To work around these problems, which may cause bugs in shell
+     scripts, set the `LC_COLLATE' and `LC_CTYPE' environment variables
+     to `C'.
+
+   ---------- Footnotes ----------
+
+   (1) which is the actual "bug" that prompted the change in behavior
+
+
+File: sed.info,  Node: Extended regexps,  Next: Concept Index,  Prev: Reporting Bugs,  Up: Top
+
+Extended regular expressions
+****************************
+
+   The only difference between basic and extended regular expressions
+is in the behavior of a few characters: `?', `+', parentheses, and
+braces (`{}').  While basic regular expressions require these to be
+escaped if you want them to behave as special characters, when using
+extended regular expressions you must escape them if you want them _to
+match a literal character_.
+
+Examples:
+`abc?'
+     becomes `abc\?' when using extended regular expressions.  It
+     matches the literal string `abc?'.
+
+`c\+'
+     becomes `c+' when using extended regular expressions.  It matches
+     one or more `c's.
+
+`a\{3,\}'
+     becomes `a{3,}' when using extended regular expressions.  It
+     matches three or more `a's.
+
+`\(abc\)\{2,3\}'
+     becomes `(abc){2,3}' when using extended regular expressions.  It
+     matches either `abcabc' or `abcabcabc'.
+
+`\(abc*\)\1'
+     becomes `(abc*)\1' when using extended regular expressions.
+     Backreferences must still be escaped when using extended regular
+     expressions.
+
+
+File: sed.info,  Node: Concept Index,  Next: Command and Option Index,  Prev: Extended regexps,  Up: Top
+
+Concept Index
+*************
+
+   This is a general index of all issues discussed in this manual, with
+the exception of the `sed' commands and command-line options.
+
+* Menu:
+
+* Additional reading about sed:          Other Resources.
+* ADDR1,+N:                              Addresses.
+* ADDR1,~N:                              Addresses.
+* Address, as a regular expression:      Addresses.
+* Address, last line:                    Addresses.
+* Address, numeric:                      Addresses.
+* Addresses, in sed scripts:             Addresses.
+* Append hold space to pattern space:    Other Commands.
+* Append next input line to pattern space: Other Commands.
+* Append pattern space to hold space:    Other Commands.
+* Appending text after a line:           Other Commands.
+* Backreferences, in regular expressions: The "s" Command.
+* Branch to a label, if s/// failed:     Extended Commands.
+* Branch to a label, if s/// succeeded:  Programming Commands.
+* Branch to a label, unconditionally:    Programming Commands.
+* Buffer spaces, pattern and hold:       Execution Cycle.
+* Bugs, reporting:                       Reporting Bugs.
+* Case-insensitive matching:             The "s" Command.
+* Caveat -- #n on first line:            Common Commands.
+* Command groups:                        Common Commands.
+* Comments, in scripts:                  Common Commands.
+* Conditional branch <1>:                Extended Commands.
+* Conditional branch:                    Programming Commands.
+* Copy hold space into pattern space:    Other Commands.
+* Copy pattern space into hold space:    Other Commands.
+* Delete first line from pattern space:  Other Commands.
+* Disabling autoprint, from command line: Invoking sed.
+* empty regular expression:              Addresses.
+* Evaluate Bourne-shell commands:        Extended Commands.
+* Evaluate Bourne-shell commands, after substitution: The "s" Command.
+* Exchange hold space with pattern space: Other Commands.
+* Excluding lines:                       Addresses.
+* Extended regular expressions, choosing: Invoking sed.
+* Extended regular expressions, syntax:  Extended regexps.
+* Files to be processed as input:        Invoking sed.
+* Flow of control in scripts:            Programming Commands.
+* Global substitution:                   The "s" Command.
+* GNU extensions, /dev/stderr file <1>:  The "s" Command.
+* GNU extensions, /dev/stderr file:      Other Commands.
+* GNU extensions, /dev/stdin file <1>:   Other Commands.
+* GNU extensions, /dev/stdin file:       Extended Commands.
+* GNU extensions, /dev/stdout file <1>:  Invoking sed.
+* GNU extensions, /dev/stdout file <2>:  The "s" Command.
+* GNU extensions, /dev/stdout file:      Other Commands.
+* GNU extensions, 0 address:             Addresses.
+* GNU extensions, 0,ADDR2 addressing:    Addresses.
+* GNU extensions, ADDR1,+N addressing:   Addresses.
+* GNU extensions, ADDR1,~N addressing:   Addresses.
+* GNU extensions, branch if s/// failed: Extended Commands.
+* GNU extensions, case modifiers in s commands: The "s" Command.
+* GNU extensions, checking for their presence: Extended Commands.
+* GNU extensions, disabling:             Invoking sed.
+* GNU extensions, evaluating Bourne-shell commands <1>: Extended Commands.
+* GNU extensions, evaluating Bourne-shell commands: The "s" Command.
+* GNU extensions, extended regular expressions: Invoking sed.
+* GNU extensions, g and NUMBER modifier interaction in s command: The "s" Command.
+* GNU extensions, I modifier <1>:        Addresses.
+* GNU extensions, I modifier:            The "s" Command.
+* GNU extensions, in-place editing <1>:  Reporting Bugs.
+* GNU extensions, in-place editing:      Invoking sed.
+* GNU extensions, L command:             Extended Commands.
+* GNU extensions, M modifier:            The "s" Command.
+* GNU extensions, modifiers and the empty regular expression: Addresses.
+* GNU extensions, N~M addresses:         Addresses.
+* GNU extensions, quitting silently:     Extended Commands.
+* GNU extensions, R command:             Extended Commands.
+* GNU extensions, reading a file a line at a time: Extended Commands.
+* GNU extensions, reformatting paragraphs: Extended Commands.
+* GNU extensions, returning an exit code <1>: Common Commands.
+* GNU extensions, returning an exit code: Extended Commands.
+* GNU extensions, setting line length:   Other Commands.
+* GNU extensions, special escapes <1>:   Reporting Bugs.
+* GNU extensions, special escapes:       Escapes.
+* GNU extensions, special two-address forms: Addresses.
+* GNU extensions, subprocesses <1>:      The "s" Command.
+* GNU extensions, subprocesses:          Extended Commands.
+* GNU extensions, to basic regular expressions <1>: Reporting Bugs.
+* GNU extensions, to basic regular expressions: Regular Expressions.
+* GNU extensions, two addresses supported by most commands: Other Commands.
+* GNU extensions, unlimited line length: Limitations.
+* GNU extensions, writing first line to a file: Extended Commands.
+* Goto, in scripts:                      Programming Commands.
+* Greedy regular expression matching:    Regular Expressions.
+* Grouping commands:                     Common Commands.
+* Hold space, appending from pattern space: Other Commands.
+* Hold space, appending to pattern space: Other Commands.
+* Hold space, copy into pattern space:   Other Commands.
+* Hold space, copying pattern space into: Other Commands.
+* Hold space, definition:                Execution Cycle.
+* Hold space, exchange with pattern space: Other Commands.
+* In-place editing:                      Reporting Bugs.
+* In-place editing, activating:          Invoking sed.
+* In-place editing, Perl-style backup file names: Invoking sed.
+* Inserting text before a line:          Other Commands.
+* Labels, in scripts:                    Programming Commands.
+* Last line, selecting:                  Addresses.
+* Line length, setting <1>:              Invoking sed.
+* Line length, setting:                  Other Commands.
+* Line number, printing:                 Other Commands.
+* Line selection:                        Addresses.
+* Line, selecting by number:             Addresses.
+* Line, selecting by regular expression match: Addresses.
+* Line, selecting last:                  Addresses.
+* List pattern space:                    Other Commands.
+* Mixing g and NUMBER modifiers in the s command: The "s" Command.
+* Next input line, append to pattern space: Other Commands.
+* Next input line, replace pattern space with: Common Commands.
+* Non-bugs, in-place editing:            Reporting Bugs.
+* Non-bugs, N command on the last line:  Reporting Bugs.
+* Non-bugs, regex syntax clashes:        Reporting Bugs.
+* Parenthesized substrings:              The "s" Command.
+* Pattern space, definition:             Execution Cycle.
+* Perl-style regular expressions, multiline: Addresses.
+* Portability, comments:                 Common Commands.
+* Portability, line length limitations:  Limitations.
+* Portability, N command on the last line: Reporting Bugs.
+* POSIXLY_CORRECT behavior, bracket expressions: Regular Expressions.
+* POSIXLY_CORRECT behavior, enabling:    Invoking sed.
+* POSIXLY_CORRECT behavior, escapes:     Escapes.
+* POSIXLY_CORRECT behavior, N command:   Reporting Bugs.
+* Print first line from pattern space:   Other Commands.
+* Printing line number:                  Other Commands.
+* Printing text unambiguously:           Other Commands.
+* Quitting <1>:                          Extended Commands.
+* Quitting:                              Common Commands.
+* Range of lines:                        Addresses.
+* Range with start address of zero:      Addresses.
+* Read next input line:                  Common Commands.
+* Read text from a file <1>:             Extended Commands.
+* Read text from a file:                 Other Commands.
+* Reformat pattern space:                Extended Commands.
+* Reformatting paragraphs:               Extended Commands.
+* Replace hold space with copy of pattern space: Other Commands.
+* Replace pattern space with copy of hold space: Other Commands.
+* Replacing all text matching regexp in a line: The "s" Command.
+* Replacing only Nth match of regexp in a line: The "s" Command.
+* Replacing selected lines with other text: Other Commands.
+* Requiring GNU sed:                     Extended Commands.
+* Script structure:                      sed Programs.
+* Script, from a file:                   Invoking sed.
+* Script, from command line:             Invoking sed.
+* sed program structure:                 sed Programs.
+* Selecting lines to process:            Addresses.
+* Selecting non-matching lines:          Addresses.
+* Several lines, selecting:              Addresses.
+* Slash character, in regular expressions: Addresses.
+* Spaces, pattern and hold:              Execution Cycle.
+* Special addressing forms:              Addresses.
+* Standard input, processing as input:   Invoking sed.
+* Stream editor:                         Introduction.
+* Subprocesses <1>:                      Extended Commands.
+* Subprocesses:                          The "s" Command.
+* Substitution of text, options:         The "s" Command.
+* Text, appending:                       Other Commands.
+* Text, deleting:                        Common Commands.
+* Text, insertion:                       Other Commands.
+* Text, printing:                        Common Commands.
+* Text, printing after substitution:     The "s" Command.
+* Text, writing to a file after substitution: The "s" Command.
+* Transliteration:                       Other Commands.
+* Unbuffered I/O, choosing:              Invoking sed.
+* Usage summary, printing:               Invoking sed.
+* Version, printing:                     Invoking sed.
+* Working on separate files:             Invoking sed.
+* Write first line to a file:            Extended Commands.
+* Write to a file:                       Other Commands.
+* Zero, as range start address:          Addresses.
+
+
+File: sed.info,  Node: Command and Option Index,  Prev: Concept Index,  Up: Top
+
+Command and Option Index
+************************
+
+   This is an alphabetical list of all `sed' commands and command-line
+options.
+
+* Menu:
+
+* # (comments):                          Common Commands.
+* --expression:                          Invoking sed.
+* --file:                                Invoking sed.
+* --help:                                Invoking sed.
+* --in-place:                            Invoking sed.
+* --line-length:                         Invoking sed.
+* --quiet:                               Invoking sed.
+* --regexp-extended:                     Invoking sed.
+* --silent:                              Invoking sed.
+* --unbuffered:                          Invoking sed.
+* --version:                             Invoking sed.
+* -e:                                    Invoking sed.
+* -f:                                    Invoking sed.
+* -i:                                    Invoking sed.
+* -l:                                    Invoking sed.
+* -n:                                    Invoking sed.
+* -n, forcing from within a script:      Common Commands.
+* -r:                                    Invoking sed.
+* -u:                                    Invoking sed.
+* : (label) command:                     Programming Commands.
+* = (print line number) command:         Other Commands.
+* a (append text lines) command:         Other Commands.
+* b (branch) command:                    Programming Commands.
+* c (change to text lines) command:      Other Commands.
+* D (delete first line) command:         Other Commands.
+* d (delete) command:                    Common Commands.
+* e (evaluate) command:                  Extended Commands.
+* G (appending Get) command:             Other Commands.
+* g (get) command:                       Other Commands.
+* H (append Hold) command:               Other Commands.
+* h (hold) command:                      Other Commands.
+* i (insert text lines) command:         Other Commands.
+* L (fLow paragraphs) command:           Extended Commands.
+* l (list unambiguously) command:        Other Commands.
+* N (append Next line) command:          Other Commands.
+* n (next-line) command:                 Common Commands.
+* P (print first line) command:          Other Commands.
+* p (print) command:                     Common Commands.
+* q (quit) command:                      Common Commands.
+* Q (silent Quit) command:               Extended Commands.
+* r (read file) command:                 Other Commands.
+* R (read line) command:                 Extended Commands.
+* s command, option flags:               The "s" Command.
+* T (test and branch if failed) command: Extended Commands.
+* t (test and branch if successful) command: Programming Commands.
+* v (version) command:                   Extended Commands.
+* w (write file) command:                Other Commands.
+* W (write first line) command:          Extended Commands.
+* x (eXchange) command:                  Other Commands.
+* y (transliterate) command:             Other Commands.
+* {} command grouping:                   Common Commands.
+
+
Index: /tags/kBuild-0.1.4/src/sed/doc/sed.texi
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/sed.texi	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/sed.texi	(revision 1780)
@@ -0,0 +1,4219 @@
+\input texinfo  @c -*-texinfo-*-
+@c Do not edit this file!! It is automatically generated from sed-in.texi.
+@c
+@c -- Stuff that needs adding: ----------------------------------------------
+@c (document the `;' command-separator)
+@c --------------------------------------------------------------------------
+@c Check for consistency: regexps in @code, text that they match in @samp.
+@c 
+@c Tips:
+@c    @command for command
+@c    @samp for command fragments: @samp{cat -s}
+@c    @code for sed commands and flags
+@c    Use ``quote'' not `quote' or "quote".
+@c
+@c %**start of header
+@setfilename sed.info
+@settitle sed, a stream editor
+@c %**end of header
+
+@c @smallbook
+
+@include version.texi
+
+@c Combine indices.
+@syncodeindex ky cp
+@syncodeindex pg cp
+@syncodeindex tp cp
+
+@defcodeindex op
+@syncodeindex op fn
+
+@include config.texi
+
+@copying
+This file documents version @value{VERSION} of
+@value{SSED}, a stream editor.
+
+Copyright @copyright{} 1998, 1999, 2001, 2002, 2003, 2004 Free
+Software Foundation, Inc.
+
+This document is released under the terms of the @acronym{GNU} Free
+Documentation License as published by the Free Software Foundation;
+either version 1.1, or (at your option) any later version.
+
+You should have received a copy of the @acronym{GNU} Free Documentation
+License along with @value{SSED}; see the file @file{COPYING.DOC}.
+If not, write to the Free Software Foundation, 59 Temple Place - Suite
+330, Boston, MA 02110-1301, USA.
+
+There are no Cover Texts and no Invariant Sections; this text, along
+with its equivalent in the printed manual, constitutes the Title Page.
+@end copying
+
+@setchapternewpage off
+
+@titlepage
+@title @command{sed}, a stream editor
+@subtitle version @value{VERSION}, @value{UPDATED}
+@author by Ken Pizzini, Paolo Bonzini
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1998, 1999 Free Software Foundation, Inc.
+
+@insertcopying
+
+Published by the Free Software Foundation, @*
+51 Franklin Street, Fifth Floor @*
+Boston, MA 02110-1301, USA
+@end titlepage
+
+
+@node Top
+@top
+
+@ifnottex
+@insertcopying
+@end ifnottex
+
+@menu
+* Introduction::               Introduction
+* Invoking sed::               Invocation
+* sed Programs::               @command{sed} programs
+* Examples::                   Some sample scripts
+* Limitations::                Limitations and (non-)limitations of @value{SSED}
+* Other Resources::            Other resources for learning about @command{sed}
+* Reporting Bugs::             Reporting bugs
+
+* Extended regexps::           @command{egrep}-style regular expressions
+@ifset PERL
+* Perl regexps::               Perl-style regular expressions
+@end ifset
+
+* Concept Index::              A menu with all the topics in this manual.
+* Command and Option Index::   A menu with all @command{sed} commands and
+                               command-line options.
+
+@detailmenu
+--- The detailed node listing ---
+
+sed Programs:
+* Execution Cycle::                 How @command{sed} works
+* Addresses::                       Selecting lines with @command{sed}
+* Regular Expressions::             Overview of regular expression syntax
+* Common Commands::                 Often used commands
+* The "s" Command::                 @command{sed}'s Swiss Army Knife
+* Other Commands::                  Less frequently used commands
+* Programming Commands::            Commands for @command{sed} gurus
+* Extended Commands::               Commands specific of @value{SSED}
+* Escapes::                         Specifying special characters
+
+Examples:
+* Centering lines::
+* Increment a number::
+* Rename files to lower case::
+* Print bash environment::
+* Reverse chars of lines::
+* tac::                             Reverse lines of files
+* cat -n::                          Numbering lines
+* cat -b::                          Numbering non-blank lines
+* wc -c::                           Counting chars
+* wc -w::                           Counting words
+* wc -l::                           Counting lines
+* head::                            Printing the first lines
+* tail::                            Printing the last lines
+* uniq::                            Make duplicate lines unique
+* uniq -d::                         Print duplicated lines of input
+* uniq -u::                         Remove all duplicated lines
+* cat -s::                          Squeezing blank lines
+
+@ifset PERL
+Perl regexps::                      Perl-style regular expressions
+* Backslash::                       Introduces special sequences
+* Circumflex/dollar sign/period::   Behave specially with regard to new lines
+* Square brackets::                 Are a bit different in strange cases
+* Options setting::                 Toggle modifiers in the middle of a regexp
+* Non-capturing subpatterns::       Are not counted when backreferencing
+* Repetition::                      Allows for non-greedy matching
+* Backreferences::                  Allows for more than 10 back references
+* Assertions::                      Allows for complex look ahead matches
+* Non-backtracking subpatterns::    Often gives more performance
+* Conditional subpatterns::         Allows if/then/else branches
+* Recursive patterns::              For example to match parentheses
+* Comments::                        Because things can get complex...
+@end ifset
+
+@end detailmenu
+@end menu
+
+
+@node Introduction
+@chapter Introduction
+
+@cindex Stream editor
+@command{sed} is a stream editor.
+A stream editor is used to perform basic text
+transformations on an input stream
+(a file or input from a pipeline).
+While in some ways similar to an editor which
+permits scripted edits (such as @command{ed}),
+@command{sed} works by making only one pass over the
+input(s), and is consequently more efficient.
+But it is @command{sed}'s ability to filter text in a pipeline
+which particularly distinguishes it from other types of
+editors.
+
+
+@node Invoking sed
+@chapter Invocation
+
+Normally @command{sed} is invoked like this:
+
+@example
+sed SCRIPT INPUTFILE...
+@end example
+
+The full format for invoking @command{sed} is:
+
+@example
+sed OPTIONS... [SCRIPT] [INPUTFILE...]
+@end example
+
+If you do not specify @var{INPUTFILE}, or if @var{INPUTFILE} is @file{-},
+@command{sed} filters the contents of the standard input.  The @var{script}
+is actually the first non-option parameter, which @command{sed} specially
+considers a script and not an input file if (and only if) none of the
+other @var{options} specifies a script to be executed, that is if neither
+of the @option{-e} and @option{-f} options is specified.
+
+@command{sed} may be invoked with the following command-line options:
+
+@table @code
+@item --version
+@opindex --version
+@cindex Version, printing
+Print out the version of @command{sed} that is being run and a copyright notice,
+then exit.
+
+@item --help
+@opindex --help
+@cindex Usage summary, printing
+Print a usage message briefly summarizing these command-line options
+and the bug-reporting address,
+then exit.
+
+@item -n
+@itemx --quiet
+@itemx --silent
+@opindex -n
+@opindex --quiet
+@opindex --silent
+@cindex Disabling autoprint, from command line
+By default, @command{sed} prints out the pattern space
+at the end of each cycle through the script.
+These options disable this automatic printing,
+and @command{sed} only produces output when explicitly told to
+via the @code{p} command.
+
+@item -i[@var{SUFFIX}]
+@itemx --in-place[=@var{SUFFIX}]
+@opindex -i
+@opindex --in-place
+@cindex In-place editing, activating
+@cindex @value{SSEDEXT}, in-place editing
+This option specifies that files are to be edited in-place.
+@value{SSED} does this by creating a temporary file and
+sending output to this file rather than to the standard
+output.@footnote{This applies to commands such as @code{=},
+@code{a}, @code{c}, @code{i}, @code{l}, @code{p}.  You can
+still write to the standard output by using the @code{w}
+@cindex @value{SSEDEXT}, @file{/dev/stdout} file
+or @code{W} commands together with the @file{/dev/stdout}
+special file}.
+
+This option implies @option{-s}.
+
+When the end of the file is reached, the temporary file is
+renamed to the output file's original name.  The extension,
+if supplied, is used to modify the name of the old file
+before renaming the temporary file, thereby making a backup
+copy@footnote{Note that @value{SSED} creates the backup
+    file whether or not any output is actually changed.}).
+
+@cindex In-place editing, Perl-style backup file names
+This rule is followed: if the extension doesn't contain a @code{*},
+then it is appended to the end of the current filename as a
+suffix; if the extension does contain one or more @code{*}
+characters, then @emph{each} asterisk is replaced with the
+current filename.  This allows you to add a prefix to the
+backup file, instead of (or in addition to) a suffix, or
+even to place backup copies of the original files into another
+directory (provided the directory already exists).
+
+If no extension is supplied, the original file is
+overwritten without making a backup.
+
+@item -l @var{N}
+@itemx --line-length=@var{N}
+@opindex -l
+@opindex --line-length
+@cindex Line length, setting
+Specify the default line-wrap length for the @code{l} command.
+A length of 0 (zero) means to never wrap long lines.  If
+not specified, it is taken to be 70.
+
+@item --posix
+@cindex @value{SSEDEXT}, disabling
+@value{SSED} includes several extensions to @acronym{POSIX}
+sed.  In order to simplify writing portable scripts, this
+option disables all the extensions that this manual documents,
+including additional commands.
+@cindex @code{POSIXLY_CORRECT} behavior, enabling
+Most of the extensions accept @command{sed} programs that
+are outside the syntax mandated by @acronym{POSIX}, but some
+of them (such as the behavior of the @command{N} command
+described in @pxref{Reporting Bugs}) actually violate the
+standard.  If you want to disable only the latter kind of
+extension, you can set the @code{POSIXLY_CORRECT} variable
+to a non-empty value.
+
+@item -r
+@itemx --regexp-extended
+@opindex -r
+@opindex --regexp-extended
+@cindex Extended regular expressions, choosing
+@cindex @acronym{GNU} extensions, extended regular expressions
+Use extended regular expressions rather than basic
+regular expressions.  Extended regexps are those that
+@command{egrep} accepts; they can be clearer because they
+usually have less backslashes, but are a @acronym{GNU} extension
+and hence scripts that use them are not portable.
+@xref{Extended regexps, , Extended regular expressions}.
+
+@ifset PERL
+@item -R
+@itemx --regexp-perl
+@opindex -R
+@opindex --regexp-perl
+@cindex Perl-style regular expressions, choosing
+@cindex @value{SSEDEXT}, Perl-style regular expressions
+Use Perl-style regular expressions rather than basic
+regular expressions.  Perl-style regexps are extremely
+powerful but are a @value{SSED} extension and hence scripts that
+use it are not portable.  @xref{Perl regexps, ,
+Perl-style regular expressions}.
+@end ifset
+
+@item -s
+@itemx --separate
+@cindex Working on separate files
+By default, @command{sed} will consider the files specified on the
+command line as a single continuous long stream.  This @value{SSED}
+extension allows the user to consider them as separate files:
+range addresses (such as @samp{/abc/,/def/}) are not allowed
+to span several files, line numbers are relative to the start
+of each file, @code{$} refers to the last line of each file,
+and files invoked from the @code{R} commands are rewound at the
+start of each file.
+
+@item -u
+@itemx --unbuffered
+@opindex -u
+@opindex --unbuffered
+@cindex Unbuffered I/O, choosing
+Buffer both input and output as minimally as practical.
+(This is particularly useful if the input is coming from
+the likes of @samp{tail -f}, and you wish to see the transformed
+output as soon as possible.)
+
+@item -e @var{script}
+@itemx --expression=@var{script}
+@opindex -e
+@opindex --expression
+@cindex Script, from command line
+Add the commands in @var{script} to the set of commands to be
+run while processing the input.
+
+@item -f @var{script-file}
+@itemx --file=@var{script-file}
+@opindex -f
+@opindex --file
+@cindex Script, from a file
+Add the commands contained in the file @var{script-file}
+to the set of commands to be run while processing the input.
+
+@end table
+
+If no @option{-e}, @option{-f}, @option{--expression}, or @option{--file}
+options are given on the command-line,
+then the first non-option argument on the command line is
+taken to be the @var{script} to be executed.
+
+@cindex Files to be processed as input
+If any command-line parameters remain after processing the above,
+these parameters are interpreted as the names of input files to
+be processed.
+@cindex Standard input, processing as input
+A file name of @samp{-} refers to the standard input stream.
+The standard input will be processed if no file names are specified.
+
+
+@node sed Programs
+@chapter @command{sed} Programs
+
+@cindex @command{sed} program structure
+@cindex Script structure
+A @command{sed} program consists of one or more @command{sed} commands,
+passed in by one or more of the
+@option{-e}, @option{-f}, @option{--expression}, and @option{--file}
+options, or the first non-option argument if zero of these
+options are used.
+This document will refer to ``the'' @command{sed} script;
+this is understood to mean the in-order catenation
+of all of the @var{script}s and @var{script-file}s passed in.
+
+Each @code{sed} command consists of an optional address or
+address range, followed by a one-character command name
+and any additional command-specific code.
+
+@menu
+* Execution Cycle::          How @command{sed} works
+* Addresses::                Selecting lines with @command{sed}
+* Regular Expressions::      Overview of regular expression syntax
+* Common Commands::          Often used commands
+* The "s" Command::          @command{sed}'s Swiss Army Knife
+* Other Commands::           Less frequently used commands
+* Programming Commands::     Commands for @command{sed} gurus
+* Extended Commands::        Commands specific of @value{SSED}
+* Escapes::                  Specifying special characters
+@end menu
+
+
+@node Execution Cycle
+@section How @command{sed} Works
+
+@cindex Buffer spaces, pattern and hold
+@cindex Spaces, pattern and hold
+@cindex Pattern space, definition
+@cindex Hold space, definition
+@command{sed} maintains two data buffers: the active @emph{pattern} space,
+and the auxiliary @emph{hold} space. Both are initially empty.
+
+@command{sed} operates by performing the following cycle on each
+lines of input: first, @command{sed} reads one line from the input
+stream, removes any trailing newline, and places it in the pattern space.
+Then commands are executed; each command can have an address associated
+to it: addresses are a kind of condition code, and a command is only
+executed if the condition is verified before the command is to be
+executed.
+
+When the end of the script is reached, unless the @option{-n} option
+is in use, the contents of pattern space are printed out to the output
+stream, adding back the trailing newline if it was removed.@footnote{Actually,
+  if @command{sed} prints a line without the terminating newline, it will
+  nevertheless print the missing newline as soon as more text is sent to
+  the same output stream, which gives the ``least expected surprise''
+  even though it does not make commands like @samp{sed -n p} exactly
+  identical to @command{cat}.} Then the next cycle starts for the next
+input line.
+
+Unless special commands (like @samp{D}) are used, the pattern space is
+deleted between two cycles. The hold space, on the other hand, keeps
+its data between cycles (see commands @samp{h}, @samp{H}, @samp{x},
+@samp{g}, @samp{G} to move data between both buffers).
+
+
+@node Addresses
+@section Selecting lines with @command{sed}
+@cindex Addresses, in @command{sed} scripts
+@cindex Line selection
+@cindex Selecting lines to process
+
+Addresses in a @command{sed} script can be in any of the following forms:
+@table @code
+@item @var{number}
+@cindex Address, numeric
+@cindex Line, selecting by number
+Specifying a line number will match only that line in the input.
+(Note that @command{sed} counts lines continuously across all input files
+unless @option{-i} or @option{-s} options are specified.)
+
+@item @var{first}~@var{step}
+@cindex @acronym{GNU} extensions, @samp{@var{n}~@var{m}} addresses
+This @acronym{GNU} extension matches every @var{step}th line
+starting with line @var{first}.
+In particular, lines will be selected when there exists
+a non-negative @var{n} such that the current line-number equals
+@var{first} + (@var{n} * @var{step}).
+Thus, to select the odd-numbered lines,
+one would use @code{1~2};
+to pick every third line starting with the second, @samp{2~3} would be used;
+to pick every fifth line starting with the tenth, use @samp{10~5};
+and @samp{50~0} is just an obscure way of saying @code{50}.
+
+@item $
+@cindex Address, last line
+@cindex Last line, selecting
+@cindex Line, selecting last
+This address matches the last line of the last file of input, or
+the last line of each file when the @option{-i} or @option{-s} options
+are specified.
+
+@item /@var{regexp}/
+@cindex Address, as a regular expression
+@cindex Line, selecting by regular expression match
+This will select any line which matches the regular expression @var{regexp}.
+If @var{regexp} itself includes any @code{/} characters,
+each must be escaped by a backslash (@code{\}).
+
+@cindex empty regular expression
+@cindex @value{SSEDEXT}, modifiers and the empty regular expression
+The empty regular expression @samp{//} repeats the last regular
+expression match (the same holds if the empty regular expression is
+passed to the @code{s} command).  Note that modifiers to regular expressions
+are evaluated when the regular expression is compiled, thus it is invalid to
+specify them together with the empty regular expression.
+
+@item \%@var{regexp}%
+(The @code{%} may be replaced by any other single character.)
+
+@cindex Slash character, in regular expressions
+This also matches the regular expression @var{regexp},
+but allows one to use a different delimiter than @code{/}.
+This is particularly useful if the @var{regexp} itself contains
+a lot of slashes, since it avoids the tedious escaping of every @code{/}.
+If @var{regexp} itself includes any delimiter characters,
+each must be escaped by a backslash (@code{\}).
+
+@item /@var{regexp}/I
+@itemx \%@var{regexp}%I
+@cindex @acronym{GNU} extensions, @code{I} modifier
+@ifset PERL
+@cindex Perl-style regular expressions, case-insensitive
+@end ifset
+The @code{I} modifier to regular-expression matching is a @acronym{GNU}
+extension which causes the @var{regexp} to be matched in
+a case-insensitive manner.
+
+@item /@var{regexp}/M
+@itemx \%@var{regexp}%M
+@ifset PERL
+@cindex @value{SSEDEXT}, @code{M} modifier
+@end ifset
+@cindex Perl-style regular expressions, multiline
+The @code{M} modifier to regular-expression matching is a @value{SSED}
+extension which causes @code{^} and @code{$} to match respectively
+(in addition to the normal behavior) the empty string after a newline,
+and the empty string before a newline.  There are special character
+sequences
+@ifset PERL
+(@code{\A} and @code{\Z} in Perl mode, @code{\`} and @code{\'}
+in basic or extended regular expression modes)
+@end ifset
+@ifclear PERL
+(@code{\`} and @code{\'})
+@end ifclear
+which always match the beginning or the end of the buffer.
+@code{M} stands for @cite{multi-line}.
+
+@ifset PERL
+@item /@var{regexp}/S
+@itemx \%@var{regexp}%S
+@cindex @value{SSEDEXT}, @code{S} modifier
+@cindex Perl-style regular expressions, single line
+The @code{S} modifier to regular-expression matching is only valid
+in Perl mode and specifies that the dot character (@code{.}) will
+match the newline character too.  @code{S} stands for @cite{single-line}.
+@end ifset
+
+@ifset PERL
+@item /@var{regexp}/X
+@itemx \%@var{regexp}%X
+@cindex @value{SSEDEXT}, @code{X} modifier
+@cindex Perl-style regular expressions, extended
+The @code{X} modifier to regular-expression matching is also
+valid in Perl mode only.  If it is used, whitespace in the
+pattern (other than in a character class) and
+characters between a @kbd{#} outside a character class and the
+next newline character are ignored. An escaping backslash
+can be used to include a whitespace or @kbd{#} character as part
+of the pattern.
+@end ifset
+@end table
+
+If no addresses are given, then all lines are matched;
+if one address is given, then only lines matching that
+address are matched.
+
+@cindex Range of lines
+@cindex Several lines, selecting
+An address range can be specified by specifying two addresses
+separated by a comma (@code{,}).  An address range matches lines
+starting from where the first address matches, and continues
+until the second address matches (inclusively).
+
+If the second address is a @var{regexp}, then checking for the
+ending match will start with the line @emph{following} the
+line which matched the first address: a range will always
+span at least two lines (except of course if the input stream
+ends).
+
+If the second address is a @var{number} less than (or equal to)
+the line matching the first address, then only the one line is
+matched.
+
+@cindex Special addressing forms
+@cindex Range with start address of zero
+@cindex Zero, as range start address
+@cindex @var{addr1},+N
+@cindex @var{addr1},~N
+@cindex @acronym{GNU} extensions, special two-address forms
+@cindex @acronym{GNU} extensions, @code{0} address
+@cindex @acronym{GNU} extensions, 0,@var{addr2} addressing
+@cindex @acronym{GNU} extensions, @var{addr1},+@var{N} addressing
+@cindex @acronym{GNU} extensions, @var{addr1},~@var{N} addressing
+@value{SSED} also supports some special two-address forms; all these
+are @acronym{GNU} extensions:
+@table @code
+@item 0,/@var{regexp}/
+A line number of @code{0} can be used in an address specification like
+@code{0,/@var{regexp}/} so that @command{sed} will try to match
+@var{regexp} in the first input line too.  In other words,
+@code{0,/@var{regexp}/} is similar to @code{1,/@var{regexp}/},
+except that if @var{addr2} matches the very first line of input the
+@code{0,/@var{regexp}/} form will consider it to end the range, whereas
+the @code{1,/@var{regexp}/} form will match the beginning of its range and
+hence make the range span up to the @emph{second} occurrence of the
+regular expression.
+
+Note that this is the only place where the @code{0} address makes
+sense; there is no 0-th line and commands which are given the @code{0}
+address in any other way will give an error.
+
+@item @var{addr1},+@var{N}
+Matches @var{addr1} and the @var{N} lines following @var{addr1}.
+
+@item @var{addr1},~@var{N}
+Matches @var{addr1} and the lines following @var{addr1}
+until the next line whose input line number is a multiple of @var{N}.
+@end table
+
+@cindex Excluding lines
+@cindex Selecting non-matching lines
+Appending the @code{!} character to the end of an address
+specification negates the sense of the match.
+That is, if the @code{!} character follows an address range,
+then only lines which do @emph{not} match the address range
+will be selected.
+This also works for singleton addresses,
+and, perhaps perversely, for the null address.
+
+
+@node Regular Expressions
+@section Overview of Regular Expression Syntax
+
+To know how to use @command{sed}, people should understand regular
+expressions (@dfn{regexp} for short).  A regular expression
+is a pattern that is matched against a
+subject string from left to right.  Most characters are
+@dfn{ordinary}: they stand for
+themselves in a pattern, and match the corresponding characters
+in the subject.  As a trivial example, the pattern
+
+@example
+     The quick brown fox
+@end example
+
+@noindent
+matches a portion of a subject string that is identical to
+itself.  The power of regular expressions comes from the
+ability to include alternatives and repetitions in the pattern.
+These are encoded in the pattern by the use of @dfn{special characters},
+which do not stand for themselves but instead
+are interpreted in some special way.  Here is a brief description
+of regular expression syntax as used in @command{sed}.
+
+@table @code
+@item @var{char}
+A single ordinary character matches itself.
+
+@item *
+@cindex @acronym{GNU} extensions, to basic regular expressions
+Matches a sequence of zero or more instances of matches for the
+preceding regular expression, which must be an ordinary character, a
+special character preceded by @code{\}, a @code{.}, a grouped regexp
+(see below), or a bracket expression.  As a @acronym{GNU} extension, a
+postfixed regular expression can also be followed by @code{*}; for
+example, @code{a**} is equivalent to @code{a*}.  @acronym{POSIX}
+1003.1-2001 says that @code{*} stands for itself when it appears at
+the start of a regular expression or subexpression, but many
+non@acronym{GNU} implementations do not support this and portable
+scripts should instead use @code{\*} in these contexts.
+
+@item \+
+@cindex @acronym{GNU} extensions, to basic regular expressions
+As @code{*}, but matches one or more.  It is a @acronym{GNU} extension.
+
+@item \?
+@cindex @acronym{GNU} extensions, to basic regular expressions
+As @code{*}, but only matches zero or one.  It is a @acronym{GNU} extension.
+
+@item \@{@var{i}\@}
+As @code{*}, but matches exactly @var{i} sequences (@var{i} is a
+decimal integer; for portability, keep it between 0 and 255
+inclusive).
+
+@item \@{@var{i},@var{j}\@}
+Matches between @var{i} and @var{j}, inclusive, sequences.
+
+@item \@{@var{i},\@}
+Matches more than or equal to @var{i} sequences.
+
+@item \(@var{regexp}\)
+Groups the inner @var{regexp} as a whole, this is used to: 
+
+@itemize @bullet
+@item
+@cindex @acronym{GNU} extensions, to basic regular expressions
+Apply postfix operators, like @code{\(abcd\)*}:
+this will search for zero or more whole sequences 
+of @samp{abcd}, while @code{abcd*} would search
+for @samp{abc} followed by zero or more occurrences
+of @samp{d}.  Note that support for @code{\(abcd\)*} is
+required by @acronym{POSIX} 1003.1-2001, but many non-@acronym{GNU}
+implementations do not support it and hence it is not universally
+portable.         
+
+@item
+Use back references (see below).
+@end itemize
+
+@item .
+Matches any character, including newline.
+
+@item ^
+Matches the null string at beginning of line, i.e. what
+appears after the circumflex must appear at the 
+beginning of line. @code{^#include} will match only 
+lines where @samp{#include} is the first thing on line---if
+there are spaces before, for example, the match fails.
+@code{^} acts as a special character only at the beginning
+of the regular expression or subexpression (that is,
+after @code{\(} or @code{\|}).  Portable scripts should avoid
+@code{^} at the beginning of a subexpression, though, as
+@acronym{POSIX} allows implementations that treat @code{^} as
+an ordinary character in that context.
+
+
+@item $
+It is the same as @code{^}, but refers to end of line.
+@code{$} also acts as a special character only at the end
+of the regular expression or subexpression (that is, before @code{\)}
+or @code{\|}), and its use at the end of a subexpression is not
+portable.
+
+
+@item [@var{list}]
+@itemx [^@var{list}]
+Matches any single character in @var{list}: for example,
+@code{[aeiou]} matches all vowels.  A list may include
+sequences like @code{@var{char1}-@var{char2}}, which
+matches any character between (inclusive) @var{char1}
+and @var{char2}.
+
+A leading @code{^} reverses the meaning of @var{list}, so that
+it matches any single character @emph{not} in @var{list}.  To include
+@code{]} in the list, make it the first character (after
+the @code{^} if needed), to include @code{-} in the list,
+make it the first or last; to include @code{^} put
+it after the first character.
+
+@cindex @code{POSIXLY_CORRECT} behavior, bracket expressions
+The characters @code{$}, @code{*}, @code{.}, @code{[}, and @code{\}
+are normally not special within @var{list}.  For example, @code{[\*]}
+matches either @samp{\} or @samp{*}, because the @code{\} is not
+special here.  However, strings like @code{[.ch.]}, @code{[=a=]}, and
+@code{[:space:]} are special within @var{list} and represent collating
+symbols, equivalence classes, and character classes, respectively, and
+@code{[} is therefore special within @var{list} when it is followed by
+@code{.}, @code{=}, or @code{:}.  Also, when not in
+@env{POSIXLY_CORRECT} mode, special escapes like @code{\n} and
+@code{\t} are recognized within @var{list}.  @xref{Escapes}.
+
+@item @var{regexp1}\|@var{regexp2}
+@cindex @acronym{GNU} extensions, to basic regular expressions
+Matches either @var{regexp1} or @var{regexp2}.  Use
+parentheses to use complex alternative regular expressions.
+The matching process tries each alternative in turn, from
+left to right, and the first one that succeeds is used.
+It is a @acronym{GNU} extension.
+
+@item @var{regexp1}@var{regexp2}
+Matches the concatenation of @var{regexp1} and @var{regexp2}.
+Concatenation binds more tightly than @code{\|}, @code{^}, and
+@code{$}, but less tightly than the other regular expression
+operators.
+
+@item \@var{digit}
+Matches the @var{digit}-th @code{\(@dots{}\)} parenthesized
+subexpression in the regular expression.  This is called a @dfn{back
+reference}.  Subexpressions are implicity numbered by counting
+occurrences of @code{\(} left-to-right.
+
+@item \n
+Matches the newline character.
+
+@item \@var{char}
+Matches @var{char}, where @var{char} is one of @code{$},
+@code{*}, @code{.}, @code{[}, @code{\}, or @code{^}.
+Note that the only C-like
+backslash sequences that you can portably assume to be
+interpreted are @code{\n} and @code{\\}; in particular
+@code{\t} is not portable, and matches a @samp{t} under most
+implementations of @command{sed}, rather than a tab character.
+
+@end table
+
+@cindex Greedy regular expression matching
+Note that the regular expression matcher is greedy, i.e., matches
+are attempted from left to right and, if two or more matches are
+possible starting at the same character, it selects the longest.
+
+@noindent
+Examples:
+@table @samp
+@item abcdef
+Matches @samp{abcdef}.
+
+@item a*b
+Matches zero or more @samp{a}s followed by a single
+@samp{b}.  For example, @samp{b} or @samp{aaaaab}. 
+
+@item a\?b
+Matches @samp{b} or @samp{ab}.
+
+@item a\+b\+
+Matches one or more @samp{a}s followed by one or more
+@samp{b}s: @samp{ab} is the shortest possible match, but
+other examples are @samp{aaaab} or @samp{abbbbb} or
+@samp{aaaaaabbbbbbb}.
+
+@item .*
+@itemx .\+
+These two both match all the characters in a string;
+however, the first matches every string (including the empty
+string), while the second matches only strings containing
+at least one character.
+
+@item ^main.*(.*)
+his matches a string starting with @samp{main},
+followed by an opening and closing
+parenthesis.  The @samp{n}, @samp{(} and @samp{)} need not
+be adjacent.
+
+@item ^#
+This matches a string beginning with @samp{#}.
+
+@item \\$
+This matches a string ending with a single backslash.  The
+regexp contains two backslashes for escaping.
+
+@item \$
+Instead, this matches a string consisting of a single dollar sign,
+because it is escaped.
+
+@item [a-zA-Z0-9]
+In the C locale, this matches any @acronym{ASCII} letters or digits.
+
+@item [^ @kbd{tab}]\+
+(Here @kbd{tab} stands for a single tab character.)
+This matches a string of one or more
+characters, none of which is a space or a tab.
+Usually this means a word.
+
+@item ^\(.*\)\n\1$
+This matches a string consisting of two equal substrings separated by
+a newline.
+
+@item .\@{9\@}A$
+This matches nine characters followed by an @samp{A}.
+
+@item ^.\@{15\@}A
+This matches the start of a string that contains 16 characters,
+the last of which is an @samp{A}.
+
+@end table
+
+
+
+@node Common Commands
+@section Often-Used Commands
+
+If you use @command{sed} at all, you will quite likely want to know
+these commands.
+
+@table @code
+@item #
+[No addresses allowed.]
+
+@findex # (comments)
+@cindex Comments, in scripts
+The @code{#} character begins a comment;
+the comment continues until the next newline.
+
+@cindex Portability, comments
+If you are concerned about portability, be aware that
+some implementations of @command{sed} (which are not @sc{posix}
+conformant) may only support a single one-line comment,
+and then only when the very first character of the script is a @code{#}.
+
+@findex -n, forcing from within a script
+@cindex Caveat --- #n on first line
+Warning: if the first two characters of the @command{sed} script
+are @code{#n}, then the @option{-n} (no-autoprint) option is forced.
+If you want to put a comment in the first line of your script
+and that comment begins with the letter @samp{n}
+and you do not want this behavior,
+then be sure to either use a capital @samp{N},
+or place at least one space before the @samp{n}.
+
+@item q [@var{exit-code}]
+This command only accepts a single address.
+
+@findex q (quit) command
+@cindex @value{SSEDEXT}, returning an exit code
+@cindex Quitting
+Exit @command{sed} without processing any more commands or input.
+Note that the current pattern space is printed if auto-print is
+not disabled with the @option{-n} options.  The ability to return
+an exit code from the @command{sed} script is a @value{SSED} extension.
+
+@item d
+@findex d (delete) command
+@cindex Text, deleting
+Delete the pattern space;
+immediately start next cycle.
+
+@item p
+@findex p (print) command
+@cindex Text, printing
+Print out the pattern space (to the standard output).
+This command is usually only used in conjunction with the @option{-n}
+command-line option.
+
+@item n
+@findex n (next-line) command
+@cindex Next input line, replace pattern space with
+@cindex Read next input line
+If auto-print is not disabled, print the pattern space,
+then, regardless, replace the pattern space with the next line of input.
+If there is no more input then @command{sed} exits without processing
+any more commands.
+
+@item @{ @var{commands} @}
+@findex @{@} command grouping
+@cindex Grouping commands
+@cindex Command groups
+A group of commands may be enclosed between
+@code{@{} and @code{@}} characters.
+This is particularly useful when you want a group of commands
+to be triggered by a single address (or address-range) match.
+
+@end table
+
+@node The "s" Command
+@section The @code{s} Command
+
+The syntax of the @code{s} (as in substitute) command is
+@samp{s/@var{regexp}/@var{replacement}/@var{flags}}.  The @code{/}
+characters may be uniformly replaced by any other single
+character within any given @code{s} command.  The @code{/}
+character (or whatever other character is used in its stead)
+can appear in the @var{regexp} or @var{replacement}
+only if it is preceded by a @code{\} character.
+
+The @code{s} command is probably the most important in @command{sed}
+and has a lot of different options.  Its basic concept is simple:
+the @code{s} command attempts to match the pattern
+space against the supplied @var{regexp}; if the match is
+successful, then that portion of the pattern
+space which was matched is replaced with @var{replacement}.
+
+@cindex Backreferences, in regular expressions
+@cindex Parenthesized substrings
+The @var{replacement} can contain @code{\@var{n}} (@var{n} being
+a number from 1 to 9, inclusive) references, which refer to
+the portion of the match which is contained between the @var{n}th
+@code{\(} and its matching @code{\)}.
+Also, the @var{replacement} can contain unescaped @code{&}
+characters which reference the whole matched portion
+of the pattern space.
+@cindex @value{SSEDEXT}, case modifiers in @code{s} commands
+Finally, as a @value{SSED} extension, you can include a
+special sequence made of a backslash and one of the letters
+@code{L}, @code{l}, @code{U}, @code{u}, or @code{E}.
+The meaning is as follows:
+
+@table @code
+@item \L
+Turn the replacement
+to lowercase until a @code{\U} or @code{\E} is found,
+
+@item \l
+Turn the
+next character to lowercase,
+
+@item \U
+Turn the replacement to uppercase
+until a @code{\L} or @code{\E} is found,
+
+@item \u
+Turn the next character
+to uppercase,
+
+@item \E
+Stop case conversion started by @code{\L} or @code{\U}.
+@end table
+
+To include a literal @code{\}, @code{&}, or newline in the final
+replacement, be sure to precede the desired @code{\}, @code{&},
+or newline in the @var{replacement} with a @code{\}.
+
+@findex s command, option flags
+@cindex Substitution of text, options
+The @code{s} command can be followed by zero or more of the
+following @var{flags}:
+
+@table @code
+@item g
+@cindex Global substitution
+@cindex Replacing all text matching regexp in a line
+Apply the replacement to @emph{all} matches to the @var{regexp},
+not just the first.
+
+@item @var{number}
+@cindex Replacing only @var{n}th match of regexp in a line
+Only replace the @var{number}th match of the @var{regexp}.
+
+@cindex @acronym{GNU} extensions, @code{g} and @var{number} modifier interaction in @code{s} command
+@cindex Mixing @code{g} and @var{number} modifiers in the @code{s} command
+Note: the @sc{posix} standard does not specify what should happen
+when you mix the @code{g} and @var{number} modifiers,
+and currently there is no widely agreed upon meaning
+across @command{sed} implementations.
+For @value{SSED}, the interaction is defined to be:
+ignore matches before the @var{number}th,
+and then match and replace all matches from
+the @var{number}th on.
+
+@item p
+@cindex Text, printing after substitution
+If the substitution was made, then print the new pattern space.
+
+Note: when both the @code{p} and @code{e} options are specified,
+the relative ordering of the two produces very different results.
+In general, @code{ep} (evaluate then print) is what you want,
+but operating the other way round can be useful for debugging.
+For this reason, the current version of @value{SSED} interprets
+specially the presence of @code{p} options both before and after
+@code{e}, printing the pattern space before and after evaluation,
+while in general flags for the @code{s} command show their
+effect just once.  This behavior, although documented, might
+change in future versions.
+
+@item w @var{file-name}
+@cindex Text, writing to a file after substitution
+@cindex @value{SSEDEXT}, @file{/dev/stdout} file
+@cindex @value{SSEDEXT}, @file{/dev/stderr} file
+If the substitution was made, then write out the result to the named file.
+As a @value{SSED} extension, two special values of @var{file-name} are
+supported: @file{/dev/stderr}, which writes the result to the standard
+error, and @file{/dev/stdout}, which writes to the standard
+output.@footnote{This is equivalent to @code{p} unless the @option{-i}
+option is being used.}
+
+@item e
+@cindex Evaluate Bourne-shell commands, after substitution
+@cindex Subprocesses
+@cindex @value{SSEDEXT}, evaluating Bourne-shell commands
+@cindex @value{SSEDEXT}, subprocesses
+This command allows one to pipe input from a shell command
+into pattern space.  If a substitution was made, the command
+that is found in pattern space is executed and pattern space
+is replaced with its output.  A trailing newline is suppressed;
+results are undefined if the command to be executed contains
+a @sc{nul} character.  This is a @value{SSED} extension.
+
+@item I
+@itemx i
+@cindex @acronym{GNU} extensions, @code{I} modifier
+@cindex Case-insensitive matching
+@ifset PERL
+@cindex Perl-style regular expressions, case-insensitive
+@end ifset
+The @code{I} modifier to regular-expression matching is a @acronym{GNU}
+extension which makes @command{sed} match @var{regexp} in a
+case-insensitive manner.
+
+@item M
+@itemx m
+@cindex @value{SSEDEXT}, @code{M} modifier
+@ifset PERL
+@cindex Perl-style regular expressions, multiline
+@end ifset
+The @code{M} modifier to regular-expression matching is a @value{SSED}
+extension which causes @code{^} and @code{$} to match respectively
+(in addition to the normal behavior) the empty string after a newline,
+and the empty string before a newline.  There are special character
+sequences
+@ifset PERL
+(@code{\A} and @code{\Z} in Perl mode, @code{\`} and @code{\'}
+in basic or extended regular expression modes)
+@end ifset
+@ifclear PERL
+(@code{\`} and @code{\'})
+@end ifclear
+which always match the beginning or the end of the buffer.
+@code{M} stands for @cite{multi-line}.
+
+@ifset PERL
+@item S
+@itemx s
+@cindex @value{SSEDEXT}, @code{S} modifier
+@cindex Perl-style regular expressions, single line
+The @code{S} modifier to regular-expression matching is only valid
+in Perl mode and specifies that the dot character (@code{.}) will
+match the newline character too.  @code{S} stands for @cite{single-line}.
+@end ifset
+
+@ifset PERL
+@item X
+@itemx x
+@cindex @value{SSEDEXT}, @code{X} modifier
+@cindex Perl-style regular expressions, extended
+The @code{X} modifier to regular-expression matching is also
+valid in Perl mode only.  If it is used, whitespace in the
+pattern (other than in a character class) and
+characters between a @kbd{#} outside a character class and the
+next newline character are ignored. An escaping backslash
+can be used to include a whitespace or @kbd{#} character as part
+of the pattern.
+@end ifset
+@end table
+
+
+@node Other Commands
+@section Less Frequently-Used Commands
+
+Though perhaps less frequently used than those in the previous
+section, some very small yet useful @command{sed} scripts can be built with
+these commands.
+
+@table @code
+@item y/@var{source-chars}/@var{dest-chars}/
+(The @code{/} characters may be uniformly replaced by
+any other single character within any given @code{y} command.)
+
+@findex y (transliterate) command
+@cindex Transliteration
+Transliterate any characters in the pattern space which match
+any of the @var{source-chars} with the corresponding character
+in @var{dest-chars}.
+
+Instances of the @code{/} (or whatever other character is used in its stead),
+@code{\}, or newlines can appear in the @var{source-chars} or @var{dest-chars}
+lists, provide that each instance is escaped by a @code{\}.
+The @var{source-chars} and @var{dest-chars} lists @emph{must}
+contain the same number of characters (after de-escaping).
+
+@item a\
+@itemx @var{text}
+@cindex @value{SSEDEXT}, two addresses supported by most commands
+As a @acronym{GNU} extension, this command accepts two addresses.
+
+@findex a (append text lines) command
+@cindex Appending text after a line
+@cindex Text, appending
+Queue the lines of text which follow this command
+(each but the last ending with a @code{\},
+which are removed from the output)
+to be output at the end of the current cycle,
+or when the next input line is read.
+
+Escape sequences in @var{text} are processed, so you should
+use @code{\\} in @var{text} to print a single backslash.
+
+As a @acronym{GNU} extension, if between the @code{a} and the newline there is
+other than a whitespace-@code{\} sequence, then the text of this line,
+starting at the first non-whitespace character after the @code{a},
+is taken as the first line of the @var{text} block.
+(This enables a simplification in scripting a one-line add.)
+This extension also works with the @code{i} and @code{c} commands.
+
+@item i\
+@itemx @var{text}
+@cindex @value{SSEDEXT}, two addresses supported by most commands
+As a @acronym{GNU} extension, this command accepts two addresses.
+
+@findex i (insert text lines) command
+@cindex Inserting text before a line
+@cindex Text, insertion
+Immediately output the lines of text which follow this command
+(each but the last ending with a @code{\},
+which are removed from the output).
+
+@item c\
+@itemx @var{text}
+@findex c (change to text lines) command
+@cindex Replacing selected lines with other text
+Delete the lines matching the address or address-range,
+and output the lines of text which follow this command
+(each but the last ending with a @code{\},
+which are removed from the output)
+in place of the last line
+(or in place of each line, if no addresses were specified).
+A new cycle is started after this command is done,
+since the pattern space will have been deleted.
+
+@item =
+@cindex @value{SSEDEXT}, two addresses supported by most commands
+As a @acronym{GNU} extension, this command accepts two addresses.
+
+@findex = (print line number) command
+@cindex Printing line number
+@cindex Line number, printing
+Print out the current input line number (with a trailing newline).
+
+@item l @var{n}
+@findex l (list unambiguously) command
+@cindex List pattern space
+@cindex Printing text unambiguously
+@cindex Line length, setting
+@cindex @value{SSEDEXT}, setting line length
+Print the pattern space in an unambiguous form:
+non-printable characters (and the @code{\} character)
+are printed in C-style escaped form; long lines are split,
+with a trailing @code{\} character to indicate the split;
+the end of each line is marked with a @code{$}.
+
+@var{n} specifies the desired line-wrap length;
+a length of 0 (zero) means to never wrap long lines.  If omitted,
+the default as specified on the command line is used.  The @var{n}
+parameter is a @value{SSED} extension.
+
+@item r @var{filename}
+@cindex @value{SSEDEXT}, two addresses supported by most commands
+As a @acronym{GNU} extension, this command accepts two addresses.
+
+@findex r (read file) command
+@cindex Read text from a file
+@cindex @value{SSEDEXT}, @file{/dev/stdin} file
+Queue the contents of @var{filename} to be read and
+inserted into the output stream at the end of the current cycle,
+or when the next input line is read.
+Note that if @var{filename} cannot be read, it is treated as
+if it were an empty file, without any error indication.
+
+As a @value{SSED} extension, the special value @file{/dev/stdin}
+is supported for the file name, which reads the contents of the
+standard input.
+
+@item w @var{filename}
+@findex w (write file) command
+@cindex Write to a file
+@cindex @value{SSEDEXT}, @file{/dev/stdout} file
+@cindex @value{SSEDEXT}, @file{/dev/stderr} file
+Write the pattern space to @var{filename}.
+As a @value{SSED} extension, two special values of @var{file-name} are
+supported: @file{/dev/stderr}, which writes the result to the standard
+error, and @file{/dev/stdout}, which writes to the standard
+output.@footnote{This is equivalent to @code{p} unless the @option{-i}
+option is being used.}
+
+The file will be created (or truncated) before the
+first input line is read; all @code{w} commands
+(including instances of @code{w} flag on successful @code{s} commands)
+which refer to the same @var{filename} are output without
+closing and reopening the file.
+
+@item D
+@findex D (delete first line) command
+@cindex Delete first line from pattern space
+Delete text in the pattern space up to the first newline.
+If any text is left, restart cycle with the resultant
+pattern space (without reading a new line of input),
+otherwise start a normal new cycle.
+
+@item N
+@findex N (append Next line) command
+@cindex Next input line, append to pattern space
+@cindex Append next input line to pattern space
+Add a newline to the pattern space,
+then append the next line of input to the pattern space.
+If there is no more input then @command{sed} exits without processing
+any more commands.
+
+@item P
+@findex P (print first line) command
+@cindex Print first line from pattern space
+Print out the portion of the pattern space up to the first newline.
+
+@item h
+@findex h (hold) command
+@cindex Copy pattern space into hold space
+@cindex Replace hold space with copy of pattern space
+@cindex Hold space, copying pattern space into
+Replace the contents of the hold space with the contents of the pattern space.
+
+@item H
+@findex H (append Hold) command
+@cindex Append pattern space to hold space
+@cindex Hold space, appending from pattern space
+Append a newline to the contents of the hold space,
+and then append the contents of the pattern space to that of the hold space.
+
+@item g
+@findex g (get) command
+@cindex Copy hold space into pattern space
+@cindex Replace pattern space with copy of hold space
+@cindex Hold space, copy into pattern space
+Replace the contents of the pattern space with the contents of the hold space.
+
+@item G
+@findex G (appending Get) command
+@cindex Append hold space to pattern space
+@cindex Hold space, appending to pattern space
+Append a newline to the contents of the pattern space,
+and then append the contents of the hold space to that of the pattern space.
+
+@item x
+@findex x (eXchange) command
+@cindex Exchange hold space with pattern space
+@cindex Hold space, exchange with pattern space
+Exchange the contents of the hold and pattern spaces.
+
+@end table
+
+
+@node Programming Commands
+@section Commands for @command{sed} gurus
+
+In most cases, use of these commands indicates that you are
+probably better off programming in something like @command{awk}
+or Perl.  But occasionally one is committed to sticking
+with @command{sed}, and these commands can enable one to write
+quite convoluted scripts.
+
+@cindex Flow of control in scripts
+@table @code
+@item : @var{label}
+[No addresses allowed.]
+
+@findex : (label) command
+@cindex Labels, in scripts
+Specify the location of @var{label} for branch commands.
+In all other respects, a no-op.
+
+@item b @var{label}
+@findex b (branch) command
+@cindex Branch to a label, unconditionally
+@cindex Goto, in scripts
+Unconditionally branch to @var{label}.
+The @var{label} may be omitted, in which case the next cycle is started.
+
+@item t @var{label}
+@findex t (test and branch if successful) command
+@cindex Branch to a label, if @code{s///} succeeded
+@cindex Conditional branch
+Branch to @var{label} only if there has been a successful @code{s}ubstitution
+since the last input line was read or conditional branch was taken.
+The @var{label} may be omitted, in which case the next cycle is started.
+
+@end table
+
+@node Extended Commands
+@section Commands Specific to @value{SSED}
+
+These commands are specific to @value{SSED}, so you
+must use them with care and only when you are sure that
+hindering portability is not evil.  They allow you to check
+for @value{SSED} extensions or to do tasks that are required
+quite often, yet are unsupported by standard @command{sed}s.
+
+@table @code
+@item e [@var{command}]
+@findex e (evaluate) command
+@cindex Evaluate Bourne-shell commands
+@cindex Subprocesses
+@cindex @value{SSEDEXT}, evaluating Bourne-shell commands
+@cindex @value{SSEDEXT}, subprocesses
+This command allows one to pipe input from a shell command
+into pattern space.  Without parameters, the @code{e} command
+executes the command that is found in pattern space and
+replaces the pattern space with the output; a trailing newline
+is suppressed.
+
+If a parameter is specified, instead, the @code{e} command
+interprets it as a command and sends its output to the output stream
+(like @code{r} does).  The command can run across multiple
+lines, all but the last ending with a back-slash.
+
+In both cases, the results are undefined if the command to be
+executed contains a @sc{nul} character.
+
+@item L @var{n}
+@findex L (fLow paragraphs) command
+@cindex Reformat pattern space
+@cindex Reformatting paragraphs
+@cindex @value{SSEDEXT}, reformatting paragraphs
+@cindex @value{SSEDEXT}, @code{L} command
+This @value{SSED} extension fills and joins lines in pattern space
+to produce output lines of (at most) @var{n} characters, like
+@code{fmt} does; if @var{n} is omitted, the default as specified
+on the command line is used.  This command is considered a failed
+experiment and unless there is enough request (which seems unlikely)
+will be removed in future versions.
+
+@ignore
+Blank lines, spaces between words, and indentation are
+preserved in the output; successive input lines with different
+indentation are not joined; tabs are expanded to 8 columns.
+
+If the pattern space contains multiple lines, they are joined, but
+since the pattern space usually contains a single line, the behavior
+of a simple @code{L;d} script is the same as @samp{fmt -s} (i.e.,
+it does not join short lines to form longer ones).
+
+@var{n} specifies the desired line-wrap length; if omitted,
+the default as specified on the command line is used.
+@end ignore
+
+@item Q [@var{exit-code}]
+This command only accepts a single address.
+
+@findex Q (silent Quit) command
+@cindex @value{SSEDEXT}, quitting silently
+@cindex @value{SSEDEXT}, returning an exit code
+@cindex Quitting
+This command is the same as @code{q}, but will not print the
+contents of pattern space.  Like @code{q}, it provides the
+ability to return an exit code to the caller.
+
+This command can be useful because the only alternative ways
+to accomplish this apparently trivial function are to use
+the @option{-n} option (which can unnecessarily complicate
+your script) or resorting to the following snippet, which
+wastes time by reading the whole file without any visible effect:
+
+@example
+:eat
+$d       @i{Quit silently on the last line}
+N        @i{Read another line, silently}
+g        @i{Overwrite pattern space each time to save memory}
+b eat
+@end example
+
+@item R @var{filename}
+@findex R (read line) command
+@cindex Read text from a file
+@cindex @value{SSEDEXT}, reading a file a line at a time
+@cindex @value{SSEDEXT}, @code{R} command
+@cindex @value{SSEDEXT}, @file{/dev/stdin} file
+Queue a line of @var{filename} to be read and
+inserted into the output stream at the end of the current cycle,
+or when the next input line is read.
+Note that if @var{filename} cannot be read, or if its end is
+reached, no line is appended, without any error indication.
+
+As with the @code{r} command, the special value @file{/dev/stdin}
+is supported for the file name, which reads a line from the
+standard input.
+
+@item T @var{label}
+@findex T (test and branch if failed) command
+@cindex @value{SSEDEXT}, branch if @code{s///} failed
+@cindex Branch to a label, if @code{s///} failed
+@cindex Conditional branch
+Branch to @var{label} only if there have been no successful
+@code{s}ubstitutions since the last input line was read or
+conditional branch was taken. The @var{label} may be omitted,
+in which case the next cycle is started.
+
+@item v @var{version}
+@findex v (version) command
+@cindex @value{SSEDEXT}, checking for their presence
+@cindex Requiring @value{SSED}
+This command does nothing, but makes @command{sed} fail if
+@value{SSED} extensions are not supported, simply because other
+versions of @command{sed} do not implement it.  In addition, you
+can specify the version of @command{sed} that your script
+requires, such as @code{4.0.5}.  The default is @code{4.0}
+because that is the first version that implemented this command.
+
+This command enables all @value{SSEDEXT} even if
+@env{POSIXLY_CORRECT} is set in the environment.
+
+@item W @var{filename}
+@findex W (write first line) command
+@cindex Write first line to a file
+@cindex @value{SSEDEXT}, writing first line to a file
+Write to the given filename the portion of the pattern space up to
+the first newline.  Everything said under the @code{w} command about
+file handling holds here too.
+@end table
+
+@node Escapes
+@section @acronym{GNU} Extensions for Escapes in Regular Expressions
+
+@cindex @acronym{GNU} extensions, special escapes
+Until this chapter, we have only encountered escapes of the form
+@samp{\^}, which tell @command{sed} not to interpret the circumflex
+as a special character, but rather to take it literally.  For
+example, @samp{\*} matches a single asterisk rather than zero
+or more backslashes.
+
+@cindex @code{POSIXLY_CORRECT} behavior, escapes
+This chapter introduces another kind of escape@footnote{All
+the escapes introduced here are @acronym{GNU}
+extensions, with the exception of @code{\n}.  In basic regular
+expression mode, setting @code{POSIXLY_CORRECT} disables them inside
+bracket expressions.}---that
+is, escapes that are applied to a character or sequence of characters
+that ordinarily are taken literally, and that @command{sed} replaces
+with a special character.  This provides a way
+of encoding non-printable characters in patterns in a visible manner.
+There is no restriction on the appearance of non-printing characters
+in a @command{sed} script but when a script is being prepared in the
+shell or by text editing, it is usually easier to use one of
+the following escape sequences than the binary character it
+represents:
+
+The list of these escapes is:
+
+@table @code
+@item \a
+Produces or matches a @sc{bel} character, that is an ``alert'' (@sc{ascii} 7).
+
+@item \f
+Produces or matches a form feed (@sc{ascii} 12).
+
+@item \n
+Produces or matches a newline (@sc{ascii} 10).
+
+@item \r
+Produces or matches a carriage return (@sc{ascii} 13).
+
+@item \t
+Produces or matches a horizontal tab (@sc{ascii} 9).
+
+@item \v
+Produces or matches a so called ``vertical tab'' (@sc{ascii} 11).
+
+@item \c@var{x}
+Produces or matches @kbd{@sc{Control}-@var{x}}, where @var{x} is
+any character.  The precise effect of @samp{\c@var{x}} is as follows:
+if @var{x} is a lower case letter, it is converted to upper case.
+Then bit 6 of the character (hex 40) is inverted.  Thus @samp{\cz} becomes
+hex 1A, but @samp{\c@{} becomes hex 3B, while @samp{\c;} becomes hex 7B.
+
+@item \d@var{xxx}
+Produces or matches a character whose decimal @sc{ascii} value is @var{xxx}.
+
+@item \o@var{xxx}
+@ifset PERL
+@item \@var{xxx}
+@end ifset
+Produces or matches a character whose octal @sc{ascii} value is @var{xxx}.
+@ifset PERL
+The syntax without the @code{o} is active in Perl mode, while the one
+with the @code{o} is active in the normal or extended @sc{posix} regular
+expression modes.
+@end ifset
+
+@item \x@var{xx}
+Produces or matches a character whose hexadecimal @sc{ascii} value is @var{xx}.
+@end table
+
+@samp{\b} (backspace) was omitted because of the conflict with
+the existing ``word boundary'' meaning.
+
+Other escapes match a particular character class and are valid only in
+regular expressions:
+
+@table @code
+@item \w
+Matches any ``word'' character.  A ``word'' character is any
+letter or digit or the underscore character.
+
+@item \W
+Matches any ``non-word'' character.
+
+@item \b
+Matches a word boundary; that is it matches if the character
+to the left is a ``word'' character and the character to the
+right is a ``non-word'' character, or vice-versa.
+
+@item \B
+Matches everywhere but on a word boundary; that is it matches
+if the character to the left and the character to the right
+are either both ``word'' characters or both ``non-word''
+characters.
+
+@item \`
+Matches only at the start of pattern space.  This is different
+from @code{^} in multi-line mode.
+
+@item \'
+Matches only at the end of pattern space.  This is different
+from @code{$} in multi-line mode.
+
+@ifset PERL
+@item \G
+Match only at the start of pattern space or, when doing a global
+substitution using the @code{s///g} command and option, at
+the end-of-match position of the prior match.  For example,
+@samp{s/\Ga/Z/g} will change an initial run of @code{a}s to
+a run of @code{Z}s
+@end ifset
+@end table
+
+@node Examples
+@chapter Some Sample Scripts
+
+Here are some @command{sed} scripts to guide you in the art of mastering
+@command{sed}.
+
+@menu
+Some exotic examples:
+* Centering lines::
+* Increment a number::
+* Rename files to lower case::
+* Print bash environment::
+* Reverse chars of lines::
+
+Emulating standard utilities:
+* tac::                             Reverse lines of files
+* cat -n::                          Numbering lines
+* cat -b::                          Numbering non-blank lines
+* wc -c::                           Counting chars
+* wc -w::                           Counting words
+* wc -l::                           Counting lines
+* head::                            Printing the first lines
+* tail::                            Printing the last lines
+* uniq::                            Make duplicate lines unique
+* uniq -d::                         Print duplicated lines of input
+* uniq -u::                         Remove all duplicated lines
+* cat -s::                          Squeezing blank lines
+@end menu
+
+@node Centering lines
+@section Centering Lines
+
+This script centers all lines of a file on a 80 columns width.
+To change that width, the number in @code{\@{@dots{}\@}} must be
+replaced, and the number of added spaces also must be changed.
+
+Note how the buffer commands are used to separate parts in
+the regular expressions to be matched---this is a common
+technique.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+@group
+# Put 80 spaces in the buffer
+1 @{
+  x
+  s/^$/          /
+  s/^.*$/&&&&&&&&/
+  x
+@}
+@end group
+
+@group
+# del leading and trailing spaces
+y/@kbd{tab}/ /
+s/^ *//
+s/ *$//
+@end group
+
+@group
+# add a newline and 80 spaces to end of line
+G
+@end group
+
+@group
+# keep first 81 chars (80 + a newline)
+s/^\(.\@{81\@}\).*$/\1/
+@end group
+
+@group
+# \2 matches half of the spaces, which are moved to the beginning
+s/^\(.*\)\n\(.*\)\2/\2\1/
+@end group
+@end example
+@c end---------------------------------------------
+
+@node Increment a number
+@section Increment a Number
+
+This script is one of a few that demonstrate how to do arithmetic
+in @command{sed}.  This is indeed possible,@footnote{@command{sed} guru Greg
+Ubben wrote an implementation of the @command{dc} @sc{rpn} calculator!
+It is distributed together with sed.} but must be done manually.
+
+To increment one number you just add 1 to last digit, replacing
+it by the following digit.  There is one exception: when the digit
+is a nine the previous digits must be also incremented until you
+don't have a nine.
+
+This solution by Bruno Haible is very clever and smart because
+it uses a single buffer; if you don't have this limitation, the
+algorithm used in @ref{cat -n, Numbering lines}, is faster.
+It works by replacing trailing nines with an underscore, then
+using multiple @code{s} commands to increment the last digit,
+and then again substituting underscores with zeros.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+/[^0-9]/ d
+
+@group
+# replace all leading 9s by _ (any other character except digits, could
+# be used)
+:d
+s/9\(_*\)$/_\1/
+td
+@end group
+
+@group
+# incr last digit only.  The first line adds a most-significant
+# digit of 1 if we have to add a digit.
+#
+# The @code{tn} commands are not necessary, but make the thing
+# faster
+@end group
+
+@group
+s/^\(_*\)$/1\1/; tn
+s/8\(_*\)$/9\1/; tn
+s/7\(_*\)$/8\1/; tn
+s/6\(_*\)$/7\1/; tn
+s/5\(_*\)$/6\1/; tn
+s/4\(_*\)$/5\1/; tn
+s/3\(_*\)$/4\1/; tn
+s/2\(_*\)$/3\1/; tn
+s/1\(_*\)$/2\1/; tn
+s/0\(_*\)$/1\1/; tn
+@end group
+
+@group
+:n
+y/_/0/
+@end group
+@end example
+@c end---------------------------------------------
+
+@node Rename files to lower case
+@section Rename Files to Lower Case
+
+This is a pretty strange use of @command{sed}.  We transform text, and
+transform it to be shell commands, then just feed them to shell.
+Don't worry, even worse hacks are done when using @command{sed}; I have
+seen a script converting the output of @command{date} into a @command{bc}
+program!
+ 
+The main body of this is the @command{sed} script, which remaps the name
+from lower to upper (or vice-versa) and even checks out 
+if the remapped name is the same as the original name.
+Note how the script is parameterized using shell
+variables and proper quoting.
+
+@c start-------------------------------------------
+@example
+@group
+#! /bin/sh
+# rename files to lower/upper case... 
+#
+# usage: 
+#    move-to-lower * 
+#    move-to-upper * 
+# or
+#    move-to-lower -R .
+#    move-to-upper -R .
+#
+@end group
+
+@group
+help()
+@{
+	cat << eof
+Usage: $0 [-n] [-r] [-h] files...
+@end group
+
+@group
+-n      do nothing, only see what would be done
+-R      recursive (use find)
+-h      this message
+files   files to remap to lower case
+@end group
+
+@group
+Examples:
+       $0 -n *        (see if everything is ok, then...)
+       $0 *
+@end group
+
+       $0 -R .
+
+@group
+eof
+@}
+@end group
+
+@group
+apply_cmd='sh'
+finder='echo "$@@" | tr " " "\n"'
+files_only=
+@end group
+
+@group
+while :
+do
+    case "$1" in 
+        -n) apply_cmd='cat' ;;
+        -R) finder='find "$@@" -type f';;
+        -h) help ; exit 1 ;;
+        *) break ;;
+    esac
+    shift
+done
+@end group
+
+@group
+if [ -z "$1" ]; then
+        echo Usage: $0 [-h] [-n] [-r] files...
+        exit 1
+fi
+@end group
+
+@group
+LOWER='abcdefghijklmnopqrstuvwxyz'
+UPPER='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+@end group
+
+@group
+case `basename $0` in
+        *upper*) TO=$UPPER; FROM=$LOWER ;;
+        *)       FROM=$UPPER; TO=$LOWER ;;
+esac
+@end group
+	
+eval $finder | sed -n '
+
+@group
+# remove all trailing slashes
+s/\/*$//
+@end group
+
+@group
+# add ./ if there is no path, only a filename
+/\//! s/^/.\//
+@end group
+
+@group
+# save path+filename
+h
+@end group
+
+@group
+# remove path
+s/.*\///
+@end group
+
+@group
+# do conversion only on filename
+y/'$FROM'/'$TO'/
+@end group
+
+@group
+# now line contains original path+file, while
+# hold space contains the new filename
+x
+@end group
+
+@group
+# add converted file name to line, which now contains
+# path/file-name\nconverted-file-name
+G
+@end group
+
+@group
+# check if converted file name is equal to original file name,
+# if it is, do not print nothing
+/^.*\/\(.*\)\n\1/b
+@end group
+
+@group
+# now, transform path/fromfile\n, into
+# mv path/fromfile path/tofile and print it
+s/^\(.*\/\)\(.*\)\n\(.*\)$/mv "\1\2" "\1\3"/p
+@end group
+
+' | $apply_cmd
+@end example
+@c end---------------------------------------------
+
+@node Print bash environment
+@section Print @command{bash} Environment
+
+This script strips the definition of the shell functions
+from the output of the @command{set} Bourne-shell command.
+
+@c start-------------------------------------------
+@example
+#!/bin/sh
+
+@group
+set | sed -n '
+:x
+@end group
+
+@group
+@ifinfo
+# if no occurrence of "=()" print and load next line
+@end ifinfo
+@ifnotinfo
+# if no occurrence of @samp{=()} print and load next line
+@end ifnotinfo
+/=()/! @{ p; b; @}
+/ () $/! @{ p; b; @}
+@end group
+
+@group
+# possible start of functions section
+# save the line in case this is a var like FOO="() "
+h
+@end group
+
+@group
+# if the next line has a brace, we quit because
+# nothing comes after functions
+n
+/^@{/ q
+@end group
+
+@group
+# print the old line
+x; p
+@end group
+
+@group
+# work on the new line now
+x; bx
+'
+@end group
+@end example
+@c end---------------------------------------------
+
+@node Reverse chars of lines
+@section Reverse Characters of Lines
+
+This script can be used to reverse the position of characters
+in lines.  The technique moves two characters at a time, hence
+it is faster than more intuitive implementations.
+
+Note the @code{tx} command before the definition of the label.
+This is often needed to reset the flag that is tested by
+the @code{t} command.
+
+Imaginative readers will find uses for this script.  An example
+is reversing the output of @command{banner}.@footnote{This requires
+another script to pad the output of banner; for example
+
+@example
+#! /bin/sh
+
+banner -w $1 $2 $3 $4 |
+  sed -e :a -e '/^.\@{0,'$1'\@}$/ @{ s/$/ /; ba; @}' |
+  ~/sedscripts/reverseline.sed
+@end example
+}
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+/../! b
+
+@group
+# Reverse a line.  Begin embedding the line between two newlines
+s/^.*$/\
+&\
+/
+@end group
+
+@group
+# Move first character at the end.  The regexp matches until
+# there are zero or one characters between the markers
+tx
+:x
+s/\(\n.\)\(.*\)\(.\n\)/\3\2\1/
+tx
+@end group
+
+@group
+# Remove the newline markers
+s/\n//g
+@end group
+@end example
+@c end---------------------------------------------
+
+@node tac
+@section Reverse Lines of Files
+
+This one begins a series of totally useless (yet interesting)
+scripts emulating various Unix commands.  This, in particular,
+is a @command{tac} workalike.
+
+Note that on implementations other than @acronym{GNU} @command{sed}
+@ifset PERL
+and @value{SSED}
+@end ifset
+this script might easily overflow internal buffers.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+# reverse all lines of input, i.e. first line became last, ...
+
+@group
+# from the second line, the buffer (which contains all previous lines)
+# is *appended* to current line, so, the order will be reversed
+1! G
+@end group
+
+@group
+# on the last line we're done -- print everything
+$ p
+@end group
+
+@group
+# store everything on the buffer again
+h
+@end group
+@end example
+@c end---------------------------------------------
+
+@node cat -n
+@section Numbering Lines
+
+This script replaces @samp{cat -n}; in fact it formats its output
+exactly like @acronym{GNU} @command{cat} does.
+
+Of course this is completely useless and for two reasons:  first,
+because somebody else did it in C, second, because the following
+Bourne-shell script could be used for the same purpose and would
+be much faster:
+
+@c start-------------------------------------------
+@example
+@group
+#! /bin/sh
+sed -e "=" $@@ | sed -e '
+  s/^/      /
+  N
+  s/^ *\(......\)\n/\1  /
+'
+@end group
+@end example
+@c end---------------------------------------------
+
+It uses @command{sed} to print the line number, then groups lines two
+by two using @code{N}.  Of course, this script does not teach as much as
+the one presented below.
+
+The algorithm used for incrementing uses both buffers, so the line
+is printed as soon as possible and then discarded.  The number
+is split so that changing digits go in a buffer and unchanged ones go
+in the other; the changed digits are modified in a single step
+(using a @code{y} command).  The line number for the next line
+is then composed and stored in the hold space, to be used in the
+next iteration.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+@group
+# Prime the pump on the first line
+x
+/^$/ s/^.*$/1/
+@end group
+
+@group
+# Add the correct line number before the pattern
+G
+h
+@end group
+
+@group
+# Format it and print it
+s/^/      /
+s/^ *\(......\)\n/\1  /p
+@end group
+
+@group
+# Get the line number from hold space; add a zero
+# if we're going to add a digit on the next line
+g
+s/\n.*$//
+/^9*$/ s/^/0/
+@end group
+
+@group
+# separate changing/unchanged digits with an x
+s/.9*$/x&/
+@end group
+
+@group
+# keep changing digits in hold space
+h
+s/^.*x//
+y/0123456789/1234567890/
+x
+@end group
+
+@group
+# keep unchanged digits in pattern space
+s/x.*$//
+@end group
+
+@group
+# compose the new number, remove the newline implicitly added by G
+G
+s/\n//
+h
+@end group
+@end example
+@c end---------------------------------------------
+
+@node cat -b
+@section Numbering Non-blank Lines
+
+Emulating @samp{cat -b} is almost the same as @samp{cat -n}---we only
+have to select which lines are to be numbered and which are not.
+
+The part that is common to this script and the previous one is
+not commented to show how important it is to comment @command{sed}
+scripts properly...
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+@group
+/^$/ @{
+  p
+  b
+@}
+@end group
+
+@group
+# Same as cat -n from now
+x
+/^$/ s/^.*$/1/
+G
+h
+s/^/      /
+s/^ *\(......\)\n/\1  /p
+x
+s/\n.*$//
+/^9*$/ s/^/0/
+s/.9*$/x&/
+h
+s/^.*x//
+y/0123456789/1234567890/
+x
+s/x.*$//
+G
+s/\n//
+h
+@end group
+@end example
+@c end---------------------------------------------
+
+@node wc -c
+@section Counting Characters
+
+This script shows another way to do arithmetic with @command{sed}.
+In this case we have to add possibly large numbers, so implementing
+this by successive increments would not be feasible (and possibly
+even more complicated to contrive than this script).
+
+The approach is to map numbers to letters, kind of an abacus
+implemented with @command{sed}.  @samp{a}s are units, @samp{b}s are
+tens and so on: we simply add the number of characters
+on the current line as units, and then propagate the carry
+to tens, hundreds, and so on.
+
+As usual, running totals are kept in hold space.
+
+On the last line, we convert the abacus form back to decimal.
+For the sake of variety, this is done with a loop rather than
+with some 80 @code{s} commands@footnote{Some implementations
+have a limit of 199 commands per script}: first we
+convert units, removing @samp{a}s from the number; then we
+rotate letters so that tens become @samp{a}s, and so on
+until no more letters remain.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+@group
+# Add n+1 a's to hold space (+1 is for the newline)
+s/./a/g
+H
+x
+s/\n/a/
+@end group
+
+@group
+# Do the carry.  The t's and b's are not necessary,
+# but they do speed up the thing
+t a
+: a;  s/aaaaaaaaaa/b/g; t b; b done
+: b;  s/bbbbbbbbbb/c/g; t c; b done
+: c;  s/cccccccccc/d/g; t d; b done
+: d;  s/dddddddddd/e/g; t e; b done
+: e;  s/eeeeeeeeee/f/g; t f; b done
+: f;  s/ffffffffff/g/g; t g; b done
+: g;  s/gggggggggg/h/g; t h; b done
+: h;  s/hhhhhhhhhh//g
+@end group
+
+@group
+: done
+$! @{
+  h
+  b
+@}
+@end group
+
+# On the last line, convert back to decimal
+
+@group
+: loop
+/a/! s/[b-h]*/&0/
+s/aaaaaaaaa/9/
+s/aaaaaaaa/8/
+s/aaaaaaa/7/
+s/aaaaaa/6/
+s/aaaaa/5/
+s/aaaa/4/
+s/aaa/3/
+s/aa/2/
+s/a/1/
+@end group
+
+@group
+: next
+y/bcdefgh/abcdefg/
+/[a-h]/ b loop
+p
+@end group
+@end example
+@c end---------------------------------------------
+
+@node wc -w
+@section Counting Words
+
+This script is almost the same as the previous one, once each
+of the words on the line is converted to a single @samp{a}
+(in the previous script each letter was changed to an @samp{a}).
+
+It is interesting that real @command{wc} programs have optimized
+loops for @samp{wc -c}, so they are much slower at counting
+words rather than characters.  This script's bottleneck,
+instead, is arithmetic, and hence the word-counting one
+is faster (it has to manage smaller numbers).
+
+Again, the common parts are not commented to show the importance
+of commenting @command{sed} scripts.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+@group
+# Convert words to a's
+s/[ @kbd{tab}][ @kbd{tab}]*/ /g
+s/^/ /
+s/ [^ ][^ ]*/a /g
+s/ //g
+@end group
+
+@group
+# Append them to hold space
+H
+x
+s/\n//
+@end group
+
+@group
+# From here on it is the same as in wc -c.
+/aaaaaaaaaa/! bx;   s/aaaaaaaaaa/b/g
+/bbbbbbbbbb/! bx;   s/bbbbbbbbbb/c/g
+/cccccccccc/! bx;   s/cccccccccc/d/g
+/dddddddddd/! bx;   s/dddddddddd/e/g
+/eeeeeeeeee/! bx;   s/eeeeeeeeee/f/g
+/ffffffffff/! bx;   s/ffffffffff/g/g
+/gggggggggg/! bx;   s/gggggggggg/h/g
+s/hhhhhhhhhh//g
+:x
+$! @{ h; b; @}
+:y
+/a/! s/[b-h]*/&0/
+s/aaaaaaaaa/9/
+s/aaaaaaaa/8/
+s/aaaaaaa/7/
+s/aaaaaa/6/
+s/aaaaa/5/
+s/aaaa/4/
+s/aaa/3/
+s/aa/2/
+s/a/1/
+y/bcdefgh/abcdefg/
+/[a-h]/ by
+p
+@end group
+@end example
+@c end---------------------------------------------
+
+@node wc -l
+@section Counting Lines
+
+No strange things are done now, because @command{sed} gives us
+@samp{wc -l} functionality for free!!! Look:
+
+@c start-------------------------------------------
+@example
+@group
+#!/usr/bin/sed -nf
+$=
+@end group
+@end example
+@c end---------------------------------------------
+
+@node head
+@section Printing the First Lines
+
+This script is probably the simplest useful @command{sed} script.
+It displays the first 10 lines of input; the number of displayed
+lines is right before the @code{q} command.
+
+@c start-------------------------------------------
+@example
+@group
+#!/usr/bin/sed -f
+10q
+@end group
+@end example
+@c end---------------------------------------------
+
+@node tail
+@section Printing the Last Lines
+
+Printing the last @var{n} lines rather than the first is more complex
+but indeed possible.  @var{n} is encoded in the second line, before
+the bang character.
+
+This script is similar to the @command{tac} script in that it keeps the
+final output in the hold space and prints it at the end:
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+@group
+1! @{; H; g; @}
+1,10 !s/[^\n]*\n//
+$p
+h
+@end group
+@end example
+@c end---------------------------------------------
+
+Mainly, the scripts keeps a window of 10 lines and slides it
+by adding a line and deleting the oldest (the substitution command
+on the second line works like a @code{D} command but does not
+restart the loop).
+
+The ``sliding window'' technique is a very powerful way to write
+efficient and complex @command{sed} scripts, because commands like
+@code{P} would require a lot of work if implemented manually.
+
+To introduce the technique, which is fully demonstrated in the
+rest of this chapter and is based on the @code{N}, @code{P}
+and @code{D} commands, here is an implementation of @command{tail}
+using a simple ``sliding window.''
+
+This looks complicated but in fact the working is the same as
+the last script: after we have kicked in the appropriate number
+of lines, however, we stop using the hold space to keep inter-line
+state, and instead use @code{N} and @code{D} to slide pattern
+space by one line:
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+@group
+1h
+2,10 @{; H; g; @}
+$q
+1,9d
+N
+D
+@end group
+@end example
+@c end---------------------------------------------
+
+Note how the first, second and fourth line are inactive after
+the first ten lines of input.  After that, all the script does
+is: exiting on the last line of input, appending the next input
+line to pattern space, and removing the first line.
+
+@node uniq
+@section Make Duplicate Lines Unique
+
+This is an example of the art of using the @code{N}, @code{P}
+and @code{D} commands, probably the most difficult to master.
+
+@c start-------------------------------------------
+@example
+@group
+#!/usr/bin/sed -f
+h
+@end group
+
+@group
+:b
+# On the last line, print and exit
+$b
+N
+/^\(.*\)\n\1$/ @{
+    # The two lines are identical.  Undo the effect of
+    # the n command.
+    g
+    bb
+@}
+@end group
+
+@group
+# If the @code{N} command had added the last line, print and exit
+$b
+@end group
+
+@group
+# The lines are different; print the first and go
+# back working on the second.
+P
+D
+@end group
+@end example
+@c end---------------------------------------------
+
+As you can see, we mantain a 2-line window using @code{P} and @code{D}.
+This technique is often used in advanced @command{sed} scripts.
+
+@node uniq -d
+@section Print Duplicated Lines of Input
+
+This script prints only duplicated lines, like @samp{uniq -d}.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+@group
+$b
+N
+/^\(.*\)\n\1$/ @{
+    # Print the first of the duplicated lines
+    s/.*\n//
+    p
+@end group
+
+@group
+    # Loop until we get a different line
+    :b
+    $b
+    N
+    /^\(.*\)\n\1$/ @{
+        s/.*\n//
+        bb
+    @}
+@}
+@end group
+
+@group
+# The last line cannot be followed by duplicates
+$b
+@end group
+
+@group
+# Found a different one.  Leave it alone in the pattern space
+# and go back to the top, hunting its duplicates
+D
+@end group
+@end example
+@c end---------------------------------------------
+
+@node uniq -u
+@section Remove All Duplicated Lines
+
+This script prints only unique lines, like @samp{uniq -u}.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+@group
+# Search for a duplicate line --- until that, print what you find.
+$b
+N
+/^\(.*\)\n\1$/ ! @{
+    P
+    D
+@}
+@end group
+
+@group
+:c
+# Got two equal lines in pattern space.  At the
+# end of the file we simply exit
+$d
+@end group
+
+@group
+# Else, we keep reading lines with @code{N} until we
+# find a different one
+s/.*\n//
+N
+/^\(.*\)\n\1$/ @{
+    bc
+@}
+@end group
+
+@group
+# Remove the last instance of the duplicate line
+# and go back to the top
+D
+@end group
+@end example
+@c end---------------------------------------------
+
+@node cat -s
+@section Squeezing Blank Lines
+
+As a final example, here are three scripts, of increasing complexity
+and speed, that implement the same function as @samp{cat -s}, that is
+squeezing blank lines.
+
+The first leaves a blank line at the beginning and end if there are
+some already.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+@group
+# on empty lines, join with next
+# Note there is a star in the regexp
+:x
+/^\n*$/ @{
+N
+bx
+@}
+@end group
+
+@group
+# now, squeeze all '\n', this can be also done by:
+# s/^\(\n\)*/\1/
+s/\n*/\
+/
+@end group
+@end example
+@c end---------------------------------------------
+
+This one is a bit more complex and removes all empty lines
+at the beginning.  It does leave a single blank line at end
+if one was there.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -f
+
+@group
+# delete all leading empty lines
+1,/^./@{
+/./!d
+@}
+@end group
+
+@group
+# on an empty line we remove it and all the following
+# empty lines, but one
+:x
+/./!@{
+N
+s/^\n$//
+tx
+@}
+@end group
+@end example
+@c end---------------------------------------------
+
+This removes leading and trailing blank lines.  It is also the
+fastest.  Note that loops are completely done with @code{n} and
+@code{b}, without relying on @command{sed} to restart the
+the script automatically at the end of a line.
+
+@c start-------------------------------------------
+@example
+#!/usr/bin/sed -nf
+
+@group
+# delete all (leading) blanks
+/./!d
+@end group
+
+@group
+# get here: so there is a non empty
+:x
+# print it
+p
+# get next
+n
+# got chars? print it again, etc... 
+/./bx
+@end group
+
+@group
+# no, don't have chars: got an empty line
+:z
+# get next, if last line we finish here so no trailing
+# empty lines are written
+n
+# also empty? then ignore it, and get next... this will
+# remove ALL empty lines
+/./!bz
+@end group
+
+@group
+# all empty lines were deleted/ignored, but we have a non empty.  As
+# what we want to do is to squeeze, insert a blank line artificially
+i\
+@end group
+
+bx
+@end example
+@c end---------------------------------------------
+
+@node Limitations
+@chapter @value{SSED}'s Limitations and Non-limitations
+
+@cindex @acronym{GNU} extensions, unlimited line length
+@cindex Portability, line length limitations
+For those who want to write portable @command{sed} scripts,
+be aware that some implementations have been known to
+limit line lengths (for the pattern and hold spaces)
+to be no more than 4000 bytes.
+The @sc{posix} standard specifies that conforming @command{sed}
+implementations shall support at least 8192 byte line lengths.
+@value{SSED} has no built-in limit on line length;
+as long as it can @code{malloc()} more (virtual) memory,
+you can feed or construct lines as long as you like.
+
+However, recursion is used to handle subpatterns and indefinite
+repetition.  This means that the available stack space may limit
+the size of the buffer that can be processed by certain patterns.
+
+@ifset PERL
+There are some size limitations in the regular expression
+matcher but it is hoped that they will never in practice
+be relevant.  The maximum length of a compiled pattern
+is 65539 (sic) bytes.  All values in repeating quantifiers
+must be less than 65536.  The maximum nesting depth of
+all parenthesized subpatterns, including capturing and
+non-capturing subpatterns@footnote{The
+distinction is meaningful when referring to Perl-style
+regular expressions.}, assertions, and other types of
+subpattern, is 200.
+
+Also, @value{SSED} recognizes the @sc{posix} syntax
+@code{[.@var{ch}.]} and @code{[=@var{ch}=]}
+where @var{ch} is a ``collating element'', but these
+are not supported, and an error is given if they are
+encountered.
+
+Here are a few distinctions between the real Perl-style
+regular expressions and those that @option{-R} recognizes.
+
+@enumerate
+@item
+Lookahead assertions do not allow repeat quantifiers after them
+Perl permits them, but they do not mean what you
+might think. For example, @samp{(?!a)@{3@}} does not assert that the
+next three characters are not @samp{a}. It just asserts three times that the
+next character is not @samp{a} --- a waste of time and nothing else.
+
+@item
+Capturing subpatterns that occur inside  negative  lookahead
+head  assertions  are  counted,  but  their  entries are counted
+as empty in the second half of an @code{s} command.
+Perl sets its numerical variables from any such patterns
+that are matched before the assertion fails to match
+something (thereby succeeding), but only if the negative
+lookahead assertion contains just one branch.
+
+@item
+The following Perl escape sequences are not supported:
+@samp{\l}, @samp{\u}, @samp{\L}, @samp{\U}, @samp{\E},
+@samp{\Q}. In fact these are implemented by Perl's general
+string-handling and are not part of its pattern matching engine.
+
+@item
+The Perl @samp{\G} assertion is not supported as it is not
+relevant to single pattern matches.
+
+@item
+Fairly obviously, @value{SSED} does not support the @samp{(?@{code@})}
+and @samp{(?p@{code@})} constructions. However, there is some experimental
+support for recursive patterns using the non-Perl item @samp{(?R)}.
+
+@item
+There are at the time of writing some oddities in Perl
+5.005_02 concerned with the settings of captured strings
+when part of a pattern is repeated. For example, matching
+@samp{aba} against the pattern @samp{/^(a(b)?)+$/} sets
+@samp{$2}@footnote{@samp{$2} would be @samp{\2} in @value{SSED}.}
+to the value @samp{b}, but matching @samp{aabbaa}
+against @samp{/^(aa(bb)?)+$/} leaves @samp{$2}
+unset.  However, if the pattern is changed to
+@samp{/^(aa(b(b))?)+$/} then @samp{$2} (and @samp{$3}) are set.
+In Perl 5.004 @samp{$2} is set in both cases, and that is also
+true of @value{SSED}.
+
+@item
+Another as yet unresolved discrepancy is that in Perl
+5.005_02 the pattern @samp{/^(a)?(?(1)a|b)+$/} matches
+the string @samp{a}, whereas in @value{SSED} it does not.
+However, in both Perl and @value{SSED} @samp{/^(a)?a/} matched
+against @samp{a} leaves $1 unset.
+@end enumerate
+@end ifset
+
+@node Other Resources
+@chapter Other Resources for Learning About @command{sed}
+
+@cindex Additional reading about @command{sed}
+In addition to several books that have been written about @command{sed}
+(either specifically or as chapters in books which discuss
+shell programming), one can find out more about @command{sed}
+(including suggestions of a few books) from the FAQ
+for the @code{sed-users} mailing list, available from any of:
+@display
+ @uref{http://www.student.northpark.edu/pemente/sed/sedfaq.html}
+ @uref{http://sed.sf.net/grabbag/tutorials/sedfaq.html}
+@end display
+
+Also of interest are
+@uref{http://www.student.northpark.edu/pemente/sed/index.htm}
+and @uref{http://sed.sf.net/grabbag},
+which include @command{sed} tutorials and other @command{sed}-related goodies.
+
+The @code{sed-users} mailing list itself maintained by Sven Guckes.
+To subscribe, visit @uref{http://groups.yahoo.com} and search
+for the @code{sed-users} mailing list.
+
+@node Reporting Bugs
+@chapter Reporting Bugs
+
+@cindex Bugs, reporting
+Email bug reports to @email{bonzini@@gnu.org}.
+Be sure to include the word ``sed'' somewhere in the @code{Subject:} field.
+Also, please include the output of @samp{sed --version} in the body
+of your report if at all possible.
+
+Please do not send a bug report like this:
+
+@example
+@i{while building frobme-1.3.4}
+$ configure 
+@error{} sed: file sedscr line 1: Unknown option to 's'
+@end example
+
+If @value{SSED} doesn't configure your favorite package, take a
+few extra minutes to identify the specific problem and make a stand-alone
+test case.  Unlike other programs such as C compilers, making such test
+cases for @command{sed} is quite simple.
+
+A stand-alone test case includes all the data necessary to perform the
+test, and the specific invocation of @command{sed} that causes the problem.
+The smaller a stand-alone test case is, the better.  A test case should
+not involve something as far removed from @command{sed} as ``try to configure
+frobme-1.3.4''.  Yes, that is in principle enough information to look
+for the bug, but that is not a very practical prospect.
+
+Here are a few commonly reported bugs that are not bugs.
+
+@table @asis
+@item @code{N} command on the last line
+@cindex Portability, @code{N} command on the last line
+@cindex Non-bugs, @code{N} command on the last line
+
+Most versions of @command{sed} exit without printing anything when
+the @command{N} command is issued on the last line of a file.
+@value{SSED} prints pattern space before exiting unless of course
+the @command{-n} command switch has been specified.  This choice is
+by design.
+
+For example, the behavior of
+@example
+sed N foo bar
+@end example
+@noindent
+would depend on whether foo has an even or an odd number of
+lines@footnote{which is the actual ``bug'' that prompted the
+change in behavior}.  Or, when writing a script to read the
+next few lines following a pattern match, traditional
+implementations of @code{sed} would force you to write
+something like
+@example
+/foo/@{ $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N; $!N @}
+@end example
+@noindent
+instead of just
+@example
+/foo/@{ N;N;N;N;N;N;N;N;N; @}
+@end example
+ 
+@cindex @code{POSIXLY_CORRECT} behavior, @code{N} command
+In any case, the simplest workaround is to use @code{$d;N} in
+scripts that rely on the traditional behavior, or to set
+the @code{POSIXLY_CORRECT} variable to a non-empty value.
+
+@item Regex syntax clashes (problems with backslashes)
+@cindex @acronym{GNU} extensions, to basic regular expressions
+@cindex Non-bugs, regex syntax clashes
+@command{sed} uses the @sc{posix} basic regular expression syntax.  According to
+the standard, the meaning of some escape sequences is undefined in
+this syntax;  notable in the case of @command{sed} are @code{\|},
+@code{\+}, @code{\?}, @code{\`}, @code{\'}, @code{\<},
+@code{\>}, @code{\b}, @code{\B}, @code{\w}, and @code{\W}.
+
+As in all @acronym{GNU} programs that use @sc{posix} basic regular
+expressions, @command{sed} interprets these escape sequences as special
+characters.  So, @code{x\+} matches one or more occurrences of @samp{x}.
+@code{abc\|def} matches either @samp{abc} or @samp{def}.
+
+This syntax may cause problems when running scripts written for other
+@command{sed}s.  Some @command{sed} programs have been written with the
+assumption that @code{\|} and @code{\+} match the literal characters
+@code{|} and @code{+}.  Such scripts must be modified by removing the
+spurious backslashes if they are to be used with modern implementations
+of @command{sed}, like
+@ifset PERL
+@value{SSED} or
+@end ifset
+@acronym{GNU} @command{sed}.
+
+On the other hand, some scripts use s|abc\|def||g to remove occurrences
+of @emph{either} @code{abc} or @code{def}.  While this worked until
+@command{sed} 4.0.x, newer versions interpret this as removing the
+string @code{abc|def}.  This is again undefined behavior according to
+@acronym{POSIX}, and this interpretation is arguably more robust: older
+@command{sed}s, for example, required that the regex matcher parsed
+@code{\/} as @code{/} in the common case of escaping a slash, which is
+again undefined behavior; the new behavior avoids this, and this is good
+because the regex matcher is only partially under our control.
+
+@cindex @acronym{GNU} extensions, special escapes
+In addition, this version of @command{sed} supports several escape characters
+(some of which are multi-character) to insert non-printable characters
+in scripts (@code{\a}, @code{\c}, @code{\d}, @code{\o}, @code{\r},
+@code{\t}, @code{\v}, @code{\x}).  These can cause similar problems
+with scripts written for other @command{sed}s.
+
+@item @option{-i} clobbers read-only files
+@cindex In-place editing
+@cindex @value{SSEDEXT}, in-place editing
+@cindex Non-bugs, in-place editing
+
+In short, @samp{sed -i} will let you delete the contents of
+a read-only file, and in general the @option{-i} option
+(@pxref{Invoking sed, , Invocation}) lets you clobber
+protected files.  This is not a bug, but rather a consequence
+of how the Unix filesystem works.
+
+The permissions on a file say what can happen to the data
+in that file, while the permissions on a directory say what can
+happen to the list of files in that directory.  @samp{sed -i}
+will not ever open for writing  a file that is already on disk.
+Rather, it will work on a temporary file that is finally renamed
+to the original name: if you rename or delete files, you're actually
+modifying the contents of the directory, so the operation depends on
+the permissions of the directory, not of the file.  For this same
+reason, @command{sed} does not let you use @option{-i} on a writeable file
+in a read-only directory (but unbelievably nobody reports that as a
+bug@dots{}).
+
+@item @code{0a} does not work (gives an error)
+There is no line 0.  0 is a special address that is only used to treat
+addresses like @code{0,/@var{RE}/} as active when the script starts: if
+you write @code{1,/abc/d} and the first line includes the word @samp{abc},
+then that match would be ignored because address ranges must span at least
+two lines (barring the end of the file); but what you probably wanted is
+to delete every line up to the first one including @samp{abc}, and this
+is obtained with @code{0,/abc/d}.
+
+@ifclear PERL
+@item @code{[a-z]} is case insensitive
+You are encountering problems with locales.  POSIX mandates that @code{[a-z]}
+uses the current locale's collation order -- in C parlance, that means using
+@code{strcoll(3)} instead of @code{strcmp(3)}.  Some locales have a
+case-insensitive collation order, others don't: one of those that have
+problems is Estonian.
+
+Another problem is that @code{[a-z]} tries to use collation symbols.
+This only happens if you are on the @acronym{GNU} system, using
+@acronym{GNU} libc's regular expression matcher instead of compiling the
+one supplied with @acronym{GNU} sed.  In a Danish locale, for example,
+the regular expression @code{^[a-z]$} matches the string @samp{aa},
+because this is a single collating symbol that comes after @samp{a}
+and before @samp{b}; @samp{ll} behaves similarly in Spanish
+locales, or @samp{ij} in Dutch locales.
+
+To work around these problems, which may cause bugs in shell scripts, set
+the @env{LC_COLLATE} and @env{LC_CTYPE} environment variables to @samp{C}.
+@end ifclear
+@end table
+
+
+@node Extended regexps
+@appendix Extended regular expressions
+@cindex Extended regular expressions, syntax
+
+The only difference between basic and extended regular expressions is in
+the behavior of a few characters: @samp{?}, @samp{+}, parentheses,
+and braces (@samp{@{@}}).  While basic regular expressions require
+these to be escaped if you want them to behave as special characters,
+when using extended regular expressions you must escape them if
+you want them @emph{to match a literal character}.
+
+@noindent
+Examples:
+@table @code
+@item abc?
+becomes @samp{abc\?} when using extended regular expressions.  It matches
+the literal string @samp{abc?}.
+
+@item c\+
+becomes @samp{c+} when using extended regular expressions.  It matches
+one or more @samp{c}s.
+
+@item a\@{3,\@}
+becomes @samp{a@{3,@}} when using extended regular expressions.  It matches
+three or more @samp{a}s.
+
+@item \(abc\)\@{2,3\@}
+becomes @samp{(abc)@{2,3@}} when using extended regular expressions.  It
+matches either @samp{abcabc} or @samp{abcabcabc}.
+
+@item \(abc*\)\1
+becomes @samp{(abc*)\1} when using extended regular expressions.
+Backreferences must still be escaped when using extended regular
+expressions.
+@end table
+
+@ifset PERL
+@node Perl regexps
+@appendix Perl-style regular expressions
+@cindex Perl-style regular expressions, syntax
+
+@emph{This part is taken from the @file{pcre.txt} file distributed together
+with the free @sc{pcre} regular expression matcher; it was written by Philip Hazel.}
+
+Perl introduced several extensions to regular expressions, some
+of them incompatible with the syntax of regular expressions
+accepted by Emacs and other @acronym{GNU} tools (whose matcher was
+based on the Emacs matcher).  @value{SSED} implements
+both kinds of extensions.
+
+@iftex
+Summarizing, we have:
+
+@itemize @bullet
+@item
+A backslash can introduce several special sequences
+
+@item
+The circumflex, dollar sign, and period characters behave specially 
+with regard to new lines
+
+@item
+Strange uses of square brackets are parsed differently
+
+@item
+You can toggle modifiers in the middle of a regular expression
+
+@item
+You can specify that a subpattern does not count when numbering backreferences
+
+@item
+@cindex Greedy regular expression matching
+You can specify greedy or non-greedy matching
+
+@item
+You can have more than ten back references
+
+@item
+You can do complex look aheads and look behinds (in the spirit of
+@code{\b}, but with subpatterns).
+
+@item
+You can often improve performance by avoiding that @command{sed} wastes
+time with backtracking
+
+@item
+You can have if/then/else branches
+
+@item
+You can do recursive matches, for example to look for unbalanced parentheses
+
+@item
+You can have comments and non-significant whitespace, because things can
+get complex...
+@end itemize
+
+Most of these extensions are introduced by the special @code{(?}
+sequence, which gives special meanings to parenthesized groups.
+@end iftex
+@menu
+Other extensions can be roughly subdivided in two categories
+On one hand Perl introduces several more escaped sequences
+(that is, sequences introduced by a backslash).  On the other
+hand, it specifies that if a question mark follows an open
+parentheses it should give a special meaning to the parenthesized
+group.
+
+* Backslash::                       Introduces special sequences
+* Circumflex/dollar sign/period::   Behave specially with regard to new lines
+* Square brackets::                 Are a bit different in strange cases
+* Options setting::                 Toggle modifiers in the middle of a regexp
+* Non-capturing subpatterns::       Are not counted when backreferencing
+* Repetition::                      Allows for non-greedy matching
+* Backreferences::                  Allows for more than 10 back references
+* Assertions::                      Allows for complex look ahead matches
+* Non-backtracking subpatterns::    Often gives more performance
+* Conditional subpatterns::         Allows if/then/else branches
+* Recursive patterns::              For example to match parentheses
+* Comments::                        Because things can get complex...
+@end menu
+
+@node Backslash
+@appendixsec Backslash
+@cindex Perl-style regular expressions, escaped sequences
+
+There are a few difference in the handling of backslashed 
+sequences in Perl mode.
+
+First of all, there are no @code{\o} and @code{\d} sequences.
+@sc{ascii} values for characters can be specified in octal
+with a @code{\@var{xxx}} sequence, where @var{xxx} is a
+sequence of up to three octal digits.  If the first digit
+is a zero, the treatment of the sequence is straightforward;
+just note that if the character that follows the escaped digit
+is itself an octal digit, you have to supply three octal digits
+for @var{xxx}.  For example @code{\07} is a @sc{bel} character
+rather than a @sc{nul} and a literal @code{7} (this sequence is
+instead represented by @code{\0007}).
+
+@cindex Perl-style regular expressions, backreferences
+The handling of a backslash followed by a digit other than 0
+is complicated.  Outside a character class, @command{sed} reads it
+and any following digits as a decimal number. If the number
+is less than 10, or if there have been at least that many
+previous capturing left parentheses in the expression, the
+entire sequence is taken as a back reference. A description
+of how this works is given later, following the discussion
+of parenthesized subpatterns.
+
+Inside a character class, or if the decimal number is
+greater than 9 and there have not been that many capturing
+subpatterns, @command{sed} re-reads up to three octal digits following
+the backslash, and generates a single byte from the
+least significant 8 bits of the value. Any subsequent digits
+stand for themselves.  For example:
+
+@example
+     \040  @i{is another way of writing a space}
+     \40   @i{is the same, provided there are fewer than 40}
+           @i{previous capturing subpatterns}
+     \7    @i{is always a back reference}
+     \011  @i{is always a tab}
+     \11   @i{might be a back reference, or another way of}
+           @i{writing a tab}
+     \0113 @i{is a tab followed by the character @samp{3}}
+     \113  @i{is the character with octal code 113 (since there}
+           @i{can be no more than 99 back references)}
+     \377  @i{is a byte consisting entirely of 1 bits (@sc{ascii} 255)}
+     \81   @i{is either a back reference, or a binary zero}
+           @i{followed by the two characters @samp{81}}
+@end example
+
+Note that octal values of 100 or greater must not be introduced
+duced by a leading zero, because no more than three octal
+digits are ever read.
+
+All the sequences that define a single byte value can be
+used both inside and outside character classes. In addition,
+inside a character class, the sequence @code{\b} is interpreted
+as the backspace character (hex 08). Outside a character
+class it has a different meaning (see below).
+
+In addition, there are four additional escapes specifying
+generic character classes (like @code{\w} and @code{\W} do):
+
+@cindex Perl-style regular expressions, character classes
+@table @samp
+@item \d
+Matches any decimal digit
+
+@item \D
+Matches any character that is not a decimal digit
+@end table
+
+In Perl mode, these character type sequences can appear both inside and
+outside character classes. Instead, in @sc{posix} mode these sequences
+(as well as @code{\w} and @code{\W}) are treated as two literal characters
+(a backslash and a letter) inside square brackets.
+
+Escaped sequences specifying assertions are also different in
+Perl mode.  An assertion specifies a condition that has to be met
+at a particular point in a match, without consuming any
+characters from the subject string. The use of subpatterns
+for more complicated assertions is described below.  The
+backslashed assertions are
+
+@cindex Perl-style regular expressions, assertions
+@table @samp
+@item \b
+Asserts that the point is at a word boundary.
+A word boundary is a position in the subject string where
+the current character and the previous character do not both
+match @code{\w} or @code{\W} (i.e. one matches @code{\w} and
+the other matches @code{\W}), or the start or end of the string
+if the first or last character matches @code{\w}, respectively.
+
+@item \B
+Asserts that the point is not at a word boundary.
+
+@item \A
+Asserts the matcher is at the start of pattern space (independent
+of multiline mode).
+
+@item \Z
+Asserts the matcher is at the end of pattern space,
+or at a newline before the end of pattern space (independent of
+multiline mode)
+
+@item \z
+Asserts the matcher is at the end of pattern space (independent
+of multiline mode)
+@end table
+
+These assertions may not appear in character classes (but
+note that @code{\b} has a different meaning, namely the
+backspace character, inside a character class).
+Note that Perl mode does not support directly assertions
+for the beginning and the end of word; the @acronym{GNU} extensions
+@code{\<} and @code{\>} achieve this purpose in @sc{posix} mode
+instead.
+
+The @code{\A}, @code{\Z}, and @code{\z} assertions differ
+from the traditional circumflex and dollar sign (described below)
+in that they only ever match at the very start and end of the
+subject string, whatever options are set; in particular @code{\A}
+and @code{\z} are the same as the @acronym{GNU} extensions
+@code{\`} and @code{\'} that are active in @sc{posix} mode.
+
+@node Circumflex/dollar sign/period
+@appendixsec Circumflex, dollar sign, period
+@cindex Perl-style regular expressions, newlines
+
+Outside a character class, in the default matching mode, the
+circumflex character is an assertion which is true only if
+the current matching point is at the start of the subject
+string.  Inside a character class, the circumflex has an entirely
+different meaning (see below).
+
+The circumflex need not be the first character of the pattern if
+a number of alternatives are involved, but it should be the
+first thing in each alternative in which it appears if the
+pattern is ever to match that branch. If all possible alternatives,
+start with a circumflex, that is, if the pattern is
+constrained to match only at the start of the subject, it is
+said to be an @dfn{anchored} pattern. (There are also other constructs
+structs that can cause a pattern to be anchored.)
+
+A dollar sign is an assertion which is true only if the
+current matching point is at the end of the subject string,
+or immediately before a newline character that is the last
+character in the string (by default).  A dollar sign need not be the
+last character of the pattern if a number of alternatives
+are involved, but it should be the last item in any branch
+in which it appears.  A dollar sign has no special meaning in a
+character class.
+
+@cindex Perl-style regular expressions, multiline
+The meanings of the circumflex and dollar sign characters are
+changed if the @code{M} modifier option is used. When this is
+the case, they match immediately after and immediately
+before an internal @code{\n} character, respectively, in addition
+to matching at the start and end of the subject string.  For
+example, the pattern @code{/^abc$/} matches the subject string
+@samp{def\nabc} in multiline mode, but not otherwise.  Consequently,
+patterns that are anchored in single line mode
+because all branches start with @code{^} are not anchored in
+multiline mode.
+
+@cindex Perl-style regular expressions, multiline
+Note that the sequences @code{\A}, @code{\Z}, and @code{\z}
+can be used to match the start and end of the subject in both
+modes, and if all branches of a pattern start with @code{\A}
+is it always anchored, whether the @code{M} modifier is set or not.
+
+@cindex Perl-style regular expressions, single line
+Outside a character class, a dot in the pattern matches any
+one character in the subject, including a non-printing character,
+but not (by default) newline.  If the @code{S} modifier is used,
+dots match newlines as well.  Actually, the handling of
+dot is entirely independent of the handling of circumflex
+and dollar sign, the only relationship being that they both
+involve newline characters. Dot has no special meaning in a
+character class.
+
+@node Square brackets
+@appendixsec Square brackets
+@cindex Perl-style regular expressions, character classes
+
+An opening square bracket introduces a character class, terminated
+by a closing square bracket.  A closing square bracket on its own
+is not special.  If a closing square bracket is required as a
+member of the class, it should be the first data character in
+the class (after an initial circumflex, if present) or escaped with a backslash.
+
+A character class matches a single character in the subject;
+the character must be in the set of characters defined by
+the class, unless the first character in the class is a circumflex,
+in which case the subject character must not be in
+the set defined by the class. If a circumflex is actually
+required as a member of the class, ensure it is not the
+first character, or escape it with a backslash.
+
+For example, the character class [aeiou] matches any lower
+case vowel, while [^aeiou] matches any character that is not
+a lower case vowel. Note that a circumflex is just a convenient
+venient notation for specifying the characters which are in
+the class by enumerating those that are not. It is not an
+assertion: it still consumes a character from the subject
+string, and fails if the current pointer is at the end of
+the string.
+
+@cindex Perl-style regular expressions, case-insensitive
+When caseless matching is set, any letters in a class
+represent both their upper case and lower case versions, so
+for example, a caseless @code{[aeiou]} matches uppercase
+and lowercase @samp{A}s, and a caseless @code{[^aeiou]}
+does not match @samp{A}, whereas a case-sensitive version would.
+
+@cindex Perl-style regular expressions, single line
+@cindex Perl-style regular expressions, multiline
+The newline character is never treated in any special way in
+character classes, whatever the setting of the @code{S} and
+@code{M} options (modifiers) is.  A class such as @code{[^a]} will
+always match a newline.
+
+The minus (hyphen) character can be used to specify a range
+of characters in a character class.  For example, @code{[d-m]}
+matches any letter between d and m, inclusive.  If a minus
+character is required in a class, it must be escaped with a
+backslash or appear in a position where it cannot be interpreted
+as indicating a range, typically as the first or last
+character in the class.
+
+It is not possible to have the literal character @code{]} as the
+end character of a range.  A pattern such as @code{[W-]46]} is
+interpreted as a class of two characters (@code{W} and @code{-})
+followed by a literal string @code{46]}, so it would match
+@samp{W46]} or @samp{-46]}. However, if the @code{]} is escaped
+with a backslash it is interpreted as the end of range, so
+@code{[W-\]46]} is interpreted as a single class containing a
+range followed by two separate characters. The octal or
+hexadecimal representation of @code{]} can also be used to end a range.
+
+Ranges operate in @sc{ascii} collating sequence. They can also be
+used for characters specified numerically, for example
+@code{[\000-\037]}. If a range that includes letters is used when
+caseless matching is set, it matches the letters in either
+case. For example, a caseless @code{[W-c]} is equivalent to
+@code{[][\^_`wxyzabc]}, matched caselessly, and if character
+tables for the French locale are in use, @code{[\xc8-\xcb]}
+matches accented E characters in both cases.
+
+Unlike in @sc{posix} mode, the character types @code{\d},
+@code{\D}, @code{\s}, @code{\S}, @code{\w}, and @code{\W}
+may also appear in a character class, and add the characters
+that they match to the class. For example, @code{[\dABCDEF]} matches any
+hexadecimal digit.  A circumflex can conveniently be used
+with the upper case character types to specify a more restricted
+set of characters than the matching lower case type.
+For example, the class @code{[^\W_]} matches any letter or digit,
+but not underscore.
+
+All non-alphameric characters other than @code{\}, @code{-},
+@code{^} (at the start) and the terminating @code{]}
+are non-special in character classes, but it does no harm
+if they are escaped.
+
+Perl 5.6 supports the @sc{posix} notation for character classes, which
+uses names enclosed by @code{[:} and @code{:]} within the enclosing
+square brackets, and @value{SSED} supports this notation as well.
+For example,
+
+@example
+     [01[:alpha:]%]
+@end example
+
+@noindent
+matches @samp{0}, @samp{1}, any alphabetic character, or @samp{%}.
+The supported class names are
+
+@table @code
+@item alnum
+Matches letters and digits
+
+@item alpha
+Matches letters
+
+@item ascii
+Matches character codes 0 - 127
+
+@item cntrl
+Matches control characters
+
+@item digit
+Matches decimal digits (same as \d)
+
+@item graph
+Matches printing characters, excluding space
+
+@item lower
+Matches lower case letters
+
+@item print
+Matches printing characters, including space
+
+@item punct
+Matches printing characters, excluding letters and digits
+
+@item space
+Matches white space (same as \s)
+
+@item upper
+Matches upper case letters
+
+@item word
+Matches ``word'' characters (same as \w)
+
+@item xdigit
+Matches hexadecimal digits
+@end table
+
+The names @code{ascii} and @code{word} are extensions valid only in
+Perl mode.  Another Perl extension is negation, which is
+indicated by a circumflex character after the colon. For example,
+
+@example
+     [12[:^digit:]]
+@end example
+
+@noindent
+matches @samp{1}, @samp{2}, or any non-digit.
+
+@node Options setting
+@appendixsec Options setting
+@cindex Perl-style regular expressions, toggling options
+@cindex Perl-style regular expressions, case-insensitive
+@cindex Perl-style regular expressions, multiline
+@cindex Perl-style regular expressions, single line
+@cindex Perl-style regular expressions, extended
+
+The settings of the @code{I}, @code{M}, @code{S}, @code{X}
+modifiers can be changed from within the pattern by
+a sequence of Perl option letters enclosed between @code{(?}
+and @code{)}. The option letters must be lowercase.
+
+For example, @code{(?im)} sets caseless, multiline matching. It is
+also possible to unset these options by preceding the letter
+with a hyphen; you can also have combined settings and unsettings:
+@code{(?im-sx)} sets caseless and multiline matching,
+while unsets single line matching (for dots) and extended
+whitespace interpretation.  If a letter appears both before
+and after the hyphen, the option is unset.
+
+The scope of these option changes depends on where in the
+pattern the setting occurs. For settings that are outside
+any subpattern (defined below), the effect is the same as if
+the options were set or unset at the start of matching. The
+following patterns all behave in exactly the same way:
+
+@example
+     (?i)abc
+     a(?i)bc
+     ab(?i)c
+     abc(?i)
+@end example
+
+which in turn is the same as specifying the pattern abc with
+the @code{I} modifier.  In other words, ``top level'' settings
+apply to the whole pattern (unless there are other
+changes inside subpatterns). If there is more than one setting
+of the same option at top level, the rightmost setting
+is used.
+
+If an option change occurs inside a subpattern, the effect
+is different.  This is a change of behaviour in Perl 5.005.
+An option change inside a subpattern affects only that part
+of the subpattern @emph{that follows} it, so
+
+@example
+     (a(?i)b)c
+@end example
+
+@noindent
+matches abc and aBc and no other  strings  (assuming
+case-sensitive matching is used).  By this means, options can
+be made to have different settings in different parts of the
+pattern.  Any changes made in one alternative do carry on
+into subsequent branches within the same subpattern.  For
+example,
+
+@example
+     (a(?i)b|c)
+@end example
+
+@noindent
+matches @samp{ab}, @samp{aB}, @samp{c}, and @samp{C},
+even though when matching @samp{C} the first branch is
+abandoned before the option setting.
+This is because the effects of option settings happen at
+compile time. There would be some very weird behaviour otherwise.
+
+@ignore
+There are two PCRE-specific options PCRE_UNGREEDY and PCRE_EXTRA
+that can be changed in the same way as the Perl-compatible options by
+using the characters U and X respectively.  The (?X) flag
+setting is special in that it must always occur earlier in
+the pattern than any of the additional features it turns on,
+even when it is at top level. It is best put at the start.
+@end ignore
+
+
+@node Non-capturing subpatterns
+@appendixsec Non-capturing subpatterns
+@cindex Perl-style regular expressions, non-capturing subpatterns
+
+Marking part of a pattern as a subpattern does two things.
+On one hand, it localizes a set of alternatives; on the other
+hand, it sets up the subpattern as a capturing subpattern (as
+defined above).  The subpattern can be backreferenced and
+referenced in the right side of @code{s} commands.
+
+For example, if the string @samp{the red king} is matched against
+the pattern
+
+@example
+     the ((red|white) (king|queen))
+@end example
+
+@noindent
+the captured substrings are @samp{red king}, @samp{red},
+and @samp{king}, and are numbered 1, 2, and 3.
+
+The fact that plain parentheses fulfil two functions is not
+always helpful.  There are often times when a grouping
+subpattern is required without a capturing requirement.  If an
+opening parenthesis is followed by @code{?:}, the subpattern does
+not do any capturing, and is not counted when computing the
+number of any subsequent capturing subpatterns. For example,
+if the string @samp{the white queen} is matched against the pattern
+
+@example
+     the ((?:red|white) (king|queen))
+@end example
+
+@noindent
+the captured substrings are @samp{white queen} and @samp{queen},
+and are numbered 1 and 2. The maximum number of captured
+substrings is 99, while the maximum number of all subpatterns,
+both capturing and non-capturing, is 200.
+
+As a convenient shorthand, if any option settings are
+equired at the start of a non-capturing subpattern, the
+option letters may appear between the @code{?} and the
+@code{:}.  Thus the two patterns
+
+@example
+   (?i:saturday|sunday)
+   (?:(?i)saturday|sunday)
+@end example
+
+@noindent
+match exactly the same set of strings.  Because alternative
+branches are tried from left to right, and options are not
+reset until the end of the subpattern is reached, an option
+setting in one branch does affect subsequent branches, so
+the above patterns match @samp{SUNDAY} as well as @samp{Saturday}.
+
+
+@node Repetition
+@appendixsec Repetition
+@cindex Perl-style regular expressions, repetitions
+
+Repetition is specified by quantifiers, which can follow any
+of the following items:
+
+@itemize @bullet
+@item
+a single character, possibly escaped
+
+@item
+the @code{.} special character
+
+@item
+a character class
+
+@item
+a back reference (see next section)
+
+@item
+a parenthesized subpattern (unless it is an assertion; @pxref{Assertions})
+@end itemize
+
+The general repetition quantifier specifies a minimum and
+maximum number of permitted matches, by giving the two
+numbers in curly brackets (braces), separated by a comma.
+The numbers must be less than 65536, and the first must be
+less than or equal to the second. For example:
+
+@example
+     z@{2,4@}
+@end example
+
+@noindent
+matches @samp{zz}, @samp{zzz}, or @samp{zzzz}. A closing brace on its own
+is not a special character. If the second number is omitted,
+but the comma is present, there is no upper limit; if the
+second number and the comma are both omitted, the quantifier
+specifies an exact number of required matches. Thus
+
+@example
+     [aeiou]@{3,@}
+@end example
+
+@noindent
+matches at least 3 successive vowels, but may match many
+more, while
+
+@example
+     \d@{8@}
+@end example
+
+@noindent
+matches exactly 8 digits.  An opening curly bracket that
+appears in a position where a quantifier is not allowed, or
+one that does not match the syntax of a quantifier, is taken
+as a literal character. For example, @{,6@} is not a quantifier,
+but a literal string of four characters.@footnote{It
+raises an error if @option{-R} is not used.}
+
+The quantifier @samp{@{0@}} is permitted, causing the expression to
+behave as if the previous item and the quantifier were not
+present.
+
+For convenience (and historical compatibility) the three
+most common quantifiers have single-character abbreviations:
+
+@table @code
+@item *
+is equivalent to @{0,@}
+
+@item +
+is equivalent to @{1,@}
+
+@item ?
+is equivalent to @{0,1@}
+@end table
+
+It is possible to construct infinite loops by following a
+subpattern that can match no characters with a quantifier
+that has no upper limit, for example:
+
+@example
+     (a?)*
+@end example
+
+Earlier versions of Perl used to give an error at
+compile time for such patterns. However, because there are
+cases where this can be useful, such patterns are now
+accepted, but if any repetition of the subpattern does in
+fact match no characters, the loop is forcibly broken.
+
+@cindex Greedy regular expression matching
+@cindex Perl-style regular expressions, stingy repetitions
+By default, the quantifiers are @dfn{greedy} like in @sc{posix}
+mode, that is, they match as much as possible (up to the maximum
+number of permitted times), without causing the rest of the
+pattern to fail. The classic example of where this gives problems
+is in trying to match comments in C programs. These appear between
+the sequences @code{/*} and @code{*/} and within the sequence, individual
+@code{*} and @code{/} characters may appear. An attempt to match C
+comments by applying the pattern
+
+@example
+     /\*.*\*/
+@end example
+
+@noindent
+to the string
+
+@example
+     /* first command */ not comment /* second comment */
+@end example
+
+@noindent
+
+fails, because it matches the entire string owing to the
+greediness of the @code{.*} item.
+
+However, if a quantifier is followed by a question mark, it
+ceases to be greedy, and instead matches the minimum number
+of times possible, so the pattern @code{/\*.*?\*/}
+does the right thing with the C comments. The meaning of the
+various quantifiers is not otherwise changed, just the preferred
+number of matches.  Do not confuse this use of question
+mark with its use as a quantifier in its own right.
+Because it has two uses, it can sometimes appear doubled, as in
+
+@example
+     \d??\d
+@end example
+
+which matches one digit by preference, but can match two if
+that is the only way the rest of the pattern matches.
+
+Note that greediness does not matter when specifying addresses,
+but can be nevertheless used to improve performance.
+
+@ignore
+   If the PCRE_UNGREEDY option is set (an option which is not
+   available in Perl), the quantifiers are not greedy by
+   default, but individual ones can be made greedy by following
+   them with a question mark. In other words, it inverts the
+   default behaviour.
+@end ignore
+
+When a parenthesized subpattern is quantified with a minimum
+repeat count that is greater than 1 or with a limited maximum,
+more store is required for the compiled pattern, in
+proportion to the size of the minimum or maximum.
+
+@cindex Perl-style regular expressions, single line
+If a pattern starts with @code{.*} or @code{.@{0,@}} and the
+@code{S} modifier is used, the pattern is implicitly anchored,
+because whatever follows will be tried against every character
+position in the subject string, so there is no point in
+retrying the overall match at any position after the first.
+PCRE treats such a pattern as though it were preceded by \A.
+
+When a capturing subpattern is repeated, the value captured
+is the substring that matched the final iteration. For example,
+after
+
+@example
+     (tweedle[dume]@{3@}\s*)+
+@end example
+
+@noindent
+has matched @samp{tweedledum tweedledee} the value of the
+captured substring is @samp{tweedledee}.  However, if there are
+nested capturing subpatterns, the corresponding captured
+values may have been set in previous iterations. For example,
+after
+
+@example
+     /(a|(b))+/
+@end example
+
+matches @samp{aba}, the value of the second captured substring is
+@samp{b}.
+
+@node Backreferences
+@appendixsec Backreferences
+@cindex Perl-style regular expressions, backreferences
+
+Outside a character class, a backslash followed by a digit
+greater than 0 (and possibly further digits) is a back
+reference to a capturing subpattern earlier (i.e.  to its
+left) in the pattern, provided there have been that many
+previous capturing left parentheses.
+
+However, if the decimal number following the backslash is
+less than 10, it is always taken as a back reference, and
+causes an error only if there are not that many capturing
+left parentheses in the entire pattern. In other words, the
+parentheses that are referenced need not be to the left of
+the reference for numbers less than 10. @ref{Backslash}
+for further details of the handling of digits following a backslash.
+
+A back reference matches whatever actually matched the capturing
+subpattern in the current subject string, rather than
+anything matching the subpattern itself. So the pattern
+
+@example
+     (sens|respons)e and \1ibility
+@end example
+
+@noindent
+matches @samp{sense and sensibility} and @samp{response and responsibility},
+but not @samp{sense and responsibility}. If caseful
+matching is in force at the time of the back reference, the
+case of letters is relevant. For example,
+
+@example
+     ((?i)blah)\s+\1
+@end example
+
+@noindent
+matches @samp{blah blah} and @samp{Blah Blah}, but not
+@samp{BLAH blah}, even though the original capturing
+subpattern is matched caselessly.
+
+There may be more than one back reference to the same subpattern.
+Also, if a subpattern has not actually been used in a
+particular match, any back references to it always fail. For
+example, the pattern
+
+@example
+     (a|(bc))\2
+@end example
+
+@noindent
+always fails if it starts to match @samp{a} rather than
+@samp{bc}.  Because there may be up to 99 back references, all
+digits following the backslash are taken as part of a potential
+back reference number; this is different from what happens
+in @sc{posix} mode. If the pattern continues with a digit
+character, some delimiter must be used to terminate the back
+reference.  If the @code{X} modifier option is set, this can be
+whitespace.  Otherwise an empty comment can be used, or the
+following character can be expressed in hexadecimal or octal.
+
+A back reference that occurs inside the parentheses to which
+it refers fails when the subpattern is first used, so, for
+example, @code{(a\1)} never matches.  However, such references
+can be useful inside repeated subpatterns. For example, the
+pattern
+
+@example
+     (a|b\1)+
+@end example
+
+@noindent
+matches any number of @samp{a}s and also @samp{aba}, @samp{ababbaa},
+etc. At each iteration of the subpattern, the back reference matches
+the character string corresponding to the previous iteration.  In
+order for this to work, the pattern must be such that the first
+iteration does not need to match the back reference.  This can be
+done using alternation, as in the example above, or by a
+quantifier with a minimum of zero.
+
+@node Assertions
+@appendixsec Assertions
+@cindex Perl-style regular expressions, assertions
+@cindex Perl-style regular expressions, asserting subpatterns
+
+An assertion is a test on the characters following or
+preceding the current matching point that does not actually
+consume any characters. The simple assertions coded as @code{\b},
+@code{\B}, @code{\A}, @code{\Z}, @code{\z}, @code{^} and @code{$}
+are described above. More complicated assertions are coded as
+subpatterns.  There are two kinds: those that look ahead of the
+current position in the subject string, and those that look behind it.
+
+@cindex Perl-style regular expressions, lookahead subpatterns
+An assertion subpattern is matched in the normal way, except
+that it does not cause the current matching position to be
+changed. Lookahead assertions start with @code{(?=} for positive
+assertions and @code{(?!} for negative assertions. For example,
+
+@example
+     \w+(?=;)
+@end example
+
+@noindent
+matches a word followed by a semicolon, but does not include
+the semicolon in the match, and
+
+@example
+     foo(?!bar)
+@end example
+
+@noindent
+matches any occurrence of @samp{foo} that is not followed by
+@samp{bar}.
+
+Note that the apparently similar pattern
+
+@example
+     (?!foo)bar
+@end example
+
+@noindent
+@cindex Perl-style regular expressions, lookbehind subpatterns
+finds any occurrence of @samp{bar} even if it is preceded by
+@samp{foo}, because the assertion @code{(?!foo)} is always true
+when the next three characters are @samp{bar}. A lookbehind
+assertion is needed to achieve this effect.
+Lookbehind assertions start with @code{(?<=} for positive
+assertions and @code{(?<!} for negative assertions. So,
+
+@example
+     (?<!foo)bar
+@end example
+
+achieves the required effect of finding an occurrence of
+@samp{bar} that is not preceded by @samp{foo}. The contents of a
+lookbehind assertion are restricted
+such that all the strings it matches must have a fixed
+length.  However, if there are several alternatives, they do
+not all have to have the same fixed length.  This is an extension
+compared with Perl 5.005, which requires all branches to match
+the same length of string. Thus
+
+@example
+     (?<=dogs|cats|)
+@end example
+
+@noindent
+is permitted, but the apparently equivalent regular expression
+
+@example
+     (?<!dogs?|cats?)
+@end example
+
+@noindent
+causes an error at compile time. Branches that match different
+length strings are permitted only at the top level of
+a lookbehind assertion: an assertion such as
+
+@example
+     (?<=ab(c|de))
+@end example
+
+@noindent
+is not permitted, because its single top-level branch can
+match two different lengths, but it is acceptable if rewritten
+to use two top-level branches:
+
+@example
+     (?<=abc|abde)
+@end example
+
+All this is required because lookbehind assertions simply
+move the current position back by the alternative's fixed
+width and then try to match.  If there are
+insufficient characters before the current position, the
+match is deemed to fail.  Lookbehinds, in conjunction with
+non-backtracking subpatterns can be particularly useful for
+matching at the ends of strings; an example is given at the end
+of the section on non-backtracking subpatterns.
+
+Several assertions (of any sort) may occur in succession.
+For example,
+
+@example
+     (?<=\d@{3@})(?<!999)foo
+@end example
+
+@noindent
+matches @samp{foo} preceded by three digits that are not @samp{999}.
+Notice that each of the assertions is applied independently
+at the same point in the subject string. First there is a
+check that the previous three characters are all digits, and
+then there is a check that the same three characters are not
+@samp{999}.  This pattern does not match @samp{foo} preceded by six
+characters, the first of which are digits and the last three
+of which are not @samp{999}.  For example, it doesn't match
+@samp{123abcfoo}. A pattern to do that is
+
+@example
+     (?<=\d@{3@}...)(?<!999)foo
+@end example
+
+@noindent
+This time the first assertion looks at the preceding six
+characters, checking that the first three are digits, and
+then the second assertion checks that the preceding three
+characters are not @samp{999}.  Actually, assertions can be
+nested in any combination, so one can write this as 
+
+@example
+     (?<=\d@{3@}(?!999)...)foo
+@end example
+
+or
+
+@example
+     (?<=\d@{3@}...(?<!999))foo
+@end example
+
+@noindent
+both of which might be considered more readable.
+
+Assertion subpatterns are not capturing subpatterns, and may
+not be repeated, because it makes no sense to assert the
+same thing several times. If any kind of assertion contains
+capturing subpatterns within it, these are counted for the
+purposes of numbering the capturing subpatterns in the whole
+pattern.  However, substring capturing is carried out only
+for positive assertions, because it does not make sense for
+negative assertions.
+
+Assertions count towards the maximum of 200 parenthesized
+subpatterns.
+
+@node Non-backtracking subpatterns
+@appendixsec Non-backtracking subpatterns
+@cindex Perl-style regular expressions, non-backtracking subpatterns
+
+With both maximizing and minimizing repetition, failure of
+what follows normally causes the repeated item to be evaluated
+again to see if a different number of repeats allows the
+rest of the pattern to match. Sometimes it is useful to
+prevent this, either to change the nature of the match, or
+to cause it fail earlier than it otherwise might, when the
+author of the pattern knows there is no point in carrying
+on.
+
+Consider, for example, the pattern @code{\d+foo} when applied to
+the subject line
+
+@example
+     123456bar
+@end example
+
+After matching all 6 digits and then failing to match @samp{foo},
+the normal action of the matcher is to try again with only 5
+digits matching the @code{\d+} item, and then with 4, and so on,
+before ultimately failing. Non-backtracking subpatterns
+provide the means for specifying that once a portion of the
+pattern has matched, it is not to be re-evaluated in this way,
+so the matcher would give up immediately on failing to match
+@samp{foo} the first time.  The notation is another kind of special
+parenthesis, starting with @code{(?>} as in this example:
+
+@example
+     (?>\d+)bar
+@end example
+
+This kind of parenthesis ``locks up'' the part of the pattern
+it contains once it has matched, and a failure further into
+the pattern is prevented from backtracking into it.
+Backtracking past it to previous items, however, works as
+normal.
+
+Non-backtracking subpatterns are not capturing subpatterns.  Simple
+cases such as the above example can be thought of as a maximizing
+repeat that must swallow everything it can.  So,
+while both @code{\d+} and @code{\d+?} are prepared to adjust the number of
+digits they match in order to make the rest of the pattern
+match, @code{(?>\d+)} can only match an entire sequence of digits.
+
+This construction can of course contain arbitrarily complicated
+subpatterns, and it can be nested.
+
+@cindex Perl-style regular expressions, lookbehind subpatterns
+Non-backtracking subpatterns can be used in conjunction with look-behind
+assertions to specify efficient matching at the end
+of the subject string. Consider a simple pattern such as
+
+@example
+     abcd$
+@end example
+
+@noindent
+when applied to a long string which does not match.  Because
+matching proceeds from left to right, @command{sed} will look for
+each @samp{a} in the subject and then see if what follows matches
+the rest of the pattern. If the pattern is specified as
+
+@example
+     ^.*abcd$
+@end example
+
+@noindent
+the initial @code{.*} matches the entire string at first, but when
+this fails (because there is no following @samp{a}), it backtracks
+to match all but the last character, then all but the
+last two characters, and so on. Once again the search for
+@samp{a} covers the entire string, from right to left, so we are
+no better off. However, if the pattern is written as
+
+@example
+     ^(?>.*)(?<=abcd)
+@end example
+
+there can be no backtracking for the .* item; it can match
+only the entire string. The subsequent lookbehind assertion
+does a single test on the last four characters. If it fails,
+the match fails immediately. For long strings, this approach
+makes a significant difference to the processing time.
+
+When a pattern contains an unlimited repeat inside a subpattern
+that can itself be repeated an unlimited number of
+times, the use of a once-only subpattern is the only way to
+avoid some failing matches taking a very long time
+indeed.@footnote{Actually, the matcher embedded in @value{SSED}
+    tries to do something for this in the simplest cases,
+    like @code{([^b]*b)*}.  These cases are actually quite
+    common: they happen for example in a regular expression
+    like @code{\/\*([^*]*\*)*\/} which matches C comments.}
+
+The pattern
+
+@example
+     (\D+|<\d+>)*[!?]
+@end example
+
+([^0-9<]+<(\d+>)?)*[!?]
+
+@noindent
+matches an unlimited number of substrings that either consist
+of non-digits, or digits enclosed in angular brackets, followed by
+an exclamation or question mark. When it matches, it runs quickly.
+However, if it is applied to
+
+@example
+     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+@end example
+
+@noindent
+it takes a long time before reporting failure.  This is
+because the string can be divided between the two repeats in
+a large number of ways, and all have to be tried.@footnote{The
+example used @code{[!?]} rather than a single character at the end,
+because both @value{SSED} and Perl have an optimization that allows
+for fast failure when a single character is used. They
+remember the last single character that is required for a
+match, and fail early if it is not present in the string.}
+
+If the pattern is changed to
+
+@example
+     ((?>\D+)|<\d+>)*[!?]
+@end example
+
+sequences of non-digits cannot be broken, and failure happens
+quickly.
+
+@node Conditional subpatterns
+@appendixsec Conditional subpatterns
+@cindex Perl-style regular expressions, conditional subpatterns
+
+It is possible to cause the matching process to obey a subpattern
+conditionally or to choose between two alternative
+subpatterns, depending on the result of an assertion, or
+whether a previous capturing subpattern matched or not. The
+two possible forms of conditional subpattern are
+
+@example
+     (?(@var{condition})@var{yes-pattern})
+     (?(@var{condition})@var{yes-pattern}|@var{no-pattern})
+@end example
+
+If the condition is satisfied, the yes-pattern is used; otherwise
+the no-pattern (if present) is used. If there are more than two
+alternatives in the subpattern, a compile-time error occurs.
+
+There are two kinds of condition. If the text between the
+parentheses consists of a sequence of digits, the condition
+is satisfied if the capturing subpattern of that number has
+previously matched.  The number must be greater than zero.
+Consider the following pattern, which contains non-significant
+white space to make it more readable (assume the @code{X} modifier)
+and to divide it into three parts for ease of discussion:
+
+@example
+     ( \( )?   [^()]+   (?(1) \) )
+@end example
+
+The first part matches an optional opening parenthesis, and
+if that character is present, sets it as the first captured
+substring. The second part matches one or more characters
+that are not parentheses. The third part is a conditional
+subpattern that tests whether the first set of parentheses
+matched or not.  If they did, that is, if subject started
+with an opening parenthesis, the condition is true, and so
+the yes-pattern is executed and a closing parenthesis is
+required. Otherwise, since no-pattern is not present, the
+subpattern matches nothing.  In other words, this pattern
+matches a sequence of non-parentheses, optionally enclosed
+in parentheses.
+
+@cindex Perl-style regular expressions, lookahead subpatterns
+If the condition is not a sequence of digits, it must be an
+assertion.  This may be a positive or negative lookahead or
+lookbehind assertion. Consider this pattern, again containing
+non-significant white space, and with the two alternatives
+on the second line:
+
+@example
+     (?(?=...[a-z])
+        \d\d-[a-z]@{3@}-\d\d |
+        \d\d-\d\d-\d\d )
+@end example
+
+The condition is a positive lookahead assertion that matches
+a letter that is three characters away from the current point.
+If a letter is found, the subject is matched against the first
+alternative @samp{@var{dd}-@var{aaa}-@var{dd}} (where @var{aaa} are
+letters and @var{dd} are digits); otherwise it is matched against 
+the second alternative, @samp{@var{dd}-@var{dd}-@var{dd}}.
+
+
+@node Recursive patterns
+@appendixsec Recursive patterns
+@cindex Perl-style regular expressions, recursive patterns
+@cindex Perl-style regular expressions, recursion
+
+Consider the problem of matching a string in parentheses,
+allowing for unlimited nested parentheses. Without the use
+of recursion, the best that can be done is to use a pattern
+that matches up to some fixed depth of nesting. It is not
+possible to handle an arbitrary nesting depth. Perl 5.6 has
+provided an experimental facility that allows regular
+expressions to recurse (amongst other things). It does this
+by interpolating Perl code in the expression at run time,
+and the code can refer to the expression itself. A Perl pattern
+tern to solve the parentheses problem can be created like
+this:
+
+@example
+     $re = qr@{\( (?: (?>[^()]+) | (?p@{$re@}) )* \)@}x;
+@end example
+
+The @code{(?p@{...@})} item interpolates Perl code at run time,
+and in this case refers recursively to the pattern in which it
+appears. Obviously, @command{sed} cannot support the interpolation of
+Perl code.  Instead, the special item @code{(?R)} is provided for
+the specific case of recursion. This pattern solves the
+parentheses problem (assume the @code{X} modifier option is used
+so that white space is ignored):
+
+@example
+     \( ( (?>[^()]+) | (?R) )* \)
+@end example
+
+First it matches an opening parenthesis. Then it matches any
+number of substrings which can either be a sequence of
+non-parentheses, or a recursive match of the pattern itself
+(i.e. a correctly parenthesized substring). Finally there is
+a closing parenthesis.
+
+This particular example pattern contains nested unlimited
+repeats, and so the use of a non-backtracking subpattern for
+matching strings of non-parentheses is important when applying
+the pattern to strings that do not match. For example, when
+it is applied to
+
+@example
+     (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
+@end example
+
+it yields a ``no match'' response quickly. However, if a
+standard backtracking subpattern is not used, the match runs
+for a very long time indeed because there are so many different
+ways the @code{+} and @code{*} repeats can carve up the subject,
+and all have to be tested before failure can be reported.
+
+The values set for any capturing subpatterns are those from
+the outermost level of the recursion at which the subpattern
+value is set. If the pattern above is matched against
+
+@example
+     (ab(cd)ef)
+@end example
+
+@noindent
+the value for the capturing parentheses is @samp{ef}, which is
+the last value taken on at the top level.
+
+@node Comments
+@appendixsec Comments
+@cindex Perl-style regular expressions, comments
+
+The sequence (?# marks the start of a comment which continues
+ues up to the next closing parenthesis. Nested parentheses
+are not permitted. The characters that make up a comment
+play no part in the pattern matching at all.
+
+@cindex Perl-style regular expressions, extended
+If the @code{X} modifier option is used, an unescaped @code{#} character
+outside a character class introduces a comment that continues
+up to the next newline character in the pattern.
+@end ifset
+
+
+@page
+@node Concept Index
+@unnumbered Concept Index
+
+This is a general index of all issues discussed in this manual, with the
+exception of the @command{sed} commands and command-line options.
+
+@printindex cp
+
+@page
+@node Command and Option Index
+@unnumbered Command and Option Index
+
+This is an alphabetical list of all @command{sed} commands and command-line
+options.
+
+@printindex fn
+
+@contents
+@bye
+
+@c XXX FIXME: the term "cycle" is never defined...
Index: /tags/kBuild-0.1.4/src/sed/doc/sed.x
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/sed.x	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/sed.x	(revision 1780)
@@ -0,0 +1,313 @@
+.SH NAME
+sed \- a Stream EDitor
+.SH SYNOPSIS
+.nf
+sed [-V] [--version] [--help] [-n] [--quiet] [--silent]
+    [-l N] [--line-length=N] [-u] [--unbuffered]
+    [-r] [--regexp-extended] 
+    [-e script] [--expression=script]
+    [-f script-file] [--file=script-file]
+    [script-if-no-other-script]
+    [file...]
+.fi
+[DESCRIPTION]
+.ds sd \fIsed\fP
+.ds Sd \fISed\fP
+\*(Sd is a stream editor.
+A stream editor is used to perform basic text
+transformations on an input stream
+(a file or input from a pipeline).
+While in some ways similar to an editor which
+permits scripted edits (such as \fIed\fP),
+\*(sd works by making only one pass over the
+input(s), and is consequently more efficient.
+But it is \*(sd's ability to filter text in a pipeline
+which particularly distinguishes it from other types of
+editors.
+
+[COMMAND SYNOPSIS]
+This is just a brief synopsis of \*(sd commands to serve as
+a reminder to those who already know \*(sd;
+other documentation (such as the texinfo document)
+must be consulted for fuller descriptions.
+.SS
+Zero-address ``commands''
+.TP
+.RI :\  label
+Label for
+.B b
+and
+.B t
+commands.
+.TP
+.RI # comment
+The comment extends until the next newline (or the end of a
+.B -e
+script fragment).
+.TP
+}
+The closing bracket of a { } block.
+.SS
+Zero- or One- address commands
+.TP
+=
+Print the current line number.
+.TP
+a \e
+.TP
+.I text
+Append
+.IR text ,
+which has each embedded newline preceded by a backslash.
+.TP
+i \e
+.TP
+.I text
+Insert
+.IR text ,
+which has each embedded newline preceded by a backslash.
+.TP
+q
+Immediately quit the \*(sd script without processing
+any more input,
+except that if auto-print is not disabled
+the current pattern space will be printed.
+.TP
+Q
+Immediately quit the \*(sd script without processing
+any more input.
+.TP
+.RI r\  filename
+Append text read from
+.IR filename .
+.TP
+.RI R\  filename
+Append a line read from
+.IR filename .
+.SS
+Commands which accept address ranges
+.TP
+{
+Begin a block of commands (end with a }).
+.TP
+.RI b\  label
+Branch to
+.IR label ;
+if
+.I label
+is omitted, branch to end of script.
+.TP
+.RI t\  label
+If a s/// has done a successful substitution since the
+last input line was read and since the last t or T
+command, then branch to
+.IR label ;
+if
+.I label
+is omitted, branch to end of script.
+.TP
+.RI T\  label
+If no s/// has done a successful substitution since the
+last input line was read and since the last t or T
+command, then branch to
+.IR label ;
+if
+.I label
+is omitted, branch to end of script.
+.TP
+c \e
+.TP
+.I text
+Replace the selected lines with
+.IR text ,
+which has each embedded newline preceded by a backslash.
+.TP
+d
+Delete pattern space.
+Start next cycle.
+.TP
+D
+Delete up to the first embedded newline in the pattern space.
+Start next cycle, but skip reading from the input
+if there is still data in the pattern space.
+.TP
+h H
+Copy/append pattern space to hold space.
+.TP
+g G
+Copy/append hold space to pattern space.
+.TP
+x
+Exchange the contents of the hold and pattern spaces.
+.TP
+l
+List out the current line in a ``visually unambiguous'' form.
+.TP
+n N
+Read/append the next line of input into the pattern space.
+.TP
+p
+Print the current pattern space.
+.TP
+P
+Print up to the first embedded newline of the current pattern space.
+.TP
+.RI s/ regexp / replacement /
+Attempt to match
+.I regexp
+against the pattern space.
+If successful, replace that portion matched
+with
+.IR replacement .
+The
+.I replacement
+may contain the special character
+.B &
+to refer to that portion of the pattern space which matched,
+and the special escapes \e1 through \e9 to refer to the
+corresponding matching sub-expressions in the
+.IR regexp .
+.TP
+.RI w\  filename
+Write the current pattern space to
+.IR filename .
+.TP
+.RI W\  filename
+Write the first line of the current pattern space to
+.IR filename .
+.TP
+.RI y/ source / dest /
+Transliterate the characters in the pattern space which appear in
+.I source
+to the corresponding character in
+.IR dest .
+.SH
+Addresses
+\*(Sd commands can be given with no addresses, in which
+case the command will be executed for all input lines;
+with one address, in which case the command will only be executed
+for input lines which match that address; or with two
+addresses, in which case the command will be executed
+for all input lines which match the inclusive range of
+lines starting from the first address and continuing to
+the second address.
+Three things to note about address ranges:
+the syntax is
+.IR addr1 , addr2
+(i.e., the addresses are separated by a comma);
+the line which
+.I addr1
+matched will always be accepted,
+even if
+.I addr2
+selects an earlier line;
+and if
+.I addr2
+is a
+.IR regexp ,
+it will not be tested against the line that
+.I addr1
+matched.
+.PP
+After the address (or address-range),
+and before the command, a
+.B !
+may be inserted,
+which specifies that the command shall only be
+executed if the address (or address-range) does
+.B not
+match.
+.PP
+The following address types are supported:
+.TP
+.I number
+Match only the specified line
+.IR number .
+.TP
+.IR first ~ step
+Match every
+.IR step 'th
+line starting with line
+.IR first .
+For example, ``sed -n 1~2p'' will print all the odd-numbered lines in
+the input stream, and the address 2~5 will match every fifth line,
+starting with the second. (This is an extension.)
+.TP
+$
+Match the last line.
+.TP
+.RI / regexp /
+Match lines matching the regular expression
+.IR regexp .
+.TP
+.BI \fR\e\fPc regexp c
+Match lines matching the regular expression
+.IR regexp .
+The
+.B c
+may be any character.
+.PP
+GNU \*(sd also supports some special 2-address forms:
+.TP
+.RI 0, addr2
+Start out in "matched first address" state, until
+.I addr2
+is found.
+This is similar to
+.RI 1, addr2 ,
+except that if
+.I addr2
+matches the very first line of input the
+.RI 0, addr2
+form will be at the end of its range, whereas the
+.RI 1, addr2
+form will still be at the beginning of its range.
+.TP
+.IR addr1 ,+ N
+Will match
+.I addr1
+and the
+.I N
+lines following
+.IR addr1 .
+.TP
+.IR addr1 ,~ N
+Will match
+.I addr1
+and the lines following
+.I addr1
+until the next line whose input line number is a multiple of
+.IR N .
+
+[REGULAR EXPRESSIONS]
+POSIX.2 BREs
+.I should
+be supported, but they aren't completely because of performance
+problems.
+The
+.B \en
+sequence in a regular expression matches the newline character,
+and similarly for
+.BR \ea ,
+.BR \et ,
+and other sequences.
+
+[SEE ALSO]
+.BR awk (1),
+.BR ed (1),
+.BR grep (1),
+.BR tr (1),
+.BR perlre (1),
+sed.info,
+any of various books on \*(sd,
+.na
+the \*(sd FAQ (http://sed.sf.net/grabbag/tutorials/sedfaq.txt),
+http://sed.sf.net/grabbag/.
+
+[BUGS]
+.PP
+E-mail bug reports to
+.BR bonzini@gnu.org .
+Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.
+Also, please include the output of ``sed --version'' in the body
+of your report if at all possible.
Index: /tags/kBuild-0.1.4/src/sed/doc/stamp-vti
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/stamp-vti	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/stamp-vti	(revision 1780)
@@ -0,0 +1,4 @@
+@set UPDATED 30 January 2006
+@set UPDATED-MONTH January 2006
+@set EDITION 4.1.5
+@set VERSION 4.1.5
Index: /tags/kBuild-0.1.4/src/sed/doc/version.texi
===================================================================
--- /tags/kBuild-0.1.4/src/sed/doc/version.texi	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/doc/version.texi	(revision 1780)
@@ -0,0 +1,4 @@
+@set UPDATED 30 January 2006
+@set UPDATED-MONTH January 2006
+@set EDITION 4.1.5
+@set VERSION 4.1.5
Index: /tags/kBuild-0.1.4/src/sed/intl/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/ChangeLog	(revision 1780)
@@ -0,0 +1,4 @@
+2002-01-31  GNU  <bug-gnu-gettext@gnu.org>
+
+	* Version 0.11 released.
+
Index: /tags/kBuild-0.1.4/src/sed/intl/Makefile.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/Makefile.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/Makefile.in	(revision 1780)
@@ -0,0 +1,337 @@
+# Makefile for directory with message catalog handling in GNU NLS Utilities.
+# Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library General Public License as published
+# by the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ..
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+transform = @program_transform_name@
+libdir = @libdir@
+includedir = @includedir@
+datadir = @datadir@
+localedir = $(datadir)/locale
+gettextsrcdir = $(datadir)/gettext/intl
+aliaspath = $(localedir)
+subdir = intl
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac`
+
+l = @INTL_LIBTOOL_SUFFIX_PREFIX@
+
+AR = ar
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+RANLIB = @RANLIB@
+YACC = @INTLBISON@ -y -d
+YFLAGS = --name-prefix=__gettext
+
+DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \
+-DLIBDIR=\"$(libdir)\" -DIN_LIBINTL @DEFS@
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+HEADERS = $(COMHDRS) libgnuintl.h loadinfo.h
+COMHDRS = gmo.h gettextP.h hash-string.h plural-exp.h eval-plural.h os2compat.h
+SOURCES = $(COMSRCS) intl-compat.c
+COMSRCS = bindtextdom.c dcgettext.c dgettext.c gettext.c \
+finddomain.c loadmsgcat.c localealias.c textdomain.c l10nflist.c \
+explodename.c dcigettext.c dcngettext.c dngettext.c ngettext.c plural.y \
+plural-exp.c localcharset.c localename.c osdep.c os2compat.c
+OBJECTS = @INTLOBJS@ bindtextdom.$lo dcgettext.$lo dgettext.$lo gettext.$lo \
+finddomain.$lo loadmsgcat.$lo localealias.$lo textdomain.$lo l10nflist.$lo \
+explodename.$lo dcigettext.$lo dcngettext.$lo dngettext.$lo ngettext.$lo \
+plural.$lo plural-exp.$lo localcharset.$lo localename.$lo osdep.$lo
+GETTOBJS = intl-compat.$lo
+DISTFILES.common = Makefile.in \
+config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES)
+DISTFILES.generated = plural.c
+DISTFILES.normal = VERSION
+DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc
+DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \
+COPYING.LIB-2 gettext.h libgettext.h plural-eval.c
+
+# Libtool's library version information for libintl.
+# Before making a gettext release, the gettext maintainer must change this
+# according to the libtool documentation, section "Library interface versions".
+# Maintainers of other packages that include the intl directory must *not*
+# change these values.
+LTV_CURRENT=2
+LTV_REVISION=0
+LTV_AGE=0
+
+.SUFFIXES:
+.SUFFIXES: .c .y .o .lo .sin .sed
+.c.o:
+	$(COMPILE) $<
+.c.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) $<
+
+.y.c:
+	$(YACC) $(YFLAGS) --output $@ $<
+	rm -f $*.h
+
+.sin.sed:
+	sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $< > t-$@
+	mv t-$@ $@
+
+INCLUDES = -I.. -I. -I$(top_srcdir)/intl
+
+all: all-@USE_INCLUDED_LIBINTL@
+all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed
+all-no: all-no-@BUILD_INCLUDED_LIBINTL@
+all-no-yes: libgnuintl.$la
+all-no-no:
+
+libintl.a libgnuintl.a: $(OBJECTS)
+	rm -f $@
+	$(AR) cru $@ $(OBJECTS)
+	$(RANLIB) $@
+
+libintl.la libgnuintl.la: $(OBJECTS)
+	$(LIBTOOL) --mode=link \
+	  $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \
+	  $(OBJECTS) @LTLIBICONV@ -lc \
+	  -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \
+	  -rpath $(libdir) \
+	  -no-undefined
+
+libintl.h: libgnuintl.h
+	cp $(srcdir)/libgnuintl.h libintl.h
+
+charset.alias: config.charset
+	$(SHELL) $(srcdir)/config.charset '@host@' > t-$@
+	mv t-$@ $@
+
+check: all
+
+# This installation goal is only used in GNU gettext.  Packages which
+# only use the library should use install instead.
+
+# We must not install the libintl.h/libintl.a files if we are on a
+# system which has the GNU gettext() function in its C library or in a
+# separate library.
+# If you want to use the one which comes with this version of the
+# package, you have to use `configure --with-included-gettext'.
+install: install-exec install-data
+install-exec: all
+	if test "$(PACKAGE)" = "gettext" \
+	   && test '@INTLOBJS@' = '$(GETTOBJS)'; then \
+	  $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
+	  $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \
+	  $(LIBTOOL) --mode=install \
+	    $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \
+	else \
+	  : ; \
+	fi
+	if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \
+	  temp=$(DESTDIR)$(libdir)/t-charset.alias; \
+	  dest=$(DESTDIR)$(libdir)/charset.alias; \
+	  if test -f $(DESTDIR)$(libdir)/charset.alias; then \
+	    orig=$(DESTDIR)$(libdir)/charset.alias; \
+	    sed -f ref-add.sed $$orig > $$temp; \
+	    $(INSTALL_DATA) $$temp $$dest; \
+	    rm -f $$temp; \
+	  else \
+	    if test @GLIBC21@ = no; then \
+	      orig=charset.alias; \
+	      sed -f ref-add.sed $$orig > $$temp; \
+	      $(INSTALL_DATA) $$temp $$dest; \
+	      rm -f $$temp; \
+	    fi; \
+	  fi; \
+	  $(mkinstalldirs) $(DESTDIR)$(localedir); \
+	  test -f $(DESTDIR)$(localedir)/locale.alias \
+	    && orig=$(DESTDIR)$(localedir)/locale.alias \
+	    || orig=$(srcdir)/locale.alias; \
+	  temp=$(DESTDIR)$(localedir)/t-locale.alias; \
+	  dest=$(DESTDIR)$(localedir)/locale.alias; \
+	  sed -f ref-add.sed $$orig > $$temp; \
+	  $(INSTALL_DATA) $$temp $$dest; \
+	  rm -f $$temp; \
+	else \
+	  : ; \
+	fi
+install-data: all
+	if test "$(PACKAGE)" = "gettext"; then \
+	  $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
+	  $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \
+	  $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \
+	  dists="COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common)"; \
+	  for file in $$dists; do \
+	    $(INSTALL_DATA) $(srcdir)/$$file \
+			    $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	  chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \
+	  dists="$(DISTFILES.generated)"; \
+	  for file in $$dists; do \
+	    if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
+	    $(INSTALL_DATA) $$dir/$$file \
+			    $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	  dists="$(DISTFILES.obsolete)"; \
+	  for file in $$dists; do \
+	    rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	else \
+	  : ; \
+	fi
+
+install-strip: install
+
+installdirs:
+	if test "$(PACKAGE)" = "gettext" \
+	   && test '@INTLOBJS@' = '$(GETTOBJS)'; then \
+	  $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
+	else \
+	  : ; \
+	fi
+	if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \
+	  $(mkinstalldirs) $(DESTDIR)$(localedir); \
+	else \
+	  : ; \
+	fi
+	if test "$(PACKAGE)" = "gettext"; then \
+	  $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
+	else \
+	  : ; \
+	fi
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+	if test "$(PACKAGE)" = "gettext" \
+	   && test '@INTLOBJS@' = '$(GETTOBJS)'; then \
+	  rm -f $(DESTDIR)$(includedir)/libintl.h; \
+	  $(LIBTOOL) --mode=uninstall \
+	    rm -f $(DESTDIR)$(libdir)/libintl.$la; \
+	else \
+	  : ; \
+	fi
+	if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+	  if test -f $(DESTDIR)$(libdir)/charset.alias; then \
+	    temp=$(DESTDIR)$(libdir)/t-charset.alias; \
+	    dest=$(DESTDIR)$(libdir)/charset.alias; \
+	    sed -f ref-del.sed $$dest > $$temp; \
+	    if grep '^# Packages using this file: $$' $$temp > /dev/null; then \
+	      rm -f $$dest; \
+	    else \
+	      $(INSTALL_DATA) $$temp $$dest; \
+	    fi; \
+	    rm -f $$temp; \
+	  fi; \
+	  if test -f $(DESTDIR)$(localedir)/locale.alias; then \
+	    temp=$(DESTDIR)$(localedir)/t-locale.alias; \
+	    dest=$(DESTDIR)$(localedir)/locale.alias; \
+	    sed -f ref-del.sed $$dest > $$temp; \
+	    if grep '^# Packages using this file: $$' $$temp > /dev/null; then \
+	      rm -f $$dest; \
+	    else \
+	      $(INSTALL_DATA) $$temp $$dest; \
+	    fi; \
+	    rm -f $$temp; \
+	  fi; \
+	else \
+	  : ; \
+	fi
+	if test "$(PACKAGE)" = "gettext"; then \
+	  for file in VERSION ChangeLog COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \
+	    rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	else \
+	  : ; \
+	fi
+
+info dvi:
+
+$(OBJECTS): ../config.h libgnuintl.h
+bindtextdom.$lo dcgettext.$lo dcigettext.$lo dcngettext.$lo dgettext.$lo dngettext.$lo finddomain.$lo gettext.$lo intl-compat.$lo loadmsgcat.$lo localealias.$lo ngettext.$lo textdomain.$lo: gettextP.h gmo.h loadinfo.h
+dcigettext.$lo: hash-string.h
+explodename.$lo l10nflist.$lo: loadinfo.h
+dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: plural-exp.h
+dcigettext.$lo: eval-plural.h
+
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES)
+	here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES)
+
+id: ID
+
+ID: $(HEADERS) $(SOURCES)
+	here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES)
+
+
+mostlyclean:
+	rm -f *.a *.la *.o *.lo core core.*
+	rm -f libintl.h charset.alias ref-add.sed ref-del.sed
+	rm -f -r .libs _libs
+
+clean: mostlyclean
+
+distclean: clean
+	rm -f Makefile ID TAGS
+	if test "$(PACKAGE)" = gettext; then \
+	  rm -f ChangeLog.inst $(DISTFILES.normal); \
+	else \
+	  : ; \
+	fi
+
+maintainer-clean: distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+
+# GNU gettext needs not contain the file `VERSION' but contains some
+# other files which should not be distributed in other packages.
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: Makefile
+	if test "$(PACKAGE)" = gettext; then \
+	  additional="$(DISTFILES.gettext)"; \
+	else \
+	  additional="$(DISTFILES.normal)"; \
+	fi; \
+	$(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \
+	for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \
+	  if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
+	  cp -p $$dir/$$file $(distdir); \
+	done
+
+Makefile: Makefile.in ../config.status
+	cd .. \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /tags/kBuild-0.1.4/src/sed/intl/VERSION
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/VERSION	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/VERSION	(revision 1780)
@@ -0,0 +1,1 @@
+GNU gettext library from gettext-0.11
Index: /tags/kBuild-0.1.4/src/sed/intl/bindtextdom.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/bindtextdom.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/bindtextdom.c	(revision 1780)
@@ -0,0 +1,369 @@
+/* Implementation of the bindtextdomain(3) function
+   Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "gettextP.h"
+
+#ifdef _LIBC
+/* We have to handle multi-threaded applications.  */
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_rwlock_define(CLASS, NAME)
+# define __libc_rwlock_wrlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#endif
+
+/* The internal variables in the standalone libintl.a must have different
+   names than the internal variables in GNU libc, otherwise programs
+   using libintl.a cannot be linked statically.  */
+#if !defined _LIBC
+# define _nl_default_dirname _nl_default_dirname__
+# define _nl_domain_bindings _nl_domain_bindings__
+#endif
+
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Contains the default location of the message catalogs.  */
+extern const char _nl_default_dirname[];
+
+/* List with bindings of specific domains.  */
+extern struct binding *_nl_domain_bindings;
+
+/* Lock variable to protect the global data in the gettext implementation.  */
+__libc_rwlock_define (extern, _nl_state_lock)
+
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define BINDTEXTDOMAIN __bindtextdomain
+# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
+# ifndef strdup
+#  define strdup(str) __strdup (str)
+# endif
+#else
+# define BINDTEXTDOMAIN bindtextdomain__
+# define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
+#endif
+
+/* Prototypes for local functions.  */
+static void set_binding_values PARAMS ((const char *domainname,
+					const char **dirnamep,
+					const char **codesetp));
+
+/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
+   to be used for the DOMAINNAME message catalog.
+   If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
+   modified, only the current value is returned.
+   If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
+   modified nor returned.  */
+static void
+set_binding_values (domainname, dirnamep, codesetp)
+     const char *domainname;
+     const char **dirnamep;
+     const char **codesetp;
+{
+  struct binding *binding;
+  int modified;
+
+  /* Some sanity checks.  */
+  if (domainname == NULL || domainname[0] == '\0')
+    {
+      if (dirnamep)
+	*dirnamep = NULL;
+      if (codesetp)
+	*codesetp = NULL;
+      return;
+    }
+
+  __libc_rwlock_wrlock (_nl_state_lock);
+
+  modified = 0;
+
+  for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
+    {
+      int compare = strcmp (domainname, binding->domainname);
+      if (compare == 0)
+	/* We found it!  */
+	break;
+      if (compare < 0)
+	{
+	  /* It is not in the list.  */
+	  binding = NULL;
+	  break;
+	}
+    }
+
+  if (binding != NULL)
+    {
+      if (dirnamep)
+	{
+	  const char *dirname = *dirnamep;
+
+	  if (dirname == NULL)
+	    /* The current binding has be to returned.  */
+	    *dirnamep = binding->dirname;
+	  else
+	    {
+	      /* The domain is already bound.  If the new value and the old
+		 one are equal we simply do nothing.  Otherwise replace the
+		 old binding.  */
+	      char *result = binding->dirname;
+	      if (strcmp (dirname, result) != 0)
+		{
+		  if (strcmp (dirname, _nl_default_dirname) == 0)
+		    result = (char *) _nl_default_dirname;
+		  else
+		    {
+#if defined _LIBC || defined HAVE_STRDUP
+		      result = strdup (dirname);
+#else
+		      size_t len = strlen (dirname) + 1;
+		      result = (char *) malloc (len);
+		      if (__builtin_expect (result != NULL, 1))
+			memcpy (result, dirname, len);
+#endif
+		    }
+
+		  if (__builtin_expect (result != NULL, 1))
+		    {
+		      if (binding->dirname != _nl_default_dirname)
+			free (binding->dirname);
+
+		      binding->dirname = result;
+		      modified = 1;
+		    }
+		}
+	      *dirnamep = result;
+	    }
+	}
+
+      if (codesetp)
+	{
+	  const char *codeset = *codesetp;
+
+	  if (codeset == NULL)
+	    /* The current binding has be to returned.  */
+	    *codesetp = binding->codeset;
+	  else
+	    {
+	      /* The domain is already bound.  If the new value and the old
+		 one are equal we simply do nothing.  Otherwise replace the
+		 old binding.  */
+	      char *result = binding->codeset;
+	      if (result == NULL || strcmp (codeset, result) != 0)
+		{
+#if defined _LIBC || defined HAVE_STRDUP
+		  result = strdup (codeset);
+#else
+		  size_t len = strlen (codeset) + 1;
+		  result = (char *) malloc (len);
+		  if (__builtin_expect (result != NULL, 1))
+		    memcpy (result, codeset, len);
+#endif
+
+		  if (__builtin_expect (result != NULL, 1))
+		    {
+		      if (binding->codeset != NULL)
+			free (binding->codeset);
+
+		      binding->codeset = result;
+		      binding->codeset_cntr++;
+		      modified = 1;
+		    }
+		}
+	      *codesetp = result;
+	    }
+	}
+    }
+  else if ((dirnamep == NULL || *dirnamep == NULL)
+	   && (codesetp == NULL || *codesetp == NULL))
+    {
+      /* Simply return the default values.  */
+      if (dirnamep)
+	*dirnamep = _nl_default_dirname;
+      if (codesetp)
+	*codesetp = NULL;
+    }
+  else
+    {
+      /* We have to create a new binding.  */
+      size_t len = strlen (domainname) + 1;
+      struct binding *new_binding =
+	(struct binding *) malloc (offsetof (struct binding, domainname) + len);
+
+      if (__builtin_expect (new_binding == NULL, 0))
+	goto failed;
+
+      memcpy (new_binding->domainname, domainname, len);
+
+      if (dirnamep)
+	{
+	  const char *dirname = *dirnamep;
+
+	  if (dirname == NULL)
+	    /* The default value.  */
+	    dirname = _nl_default_dirname;
+	  else
+	    {
+	      if (strcmp (dirname, _nl_default_dirname) == 0)
+		dirname = _nl_default_dirname;
+	      else
+		{
+		  char *result;
+#if defined _LIBC || defined HAVE_STRDUP
+		  result = strdup (dirname);
+		  if (__builtin_expect (result == NULL, 0))
+		    goto failed_dirname;
+#else
+		  size_t len = strlen (dirname) + 1;
+		  result = (char *) malloc (len);
+		  if (__builtin_expect (result == NULL, 0))
+		    goto failed_dirname;
+		  memcpy (result, dirname, len);
+#endif
+		  dirname = result;
+		}
+	    }
+	  *dirnamep = dirname;
+	  new_binding->dirname = (char *) dirname;
+	}
+      else
+	/* The default value.  */
+	new_binding->dirname = (char *) _nl_default_dirname;
+
+      new_binding->codeset_cntr = 0;
+
+      if (codesetp)
+	{
+	  const char *codeset = *codesetp;
+
+	  if (codeset != NULL)
+	    {
+	      char *result;
+
+#if defined _LIBC || defined HAVE_STRDUP
+	      result = strdup (codeset);
+	      if (__builtin_expect (result == NULL, 0))
+		goto failed_codeset;
+#else
+	      size_t len = strlen (codeset) + 1;
+	      result = (char *) malloc (len);
+	      if (__builtin_expect (result == NULL, 0))
+		goto failed_codeset;
+	      memcpy (result, codeset, len);
+#endif
+	      codeset = result;
+	      new_binding->codeset_cntr++;
+	    }
+	  *codesetp = codeset;
+	  new_binding->codeset = (char *) codeset;
+	}
+      else
+	new_binding->codeset = NULL;
+
+      /* Now enqueue it.  */
+      if (_nl_domain_bindings == NULL
+	  || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
+	{
+	  new_binding->next = _nl_domain_bindings;
+	  _nl_domain_bindings = new_binding;
+	}
+      else
+	{
+	  binding = _nl_domain_bindings;
+	  while (binding->next != NULL
+		 && strcmp (domainname, binding->next->domainname) > 0)
+	    binding = binding->next;
+
+	  new_binding->next = binding->next;
+	  binding->next = new_binding;
+	}
+
+      modified = 1;
+
+      /* Here we deal with memory allocation failures.  */
+      if (0)
+	{
+	failed_codeset:
+	  if (new_binding->dirname != _nl_default_dirname)
+	    free (new_binding->dirname);
+	failed_dirname:
+	  free (new_binding);
+	failed:
+	  if (dirnamep)
+	    *dirnamep = NULL;
+	  if (codesetp)
+	    *codesetp = NULL;
+	}
+    }
+
+  /* If we modified any binding, we flush the caches.  */
+  if (modified)
+    ++_nl_msg_cat_cntr;
+
+  __libc_rwlock_unlock (_nl_state_lock);
+}
+
+/* Specify that the DOMAINNAME message catalog will be found
+   in DIRNAME rather than in the system locale data base.  */
+char *
+BINDTEXTDOMAIN (domainname, dirname)
+     const char *domainname;
+     const char *dirname;
+{
+  set_binding_values (domainname, &dirname, NULL);
+  return (char *) dirname;
+}
+
+/* Specify the character encoding in which the messages from the
+   DOMAINNAME message catalog will be returned.  */
+char *
+BIND_TEXTDOMAIN_CODESET (domainname, codeset)
+     const char *domainname;
+     const char *codeset;
+{
+  set_binding_values (domainname, NULL, &codeset);
+  return (char *) codeset;
+}
+
+#ifdef _LIBC
+/* Aliases for function names in GNU C Library.  */
+weak_alias (__bindtextdomain, bindtextdomain);
+weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/config.charset
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/config.charset	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/config.charset	(revision 1780)
@@ -0,0 +1,440 @@
+#! /bin/sh
+# Output a system dependent table of character encoding aliases.
+#
+#   Copyright (C) 2000-2002 Free Software Foundation, Inc.
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU Library General Public License as published
+#   by the Free Software Foundation; either version 2, or (at your option)
+#   any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#   Library General Public License for more details.
+#
+#   You should have received a copy of the GNU Library General Public
+#   License along with this program; if not, write to the Free Software
+#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+#   USA.
+#
+# The table consists of lines of the form
+#    ALIAS  CANONICAL
+#
+# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)".
+# ALIAS is compared in a case sensitive way.
+#
+# CANONICAL is the GNU canonical name for this character encoding.
+# It must be an encoding supported by libiconv. Support by GNU libc is
+# also desirable. CANONICAL is case insensitive. Usually an upper case
+# MIME charset name is preferred.
+# The current list of GNU canonical charset names is as follows.
+#
+#       name                         used by which systems         a MIME name?
+#   ASCII, ANSI_X3.4-1968     glibc solaris freebsd
+#   ISO-8859-1                glibc aix hpux irix osf solaris freebsd   yes
+#   ISO-8859-2                glibc aix hpux irix osf solaris freebsd   yes
+#   ISO-8859-3                glibc                                     yes
+#   ISO-8859-4                osf solaris freebsd                       yes
+#   ISO-8859-5                glibc aix hpux irix osf solaris freebsd   yes
+#   ISO-8859-6                glibc aix hpux solaris                    yes
+#   ISO-8859-7                glibc aix hpux irix osf solaris           yes
+#   ISO-8859-8                glibc aix hpux osf solaris                yes
+#   ISO-8859-9                glibc aix hpux irix osf solaris           yes
+#   ISO-8859-13               glibc
+#   ISO-8859-15               glibc aix osf solaris freebsd
+#   KOI8-R                    glibc solaris freebsd                     yes
+#   KOI8-U                    glibc freebsd                             yes
+#   CP437                     dos
+#   CP775                     dos
+#   CP850                     aix osf dos
+#   CP852                     dos
+#   CP855                     dos
+#   CP856                     aix
+#   CP857                     dos
+#   CP861                     dos
+#   CP862                     dos
+#   CP864                     dos
+#   CP865                     dos
+#   CP866                     freebsd dos
+#   CP869                     dos
+#   CP874                     win32 dos
+#   CP922                     aix
+#   CP932                     aix win32 dos
+#   CP943                     aix
+#   CP949                     osf win32 dos
+#   CP950                     win32 dos
+#   CP1046                    aix
+#   CP1124                    aix
+#   CP1129                    aix
+#   CP1250                    win32
+#   CP1251                    glibc win32
+#   CP1252                    aix win32
+#   CP1253                    win32
+#   CP1254                    win32
+#   CP1255                    win32
+#   CP1256                    win32
+#   CP1257                    win32
+#   GB2312                    glibc aix hpux irix solaris freebsd       yes
+#   EUC-JP                    glibc aix hpux irix osf solaris freebsd   yes
+#   EUC-KR                    glibc aix hpux irix osf solaris freebsd   yes
+#   EUC-TW                    glibc aix hpux irix osf solaris
+#   BIG5                      glibc aix hpux osf solaris freebsd        yes
+#   BIG5-HKSCS                glibc
+#   GBK                       aix osf win32 dos
+#   GB18030                   glibc
+#   SHIFT_JIS                 hpux osf solaris freebsd                  yes
+#   JOHAB                     glibc win32
+#   TIS-620                   glibc aix hpux osf solaris
+#   VISCII                    glibc                                     yes
+#   HP-ROMAN8                 hpux
+#   HP-ARABIC8                hpux
+#   HP-GREEK8                 hpux
+#   HP-HEBREW8                hpux
+#   HP-TURKISH8               hpux
+#   HP-KANA8                  hpux
+#   DEC-KANJI                 osf
+#   DEC-HANYU                 osf
+#   UTF-8                     glibc aix hpux osf solaris                yes
+#
+# Note: Names which are not marked as being a MIME name should not be used in
+# Internet protocols for information interchange (mail, news, etc.).
+#
+# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
+# must understand both names and treat them as equivalent.
+#
+# The first argument passed to this file is the canonical host specification,
+#    CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+#    CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+
+host="$1"
+os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'`
+echo "# This file contains a table of character encoding aliases,"
+echo "# suitable for operating system '${os}'."
+echo "# It was automatically generated from config.charset."
+# List of references, updated during installation:
+echo "# Packages using this file: "
+case "$os" in
+    linux* | *-gnu*)
+	# With glibc-2.1 or newer, we don't need any canonicalization,
+	# because glibc has iconv and both glibc and libiconv support all
+	# GNU canonical names directly. Therefore, the Makefile does not
+	# need to install the alias file at all.
+	# The following applies only to glibc-2.0.x and older libcs.
+	echo "ISO_646.IRV:1983 ASCII"
+	;;
+    aix*)
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-6 ISO-8859-6"
+	echo "ISO8859-7 ISO-8859-7"
+	echo "ISO8859-8 ISO-8859-8"
+	echo "ISO8859-9 ISO-8859-9"
+	echo "ISO8859-15 ISO-8859-15"
+	echo "IBM-850 CP850"
+	echo "IBM-856 CP856"
+	echo "IBM-921 ISO-8859-13"
+	echo "IBM-922 CP922"
+	echo "IBM-932 CP932"
+	echo "IBM-943 CP943"
+	echo "IBM-1046 CP1046"
+	echo "IBM-1124 CP1124"
+	echo "IBM-1129 CP1129"
+	echo "IBM-1252 CP1252"
+	echo "IBM-eucCN GB2312"
+	echo "IBM-eucJP EUC-JP"
+	echo "IBM-eucKR EUC-KR"
+	echo "IBM-eucTW EUC-TW"
+	echo "big5 BIG5"
+	echo "GBK GBK"
+	echo "TIS-620 TIS-620"
+	echo "UTF-8 UTF-8"
+	;;
+    hpux*)
+	echo "iso88591 ISO-8859-1"
+	echo "iso88592 ISO-8859-2"
+	echo "iso88595 ISO-8859-5"
+	echo "iso88596 ISO-8859-6"
+	echo "iso88597 ISO-8859-7"
+	echo "iso88598 ISO-8859-8"
+	echo "iso88599 ISO-8859-9"
+	echo "iso885915 ISO-8859-15"
+	echo "roman8 HP-ROMAN8"
+	echo "arabic8 HP-ARABIC8"
+	echo "greek8 HP-GREEK8"
+	echo "hebrew8 HP-HEBREW8"
+	echo "turkish8 HP-TURKISH8"
+	echo "kana8 HP-KANA8"
+	echo "tis620 TIS-620"
+	echo "big5 BIG5"
+	echo "eucJP EUC-JP"
+	echo "eucKR EUC-KR"
+	echo "eucTW EUC-TW"
+	echo "hp15CN GB2312"
+	#echo "ccdc ?" # what is this?
+	echo "SJIS SHIFT_JIS"
+	echo "utf8 UTF-8"
+	;;
+    irix*)
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-7 ISO-8859-7"
+	echo "ISO8859-9 ISO-8859-9"
+	echo "eucCN GB2312"
+	echo "eucJP EUC-JP"
+	echo "eucKR EUC-KR"
+	echo "eucTW EUC-TW"
+	;;
+    osf*)
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-4 ISO-8859-4"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-7 ISO-8859-7"
+	echo "ISO8859-8 ISO-8859-8"
+	echo "ISO8859-9 ISO-8859-9"
+	echo "ISO8859-15 ISO-8859-15"
+	echo "cp850 CP850"
+	echo "big5 BIG5"
+	echo "dechanyu DEC-HANYU"
+	echo "dechanzi GB2312"
+	echo "deckanji DEC-KANJI"
+	echo "deckorean EUC-KR"
+	echo "eucJP EUC-JP"
+	echo "eucKR EUC-KR"
+	echo "eucTW EUC-TW"
+	echo "GBK GBK"
+	echo "KSC5601 CP949"
+	echo "sdeckanji EUC-JP"
+	echo "SJIS SHIFT_JIS"
+	echo "TACTIS TIS-620"
+	echo "UTF-8 UTF-8"
+	;;
+    solaris*)
+	echo "646 ASCII"
+	echo "ISO8859-1 ISO-8859-1"
+	echo "ISO8859-2 ISO-8859-2"
+	echo "ISO8859-4 ISO-8859-4"
+	echo "ISO8859-5 ISO-8859-5"
+	echo "ISO8859-6 ISO-8859-6"
+	echo "ISO8859-7 ISO-8859-7"
+	echo "ISO8859-8 ISO-8859-8"
+	echo "ISO8859-9 ISO-8859-9"
+	echo "ISO8859-15 ISO-8859-15"
+	echo "koi8-r KOI8-R"
+	echo "BIG5 BIG5"
+	echo "gb2312 GB2312"
+	echo "cns11643 EUC-TW"
+	echo "5601 EUC-KR"
+	echo "eucJP EUC-JP"
+	echo "PCK SHIFT_JIS"
+	echo "TIS620.2533 TIS-620"
+	#echo "sun_eu_greek ?" # what is this?
+	echo "UTF-8 UTF-8"
+	;;
+    freebsd* | os2*)
+	# FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore
+	# localcharset.c falls back to using the full locale name
+	# from the environment variables.
+	# Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just
+	# reuse FreeBSD's locale data for OS/2.
+	echo "C ASCII"
+	echo "US-ASCII ASCII"
+	for l in la_LN lt_LN; do
+	  echo "$l.ASCII ASCII"
+	done
+	for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
+	         fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \
+	         lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do
+	  echo "$l.ISO_8859-1 ISO-8859-1"
+	  echo "$l.DIS_8859-15 ISO-8859-15"
+	done
+	for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do
+	  echo "$l.ISO_8859-2 ISO-8859-2"
+	done
+	for l in la_LN lt_LT; do
+	  echo "$l.ISO_8859-4 ISO-8859-4"
+	done
+	for l in ru_RU ru_SU; do
+	  echo "$l.KOI8-R KOI8-R"
+	  echo "$l.ISO_8859-5 ISO-8859-5"
+	  echo "$l.CP866 CP866"
+	done
+	echo "uk_UA.KOI8-U KOI8-U"
+	echo "zh_TW.BIG5 BIG5"
+	echo "zh_TW.Big5 BIG5"
+	echo "zh_CN.EUC GB2312"
+	echo "ja_JP.EUC EUC-JP"
+	echo "ja_JP.SJIS SHIFT_JIS"
+	echo "ja_JP.Shift_JIS SHIFT_JIS"
+	echo "ko_KR.EUC EUC-KR"
+	;;
+    beos*)
+	# BeOS has a single locale, and it has UTF-8 encoding.
+	echo "* UTF-8"
+	;;
+    msdosdjgpp*)
+	# DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore
+	# localcharset.c falls back to using the full locale name
+	# from the environment variables.
+	echo "#"
+	echo "# The encodings given here may not all be correct."
+	echo "# If you find that the encoding given for your language and"
+	echo "# country is not the one your DOS machine actually uses, just"
+	echo "# correct it in this file, and send a mail to"
+	echo "# Juan Manuel Guerrero <st001906@hrz1.hrz.tu-darmstadt.de>"
+	echo "# and Bruno Haible <haible@clisp.cons.org>."
+	echo "#"
+	echo "C ASCII"
+	# ISO-8859-1 languages
+	echo "ca CP850"
+	echo "ca_ES CP850"
+	echo "da CP865"    # not CP850 ??
+	echo "da_DK CP865" # not CP850 ??
+	echo "de CP850"
+	echo "de_AT CP850"
+	echo "de_CH CP850"
+	echo "de_DE CP850"
+	echo "en CP850"
+	echo "en_AU CP850" # not CP437 ??
+	echo "en_CA CP850"
+	echo "en_GB CP850"
+	echo "en_NZ CP437"
+	echo "en_US CP437"
+	echo "en_ZA CP850" # not CP437 ??
+	echo "es CP850"
+	echo "es_AR CP850"
+	echo "es_BO CP850"
+	echo "es_CL CP850"
+	echo "es_CO CP850"
+	echo "es_CR CP850"
+	echo "es_CU CP850"
+	echo "es_DO CP850"
+	echo "es_EC CP850"
+	echo "es_ES CP850"
+	echo "es_GT CP850"
+	echo "es_HN CP850"
+	echo "es_MX CP850"
+	echo "es_NI CP850"
+	echo "es_PA CP850"
+	echo "es_PY CP850"
+	echo "es_PE CP850"
+	echo "es_SV CP850"
+	echo "es_UY CP850"
+	echo "es_VE CP850"
+	echo "et CP850"
+	echo "et_EE CP850"
+	echo "eu CP850"
+	echo "eu_ES CP850"
+	echo "fi CP850"
+	echo "fi_FI CP850"
+	echo "fr CP850"
+	echo "fr_BE CP850"
+	echo "fr_CA CP850"
+	echo "fr_CH CP850"
+	echo "fr_FR CP850"
+	echo "ga CP850"
+	echo "ga_IE CP850"
+	echo "gd CP850"
+	echo "gd_GB CP850"
+	echo "gl CP850"
+	echo "gl_ES CP850"
+	echo "id CP850"    # not CP437 ??
+	echo "id_ID CP850" # not CP437 ??
+	echo "is CP861"    # not CP850 ??
+	echo "is_IS CP861" # not CP850 ??
+	echo "it CP850"
+	echo "it_CH CP850"
+	echo "it_IT CP850"
+	echo "lt CP775"
+	echo "lt_LT CP775"
+	echo "lv CP775"
+	echo "lv_LV CP775"
+	echo "nb CP865"    # not CP850 ??
+	echo "nb_NO CP865" # not CP850 ??
+	echo "nl CP850"
+	echo "nl_BE CP850"
+	echo "nl_NL CP850"
+	echo "nn CP865"    # not CP850 ??
+	echo "nn_NO CP865" # not CP850 ??
+	echo "no CP865"    # not CP850 ??
+	echo "no_NO CP865" # not CP850 ??
+	echo "pt CP850"
+	echo "pt_BR CP850"
+	echo "pt_PT CP850"
+	echo "sv CP850"
+	echo "sv_SE CP850"
+	# ISO-8859-2 languages
+	echo "cs CP852"
+	echo "cs_CZ CP852"
+	echo "hr CP852"
+	echo "hr_HR CP852"
+	echo "hu CP852"
+	echo "hu_HU CP852"
+	echo "pl CP852"
+	echo "pl_PL CP852"
+	echo "ro CP852"
+	echo "ro_RO CP852"
+	echo "sk CP852"
+	echo "sk_SK CP852"
+	echo "sl CP852"
+	echo "sl_SI CP852"
+	echo "sq CP852"
+	echo "sq_AL CP852"
+	echo "sr CP852"    # CP852 or CP866 or CP855 ??
+	echo "sr_YU CP852" # CP852 or CP866 or CP855 ??
+	# ISO-8859-3 languages
+	echo "mt CP850"
+	echo "mt_MT CP850"
+	# ISO-8859-5 languages
+	echo "be CP866"
+	echo "be_BE CP866"
+	echo "bg CP866"    # not CP855 ??
+	echo "bg_BG CP866" # not CP855 ??
+	echo "mk CP866"    # not CP855 ??
+	echo "mk_MK CP866" # not CP855 ??
+	echo "ru KOI8-R"    # not CP866 ??
+	echo "ru_RU KOI8-R" # not CP866 ??
+	# ISO-8859-6 languages
+	echo "ar CP864"
+	echo "ar_AE CP864"
+	echo "ar_DZ CP864"
+	echo "ar_EG CP864"
+	echo "ar_IQ CP864"
+	echo "ar_IR CP864"
+	echo "ar_JO CP864"
+	echo "ar_KW CP864"
+	echo "ar_MA CP864"
+	echo "ar_OM CP864"
+	echo "ar_QA CP864"
+	echo "ar_SA CP864"
+	echo "ar_SY CP864"
+	# ISO-8859-7 languages
+	echo "el CP869"
+	echo "el_GR CP869"
+	# ISO-8859-8 languages
+	echo "he CP862"
+	echo "he_IL CP862"
+	# ISO-8859-9 languages
+	echo "tr CP857"
+	echo "tr_TR CP857"
+	# Japanese
+	echo "ja CP932"
+	echo "ja_JP CP932"
+	# Chinese
+	echo "zh_CN GBK"
+	echo "zh_TW CP950" # not CP938 ??
+	# Korean
+	echo "kr CP949"    # not CP934 ??
+	echo "kr_KR CP949" # not CP934 ??
+	# Thai
+	echo "th CP874"
+	echo "th_TH CP874"
+	# Other
+	echo "eo CP850"
+	echo "eo_EO CP850"
+	;;
+esac
Index: /tags/kBuild-0.1.4/src/sed/intl/dcgettext.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/dcgettext.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/dcgettext.c	(revision 1780)
@@ -0,0 +1,58 @@
+/* Implementation of the dcgettext(3) function.
+   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define DCGETTEXT __dcgettext
+# define DCIGETTEXT __dcigettext
+#else
+# define DCGETTEXT dcgettext__
+# define DCIGETTEXT dcigettext__
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+   locale.  */
+char *
+DCGETTEXT (domainname, msgid, category)
+     const char *domainname;
+     const char *msgid;
+     int category;
+{
+  return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__dcgettext, dcgettext);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/dcigettext.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/dcigettext.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/dcigettext.c	(revision 1780)
@@ -0,0 +1,1167 @@
+/* Implementation of the internal dcigettext function.
+   Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include <locale.h>
+
+#if defined HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+
+#include "gettextP.h"
+#include "plural-exp.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "hash-string.h"
+
+/* Thread safetyness.  */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_lock_define_initialized(CLASS, NAME)
+# define __libc_lock_lock(NAME)
+# define __libc_lock_unlock(NAME)
+# define __libc_rwlock_define_initialized(CLASS, NAME)
+# define __libc_rwlock_rdlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#endif
+
+/* Alignment of types.  */
+#if defined __GNUC__ && __GNUC__ >= 2
+# define alignof(TYPE) __alignof__ (TYPE)
+#else
+# define alignof(TYPE) \
+    ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
+#endif
+
+/* The internal variables in the standalone libintl.a must have different
+   names than the internal variables in GNU libc, otherwise programs
+   using libintl.a cannot be linked statically.  */
+#if !defined _LIBC
+# define _nl_default_default_domain _nl_default_default_domain__
+# define _nl_current_default_domain _nl_current_default_domain__
+# define _nl_default_dirname _nl_default_dirname__
+# define _nl_domain_bindings _nl_domain_bindings__
+#endif
+
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions.  This is required by the standard
+   because some ANSI C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# define getcwd __getcwd
+# ifndef stpcpy
+#  define stpcpy __stpcpy
+# endif
+# define tfind __tfind
+#else
+# if !defined HAVE_GETCWD
+char *getwd ();
+#  define getcwd(buf, max) getwd (buf)
+# else
+char *getcwd ();
+# endif
+# ifndef HAVE_STPCPY
+static char *stpcpy PARAMS ((char *dest, const char *src));
+# endif
+# ifndef HAVE_MEMPCPY
+static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
+# endif
+#endif
+
+/* Amount to increase buffer size by in each try.  */
+#define PATH_INCR 32
+
+/* The following is from pathmax.h.  */
+/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
+   PATH_MAX but might cause redefinition warnings when sys/param.h is
+   later included (as on MORE/BSD 4.3).  */
+#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
+# include <limits.h>
+#endif
+
+#ifndef _POSIX_PATH_MAX
+# define _POSIX_PATH_MAX 255
+#endif
+
+#if !defined PATH_MAX && defined _PC_PATH_MAX
+# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
+#endif
+
+/* Don't include sys/param.h if it already has been.  */
+#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
+# include <sys/param.h>
+#endif
+
+#if !defined PATH_MAX && defined MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+/* Pathname support.
+   ISSLASH(C)           tests whether C is a directory separator character.
+   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
+                        it may be concatenated to a directory pathname.
+   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+     && (P)[1] == ':')
+# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
+# define IS_PATH_WITH_DIR(P) \
+    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+#else
+  /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+#endif
+
+/* This is the type used for the search tree where known translations
+   are stored.  */
+struct known_translation_t
+{
+  /* Domain in which to search.  */
+  char *domainname;
+
+  /* The category.  */
+  int category;
+
+  /* State of the catalog counter at the point the string was found.  */
+  int counter;
+
+  /* Catalog where the string was found.  */
+  struct loaded_l10nfile *domain;
+
+  /* And finally the translation.  */
+  const char *translation;
+  size_t translation_length;
+
+  /* Pointer to the string in question.  */
+  char msgid[ZERO];
+};
+
+/* Root of the search tree with known translations.  We can use this
+   only if the system provides the `tsearch' function family.  */
+#if defined HAVE_TSEARCH || defined _LIBC
+# include <search.h>
+
+static void *root;
+
+# ifdef _LIBC
+#  define tsearch __tsearch
+# endif
+
+/* Function to compare two entries in the table of known translations.  */
+static int transcmp PARAMS ((const void *p1, const void *p2));
+static int
+transcmp (p1, p2)
+     const void *p1;
+     const void *p2;
+{
+  const struct known_translation_t *s1;
+  const struct known_translation_t *s2;
+  int result;
+
+  s1 = (const struct known_translation_t *) p1;
+  s2 = (const struct known_translation_t *) p2;
+
+  result = strcmp (s1->msgid, s2->msgid);
+  if (result == 0)
+    {
+      result = strcmp (s1->domainname, s2->domainname);
+      if (result == 0)
+	/* We compare the category last (though this is the cheapest
+	   operation) since it is hopefully always the same (namely
+	   LC_MESSAGES).  */
+	result = s1->category - s2->category;
+    }
+
+  return result;
+}
+#endif
+
+/* Name of the default domain used for gettext(3) prior any call to
+   textdomain(3).  The default value for this is "messages".  */
+const char _nl_default_default_domain[] = "messages";
+
+/* Value used as the default domain for gettext(3).  */
+const char *_nl_current_default_domain = _nl_default_default_domain;
+
+/* Contains the default location of the message catalogs.  */
+#if defined __EMX__
+extern const char _nl_default_dirname[];
+#else
+const char _nl_default_dirname[] = LOCALEDIR;
+#endif
+
+/* List with bindings of specific domains created by bindtextdomain()
+   calls.  */
+struct binding *_nl_domain_bindings;
+
+/* Prototypes for local functions.  */
+static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
+				    unsigned long int n,
+				    const char *translation,
+				    size_t translation_len))
+     internal_function;
+static const char *category_to_name PARAMS ((int category)) internal_function;
+static const char *guess_category_value PARAMS ((int category,
+						 const char *categoryname))
+     internal_function;
+
+
+/* For those loosing systems which don't have `alloca' we have to add
+   some additional code emulating it.  */
+#ifdef HAVE_ALLOCA
+/* Nothing has to be done.  */
+# define ADD_BLOCK(list, address) /* nothing */
+# define FREE_BLOCKS(list) /* nothing */
+#else
+struct block_list
+{
+  void *address;
+  struct block_list *next;
+};
+# define ADD_BLOCK(list, addr)						      \
+  do {									      \
+    struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
+    /* If we cannot get a free block we cannot add the new element to	      \
+       the list.  */							      \
+    if (newp != NULL) {							      \
+      newp->address = (addr);						      \
+      newp->next = (list);						      \
+      (list) = newp;							      \
+    }									      \
+  } while (0)
+# define FREE_BLOCKS(list)						      \
+  do {									      \
+    while (list != NULL) {						      \
+      struct block_list *old = list;					      \
+      list = list->next;						      \
+      free (old);							      \
+    }									      \
+  } while (0)
+# undef alloca
+# define alloca(size) (malloc (size))
+#endif	/* have alloca */
+
+
+#ifdef _LIBC
+/* List of blocks allocated for translations.  */
+typedef struct transmem_list
+{
+  struct transmem_list *next;
+  char data[ZERO];
+} transmem_block_t;
+static struct transmem_list *transmem_list;
+#else
+typedef unsigned char transmem_block_t;
+#endif
+
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define DCIGETTEXT __dcigettext
+#else
+# define DCIGETTEXT dcigettext__
+#endif
+
+/* Lock variable to protect the global data in the gettext implementation.  */
+#ifdef _LIBC
+__libc_rwlock_define_initialized (, _nl_state_lock)
+#endif
+
+/* Checking whether the binaries runs SUID must be done and glibc provides
+   easier methods therefore we make a difference here.  */
+#ifdef _LIBC
+# define ENABLE_SECURE __libc_enable_secure
+# define DETERMINE_SECURE
+#else
+# ifndef HAVE_GETUID
+#  define getuid() 0
+# endif
+# ifndef HAVE_GETGID
+#  define getgid() 0
+# endif
+# ifndef HAVE_GETEUID
+#  define geteuid() getuid()
+# endif
+# ifndef HAVE_GETEGID
+#  define getegid() getgid()
+# endif
+static int enable_secure;
+# define ENABLE_SECURE (enable_secure == 1)
+# define DETERMINE_SECURE \
+  if (enable_secure == 0)						      \
+    {									      \
+      if (getuid () != geteuid () || getgid () != getegid ())		      \
+	enable_secure = 1;						      \
+      else								      \
+	enable_secure = -1;						      \
+    }
+#endif
+
+/* Get the function to evaluate the plural expression.  */
+#include "eval-plural.h"
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+   CATEGORY locale and, if PLURAL is nonzero, search over string
+   depending on the plural form determined by N.  */
+char *
+DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     int plural;
+     unsigned long int n;
+     int category;
+{
+#ifndef HAVE_ALLOCA
+  struct block_list *block_list = NULL;
+#endif
+  struct loaded_l10nfile *domain;
+  struct binding *binding;
+  const char *categoryname;
+  const char *categoryvalue;
+  char *dirname, *xdomainname;
+  char *single_locale;
+  char *retval;
+  size_t retlen;
+  int saved_errno;
+#if defined HAVE_TSEARCH || defined _LIBC
+  struct known_translation_t *search;
+  struct known_translation_t **foundp = NULL;
+  size_t msgid_len;
+#endif
+  size_t domainname_len;
+
+  /* If no real MSGID is given return NULL.  */
+  if (msgid1 == NULL)
+    return NULL;
+
+  __libc_rwlock_rdlock (_nl_state_lock);
+
+  /* If DOMAINNAME is NULL, we are interested in the default domain.  If
+     CATEGORY is not LC_MESSAGES this might not make much sense but the
+     definition left this undefined.  */
+  if (domainname == NULL)
+    domainname = _nl_current_default_domain;
+
+  /* OS/2 specific: backward compatibility with older libintl versions  */
+#ifdef LC_MESSAGES_COMPAT
+  if (category == LC_MESSAGES_COMPAT)
+    category = LC_MESSAGES;
+#endif
+
+#if defined HAVE_TSEARCH || defined _LIBC
+  msgid_len = strlen (msgid1) + 1;
+
+  /* Try to find the translation among those which we found at
+     some time.  */
+  search = (struct known_translation_t *)
+	   alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
+  memcpy (search->msgid, msgid1, msgid_len);
+  search->domainname = (char *) domainname;
+  search->category = category;
+
+  foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
+  if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
+    {
+      /* Now deal with plural.  */
+      if (plural)
+	retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
+				(*foundp)->translation_length);
+      else
+	retval = (char *) (*foundp)->translation;
+
+      __libc_rwlock_unlock (_nl_state_lock);
+      return retval;
+    }
+#endif
+
+  /* Preserve the `errno' value.  */
+  saved_errno = errno;
+
+  /* See whether this is a SUID binary or not.  */
+  DETERMINE_SECURE;
+
+  /* First find matching binding.  */
+  for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
+    {
+      int compare = strcmp (domainname, binding->domainname);
+      if (compare == 0)
+	/* We found it!  */
+	break;
+      if (compare < 0)
+	{
+	  /* It is not in the list.  */
+	  binding = NULL;
+	  break;
+	}
+    }
+
+  if (binding == NULL)
+    dirname = (char *) _nl_default_dirname;
+  else if (IS_ABSOLUTE_PATH (binding->dirname))
+    dirname = binding->dirname;
+  else
+    {
+      /* We have a relative path.  Make it absolute now.  */
+      size_t dirname_len = strlen (binding->dirname) + 1;
+      size_t path_max;
+      char *ret;
+
+      path_max = (unsigned int) PATH_MAX;
+      path_max += 2;		/* The getcwd docs say to do this.  */
+
+      for (;;)
+	{
+	  dirname = (char *) alloca (path_max + dirname_len);
+	  ADD_BLOCK (block_list, dirname);
+
+	  __set_errno (0);
+	  ret = getcwd (dirname, path_max);
+	  if (ret != NULL || errno != ERANGE)
+	    break;
+
+	  path_max += path_max / 2;
+	  path_max += PATH_INCR;
+	}
+
+      if (ret == NULL)
+	{
+	  /* We cannot get the current working directory.  Don't signal an
+	     error but simply return the default string.  */
+	  FREE_BLOCKS (block_list);
+	  __libc_rwlock_unlock (_nl_state_lock);
+	  __set_errno (saved_errno);
+	  return (plural == 0
+		  ? (char *) msgid1
+		  /* Use the Germanic plural rule.  */
+		  : n == 1 ? (char *) msgid1 : (char *) msgid2);
+	}
+
+      stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
+    }
+
+  /* Now determine the symbolic name of CATEGORY and its value.  */
+  categoryname = category_to_name (category);
+  categoryvalue = guess_category_value (category, categoryname);
+
+  domainname_len = strlen (domainname);
+  xdomainname = (char *) alloca (strlen (categoryname)
+				 + domainname_len + 5);
+  ADD_BLOCK (block_list, xdomainname);
+
+  stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
+		  domainname, domainname_len),
+	  ".mo");
+
+  /* Creating working area.  */
+  single_locale = (char *) alloca (strlen (categoryvalue) + 1);
+  ADD_BLOCK (block_list, single_locale);
+
+
+  /* Search for the given string.  This is a loop because we perhaps
+     got an ordered list of languages to consider for the translation.  */
+  while (1)
+    {
+      /* Make CATEGORYVALUE point to the next element of the list.  */
+      while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
+	++categoryvalue;
+      if (categoryvalue[0] == '\0')
+	{
+	  /* The whole contents of CATEGORYVALUE has been searched but
+	     no valid entry has been found.  We solve this situation
+	     by implicitly appending a "C" entry, i.e. no translation
+	     will take place.  */
+	  single_locale[0] = 'C';
+	  single_locale[1] = '\0';
+	}
+      else
+	{
+	  char *cp = single_locale;
+	  while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
+	    *cp++ = *categoryvalue++;
+	  *cp = '\0';
+
+	  /* When this is a SUID binary we must not allow accessing files
+	     outside the dedicated directories.  */
+	  if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
+	    /* Ingore this entry.  */
+	    continue;
+	}
+
+      /* If the current locale value is C (or POSIX) we don't load a
+	 domain.  Return the MSGID.  */
+      if (strcmp (single_locale, "C") == 0
+	  || strcmp (single_locale, "POSIX") == 0)
+	{
+	  FREE_BLOCKS (block_list);
+	  __libc_rwlock_unlock (_nl_state_lock);
+	  __set_errno (saved_errno);
+	  return (plural == 0
+		  ? (char *) msgid1
+		  /* Use the Germanic plural rule.  */
+		  : n == 1 ? (char *) msgid1 : (char *) msgid2);
+	}
+
+
+      /* Find structure describing the message catalog matching the
+	 DOMAINNAME and CATEGORY.  */
+      domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
+
+      if (domain != NULL)
+	{
+	  retval = _nl_find_msg (domain, binding, msgid1, &retlen);
+
+	  if (retval == NULL)
+	    {
+	      int cnt;
+
+	      for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
+		{
+		  retval = _nl_find_msg (domain->successor[cnt], binding,
+					 msgid1, &retlen);
+
+		  if (retval != NULL)
+		    {
+		      domain = domain->successor[cnt];
+		      break;
+		    }
+		}
+	    }
+
+	  if (retval != NULL)
+	    {
+	      /* Found the translation of MSGID1 in domain DOMAIN:
+		 starting at RETVAL, RETLEN bytes.  */
+	      FREE_BLOCKS (block_list);
+	      __set_errno (saved_errno);
+#if defined HAVE_TSEARCH || defined _LIBC
+	      if (foundp == NULL)
+		{
+		  /* Create a new entry and add it to the search tree.  */
+		  struct known_translation_t *newp;
+
+		  newp = (struct known_translation_t *)
+		    malloc (offsetof (struct known_translation_t, msgid)
+			    + msgid_len + domainname_len + 1);
+		  if (newp != NULL)
+		    {
+		      newp->domainname =
+			mempcpy (newp->msgid, msgid1, msgid_len);
+		      memcpy (newp->domainname, domainname, domainname_len + 1);
+		      newp->category = category;
+		      newp->counter = _nl_msg_cat_cntr;
+		      newp->domain = domain;
+		      newp->translation = retval;
+		      newp->translation_length = retlen;
+
+		      /* Insert the entry in the search tree.  */
+		      foundp = (struct known_translation_t **)
+			tsearch (newp, &root, transcmp);
+		      if (foundp == NULL
+			  || __builtin_expect (*foundp != newp, 0))
+			/* The insert failed.  */
+			free (newp);
+		    }
+		}
+	      else
+		{
+		  /* We can update the existing entry.  */
+		  (*foundp)->counter = _nl_msg_cat_cntr;
+		  (*foundp)->domain = domain;
+		  (*foundp)->translation = retval;
+		  (*foundp)->translation_length = retlen;
+		}
+#endif
+	      /* Now deal with plural.  */
+	      if (plural)
+		retval = plural_lookup (domain, n, retval, retlen);
+
+	      __libc_rwlock_unlock (_nl_state_lock);
+	      return retval;
+	    }
+	}
+    }
+  /* NOTREACHED */
+}
+
+
+char *
+internal_function
+_nl_find_msg (domain_file, domainbinding, msgid, lengthp)
+     struct loaded_l10nfile *domain_file;
+     struct binding *domainbinding;
+     const char *msgid;
+     size_t *lengthp;
+{
+  struct loaded_domain *domain;
+  size_t act;
+  char *result;
+  size_t resultlen;
+
+  if (domain_file->decided == 0)
+    _nl_load_domain (domain_file, domainbinding);
+
+  if (domain_file->data == NULL)
+    return NULL;
+
+  domain = (struct loaded_domain *) domain_file->data;
+
+  /* Locate the MSGID and its translation.  */
+  if (domain->hash_size > 2 && domain->hash_tab != NULL)
+    {
+      /* Use the hashing table.  */
+      nls_uint32 len = strlen (msgid);
+      nls_uint32 hash_val = hash_string (msgid);
+      nls_uint32 idx = hash_val % domain->hash_size;
+      nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
+
+      while (1)
+	{
+	  nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
+
+	  if (nstr == 0)
+	    /* Hash table entry is empty.  */
+	    return NULL;
+
+	  /* Compare msgid with the original string at index nstr-1.
+	     We compare the lengths with >=, not ==, because plural entries
+	     are represented by strings with an embedded NUL.  */
+	  if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len
+	      && (strcmp (msgid,
+			  domain->data + W (domain->must_swap,
+					    domain->orig_tab[nstr - 1].offset))
+		  == 0))
+	    {
+	      act = nstr - 1;
+	      goto found;
+	    }
+
+	  if (idx >= domain->hash_size - incr)
+	    idx -= domain->hash_size - incr;
+	  else
+	    idx += incr;
+	}
+      /* NOTREACHED */
+    }
+  else
+    {
+      /* Try the default method:  binary search in the sorted array of
+	 messages.  */
+      size_t top, bottom;
+
+      bottom = 0;
+      top = domain->nstrings;
+      while (bottom < top)
+	{
+	  int cmp_val;
+
+	  act = (bottom + top) / 2;
+	  cmp_val = strcmp (msgid, (domain->data
+				    + W (domain->must_swap,
+					 domain->orig_tab[act].offset)));
+	  if (cmp_val < 0)
+	    top = act;
+	  else if (cmp_val > 0)
+	    bottom = act + 1;
+	  else
+	    goto found;
+	}
+      /* No translation was found.  */
+      return NULL;
+    }
+
+ found:
+  /* The translation was found at index ACT.  If we have to convert the
+     string to use a different character set, this is the time.  */
+  result = ((char *) domain->data
+	    + W (domain->must_swap, domain->trans_tab[act].offset));
+  resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
+
+#if defined _LIBC || HAVE_ICONV
+  if (domain->codeset_cntr
+      != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
+    {
+      /* The domain's codeset has changed through bind_textdomain_codeset()
+	 since the message catalog was initialized or last accessed.  We
+	 have to reinitialize the converter.  */
+      _nl_free_domain_conv (domain);
+      _nl_init_domain_conv (domain_file, domain, domainbinding);
+    }
+
+  if (
+# ifdef _LIBC
+      domain->conv != (__gconv_t) -1
+# else
+#  if HAVE_ICONV
+      domain->conv != (iconv_t) -1
+#  endif
+# endif
+      )
+    {
+      /* We are supposed to do a conversion.  First allocate an
+	 appropriate table with the same structure as the table
+	 of translations in the file, where we can put the pointers
+	 to the converted strings in.
+	 There is a slight complication with plural entries.  They
+	 are represented by consecutive NUL terminated strings.  We
+	 handle this case by converting RESULTLEN bytes, including
+	 NULs.  */
+
+      if (domain->conv_tab == NULL
+	  && ((domain->conv_tab = (char **) calloc (domain->nstrings,
+						    sizeof (char *)))
+	      == NULL))
+	/* Mark that we didn't succeed allocating a table.  */
+	domain->conv_tab = (char **) -1;
+
+      if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
+	/* Nothing we can do, no more memory.  */
+	goto converted;
+
+      if (domain->conv_tab[act] == NULL)
+	{
+	  /* We haven't used this string so far, so it is not
+	     translated yet.  Do this now.  */
+	  /* We use a bit more efficient memory handling.
+	     We allocate always larger blocks which get used over
+	     time.  This is faster than many small allocations.   */
+	  __libc_lock_define_initialized (static, lock)
+# define INITIAL_BLOCK_SIZE	4080
+	  static unsigned char *freemem;
+	  static size_t freemem_size;
+
+	  const unsigned char *inbuf;
+	  unsigned char *outbuf;
+	  int malloc_count;
+# ifndef _LIBC
+	  transmem_block_t *transmem_list = NULL;
+# endif
+
+	  __libc_lock_lock (lock);
+
+	  inbuf = (const unsigned char *) result;
+	  outbuf = freemem + sizeof (size_t);
+
+	  malloc_count = 0;
+	  while (1)
+	    {
+	      transmem_block_t *newmem;
+# ifdef _LIBC
+	      size_t non_reversible;
+	      int res;
+
+	      if (freemem_size < sizeof (size_t))
+		goto resize_freemem;
+
+	      res = __gconv (domain->conv,
+			     &inbuf, inbuf + resultlen,
+			     &outbuf,
+			     outbuf + freemem_size - sizeof (size_t),
+			     &non_reversible);
+
+	      if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
+		break;
+
+	      if (res != __GCONV_FULL_OUTPUT)
+		{
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+
+	      inbuf = result;
+# else
+#  if HAVE_ICONV
+	      const char *inptr = (const char *) inbuf;
+	      size_t inleft = resultlen;
+	      char *outptr = (char *) outbuf;
+	      size_t outleft;
+
+	      if (freemem_size < sizeof (size_t))
+		goto resize_freemem;
+
+	      outleft = freemem_size - sizeof (size_t);
+	      if (iconv (domain->conv,
+			 (ICONV_CONST char **) &inptr, &inleft,
+			 &outptr, &outleft)
+		  != (size_t) (-1))
+		{
+		  outbuf = (unsigned char *) outptr;
+		  break;
+		}
+	      if (errno != E2BIG)
+		{
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+#  endif
+# endif
+
+	    resize_freemem:
+	      /* We must allocate a new buffer or resize the old one.  */
+	      if (malloc_count > 0)
+		{
+		  ++malloc_count;
+		  freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
+		  newmem = (transmem_block_t *) realloc (transmem_list,
+							 freemem_size);
+# ifdef _LIBC
+		  if (newmem != NULL)
+		    transmem_list = transmem_list->next;
+		  else
+		    {
+		      struct transmem_list *old = transmem_list;
+
+		      transmem_list = transmem_list->next;
+		      free (old);
+		    }
+# endif
+		}
+	      else
+		{
+		  malloc_count = 1;
+		  freemem_size = INITIAL_BLOCK_SIZE;
+		  newmem = (transmem_block_t *) malloc (freemem_size);
+		}
+	      if (__builtin_expect (newmem == NULL, 0))
+		{
+		  freemem = NULL;
+		  freemem_size = 0;
+		  __libc_lock_unlock (lock);
+		  goto converted;
+		}
+
+# ifdef _LIBC
+	      /* Add the block to the list of blocks we have to free
+                 at some point.  */
+	      newmem->next = transmem_list;
+	      transmem_list = newmem;
+
+	      freemem = newmem->data;
+	      freemem_size -= offsetof (struct transmem_list, data);
+# else
+	      transmem_list = newmem;
+	      freemem = newmem;
+# endif
+
+	      outbuf = freemem + sizeof (size_t);
+	    }
+
+	  /* We have now in our buffer a converted string.  Put this
+	     into the table of conversions.  */
+	  *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
+	  domain->conv_tab[act] = (char *) freemem;
+	  /* Shrink freemem, but keep it aligned.  */
+	  freemem_size -= outbuf - freemem;
+	  freemem = outbuf;
+	  freemem += freemem_size & (alignof (size_t) - 1);
+	  freemem_size = freemem_size & ~ (alignof (size_t) - 1);
+
+	  __libc_lock_unlock (lock);
+	}
+
+      /* Now domain->conv_tab[act] contains the translation of all
+	 the plural variants.  */
+      result = domain->conv_tab[act] + sizeof (size_t);
+      resultlen = *(size_t *) domain->conv_tab[act];
+    }
+
+ converted:
+  /* The result string is converted.  */
+
+#endif /* _LIBC || HAVE_ICONV */
+
+  *lengthp = resultlen;
+  return result;
+}
+
+
+/* Look up a plural variant.  */
+static char *
+internal_function
+plural_lookup (domain, n, translation, translation_len)
+     struct loaded_l10nfile *domain;
+     unsigned long int n;
+     const char *translation;
+     size_t translation_len;
+{
+  struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
+  unsigned long int index;
+  const char *p;
+
+  index = plural_eval (domaindata->plural, n);
+  if (index >= domaindata->nplurals)
+    /* This should never happen.  It means the plural expression and the
+       given maximum value do not match.  */
+    index = 0;
+
+  /* Skip INDEX strings at TRANSLATION.  */
+  p = translation;
+  while (index-- > 0)
+    {
+#ifdef _LIBC
+      p = __rawmemchr (p, '\0');
+#else
+      p = strchr (p, '\0');
+#endif
+      /* And skip over the NUL byte.  */
+      p++;
+
+      if (p >= translation + translation_len)
+	/* This should never happen.  It means the plural expression
+	   evaluated to a value larger than the number of variants
+	   available for MSGID1.  */
+	return (char *) translation;
+    }
+  return (char *) p;
+}
+
+
+/* Return string representation of locale CATEGORY.  */
+static const char *
+internal_function
+category_to_name (category)
+     int category;
+{
+  const char *retval;
+
+  switch (category)
+  {
+#ifdef LC_COLLATE
+  case LC_COLLATE:
+    retval = "LC_COLLATE";
+    break;
+#endif
+#ifdef LC_CTYPE
+  case LC_CTYPE:
+    retval = "LC_CTYPE";
+    break;
+#endif
+#ifdef LC_MONETARY
+  case LC_MONETARY:
+    retval = "LC_MONETARY";
+    break;
+#endif
+#ifdef LC_NUMERIC
+  case LC_NUMERIC:
+    retval = "LC_NUMERIC";
+    break;
+#endif
+#ifdef LC_TIME
+  case LC_TIME:
+    retval = "LC_TIME";
+    break;
+#endif
+#ifdef LC_MESSAGES
+  case LC_MESSAGES:
+    retval = "LC_MESSAGES";
+    break;
+#endif
+#ifdef LC_RESPONSE
+  case LC_RESPONSE:
+    retval = "LC_RESPONSE";
+    break;
+#endif
+#ifdef LC_ALL
+  case LC_ALL:
+    /* This might not make sense but is perhaps better than any other
+       value.  */
+    retval = "LC_ALL";
+    break;
+#endif
+  default:
+    /* If you have a better idea for a default value let me know.  */
+    retval = "LC_XXX";
+  }
+
+  return retval;
+}
+
+/* Guess value of current locale from value of the environment variables.  */
+static const char *
+internal_function
+guess_category_value (category, categoryname)
+     int category;
+     const char *categoryname;
+{
+  const char *language;
+  const char *retval;
+
+  /* The highest priority value is the `LANGUAGE' environment
+     variable.  But we don't use the value if the currently selected
+     locale is the C locale.  This is a GNU extension.  */
+  language = getenv ("LANGUAGE");
+  if (language != NULL && language[0] == '\0')
+    language = NULL;
+
+  /* We have to proceed with the POSIX methods of looking to `LC_ALL',
+     `LC_xxx', and `LANG'.  On some systems this can be done by the
+     `setlocale' function itself.  */
+#ifdef _LIBC
+  retval = setlocale (category, NULL);
+#else
+  retval = _nl_locale_name (category, categoryname);
+#endif
+
+  /* Ignore LANGUAGE if the locale is set to "C" because
+     1. "C" locale usually uses the ASCII encoding, and most international
+	messages use non-ASCII characters. These characters get displayed
+	as question marks (if using glibc's iconv()) or as invalid 8-bit
+	characters (because other iconv()s refuse to convert most non-ASCII
+	characters to ASCII). In any case, the output is ugly.
+     2. The precise output of some programs in the "C" locale is specified
+	by POSIX and should not depend on environment variables like
+	"LANGUAGE".  We allow such programs to use gettext().  */
+  return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
+}
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library.  So we
+   avoid the non-standard function stpcpy.  In GNU C Library this
+   function is available, though.  Also allow the symbol HAVE_STPCPY
+   to be defined.  */
+#if !_LIBC && !HAVE_STPCPY
+static char *
+stpcpy (dest, src)
+     char *dest;
+     const char *src;
+{
+  while ((*dest++ = *src++) != '\0')
+    /* Do nothing. */ ;
+  return dest - 1;
+}
+#endif
+
+#if !_LIBC && !HAVE_MEMPCPY
+static void *
+mempcpy (dest, src, n)
+     void *dest;
+     const void *src;
+     size_t n;
+{
+  return (void *) ((char *) memcpy (dest, src, n) + n);
+}
+#endif
+
+
+#ifdef _LIBC
+/* If we want to free all resources we have to do some work at
+   program's end.  */
+static void __attribute__ ((unused))
+free_mem (void)
+{
+  void *old;
+
+  while (_nl_domain_bindings != NULL)
+    {
+      struct binding *oldp = _nl_domain_bindings;
+      _nl_domain_bindings = _nl_domain_bindings->next;
+      if (oldp->dirname != _nl_default_dirname)
+	/* Yes, this is a pointer comparison.  */
+	free (oldp->dirname);
+      free (oldp->codeset);
+      free (oldp);
+    }
+
+  if (_nl_current_default_domain != _nl_default_default_domain)
+    /* Yes, again a pointer comparison.  */
+    free ((char *) _nl_current_default_domain);
+
+  /* Remove the search tree with the known translations.  */
+  __tdestroy (root, free);
+  root = NULL;
+
+  while (transmem_list != NULL)
+    {
+      old = transmem_list;
+      transmem_list = transmem_list->next;
+      free (old);
+    }
+}
+
+text_set_element (__libc_subfreeres, free_mem);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/dcngettext.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/dcngettext.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/dcngettext.c	(revision 1780)
@@ -0,0 +1,60 @@
+/* Implementation of the dcngettext(3) function.
+   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define DCNGETTEXT __dcngettext
+# define DCIGETTEXT __dcigettext
+#else
+# define DCNGETTEXT dcngettext__
+# define DCIGETTEXT dcigettext__
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+   locale.  */
+char *
+DCNGETTEXT (domainname, msgid1, msgid2, n, category)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+     int category;
+{
+  return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__dcngettext, dcngettext);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/dgettext.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/dgettext.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/dgettext.c	(revision 1780)
@@ -0,0 +1,59 @@
+/* Implementation of the dgettext(3) function.
+   Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <locale.h>
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define DGETTEXT __dgettext
+# define DCGETTEXT __dcgettext
+#else
+# define DGETTEXT dgettext__
+# define DCGETTEXT dcgettext__
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog of the current
+   LC_MESSAGES locale.  */
+char *
+DGETTEXT (domainname, msgid)
+     const char *domainname;
+     const char *msgid;
+{
+  return DCGETTEXT (domainname, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__dgettext, dgettext);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/dngettext.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/dngettext.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/dngettext.c	(revision 1780)
@@ -0,0 +1,61 @@
+/* Implementation of the dngettext(3) function.
+   Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <locale.h>
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define DNGETTEXT __dngettext
+# define DCNGETTEXT __dcngettext
+#else
+# define DNGETTEXT dngettext__
+# define DCNGETTEXT dcngettext__
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog of the current
+   LC_MESSAGES locale and skip message according to the plural form.  */
+char *
+DNGETTEXT (domainname, msgid1, msgid2, n)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+{
+  return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__dngettext, dngettext);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/eval-plural.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/eval-plural.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/eval-plural.h	(revision 1780)
@@ -0,0 +1,105 @@
+/* Plural expression evaluation.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef STATIC
+#define STATIC static
+#endif
+
+/* Evaluate the plural expression and return an index value.  */
+STATIC unsigned long int plural_eval PARAMS ((struct expression *pexp,
+					      unsigned long int n))
+     internal_function;
+
+STATIC
+unsigned long int
+internal_function
+plural_eval (pexp, n)
+     struct expression *pexp;
+     unsigned long int n;
+{
+  switch (pexp->nargs)
+    {
+    case 0:
+      switch (pexp->operation)
+	{
+	case var:
+	  return n;
+	case num:
+	  return pexp->val.num;
+	default:
+	  break;
+	}
+      /* NOTREACHED */
+      break;
+    case 1:
+      {
+	/* pexp->operation must be lnot.  */
+	unsigned long int arg = plural_eval (pexp->val.args[0], n);
+	return ! arg;
+      }
+    case 2:
+      {
+	unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
+	if (pexp->operation == lor)
+	  return leftarg || plural_eval (pexp->val.args[1], n);
+	else if (pexp->operation == land)
+	  return leftarg && plural_eval (pexp->val.args[1], n);
+	else
+	  {
+	    unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
+
+	    switch (pexp->operation)
+	      {
+	      case mult:
+		return leftarg * rightarg;
+	      case divide:
+		return leftarg / rightarg;
+	      case module:
+		return leftarg % rightarg;
+	      case plus:
+		return leftarg + rightarg;
+	      case minus:
+		return leftarg - rightarg;
+	      case less_than:
+		return leftarg < rightarg;
+	      case greater_than:
+		return leftarg > rightarg;
+	      case less_or_equal:
+		return leftarg <= rightarg;
+	      case greater_or_equal:
+		return leftarg >= rightarg;
+	      case equal:
+		return leftarg == rightarg;
+	      case not_equal:
+		return leftarg != rightarg;
+	      default:
+		break;
+	      }
+	  }
+	/* NOTREACHED */
+	break;
+      }
+    case 3:
+      {
+	/* pexp->operation must be qmop.  */
+	unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
+	return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
+      }
+    }
+  /* NOTREACHED */
+  return 0;
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/explodename.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/explodename.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/explodename.c	(revision 1780)
@@ -0,0 +1,192 @@
+/* Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "loadinfo.h"
+
+/* On some strange systems still no definition of NULL is found.  Sigh!  */
+#ifndef NULL
+# if defined __STDC__ && __STDC__
+#  define NULL ((void *) 0)
+# else
+#  define NULL 0
+# endif
+#endif
+
+/* @@ end of prolog @@ */
+
+char *
+_nl_find_language (name)
+     const char *name;
+{
+  while (name[0] != '\0' && name[0] != '_' && name[0] != '@'
+	 && name[0] != '+' && name[0] != ',')
+    ++name;
+
+  return (char *) name;
+}
+
+
+int
+_nl_explode_name (name, language, modifier, territory, codeset,
+		  normalized_codeset, special, sponsor, revision)
+     char *name;
+     const char **language;
+     const char **modifier;
+     const char **territory;
+     const char **codeset;
+     const char **normalized_codeset;
+     const char **special;
+     const char **sponsor;
+     const char **revision;
+{
+  enum { undecided, xpg, cen } syntax;
+  char *cp;
+  int mask;
+
+  *modifier = NULL;
+  *territory = NULL;
+  *codeset = NULL;
+  *normalized_codeset = NULL;
+  *special = NULL;
+  *sponsor = NULL;
+  *revision = NULL;
+
+  /* Now we determine the single parts of the locale name.  First
+     look for the language.  Termination symbols are `_' and `@' if
+     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
+  mask = 0;
+  syntax = undecided;
+  *language = cp = name;
+  cp = _nl_find_language (*language);
+
+  if (*language == cp)
+    /* This does not make sense: language has to be specified.  Use
+       this entry as it is without exploding.  Perhaps it is an alias.  */
+    cp = strchr (*language, '\0');
+  else if (cp[0] == '_')
+    {
+      /* Next is the territory.  */
+      cp[0] = '\0';
+      *territory = ++cp;
+
+      while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@'
+	     && cp[0] != '+' && cp[0] != ',' && cp[0] != '_')
+	++cp;
+
+      mask |= TERRITORY;
+
+      if (cp[0] == '.')
+	{
+	  /* Next is the codeset.  */
+	  syntax = xpg;
+	  cp[0] = '\0';
+	  *codeset = ++cp;
+
+	  while (cp[0] != '\0' && cp[0] != '@')
+	    ++cp;
+
+	  mask |= XPG_CODESET;
+
+	  if (*codeset != cp && (*codeset)[0] != '\0')
+	    {
+	      *normalized_codeset = _nl_normalize_codeset (*codeset,
+							   cp - *codeset);
+	      if (strcmp (*codeset, *normalized_codeset) == 0)
+		free ((char *) *normalized_codeset);
+	      else
+		mask |= XPG_NORM_CODESET;
+	    }
+	}
+    }
+
+  if (cp[0] == '@' || (syntax != xpg && cp[0] == '+'))
+    {
+      /* Next is the modifier.  */
+      syntax = cp[0] == '@' ? xpg : cen;
+      cp[0] = '\0';
+      *modifier = ++cp;
+
+      while (syntax == cen && cp[0] != '\0' && cp[0] != '+'
+	     && cp[0] != ',' && cp[0] != '_')
+	++cp;
+
+      mask |= XPG_MODIFIER | CEN_AUDIENCE;
+    }
+
+  if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_'))
+    {
+      syntax = cen;
+
+      if (cp[0] == '+')
+	{
+ 	  /* Next is special application (CEN syntax).  */
+	  cp[0] = '\0';
+	  *special = ++cp;
+
+	  while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_')
+	    ++cp;
+
+	  mask |= CEN_SPECIAL;
+	}
+
+      if (cp[0] == ',')
+	{
+ 	  /* Next is sponsor (CEN syntax).  */
+	  cp[0] = '\0';
+	  *sponsor = ++cp;
+
+	  while (cp[0] != '\0' && cp[0] != '_')
+	    ++cp;
+
+	  mask |= CEN_SPONSOR;
+	}
+
+      if (cp[0] == '_')
+	{
+ 	  /* Next is revision (CEN syntax).  */
+	  cp[0] = '\0';
+	  *revision = ++cp;
+
+	  mask |= CEN_REVISION;
+	}
+    }
+
+  /* For CEN syntax values it might be important to have the
+     separator character in the file name, not for XPG syntax.  */
+  if (syntax == xpg)
+    {
+      if (*territory != NULL && (*territory)[0] == '\0')
+	mask &= ~TERRITORY;
+
+      if (*codeset != NULL && (*codeset)[0] == '\0')
+	mask &= ~XPG_CODESET;
+
+      if (*modifier != NULL && (*modifier)[0] == '\0')
+	mask &= ~XPG_MODIFIER;
+    }
+
+  return mask;
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/finddomain.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/finddomain.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/finddomain.c	(revision 1780)
@@ -0,0 +1,198 @@
+/* Handle list of needed message catalogs
+   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@gnu.org>, 1995.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+/* List of already loaded domains.  */
+static struct loaded_l10nfile *_nl_loaded_domains;
+
+
+/* Return a data structure describing the message catalog described by
+   the DOMAINNAME and CATEGORY parameters with respect to the currently
+   established bindings.  */
+struct loaded_l10nfile *
+internal_function
+_nl_find_domain (dirname, locale, domainname, domainbinding)
+     const char *dirname;
+     char *locale;
+     const char *domainname;
+     struct binding *domainbinding;
+{
+  struct loaded_l10nfile *retval;
+  const char *language;
+  const char *modifier;
+  const char *territory;
+  const char *codeset;
+  const char *normalized_codeset;
+  const char *special;
+  const char *sponsor;
+  const char *revision;
+  const char *alias_value;
+  int mask;
+
+  /* LOCALE can consist of up to four recognized parts for the XPG syntax:
+
+		language[_territory[.codeset]][@modifier]
+
+     and six parts for the CEN syntax:
+
+	language[_territory][+audience][+special][,[sponsor][_revision]]
+
+     Beside the first part all of them are allowed to be missing.  If
+     the full specified locale is not found, the less specific one are
+     looked for.  The various parts will be stripped off according to
+     the following order:
+		(1) revision
+		(2) sponsor
+		(3) special
+		(4) codeset
+		(5) normalized codeset
+		(6) territory
+		(7) audience/modifier
+   */
+
+  /* If we have already tested for this locale entry there has to
+     be one data set in the list of loaded domains.  */
+  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
+			       strlen (dirname) + 1, 0, locale, NULL, NULL,
+			       NULL, NULL, NULL, NULL, NULL, domainname, 0);
+  if (retval != NULL)
+    {
+      /* We know something about this locale.  */
+      int cnt;
+
+      if (retval->decided == 0)
+	_nl_load_domain (retval, domainbinding);
+
+      if (retval->data != NULL)
+	return retval;
+
+      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
+	{
+	  if (retval->successor[cnt]->decided == 0)
+	    _nl_load_domain (retval->successor[cnt], domainbinding);
+
+	  if (retval->successor[cnt]->data != NULL)
+	    break;
+	}
+      return cnt >= 0 ? retval : NULL;
+      /* NOTREACHED */
+    }
+
+  /* See whether the locale value is an alias.  If yes its value
+     *overwrites* the alias name.  No test for the original value is
+     done.  */
+  alias_value = _nl_expand_alias (locale);
+  if (alias_value != NULL)
+    {
+#if defined _LIBC || defined HAVE_STRDUP
+      locale = strdup (alias_value);
+      if (locale == NULL)
+	return NULL;
+#else
+      size_t len = strlen (alias_value) + 1;
+      locale = (char *) malloc (len);
+      if (locale == NULL)
+	return NULL;
+
+      memcpy (locale, alias_value, len);
+#endif
+    }
+
+  /* Now we determine the single parts of the locale name.  First
+     look for the language.  Termination symbols are `_' and `@' if
+     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
+  mask = _nl_explode_name (locale, &language, &modifier, &territory,
+			   &codeset, &normalized_codeset, &special,
+			   &sponsor, &revision);
+
+  /* Create all possible locale entries which might be interested in
+     generalization.  */
+  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
+			       strlen (dirname) + 1, mask, language, territory,
+			       codeset, normalized_codeset, modifier, special,
+			       sponsor, revision, domainname, 1);
+  if (retval == NULL)
+    /* This means we are out of core.  */
+    return NULL;
+
+  if (retval->decided == 0)
+    _nl_load_domain (retval, domainbinding);
+  if (retval->data == NULL)
+    {
+      int cnt;
+      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
+	{
+	  if (retval->successor[cnt]->decided == 0)
+	    _nl_load_domain (retval->successor[cnt], domainbinding);
+	  if (retval->successor[cnt]->data != NULL)
+	    break;
+	}
+    }
+
+  /* The room for an alias was dynamically allocated.  Free it now.  */
+  if (alias_value != NULL)
+    free (locale);
+
+  /* The space for normalized_codeset is dynamically allocated.  Free it.  */
+  if (mask & XPG_NORM_CODESET)
+    free ((void *) normalized_codeset);
+
+  return retval;
+}
+
+
+#ifdef _LIBC
+static void __attribute__ ((unused))
+free_mem (void)
+{
+  struct loaded_l10nfile *runp = _nl_loaded_domains;
+
+  while (runp != NULL)
+    {
+      struct loaded_l10nfile *here = runp;
+      if (runp->data != NULL)
+	_nl_unload_domain ((struct loaded_domain *) runp->data);
+      runp = runp->next;
+      free ((char *) here->filename);
+      free (here);
+    }
+}
+
+text_set_element (__libc_subfreeres, free_mem);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/gettext.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/gettext.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/gettext.c	(revision 1780)
@@ -0,0 +1,64 @@
+/* Implementation of gettext(3) function.
+   Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define __need_NULL
+# include <stddef.h>
+#else
+# include <stdlib.h>		/* Just for NULL.  */
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define GETTEXT __gettext
+# define DCGETTEXT __dcgettext
+#else
+# define GETTEXT gettext__
+# define DCGETTEXT dcgettext__
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+   LC_MESSAGES locale.  If not found, returns MSGID itself (the default
+   text).  */
+char *
+GETTEXT (msgid)
+     const char *msgid;
+{
+  return DCGETTEXT (NULL, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__gettext, gettext);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/gettextP.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/gettextP.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/gettextP.h	(revision 1780)
@@ -0,0 +1,201 @@
+/* Header describing internals of libintl library.
+   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifndef _GETTEXTP_H
+#define _GETTEXTP_H
+
+#include <stddef.h>		/* Get size_t.  */
+
+#ifdef _LIBC
+# include "../iconv/gconv_int.h"
+#else
+# if HAVE_ICONV
+#  include <iconv.h>
+# endif
+#endif
+
+#include "loadinfo.h"
+
+#include "gmo.h"		/* Get nls_uint32.  */
+
+/* @@ end of prolog @@ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+/* Tell the compiler when a conditional or integer expression is
+   almost always true or almost always false.  */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+#ifndef W
+# define W(flag, data) ((flag) ? SWAP (data) : (data))
+#endif
+
+
+#ifdef _LIBC
+# include <byteswap.h>
+# define SWAP(i) bswap_32 (i)
+#else
+static inline nls_uint32
+SWAP (i)
+     nls_uint32 i;
+{
+  return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
+}
+#endif
+
+
+/* The representation of an opened message catalog.  */
+struct loaded_domain
+{
+  const char *data;
+  int use_mmap;
+  size_t mmap_size;
+  int must_swap;
+  nls_uint32 nstrings;
+  struct string_desc *orig_tab;
+  struct string_desc *trans_tab;
+  nls_uint32 hash_size;
+  nls_uint32 *hash_tab;
+  int codeset_cntr;
+#ifdef _LIBC
+  __gconv_t conv;
+#else
+# if HAVE_ICONV
+  iconv_t conv;
+# endif
+#endif
+  char **conv_tab;
+
+  struct expression *plural;
+  unsigned long int nplurals;
+};
+
+/* We want to allocate a string at the end of the struct.  But ISO C
+   doesn't allow zero sized arrays.  */
+#ifdef __GNUC__
+# define ZERO 0
+#else
+# define ZERO 1
+#endif
+
+/* A set of settings bound to a message domain.  Used to store settings
+   from bindtextdomain() and bind_textdomain_codeset().  */
+struct binding
+{
+  struct binding *next;
+  char *dirname;
+  int codeset_cntr;	/* Incremented each time codeset changes.  */
+  char *codeset;
+  char domainname[ZERO];
+};
+
+/* A counter which is incremented each time some previous translations
+   become invalid.
+   This variable is part of the external ABI of the GNU libintl.  */
+extern int _nl_msg_cat_cntr;
+
+#ifndef _LIBC
+const char *_nl_locale_name PARAMS ((int category, const char *categoryname));
+#endif
+
+struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
+						 char *__locale,
+						 const char *__domainname,
+					      struct binding *__domainbinding))
+     internal_function;
+void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain,
+			      struct binding *__domainbinding))
+     internal_function;
+void _nl_unload_domain PARAMS ((struct loaded_domain *__domain))
+     internal_function;
+const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file,
+					  struct loaded_domain *__domain,
+					  struct binding *__domainbinding))
+     internal_function;
+void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain))
+     internal_function;
+
+char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
+			    struct binding *domainbinding,
+			    const char *msgid, size_t *lengthp))
+     internal_function;
+
+#ifdef _LIBC
+extern char *__gettext PARAMS ((const char *__msgid));
+extern char *__dgettext PARAMS ((const char *__domainname,
+				 const char *__msgid));
+extern char *__dcgettext PARAMS ((const char *__domainname,
+				  const char *__msgid, int __category));
+extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2,
+				 unsigned long int __n));
+extern char *__dngettext PARAMS ((const char *__domainname,
+				  const char *__msgid1, const char *__msgid2,
+				  unsigned long int n));
+extern char *__dcngettext PARAMS ((const char *__domainname,
+				   const char *__msgid1, const char *__msgid2,
+				   unsigned long int __n, int __category));
+extern char *__dcigettext PARAMS ((const char *__domainname,
+				   const char *__msgid1, const char *__msgid2,
+				   int __plural, unsigned long int __n,
+				   int __category));
+extern char *__textdomain PARAMS ((const char *__domainname));
+extern char *__bindtextdomain PARAMS ((const char *__domainname,
+				       const char *__dirname));
+extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname,
+						const char *__codeset));
+#else
+extern char *gettext__ PARAMS ((const char *__msgid));
+extern char *dgettext__ PARAMS ((const char *__domainname,
+				 const char *__msgid));
+extern char *dcgettext__ PARAMS ((const char *__domainname,
+				  const char *__msgid, int __category));
+extern char *ngettext__ PARAMS ((const char *__msgid1, const char *__msgid2,
+				 unsigned long int __n));
+extern char *dngettext__ PARAMS ((const char *__domainname,
+				  const char *__msgid1, const char *__msgid2,
+				  unsigned long int __n));
+extern char *dcngettext__ PARAMS ((const char *__domainname,
+				   const char *__msgid1, const char *__msgid2,
+				   unsigned long int __n, int __category));
+extern char *dcigettext__ PARAMS ((const char *__domainname,
+				   const char *__msgid1, const char *__msgid2,
+				   int __plural, unsigned long int __n,
+				   int __category));
+extern char *textdomain__ PARAMS ((const char *__domainname));
+extern char *bindtextdomain__ PARAMS ((const char *__domainname,
+				       const char *__dirname));
+extern char *bind_textdomain_codeset__ PARAMS ((const char *__domainname,
+						const char *__codeset));
+#endif
+
+/* @@ begin of epilog @@ */
+
+#endif /* gettextP.h  */
Index: /tags/kBuild-0.1.4/src/sed/intl/gmo.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/gmo.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/gmo.h	(revision 1780)
@@ -0,0 +1,100 @@
+/* Description of GNU message catalog format: general file layout.
+   Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifndef _GETTEXT_H
+#define _GETTEXT_H 1
+
+#include <limits.h>
+
+/* @@ end of prolog @@ */
+
+/* The magic number of the GNU message catalog format.  */
+#define _MAGIC 0x950412de
+#define _MAGIC_SWAPPED 0xde120495
+
+/* Revision number of the currently used .mo (binary) file format.  */
+#define MO_REVISION_NUMBER 0
+
+/* The following contortions are an attempt to use the C preprocessor
+   to determine an unsigned integral type that is 32 bits wide.  An
+   alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+   as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work
+   when cross-compiling.  */
+
+#if __STDC__
+# define UINT_MAX_32_BITS 4294967295U
+#else
+# define UINT_MAX_32_BITS 0xFFFFFFFF
+#endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+   This should be valid for all systems GNU cares about because
+   that doesn't include 16-bit systems, and only modern systems
+   (that certainly have <limits.h>) have 64+-bit integral types.  */
+
+#ifndef UINT_MAX
+# define UINT_MAX UINT_MAX_32_BITS
+#endif
+
+#if UINT_MAX == UINT_MAX_32_BITS
+typedef unsigned nls_uint32;
+#else
+# if USHRT_MAX == UINT_MAX_32_BITS
+typedef unsigned short nls_uint32;
+# else
+#  if ULONG_MAX == UINT_MAX_32_BITS
+typedef unsigned long nls_uint32;
+#  else
+  /* The following line is intended to throw an error.  Using #error is
+     not portable enough.  */
+  "Cannot determine unsigned 32-bit data type."
+#  endif
+# endif
+#endif
+
+
+/* Header for binary .mo file format.  */
+struct mo_file_header
+{
+  /* The magic number.  */
+  nls_uint32 magic;
+  /* The revision number of the file format.  */
+  nls_uint32 revision;
+  /* The number of strings pairs.  */
+  nls_uint32 nstrings;
+  /* Offset of table with start offsets of original strings.  */
+  nls_uint32 orig_tab_offset;
+  /* Offset of table with start offsets of translation strings.  */
+  nls_uint32 trans_tab_offset;
+  /* Size of hashing table.  */
+  nls_uint32 hash_tab_size;
+  /* Offset of first hashing entry.  */
+  nls_uint32 hash_tab_offset;
+};
+
+struct string_desc
+{
+  /* Length of addressed string.  */
+  nls_uint32 length;
+  /* Offset of string in file.  */
+  nls_uint32 offset;
+};
+
+/* @@ begin of epilog @@ */
+
+#endif	/* gettext.h  */
Index: /tags/kBuild-0.1.4/src/sed/intl/hash-string.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/hash-string.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/hash-string.h	(revision 1780)
@@ -0,0 +1,59 @@
+/* Description of GNU message catalog format: string hashing function.
+   Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* @@ end of prolog @@ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(Args) Args
+# else
+#  define PARAMS(Args) ()
+# endif
+#endif
+
+/* We assume to have `unsigned long int' value with at least 32 bits.  */
+#define HASHWORDBITS 32
+
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+   [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+   1986, 1987 Bell Telephone Laboratories, Inc.]  */
+static unsigned long int hash_string PARAMS ((const char *__str_param));
+
+static inline unsigned long int
+hash_string (str_param)
+     const char *str_param;
+{
+  unsigned long int hval, g;
+  const char *str = str_param;
+
+  /* Compute the hash value for the given string.  */
+  hval = 0;
+  while (*str != '\0')
+    {
+      hval <<= 4;
+      hval += (unsigned long int) *str++;
+      g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+      if (g != 0)
+	{
+	  hval ^= g >> (HASHWORDBITS - 8);
+	  hval ^= g;
+	}
+    }
+  return hval;
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/intl-compat.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/intl-compat.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/intl-compat.c	(revision 1780)
@@ -0,0 +1,166 @@
+/* intl-compat.c - Stub functions to call gettext functions from GNU gettext
+   Library.
+   Copyright (C) 1995, 2000, 2001 Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libgnuintl.h"
+#include "gettextP.h"
+
+/* @@ end of prolog @@ */
+
+/* This file redirects the gettext functions (without prefix or suffix) to
+   those defined in the included GNU gettext library (with "__" suffix).
+   It is compiled into libintl when the included GNU gettext library is
+   configured --with-included-gettext.
+
+   This redirection works also in the case that the system C library or
+   the system libintl library contain gettext/textdomain/... functions.
+   If it didn't, we would need to add preprocessor level redirections to
+   libgnuintl.h of the following form:
+
+#    define gettext gettext__
+#    define dgettext dgettext__
+#    define dcgettext dcgettext__
+#    define ngettext ngettext__
+#    define dngettext dngettext__
+#    define dcngettext dcngettext__
+#    define textdomain textdomain__
+#    define bindtextdomain bindtextdomain__
+#    define bind_textdomain_codeset bind_textdomain_codeset__
+
+   How does this redirection work? There are two cases.
+   A. When libintl.a is linked into an executable, it works because
+      functions defined in the executable always override functions in
+      the shared libraries.
+   B. When libintl.so is used, it works because
+      1. those systems defining gettext/textdomain/... in the C library
+         (namely, Solaris 2.4 and newer, and GNU libc 2.0 and newer) are
+         ELF systems and define these symbols as weak, thus explicitly
+         letting other shared libraries override it.
+      2. those systems defining gettext/textdomain/... in a standalone
+         libintl.so library (namely, Solaris 2.3 and newer) have this
+         shared library in /usr/lib, and the linker will search /usr/lib
+         *after* the directory where the GNU gettext library is installed.
+
+   A third case, namely when libintl.a is linked into a shared library
+   whose name is not libintl.so, is not supported. In this case, on
+   Solaris, when -lintl precedes the linker option for the shared library
+   containing GNU gettext, the system's gettext would indeed override
+   the GNU gettext. Anyone doing this kind of stuff must be clever enough
+   to 1. compile libintl.a with -fPIC, 2. remove -lintl from his linker
+   command line.  */
+
+
+#undef gettext
+#undef dgettext
+#undef dcgettext
+#undef ngettext
+#undef dngettext
+#undef dcngettext
+#undef textdomain
+#undef bindtextdomain
+#undef bind_textdomain_codeset
+
+
+char *
+gettext (msgid)
+     const char *msgid;
+{
+  return gettext__ (msgid);
+}
+
+
+char *
+dgettext (domainname, msgid)
+     const char *domainname;
+     const char *msgid;
+{
+  return dgettext__ (domainname, msgid);
+}
+
+
+char *
+dcgettext (domainname, msgid, category)
+     const char *domainname;
+     const char *msgid;
+     int category;
+{
+  return dcgettext__ (domainname, msgid, category);
+}
+
+
+char *
+ngettext (msgid1, msgid2, n)
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+{
+  return ngettext__ (msgid1, msgid2, n);
+}
+
+
+char *
+dngettext (domainname, msgid1, msgid2, n)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+{
+  return dngettext__ (domainname, msgid1, msgid2, n);
+}
+
+
+char *
+dcngettext (domainname, msgid1, msgid2, n, category)
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+     int category;
+{
+  return dcngettext__ (domainname, msgid1, msgid2, n, category);
+}
+
+
+char *
+textdomain (domainname)
+     const char *domainname;
+{
+  return textdomain__ (domainname);
+}
+
+
+char *
+bindtextdomain (domainname, dirname)
+     const char *domainname;
+     const char *dirname;
+{
+  return bindtextdomain__ (domainname, dirname);
+}
+
+
+char *
+bind_textdomain_codeset (domainname, codeset)
+     const char *domainname;
+     const char *codeset;
+{
+  return bind_textdomain_codeset__ (domainname, codeset);
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/l10nflist.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/l10nflist.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/l10nflist.c	(revision 1780)
@@ -0,0 +1,402 @@
+/* Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* Tell glibc's <string.h> to provide a prototype for stpcpy().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#if defined _LIBC || defined HAVE_ARGZ_H
+# include <argz.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "loadinfo.h"
+
+/* On some strange systems still no definition of NULL is found.  Sigh!  */
+#ifndef NULL
+# if defined __STDC__ && __STDC__
+#  define NULL ((void *) 0)
+# else
+#  define NULL 0
+# endif
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions.  This is required by the standard
+   because some ANSI C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# ifndef stpcpy
+#  define stpcpy(dest, src) __stpcpy(dest, src)
+# endif
+#else
+# ifndef HAVE_STPCPY
+static char *stpcpy PARAMS ((char *dest, const char *src));
+# endif
+#endif
+
+/* Define function which are usually not available.  */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
+/* Returns the number of strings in ARGZ.  */
+static size_t argz_count__ PARAMS ((const char *argz, size_t len));
+
+static size_t
+argz_count__ (argz, len)
+     const char *argz;
+     size_t len;
+{
+  size_t count = 0;
+  while (len > 0)
+    {
+      size_t part_len = strlen (argz);
+      argz += part_len + 1;
+      len -= part_len + 1;
+      count++;
+    }
+  return count;
+}
+# undef __argz_count
+# define __argz_count(argz, len) argz_count__ (argz, len)
+#endif	/* !_LIBC && !HAVE___ARGZ_COUNT */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
+/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
+   except the last into the character SEP.  */
+static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
+
+static void
+argz_stringify__ (argz, len, sep)
+     char *argz;
+     size_t len;
+     int sep;
+{
+  while (len > 0)
+    {
+      size_t part_len = strlen (argz);
+      argz += part_len;
+      len -= part_len + 1;
+      if (len > 0)
+	*argz++ = sep;
+    }
+}
+# undef __argz_stringify
+# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
+#endif	/* !_LIBC && !HAVE___ARGZ_STRINGIFY */
+
+#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
+static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
+				  const char *entry));
+
+static char *
+argz_next__ (argz, argz_len, entry)
+     char *argz;
+     size_t argz_len;
+     const char *entry;
+{
+  if (entry)
+    {
+      if (entry < argz + argz_len)
+        entry = strchr (entry, '\0') + 1;
+
+      return entry >= argz + argz_len ? NULL : (char *) entry;
+    }
+  else
+    if (argz_len > 0)
+      return argz;
+    else
+      return 0;
+}
+# undef __argz_next
+# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
+#endif	/* !_LIBC && !HAVE___ARGZ_NEXT */
+
+
+/* Return number of bits set in X.  */
+static int pop PARAMS ((int x));
+
+static inline int
+pop (x)
+     int x;
+{
+  /* We assume that no more than 16 bits are used.  */
+  x = ((x & ~0x5555) >> 1) + (x & 0x5555);
+  x = ((x & ~0x3333) >> 2) + (x & 0x3333);
+  x = ((x >> 4) + x) & 0x0f0f;
+  x = ((x >> 8) + x) & 0xff;
+
+  return x;
+}
+
+
+
+struct loaded_l10nfile *
+_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
+		    territory, codeset, normalized_codeset, modifier, special,
+		    sponsor, revision, filename, do_allocate)
+     struct loaded_l10nfile **l10nfile_list;
+     const char *dirlist;
+     size_t dirlist_len;
+     int mask;
+     const char *language;
+     const char *territory;
+     const char *codeset;
+     const char *normalized_codeset;
+     const char *modifier;
+     const char *special;
+     const char *sponsor;
+     const char *revision;
+     const char *filename;
+     int do_allocate;
+{
+  char *abs_filename;
+  struct loaded_l10nfile *last = NULL;
+  struct loaded_l10nfile *retval;
+  char *cp;
+  size_t entries;
+  int cnt;
+
+  /* Allocate room for the full file name.  */
+  abs_filename = (char *) malloc (dirlist_len
+				  + strlen (language)
+				  + ((mask & TERRITORY) != 0
+				     ? strlen (territory) + 1 : 0)
+				  + ((mask & XPG_CODESET) != 0
+				     ? strlen (codeset) + 1 : 0)
+				  + ((mask & XPG_NORM_CODESET) != 0
+				     ? strlen (normalized_codeset) + 1 : 0)
+				  + (((mask & XPG_MODIFIER) != 0
+				      || (mask & CEN_AUDIENCE) != 0)
+				     ? strlen (modifier) + 1 : 0)
+				  + ((mask & CEN_SPECIAL) != 0
+				     ? strlen (special) + 1 : 0)
+				  + (((mask & CEN_SPONSOR) != 0
+				      || (mask & CEN_REVISION) != 0)
+				     ? (1 + ((mask & CEN_SPONSOR) != 0
+					     ? strlen (sponsor) + 1 : 0)
+					+ ((mask & CEN_REVISION) != 0
+					   ? strlen (revision) + 1 : 0)) : 0)
+				  + 1 + strlen (filename) + 1);
+
+  if (abs_filename == NULL)
+    return NULL;
+
+  retval = NULL;
+  last = NULL;
+
+  /* Construct file name.  */
+  memcpy (abs_filename, dirlist, dirlist_len);
+  __argz_stringify (abs_filename, dirlist_len, PATH_SEPARATOR);
+  cp = abs_filename + (dirlist_len - 1);
+  *cp++ = '/';
+  cp = stpcpy (cp, language);
+
+  if ((mask & TERRITORY) != 0)
+    {
+      *cp++ = '_';
+      cp = stpcpy (cp, territory);
+    }
+  if ((mask & XPG_CODESET) != 0)
+    {
+      *cp++ = '.';
+      cp = stpcpy (cp, codeset);
+    }
+  if ((mask & XPG_NORM_CODESET) != 0)
+    {
+      *cp++ = '.';
+      cp = stpcpy (cp, normalized_codeset);
+    }
+  if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
+    {
+      /* This component can be part of both syntaces but has different
+	 leading characters.  For CEN we use `+', else `@'.  */
+      *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
+      cp = stpcpy (cp, modifier);
+    }
+  if ((mask & CEN_SPECIAL) != 0)
+    {
+      *cp++ = '+';
+      cp = stpcpy (cp, special);
+    }
+  if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
+    {
+      *cp++ = ',';
+      if ((mask & CEN_SPONSOR) != 0)
+	cp = stpcpy (cp, sponsor);
+      if ((mask & CEN_REVISION) != 0)
+	{
+	  *cp++ = '_';
+	  cp = stpcpy (cp, revision);
+	}
+    }
+
+  *cp++ = '/';
+  stpcpy (cp, filename);
+
+  /* Look in list of already loaded domains whether it is already
+     available.  */
+  last = NULL;
+  for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
+    if (retval->filename != NULL)
+      {
+	int compare = strcmp (retval->filename, abs_filename);
+	if (compare == 0)
+	  /* We found it!  */
+	  break;
+	if (compare < 0)
+	  {
+	    /* It's not in the list.  */
+	    retval = NULL;
+	    break;
+	  }
+
+	last = retval;
+      }
+
+  if (retval != NULL || do_allocate == 0)
+    {
+      free (abs_filename);
+      return retval;
+    }
+
+  retval = (struct loaded_l10nfile *)
+    malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
+				* (1 << pop (mask))
+				* sizeof (struct loaded_l10nfile *)));
+  if (retval == NULL)
+    return NULL;
+
+  retval->filename = abs_filename;
+  retval->decided = (__argz_count (dirlist, dirlist_len) != 1
+		     || ((mask & XPG_CODESET) != 0
+			 && (mask & XPG_NORM_CODESET) != 0));
+  retval->data = NULL;
+
+  if (last == NULL)
+    {
+      retval->next = *l10nfile_list;
+      *l10nfile_list = retval;
+    }
+  else
+    {
+      retval->next = last->next;
+      last->next = retval;
+    }
+
+  entries = 0;
+  /* If the DIRLIST is a real list the RETVAL entry corresponds not to
+     a real file.  So we have to use the DIRLIST separation mechanism
+     of the inner loop.  */
+  cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
+  for (; cnt >= 0; --cnt)
+    if ((cnt & ~mask) == 0
+	&& ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
+	&& ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
+      {
+	/* Iterate over all elements of the DIRLIST.  */
+	char *dir = NULL;
+
+	while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
+	       != NULL)
+	  retval->successor[entries++]
+	    = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
+				  language, territory, codeset,
+				  normalized_codeset, modifier, special,
+				  sponsor, revision, filename, 1);
+      }
+  retval->successor[entries] = NULL;
+
+  return retval;
+}
+
+
+/* Normalize codeset name.  There is no standard for the codeset
+   names.  Normalization allows the user to use any of the common
+   names.  The return value is dynamically allocated and has to be
+   freed by the caller.  */
+const char *
+_nl_normalize_codeset (codeset, name_len)
+     const char *codeset;
+     size_t name_len;
+{
+  int len = 0;
+  int only_digit = 1;
+  char *retval;
+  char *wp;
+  size_t cnt;
+
+  for (cnt = 0; cnt < name_len; ++cnt)
+    if (isalnum ((unsigned char) codeset[cnt]))
+      {
+	++len;
+
+	if (isalpha ((unsigned char) codeset[cnt]))
+	  only_digit = 0;
+      }
+
+  retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
+
+  if (retval != NULL)
+    {
+      if (only_digit)
+	wp = stpcpy (retval, "iso");
+      else
+	wp = retval;
+
+      for (cnt = 0; cnt < name_len; ++cnt)
+	if (isalpha ((unsigned char) codeset[cnt]))
+	  *wp++ = tolower ((unsigned char) codeset[cnt]);
+	else if (isdigit ((unsigned char) codeset[cnt]))
+	  *wp++ = codeset[cnt];
+
+      *wp = '\0';
+    }
+
+  return (const char *) retval;
+}
+
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library.  So we
+   avoid the non-standard function stpcpy.  In GNU C Library this
+   function is available, though.  Also allow the symbol HAVE_STPCPY
+   to be defined.  */
+#if !_LIBC && !HAVE_STPCPY
+static char *
+stpcpy (dest, src)
+     char *dest;
+     const char *src;
+{
+  while ((*dest++ = *src++) != '\0')
+    /* Do nothing. */ ;
+  return dest - 1;
+}
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/libgnuintl.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/libgnuintl.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/libgnuintl.h	(revision 1780)
@@ -0,0 +1,137 @@
+/* Message catalogs for internationalization.
+   Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifndef _LIBINTL_H
+#define _LIBINTL_H	1
+
+#include <locale.h>
+
+/* The LC_MESSAGES locale category is the category used by the functions
+   gettext() and dgettext().  It is specified in POSIX, but not in ANSI C.
+   On systems that don't define it, use an arbitrary value instead.
+   On Solaris, <locale.h> defines __LOCALE_H then includes <libintl.h> (i.e.
+   this file!) and then only defines LC_MESSAGES.  To avoid a redefinition
+   warning, don't define LC_MESSAGES in this case.  */
+#if !defined LC_MESSAGES && !defined __LOCALE_H
+# define LC_MESSAGES 1729
+#endif
+
+/* We define an additional symbol to signal that we use the GNU
+   implementation of gettext.  */
+#define __USE_GNU_GETTEXT 1
+
+/* Resolve a platform specific conflict on DJGPP.  GNU gettext takes
+   precedence over _conio_gettext.  */
+#ifdef __DJGPP__
+# undef gettext
+# define gettext gettext
+#endif
+
+/* Use _INTL_PARAMS, not PARAMS, in order to avoid clashes with identifiers
+   used by programs.  Similarly, test __PROTOTYPES, not PROTOTYPES.  */
+#ifndef _INTL_PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define _INTL_PARAMS(args) args
+# else
+#  define _INTL_PARAMS(args) ()
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+   LC_MESSAGES locale.  If not found, returns MSGID itself (the default
+   text).  */
+extern char *gettext _INTL_PARAMS ((const char *__msgid));
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+   LC_MESSAGES locale.  */
+extern char *dgettext _INTL_PARAMS ((const char *__domainname,
+				     const char *__msgid));
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+   locale.  */
+extern char *dcgettext _INTL_PARAMS ((const char *__domainname,
+				      const char *__msgid,
+				      int __category));
+
+
+/* Similar to `gettext' but select the plural form corresponding to the
+   number N.  */
+extern char *ngettext _INTL_PARAMS ((const char *__msgid1,
+				     const char *__msgid2,
+				     unsigned long int __n));
+
+/* Similar to `dgettext' but select the plural form corresponding to the
+   number N.  */
+extern char *dngettext _INTL_PARAMS ((const char *__domainname,
+				      const char *__msgid1,
+				      const char *__msgid2,
+				      unsigned long int __n));
+
+/* Similar to `dcgettext' but select the plural form corresponding to the
+   number N.  */
+extern char *dcngettext _INTL_PARAMS ((const char *__domainname,
+				       const char *__msgid1,
+				       const char *__msgid2,
+				       unsigned long int __n,
+				       int __category));
+
+
+/* Set the current default message catalog to DOMAINNAME.
+   If DOMAINNAME is null, return the current default.
+   If DOMAINNAME is "", reset to the default of "messages".  */
+extern char *textdomain _INTL_PARAMS ((const char *__domainname));
+
+/* Specify that the DOMAINNAME message catalog will be found
+   in DIRNAME rather than in the system locale data base.  */
+extern char *bindtextdomain _INTL_PARAMS ((const char *__domainname,
+					   const char *__dirname));
+
+/* Specify the character encoding in which the messages from the
+   DOMAINNAME message catalog will be returned.  */
+extern char *bind_textdomain_codeset _INTL_PARAMS ((const char *__domainname,
+						    const char *__codeset));
+
+
+/* Optimized version of the functions above.  */
+#if defined __OPTIMIZED
+/* These are macros, but could also be inline functions.  */
+
+# define gettext(msgid)							      \
+  dgettext (NULL, msgid)
+
+# define dgettext(domainname, msgid)					      \
+  dcgettext (domainname, msgid, LC_MESSAGES)
+
+# define ngettext(msgid1, msgid2, n)					      \
+  dngettext (NULL, msgid1, msgid2, n)
+
+# define dngettext(domainname, msgid1, msgid2, n)			      \
+  dcngettext (domainname, msgid1, msgid2, n, LC_MESSAGES)
+
+#endif /* Optimizing. */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* libintl.h */
Index: /tags/kBuild-0.1.4/src/sed/intl/loadinfo.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/loadinfo.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/loadinfo.h	(revision 1780)
@@ -0,0 +1,121 @@
+/* Copyright (C) 1996-1999, 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifndef _LOADINFO_H
+#define _LOADINFO_H	1
+
+/* Declarations of locale dependent catalog lookup functions.
+   Implemented in
+
+     localealias.c    Possibly replace a locale name by another.
+     explodename.c    Split a locale name into its various fields.
+     l10nflist.c      Generate a list of filenames of possible message catalogs.
+     finddomain.c     Find and open the relevant message catalogs.
+
+   The main function _nl_find_domain() in finddomain.c is declared
+   in gettextP.h.
+ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+/* Tell the compiler when a conditional or integer expression is
+   almost always true or almost always false.  */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+/* Separator in PATH like lists of pathnames.  */
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
+# define PATH_SEPARATOR ';'
+#else
+  /* Unix */
+# define PATH_SEPARATOR ':'
+#endif
+
+/* Encoding of locale name parts.  */
+#define CEN_REVISION		1
+#define CEN_SPONSOR		2
+#define CEN_SPECIAL		4
+#define XPG_NORM_CODESET	8
+#define XPG_CODESET		16
+#define TERRITORY		32
+#define CEN_AUDIENCE		64
+#define XPG_MODIFIER		128
+
+#define CEN_SPECIFIC	(CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE)
+#define XPG_SPECIFIC	(XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER)
+
+
+struct loaded_l10nfile
+{
+  const char *filename;
+  int decided;
+
+  const void *data;
+
+  struct loaded_l10nfile *next;
+  struct loaded_l10nfile *successor[1];
+};
+
+
+/* Normalize codeset name.  There is no standard for the codeset
+   names.  Normalization allows the user to use any of the common
+   names.  The return value is dynamically allocated and has to be
+   freed by the caller.  */
+extern const char *_nl_normalize_codeset PARAMS ((const char *codeset,
+						  size_t name_len));
+
+extern struct loaded_l10nfile *
+_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list,
+			    const char *dirlist, size_t dirlist_len, int mask,
+			    const char *language, const char *territory,
+			    const char *codeset,
+			    const char *normalized_codeset,
+			    const char *modifier, const char *special,
+			    const char *sponsor, const char *revision,
+			    const char *filename, int do_allocate));
+
+
+extern const char *_nl_expand_alias PARAMS ((const char *name));
+
+/* normalized_codeset is dynamically allocated and has to be freed by
+   the caller.  */
+extern int _nl_explode_name PARAMS ((char *name, const char **language,
+				     const char **modifier,
+				     const char **territory,
+				     const char **codeset,
+				     const char **normalized_codeset,
+				     const char **special,
+				     const char **sponsor,
+				     const char **revision));
+
+extern char *_nl_find_language PARAMS ((const char *name));
+
+#endif	/* loadinfo.h */
Index: /tags/kBuild-0.1.4/src/sed/intl/loadmsgcat.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/loadmsgcat.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/loadmsgcat.c	(revision 1780)
@@ -0,0 +1,445 @@
+/* Load needed message catalogs.
+   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE    1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#ifdef _LIBC
+# include <langinfo.h>
+# include <locale.h>
+#endif
+
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
+    || (defined _LIBC && defined _POSIX_MAPPED_FILES)
+# include <sys/mman.h>
+# undef HAVE_MMAP
+# define HAVE_MMAP	1
+#else
+# undef HAVE_MMAP
+#endif
+
+#include "gmo.h"
+#include "gettextP.h"
+#include "plural-exp.h"
+
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ISO C functions.  This is required by the standard
+   because some ISO C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# define open   __open
+# define close  __close
+# define read   __read
+# define mmap   __mmap
+# define munmap __munmap
+#endif
+
+/* For those losing systems which don't have `alloca' we have to add
+   some additional code emulating it.  */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+/* For systems that distinguish between text and binary I/O.
+   O_BINARY is usually declared in <fcntl.h>. */
+#if !defined O_BINARY && defined _O_BINARY
+  /* For MSC-compatible compilers.  */
+# define O_BINARY _O_BINARY
+# define O_TEXT _O_TEXT
+#endif
+#ifdef __BEOS__
+  /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect.  */
+# undef O_BINARY
+# undef O_TEXT
+#endif
+/* On reasonable systems, binary I/O is the default.  */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+/* We need a sign, whether a new catalog was loaded, which can be associated
+   with all translations.  This is important if the translations are
+   cached by one of GCC's features.  */
+int _nl_msg_cat_cntr;
+
+
+/* Initialize the codeset dependent parts of an opened message catalog.
+   Return the header entry.  */
+const char *
+internal_function
+_nl_init_domain_conv (domain_file, domain, domainbinding)
+     struct loaded_l10nfile *domain_file;
+     struct loaded_domain *domain;
+     struct binding *domainbinding;
+{
+  /* Find out about the character set the file is encoded with.
+     This can be found (in textual form) in the entry "".  If this
+     entry does not exist or if this does not contain the `charset='
+     information, we will assume the charset matches the one the
+     current locale and we don't have to perform any conversion.  */
+  char *nullentry;
+  size_t nullentrylen;
+
+  /* Preinitialize fields, to avoid recursion during _nl_find_msg.  */
+  domain->codeset_cntr =
+    (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
+#ifdef _LIBC
+  domain->conv = (__gconv_t) -1;
+#else
+# if HAVE_ICONV
+  domain->conv = (iconv_t) -1;
+# endif
+#endif
+  domain->conv_tab = NULL;
+
+  /* Get the header entry.  */
+  nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
+
+  if (nullentry != NULL)
+    {
+#if defined _LIBC || HAVE_ICONV
+      const char *charsetstr;
+
+      charsetstr = strstr (nullentry, "charset=");
+      if (charsetstr != NULL)
+	{
+	  size_t len;
+	  char *charset;
+	  const char *outcharset;
+
+	  charsetstr += strlen ("charset=");
+	  len = strcspn (charsetstr, " \t\n");
+
+	  charset = (char *) alloca (len + 1);
+# if defined _LIBC || HAVE_MEMPCPY
+	  *((char *) mempcpy (charset, charsetstr, len)) = '\0';
+# else
+	  memcpy (charset, charsetstr, len);
+	  charset[len] = '\0';
+# endif
+
+	  /* The output charset should normally be determined by the
+	     locale.  But sometimes the locale is not used or not correctly
+	     set up, so we provide a possibility for the user to override
+	     this.  Moreover, the value specified through
+	     bind_textdomain_codeset overrides both.  */
+	  if (domainbinding != NULL && domainbinding->codeset != NULL)
+	    outcharset = domainbinding->codeset;
+	  else
+	    {
+	      outcharset = getenv ("OUTPUT_CHARSET");
+	      if (outcharset == NULL || outcharset[0] == '\0')
+		{
+# ifdef _LIBC
+		  outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
+# else
+#  if HAVE_ICONV
+		  extern const char *locale_charset PARAMS ((void));
+		  outcharset = locale_charset ();
+#  endif
+# endif
+		}
+	    }
+
+# ifdef _LIBC
+	  /* We always want to use transliteration.  */
+	  outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+	  charset = norm_add_slashes (charset, NULL);
+	  if (__gconv_open (outcharset, charset, &domain->conv,
+			    GCONV_AVOID_NOCONV)
+	      != __GCONV_OK)
+	    domain->conv = (__gconv_t) -1;
+# else
+#  if HAVE_ICONV
+	  /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
+	     we want to use transliteration.  */
+#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
+       || _LIBICONV_VERSION >= 0x0105
+	  len = strlen (outcharset);
+	  {
+	    char *tmp = (char *) alloca (len + 10 + 1);
+	    memcpy (tmp, outcharset, len);
+	    memcpy (tmp + len, "//TRANSLIT", 10 + 1);
+	    outcharset = tmp;
+	  }
+#   endif
+	  domain->conv = iconv_open (outcharset, charset);
+#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
+       || _LIBICONV_VERSION >= 0x0105
+	  freea (outcharset);
+#   endif
+#  endif
+# endif
+
+	  freea (charset);
+	}
+#endif /* _LIBC || HAVE_ICONV */
+    }
+
+  return nullentry;
+}
+
+/* Frees the codeset dependent parts of an opened message catalog.  */
+void
+internal_function
+_nl_free_domain_conv (domain)
+     struct loaded_domain *domain;
+{
+  if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
+    free (domain->conv_tab);
+
+#ifdef _LIBC
+  if (domain->conv != (__gconv_t) -1)
+    __gconv_close (domain->conv);
+#else
+# if HAVE_ICONV
+  if (domain->conv != (iconv_t) -1)
+    iconv_close (domain->conv);
+# endif
+#endif
+}
+
+/* Load the message catalogs specified by FILENAME.  If it is no valid
+   message catalog do nothing.  */
+void
+internal_function
+_nl_load_domain (domain_file, domainbinding)
+     struct loaded_l10nfile *domain_file;
+     struct binding *domainbinding;
+{
+  int fd;
+  size_t size;
+#ifdef _LIBC
+  struct stat64 st;
+#else
+  struct stat st;
+#endif
+  struct mo_file_header *data = (struct mo_file_header *) -1;
+  int use_mmap = 0;
+  struct loaded_domain *domain;
+  const char *nullentry;
+
+  domain_file->decided = 1;
+  domain_file->data = NULL;
+
+  /* Note that it would be useless to store domainbinding in domain_file
+     because domainbinding might be == NULL now but != NULL later (after
+     a call to bind_textdomain_codeset).  */
+
+  /* If the record does not represent a valid locale the FILENAME
+     might be NULL.  This can happen when according to the given
+     specification the locale file name is different for XPG and CEN
+     syntax.  */
+  if (domain_file->filename == NULL)
+    return;
+
+  /* Try to open the addressed file.  */
+  fd = open (domain_file->filename, O_RDONLY | O_BINARY);
+  if (fd == -1)
+    return;
+
+  /* We must know about the size of the file.  */
+  if (
+#ifdef _LIBC
+      __builtin_expect (fstat64 (fd, &st) != 0, 0)
+#else
+      __builtin_expect (fstat (fd, &st) != 0, 0)
+#endif
+      || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
+      || __builtin_expect (size < sizeof (struct mo_file_header), 0))
+    {
+      /* Something went wrong.  */
+      close (fd);
+      return;
+    }
+
+#ifdef HAVE_MMAP
+  /* Now we are ready to load the file.  If mmap() is available we try
+     this first.  If not available or it failed we try to load it.  */
+  data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
+					 MAP_PRIVATE, fd, 0);
+
+  if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
+    {
+      /* mmap() call was successful.  */
+      close (fd);
+      use_mmap = 1;
+    }
+#endif
+
+  /* If the data is not yet available (i.e. mmap'ed) we try to load
+     it manually.  */
+  if (data == (struct mo_file_header *) -1)
+    {
+      size_t to_read;
+      char *read_ptr;
+
+      data = (struct mo_file_header *) malloc (size);
+      if (data == NULL)
+	return;
+
+      to_read = size;
+      read_ptr = (char *) data;
+      do
+	{
+	  long int nb = (long int) read (fd, read_ptr, to_read);
+	  if (nb <= 0)
+	    {
+#ifdef EINTR
+	      if (nb == -1 && errno == EINTR)
+		continue;
+#endif
+	      close (fd);
+	      return;
+	    }
+	  read_ptr += nb;
+	  to_read -= nb;
+	}
+      while (to_read > 0);
+
+      close (fd);
+    }
+
+  /* Using the magic number we can test whether it really is a message
+     catalog file.  */
+  if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
+			0))
+    {
+      /* The magic number is wrong: not a message catalog file.  */
+#ifdef HAVE_MMAP
+      if (use_mmap)
+	munmap ((caddr_t) data, size);
+      else
+#endif
+	free (data);
+      return;
+    }
+
+  domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
+  if (domain == NULL)
+    return;
+  domain_file->data = domain;
+
+  domain->data = (char *) data;
+  domain->use_mmap = use_mmap;
+  domain->mmap_size = size;
+  domain->must_swap = data->magic != _MAGIC;
+
+  /* Fill in the information about the available tables.  */
+  switch (W (domain->must_swap, data->revision))
+    {
+    case 0:
+      domain->nstrings = W (domain->must_swap, data->nstrings);
+      domain->orig_tab = (struct string_desc *)
+	((char *) data + W (domain->must_swap, data->orig_tab_offset));
+      domain->trans_tab = (struct string_desc *)
+	((char *) data + W (domain->must_swap, data->trans_tab_offset));
+      domain->hash_size = W (domain->must_swap, data->hash_tab_size);
+      domain->hash_tab = (nls_uint32 *)
+	((char *) data + W (domain->must_swap, data->hash_tab_offset));
+      break;
+    default:
+      /* This is an invalid revision.  */
+#ifdef HAVE_MMAP
+      if (use_mmap)
+	munmap ((caddr_t) data, size);
+      else
+#endif
+	free (data);
+      free (domain);
+      domain_file->data = NULL;
+      return;
+    }
+
+  /* Now initialize the character set converter from the character set
+     the file is encoded with (found in the header entry) to the domain's
+     specified character set or the locale's character set.  */
+  nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
+
+  /* Also look for a plural specification.  */
+  EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
+}
+
+
+#ifdef _LIBC
+void
+internal_function
+_nl_unload_domain (domain)
+     struct loaded_domain *domain;
+{
+  if (domain->plural != &__gettext_germanic_plural)
+    __gettext_free_exp (domain->plural);
+
+  _nl_free_domain_conv (domain);
+
+# ifdef _POSIX_MAPPED_FILES
+  if (domain->use_mmap)
+    munmap ((caddr_t) domain->data, domain->mmap_size);
+  else
+# endif	/* _POSIX_MAPPED_FILES */
+    free ((void *) domain->data);
+
+  free (domain);
+}
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/localcharset.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/localcharset.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/localcharset.c	(revision 1780)
@@ -0,0 +1,345 @@
+/* Determine a canonical name for the current locale's character encoding.
+
+   Copyright (C) 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* Written by Bruno Haible <haible@clisp.cons.org>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# undef WIN32   /* avoid warning on mingw32 */
+# define WIN32
+#endif
+
+#if defined __EMX__
+/* Assume EMX program runs on OS/2, even if compiled under DOS.  */
+# define OS2
+#endif
+
+#if !defined WIN32
+# if HAVE_LANGINFO_CODESET
+#  include <langinfo.h>
+# else
+#  if HAVE_SETLOCALE
+#   include <locale.h>
+#  endif
+# endif
+#elif defined WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+#if defined OS2
+# define INCL_DOS
+# include <os2.h>
+#endif
+
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+#endif
+
+#ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+#endif
+
+#ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+#endif
+
+#ifdef HAVE_GETC_UNLOCKED
+# undef getc
+# define getc getc_unlocked
+#endif
+
+/* The following static variable is declared 'volatile' to avoid a
+   possible multithread problem in the function get_charset_aliases. If we
+   are running in a threaded environment, and if two threads initialize
+   'charset_aliases' simultaneously, both will produce the same value,
+   and everything will be ok if the two assignments to 'charset_aliases'
+   are atomic. But I don't know what will happen if the two assignments mix.  */
+#if __STDC__ != 1
+# define volatile /* empty */
+#endif
+/* Pointer to the contents of the charset.alias file, if it has already been
+   read, else NULL.  Its format is:
+   ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0'  */
+static const char * volatile charset_aliases;
+
+/* Return a pointer to the contents of the charset.alias file.  */
+static const char *
+get_charset_aliases ()
+{
+  const char *cp;
+
+  cp = charset_aliases;
+  if (cp == NULL)
+    {
+#if !defined WIN32
+      FILE *fp;
+      const char *dir = LIBDIR;
+      const char *base = "charset.alias";
+      char *file_name;
+
+      /* Concatenate dir and base into freshly allocated file_name.  */
+      {
+	size_t dir_len = strlen (dir);
+	size_t base_len = strlen (base);
+	int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
+	file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
+	if (file_name != NULL)
+	  {
+	    memcpy (file_name, dir, dir_len);
+	    if (add_slash)
+	      file_name[dir_len] = DIRECTORY_SEPARATOR;
+	    memcpy (file_name + dir_len + add_slash, base, base_len + 1);
+	  }
+      }
+
+      if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL)
+	/* Out of memory or file not found, treat it as empty.  */
+	cp = "";
+      else
+	{
+	  /* Parse the file's contents.  */
+	  int c;
+	  char buf1[50+1];
+	  char buf2[50+1];
+	  char *res_ptr = NULL;
+	  size_t res_size = 0;
+	  size_t l1, l2;
+
+	  for (;;)
+	    {
+	      c = getc (fp);
+	      if (c == EOF)
+		break;
+	      if (c == '\n' || c == ' ' || c == '\t')
+		continue;
+	      if (c == '#')
+		{
+		  /* Skip comment, to end of line.  */
+		  do
+		    c = getc (fp);
+		  while (!(c == EOF || c == '\n'));
+		  if (c == EOF)
+		    break;
+		  continue;
+		}
+	      ungetc (c, fp);
+	      if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
+		break;
+	      l1 = strlen (buf1);
+	      l2 = strlen (buf2);
+	      if (res_size == 0)
+		{
+		  res_size = l1 + 1 + l2 + 1;
+		  res_ptr = (char *) malloc (res_size + 1);
+		}
+	      else
+		{
+		  res_size += l1 + 1 + l2 + 1;
+		  res_ptr = (char *) realloc (res_ptr, res_size + 1);
+		}
+	      if (res_ptr == NULL)
+		{
+		  /* Out of memory. */
+		  res_size = 0;
+		  break;
+		}
+	      strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
+	      strcpy (res_ptr + res_size - (l2 + 1), buf2);
+	    }
+	  fclose (fp);
+	  if (res_size == 0)
+	    cp = "";
+	  else
+	    {
+	      *(res_ptr + res_size) = '\0';
+	      cp = res_ptr;
+	    }
+	}
+
+      if (file_name != NULL)
+	free (file_name);
+
+#else
+
+      /* To avoid the troubles of installing a separate file in the same
+	 directory as the DLL and of retrieving the DLL's directory at
+	 runtime, simply inline the aliases here.  */
+
+# if defined WIN32
+      cp = "CP936" "\0" "GBK" "\0"
+	   "CP1361" "\0" "JOHAB" "\0";
+# endif
+#endif
+
+      charset_aliases = cp;
+    }
+
+  return cp;
+}
+
+/* Determine the current locale's character encoding, and canonicalize it
+   into one of the canonical names listed in config.charset.
+   The result must not be freed; it is statically allocated.
+   If the canonical name cannot be determined, the result is a non-canonical
+   name.  */
+
+#ifdef STATIC
+STATIC
+#endif
+const char *
+locale_charset ()
+{
+  const char *codeset;
+  const char *aliases;
+
+#if !(defined WIN32 || defined OS2)
+
+# if HAVE_LANGINFO_CODESET
+
+  /* Most systems support nl_langinfo (CODESET) nowadays.  */
+  codeset = nl_langinfo (CODESET);
+
+# else
+
+  /* On old systems which lack it, use setlocale or getenv.  */
+  const char *locale = NULL;
+
+  /* But most old systems don't have a complete set of locales.  Some
+     (like SunOS 4 or DJGPP) have only the C locale.  Therefore we don't
+     use setlocale here; it would return "C" when it doesn't support the
+     locale name the user has set.  */
+#  if HAVE_SETLOCALE && 0
+  locale = setlocale (LC_CTYPE, NULL);
+#  endif
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_ALL");
+      if (locale == NULL || locale[0] == '\0')
+	{
+	  locale = getenv ("LC_CTYPE");
+	  if (locale == NULL || locale[0] == '\0')
+	    locale = getenv ("LANG");
+	}
+    }
+
+  /* On some old systems, one used to set locale = "iso8859_1". On others,
+     you set it to "language_COUNTRY.charset". In any case, we resolve it
+     through the charset.alias file.  */
+  codeset = locale;
+
+# endif
+
+#elif defined WIN32
+
+  static char buf[2 + 10 + 1];
+
+  /* Win32 has a function returning the locale's codepage as a number.  */
+  sprintf (buf, "CP%u", GetACP ());
+  codeset = buf;
+
+#elif defined OS2
+
+  const char *locale;
+  static char buf[2 + 10 + 1];
+  ULONG cp[3];
+  ULONG cplen;
+
+  /* Allow user to override the codeset, as set in the operating system,
+     with standard language environment variables.  */
+  locale = getenv ("LC_ALL");
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_CTYPE");
+      if (locale == NULL || locale[0] == '\0')
+	locale = getenv ("LANG");
+    }
+  if (locale != NULL && locale[0] != '\0')
+    {
+      /* If the locale name contains an encoding after the dot, return it.  */
+      const char *dot = strchr (locale, '.');
+
+      if (dot != NULL)
+	{
+	  const char *modifier;
+
+	  dot++;
+	  /* Look for the possible @... trailer and remove it, if any.  */
+	  modifier = strchr (dot, '@');
+	  if (modifier == NULL)
+	    return dot;
+	  if (modifier - dot < sizeof (buf))
+	    {
+	      memcpy (buf, dot, modifier - dot);
+	      buf [modifier - dot] = '\0';
+	      return buf;
+	    }
+	}
+
+      /* Resolve through the charset.alias file.  */
+      codeset = locale;
+    }
+  else
+    {
+      /* OS/2 has a function returning the locale's codepage as a number.  */
+      if (DosQueryCp (sizeof (cp), cp, &cplen))
+	codeset = "";
+      else
+	{
+	  sprintf (buf, "CP%u", cp[0]);
+	  codeset = buf;
+	}
+    }
+
+#endif
+
+  if (codeset == NULL)
+    /* The canonical name cannot be determined.  */
+    codeset = "";
+
+  /* Resolve alias. */
+  for (aliases = get_charset_aliases ();
+       *aliases != '\0';
+       aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
+    if (strcmp (codeset, aliases) == 0
+	|| (aliases[0] == '*' && aliases[1] == '\0'))
+      {
+	codeset = aliases + strlen (aliases) + 1;
+	break;
+      }
+
+  return codeset;
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/locale.alias
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/locale.alias	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/locale.alias	(revision 1780)
@@ -0,0 +1,78 @@
+# Locale name alias data base.
+# Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library General Public License as published
+# by the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+# The format of this file is the same as for the corresponding file of
+# the X Window System, which normally can be found in
+#	/usr/lib/X11/locale/locale.alias
+# A single line contains two fields: an alias and a substitution value.
+# All entries are case independent.
+
+# Note: This file is far from being complete.  If you have a value for
+# your own site which you think might be useful for others too, share
+# it with the rest of us.  Send it using the `glibcbug' script to
+# bugs@gnu.org.
+
+# Packages using this file: 
+
+bokmal		no_NO.ISO-8859-1
+bokmål		no_NO.ISO-8859-1
+catalan		ca_ES.ISO-8859-1
+croatian	hr_HR.ISO-8859-2
+czech		cs_CZ.ISO-8859-2
+danish          da_DK.ISO-8859-1
+dansk		da_DK.ISO-8859-1
+deutsch		de_DE.ISO-8859-1
+dutch		nl_NL.ISO-8859-1
+eesti		et_EE.ISO-8859-1
+estonian	et_EE.ISO-8859-1
+finnish         fi_FI.ISO-8859-1
+français	fr_FR.ISO-8859-1
+french		fr_FR.ISO-8859-1
+galego		gl_ES.ISO-8859-1
+galician	gl_ES.ISO-8859-1
+german		de_DE.ISO-8859-1
+greek           el_GR.ISO-8859-7
+hebrew          he_IL.ISO-8859-8
+hrvatski	hr_HR.ISO-8859-2
+hungarian       hu_HU.ISO-8859-2
+icelandic       is_IS.ISO-8859-1
+italian         it_IT.ISO-8859-1
+japanese	ja_JP.eucJP
+japanese.euc	ja_JP.eucJP
+ja_JP		ja_JP.eucJP
+ja_JP.ujis	ja_JP.eucJP
+japanese.sjis	ja_JP.SJIS
+korean		ko_KR.eucKR
+korean.euc 	ko_KR.eucKR
+ko_KR		ko_KR.eucKR
+lithuanian      lt_LT.ISO-8859-13
+nb_NO		no_NO.ISO-8859-1
+nb_NO.ISO-8859-1 no_NO.ISO-8859-1
+norwegian       no_NO.ISO-8859-1
+nynorsk		nn_NO.ISO-8859-1
+polish          pl_PL.ISO-8859-2
+portuguese      pt_PT.ISO-8859-1
+romanian        ro_RO.ISO-8859-2
+russian         ru_RU.ISO-8859-5
+slovak          sk_SK.ISO-8859-2
+slovene         sl_SI.ISO-8859-2
+slovenian       sl_SI.ISO-8859-2
+spanish         es_ES.ISO-8859-1
+swedish         sv_SE.ISO-8859-1
+thai		th_TH.TIS-620
+turkish         tr_TR.ISO-8859-9
Index: /tags/kBuild-0.1.4/src/sed/intl/localealias.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/localealias.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/localealias.c	(revision 1780)
@@ -0,0 +1,419 @@
+/* Handle aliases for locale names.
+   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE    1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#if defined _LIBC || defined HAVE___FSETLOCKING
+# include <stdio_ext.h>
+#endif
+#include <sys/types.h>
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettextP.h"
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions.  This is required by the standard
+   because some ANSI C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# define strcasecmp __strcasecmp
+
+# ifndef mempcpy
+#  define mempcpy __mempcpy
+# endif
+# define HAVE_MEMPCPY	1
+# define HAVE___FSETLOCKING	1
+
+/* We need locking here since we can be called from different places.  */
+# include <bits/libc-lock.h>
+
+__libc_lock_define_initialized (static, lock);
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+/* Some optimizations for glibc.  */
+#ifdef _LIBC
+# define FEOF(fp)		feof_unlocked (fp)
+# define FGETS(buf, n, fp)	fgets_unlocked (buf, n, fp)
+#else
+# define FEOF(fp)		feof (fp)
+# define FGETS(buf, n, fp)	fgets (buf, n, fp)
+#endif
+
+/* For those losing systems which don't have `alloca' we have to add
+   some additional code emulating it.  */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED
+# undef fgets
+# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
+#endif
+#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED
+# undef feof
+# define feof(s) feof_unlocked (s)
+#endif
+
+
+struct alias_map
+{
+  const char *alias;
+  const char *value;
+};
+
+
+static char *string_space;
+static size_t string_space_act;
+static size_t string_space_max;
+static struct alias_map *map;
+static size_t nmap;
+static size_t maxmap;
+
+
+/* Prototypes for local functions.  */
+static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
+     internal_function;
+static int extend_alias_table PARAMS ((void));
+static int alias_compare PARAMS ((const struct alias_map *map1,
+				  const struct alias_map *map2));
+
+
+const char *
+_nl_expand_alias (name)
+    const char *name;
+{
+  static const char *locale_alias_path;
+  struct alias_map *retval;
+  const char *result = NULL;
+  size_t added;
+
+#ifdef _LIBC
+  __libc_lock_lock (lock);
+#endif
+
+  if (locale_alias_path == NULL)
+    locale_alias_path = LOCALE_ALIAS_PATH;
+
+  do
+    {
+      struct alias_map item;
+
+      item.alias = name;
+
+      if (nmap > 0)
+	retval = (struct alias_map *) bsearch (&item, map, nmap,
+					       sizeof (struct alias_map),
+					       (int (*) PARAMS ((const void *,
+								 const void *))
+						) alias_compare);
+      else
+	retval = NULL;
+
+      /* We really found an alias.  Return the value.  */
+      if (retval != NULL)
+	{
+	  result = retval->value;
+	  break;
+	}
+
+      /* Perhaps we can find another alias file.  */
+      added = 0;
+      while (added == 0 && locale_alias_path[0] != '\0')
+	{
+	  const char *start;
+
+	  while (locale_alias_path[0] == PATH_SEPARATOR)
+	    ++locale_alias_path;
+	  start = locale_alias_path;
+
+	  while (locale_alias_path[0] != '\0'
+		 && locale_alias_path[0] != PATH_SEPARATOR)
+	    ++locale_alias_path;
+
+	  if (start < locale_alias_path)
+	    added = read_alias_file (start, locale_alias_path - start);
+	}
+    }
+  while (added != 0);
+
+#ifdef _LIBC
+  __libc_lock_unlock (lock);
+#endif
+
+  return result;
+}
+
+
+static size_t
+internal_function
+read_alias_file (fname, fname_len)
+     const char *fname;
+     int fname_len;
+{
+  FILE *fp;
+  char *full_fname;
+  size_t added;
+  static const char aliasfile[] = "/locale.alias";
+
+  full_fname = (char *) alloca (fname_len + sizeof aliasfile);
+#ifdef HAVE_MEMPCPY
+  mempcpy (mempcpy (full_fname, fname, fname_len),
+	   aliasfile, sizeof aliasfile);
+#else
+  memcpy (full_fname, fname, fname_len);
+  memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
+#endif
+
+  fp = fopen (full_fname, "r");
+  freea (full_fname);
+  if (fp == NULL)
+    return 0;
+
+#ifdef HAVE___FSETLOCKING
+  /* No threads present.  */
+  __fsetlocking (fp, FSETLOCKING_BYCALLER);
+#endif
+
+  added = 0;
+  while (!FEOF (fp))
+    {
+      /* It is a reasonable approach to use a fix buffer here because
+	 a) we are only interested in the first two fields
+	 b) these fields must be usable as file names and so must not
+	    be that long
+       */
+      char buf[BUFSIZ];
+      char *alias;
+      char *value;
+      char *cp;
+
+      if (FGETS (buf, sizeof buf, fp) == NULL)
+	/* EOF reached.  */
+	break;
+
+      /* Possibly not the whole line fits into the buffer.  Ignore
+	 the rest of the line.  */
+      if (strchr (buf, '\n') == NULL)
+	{
+	  char altbuf[BUFSIZ];
+	  do
+	    if (FGETS (altbuf, sizeof altbuf, fp) == NULL)
+	      /* Make sure the inner loop will be left.  The outer loop
+		 will exit at the `feof' test.  */
+	      break;
+	  while (strchr (altbuf, '\n') == NULL);
+	}
+
+      cp = buf;
+      /* Ignore leading white space.  */
+      while (isspace ((unsigned char) cp[0]))
+	++cp;
+
+      /* A leading '#' signals a comment line.  */
+      if (cp[0] != '\0' && cp[0] != '#')
+	{
+	  alias = cp++;
+	  while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
+	    ++cp;
+	  /* Terminate alias name.  */
+	  if (cp[0] != '\0')
+	    *cp++ = '\0';
+
+	  /* Now look for the beginning of the value.  */
+	  while (isspace ((unsigned char) cp[0]))
+	    ++cp;
+
+	  if (cp[0] != '\0')
+	    {
+	      size_t alias_len;
+	      size_t value_len;
+
+	      value = cp++;
+	      while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
+		++cp;
+	      /* Terminate value.  */
+	      if (cp[0] == '\n')
+		{
+		  /* This has to be done to make the following test
+		     for the end of line possible.  We are looking for
+		     the terminating '\n' which do not overwrite here.  */
+		  *cp++ = '\0';
+		  *cp = '\n';
+		}
+	      else if (cp[0] != '\0')
+		*cp++ = '\0';
+
+	      if (nmap >= maxmap)
+		if (__builtin_expect (extend_alias_table (), 0))
+		  return added;
+
+	      alias_len = strlen (alias) + 1;
+	      value_len = strlen (value) + 1;
+
+	      if (string_space_act + alias_len + value_len > string_space_max)
+		{
+		  /* Increase size of memory pool.  */
+		  size_t new_size = (string_space_max
+				     + (alias_len + value_len > 1024
+					? alias_len + value_len : 1024));
+		  char *new_pool = (char *) realloc (string_space, new_size);
+		  if (new_pool == NULL)
+		    return added;
+
+		  if (__builtin_expect (string_space != new_pool, 0))
+		    {
+		      size_t i;
+
+		      for (i = 0; i < nmap; i++)
+			{
+			  map[i].alias += new_pool - string_space;
+			  map[i].value += new_pool - string_space;
+			}
+		    }
+
+		  string_space = new_pool;
+		  string_space_max = new_size;
+		}
+
+	      map[nmap].alias = memcpy (&string_space[string_space_act],
+					alias, alias_len);
+	      string_space_act += alias_len;
+
+	      map[nmap].value = memcpy (&string_space[string_space_act],
+					value, value_len);
+	      string_space_act += value_len;
+
+	      ++nmap;
+	      ++added;
+	    }
+	}
+    }
+
+  /* Should we test for ferror()?  I think we have to silently ignore
+     errors.  --drepper  */
+  fclose (fp);
+
+  if (added > 0)
+    qsort (map, nmap, sizeof (struct alias_map),
+	   (int (*) PARAMS ((const void *, const void *))) alias_compare);
+
+  return added;
+}
+
+
+static int
+extend_alias_table ()
+{
+  size_t new_size;
+  struct alias_map *new_map;
+
+  new_size = maxmap == 0 ? 100 : 2 * maxmap;
+  new_map = (struct alias_map *) realloc (map, (new_size
+						* sizeof (struct alias_map)));
+  if (new_map == NULL)
+    /* Simply don't extend: we don't have any more core.  */
+    return -1;
+
+  map = new_map;
+  maxmap = new_size;
+  return 0;
+}
+
+
+#ifdef _LIBC
+static void __attribute__ ((unused))
+free_mem (void)
+{
+  if (string_space != NULL)
+    free (string_space);
+  if (map != NULL)
+    free (map);
+}
+text_set_element (__libc_subfreeres, free_mem);
+#endif
+
+
+static int
+alias_compare (map1, map2)
+     const struct alias_map *map1;
+     const struct alias_map *map2;
+{
+#if defined _LIBC || defined HAVE_STRCASECMP
+  return strcasecmp (map1->alias, map2->alias);
+#else
+  const unsigned char *p1 = (const unsigned char *) map1->alias;
+  const unsigned char *p2 = (const unsigned char *) map2->alias;
+  unsigned char c1, c2;
+
+  if (p1 == p2)
+    return 0;
+
+  do
+    {
+      /* I know this seems to be odd but the tolower() function in
+	 some systems libc cannot handle nonalpha characters.  */
+      c1 = isupper (*p1) ? tolower (*p1) : *p1;
+      c2 = isupper (*p2) ? tolower (*p2) : *p2;
+      if (c1 == '\0')
+	break;
+      ++p1;
+      ++p2;
+    }
+  while (c1 == c2);
+
+  return c1 - c2;
+#endif
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/localename.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/localename.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/localename.c	(revision 1780)
@@ -0,0 +1,696 @@
+/* Determine the current selected locale.
+   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Ulrich Drepper <drepper@gnu.org>, 1995.  */
+/* Win32 code written by Tor Lillqvist <tml@iki.fi>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <locale.h>
+
+#if defined _WIN32 || defined __WIN32__
+# undef WIN32   /* avoid warning on mingw32 */
+# define WIN32
+#endif
+
+#ifdef WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* Mingw headers don't have latest language and sublanguage codes.  */
+# ifndef LANG_AFRIKAANS
+# define LANG_AFRIKAANS 0x36
+# endif
+# ifndef LANG_ALBANIAN
+# define LANG_ALBANIAN 0x1c
+# endif
+# ifndef LANG_ARABIC
+# define LANG_ARABIC 0x01
+# endif
+# ifndef LANG_ARMENIAN
+# define LANG_ARMENIAN 0x2b
+# endif
+# ifndef LANG_ASSAMESE
+# define LANG_ASSAMESE 0x4d
+# endif
+# ifndef LANG_AZERI
+# define LANG_AZERI 0x2c
+# endif
+# ifndef LANG_BASQUE
+# define LANG_BASQUE 0x2d
+# endif
+# ifndef LANG_BELARUSIAN
+# define LANG_BELARUSIAN 0x23
+# endif
+# ifndef LANG_BENGALI
+# define LANG_BENGALI 0x45
+# endif
+# ifndef LANG_CATALAN
+# define LANG_CATALAN 0x03
+# endif
+# ifndef LANG_ESTONIAN
+# define LANG_ESTONIAN 0x25
+# endif
+# ifndef LANG_FAEROESE
+# define LANG_FAEROESE 0x38
+# endif
+# ifndef LANG_FARSI
+# define LANG_FARSI 0x29
+# endif
+# ifndef LANG_GEORGIAN
+# define LANG_GEORGIAN 0x37
+# endif
+# ifndef LANG_GUJARATI
+# define LANG_GUJARATI 0x47
+# endif
+# ifndef LANG_HEBREW
+# define LANG_HEBREW 0x0d
+# endif
+# ifndef LANG_HINDI
+# define LANG_HINDI 0x39
+# endif
+# ifndef LANG_INDONESIAN
+# define LANG_INDONESIAN 0x21
+# endif
+# ifndef LANG_KANNADA
+# define LANG_KANNADA 0x4b
+# endif
+# ifndef LANG_KASHMIRI
+# define LANG_KASHMIRI 0x60
+# endif
+# ifndef LANG_KAZAK
+# define LANG_KAZAK 0x3f
+# endif
+# ifndef LANG_KONKANI
+# define LANG_KONKANI 0x57
+# endif
+# ifndef LANG_LATVIAN
+# define LANG_LATVIAN 0x26
+# endif
+# ifndef LANG_LITHUANIAN
+# define LANG_LITHUANIAN 0x27
+# endif
+# ifndef LANG_MACEDONIAN
+# define LANG_MACEDONIAN 0x2f
+# endif
+# ifndef LANG_MALAY
+# define LANG_MALAY 0x3e
+# endif
+# ifndef LANG_MALAYALAM
+# define LANG_MALAYALAM 0x4c
+# endif
+# ifndef LANG_MANIPURI
+# define LANG_MANIPURI 0x58
+# endif
+# ifndef LANG_MARATHI
+# define LANG_MARATHI 0x4e
+# endif
+# ifndef LANG_NEPALI
+# define LANG_NEPALI 0x61
+# endif
+# ifndef LANG_ORIYA
+# define LANG_ORIYA 0x48
+# endif
+# ifndef LANG_PUNJABI
+# define LANG_PUNJABI 0x46
+# endif
+# ifndef LANG_SANSKRIT
+# define LANG_SANSKRIT 0x4f
+# endif
+# ifndef LANG_SERBIAN
+# define LANG_SERBIAN 0x1a
+# endif
+# ifndef LANG_SINDHI
+# define LANG_SINDHI 0x59
+# endif
+# ifndef LANG_SLOVAK
+# define LANG_SLOVAK 0x1b
+# endif
+# ifndef LANG_SWAHILI
+# define LANG_SWAHILI 0x41
+# endif
+# ifndef LANG_SORBIAN
+# define LANG_SORBIAN 0x2e
+# endif
+# ifndef LANG_TAMIL
+# define LANG_TAMIL 0x49
+# endif
+# ifndef LANG_TATAR
+# define LANG_TATAR 0x44
+# endif
+# ifndef LANG_TELUGU
+# define LANG_TELUGU 0x4a
+# endif
+# ifndef LANG_THAI
+# define LANG_THAI 0x1e
+# endif
+# ifndef LANG_UKRAINIAN
+# define LANG_UKRAINIAN 0x22
+# endif
+# ifndef LANG_URDU
+# define LANG_URDU 0x20
+# endif
+# ifndef LANG_UZBEK
+# define LANG_UZBEK 0x43
+# endif
+# ifndef LANG_VIETNAMESE
+# define LANG_VIETNAMESE 0x2a
+# endif
+# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
+# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
+# endif
+# ifndef SUBLANG_ARABIC_IRAQ
+# define SUBLANG_ARABIC_IRAQ 0x02
+# endif
+# ifndef SUBLANG_ARABIC_EGYPT
+# define SUBLANG_ARABIC_EGYPT 0x03
+# endif
+# ifndef SUBLANG_ARABIC_LIBYA
+# define SUBLANG_ARABIC_LIBYA 0x04
+# endif
+# ifndef SUBLANG_ARABIC_ALGERIA
+# define SUBLANG_ARABIC_ALGERIA 0x05
+# endif
+# ifndef SUBLANG_ARABIC_MOROCCO
+# define SUBLANG_ARABIC_MOROCCO 0x06
+# endif
+# ifndef SUBLANG_ARABIC_TUNISIA
+# define SUBLANG_ARABIC_TUNISIA 0x07
+# endif
+# ifndef SUBLANG_ARABIC_OMAN
+# define SUBLANG_ARABIC_OMAN 0x08
+# endif
+# ifndef SUBLANG_ARABIC_YEMEN
+# define SUBLANG_ARABIC_YEMEN 0x09
+# endif
+# ifndef SUBLANG_ARABIC_SYRIA
+# define SUBLANG_ARABIC_SYRIA 0x0a
+# endif
+# ifndef SUBLANG_ARABIC_JORDAN
+# define SUBLANG_ARABIC_JORDAN 0x0b
+# endif
+# ifndef SUBLANG_ARABIC_LEBANON
+# define SUBLANG_ARABIC_LEBANON 0x0c
+# endif
+# ifndef SUBLANG_ARABIC_KUWAIT
+# define SUBLANG_ARABIC_KUWAIT 0x0d
+# endif
+# ifndef SUBLANG_ARABIC_UAE
+# define SUBLANG_ARABIC_UAE 0x0e
+# endif
+# ifndef SUBLANG_ARABIC_BAHRAIN
+# define SUBLANG_ARABIC_BAHRAIN 0x0f
+# endif
+# ifndef SUBLANG_ARABIC_QATAR
+# define SUBLANG_ARABIC_QATAR 0x10
+# endif
+# ifndef SUBLANG_AZERI_LATIN
+# define SUBLANG_AZERI_LATIN 0x01
+# endif
+# ifndef SUBLANG_AZERI_CYRILLIC
+# define SUBLANG_AZERI_CYRILLIC 0x02
+# endif
+# ifndef SUBLANG_CHINESE_MACAU
+# define SUBLANG_CHINESE_MACAU 0x05
+# endif
+# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
+# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
+# endif
+# ifndef SUBLANG_ENGLISH_JAMAICA
+# define SUBLANG_ENGLISH_JAMAICA 0x08
+# endif
+# ifndef SUBLANG_ENGLISH_CARIBBEAN
+# define SUBLANG_ENGLISH_CARIBBEAN 0x09
+# endif
+# ifndef SUBLANG_ENGLISH_BELIZE
+# define SUBLANG_ENGLISH_BELIZE 0x0a
+# endif
+# ifndef SUBLANG_ENGLISH_TRINIDAD
+# define SUBLANG_ENGLISH_TRINIDAD 0x0b
+# endif
+# ifndef SUBLANG_ENGLISH_ZIMBABWE
+# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
+# endif
+# ifndef SUBLANG_ENGLISH_PHILIPPINES
+# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
+# endif
+# ifndef SUBLANG_FRENCH_LUXEMBOURG
+# define SUBLANG_FRENCH_LUXEMBOURG 0x05
+# endif
+# ifndef SUBLANG_FRENCH_MONACO
+# define SUBLANG_FRENCH_MONACO 0x06
+# endif
+# ifndef SUBLANG_GERMAN_LUXEMBOURG
+# define SUBLANG_GERMAN_LUXEMBOURG 0x04
+# endif
+# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
+# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
+# endif
+# ifndef SUBLANG_KASHMIRI_INDIA
+# define SUBLANG_KASHMIRI_INDIA 0x02
+# endif
+# ifndef SUBLANG_MALAY_MALAYSIA
+# define SUBLANG_MALAY_MALAYSIA 0x01
+# endif
+# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
+# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
+# endif
+# ifndef SUBLANG_NEPALI_INDIA
+# define SUBLANG_NEPALI_INDIA 0x02
+# endif
+# ifndef SUBLANG_SERBIAN_LATIN
+# define SUBLANG_SERBIAN_LATIN 0x02
+# endif
+# ifndef SUBLANG_SERBIAN_CYRILLIC
+# define SUBLANG_SERBIAN_CYRILLIC 0x03
+# endif
+# ifndef SUBLANG_SPANISH_GUATEMALA
+# define SUBLANG_SPANISH_GUATEMALA 0x04
+# endif
+# ifndef SUBLANG_SPANISH_COSTA_RICA
+# define SUBLANG_SPANISH_COSTA_RICA 0x05
+# endif
+# ifndef SUBLANG_SPANISH_PANAMA
+# define SUBLANG_SPANISH_PANAMA 0x06
+# endif
+# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
+# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
+# endif
+# ifndef SUBLANG_SPANISH_VENEZUELA
+# define SUBLANG_SPANISH_VENEZUELA 0x08
+# endif
+# ifndef SUBLANG_SPANISH_COLOMBIA
+# define SUBLANG_SPANISH_COLOMBIA 0x09
+# endif
+# ifndef SUBLANG_SPANISH_PERU
+# define SUBLANG_SPANISH_PERU 0x0a
+# endif
+# ifndef SUBLANG_SPANISH_ARGENTINA
+# define SUBLANG_SPANISH_ARGENTINA 0x0b
+# endif
+# ifndef SUBLANG_SPANISH_ECUADOR
+# define SUBLANG_SPANISH_ECUADOR 0x0c
+# endif
+# ifndef SUBLANG_SPANISH_CHILE
+# define SUBLANG_SPANISH_CHILE 0x0d
+# endif
+# ifndef SUBLANG_SPANISH_URUGUAY
+# define SUBLANG_SPANISH_URUGUAY 0x0e
+# endif
+# ifndef SUBLANG_SPANISH_PARAGUAY
+# define SUBLANG_SPANISH_PARAGUAY 0x0f
+# endif
+# ifndef SUBLANG_SPANISH_BOLIVIA
+# define SUBLANG_SPANISH_BOLIVIA 0x10
+# endif
+# ifndef SUBLANG_SPANISH_EL_SALVADOR
+# define SUBLANG_SPANISH_EL_SALVADOR 0x11
+# endif
+# ifndef SUBLANG_SPANISH_HONDURAS
+# define SUBLANG_SPANISH_HONDURAS 0x12
+# endif
+# ifndef SUBLANG_SPANISH_NICARAGUA
+# define SUBLANG_SPANISH_NICARAGUA 0x13
+# endif
+# ifndef SUBLANG_SPANISH_PUERTO_RICO
+# define SUBLANG_SPANISH_PUERTO_RICO 0x14
+# endif
+# ifndef SUBLANG_SWEDISH_FINLAND
+# define SUBLANG_SWEDISH_FINLAND 0x02
+# endif
+# ifndef SUBLANG_URDU_PAKISTAN
+# define SUBLANG_URDU_PAKISTAN 0x01
+# endif
+# ifndef SUBLANG_URDU_INDIA
+# define SUBLANG_URDU_INDIA 0x02
+# endif
+# ifndef SUBLANG_UZBEK_LATIN
+# define SUBLANG_UZBEK_LATIN 0x01
+# endif
+# ifndef SUBLANG_UZBEK_CYRILLIC
+# define SUBLANG_UZBEK_CYRILLIC 0x02
+# endif
+#endif
+
+/* XPG3 defines the result of 'setlocale (category, NULL)' as:
+   "Directs 'setlocale()' to query 'category' and return the current
+    setting of 'local'."
+   However it does not specify the exact format.  Neither do SUSV2 and
+   ISO C 99.  So we can use this feature only on selected systems (e.g.
+   those using GNU C Library).  */
+#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2)
+# define HAVE_LOCALE_NULL
+#endif
+
+/* Determine the current locale's name, and canonicalize it into XPG syntax
+     language[_territory[.codeset]][@modifier]
+   The codeset part in the result is not reliable; the locale_charset()
+   should be used for codeset information instead.
+   The result must not be freed; it is statically allocated.  */
+
+const char *
+_nl_locale_name (category, categoryname)
+     int category;
+     const char *categoryname;
+{
+  const char *retval;
+
+#ifndef WIN32
+
+  /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
+     On some systems this can be done by the 'setlocale' function itself.  */
+# if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
+  retval = setlocale (category, NULL);
+# else
+  /* Setting of LC_ALL overwrites all other.  */
+  retval = getenv ("LC_ALL");
+  if (retval == NULL || retval[0] == '\0')
+    {
+      /* Next comes the name of the desired category.  */
+      retval = getenv (categoryname);
+      if (retval == NULL || retval[0] == '\0')
+	{
+	  /* Last possibility is the LANG environment variable.  */
+	  retval = getenv ("LANG");
+	  if (retval == NULL || retval[0] == '\0')
+	    /* We use C as the default domain.  POSIX says this is
+	       implementation defined.  */
+	    retval = "C";
+	}
+    }
+# endif
+
+  return retval;
+
+#else /* WIN32 */
+
+  /* Return an XPG style locale name language[_territory][@modifier].
+     Don't even bother determining the codeset; it's not useful in this
+     context, because message catalogs are not specific to a single
+     codeset.  */
+
+  LCID lcid;
+  LANGID langid;
+  int primary, sub;
+
+  /* Let the user override the system settings through environment
+     variables, as on POSIX systems.  */
+  retval = getenv ("LC_ALL");
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+  retval = getenv (categoryname);
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+  retval = getenv ("LANG");
+  if (retval != NULL && retval[0] != '\0')
+    return retval;
+
+  /* Use native Win32 API locale ID.  */
+  lcid = GetThreadLocale ();
+
+  /* Strip off the sorting rules, keep only the language part.  */
+  langid = LANGIDFROMLCID (lcid);
+
+  /* Split into language and territory part.  */
+  primary = PRIMARYLANGID (langid);
+  sub = SUBLANGID (langid);
+  switch (primary)
+    {
+    case LANG_AFRIKAANS: return "af_ZA";
+    case LANG_ALBANIAN: return "sq_AL";
+    case LANG_ARABIC:
+      switch (sub)
+	{
+	case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
+	case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
+	case SUBLANG_ARABIC_EGYPT: return "ar_EG";
+	case SUBLANG_ARABIC_LIBYA: return "ar_LY";
+	case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
+	case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
+	case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
+	case SUBLANG_ARABIC_OMAN: return "ar_OM";
+	case SUBLANG_ARABIC_YEMEN: return "ar_YE";
+	case SUBLANG_ARABIC_SYRIA: return "ar_SY";
+	case SUBLANG_ARABIC_JORDAN: return "ar_JO";
+	case SUBLANG_ARABIC_LEBANON: return "ar_LB";
+	case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
+	case SUBLANG_ARABIC_UAE: return "ar_AE";
+	case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
+	case SUBLANG_ARABIC_QATAR: return "ar_QA";
+	}
+      return "ar";
+    case LANG_ARMENIAN: return "hy_AM";
+    case LANG_ASSAMESE: return "as_IN";
+    case LANG_AZERI:
+      switch (sub)
+	{
+	/* FIXME: Adjust this when Azerbaijani locales appear on Unix.  */
+	case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
+	case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
+	}
+      return "az";
+    case LANG_BASQUE:
+      return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR".  */
+    case LANG_BELARUSIAN: return "be_BY";
+    case LANG_BENGALI: return "bn_IN";
+    case LANG_BULGARIAN: return "bg_BG";
+    case LANG_CATALAN: return "ca_ES";
+    case LANG_CHINESE:
+      switch (sub)
+	{
+	case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
+	case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
+	case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
+	case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
+	case SUBLANG_CHINESE_MACAU: return "zh_MO";
+	}
+      return "zh";
+    case LANG_CROATIAN:		/* LANG_CROATIAN == LANG_SERBIAN
+				 * What used to be called Serbo-Croatian
+				 * should really now be two separate
+				 * languages because of political reasons.
+				 * (Says tml, who knows nothing about Serbian
+				 * or Croatian.)
+				 * (I can feel those flames coming already.)
+				 */
+      switch (sub)
+	{
+	/* FIXME: How to distinguish Croatian and Latin Serbian locales?  */
+	case SUBLANG_SERBIAN_LATIN: return "sr_YU";
+	case SUBLANG_SERBIAN_CYRILLIC: return "sr_YU@cyrillic";
+	default: return "hr_HR";
+	}
+    case LANG_CZECH: return "cs_CZ";
+    case LANG_DANISH: return "da_DK";
+    case LANG_DUTCH:
+      switch (sub)
+	{
+	case SUBLANG_DUTCH: return "nl_NL";
+	case SUBLANG_DUTCH_BELGIAN: return "nl_BE";
+	}
+      return "nl";
+    case LANG_ENGLISH:
+      switch (sub)
+	{
+	/* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
+	 * English was the language spoken in England.
+	 * Oh well.
+	 */
+	case SUBLANG_ENGLISH_US: return "en_US";
+	case SUBLANG_ENGLISH_UK: return "en_GB";
+	case SUBLANG_ENGLISH_AUS: return "en_AU";
+	case SUBLANG_ENGLISH_CAN: return "en_CA";
+	case SUBLANG_ENGLISH_NZ: return "en_NZ";
+	case SUBLANG_ENGLISH_EIRE: return "en_IE";
+	case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
+	case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
+	case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
+	case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
+	case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
+	case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
+	case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
+	}
+      return "en";
+    case LANG_ESTONIAN: return "et_EE";
+    case LANG_FAEROESE: return "fo_FO";
+    case LANG_FARSI: return "fa_IR";
+    case LANG_FINNISH: return "fi_FI";
+    case LANG_FRENCH:
+      switch (sub)
+	{
+	case SUBLANG_FRENCH: return "fr_FR";
+	case SUBLANG_FRENCH_BELGIAN: return "fr_BE";
+	case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
+	case SUBLANG_FRENCH_SWISS: return "fr_CH";
+	case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
+	case SUBLANG_FRENCH_MONACO: return "fr_MC";
+	}
+      return "fr";
+    case LANG_GEORGIAN: return "ka_GE";
+    case LANG_GERMAN:
+      switch (sub)
+	{
+	case SUBLANG_GERMAN: return "de_DE";
+	case SUBLANG_GERMAN_SWISS: return "de_CH";
+	case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
+	case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
+	case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
+	}
+      return "de";
+    case LANG_GREEK: return "el_GR";
+    case LANG_GUJARATI: return "gu_IN";
+    case LANG_HEBREW: return "he_IL";
+    case LANG_HINDI: return "hi_IN";
+    case LANG_HUNGARIAN: return "hu_HU";
+    case LANG_ICELANDIC: return "is_IS";
+    case LANG_INDONESIAN: return "id_ID";
+    case LANG_ITALIAN:
+      switch (sub)
+	{
+	case SUBLANG_ITALIAN: return "it_IT";
+	case SUBLANG_ITALIAN_SWISS: return "it_CH";
+	}
+      return "it";
+    case LANG_JAPANESE: return "ja_JP";
+    case LANG_KANNADA: return "kn_IN";
+    case LANG_KASHMIRI:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "ks_PK";
+	case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
+	}
+      return "ks";
+    case LANG_KAZAK: return "kk_KZ";
+    case LANG_KONKANI:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "kok_IN";
+    case LANG_KOREAN: return "ko_KR";
+    case LANG_LATVIAN: return "lv_LV";
+    case LANG_LITHUANIAN: return "lt_LT";
+    case LANG_MACEDONIAN: return "mk_MK";
+    case LANG_MALAY:
+      switch (sub)
+	{
+	case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
+	case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
+	}
+      return "ms";
+    case LANG_MALAYALAM: return "ml_IN";
+    case LANG_MANIPURI:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "mni_IN";
+    case LANG_MARATHI: return "mr_IN";
+    case LANG_NEPALI:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "ne_NP";
+	case SUBLANG_NEPALI_INDIA: return "ne_IN";
+	}
+      return "ne";
+    case LANG_NORWEGIAN:
+      switch (sub)
+	{
+	case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
+	case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
+	}
+      return "no";
+    case LANG_ORIYA: return "or_IN";
+    case LANG_POLISH: return "pl_PL";
+    case LANG_PORTUGUESE:
+      switch (sub)
+	{
+	case SUBLANG_PORTUGUESE: return "pt_PT";
+	/* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
+	   Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
+	case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
+	}
+      return "pt";
+    case LANG_PUNJABI: return "pa_IN";
+    case LANG_ROMANIAN: return "ro_RO";
+    case LANG_RUSSIAN:
+      return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA".  */
+    case LANG_SANSKRIT: return "sa_IN";
+    case LANG_SINDHI: return "sd";
+    case LANG_SLOVAK: return "sk_SK";
+    case LANG_SLOVENIAN: return "sl_SI";
+    case LANG_SORBIAN:
+      /* FIXME: Adjust this when such locales appear on Unix.  */
+      return "wen_DE";
+    case LANG_SPANISH:
+      switch (sub)
+	{
+	case SUBLANG_SPANISH: return "es_ES";
+	case SUBLANG_SPANISH_MEXICAN: return "es_MX";
+	case SUBLANG_SPANISH_MODERN:
+	  return "es_ES@modern";	/* not seen on Unix */
+	case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
+	case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
+	case SUBLANG_SPANISH_PANAMA: return "es_PA";
+	case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
+	case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
+	case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
+	case SUBLANG_SPANISH_PERU: return "es_PE";
+	case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
+	case SUBLANG_SPANISH_ECUADOR: return "es_EC";
+	case SUBLANG_SPANISH_CHILE: return "es_CL";
+	case SUBLANG_SPANISH_URUGUAY: return "es_UY";
+	case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
+	case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
+	case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
+	case SUBLANG_SPANISH_HONDURAS: return "es_HN";
+	case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
+	case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
+	}
+      return "es";
+    case LANG_SWAHILI: return "sw";
+    case LANG_SWEDISH:
+      switch (sub)
+	{
+	case SUBLANG_DEFAULT: return "sv_SE";
+	case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
+	}
+      return "sv";
+    case LANG_TAMIL:
+      return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG".  */
+    case LANG_TATAR: return "tt";
+    case LANG_TELUGU: return "te_IN";
+    case LANG_THAI: return "th_TH";
+    case LANG_TURKISH: return "tr_TR";
+    case LANG_UKRAINIAN: return "uk_UA";
+    case LANG_URDU:
+      switch (sub)
+	{
+	case SUBLANG_URDU_PAKISTAN: return "ur_PK";
+	case SUBLANG_URDU_INDIA: return "ur_IN";
+	}
+      return "ur";
+    case LANG_UZBEK:
+      switch (sub)
+	{
+	/* FIXME: Adjust this when Uzbek locales appear on Unix.  */
+	case SUBLANG_UZBEK_LATIN: return "uz_UZ@latin";
+	case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
+	}
+      return "uz";
+    case LANG_VIETNAMESE: return "vi_VN";
+    default: return "C";
+    }
+
+#endif
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/ngettext.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/ngettext.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/ngettext.c	(revision 1780)
@@ -0,0 +1,68 @@
+/* Implementation of ngettext(3) function.
+   Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define __need_NULL
+# include <stddef.h>
+#else
+# include <stdlib.h>		/* Just for NULL.  */
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+#include <locale.h>
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define NGETTEXT __ngettext
+# define DCNGETTEXT __dcngettext
+#else
+# define NGETTEXT ngettext__
+# define DCNGETTEXT dcngettext__
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+   LC_MESSAGES locale.  If not found, returns MSGID itself (the default
+   text).  */
+char *
+NGETTEXT (msgid1, msgid2, n)
+     const char *msgid1;
+     const char *msgid2;
+     unsigned long int n;
+{
+  return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__ngettext, ngettext);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/os2compat.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/os2compat.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/os2compat.c	(revision 1780)
@@ -0,0 +1,109 @@
+/* OS/2 compatibility functions.
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#define OS2_AWARE
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+/* A version of getenv() that works from DLLs */
+extern unsigned long DosScanEnv (const unsigned char *pszName, unsigned char **ppszValue);
+
+char *
+_nl_getenv (const char *name)
+{
+  unsigned char *value;
+  if (DosScanEnv (name, &value))
+    return NULL;
+  else
+    return value;
+}
+
+char _nl_default_dirname[] =	/* a 260+1 bytes large buffer */
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0"
+#define LOCALEDIR_MAX 260
+
+char *_os2_libdir = NULL;
+char *_os2_localealiaspath = NULL;
+char *_os2_localedir = NULL;
+
+static __attribute__((constructor)) void
+os2_initialize ()
+{
+  char *root = getenv ("UNIXROOT");
+  char *gnulocaledir = getenv ("GNULOCALEDIR");
+
+  _os2_libdir = gnulocaledir;
+  if (!_os2_libdir)
+    {
+      if (root)
+        {
+          size_t sl = strlen (root);
+          _os2_libdir = (char *) malloc (sl + strlen (LIBDIR) + 1);
+          memcpy (_os2_libdir, root, sl);
+          memcpy (_os2_libdir + sl, LIBDIR, strlen (LIBDIR) + 1);
+        }
+      else
+        _os2_libdir = LIBDIR;
+    }
+
+  _os2_localealiaspath = gnulocaledir;
+  if (!_os2_localealiaspath)
+    {
+      if (root)
+        {
+          size_t sl = strlen (root);
+          _os2_localealiaspath = (char *) malloc (sl + strlen (LOCALE_ALIAS_PATH) + 1);
+          memcpy (_os2_localealiaspath, root, sl);
+          memcpy (_os2_localealiaspath + sl, LOCALE_ALIAS_PATH, strlen (LOCALE_ALIAS_PATH) + 1);
+        }
+     else
+        _os2_localealiaspath = LOCALE_ALIAS_PATH;
+    }
+
+  _os2_localedir = gnulocaledir;
+  if (!_os2_localedir)
+    {
+      if (root)
+        {
+          size_t sl = strlen (root);
+          _os2_localedir = (char *) malloc (sl + strlen (LOCALEDIR) + 1);
+          memcpy (_os2_localedir, root, sl);
+          memcpy (_os2_localedir + sl, LOCALEDIR, strlen (LOCALEDIR) + 1);
+        }
+      else
+        _os2_localedir = LOCALEDIR;
+    }
+
+  {
+    extern const char _nl_default_dirname__[];
+    if (strlen (_os2_localedir) <= LOCALEDIR_MAX)
+      strcpy (_nl_default_dirname__, _os2_localedir);
+  }
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/os2compat.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/os2compat.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/os2compat.h	(revision 1780)
@@ -0,0 +1,46 @@
+/* OS/2 compatibility defines.
+   This file is intended to be included from config.h
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* When included from os2compat.h we need all the original definitions */
+#ifndef OS2_AWARE
+
+#undef LIBDIR
+#define LIBDIR			_os2_libdir
+extern char *_os2_libdir;
+
+#undef LOCALEDIR
+#define LOCALEDIR		_os2_localedir
+extern char *_os2_localedir;
+
+#undef LOCALE_ALIAS_PATH
+#define LOCALE_ALIAS_PATH	_os2_localealiaspath
+extern char *_os2_localealiaspath;
+
+#endif
+
+#undef HAVE_STRCASECMP
+#define HAVE_STRCASECMP 1
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+
+/* We have our own getenv() which works even if library is compiled as DLL */
+#define getenv _nl_getenv
+
+/* Older versions of gettext used -1 as the value of LC_MESSAGES */
+#define LC_MESSAGES_COMPAT (-1)
Index: /tags/kBuild-0.1.4/src/sed/intl/osdep.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/osdep.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/osdep.c	(revision 1780)
@@ -0,0 +1,24 @@
+/* OS dependent parts of libintl.
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#if defined __EMX__
+# include "os2compat.c"
+#else
+/* Avoid AIX compiler warning.  */
+typedef int dummy;
+#endif
Index: /tags/kBuild-0.1.4/src/sed/intl/plural-exp.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/plural-exp.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/plural-exp.c	(revision 1780)
@@ -0,0 +1,156 @@
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "plural-exp.h"
+
+#if (defined __GNUC__ && !defined __APPLE_CC__) \
+    || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+
+/* These structs are the constant expression for the germanic plural
+   form determination.  It represents the expression  "n != 1".  */
+static const struct expression plvar =
+{
+  .nargs = 0,
+  .operation = var,
+};
+static const struct expression plone =
+{
+  .nargs = 0,
+  .operation = num,
+  .val =
+  {
+    .num = 1
+  }
+};
+struct expression GERMANIC_PLURAL =
+{
+  .nargs = 2,
+  .operation = not_equal,
+  .val =
+  {
+    .args =
+    {
+      [0] = (struct expression *) &plvar,
+      [1] = (struct expression *) &plone
+    }
+  }
+};
+
+# define INIT_GERMANIC_PLURAL()
+
+#else
+
+/* For compilers without support for ISO C 99 struct/union initializers:
+   Initialization at run-time.  */
+
+static struct expression plvar;
+static struct expression plone;
+struct expression GERMANIC_PLURAL;
+
+static void
+init_germanic_plural ()
+{
+  if (plone.val.num == 0)
+    {
+      plvar.nargs = 0;
+      plvar.operation = var;
+
+      plone.nargs = 0;
+      plone.operation = num;
+      plone.val.num = 1;
+
+      GERMANIC_PLURAL.nargs = 2;
+      GERMANIC_PLURAL.operation = not_equal;
+      GERMANIC_PLURAL.val.args[0] = &plvar;
+      GERMANIC_PLURAL.val.args[1] = &plone;
+    }
+}
+
+# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
+
+#endif
+
+void
+internal_function
+EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp)
+     const char *nullentry;
+     struct expression **pluralp;
+     unsigned long int *npluralsp;
+{
+  if (nullentry != NULL)
+    {
+      const char *plural;
+      const char *nplurals;
+
+      plural = strstr (nullentry, "plural=");
+      nplurals = strstr (nullentry, "nplurals=");
+      if (plural == NULL || nplurals == NULL)
+	goto no_plural;
+      else
+	{
+	  char *endp;
+	  unsigned long int n;
+	  struct parse_args args;
+
+	  /* First get the number.  */
+	  nplurals += 9;
+	  while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
+	    ++nplurals;
+	  if (!(*nplurals >= '0' && *nplurals <= '9'))
+	    goto no_plural;
+#if defined HAVE_STRTOUL || defined _LIBC
+	  n = strtoul (nplurals, &endp, 10);
+#else
+	  for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
+	    n = n * 10 + (*endp - '0');
+#endif
+	  if (nplurals == endp)
+	    goto no_plural;
+	  *npluralsp = n;
+
+	  /* Due to the restrictions bison imposes onto the interface of the
+	     scanner function we have to put the input string and the result
+	     passed up from the parser into the same structure which address
+	     is passed down to the parser.  */
+	  plural += 7;
+	  args.cp = plural;
+	  if (PLURAL_PARSE (&args) != 0)
+	    goto no_plural;
+	  *pluralp = args.res;
+	}
+    }
+  else
+    {
+      /* By default we are using the Germanic form: singular form only
+         for `one', the plural form otherwise.  Yes, this is also what
+         English is using since English is a Germanic language.  */
+    no_plural:
+      INIT_GERMANIC_PLURAL ();
+      *pluralp = &GERMANIC_PLURAL;
+      *npluralsp = 2;
+    }
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/plural-exp.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/plural-exp.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/plural-exp.h	(revision 1780)
@@ -0,0 +1,122 @@
+/* Expression parsing and evaluation for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifndef _PLURAL_EXP_H
+#define _PLURAL_EXP_H
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+
+/* This is the representation of the expressions to determine the
+   plural form.  */
+struct expression
+{
+  int nargs;			/* Number of arguments.  */
+  enum operator
+  {
+    /* Without arguments:  */
+    var,			/* The variable "n".  */
+    num,			/* Decimal number.  */
+    /* Unary operators:  */
+    lnot,			/* Logical NOT.  */
+    /* Binary operators:  */
+    mult,			/* Multiplication.  */
+    divide,			/* Division.  */
+    module,			/* Modulo operation.  */
+    plus,			/* Addition.  */
+    minus,			/* Subtraction.  */
+    less_than,			/* Comparison.  */
+    greater_than,		/* Comparison.  */
+    less_or_equal,		/* Comparison.  */
+    greater_or_equal,		/* Comparison.  */
+    equal,			/* Comparison for equality.  */
+    not_equal,			/* Comparison for inequality.  */
+    land,			/* Logical AND.  */
+    lor,			/* Logical OR.  */
+    /* Ternary operators:  */
+    qmop			/* Question mark operator.  */
+  } operation;
+  union
+  {
+    unsigned long int num;	/* Number value for `num'.  */
+    struct expression *args[3];	/* Up to three arguments.  */
+  } val;
+};
+
+/* This is the data structure to pass information to the parser and get
+   the result in a thread-safe way.  */
+struct parse_args
+{
+  const char *cp;
+  struct expression *res;
+};
+
+
+/* Names for the libintl functions are a problem.  This source code is used
+   1. in the GNU C Library library,
+   2. in the GNU libintl library,
+   3. in the GNU gettext tools.
+   The function names in each situation must be different, to allow for
+   binary incompatible changes in 'struct expression'.  Furthermore,
+   1. in the GNU C Library library, the names have a __ prefix,
+   2.+3. in the GNU libintl library and in the GNU gettext tools, the names
+         must follow ANSI C and not start with __.
+   So we have to distinguish the three cases.  */
+#ifdef _LIBC
+# define FREE_EXPRESSION __gettext_free_exp
+# define PLURAL_PARSE __gettextparse
+# define GERMANIC_PLURAL __gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural
+#elif defined (IN_LIBINTL)
+# define FREE_EXPRESSION gettext_free_exp__
+# define PLURAL_PARSE gettextparse__
+# define GERMANIC_PLURAL gettext_germanic_plural__
+# define EXTRACT_PLURAL_EXPRESSION gettext_extract_plural__
+#else
+# define FREE_EXPRESSION free_plural_expression
+# define PLURAL_PARSE parse_plural_expression
+# define GERMANIC_PLURAL germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION extract_plural_expression
+#endif
+
+extern void FREE_EXPRESSION PARAMS ((struct expression *exp))
+     internal_function;
+extern int PLURAL_PARSE PARAMS ((void *arg));
+extern struct expression GERMANIC_PLURAL;
+extern void EXTRACT_PLURAL_EXPRESSION PARAMS ((const char *nullentry,
+					       struct expression **pluralp,
+					       unsigned long int *npluralsp))
+     internal_function;
+
+#if !defined (_LIBC) && !defined (IN_LIBINTL)
+extern unsigned long int plural_eval PARAMS ((struct expression *pexp,
+					      unsigned long int n));
+#endif
+
+#endif /* _PLURAL_EXP_H */
Index: /tags/kBuild-0.1.4/src/sed/intl/plural.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/plural.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/plural.c	(revision 1780)
@@ -0,0 +1,1325 @@
+
+/*  A Bison parser, made from plural.y
+    by GNU Bison version 1.28  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+#define yyparse __gettextparse
+#define yylex __gettextlex
+#define yyerror __gettexterror
+#define yylval __gettextlval
+#define yychar __gettextchar
+#define yydebug __gettextdebug
+#define yynerrs __gettextnerrs
+#define	EQUOP2	257
+#define	CMPOP2	258
+#define	ADDOP2	259
+#define	MULOP2	260
+#define	NUMBER	261
+
+#line 1 "plural.y"
+
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* The bison generated parser uses alloca.  AIX 3 forces us to put this
+   declaration at the beginning of the file.  The declaration in bison's
+   skeleton file comes too late.  This must come before <config.h>
+   because <config.h> may include arbitrary system headers.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+   but we want it to be called PLURAL_PARSE.  */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
+#endif
+
+#define YYLEX_PARAM	&((struct parse_args *) arg)->cp
+#define YYPARSE_PARAM	arg
+
+#line 49 "plural.y"
+typedef union {
+  unsigned long int num;
+  enum operator op;
+  struct expression *exp;
+} YYSTYPE;
+#line 55 "plural.y"
+
+/* Prototypes for local functions.  */
+static struct expression *new_exp PARAMS ((int nargs, enum operator op,
+					   struct expression * const *args));
+static inline struct expression *new_exp_0 PARAMS ((enum operator op));
+static inline struct expression *new_exp_1 PARAMS ((enum operator op,
+						   struct expression *right));
+static struct expression *new_exp_2 PARAMS ((enum operator op,
+					     struct expression *left,
+					     struct expression *right));
+static inline struct expression *new_exp_3 PARAMS ((enum operator op,
+						   struct expression *bexp,
+						   struct expression *tbranch,
+						   struct expression *fbranch));
+static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
+static void yyerror PARAMS ((const char *str));
+
+/* Allocation of expressions.  */
+
+static struct expression *
+new_exp (nargs, op, args)
+     int nargs;
+     enum operator op;
+     struct expression * const *args;
+{
+  int i;
+  struct expression *newp;
+
+  /* If any of the argument could not be malloc'ed, just return NULL.  */
+  for (i = nargs - 1; i >= 0; i--)
+    if (args[i] == NULL)
+      goto fail;
+
+  /* Allocate a new expression.  */
+  newp = (struct expression *) malloc (sizeof (*newp));
+  if (newp != NULL)
+    {
+      newp->nargs = nargs;
+      newp->operation = op;
+      for (i = nargs - 1; i >= 0; i--)
+	newp->val.args[i] = args[i];
+      return newp;
+    }
+
+ fail:
+  for (i = nargs - 1; i >= 0; i--)
+    FREE_EXPRESSION (args[i]);
+
+  return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (op)
+     enum operator op;
+{
+  return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (op, right)
+     enum operator op;
+     struct expression *right;
+{
+  struct expression *args[1];
+
+  args[0] = right;
+  return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (op, left, right)
+     enum operator op;
+     struct expression *left;
+     struct expression *right;
+{
+  struct expression *args[2];
+
+  args[0] = left;
+  args[1] = right;
+  return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (op, bexp, tbranch, fbranch)
+     enum operator op;
+     struct expression *bexp;
+     struct expression *tbranch;
+     struct expression *fbranch;
+{
+  struct expression *args[3];
+
+  args[0] = bexp;
+  args[1] = tbranch;
+  args[2] = fbranch;
+  return new_exp (3, op, args);
+}
+
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define	YYFINAL		27
+#define	YYFLAG		-32768
+#define	YYNTBASE	16
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18)
+
+static const char yytranslate[] = {     0,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,    10,     2,     2,     2,     2,     5,     2,    14,
+    15,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,    12,     2,     2,
+     2,     2,     3,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,    13,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     4,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     1,     6,     7,     8,     9,
+    11
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = {     0,
+     0,     2,     8,    12,    16,    20,    24,    28,    32,    35,
+    37,    39
+};
+
+static const short yyrhs[] = {    17,
+     0,    17,     3,    17,    12,    17,     0,    17,     4,    17,
+     0,    17,     5,    17,     0,    17,     6,    17,     0,    17,
+     7,    17,     0,    17,     8,    17,     0,    17,     9,    17,
+     0,    10,    17,     0,    13,     0,    11,     0,    14,    17,
+    15,     0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+   174,   182,   186,   190,   194,   198,   202,   206,   210,   214,
+   218,   223
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = {   "$","error","$undefined.","'?'","'|'",
+"'&'","EQUOP2","CMPOP2","ADDOP2","MULOP2","'!'","NUMBER","':'","'n'","'('","')'",
+"start","exp", NULL
+};
+#endif
+
+static const short yyr1[] = {     0,
+    16,    17,    17,    17,    17,    17,    17,    17,    17,    17,
+    17,    17
+};
+
+static const short yyr2[] = {     0,
+     1,     5,     3,     3,     3,     3,     3,     3,     2,     1,
+     1,     3
+};
+
+static const short yydefact[] = {     0,
+     0,    11,    10,     0,     1,     9,     0,     0,     0,     0,
+     0,     0,     0,     0,    12,     0,     3,     4,     5,     6,
+     7,     8,     0,     2,     0,     0,     0
+};
+
+static const short yydefgoto[] = {    25,
+     5
+};
+
+static const short yypact[] = {    -9,
+    -9,-32768,-32768,    -9,    34,-32768,    11,    -9,    -9,    -9,
+    -9,    -9,    -9,    -9,-32768,    24,    39,    43,    16,    26,
+    -3,-32768,    -9,    34,    21,    53,-32768
+};
+
+static const short yypgoto[] = {-32768,
+    -1
+};
+
+
+#define	YYLAST		53
+
+
+static const short yytable[] = {     6,
+     1,     2,     7,     3,     4,    14,    16,    17,    18,    19,
+    20,    21,    22,     8,     9,    10,    11,    12,    13,    14,
+    26,    24,    12,    13,    14,    15,     8,     9,    10,    11,
+    12,    13,    14,    13,    14,    23,     8,     9,    10,    11,
+    12,    13,    14,    10,    11,    12,    13,    14,    11,    12,
+    13,    14,    27
+};
+
+static const short yycheck[] = {     1,
+    10,    11,     4,    13,    14,     9,     8,     9,    10,    11,
+    12,    13,    14,     3,     4,     5,     6,     7,     8,     9,
+     0,    23,     7,     8,     9,    15,     3,     4,     5,     6,
+     7,     8,     9,     8,     9,    12,     3,     4,     5,     6,
+     7,     8,     9,     5,     6,     7,     8,     9,     6,     7,
+     8,     9,     0
+};
+#define YYPURE 1
+
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/local/share/bison.simple"
+/* This file comes from bison-1.28.  */
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser
+  when the %semantic_parser declaration is not specified in the grammar.
+  It was written by Richard Stallman by simplifying the hairy parser
+  used when %semantic_parser is specified.  */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
+#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
+#include <alloca.h>
+#else /* not sparc */
+/* We think this test detects Watcom and Microsoft C.  */
+/* This used to test MSDOS, but that is a bad idea
+   since that symbol is in the user namespace.  */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for malloc.h, which pollutes the namespace;
+	 instead, just don't use alloca.  */
+#include <malloc.h>
+#endif
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+   So I turned it off.   rms, 2 May 1997.  */
+/* #include <malloc.h>  */
+ #pragma alloca
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+		 and on HPUX 10.  Eventually we can turn this on.  */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#endif /* __hpux */
+#endif
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
+
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC malloc
+#endif
+
+/* Note: there must be only one dollar sign in this file.
+   It is replaced by the list of actions, each action
+   as one case of the switch.  */
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		-2
+#define YYEOF		0
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT 	goto yyabortlab
+#define YYERROR		goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+   This remains here temporarily to ease the
+   transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL		goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    { yychar = (token), yylval = (value);			\
+      yychar1 = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { yyerror ("syntax error: cannot back up"); YYERROR; }	\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+#ifndef YYPURE
+#define YYLEX		yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX		yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX		yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX		yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int	yychar;			/*  the lookahead symbol		*/
+YYSTYPE	yylval;			/*  the semantic value of the		*/
+				/*  lookahead symbol			*/
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc;			/*  location data for the lookahead	*/
+				/*  symbol				*/
+#endif
+
+int yynerrs;			/*  number of parse errors so far       */
+#endif  /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug;			/*  nonzero means print parse trace	*/
+/* Since this is uninitialized, it does not stop multiple parsers
+   from coexisting.  */
+#endif
+
+/*  YYINITDEPTH indicates the initial size of the parser's stacks	*/
+
+#ifndef	YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/*  YYMAXDEPTH is the maximum size the stacks can grow to
+    (effective only if the built-in stack extension method is used).  */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+
+/* Define __yy_memcpy.  Note that the size argument
+   should be passed with type unsigned int, because that is what the non-GCC
+   definitions require.  With GCC, __builtin_memcpy takes an arg
+   of type size_t, but it can handle unsigned int.  */
+
+#if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
+#define __yy_memcpy(TO,FROM,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
+#else				/* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (to, from, count)
+     char *to;
+     char *from;
+     unsigned int count;
+{
+  register char *f = from;
+  register char *t = to;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (char *to, char *from, unsigned int count)
+{
+  register char *t = to;
+  register char *f = from;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#endif
+#endif
+
+
+#line 217 "/usr/local/share/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+#ifdef __cplusplus
+#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not YYPARSE_PARAM */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* not YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
+int
+yyparse(YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  register int yystate;
+  register int yyn;
+  register short *yyssp;
+  register YYSTYPE *yyvsp;
+  int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
+  int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */
+
+  short	yyssa[YYINITDEPTH];	/*  the state stack			*/
+  YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/
+
+  short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
+  YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+
+#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  int yystacksize = YYINITDEPTH;
+  int yyfree_stacks = 0;
+
+#ifdef YYPURE
+  int yychar;
+  YYSTYPE yylval;
+  int yynerrs;
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylloc;
+#endif
+#endif
+
+  YYSTYPE yyval;		/*  the variable used to return		*/
+				/*  semantic values from the action	*/
+				/*  routines				*/
+
+  int yylen;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Starting parse\n");
+#endif
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss - 1;
+  yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in  yystate  .  */
+/* In all cases, when you get here, the value and location stacks
+   have just been pushed. so pushing a state here evens the stacks.  */
+yynewstate:
+
+  *++yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Give user a chance to reallocate the stack */
+      /* Use copies of these so that the &'s don't force the real ones into memory. */
+      YYSTYPE *yyvs1 = yyvs;
+      short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+      YYLTYPE *yyls1 = yyls;
+#endif
+
+      /* Get the current used size of the three stacks, in elements.  */
+      int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      /* Each stack pointer address is followed by the size of
+	 the data in use in that stack, in bytes.  */
+#ifdef YYLSP_NEEDED
+      /* This used to be a conditional around just the two extra args,
+	 but that might be undefined if yyoverflow is a macro.  */
+      yyoverflow("parser stack overflow",
+		 &yyss1, size * sizeof (*yyssp),
+		 &yyvs1, size * sizeof (*yyvsp),
+		 &yyls1, size * sizeof (*yylsp),
+		 &yystacksize);
+#else
+      yyoverflow("parser stack overflow",
+		 &yyss1, size * sizeof (*yyssp),
+		 &yyvs1, size * sizeof (*yyvsp),
+		 &yystacksize);
+#endif
+
+      yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+      yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+	{
+	  yyerror("parser stack overflow");
+	  if (yyfree_stacks)
+	    {
+	      free (yyss);
+	      free (yyvs);
+#ifdef YYLSP_NEEDED
+	      free (yyls);
+#endif
+	    }
+	  return 2;
+	}
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+	yystacksize = YYMAXDEPTH;
+#ifndef YYSTACK_USE_ALLOCA
+      yyfree_stacks = 1;
+#endif
+      yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+      __yy_memcpy ((char *)yyss, (char *)yyss1,
+		   size * (unsigned int) sizeof (*yyssp));
+      yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+      __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+		   size * (unsigned int) sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+      yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+      __yy_memcpy ((char *)yyls, (char *)yyls1,
+		   size * (unsigned int) sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + size - 1;
+      yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+      yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+      if (yyssp >= yyss + yystacksize - 1)
+	YYABORT;
+    }
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+  goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Reading a token: ");
+#endif
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)		/* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;		/* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Now at end of input.\n");
+#endif
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+      if (yydebug)
+	{
+	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+	  /* Give the individual parser a way to print the precise meaning
+	     of a token, for further debugging info.  */
+#ifdef YYPRINT
+	  YYPRINT (stderr, yychar, yylval);
+#endif
+	  fprintf (stderr, ")\n");
+	}
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* count tokens shifted since error; after three, turn off error status.  */
+  if (yyerrstatus) yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+/* Do the default action for the current state.  */
+yydefault:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+/* Do a reduction.  yyn is the number of a rule to reduce with.  */
+yyreduce:
+  yylen = yyr2[yyn];
+  if (yylen > 0)
+    yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      int i;
+
+      fprintf (stderr, "Reducing via rule %d (line %d), ",
+	       yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+
+  switch (yyn) {
+
+case 1:
+#line 175 "plural.y"
+{
+	    if (yyvsp[0].exp == NULL)
+	      YYABORT;
+	    ((struct parse_args *) arg)->res = yyvsp[0].exp;
+	  ;
+    break;}
+case 2:
+#line 183 "plural.y"
+{
+	    yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp);
+	  ;
+    break;}
+case 3:
+#line 187 "plural.y"
+{
+	    yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp);
+	  ;
+    break;}
+case 4:
+#line 191 "plural.y"
+{
+	    yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp);
+	  ;
+    break;}
+case 5:
+#line 195 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  ;
+    break;}
+case 6:
+#line 199 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  ;
+    break;}
+case 7:
+#line 203 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  ;
+    break;}
+case 8:
+#line 207 "plural.y"
+{
+	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
+	  ;
+    break;}
+case 9:
+#line 211 "plural.y"
+{
+	    yyval.exp = new_exp_1 (lnot, yyvsp[0].exp);
+	  ;
+    break;}
+case 10:
+#line 215 "plural.y"
+{
+	    yyval.exp = new_exp_0 (var);
+	  ;
+    break;}
+case 11:
+#line 219 "plural.y"
+{
+	    if ((yyval.exp = new_exp_0 (num)) != NULL)
+	      yyval.exp->val.num = yyvsp[0].num;
+	  ;
+    break;}
+case 12:
+#line 224 "plural.y"
+{
+	    yyval.exp = yyvsp[-1].exp;
+	  ;
+    break;}
+}
+   /* the action file gets copied in in place of this dollarsign */
+#line 543 "/usr/local/share/bison.simple"
+
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "state stack now");
+      while (ssp1 != yyssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+  yylsp++;
+  if (yylen == 0)
+    {
+      yylsp->first_line = yylloc.first_line;
+      yylsp->first_column = yylloc.first_column;
+      yylsp->last_line = (yylsp-1)->last_line;
+      yylsp->last_column = (yylsp-1)->last_column;
+      yylsp->text = 0;
+    }
+  else
+    {
+      yylsp->last_line = (yylsp+yylen-1)->last_line;
+      yylsp->last_column = (yylsp+yylen-1)->last_column;
+    }
+#endif
+
+  /* Now "shift" the result of the reduction.
+     Determine what state that goes to,
+     based on the state we popped back to
+     and the rule number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yyerrlab:   /* here on detecting error */
+
+  if (! yyerrstatus)
+    /* If not already recovering from an error, report this error.  */
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+	{
+	  int size = 0;
+	  char *msg;
+	  int x, count;
+
+	  count = 0;
+	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
+	  for (x = (yyn < 0 ? -yyn : 0);
+	       x < (sizeof(yytname) / sizeof(char *)); x++)
+	    if (yycheck[x + yyn] == x)
+	      size += strlen(yytname[x]) + 15, count++;
+	  msg = (char *) malloc(size + 15);
+	  if (msg != 0)
+	    {
+	      strcpy(msg, "parse error");
+
+	      if (count < 5)
+		{
+		  count = 0;
+		  for (x = (yyn < 0 ? -yyn : 0);
+		       x < (sizeof(yytname) / sizeof(char *)); x++)
+		    if (yycheck[x + yyn] == x)
+		      {
+			strcat(msg, count == 0 ? ", expecting `" : " or `");
+			strcat(msg, yytname[x]);
+			strcat(msg, "'");
+			count++;
+		      }
+		}
+	      yyerror(msg);
+	      free(msg);
+	    }
+	  else
+	    yyerror ("parse error; also virtual memory exceeded");
+	}
+      else
+#endif /* YYERROR_VERBOSE */
+	yyerror("parse error");
+    }
+
+  goto yyerrlab1;
+yyerrlab1:   /* here on error raised explicitly by an action */
+
+  if (yyerrstatus == 3)
+    {
+      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+	YYABORT;
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token
+     after shifting the error token.  */
+
+  yyerrstatus = 3;		/* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+yyerrdefault:  /* current state does not do anything special for the error token. */
+
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
+  if (yyn) goto yydefault;
+#endif
+
+yyerrpop:   /* pop the current state because it cannot handle the error token */
+
+  if (yyssp == yyss) YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "Error: state stack now");
+      while (ssp1 != yyssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+yyerrhandle:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting error token, ");
+#endif
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+ yyacceptlab:
+  /* YYACCEPT comes here.  */
+  if (yyfree_stacks)
+    {
+      free (yyss);
+      free (yyvs);
+#ifdef YYLSP_NEEDED
+      free (yyls);
+#endif
+    }
+  return 0;
+
+ yyabortlab:
+  /* YYABORT comes here.  */
+  if (yyfree_stacks)
+    {
+      free (yyss);
+      free (yyvs);
+#ifdef YYLSP_NEEDED
+      free (yyls);
+#endif
+    }
+  return 1;
+}
+#line 229 "plural.y"
+
+
+void
+internal_function
+FREE_EXPRESSION (exp)
+     struct expression *exp;
+{
+  if (exp == NULL)
+    return;
+
+  /* Handle the recursive case.  */
+  switch (exp->nargs)
+    {
+    case 3:
+      FREE_EXPRESSION (exp->val.args[2]);
+      /* FALLTHROUGH */
+    case 2:
+      FREE_EXPRESSION (exp->val.args[1]);
+      /* FALLTHROUGH */
+    case 1:
+      FREE_EXPRESSION (exp->val.args[0]);
+      /* FALLTHROUGH */
+    default:
+      break;
+    }
+
+  free (exp);
+}
+
+
+static int
+yylex (lval, pexp)
+     YYSTYPE *lval;
+     const char **pexp;
+{
+  const char *exp = *pexp;
+  int result;
+
+  while (1)
+    {
+      if (exp[0] == '\0')
+	{
+	  *pexp = exp;
+	  return YYEOF;
+	}
+
+      if (exp[0] != ' ' && exp[0] != '\t')
+	break;
+
+      ++exp;
+    }
+
+  result = *exp++;
+  switch (result)
+    {
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      {
+	unsigned long int n = result - '0';
+	while (exp[0] >= '0' && exp[0] <= '9')
+	  {
+	    n *= 10;
+	    n += exp[0] - '0';
+	    ++exp;
+	  }
+	lval->num = n;
+	result = NUMBER;
+      }
+      break;
+
+    case '=':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = equal;
+	  result = EQUOP2;
+	}
+      else
+	result = YYERRCODE;
+      break;
+
+    case '!':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = not_equal;
+	  result = EQUOP2;
+	}
+      break;
+
+    case '&':
+    case '|':
+      if (exp[0] == result)
+	++exp;
+      else
+	result = YYERRCODE;
+      break;
+
+    case '<':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = less_or_equal;
+	}
+      else
+	lval->op = less_than;
+      result = CMPOP2;
+      break;
+
+    case '>':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = greater_or_equal;
+	}
+      else
+	lval->op = greater_than;
+      result = CMPOP2;
+      break;
+
+    case '*':
+      lval->op = mult;
+      result = MULOP2;
+      break;
+
+    case '/':
+      lval->op = divide;
+      result = MULOP2;
+      break;
+
+    case '%':
+      lval->op = module;
+      result = MULOP2;
+      break;
+
+    case '+':
+      lval->op = plus;
+      result = ADDOP2;
+      break;
+
+    case '-':
+      lval->op = minus;
+      result = ADDOP2;
+      break;
+
+    case 'n':
+    case '?':
+    case ':':
+    case '(':
+    case ')':
+      /* Nothing, just return the character.  */
+      break;
+
+    case ';':
+    case '\n':
+    case '\0':
+      /* Be safe and let the user call this function again.  */
+      --exp;
+      result = YYEOF;
+      break;
+
+    default:
+      result = YYERRCODE;
+#if YYDEBUG != 0
+      --exp;
+#endif
+      break;
+    }
+
+  *pexp = exp;
+
+  return result;
+}
+
+
+static void
+yyerror (str)
+     const char *str;
+{
+  /* Do nothing.  We don't print error messages here.  */
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/plural.y
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/plural.y	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/plural.y	(revision 1780)
@@ -0,0 +1,409 @@
+%{
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* The bison generated parser uses alloca.  AIX 3 forces us to put this
+   declaration at the beginning of the file.  The declaration in bison's
+   skeleton file comes too late.  This must come before <config.h>
+   because <config.h> may include arbitrary system headers.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+   but we want it to be called PLURAL_PARSE.  */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
+#endif
+
+#define YYLEX_PARAM	&((struct parse_args *) arg)->cp
+#define YYPARSE_PARAM	arg
+%}
+%pure_parser
+%expect 7
+
+%union {
+  unsigned long int num;
+  enum operator op;
+  struct expression *exp;
+}
+
+%{
+/* Prototypes for local functions.  */
+static struct expression *new_exp PARAMS ((int nargs, enum operator op,
+					   struct expression * const *args));
+static inline struct expression *new_exp_0 PARAMS ((enum operator op));
+static inline struct expression *new_exp_1 PARAMS ((enum operator op,
+						   struct expression *right));
+static struct expression *new_exp_2 PARAMS ((enum operator op,
+					     struct expression *left,
+					     struct expression *right));
+static inline struct expression *new_exp_3 PARAMS ((enum operator op,
+						   struct expression *bexp,
+						   struct expression *tbranch,
+						   struct expression *fbranch));
+static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
+static void yyerror PARAMS ((const char *str));
+
+/* Allocation of expressions.  */
+
+static struct expression *
+new_exp (nargs, op, args)
+     int nargs;
+     enum operator op;
+     struct expression * const *args;
+{
+  int i;
+  struct expression *newp;
+
+  /* If any of the argument could not be malloc'ed, just return NULL.  */
+  for (i = nargs - 1; i >= 0; i--)
+    if (args[i] == NULL)
+      goto fail;
+
+  /* Allocate a new expression.  */
+  newp = (struct expression *) malloc (sizeof (*newp));
+  if (newp != NULL)
+    {
+      newp->nargs = nargs;
+      newp->operation = op;
+      for (i = nargs - 1; i >= 0; i--)
+	newp->val.args[i] = args[i];
+      return newp;
+    }
+
+ fail:
+  for (i = nargs - 1; i >= 0; i--)
+    FREE_EXPRESSION (args[i]);
+
+  return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (op)
+     enum operator op;
+{
+  return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (op, right)
+     enum operator op;
+     struct expression *right;
+{
+  struct expression *args[1];
+
+  args[0] = right;
+  return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (op, left, right)
+     enum operator op;
+     struct expression *left;
+     struct expression *right;
+{
+  struct expression *args[2];
+
+  args[0] = left;
+  args[1] = right;
+  return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (op, bexp, tbranch, fbranch)
+     enum operator op;
+     struct expression *bexp;
+     struct expression *tbranch;
+     struct expression *fbranch;
+{
+  struct expression *args[3];
+
+  args[0] = bexp;
+  args[1] = tbranch;
+  args[2] = fbranch;
+  return new_exp (3, op, args);
+}
+
+%}
+
+/* This declares that all operators have the same associativity and the
+   precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
+   There is no unary minus and no bitwise operators.
+   Operators with the same syntactic behaviour have been merged into a single
+   token, to save space in the array generated by bison.  */
+%right '?'		/*   ?		*/
+%left '|'		/*   ||		*/
+%left '&'		/*   &&		*/
+%left EQUOP2		/*   == !=	*/
+%left CMPOP2		/*   < > <= >=	*/
+%left ADDOP2		/*   + -	*/
+%left MULOP2		/*   * / %	*/
+%right '!'		/*   !		*/
+
+%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
+%token <num> NUMBER
+%type <exp> exp
+
+%%
+
+start:	  exp
+	  {
+	    if ($1 == NULL)
+	      YYABORT;
+	    ((struct parse_args *) arg)->res = $1;
+	  }
+	;
+
+exp:	  exp '?' exp ':' exp
+	  {
+	    $$ = new_exp_3 (qmop, $1, $3, $5);
+	  }
+	| exp '|' exp
+	  {
+	    $$ = new_exp_2 (lor, $1, $3);
+	  }
+	| exp '&' exp
+	  {
+	    $$ = new_exp_2 (land, $1, $3);
+	  }
+	| exp EQUOP2 exp
+	  {
+	    $$ = new_exp_2 ($2, $1, $3);
+	  }
+	| exp CMPOP2 exp
+	  {
+	    $$ = new_exp_2 ($2, $1, $3);
+	  }
+	| exp ADDOP2 exp
+	  {
+	    $$ = new_exp_2 ($2, $1, $3);
+	  }
+	| exp MULOP2 exp
+	  {
+	    $$ = new_exp_2 ($2, $1, $3);
+	  }
+	| '!' exp
+	  {
+	    $$ = new_exp_1 (lnot, $2);
+	  }
+	| 'n'
+	  {
+	    $$ = new_exp_0 (var);
+	  }
+	| NUMBER
+	  {
+	    if (($$ = new_exp_0 (num)) != NULL)
+	      $$->val.num = $1;
+	  }
+	| '(' exp ')'
+	  {
+	    $$ = $2;
+	  }
+	;
+
+%%
+
+void
+internal_function
+FREE_EXPRESSION (exp)
+     struct expression *exp;
+{
+  if (exp == NULL)
+    return;
+
+  /* Handle the recursive case.  */
+  switch (exp->nargs)
+    {
+    case 3:
+      FREE_EXPRESSION (exp->val.args[2]);
+      /* FALLTHROUGH */
+    case 2:
+      FREE_EXPRESSION (exp->val.args[1]);
+      /* FALLTHROUGH */
+    case 1:
+      FREE_EXPRESSION (exp->val.args[0]);
+      /* FALLTHROUGH */
+    default:
+      break;
+    }
+
+  free (exp);
+}
+
+
+static int
+yylex (lval, pexp)
+     YYSTYPE *lval;
+     const char **pexp;
+{
+  const char *exp = *pexp;
+  int result;
+
+  while (1)
+    {
+      if (exp[0] == '\0')
+	{
+	  *pexp = exp;
+	  return YYEOF;
+	}
+
+      if (exp[0] != ' ' && exp[0] != '\t')
+	break;
+
+      ++exp;
+    }
+
+  result = *exp++;
+  switch (result)
+    {
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      {
+	unsigned long int n = result - '0';
+	while (exp[0] >= '0' && exp[0] <= '9')
+	  {
+	    n *= 10;
+	    n += exp[0] - '0';
+	    ++exp;
+	  }
+	lval->num = n;
+	result = NUMBER;
+      }
+      break;
+
+    case '=':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = equal;
+	  result = EQUOP2;
+	}
+      else
+	result = YYERRCODE;
+      break;
+
+    case '!':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = not_equal;
+	  result = EQUOP2;
+	}
+      break;
+
+    case '&':
+    case '|':
+      if (exp[0] == result)
+	++exp;
+      else
+	result = YYERRCODE;
+      break;
+
+    case '<':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = less_or_equal;
+	}
+      else
+	lval->op = less_than;
+      result = CMPOP2;
+      break;
+
+    case '>':
+      if (exp[0] == '=')
+	{
+	  ++exp;
+	  lval->op = greater_or_equal;
+	}
+      else
+	lval->op = greater_than;
+      result = CMPOP2;
+      break;
+
+    case '*':
+      lval->op = mult;
+      result = MULOP2;
+      break;
+
+    case '/':
+      lval->op = divide;
+      result = MULOP2;
+      break;
+
+    case '%':
+      lval->op = module;
+      result = MULOP2;
+      break;
+
+    case '+':
+      lval->op = plus;
+      result = ADDOP2;
+      break;
+
+    case '-':
+      lval->op = minus;
+      result = ADDOP2;
+      break;
+
+    case 'n':
+    case '?':
+    case ':':
+    case '(':
+    case ')':
+      /* Nothing, just return the character.  */
+      break;
+
+    case ';':
+    case '\n':
+    case '\0':
+      /* Be safe and let the user call this function again.  */
+      --exp;
+      result = YYEOF;
+      break;
+
+    default:
+      result = YYERRCODE;
+#if YYDEBUG != 0
+      --exp;
+#endif
+      break;
+    }
+
+  *pexp = exp;
+
+  return result;
+}
+
+
+static void
+yyerror (str)
+     const char *str;
+{
+  /* Do nothing.  We don't print error messages here.  */
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/ref-add.sin
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/ref-add.sin	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/ref-add.sin	(revision 1780)
@@ -0,0 +1,31 @@
+# Add this package to a list of references stored in a text file.
+#
+#   Copyright (C) 2000 Free Software Foundation, Inc.
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU Library General Public License as published
+#   by the Free Software Foundation; either version 2, or (at your option)
+#   any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#   Library General Public License for more details.
+#
+#   You should have received a copy of the GNU Library General Public
+#   License along with this program; if not, write to the Free Software
+#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+#   USA.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# Packages using this file: / {
+  s/# Packages using this file://
+  ta
+  :a
+  s/ @PACKAGE@ / @PACKAGE@ /
+  tb
+  s/ $/ @PACKAGE@ /
+  :b
+  s/^/# Packages using this file:/
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/ref-del.sin
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/ref-del.sin	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/ref-del.sin	(revision 1780)
@@ -0,0 +1,26 @@
+# Remove this package from a list of references stored in a text file.
+#
+#   Copyright (C) 2000 Free Software Foundation, Inc.
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU Library General Public License as published
+#   by the Free Software Foundation; either version 2, or (at your option)
+#   any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#   Library General Public License for more details.
+#
+#   You should have received a copy of the GNU Library General Public
+#   License along with this program; if not, write to the Free Software
+#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+#   USA.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# Packages using this file: / {
+  s/# Packages using this file://
+  s/ @PACKAGE@ / /
+  s/^/# Packages using this file:/
+}
Index: /tags/kBuild-0.1.4/src/sed/intl/textdomain.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/intl/textdomain.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/intl/textdomain.c	(revision 1780)
@@ -0,0 +1,142 @@
+/* Implementation of the textdomain(3) function.
+   Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+#include "gettextP.h"
+
+#ifdef _LIBC
+/* We have to handle multi-threaded applications.  */
+# include <bits/libc-lock.h>
+#else
+/* Provide dummy implementation if this is outside glibc.  */
+# define __libc_rwlock_define(CLASS, NAME)
+# define __libc_rwlock_wrlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#endif
+
+/* The internal variables in the standalone libintl.a must have different
+   names than the internal variables in GNU libc, otherwise programs
+   using libintl.a cannot be linked statically.  */
+#if !defined _LIBC
+# define _nl_default_default_domain _nl_default_default_domain__
+# define _nl_current_default_domain _nl_current_default_domain__
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Name of the default text domain.  */
+extern const char _nl_default_default_domain[];
+
+/* Default text domain in which entries for gettext(3) are to be found.  */
+extern const char *_nl_current_default_domain;
+
+
+/* Names for the libintl functions are a problem.  They must not clash
+   with existing names and they should follow ANSI C.  But this source
+   code is also used in GNU C Library where the names have a __
+   prefix.  So we have to make a difference here.  */
+#ifdef _LIBC
+# define TEXTDOMAIN __textdomain
+# ifndef strdup
+#  define strdup(str) __strdup (str)
+# endif
+#else
+# define TEXTDOMAIN textdomain__
+#endif
+
+/* Lock variable to protect the global data in the gettext implementation.  */
+__libc_rwlock_define (extern, _nl_state_lock)
+
+/* Set the current default message catalog to DOMAINNAME.
+   If DOMAINNAME is null, return the current default.
+   If DOMAINNAME is "", reset to the default of "messages".  */
+char *
+TEXTDOMAIN (domainname)
+     const char *domainname;
+{
+  char *new_domain;
+  char *old_domain;
+
+  /* A NULL pointer requests the current setting.  */
+  if (domainname == NULL)
+    return (char *) _nl_current_default_domain;
+
+  __libc_rwlock_wrlock (_nl_state_lock);
+
+  old_domain = (char *) _nl_current_default_domain;
+
+  /* If domain name is the null string set to default domain "messages".  */
+  if (domainname[0] == '\0'
+      || strcmp (domainname, _nl_default_default_domain) == 0)
+    {
+      _nl_current_default_domain = _nl_default_default_domain;
+      new_domain = (char *) _nl_current_default_domain;
+    }
+  else if (strcmp (domainname, old_domain) == 0)
+    /* This can happen and people will use it to signal that some
+       environment variable changed.  */
+    new_domain = old_domain;
+  else
+    {
+      /* If the following malloc fails `_nl_current_default_domain'
+	 will be NULL.  This value will be returned and so signals we
+	 are out of core.  */
+#if defined _LIBC || defined HAVE_STRDUP
+      new_domain = strdup (domainname);
+#else
+      size_t len = strlen (domainname) + 1;
+      new_domain = (char *) malloc (len);
+      if (new_domain != NULL)
+	memcpy (new_domain, domainname, len);
+#endif
+
+      if (new_domain != NULL)
+	_nl_current_default_domain = new_domain;
+    }
+
+  /* We use this possibility to signal a change of the loaded catalogs
+     since this is most likely the case and there is no other easy we
+     to do it.  Do it only when the call was successful.  */
+  if (new_domain != NULL)
+    {
+      ++_nl_msg_cat_cntr;
+
+      if (old_domain != new_domain && old_domain != _nl_default_default_domain)
+	free (old_domain);
+    }
+
+  __libc_rwlock_unlock (_nl_state_lock);
+
+  return new_domain;
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library.  */
+weak_alias (__textdomain, textdomain);
+#endif
Index: /tags/kBuild-0.1.4/src/sed/lib/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/Makefile.am	(revision 1780)
@@ -0,0 +1,16 @@
+## Process this file with automake to produce Makefile.in
+noinst_LIBRARIES = libsed.a
+noinst_HEADERS = getopt.h utils.h obstack.h regex_.h regex_internal.h \
+	strverscmp.h stdbool_.h
+
+libsed_a_SOURCES = getopt1.c getopt.c utils.c
+
+EXTRA_DIST = memmove.c strerror.c regcomp.c regexec.c regex_internal.c
+
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/intl -I$(top_srcdir) \
+	-I$(top_builddir)/lib -I$(top_builddir)/intl
+
+libsed_a_LIBADD = @LIBOBJS@ @ALLOCA@
+libsed_a_DEPENDENCIES = $(libsed_a_LIBADD)
+
+DISTCLEANFILES = regex.h stdbool.h
Index: /tags/kBuild-0.1.4/src/sed/lib/Makefile.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/Makefile.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/Makefile.in	(revision 1780)
@@ -0,0 +1,456 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# 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_MAKE@
+
+
+SOURCES = $(libsed_a_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lib
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in $(srcdir)/regex_.h $(srcdir)/stdbool_.h \
+	alloca.c getline.c memchr.c memcmp.c memmove.c mkstemp.c \
+	obstack.c obstack.h regex.c strerror.c strverscmp.c
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \
+	$(top_srcdir)/config/getline.m4 \
+	$(top_srcdir)/config/gettext-ver.m4 \
+	$(top_srcdir)/config/gettext.m4 \
+	$(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \
+	$(top_srcdir)/config/lcmessage.m4 \
+	$(top_srcdir)/config/lib-ld.m4 \
+	$(top_srcdir)/config/lib-link.m4 \
+	$(top_srcdir)/config/lib-prefix.m4 \
+	$(top_srcdir)/config/progtest.m4 \
+	$(top_srcdir)/config/stdbool.m4 \
+	$(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = stdbool.h regex.h
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libsed_a_AR = $(AR) $(ARFLAGS)
+am_libsed_a_OBJECTS = getopt1.$(OBJEXT) getopt.$(OBJEXT) \
+	utils.$(OBJEXT)
+libsed_a_OBJECTS = $(am_libsed_a_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libsed_a_SOURCES)
+DIST_SOURCES = $(libsed_a_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_HTML_FALSE = @BUILD_HTML_FALSE@
+BUILD_HTML_TRUE = @BUILD_HTML_TRUE@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
+GMSGFMT = @GMSGFMT@
+HAVE__BOOL = @HAVE__BOOL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@
+MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SED_FEATURE_VERSION = @SED_FEATURE_VERSION@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEST_REGEX_FALSE = @TEST_REGEX_FALSE@
+TEST_REGEX_TRUE = @TEST_REGEX_TRUE@
+TEXI2HTML = @TEXI2HTML@
+TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@
+TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+noinst_LIBRARIES = libsed.a
+noinst_HEADERS = getopt.h utils.h obstack.h regex_.h regex_internal.h \
+	strverscmp.h stdbool_.h
+
+libsed_a_SOURCES = getopt1.c getopt.c utils.c
+EXTRA_DIST = memmove.c strerror.c regcomp.c regexec.c regex_internal.c
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/intl -I$(top_srcdir) \
+	-I$(top_builddir)/lib -I$(top_builddir)/intl
+
+libsed_a_LIBADD = @LIBOBJS@ @ALLOCA@
+libsed_a_DEPENDENCIES = $(libsed_a_LIBADD)
+DISTCLEANFILES = regex.h stdbool.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits  lib/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnits  lib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+stdbool.h: $(top_builddir)/config.status $(srcdir)/stdbool_.h
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libsed.a: $(libsed_a_OBJECTS) $(libsed_a_DEPENDENCIES) 
+	-rm -f libsed.a
+	$(libsed_a_AR) libsed.a $(libsed_a_OBJECTS) $(libsed_a_LIBADD)
+	$(RANLIB) libsed.a
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getline.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memchr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memcmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memmove.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mkstemp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/obstack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/regex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strerror.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strverscmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf $(DEPDIR) ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf $(DEPDIR) ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-noinstLIBRARIES ctags distclean distclean-compile \
+	distclean-generic distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /tags/kBuild-0.1.4/src/sed/lib/alloca.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/alloca.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/alloca.c	(revision 1780)
@@ -0,0 +1,504 @@
+/* alloca.c -- allocate automatically reclaimed memory
+   (Mostly) portable public-domain implementation -- D A Gwyn
+
+   This implementation of the PWB library alloca function,
+   which is used to allocate space off the run-time stack so
+   that it is automatically reclaimed upon procedure exit,
+   was inspired by discussions with J. Q. Johnson of Cornell.
+   J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+   There are some preprocessor constants that can
+   be defined when compiling for your specific system, for
+   improved efficiency; however, the defaults should be okay.
+
+   The general concept of this implementation is to keep
+   track of all alloca-allocated blocks, and reclaim any
+   that are found to be deeper in the stack than the current
+   invocation.  This heuristic does not reclaim storage as
+   soon as it becomes invalid, but it will do so eventually.
+
+   As a special case, alloca(0) reclaims storage without
+   allocating any.  It is a good idea to use alloca(0) in
+   your main control loop, etc. to force garbage collection.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef emacs
+#include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed.  */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+   there must be some other way alloca is supposed to work.  */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+   provide an "address metric" ADDRESS_FUNCTION macro.  */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#ifndef NULL
+#define	NULL	0
+#endif
+
+/* Different portions of Emacs need to call different versions of
+   malloc.  The Emacs executable needs alloca to call xmalloc, because
+   ordinary malloc isn't protected from input signals.  On the other
+   hand, the utilities in lib-src need alloca to call malloc; some of
+   them are very simple, and don't have an xmalloc routine.
+
+   Non-Emacs programs expect this to call xmalloc.
+
+   Callers below should use malloc.  */
+
+#ifndef emacs
+#define malloc xmalloc
+#endif
+extern pointer malloc ();
+
+/* Define STACK_DIRECTION if you know the direction of stack
+   growth for your system; otherwise it will be automatically
+   deduced at run-time.
+
+   STACK_DIRECTION > 0 => grows toward higher addresses
+   STACK_DIRECTION < 0 => grows toward lower addresses
+   STACK_DIRECTION = 0 => direction of growth unknown  */
+
+#ifndef STACK_DIRECTION
+#define	STACK_DIRECTION	0	/* Direction unknown.  */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define	STACK_DIR	STACK_DIRECTION	/* Known at compile-time.  */
+
+#else /* STACK_DIRECTION == 0; need run-time code.  */
+
+static int stack_dir;		/* 1 or -1 once known.  */
+#define	STACK_DIR	stack_dir
+
+static void
+find_stack_direction ()
+{
+  static char *addr = NULL;	/* Address of first `dummy', once known.  */
+  auto char dummy;		/* To get stack address.  */
+
+  if (addr == NULL)
+    {				/* Initial entry.  */
+      addr = ADDRESS_FUNCTION (dummy);
+
+      find_stack_direction ();	/* Recurse once.  */
+    }
+  else
+    {
+      /* Second entry.  */
+      if (ADDRESS_FUNCTION (dummy) > addr)
+	stack_dir = 1;		/* Stack grew upward.  */
+      else
+	stack_dir = -1;		/* Stack grew downward.  */
+    }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+   (a) chain together all alloca'ed blocks;
+   (b) keep track of stack depth.
+
+   It is very important that sizeof(header) agree with malloc
+   alignment chunk size.  The following default should work okay.  */
+
+#ifndef	ALIGN_SIZE
+#define	ALIGN_SIZE	sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];	/* To force sizeof(header).  */
+  struct
+    {
+      union hdr *next;		/* For chaining headers.  */
+      char *deep;		/* For stack depth measure.  */
+    } h;
+} header;
+
+static header *last_alloca_header = NULL;	/* -> last alloca header.  */
+
+/* Return a pointer to at least SIZE bytes of storage,
+   which will be automatically reclaimed upon exit from
+   the procedure that called alloca.  Originally, this space
+   was supposed to be taken from the current stack frame of the
+   caller, but that method cannot be made to work for some
+   implementations of C, for example under Gould's UTX/32.  */
+
+pointer
+alloca (size)
+     unsigned size;
+{
+  auto char probe;		/* Probes stack depth: */
+  register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)		/* Unknown growth direction.  */
+    find_stack_direction ();
+#endif
+
+  /* Reclaim garbage, defined as all alloca'd storage that
+     was allocated from deeper in the stack than currently.  */
+
+  {
+    register header *hp;	/* Traverses linked list.  */
+
+#ifdef emacs
+    BLOCK_INPUT;
+#endif
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if ((STACK_DIR > 0 && hp->h.deep > depth)
+	  || (STACK_DIR < 0 && hp->h.deep < depth))
+	{
+	  register header *np = hp->h.next;
+
+	  free ((pointer) hp);	/* Collect garbage.  */
+
+	  hp = np;		/* -> next header.  */
+	}
+      else
+	break;			/* Rest are not deeper.  */
+
+    last_alloca_header = hp;	/* -> last valid storage.  */
+
+#ifdef emacs
+    UNBLOCK_INPUT;
+#endif
+  }
+
+  if (size == 0)
+    return NULL;		/* No allocation required.  */
+
+  /* Allocate combined header + user data storage.  */
+
+  {
+    register pointer new = malloc (sizeof (header) + size);
+    /* Address of header.  */
+
+    if (new == 0)
+      abort();
+
+    ((header *) new)->h.next = last_alloca_header;
+    ((header *) new)->h.deep = depth;
+
+    last_alloca_header = (header *) new;
+
+    /* User storage begins just after header.  */
+
+    return (pointer) ((char *) new + sizeof (header));
+  }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+  {
+    long shgrow:32;		/* Number of times stack has grown.  */
+    long shaseg:32;		/* Size of increments to stack.  */
+    long shhwm:32;		/* High water mark of stack.  */
+    long shsize:32;		/* Current size of stack (all segments).  */
+  };
+
+/* The stack segment linkage control information occurs at
+   the high-address end of a stack segment.  (The stack
+   grows from low addresses to high addresses.)  The initial
+   part of the stack segment linkage control information is
+   0200 (octal) words.  This provides for register storage
+   for the routine which overflows the stack.  */
+
+struct stack_segment_linkage
+  {
+    long ss[0200];		/* 0200 overflow words.  */
+    long sssize:32;		/* Number of words in this segment.  */
+    long ssbase:32;		/* Offset to stack base.  */
+    long:32;
+    long sspseg:32;		/* Offset to linkage control of previous
+				   segment of stack.  */
+    long:32;
+    long sstcpt:32;		/* Pointer to task common address block.  */
+    long sscsnm;		/* Private control structure number for
+				   microtasking.  */
+    long ssusr1;		/* Reserved for user.  */
+    long ssusr2;		/* Reserved for user.  */
+    long sstpid;		/* Process ID for pid based multi-tasking.  */
+    long ssgvup;		/* Pointer to multitasking thread giveup.  */
+    long sscray[7];		/* Reserved for Cray Research.  */
+    long ssa0;
+    long ssa1;
+    long ssa2;
+    long ssa3;
+    long ssa4;
+    long ssa5;
+    long ssa6;
+    long ssa7;
+    long sss0;
+    long sss1;
+    long sss2;
+    long sss3;
+    long sss4;
+    long sss5;
+    long sss6;
+    long sss7;
+  };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+   returned by the STKSTAT library routine.  */
+struct stk_stat
+  {
+    long now;			/* Current total stack size.  */
+    long maxc;			/* Amount of contiguous space which would
+				   be required to satisfy the maximum
+				   stack demand to date.  */
+    long high_water;		/* Stack high-water mark.  */
+    long overflows;		/* Number of stack overflow ($STKOFEN) calls.  */
+    long hits;			/* Number of internal buffer hits.  */
+    long extends;		/* Number of block extensions.  */
+    long stko_mallocs;		/* Block allocations by $STKOFEN.  */
+    long underflows;		/* Number of stack underflow calls ($STKRETN).  */
+    long stko_free;		/* Number of deallocations by $STKRETN.  */
+    long stkm_free;		/* Number of deallocations by $STKMRET.  */
+    long segments;		/* Current number of stack segments.  */
+    long maxs;			/* Maximum number of stack segments so far.  */
+    long pad_size;		/* Stack pad size.  */
+    long current_address;	/* Current stack segment address.  */
+    long current_size;		/* Current stack segment size.  This
+				   number is actually corrupted by STKSTAT to
+				   include the fifteen word trailer area.  */
+    long initial_address;	/* Address of initial segment.  */
+    long initial_size;		/* Size of initial segment.  */
+  };
+
+/* The following structure describes the data structure which trails
+   any stack segment.  I think that the description in 'asdef' is
+   out of date.  I only describe the parts that I am sure about.  */
+
+struct stk_trailer
+  {
+    long this_address;		/* Address of this block.  */
+    long this_size;		/* Size of this block (does not include
+				   this trailer).  */
+    long unknown2;
+    long unknown3;
+    long link;			/* Address of trailer block of previous
+				   segment.  */
+    long unknown5;
+    long unknown6;
+    long unknown7;
+    long unknown8;
+    long unknown9;
+    long unknown10;
+    long unknown11;
+    long unknown12;
+    long unknown13;
+    long unknown14;
+  };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+   I doubt that "lint" will like this much.  */
+
+static long
+i00afunc (long *address)
+{
+  struct stk_stat status;
+  struct stk_trailer *trailer;
+  long *block, size;
+  long result = 0;
+
+  /* We want to iterate through all of the segments.  The first
+     step is to get the stack status structure.  We could do this
+     more quickly and more directly, perhaps, by referencing the
+     $LM00 common block, but I know that this works.  */
+
+  STKSTAT (&status);
+
+  /* Set up the iteration.  */
+
+  trailer = (struct stk_trailer *) (status.current_address
+				    + status.current_size
+				    - 15);
+
+  /* There must be at least one stack segment.  Therefore it is
+     a fatal error if "trailer" is null.  */
+
+  if (trailer == 0)
+    abort ();
+
+  /* Discard segments that do not contain our argument address.  */
+
+  while (trailer != 0)
+    {
+      block = (long *) trailer->this_address;
+      size = trailer->this_size;
+      if (block == 0 || size == 0)
+	abort ();
+      trailer = (struct stk_trailer *) trailer->link;
+      if ((block <= address) && (address < (block + size)))
+	break;
+    }
+
+  /* Set the result to the offset in this segment and add the sizes
+     of all predecessor segments.  */
+
+  result = address - block;
+
+  if (trailer == 0)
+    {
+      return result;
+    }
+
+  do
+    {
+      if (trailer->this_size <= 0)
+	abort ();
+      result += trailer->this_size;
+      trailer = (struct stk_trailer *) trailer->link;
+    }
+  while (trailer != 0);
+
+  /* We are done.  Note that if you present a bogus address (one
+     not in any segment), you will get a different number back, formed
+     from subtracting the address of the first block.  This is probably
+     not what you want.  */
+
+  return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+   Determine the number of the cell within the stack,
+   given the address of the cell.  The purpose of this
+   routine is to linearize, in some sense, stack addresses
+   for alloca.  */
+
+static long
+i00afunc (long address)
+{
+  long stkl = 0;
+
+  long size, pseg, this_segment, stack;
+  long result = 0;
+
+  struct stack_segment_linkage *ssptr;
+
+  /* Register B67 contains the address of the end of the
+     current stack segment.  If you (as a subprogram) store
+     your registers on the stack and find that you are past
+     the contents of B67, you have overflowed the segment.
+
+     B67 also points to the stack segment linkage control
+     area, which is what we are really interested in.  */
+
+  stkl = CRAY_STACKSEG_END ();
+  ssptr = (struct stack_segment_linkage *) stkl;
+
+  /* If one subtracts 'size' from the end of the segment,
+     one has the address of the first word of the segment.
+
+     If this is not the first segment, 'pseg' will be
+     nonzero.  */
+
+  pseg = ssptr->sspseg;
+  size = ssptr->sssize;
+
+  this_segment = stkl - size;
+
+  /* It is possible that calling this routine itself caused
+     a stack overflow.  Discard stack segments which do not
+     contain the target address.  */
+
+  while (!(this_segment <= address && address <= stkl))
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+      if (pseg == 0)
+	break;
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      this_segment = stkl - size;
+    }
+
+  result = address - this_segment;
+
+  /* If you subtract pseg from the current end of the stack,
+     you get the address of the previous stack segment's end.
+     This seems a little convoluted to me, but I'll bet you save
+     a cycle somewhere.  */
+
+  while (pseg != 0)
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      result += size;
+    }
+  return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY */
+
+#endif /* no alloca */
+#endif /* not GCC version 2 */
Index: /tags/kBuild-0.1.4/src/sed/lib/getline.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/getline.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/getline.c	(revision 1780)
@@ -0,0 +1,110 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#undef _GNU_SOURCE
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#else
+# include <string.h>
+#endif /* HAVE_STRINGS_H */
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <limits.h>
+#include <errno.h>
+
+/* Read up to (and including) a '\n' from STREAM into *LINEPTR
+   (and null-terminate it). *LINEPTR is a pointer returned from malloc (or
+   NULL), pointing to *N characters of space.  It is realloc'd as
+   necessary.  Returns the number of characters read (not including the
+   null terminator), or -1 on error or EOF.  */
+
+size_t
+getline (lineptr, n, stream)
+     char **lineptr;
+     size_t *n;
+     FILE *stream;
+{
+  char *line, *p;
+  long size, copy;
+
+  if (lineptr == NULL || n == NULL)
+    {
+      errno = EINVAL;
+      return (size_t) -1;
+    }
+
+  if (ferror (stream))
+    return (size_t) -1;
+
+  /* Make sure we have a line buffer to start with.  */
+  if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars.  */
+    {
+#ifndef	MAX_CANON
+#define	MAX_CANON	256
+#endif
+      if (!*lineptr)
+        line = (char *) malloc (MAX_CANON);
+      else
+        line = (char *) realloc (*lineptr, MAX_CANON);
+      if (line == NULL)
+	return (size_t) -1;
+      *lineptr = line;
+      *n = MAX_CANON;
+    }
+
+  line = *lineptr;
+  size = *n;
+
+  copy = size;
+  p = line;
+
+  while (1)
+    {
+      long len;
+      
+      while (--copy > 0)
+	{
+	  register int c = getc (stream);
+	  if (c == EOF)
+	    goto lose;
+	  else if ((*p++ = c) == '\n')
+	    goto win;
+	}
+      
+      /* Need to enlarge the line buffer.  */
+      len = p - line;
+      size *= 2;
+      line = (char *) realloc (line, size);
+      if (line == NULL)
+	goto lose;
+      *lineptr = line;
+      *n = size;
+      p = line + len;
+      copy = size - len;
+    }
+
+ lose:
+  if (p == *lineptr)
+    return (size_t) -1;
+
+  /* Return a partial line since we got an error in the middle.  */
+ win:
+#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS) || defined(__EMX__)
+  if (p - 2 >= *lineptr && p[-2] == '\r')
+    p[-2] = p[-1], --p;
+#endif
+  *p = '\0';
+  return p - *lineptr;
+}
Index: /tags/kBuild-0.1.4/src/sed/lib/getopt.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/getopt.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/getopt.c	(revision 1780)
@@ -0,0 +1,1063 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to drepper@gnu.org
+   before changing it!
+
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98
+   	Free Software Foundation, Inc.
+
+   NOTE: The canonical source of this file is maintained with the GNU C Library.
+   Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+   Ditto for AIX 3.2 and <stdlib.h>.  */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+# ifndef const
+#  define const
+# endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef	__GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+# include <stdlib.h>
+# include <unistd.h>
+#endif	/* GNU C library.  */
+
+#ifdef VMS
+# include <unixlib.h>
+# if HAVE_STRING_H - 0
+#  include <string.h>
+# endif
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+   When compiling libc, the _ macro is predefined.  */
+# ifdef HAVE_LIBINTL_H
+#  include <libintl.h>
+#  define _(msgid)	gettext (msgid)
+# else
+#  define _(msgid)	(msgid)
+# endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* 1003.2 says this must be 1 before any call.  */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+   causes problems with re-calling getopt as programs generally don't
+   know that. */
+
+int __getopt_initialized = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable.  */
+static char *posixly_correct;
+
+
+#ifdef	__GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+# include <string.h>
+# define my_index	strchr
+
+#elif defined(_MSC_VER) || defined(__APPLE__) || defined(__FreeBSD__) \
+   || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__) \
+   || defined(__OS2__) || defined(__DragonFly__)
+# include <stdlib.h>
+# include <string.h>
+# include <stdio.h>
+# define my_index	strchr
+
+#else
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+#ifndef strncmp
+extern int strncmp ();
+#endif
+
+static char *
+my_index (str, chr)
+     const char *str;
+     int chr;
+{
+  while (*str)
+    {
+      if (*str == chr)
+	return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+   That was relevant to code that was here before.  */
+# if (!defined __STDC__ || !__STDC__) && !defined strlen
+/* gcc with -traditional declares the built-in strlen to return int,
+   and has done so at least since version 2.4.5. -- rms.  */
+extern int strlen (const char *);
+# endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+   indicating ARGV elements that should not be considered arguments.  */
+
+/* Defined in getopt_init.c  */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+   is valid for the getopt call we must make sure that the ARGV passed
+   to getopt is that one passed to the process.  */
+static void
+__attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+  /* XXX This is no good solution.  We should rather copy the args so
+     that we can compare them later.  But we must not use malloc(3).  */
+  original_argc = argc;
+  original_argv = argv;
+}
+# ifdef text_set_element
+text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
+
+# define SWAP_FLAGS(ch1, ch2) \
+  if (nonoption_flags_len > 0)						      \
+    {									      \
+      char __tmp = __getopt_nonoption_flags[ch1];			      \
+      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \
+      __getopt_nonoption_flags[ch2] = __tmp;				      \
+    }
+#else	/* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif	/* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+#if defined __STDC__ && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+#ifdef _LIBC
+  /* First make sure the handling of the `__getopt_nonoption_flags'
+     string can work normally.  Our top argument must be in the range
+     of the string.  */
+  if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+    {
+      /* We must extend the array.  The user plays games with us and
+	 presents new arguments.  */
+      char *new_str = malloc (top + 1);
+      if (new_str == NULL)
+	nonoption_flags_len = nonoption_flags_max_len = 0;
+      else
+	{
+	  memset (__mempcpy (new_str, __getopt_nonoption_flags,
+			     nonoption_flags_max_len),
+		  '\0', top + 1 - nonoption_flags_max_len);
+	  nonoption_flags_max_len = top + 1;
+	  __getopt_nonoption_flags = new_str;
+	}
+    }
+#endif
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	      SWAP_FLAGS (bottom + i, middle + i);
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+#if defined __STDC__ && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  first_nonopt = last_nonopt = optind;
+
+  nextchar = NULL;
+
+  posixly_correct = getenv ("POSIXLY_CORRECT");
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (posixly_correct != NULL)
+    ordering = REQUIRE_ORDER;
+  else
+    ordering = PERMUTE;
+
+#ifdef _LIBC
+  if (posixly_correct == NULL
+      && argc == original_argc && argv == original_argv)
+    {
+      if (nonoption_flags_max_len == 0)
+	{
+	  if (__getopt_nonoption_flags == NULL
+	      || __getopt_nonoption_flags[0] == '\0')
+	    nonoption_flags_max_len = -1;
+	  else
+	    {
+	      const char *orig_str = __getopt_nonoption_flags;
+	      int len = nonoption_flags_max_len = strlen (orig_str);
+	      if (nonoption_flags_max_len < argc)
+		nonoption_flags_max_len = argc;
+	      __getopt_nonoption_flags =
+		(char *) malloc (nonoption_flags_max_len);
+	      if (__getopt_nonoption_flags == NULL)
+		nonoption_flags_max_len = -1;
+	      else
+		memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+			'\0', nonoption_flags_max_len - len);
+	    }
+	}
+      nonoption_flags_len = nonoption_flags_max_len;
+    }
+  else
+    nonoption_flags_len = 0;
+#endif
+
+  return optstring;
+}
+
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns -1.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  optarg = NULL;
+
+  if (optind == 0 || !__getopt_initialized)
+    {
+      if (optind == 0)
+	optind = 1;	/* Don't scan ARGV[0], the program name.  */
+      optstring = _getopt_initialize (argc, argv, optstring);
+      __getopt_initialized = 1;
+    }
+
+  /* Test whether ARGV[optind] points to a non-option argument.
+     Either it does not have option syntax, or there is an environment flag
+     from the shell indicating it is not an option.  The later information
+     is only used when the used in the GNU libc.  */
+#ifdef _LIBC
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0'	      \
+		      || (optind < nonoption_flags_len			      \
+			  && __getopt_nonoption_flags[optind] == '1'))
+#else
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+	 moved back by the user (who may also have changed the arguments).  */
+      if (last_nonopt > optind)
+	last_nonopt = optind;
+      if (first_nonopt > optind)
+	first_nonopt = optind;
+
+      if (ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (last_nonopt != optind)
+	    first_nonopt = optind;
+
+	  /* Skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (optind < argc && NONOPTION_P)
+	    optind++;
+	  last_nonopt = optind;
+	}
+
+      /* The special ARGV-element `--' means premature end of options.
+	 Skip it like a null option,
+	 then exchange with previous non-options as if it were an option,
+	 then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+	{
+	  optind++;
+
+	  if (first_nonopt != last_nonopt && last_nonopt != optind)
+	    exchange ((char **) argv);
+	  else if (first_nonopt == last_nonopt)
+	    first_nonopt = optind;
+	  last_nonopt = argc;
+
+	  optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+	 and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (first_nonopt != last_nonopt)
+	    optind = first_nonopt;
+	  return -1;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+	 either stop the scan or describe it to the caller and pass it by.  */
+
+      if (NONOPTION_P)
+	{
+	  if (ordering == REQUIRE_ORDER)
+	    return -1;
+	  optarg = argv[optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+	 Skip the initial punctuation.  */
+
+      nextchar = (argv[optind] + 1
+		  + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[optind][1] == '-'
+	  || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = -1;
+      int option_index;
+
+      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+	/* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+	 or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, nextchar, nameend - nextchar))
+	  {
+	    if ((unsigned int) (nameend - nextchar)
+		== (unsigned int) strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else
+	      /* Second or later nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (opterr)
+	    fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+		     argv[0], argv[optind]);
+	  nextchar += strlen (nextchar);
+	  optind++;
+	  optopt = 0;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  optind++;
+	  if (*nameend)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+		 allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		optarg = nameend + 1;
+	      else
+		{
+		  if (opterr)
+		   if (argv[optind - 1][1] == '-')
+		    /* --option */
+		    fprintf (stderr,
+		     _("%s: option `--%s' doesn't allow an argument\n"),
+		     argv[0], pfound->name);
+		   else
+		    /* +option or -option */
+		    fprintf (stderr,
+		     _("%s: option `%c%s' doesn't allow an argument\n"),
+		     argv[0], argv[optind - 1][0], pfound->name);
+
+		  nextchar += strlen (nextchar);
+
+		  optopt = pfound->val;
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (optind < argc)
+		optarg = argv[optind++];
+	      else
+		{
+		  if (opterr)
+		    fprintf (stderr,
+			   _("%s: option `%s' requires an argument\n"),
+			   argv[0], argv[optind - 1]);
+		  nextchar += strlen (nextchar);
+		  optopt = pfound->val;
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  nextchar += strlen (nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short
+	 option, then it's an error.
+	 Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+	  || my_index (optstring, *nextchar) == NULL)
+	{
+	  if (opterr)
+	    {
+	      if (argv[optind][1] == '-')
+		/* --option */
+		fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+			 argv[0], nextchar);
+	      else
+		/* +option or -option */
+		fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+			 argv[0], argv[optind][0], nextchar);
+	    }
+	  nextchar = (char *) "";
+	  optind++;
+	  optopt = 0;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (opterr)
+	  {
+	    if (posixly_correct)
+	      /* 1003.2 specifies the format of this message.  */
+	      fprintf (stderr, _("%s: illegal option -- %c\n"),
+		       argv[0], c);
+	    else
+	      fprintf (stderr, _("%s: invalid option -- %c\n"),
+		       argv[0], c);
+	  }
+	optopt = c;
+	return '?';
+      }
+    /* Convenience. Treat POSIX -W foo same as long option --foo */
+    if (temp[0] == 'W' && temp[1] == ';')
+      {
+	char *nameend;
+	const struct option *p;
+	const struct option *pfound = NULL;
+	int exact = 0;
+	int ambig = 0;
+	int indfound = 0;
+	int option_index;
+
+	/* This is an option that requires an argument.  */
+	if (*nextchar != '\0')
+	  {
+	    optarg = nextchar;
+	    /* If we end this ARGV-element by taking the rest as an arg,
+	       we must advance to the next element now.  */
+	    optind++;
+	  }
+	else if (optind == argc)
+	  {
+	    if (opterr)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+		fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+			 argv[0], c);
+	      }
+	    optopt = c;
+	    if (optstring[0] == ':')
+	      c = ':';
+	    else
+	      c = '?';
+	    return c;
+	  }
+	else
+	  /* We already incremented `optind' once;
+	     increment it again when taking next ARGV-elt as argument.  */
+	  optarg = argv[optind++];
+
+	/* optarg is now the argument, see if it's in the
+	   table of longopts.  */
+
+	for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+	  /* Do nothing.  */ ;
+
+	/* Test all long options for either exact match
+	   or abbreviated matches.  */
+	for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	  if (!strncmp (p->name, nextchar, nameend - nextchar))
+	    {
+	      if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+		{
+		  /* Exact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		  exact = 1;
+		  break;
+		}
+	      else if (pfound == NULL)
+		{
+		  /* First nonexact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		}
+	      else
+		/* Second or later nonexact match found.  */
+		ambig = 1;
+	    }
+	if (ambig && !exact)
+	  {
+	    if (opterr)
+	      fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+		       argv[0], argv[optind]);
+	    nextchar += strlen (nextchar);
+	    optind++;
+	    return '?';
+	  }
+	if (pfound != NULL)
+	  {
+	    option_index = indfound;
+	    if (*nameend)
+	      {
+		/* Don't test has_arg with >, because some C compilers don't
+		   allow it to be used on enums.  */
+		if (pfound->has_arg)
+		  optarg = nameend + 1;
+		else
+		  {
+		    if (opterr)
+		      fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+			       argv[0], pfound->name);
+
+		    nextchar += strlen (nextchar);
+		    return '?';
+		  }
+	      }
+	    else if (pfound->has_arg == 1)
+	      {
+		if (optind < argc)
+		  optarg = argv[optind++];
+		else
+		  {
+		    if (opterr)
+		      fprintf (stderr,
+			       _("%s: option `%s' requires an argument\n"),
+			       argv[0], argv[optind - 1]);
+		    nextchar += strlen (nextchar);
+		    return optstring[0] == ':' ? ':' : '?';
+		  }
+	      }
+	    nextchar += strlen (nextchar);
+	    if (longind != NULL)
+	      *longind = option_index;
+	    if (pfound->flag)
+	      {
+		*(pfound->flag) = pfound->val;
+		return 0;
+	      }
+	    return pfound->val;
+	  }
+	  nextchar = NULL;
+	  return 'W';	/* Let the application handle it.   */
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		optind++;
+	      }
+	    else
+	      optarg = NULL;
+	    nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*nextchar != '\0')
+	      {
+		optarg = nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		optind++;
+	      }
+	    else if (optind == argc)
+	      {
+		if (opterr)
+		  {
+		    /* 1003.2 specifies the format of this message.  */
+		    fprintf (stderr,
+			   _("%s: option requires an argument -- %c\n"),
+			   argv[0], c);
+		  }
+		optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+		 increment it again when taking next ARGV-elt as argument.  */
+	      optarg = argv[optind++];
+	    nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+			   (const struct option *) 0,
+			   (int *) 0,
+			   0);
+}
+
+#endif	/* Not ELIDE_CODE.  */
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /tags/kBuild-0.1.4/src/sed/lib/getopt.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/getopt.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/getopt.h	(revision 1780)
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+   Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+
+   NOTE: The canonical source of this file is maintained with the GNU C Library.
+   Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument 	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define	no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+		        const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind,
+			     int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* getopt.h */
Index: /tags/kBuild-0.1.4/src/sed/lib/getopt1.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/getopt1.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/getopt1.c	(revision 1780)
@@ -0,0 +1,192 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
+     Free Software Foundation, Inc.
+
+   NOTE: The canonical source of this file is maintained with the GNU C Library.
+   Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "getopt.h"
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef	NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif	/* Not ELIDE_CODE.  */
+
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
Index: /tags/kBuild-0.1.4/src/sed/lib/memchr.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/memchr.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/memchr.c	(revision 1780)
@@ -0,0 +1,200 @@
+/* Copyright (C) 1991, 1993, 1996, 1997 Free Software Foundation, Inc.
+   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se) and
+   commentary by Jim Blandy (jimb@ai.mit.edu);
+   adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+   and implemented by Roland McGrath (roland@ai.mit.edu).
+
+   NOTE: The canonical source of this file is maintained with the GNU C Library.
+   Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#undef __ptr_t
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+# define __ptr_t void *
+#else /* Not C++ or ANSI C.  */
+# define __ptr_t char *
+#endif /* C++ or ANSI C.  */
+
+#if defined (_LIBC)
+# include <string.h>
+#endif
+
+#if defined (HAVE_LIMITS_H) || defined (_LIBC)
+# include <limits.h>
+#endif
+
+#define LONG_MAX_32_BITS 2147483647
+
+#ifndef LONG_MAX
+#define LONG_MAX LONG_MAX_32_BITS
+#endif
+
+#include <sys/types.h>
+
+#undef memchr
+
+
+/* Search no more than N bytes of S for C.  */
+__ptr_t
+memchr (s, c, n)
+     const __ptr_t s;
+     int c;
+     size_t n;
+{
+  const unsigned char *char_ptr;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, charmask;
+
+  c = (unsigned char) c;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       n > 0 && ((unsigned long int) char_ptr
+		 & (sizeof (longword) - 1)) != 0;
+       --n, ++char_ptr)
+    if (*char_ptr == c)
+      return (__ptr_t) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+
+  if (sizeof (longword) != 4 && sizeof (longword) != 8)
+    abort ();
+
+#if LONG_MAX <= LONG_MAX_32_BITS
+  magic_bits = 0x7efefeff;
+#else
+  magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff;
+#endif
+
+  /* Set up a longword, each of whose bytes is C.  */
+  charmask = c | (c << 8);
+  charmask |= charmask << 16;
+#if LONG_MAX > LONG_MAX_32_BITS
+  charmask |= charmask << 32;
+#endif
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  while (n >= sizeof (longword))
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.
+
+	 3) But wait!  Aren't we looking for C, not zero?
+	 Good point.  So what we do is XOR LONGWORD with a longword,
+	 each of whose bytes is C.  This turns each byte that is C
+	 into a zero.  */
+
+      longword = *longword_ptr++ ^ charmask;
+
+      /* Add MAGIC_BITS to LONGWORD.  */
+      if ((((longword + magic_bits)
+
+	    /* Set those bits that were unchanged by the addition.  */
+	    ^ ~longword)
+
+	   /* Look at only the hole bits.  If any of the hole bits
+	      are unchanged, most likely one of the bytes was a
+	      zero.  */
+	   & ~magic_bits) != 0)
+	{
+	  /* Which of the bytes was C?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
+
+	  if (cp[0] == c)
+	    return (__ptr_t) cp;
+	  if (cp[1] == c)
+	    return (__ptr_t) &cp[1];
+	  if (cp[2] == c)
+	    return (__ptr_t) &cp[2];
+	  if (cp[3] == c)
+	    return (__ptr_t) &cp[3];
+#if LONG_MAX > 2147483647
+	  if (cp[4] == c)
+	    return (__ptr_t) &cp[4];
+	  if (cp[5] == c)
+	    return (__ptr_t) &cp[5];
+	  if (cp[6] == c)
+	    return (__ptr_t) &cp[6];
+	  if (cp[7] == c)
+	    return (__ptr_t) &cp[7];
+#endif
+	}
+
+      n -= sizeof (longword);
+    }
+
+  char_ptr = (const unsigned char *) longword_ptr;
+
+  while (n-- > 0)
+    {
+      if (*char_ptr == c)
+	return (__ptr_t) char_ptr;
+      else
+	++char_ptr;
+    }
+
+  return 0;
+}
Index: /tags/kBuild-0.1.4/src/sed/lib/memcmp.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/memcmp.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/memcmp.c	(revision 1780)
@@ -0,0 +1,396 @@
+/* Copyright (C) 1991, 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   NOTE: The canonical source of this file is maintained with the GNU C Library.
+   Bugs can be reported to bug-glibc@gnu.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, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#undef	__ptr_t
+#if defined __cplusplus || (defined __STDC__ && __STDC__)
+# define __ptr_t	void *
+#else /* Not C++ or ANSI C.  */
+# undef	const
+# define const
+# define __ptr_t	char *
+#endif /* C++ or ANSI C.  */
+
+#ifndef __P
+# if defined __GNUC__ || (defined __STDC__ && __STDC__)
+#  define __P(args) args
+# else
+#  define __P(args) ()
+# endif  /* GCC.  */
+#endif  /* Not __P.  */
+
+#if defined HAVE_STRING_H || defined _LIBC
+# include <string.h>
+#endif
+
+#undef memcmp
+
+#ifdef _LIBC
+
+# include <memcopy.h>
+# include <endian.h>
+
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN
+# endif
+
+#else	/* Not in the GNU C library.  */
+
+# include <sys/types.h>
+
+/* Type to use for aligned memory operations.
+   This should normally be the biggest type supported by a single load
+   and store.  Must be an unsigned type.  */
+# define op_t	unsigned long int
+# define OPSIZ	(sizeof(op_t))
+
+/* Threshold value for when to enter the unrolled loops.  */
+# define OP_T_THRES	16
+
+/* Type to use for unaligned operations.  */
+typedef unsigned char byte;
+
+# ifndef WORDS_BIGENDIAN
+#  define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
+# else
+#  define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2)))
+# endif
+
+#endif	/* In the GNU C library.  */
+
+#ifdef WORDS_BIGENDIAN
+# define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1)
+#else
+# define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b))
+#endif
+
+/* BE VERY CAREFUL IF YOU CHANGE THIS CODE!  */
+
+/* The strategy of this memcmp is:
+
+   1. Compare bytes until one of the block pointers is aligned.
+
+   2. Compare using memcmp_common_alignment or
+      memcmp_not_common_alignment, regarding the alignment of the other
+      block after the initial byte operations.  The maximum number of
+      full words (of type op_t) are compared in this way.
+
+   3. Compare the few remaining bytes.  */
+
+#ifndef WORDS_BIGENDIAN
+/* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine.
+   A and B are known to be different.
+   This is needed only on little-endian machines.  */
+
+static int memcmp_bytes __P((op_t, op_t));
+
+# ifdef  __GNUC__
+__inline
+# endif
+static int
+memcmp_bytes (a, b)
+     op_t a, b;
+{
+  long int srcp1 = (long int) &a;
+  long int srcp2 = (long int) &b;
+  op_t a0, b0;
+
+  do
+    {
+      a0 = ((byte *) srcp1)[0];
+      b0 = ((byte *) srcp2)[0];
+      srcp1 += 1;
+      srcp2 += 1;
+    }
+  while (a0 == b0);
+  return a0 - b0;
+}
+#endif
+
+static int memcmp_common_alignment __P((long, long, size_t));
+
+/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t'
+   objects (not LEN bytes!).  Both SRCP1 and SRCP2 should be aligned for
+   memory operations on `op_t's.  */
+#ifdef	__GNUC__
+__inline
+#endif
+static int
+memcmp_common_alignment (srcp1, srcp2, len)
+     long int srcp1;
+     long int srcp2;
+     size_t len;
+{
+  op_t a0, a1;
+  op_t b0, b1;
+
+  switch (len % 4)
+    {
+    default: /* Avoid warning about uninitialized local variables.  */
+    case 2:
+      a0 = ((op_t *) srcp1)[0];
+      b0 = ((op_t *) srcp2)[0];
+      srcp1 -= 2 * OPSIZ;
+      srcp2 -= 2 * OPSIZ;
+      len += 2;
+      goto do1;
+    case 3:
+      a1 = ((op_t *) srcp1)[0];
+      b1 = ((op_t *) srcp2)[0];
+      srcp1 -= OPSIZ;
+      srcp2 -= OPSIZ;
+      len += 1;
+      goto do2;
+    case 0:
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	return 0;
+      a0 = ((op_t *) srcp1)[0];
+      b0 = ((op_t *) srcp2)[0];
+      goto do3;
+    case 1:
+      a1 = ((op_t *) srcp1)[0];
+      b1 = ((op_t *) srcp2)[0];
+      srcp1 += OPSIZ;
+      srcp2 += OPSIZ;
+      len -= 1;
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	goto do0;
+      /* Fall through.  */
+    }
+
+  do
+    {
+      a0 = ((op_t *) srcp1)[0];
+      b0 = ((op_t *) srcp2)[0];
+      if (a1 != b1)
+	return CMP_LT_OR_GT (a1, b1);
+
+    do3:
+      a1 = ((op_t *) srcp1)[1];
+      b1 = ((op_t *) srcp2)[1];
+      if (a0 != b0)
+	return CMP_LT_OR_GT (a0, b0);
+
+    do2:
+      a0 = ((op_t *) srcp1)[2];
+      b0 = ((op_t *) srcp2)[2];
+      if (a1 != b1)
+	return CMP_LT_OR_GT (a1, b1);
+
+    do1:
+      a1 = ((op_t *) srcp1)[3];
+      b1 = ((op_t *) srcp2)[3];
+      if (a0 != b0)
+	return CMP_LT_OR_GT (a0, b0);
+
+      srcp1 += 4 * OPSIZ;
+      srcp2 += 4 * OPSIZ;
+      len -= 4;
+    }
+  while (len != 0);
+
+  /* This is the right position for do0.  Please don't move
+     it into the loop.  */
+ do0:
+  if (a1 != b1)
+    return CMP_LT_OR_GT (a1, b1);
+  return 0;
+}
+
+static int memcmp_not_common_alignment __P((long, long, size_t));
+
+/* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN
+   `op_t' objects (not LEN bytes!).  SRCP2 should be aligned for memory
+   operations on `op_t', but SRCP1 *should be unaligned*.  */
+#ifdef	__GNUC__
+__inline
+#endif
+static int
+memcmp_not_common_alignment (srcp1, srcp2, len)
+     long int srcp1;
+     long int srcp2;
+     size_t len;
+{
+  op_t a0, a1, a2, a3;
+  op_t b0, b1, b2, b3;
+  op_t x;
+  int shl, shr;
+
+  /* Calculate how to shift a word read at the memory operation
+     aligned srcp1 to make it aligned for comparison.  */
+
+  shl = 8 * (srcp1 % OPSIZ);
+  shr = 8 * OPSIZ - shl;
+
+  /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t'
+     it points in the middle of.  */
+  srcp1 &= -OPSIZ;
+
+  switch (len % 4)
+    {
+    default: /* Avoid warning about uninitialized local variables.  */
+    case 2:
+      a1 = ((op_t *) srcp1)[0];
+      a2 = ((op_t *) srcp1)[1];
+      b2 = ((op_t *) srcp2)[0];
+      srcp1 -= 1 * OPSIZ;
+      srcp2 -= 2 * OPSIZ;
+      len += 2;
+      goto do1;
+    case 3:
+      a0 = ((op_t *) srcp1)[0];
+      a1 = ((op_t *) srcp1)[1];
+      b1 = ((op_t *) srcp2)[0];
+      srcp2 -= 1 * OPSIZ;
+      len += 1;
+      goto do2;
+    case 0:
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	return 0;
+      a3 = ((op_t *) srcp1)[0];
+      a0 = ((op_t *) srcp1)[1];
+      b0 = ((op_t *) srcp2)[0];
+      srcp1 += 1 * OPSIZ;
+      goto do3;
+    case 1:
+      a2 = ((op_t *) srcp1)[0];
+      a3 = ((op_t *) srcp1)[1];
+      b3 = ((op_t *) srcp2)[0];
+      srcp1 += 2 * OPSIZ;
+      srcp2 += 1 * OPSIZ;
+      len -= 1;
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	goto do0;
+      /* Fall through.  */
+    }
+
+  do
+    {
+      a0 = ((op_t *) srcp1)[0];
+      b0 = ((op_t *) srcp2)[0];
+      x = MERGE(a2, shl, a3, shr);
+      if (x != b3)
+	return CMP_LT_OR_GT (x, b3);
+
+    do3:
+      a1 = ((op_t *) srcp1)[1];
+      b1 = ((op_t *) srcp2)[1];
+      x = MERGE(a3, shl, a0, shr);
+      if (x != b0)
+	return CMP_LT_OR_GT (x, b0);
+
+    do2:
+      a2 = ((op_t *) srcp1)[2];
+      b2 = ((op_t *) srcp2)[2];
+      x = MERGE(a0, shl, a1, shr);
+      if (x != b1)
+	return CMP_LT_OR_GT (x, b1);
+
+    do1:
+      a3 = ((op_t *) srcp1)[3];
+      b3 = ((op_t *) srcp2)[3];
+      x = MERGE(a1, shl, a2, shr);
+      if (x != b2)
+	return CMP_LT_OR_GT (x, b2);
+
+      srcp1 += 4 * OPSIZ;
+      srcp2 += 4 * OPSIZ;
+      len -= 4;
+    }
+  while (len != 0);
+
+  /* This is the right position for do0.  Please don't move
+     it into the loop.  */
+ do0:
+  x = MERGE(a2, shl, a3, shr);
+  if (x != b3)
+    return CMP_LT_OR_GT (x, b3);
+  return 0;
+}
+
+int
+memcmp (s1, s2, len)
+     const __ptr_t s1;
+     const __ptr_t s2;
+     size_t len;
+{
+  op_t a0;
+  op_t b0;
+  long int srcp1 = (long int) s1;
+  long int srcp2 = (long int) s2;
+  op_t res;
+
+  if (len >= OP_T_THRES)
+    {
+      /* There are at least some bytes to compare.  No need to test
+	 for LEN == 0 in this alignment loop.  */
+      while (srcp2 % OPSIZ != 0)
+	{
+	  a0 = ((byte *) srcp1)[0];
+	  b0 = ((byte *) srcp2)[0];
+	  srcp1 += 1;
+	  srcp2 += 1;
+	  res = a0 - b0;
+	  if (res != 0)
+	    return res;
+	  len -= 1;
+	}
+
+      /* SRCP2 is now aligned for memory operations on `op_t'.
+	 SRCP1 alignment determines if we can do a simple,
+	 aligned compare or need to shuffle bits.  */
+
+      if (srcp1 % OPSIZ == 0)
+	res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ);
+      else
+	res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ);
+      if (res != 0)
+	return res;
+
+      /* Number of bytes remaining in the interval [0..OPSIZ-1].  */
+      srcp1 += len & -OPSIZ;
+      srcp2 += len & -OPSIZ;
+      len %= OPSIZ;
+    }
+
+  /* There are just a few bytes to compare.  Use byte memory operations.  */
+  while (len != 0)
+    {
+      a0 = ((byte *) srcp1)[0];
+      b0 = ((byte *) srcp2)[0];
+      srcp1 += 1;
+      srcp2 += 1;
+      res = a0 - b0;
+      if (res != 0)
+	return res;
+      len -= 1;
+    }
+
+  return 0;
+}
+
+#ifdef weak_alias
+# undef bcmp
+weak_alias (memcmp, bcmp)
+#endif
Index: /tags/kBuild-0.1.4/src/sed/lib/memmove.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/memmove.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/memmove.c	(revision 1780)
@@ -0,0 +1,76 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* Last ditch effort to support memmove: if user doesn't have
+   memmove or bcopy, we offer this sluggish implementation. */
+
+#include "config.h"
+#ifndef HAVE_MEMMOVE
+
+#include <sys/types.h>
+#ifdef HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#ifndef VOID
+# define VOID void
+#endif
+
+VOID *
+memmove(dest, src, len)
+  VOID *dest;
+  const VOID *src;
+  size_t len;
+{
+#ifdef HAVE_BCOPY
+  bcopy(src, dest, len);
+
+#else /*!HAVE_BCOPY*/
+  char *dp = dest;
+  const char *sp = src;
+
+# ifdef HAVE_MEMCPY
+  /* A special-case for non-overlapping regions, on the assumption
+     that there is some hope that the sytem's memcpy() implementaion
+     is better than our dumb fall-back one. */
+  if ((dp < sp && dp+len < sp) || (sp < dp && sp+len < dp))
+    return memcpy(dest, src, len);
+# endif
+
+  /* I tried real hard to avoid getting to this point.
+     You *really* ought to upgrade your system's libraries;
+	 the performance of this implementation sucks. */
+  if (dp < sp)
+    {
+      while (len-- > 0)
+	*dp++ = *sp++;
+    }
+  else
+    {
+      if (dp == sp)
+	return dest;
+      dp += len;
+      sp += len;
+      while (len-- > 0)
+	*--dp = *--sp;
+    }
+#endif /*!HAVE_BCOPY*/
+
+  return dest;
+}
+
+#endif	/*!HAVE_MEMMOVE*/
Index: /tags/kBuild-0.1.4/src/sed/lib/mkstemp.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/mkstemp.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/mkstemp.c	(revision 1780)
@@ -0,0 +1,70 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#else
+# include <string.h>
+#endif /* HAVE_STRINGS_H */
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#ifdef HAVE_SYS_FILE_H
+# include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#ifdef HAVE_IO_H
+# include <io.h>
+#endif /* HAVE_IO_H */
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
+
+#include <limits.h>
+#include <errno.h>
+
+/* Generate a unique temporary file name from template.  The last six characters of
+   template must be XXXXXX and these are replaced with a string that makes the
+   filename unique. */
+
+int
+mkstemp (template)
+     char *template;
+{
+  int i, j, n, fd;
+  char *data = template + strlen(template) - 6;
+
+  if (data < template) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  for (n = 0; n <= 5; n++)
+    if (data[n] != 'X') {
+      errno = EINVAL;
+      return -1;
+    }
+
+  for (i = 0; i < INT_MAX; i++) {
+    j = i ^ 827714841;             /* Base 36 DOSSUX :-) */
+    for (n = 5; n >= 0; n--) {
+      data[n] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" [j % 36];
+      j /= 36;
+    }
+
+    fd = open (template, O_CREAT|O_EXCL|O_RDWR, 0600);
+    if (fd != -1)
+      return fd;
+  }
+    
+  errno = EEXIST;
+  return -1;
+}
Index: /tags/kBuild-0.1.4/src/sed/lib/obstack.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/obstack.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/obstack.c	(revision 1780)
@@ -0,0 +1,578 @@
+/* obstack.c - subroutines used implicitly by object stack macros -*- C -*-
+   Copyright (C) 1988,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.  Its master source is NOT part of
+   the C library, however.  The master source lives in /gd/gnu/lib.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "obstack.h"
+
+/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
+   incremented whenever callers compiled using an old obstack.h can no
+   longer properly call the functions in this obstack.c.  */
+#define OBSTACK_INTERFACE_VERSION 1
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself, and the installed library
+   supports the same library interface we do.  This code is part of the GNU
+   C Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object
+   files, it is simpler to just do this in the source for each such file.  */
+
+#include <stdio.h>		/* Random thing to get __GNU_LIBRARY__.  */
+#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
+#include <gnu-versions.h>
+#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+
+#ifndef ELIDE_CODE
+
+
+#if defined (__STDC__) && __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment.  */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT  \
+  ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+   But in fact it might be less smart and round addresses to as much as
+   DEFAULT_ROUNDING.  So we prepare for it to do that.  */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+#ifdef original_glibc_code
+/**//* When we copy a long block of data, this is the unit to do it with. */
+/**//* On some machines, copying successive ints does not work; */
+/**//* in such a case, redefine COPYING_UNIT to `long' (if that works) */
+/**//* or `char' as a last resort.  */
+/**/#ifndef COPYING_UNIT
+/**/#define COPYING_UNIT int
+/**/#endif
+#endif
+
+/* The functions allocating more room by calling `obstack_chunk_alloc'
+   jump to the handler pointed to by `obstack_alloc_failed_handler'.
+   This variable by default points to the internal function
+   `print_and_abort'.  */
+#if defined (__STDC__) && __STDC__
+static void print_and_abort (void);
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+#else
+static void print_and_abort ();
+void (*obstack_alloc_failed_handler) () = print_and_abort;
+#endif
+
+/* Exit value used when `print_and_abort' is used.  */
+#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+int obstack_exit_failure = EXIT_FAILURE;
+
+/* The non-GNU-C macros copy the obstack into this global variable
+   to avoid multiple evaluation.  */
+
+struct obstack *_obstack;
+
+/* Define a macro that either calls functions with the traditional malloc/free
+   calling interface, or calls functions with the mmalloc/mfree interface
+   (that adds an extra first argument), based on the state of use_extra_arg.
+   For free, do not use ?:, since some compilers, like the MIPS compilers,
+   do not allow (expr) ? void : void.  */
+
+#if defined (__STDC__) && __STDC__
+#define CALL_CHUNKFUN(h, size) \
+  (((h) -> use_extra_arg) \
+   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+   : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
+
+#define CALL_FREEFUN(h, old_chunk) \
+  do { \
+    if ((h) -> use_extra_arg) \
+      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+    else \
+      (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
+  } while (0)
+#else
+#define CALL_CHUNKFUN(h, size) \
+  (((h) -> use_extra_arg) \
+   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+   : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size)))
+
+#define CALL_FREEFUN(h, old_chunk) \
+  do { \
+    if ((h) -> use_extra_arg) \
+      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+    else \
+      (*(void (*) ()) (h)->freefun) ((old_chunk)); \
+  } while (0)
+#endif
+
+
+
+/* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
+   Objects start on multiples of ALIGNMENT (0 means use default).
+   CHUNKFUN is the function to use to allocate chunks,
+   and FREEFUN the function to free them.
+
+   Return nonzero if successful, zero if out of memory.
+   To recover from an out of memory error,
+   free up some memory, then call this again.  */
+
+int
+_obstack_begin (h, size, alignment, chunkfun, freefun)
+     struct obstack *h;
+     int size;
+     int alignment;
+#if defined (__STDC__) && __STDC__
+     POINTER (*chunkfun) (long);
+     void (*freefun) (void *);
+#else
+     POINTER (*chunkfun) ();
+     void (*freefun) ();
+#endif
+{
+  register struct _obstack_chunk *chunk; /* points to new chunk */
+
+  if (alignment == 0)
+    alignment = DEFAULT_ALIGNMENT;
+  if (size == 0)
+    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
+    {
+      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+	 Use the values for range checking, because if range checking is off,
+	 the extra bytes won't be missed terribly, but if range checking is on
+	 and we used a larger request, a whole extra 4096 bytes would be
+	 allocated.
+
+	 These number are irrelevant to the new GNU malloc.  I suspect it is
+	 less sensitive to the size of the request.  */
+      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+		    + 4 + DEFAULT_ROUNDING - 1)
+		   & ~(DEFAULT_ROUNDING - 1));
+      size = 4096 - extra;
+    }
+
+#if defined (__STDC__) && __STDC__
+  h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
+  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+#else
+  h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
+  h->freefun = freefun;
+#endif
+  h->chunk_size = size;
+  h->alignment_mask = alignment - 1;
+  h->use_extra_arg = 0;
+
+  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+  if (!chunk)
+    (*obstack_alloc_failed_handler) ();
+  h->next_free = h->object_base = chunk->contents;
+  h->chunk_limit = chunk->limit
+    = (char *) chunk + h->chunk_size;
+  chunk->prev = 0;
+  /* The initial chunk now contains no empty object.  */
+  h->maybe_empty_object = 0;
+  h->alloc_failed = 0;
+  return 1;
+}
+
+int
+_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
+     struct obstack *h;
+     int size;
+     int alignment;
+#if defined (__STDC__) && __STDC__
+     POINTER (*chunkfun) (POINTER, long);
+     void (*freefun) (POINTER, POINTER);
+#else
+     POINTER (*chunkfun) ();
+     void (*freefun) ();
+#endif
+     POINTER arg;
+{
+  register struct _obstack_chunk *chunk; /* points to new chunk */
+
+  if (alignment == 0)
+    alignment = DEFAULT_ALIGNMENT;
+  if (size == 0)
+    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
+    {
+      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+	 Use the values for range checking, because if range checking is off,
+	 the extra bytes won't be missed terribly, but if range checking is on
+	 and we used a larger request, a whole extra 4096 bytes would be
+	 allocated.
+
+	 These number are irrelevant to the new GNU malloc.  I suspect it is
+	 less sensitive to the size of the request.  */
+      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+		    + 4 + DEFAULT_ROUNDING - 1)
+		   & ~(DEFAULT_ROUNDING - 1));
+      size = 4096 - extra;
+    }
+
+#if defined(__STDC__) && __STDC__
+  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+#else
+  h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
+  h->freefun = freefun;
+#endif
+  h->chunk_size = size;
+  h->alignment_mask = alignment - 1;
+  h->extra_arg = arg;
+  h->use_extra_arg = 1;
+
+  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+  if (!chunk)
+    (*obstack_alloc_failed_handler) ();
+  h->next_free = h->object_base = chunk->contents;
+  h->chunk_limit = chunk->limit
+    = (char *) chunk + h->chunk_size;
+  chunk->prev = 0;
+  /* The initial chunk now contains no empty object.  */
+  h->maybe_empty_object = 0;
+  h->alloc_failed = 0;
+  return 1;
+}
+
+/* Allocate a new current chunk for the obstack *H
+   on the assumption that LENGTH bytes need to be added
+   to the current object, or a new object of length LENGTH allocated.
+   Copies any partial object from the end of the old chunk
+   to the beginning of the new one.  */
+
+void
+_obstack_newchunk (h, length)
+     struct obstack *h;
+     int length;
+{
+  register struct _obstack_chunk *old_chunk = h->chunk;
+  register struct _obstack_chunk *new_chunk;
+  register long	new_size;
+  register int obj_size = h->next_free - h->object_base;
+
+  /* Compute size for new chunk.  */
+  new_size = (obj_size + length) + (obj_size >> 3) + 100;
+  if (new_size < h->chunk_size)
+    new_size = h->chunk_size;
+
+  /* Allocate and initialize the new chunk.  */
+  new_chunk = CALL_CHUNKFUN (h, new_size);
+  if (!new_chunk)
+    (*obstack_alloc_failed_handler) ();
+  h->chunk = new_chunk;
+  new_chunk->prev = old_chunk;
+  new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+  _obstack_memcpy(new_chunk->contents, h->object_base, obj_size);
+
+  /* If the object just copied was the only data in OLD_CHUNK, */
+  /* free that chunk and remove it from the chain. */
+  /* But not if that chunk might contain an empty object.  */
+  if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
+    {
+      new_chunk->prev = old_chunk->prev;
+      CALL_FREEFUN (h, old_chunk);
+    }
+
+  h->object_base = new_chunk->contents;
+  h->next_free = h->object_base + obj_size;
+  /* The new chunk certainly contains no empty object yet.  */
+  h->maybe_empty_object = 0;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+   This is here for debugging.
+   If you use it in a program, you are probably losing.  */
+
+#if defined (__STDC__) && __STDC__
+/* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
+   obstack.h because it is just for debugging.  */
+int _obstack_allocated_p (struct obstack *h, POINTER obj);
+#endif
+
+int
+_obstack_allocated_p (h, obj)
+     struct obstack *h;
+     POINTER obj;
+{
+  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
+
+  lp = (h)->chunk;
+  /* We use >= rather than > since the object cannot be exactly at
+     the beginning of the chunk but might be an empty object exactly
+     at the end of an adjacent chunk.  */
+  while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
+    {
+      plp = lp->prev;
+      lp = plp;
+    }
+  return lp != 0;
+}
+
+
+/* Free objects in obstack H, including OBJ and everything allocate
+   more recently than OBJ.  If OBJ is zero, free everything in H.  */
+
+#undef obstack_free
+
+/* This function has two names with identical definitions.
+   This is the first one, called from non-ANSI code.  */
+
+void
+_obstack_free (h, obj)
+     struct obstack *h;
+     POINTER obj;
+{
+  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
+
+  lp = h->chunk;
+  /* We use >= because there cannot be an object at the beginning of a chunk.
+     But there can be an empty object at that address
+     at the end of another chunk.  */
+  while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
+    {
+      plp = lp->prev;
+      CALL_FREEFUN (h, lp);
+      lp = plp;
+      /* If we switch chunks, we can't tell whether the new current
+	 chunk contains an empty object, so assume that it may.  */
+      h->maybe_empty_object = 1;
+    }
+  if (lp)
+    {
+      h->object_base = h->next_free = (char *) (obj);
+      h->chunk_limit = lp->limit;
+      h->chunk = lp;
+    }
+  else if (obj != 0)
+    /* obj is not in any of the chunks! */
+    abort ();
+}
+
+/* This function is used from ANSI code.  */
+
+void
+obstack_free (h, obj)
+     struct obstack *h;
+     POINTER obj;
+{
+  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
+
+  lp = h->chunk;
+  /* We use >= because there cannot be an object at the beginning of a chunk.
+     But there can be an empty object at that address
+     at the end of another chunk.  */
+  while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
+    {
+      plp = lp->prev;
+      CALL_FREEFUN (h, lp);
+      lp = plp;
+      /* If we switch chunks, we can't tell whether the new current
+	 chunk contains an empty object, so assume that it may.  */
+      h->maybe_empty_object = 1;
+    }
+  if (lp)
+    {
+      h->object_base = h->next_free = (char *) (obj);
+      h->chunk_limit = lp->limit;
+      h->chunk = lp;
+    }
+  else if (obj != 0)
+    /* obj is not in any of the chunks! */
+    abort ();
+}
+
+
+int
+_obstack_memory_used (h)
+     struct obstack *h;
+{
+  register struct _obstack_chunk* lp;
+  register int nbytes = 0;
+
+  for (lp = h->chunk; lp != 0; lp = lp->prev)
+    {
+      nbytes += lp->limit - (char *) lp;
+    }
+  return nbytes;
+}
+
+
+/* Define the error handler.  */
+#ifndef _
+# ifdef HAVE_LIBINTL_H
+#  include <libintl.h>
+#  ifndef _
+#   define _(Str) gettext (Str)
+#  endif
+# else
+#  define _(Str) (Str)
+# endif
+#endif
+
+static void
+print_and_abort ()
+{
+  fputs (_("memory exhausted\n"), stderr);
+  exit (obstack_exit_failure);
+}
+
+
+#if 0
+/* These are now turned off because the applications do not use it
+   and it uses bcopy via obstack_grow, which causes trouble on sysV.  */
+
+/* Now define the functional versions of the obstack macros.
+   Define them to simply use the corresponding macros to do the job.  */
+
+#if defined (__STDC__) && __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+   they won't pass through the macro names in parentheses.  */
+
+/* The function names appear in parentheses in order to prevent
+   the macro-definitions of the names from being expanded there.  */
+
+POINTER (obstack_base) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_room (obstack);
+}
+
+int (obstack_make_room) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  return obstack_make_room (obstack, length);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+     struct obstack *obstack;
+     int character;
+{
+  obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+     struct obstack *obstack;
+     int character;
+{
+  obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+     struct obstack *obstack;
+{
+  return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+     struct obstack *obstack;
+     int length;
+{
+  return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+     struct obstack *obstack;
+     POINTER pointer;
+     int length;
+{
+  return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+#endif /* 0 */
+
+#endif	/* !ELIDE_CODE */
Index: /tags/kBuild-0.1.4/src/sed/lib/obstack.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/obstack.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/obstack.h	(revision 1780)
@@ -0,0 +1,614 @@
+/* obstack.h - object stack macros
+   Copyright (C) 1988,89,90,91,92,93,94,96,97,98,99 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.  Its master source is NOT part of
+   the C library, however.  The master source lives in /gd/gnu/lib.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects.  Each object starts life
+small, and may grow to maturity.  (Consider building a word syllable
+by syllable.)  An object can move while it is growing.  Once it has
+been "finished" it never changes address again.  So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'.  On occasion, they free chunks,
+by calling `obstack_chunk_free'.  You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables.  Unless you are "fascist pig with a read-only mind"
+--Gosper's immortal quote from HAKMEM item 154, out of context--you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols.  At the time you are reading a symbol you don't know
+how long it is.  One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer.  This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently.  Use one obstack for all symbol
+names.  As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it.  Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses.  When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk.  When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies.  No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk.  We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object.  This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+	We allocate large chunks.
+	We carve out one object at a time from the current chunk.
+	Once carved, an object never moves.
+	We are free to append data of any size to the currently
+	  growing object.
+	Exactly one object is growing in an obstack at any one time.
+	You can run one obstack per control block.
+	You may have as many control blocks as you dare.
+	Because of the way we do it, you can `unwind' an obstack
+	  back to a previous state. (You may remove objects much
+	  as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once.  */
+
+#ifndef _OBSTACK_H
+#define _OBSTACK_H 1
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* We use subtraction of (char *) 0 instead of casting to int
+   because on word-addressable machines a simple cast to int
+   may ignore the byte-within-word field of the pointer.  */
+
+#ifndef __PTR_TO_INT
+# define __PTR_TO_INT(P) ((P) - (char *) 0)
+#endif
+
+#ifndef __INT_TO_PTR
+# define __INT_TO_PTR(P) ((P) + (char *) 0)
+#endif
+
+/* We need the type of the resulting object.  If __PTRDIFF_TYPE__ is
+   defined, as with GNU C, use that; that way we don't pollute the
+   namespace with <stddef.h>'s symbols.  Otherwise, if <stddef.h> is
+   available, include it and use ptrdiff_t.  In traditional C, long is
+   the best that we can do.  */
+
+#ifdef __PTRDIFF_TYPE__
+# define PTR_INT_TYPE __PTRDIFF_TYPE__
+#else
+# ifdef HAVE_STDDEF_H
+#  include <stddef.h>
+#  define PTR_INT_TYPE ptrdiff_t
+# else
+#  define PTR_INT_TYPE long
+# endif
+#endif
+
+#if defined _LIBC || defined HAVE_STRING_H
+# include <string.h>
+# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
+#else
+# ifdef memcpy
+#  define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
+# else
+#  define _obstack_memcpy(To, From, N) bcopy ((From), (To), (N))
+# endif
+#endif
+
+struct _obstack_chunk		/* Lives at front of each chunk. */
+{
+  char  *limit;			/* 1 past end of this chunk */
+  struct _obstack_chunk *prev;	/* address of prior chunk or NULL */
+  char	contents[4];		/* objects begin here */
+};
+
+struct obstack		/* control current object in current chunk */
+{
+  long	chunk_size;		/* preferred size to allocate chunks in */
+  struct _obstack_chunk *chunk;	/* address of current struct obstack_chunk */
+  char	*object_base;		/* address of object we are building */
+  char	*next_free;		/* where to add next char to current object */
+  char	*chunk_limit;		/* address of char after current chunk */
+  PTR_INT_TYPE temp;		/* Temporary for some macros.  */
+  int   alignment_mask;		/* Mask of alignment for each object. */
+#if defined __STDC__ && __STDC__
+  /* These prototypes vary based on `use_extra_arg', and we use
+     casts to the prototypeless function type in all assignments,
+     but having prototypes here quiets -Wstrict-prototypes.  */
+  struct _obstack_chunk *(*chunkfun) (void *, long);
+  void (*freefun) (void *, struct _obstack_chunk *);
+  void *extra_arg;		/* first arg for chunk alloc/dealloc funcs */
+#else
+  struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk.  */
+  void (*freefun) ();		/* User's function to free a chunk.  */
+  char *extra_arg;		/* first arg for chunk alloc/dealloc funcs */
+#endif
+  unsigned use_extra_arg:1;	/* chunk alloc/dealloc funcs take extra arg */
+  unsigned maybe_empty_object:1;/* There is a possibility that the current
+				   chunk contains a zero-length object.  This
+				   prevents freeing the chunk if we allocate
+				   a bigger chunk to replace it. */
+  unsigned alloc_failed:1;	/* No longer used, as we now call the failed
+				   handler on error, but retained for binary
+				   compatibility.  */
+};
+
+/* Declare the external functions we use; they are in obstack.c.  */
+
+#if defined __STDC__ && __STDC__
+extern void _obstack_newchunk (struct obstack *, int);
+extern void _obstack_free (struct obstack *, void *);
+extern int _obstack_begin (struct obstack *, int, int,
+			    void *(*) (long), void (*) (void *));
+extern int _obstack_begin_1 (struct obstack *, int, int,
+			     void *(*) (void *, long),
+			     void (*) (void *, void *), void *);
+extern int _obstack_memory_used (struct obstack *);
+#else
+extern void _obstack_newchunk ();
+extern void _obstack_free ();
+extern int _obstack_begin ();
+extern int _obstack_begin_1 ();
+extern int _obstack_memory_used ();
+#endif
+
+
+#if defined __STDC__ && __STDC__
+
+/* Do the function-declarations after the structs
+   but before defining the macros.  */
+
+void obstack_init (struct obstack *obstack);
+
+void * obstack_alloc (struct obstack *obstack, int size);
+
+void * obstack_copy (struct obstack *obstack, const void *address, int size);
+void * obstack_copy0 (struct obstack *obstack, const void *address, int size);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+void obstack_blank (struct obstack *obstack, int size);
+
+void obstack_grow (struct obstack *obstack, const void *data, int size);
+void obstack_grow0 (struct obstack *obstack, const void *data, int size);
+
+void obstack_1grow (struct obstack *obstack, int data_char);
+void obstack_ptr_grow (struct obstack *obstack, const void *data);
+void obstack_int_grow (struct obstack *obstack, int data);
+
+void * obstack_finish (struct obstack *obstack);
+
+int obstack_object_size (struct obstack *obstack);
+
+int obstack_room (struct obstack *obstack);
+void obstack_make_room (struct obstack *obstack, int size);
+void obstack_1grow_fast (struct obstack *obstack, int data_char);
+void obstack_ptr_grow_fast (struct obstack *obstack, const void *data);
+void obstack_int_grow_fast (struct obstack *obstack, int data);
+void obstack_blank_fast (struct obstack *obstack, int size);
+
+void * obstack_base (struct obstack *obstack);
+void * obstack_next_free (struct obstack *obstack);
+int obstack_alignment_mask (struct obstack *obstack);
+int obstack_chunk_size (struct obstack *obstack);
+int obstack_memory_used (struct obstack *obstack);
+
+#endif /* __STDC__ */
+
+/* Non-ANSI C cannot really support alternative functions for these macros,
+   so we do not declare them.  */
+
+/* Error handler called when `obstack_chunk_alloc' failed to allocate
+   more memory.  This can be set to a user defined function which
+   should either abort gracefully or use longjump - but shouldn't
+   return.  The default action is to print a message and abort.  */
+#if defined __STDC__ && __STDC__
+extern void (*obstack_alloc_failed_handler) (void);
+#else
+extern void (*obstack_alloc_failed_handler) ();
+#endif
+
+/* Exit value used when `print_and_abort' is used.  */
+extern int obstack_exit_failure;
+
+
+/* Pointer to beginning of object being allocated or to be allocated next.
+   Note that this might not be the final address of the object
+   because a new chunk might be needed to hold the final size.  */
+
+#define obstack_base(h) ((h)->object_base)
+
+/* Size for allocating ordinary chunks.  */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk.  */
+
+#define obstack_next_free(h)	((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object.  */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+/* To prevent prototype warnings provide complete argument list in
+   standard C version.  */
+#if defined __STDC__ && __STDC__
+
+# define obstack_init(h)					\
+  _obstack_begin ((h), 0, 0,					\
+		  (void *(*) (long)) obstack_chunk_alloc, 	\
+		  (void (*) (void *)) obstack_chunk_free)
+
+# define obstack_begin(h, size)					\
+  _obstack_begin ((h), (size), 0,				\
+		  (void *(*) (long)) obstack_chunk_alloc, 	\
+		  (void (*) (void *)) obstack_chunk_free)
+
+# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+  _obstack_begin ((h), (size), (alignment),				   \
+		  (void *(*) (long)) (chunkfun), 			   \
+		  (void (*) (void *)) (freefun))
+
+# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+  _obstack_begin_1 ((h), (size), (alignment),				\
+		    (void *(*) (void *, long)) (chunkfun),		\
+		    (void (*) (void *, void *)) (freefun), (arg))
+
+# define obstack_chunkfun(h, newchunkfun) \
+  ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
+
+# define obstack_freefun(h, newfreefun) \
+  ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
+
+#else
+
+# define obstack_init(h)						\
+  _obstack_begin ((h), 0, 0,						\
+		  (void *(*) ()) obstack_chunk_alloc, 			\
+		  (void (*) ()) obstack_chunk_free)
+
+# define obstack_begin(h, size)						\
+  _obstack_begin ((h), (size), 0,					\
+		  (void *(*) ()) obstack_chunk_alloc,			\
+		  (void (*) ()) obstack_chunk_free)
+
+# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+  _obstack_begin ((h), (size), (alignment),				   \
+		  (void *(*) ()) (chunkfun), 				   \
+		  (void (*) ()) (freefun))
+
+# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+  _obstack_begin_1 ((h), (size), (alignment),				\
+		    (void *(*) ()) (chunkfun), 				\
+		    (void (*) ()) (freefun), (arg))
+
+# define obstack_chunkfun(h, newchunkfun) \
+  ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun))
+
+# define obstack_freefun(h, newfreefun) \
+  ((h) -> freefun = (void (*)()) (newfreefun))
+
+#endif
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#define obstack_memory_used(h) _obstack_memory_used (h)
+
+
+#if defined __GNUC__ && defined __STDC__ && __STDC__
+/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
+   does not implement __extension__.  But that compiler doesn't define
+   __GNUC_MINOR__.  */
+# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
+#  define __extension__
+# endif
+
+/* For GNU C, if not -traditional,
+   we can define these macros to compute all args only once
+   without using a global variable.
+   Also, we can avoid using the `temp' slot, to make faster code.  */
+
+# define obstack_object_size(OBSTACK)					\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     (unsigned) (__o->next_free - __o->object_base); })
+
+# define obstack_room(OBSTACK)						\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     (unsigned) (__o->chunk_limit - __o->next_free); })
+
+# define obstack_make_room(OBSTACK,length)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   int __len = (length);						\
+   if (__o->chunk_limit - __o->next_free < __len)			\
+     _obstack_newchunk (__o, __len);					\
+   (void) 0; })
+
+# define obstack_empty_p(OBSTACK)					\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
+
+# define obstack_grow(OBSTACK,where,length)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   int __len = (length);						\
+   if (__o->next_free + __len > __o->chunk_limit)			\
+     _obstack_newchunk (__o, __len);					\
+   _obstack_memcpy (__o->next_free, (where), __len);			\
+   __o->next_free += __len;						\
+   (void) 0; })
+
+# define obstack_grow0(OBSTACK,where,length)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   int __len = (length);						\
+   if (__o->next_free + __len + 1 > __o->chunk_limit)			\
+     _obstack_newchunk (__o, __len + 1);				\
+   _obstack_memcpy (__o->next_free, (where), __len);			\
+   __o->next_free += __len;						\
+   *(__o->next_free)++ = 0;						\
+   (void) 0; })
+
+# define obstack_1grow(OBSTACK,datum)					\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   if (__o->next_free + 1 > __o->chunk_limit)				\
+     _obstack_newchunk (__o, 1);					\
+   *(__o->next_free)++ = (datum);					\
+   (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers
+   or ints, and that the data added so far to the current object
+   shares that much alignment.  */
+
+# define obstack_ptr_grow(OBSTACK,datum)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   if (__o->next_free + sizeof (void *) > __o->chunk_limit)		\
+     _obstack_newchunk (__o, sizeof (void *));				\
+   ((*((void **)__o->next_free) = (datum)), (__o->next_free += sizeof (void *)));				\
+   (void) 0; })
+
+# define obstack_int_grow(OBSTACK,datum)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   if (__o->next_free + sizeof (int) > __o->chunk_limit)		\
+     _obstack_newchunk (__o, sizeof (int));				\
+   ((*((int *)__o->next_free) = (datum)), (__o->next_free += sizeof (int )));				\
+   (void) 0; })
+
+# define obstack_ptr_grow_fast(h,aptr)					\
+  (((*((void **) (h)->next_free) = (aptr)), ( (h)->next_free += sizeof (void *))))
+
+# define obstack_int_grow_fast(h,aint)					\
+  (((*((int *) (h)->next_free) = (aint)), ( (h)->next_free += sizeof (int ))))
+
+# define obstack_blank(OBSTACK,length)					\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   int __len = (length);						\
+   if (__o->chunk_limit - __o->next_free < __len)			\
+     _obstack_newchunk (__o, __len);					\
+   __o->next_free += __len;						\
+   (void) 0; })
+
+# define obstack_alloc(OBSTACK,length)					\
+__extension__								\
+({ struct obstack *__h = (OBSTACK);					\
+   obstack_blank (__h, (length));					\
+   obstack_finish (__h); })
+
+# define obstack_copy(OBSTACK,where,length)				\
+__extension__								\
+({ struct obstack *__h = (OBSTACK);					\
+   obstack_grow (__h, (where), (length));				\
+   obstack_finish (__h); })
+
+# define obstack_copy0(OBSTACK,where,length)				\
+__extension__								\
+({ struct obstack *__h = (OBSTACK);					\
+   obstack_grow0 (__h, (where), (length));				\
+   obstack_finish (__h); })
+
+/* The local variable is named __o1 to avoid a name conflict
+   when obstack_blank is called.  */
+# define obstack_finish(OBSTACK)  					\
+__extension__								\
+({ struct obstack *__o1 = (OBSTACK);					\
+   void *value;								\
+   value = (void *) __o1->object_base;					\
+   if (__o1->next_free == value)					\
+     __o1->maybe_empty_object = 1;					\
+   __o1->next_free							\
+     = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
+		     & ~ (__o1->alignment_mask));			\
+   if (__o1->next_free - (char *)__o1->chunk				\
+       > __o1->chunk_limit - (char *)__o1->chunk)			\
+     __o1->next_free = __o1->chunk_limit;				\
+   __o1->object_base = __o1->next_free;					\
+   value; })
+
+# define obstack_free(OBSTACK, OBJ)					\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   void *__obj = (OBJ);							\
+   if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit)  \
+     __o->next_free = __o->object_base = (char *)__obj;			\
+   else (obstack_free) (__o, __obj); })
+
+
+#else /* not __GNUC__ or not __STDC__ */
+
+# define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+# define obstack_room(h)		\
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+# define obstack_empty_p(h) \
+ ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
+
+/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
+   so that we can avoid having void expressions
+   in the arms of the conditional expression.
+   Casting the third operand to void was tried before,
+   but some compilers won't accept it.  */
+
+# define obstack_make_room(h,length)					\
+( (h)->temp = (length),							\
+  (((h)->next_free + (h)->temp > (h)->chunk_limit)			\
+   ? (_obstack_newchunk ((h), (h)->temp), 0) : 0))
+
+# define obstack_grow(h,where,length)					\
+( (h)->temp = (length),							\
+  (((h)->next_free + (h)->temp > (h)->chunk_limit)			\
+   ? (_obstack_newchunk ((h), (h)->temp), 0) : 0),			\
+  _obstack_memcpy ((h)->next_free, (where), (h)->temp),			\
+  (h)->next_free += (h)->temp)
+
+# define obstack_grow0(h,where,length)					\
+( (h)->temp = (length),							\
+  (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit)			\
+   ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0),			\
+  _obstack_memcpy ((h)->next_free, (where), (h)->temp),			\
+  (h)->next_free += (h)->temp,						\
+  *((h)->next_free)++ = 0)
+
+# define obstack_1grow(h,datum)						\
+( (((h)->next_free + 1 > (h)->chunk_limit)				\
+   ? (_obstack_newchunk ((h), 1), 0) : 0),				\
+  (*((h)->next_free)++ = (datum)))
+
+# define obstack_ptr_grow(h,datum)					\
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit)		\
+   ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0),		\
+  (*((const char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = (datum)))
+
+# define obstack_int_grow(h,datum)					\
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit)			\
+   ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0),			\
+  (*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = (datum)))
+
+# define obstack_ptr_grow_fast(h,aptr)					\
+  (((*((const char **) (h)->next_free) = (aptr)), ( (h)->next_free += sizeof (const char *))))
+
+# define obstack_int_grow_fast(h,aint)					\
+  (((*((int *) (h)->next_free) = (aint)), ( (h)->next_free += sizeof (int ))))
+
+# define obstack_blank(h,length)					\
+( (h)->temp = (length),							\
+  (((h)->chunk_limit - (h)->next_free < (h)->temp)			\
+   ? (_obstack_newchunk ((h), (h)->temp), 0) : 0),			\
+  ((h)->next_free += (h)->temp))
+
+# define obstack_alloc(h,length)					\
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+# define obstack_copy(h,where,length)					\
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_copy0(h,where,length)					\
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_finish(h)  						\
+( ((h)->next_free == (h)->object_base					\
+   ? (((h)->maybe_empty_object = 1), 0)					\
+   : 0),								\
+  (h)->temp = __PTR_TO_INT ((h)->object_base),				\
+  (h)->next_free							\
+    = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask)	\
+		    & ~ ((h)->alignment_mask)),				\
+  (((h)->next_free - (char *) (h)->chunk				\
+    > (h)->chunk_limit - (char *) (h)->chunk)				\
+   ? ((h)->next_free = (h)->chunk_limit) : 0),				\
+  (h)->object_base = (h)->next_free,					\
+  __INT_TO_PTR ((h)->temp))
+
+# if defined __STDC__ && __STDC__
+#  define obstack_free(h,obj)						\
+( (h)->temp = (char *) (obj) - (char *) (h)->chunk,			\
+  (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+   ? (int) ((h)->next_free = (h)->object_base				\
+	    = (h)->temp + (char *) (h)->chunk)				\
+   : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
+# else
+#  define obstack_free(h,obj)						\
+( (h)->temp = (char *) (obj) - (char *) (h)->chunk,			\
+  (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+   ? (int) ((h)->next_free = (h)->object_base				\
+	    = (h)->temp + (char *) (h)->chunk)				\
+   : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0)))
+# endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+#ifdef __cplusplus
+}	/* C++ */
+#endif
+
+#endif /* obstack.h */
Index: /tags/kBuild-0.1.4/src/sed/lib/regcomp.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/regcomp.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/regcomp.c	(revision 1780)
@@ -0,0 +1,3817 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   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.  */
+
+static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
+					  size_t length, reg_syntax_t syntax);
+static void re_compile_fastmap_iter (regex_t *bufp,
+				     const re_dfastate_t *init_state,
+				     char *fastmap);
+static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);
+#ifdef RE_ENABLE_I18N
+static void free_charset (re_charset_t *cset);
+#endif /* RE_ENABLE_I18N */
+static void free_workarea_compile (regex_t *preg);
+static reg_errcode_t create_initial_state (re_dfa_t *dfa);
+#ifdef RE_ENABLE_I18N
+static void optimize_utf8 (re_dfa_t *dfa);
+#endif
+static reg_errcode_t analyze (regex_t *preg);
+static reg_errcode_t preorder (bin_tree_t *root,
+			       reg_errcode_t (fn (void *, bin_tree_t *)),
+			       void *extra);
+static reg_errcode_t postorder (bin_tree_t *root,
+				reg_errcode_t (fn (void *, bin_tree_t *)),
+				void *extra);
+static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
+static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
+static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
+				 bin_tree_t *node);
+static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
+static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
+static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
+static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint);
+static int search_duplicated_node (const re_dfa_t *dfa, int org_node,
+				   unsigned int constraint);
+static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
+static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
+					 int node, int root);
+static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
+static int fetch_number (re_string_t *input, re_token_t *token,
+			 reg_syntax_t syntax);
+static int peek_token (re_token_t *token, re_string_t *input,
+			reg_syntax_t syntax) internal_function;
+static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
+			  reg_syntax_t syntax, reg_errcode_t *err);
+static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
+				  re_token_t *token, reg_syntax_t syntax,
+				  int nest, reg_errcode_t *err);
+static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
+				 re_token_t *token, reg_syntax_t syntax,
+				 int nest, reg_errcode_t *err);
+static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
+				     re_token_t *token, reg_syntax_t syntax,
+				     int nest, reg_errcode_t *err);
+static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
+				  re_token_t *token, reg_syntax_t syntax,
+				  int nest, reg_errcode_t *err);
+static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
+				 re_dfa_t *dfa, re_token_t *token,
+				 reg_syntax_t syntax, reg_errcode_t *err);
+static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
+				      re_token_t *token, reg_syntax_t syntax,
+				      reg_errcode_t *err);
+static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
+					    re_string_t *regexp,
+					    re_token_t *token, int token_len,
+					    re_dfa_t *dfa,
+					    reg_syntax_t syntax,
+					    int accept_hyphen);
+static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
+					  re_string_t *regexp,
+					  re_token_t *token);
+#ifdef RE_ENABLE_I18N
+static reg_errcode_t build_equiv_class (bitset_t sbcset,
+					re_charset_t *mbcset,
+					int *equiv_class_alloc,
+					const unsigned char *name);
+static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
+				      bitset_t sbcset,
+				      re_charset_t *mbcset,
+				      int *char_class_alloc,
+				      const unsigned char *class_name,
+				      reg_syntax_t syntax);
+#else  /* not RE_ENABLE_I18N */
+static reg_errcode_t build_equiv_class (bitset_t sbcset,
+					const unsigned char *name);
+static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
+				      bitset_t sbcset,
+				      const unsigned char *class_name,
+				      reg_syntax_t syntax);
+#endif /* not RE_ENABLE_I18N */
+static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
+				       RE_TRANSLATE_TYPE trans,
+				       const unsigned char *class_name,
+				       const unsigned char *extra,
+				       int non_match, reg_errcode_t *err);
+static bin_tree_t *create_tree (re_dfa_t *dfa,
+				bin_tree_t *left, bin_tree_t *right,
+				re_token_type_t type);
+static bin_tree_t *create_token_tree (re_dfa_t *dfa,
+				      bin_tree_t *left, bin_tree_t *right,
+				      const re_token_t *token);
+static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
+static void free_token (re_token_t *node);
+static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
+static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
+
+
+/* This table gives an error message for each of the error codes listed
+   in regex.h.  Obviously the order here has to be same as there.
+   POSIX doesn't require that we do anything for REG_NOERROR,
+   but why not be nice?  */
+
+const char __re_error_msgid[] attribute_hidden =
+  {
+#define REG_NOERROR_IDX	0
+    gettext_noop ("Success")	/* REG_NOERROR */
+    "\0"
+#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
+    gettext_noop ("No match")	/* REG_NOMATCH */
+    "\0"
+#define REG_BADPAT_IDX	(REG_NOMATCH_IDX + sizeof "No match")
+    gettext_noop ("Invalid regular expression") /* REG_BADPAT */
+    "\0"
+#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
+    gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
+    "\0"
+#define REG_ECTYPE_IDX	(REG_ECOLLATE_IDX + sizeof "Invalid collation character")
+    gettext_noop ("Invalid character class name") /* REG_ECTYPE */
+    "\0"
+#define REG_EESCAPE_IDX	(REG_ECTYPE_IDX + sizeof "Invalid character class name")
+    gettext_noop ("Trailing backslash") /* REG_EESCAPE */
+    "\0"
+#define REG_ESUBREG_IDX	(REG_EESCAPE_IDX + sizeof "Trailing backslash")
+    gettext_noop ("Invalid back reference") /* REG_ESUBREG */
+    "\0"
+#define REG_EBRACK_IDX	(REG_ESUBREG_IDX + sizeof "Invalid back reference")
+    gettext_noop ("Unmatched [ or [^")	/* REG_EBRACK */
+    "\0"
+#define REG_EPAREN_IDX	(REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
+    gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
+    "\0"
+#define REG_EBRACE_IDX	(REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
+    gettext_noop ("Unmatched \\{") /* REG_EBRACE */
+    "\0"
+#define REG_BADBR_IDX	(REG_EBRACE_IDX + sizeof "Unmatched \\{")
+    gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
+    "\0"
+#define REG_ERANGE_IDX	(REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
+    gettext_noop ("Invalid range end")	/* REG_ERANGE */
+    "\0"
+#define REG_ESPACE_IDX	(REG_ERANGE_IDX + sizeof "Invalid range end")
+    gettext_noop ("Memory exhausted") /* REG_ESPACE */
+    "\0"
+#define REG_BADRPT_IDX	(REG_ESPACE_IDX + sizeof "Memory exhausted")
+    gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
+    "\0"
+#define REG_EEND_IDX	(REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
+    gettext_noop ("Premature end of regular expression") /* REG_EEND */
+    "\0"
+#define REG_ESIZE_IDX	(REG_EEND_IDX + sizeof "Premature end of regular expression")
+    gettext_noop ("Regular expression too big") /* REG_ESIZE */
+    "\0"
+#define REG_ERPAREN_IDX	(REG_ESIZE_IDX + sizeof "Regular expression too big")
+    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
+  };
+
+const size_t __re_error_msgid_idx[] attribute_hidden =
+  {
+    REG_NOERROR_IDX,
+    REG_NOMATCH_IDX,
+    REG_BADPAT_IDX,
+    REG_ECOLLATE_IDX,
+    REG_ECTYPE_IDX,
+    REG_EESCAPE_IDX,
+    REG_ESUBREG_IDX,
+    REG_EBRACK_IDX,
+    REG_EPAREN_IDX,
+    REG_EBRACE_IDX,
+    REG_BADBR_IDX,
+    REG_ERANGE_IDX,
+    REG_ESPACE_IDX,
+    REG_BADRPT_IDX,
+    REG_EEND_IDX,
+    REG_ESIZE_IDX,
+    REG_ERPAREN_IDX
+  };
+
+
+/* Entry points for GNU code.  */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+   compiles PATTERN (of length LENGTH) and puts the result in BUFP.
+   Returns 0 if the pattern was valid, otherwise an error string.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+   are set in BUFP on entry.  */
+
+const char *
+re_compile_pattern (pattern, length, bufp)
+    const char *pattern;
+    size_t length;
+    struct re_pattern_buffer *bufp;
+{
+  reg_errcode_t ret;
+
+  /* And GNU code determines whether or not to get register information
+     by passing null for the REGS argument to re_match, etc., not by
+     setting no_sub, unless RE_NO_SUB is set.  */
+  bufp->no_sub = !!(re_syntax_options & RE_NO_SUB);
+
+  /* Match anchors at newline.  */
+  bufp->newline_anchor = 1;
+
+  ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
+
+  if (!ret)
+    return NULL;
+  return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
+}
+#ifdef _LIBC
+weak_alias (__re_compile_pattern, re_compile_pattern)
+#endif
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
+   also be assigned to arbitrarily: each pattern buffer stores its own
+   syntax, so it can be changed between regex compilations.  */
+/* This has no initializer because initialized variables in Emacs
+   become read-only after dumping.  */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation.  This provides
+   for compatibility for various utilities which historically have
+   different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit mask comprised of the various bits
+   defined in regex.h.  We return the old syntax.  */
+
+reg_syntax_t
+re_set_syntax (syntax)
+    reg_syntax_t syntax;
+{
+  reg_syntax_t ret = re_syntax_options;
+
+  re_syntax_options = syntax;
+  return ret;
+}
+#ifdef _LIBC
+weak_alias (__re_set_syntax, re_set_syntax)
+#endif
+
+int
+re_compile_fastmap (bufp)
+    struct re_pattern_buffer *bufp;
+{
+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+  char *fastmap = bufp->fastmap;
+
+  memset (fastmap, '\0', sizeof (char) * SBC_MAX);
+  re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
+  if (dfa->init_state != dfa->init_state_word)
+    re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
+  if (dfa->init_state != dfa->init_state_nl)
+    re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
+  if (dfa->init_state != dfa->init_state_begbuf)
+    re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
+  bufp->fastmap_accurate = 1;
+  return 0;
+}
+#ifdef _LIBC
+weak_alias (__re_compile_fastmap, re_compile_fastmap)
+#endif
+
+static inline void
+__attribute ((always_inline))
+re_set_fastmap (char *fastmap, int icase, int ch)
+{
+  fastmap[ch] = 1;
+  if (icase)
+    fastmap[tolower (ch)] = 1;
+}
+
+/* Helper function for re_compile_fastmap.
+   Compile fastmap for the initial_state INIT_STATE.  */
+
+static void
+re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
+			 char *fastmap)
+{
+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+  int node_cnt;
+  int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
+  for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
+    {
+      int node = init_state->nodes.elems[node_cnt];
+      re_token_type_t type = dfa->nodes[node].type;
+
+      if (type == CHARACTER)
+	{
+	  re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
+#ifdef RE_ENABLE_I18N
+	  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+	    {
+	      unsigned char *buf = alloca (dfa->mb_cur_max), *p;
+	      wchar_t wc;
+	      mbstate_t state;
+
+	      p = buf;
+	      *p++ = dfa->nodes[node].opr.c;
+	      while (++node < dfa->nodes_len
+		     &&	dfa->nodes[node].type == CHARACTER
+		     && dfa->nodes[node].mb_partial)
+		*p++ = dfa->nodes[node].opr.c;
+	      memset (&state, '\0', sizeof (state));
+	      if (mbrtowc (&wc, (const char *) buf, p - buf,
+			   &state) == p - buf
+		  && (__wcrtomb ((char *) buf, towlower (wc), &state)
+		      != (size_t) -1))
+		re_set_fastmap (fastmap, 0, buf[0]);
+	    }
+#endif
+	}
+      else if (type == SIMPLE_BRACKET)
+	{
+	  int i, ch;
+	  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+	    {
+	      int j;
+	      bitset_word_t w = dfa->nodes[node].opr.sbcset[i];
+	      for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+		if (w & ((bitset_word_t) 1 << j))
+		  re_set_fastmap (fastmap, icase, ch);
+	    }
+	}
+#ifdef RE_ENABLE_I18N
+      else if (type == COMPLEX_BRACKET)
+	{
+	  int i;
+	  re_charset_t *cset = dfa->nodes[node].opr.mbcset;
+	  if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes
+	      || cset->nranges || cset->nchar_classes)
+	    {
+# ifdef _LIBC
+	      if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)
+		{
+		  /* In this case we want to catch the bytes which are
+		     the first byte of any collation elements.
+		     e.g. In da_DK, we want to catch 'a' since "aa"
+			  is a valid collation element, and don't catch
+			  'b' since 'b' is the only collation element
+			  which starts from 'b'.  */
+		  const int32_t *table = (const int32_t *)
+		    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+		  for (i = 0; i < SBC_MAX; ++i)
+		    if (table[i] < 0)
+		      re_set_fastmap (fastmap, icase, i);
+		}
+# else
+	      if (dfa->mb_cur_max > 1)
+		for (i = 0; i < SBC_MAX; ++i)
+		  if (__btowc (i) == WEOF)
+		    re_set_fastmap (fastmap, icase, i);
+# endif /* not _LIBC */
+	    }
+	  for (i = 0; i < cset->nmbchars; ++i)
+	    {
+	      char buf[256];
+	      mbstate_t state;
+	      memset (&state, '\0', sizeof (state));
+	      if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
+		re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
+	      if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+		{
+		  if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
+		      != (size_t) -1)
+		    re_set_fastmap (fastmap, 0, *(unsigned char *) buf);
+		}
+	    }
+	}
+#endif /* RE_ENABLE_I18N */
+      else if (type == OP_PERIOD
+#ifdef RE_ENABLE_I18N
+	       || type == OP_UTF8_PERIOD
+#endif /* RE_ENABLE_I18N */
+	       || type == END_OF_RE)
+	{
+	  memset (fastmap, '\1', sizeof (char) * SBC_MAX);
+	  if (type == END_OF_RE)
+	    bufp->can_be_null = 1;
+	  return;
+	}
+    }
+}
+
+
+/* Entry point for POSIX code.  */
+/* regcomp takes a regular expression as a string and compiles it.
+
+   PREG is a regex_t *.  We do not expect any fields to be initialized,
+   since POSIX says we shouldn't.  Thus, we set
+
+     `buffer' to the compiled pattern;
+     `used' to the length of the compiled pattern;
+     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+       REG_EXTENDED bit in CFLAGS is set; otherwise, to
+       RE_SYNTAX_POSIX_BASIC;
+     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+     `fastmap' to an allocated space for the fastmap;
+     `fastmap_accurate' to zero;
+     `re_nsub' to the number of subexpressions in PATTERN.
+
+   PATTERN is the address of the pattern string.
+
+   CFLAGS is a series of bits which affect compilation.
+
+     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+     use POSIX basic syntax.
+
+     If REG_NEWLINE is set, then . and [^...] don't match newline.
+     Also, regexec will try a match beginning after every newline.
+
+     If REG_ICASE is set, then we considers upper- and lowercase
+     versions of letters to be equivalent when matching.
+
+     If REG_NOSUB is set, then when PREG is passed to regexec, that
+     routine will report only success or failure, and nothing about the
+     registers.
+
+   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
+   the return codes and their meanings.)  */
+
+int
+regcomp (preg, pattern, cflags)
+    regex_t *__restrict preg;
+    const char *__restrict pattern;
+    int cflags;
+{
+  reg_errcode_t ret;
+  reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
+			 : RE_SYNTAX_POSIX_BASIC);
+
+  preg->buffer = NULL;
+  preg->allocated = 0;
+  preg->used = 0;
+
+  /* Try to allocate space for the fastmap.  */
+  preg->fastmap = re_malloc (char, SBC_MAX);
+  if (BE (preg->fastmap == NULL, 0))
+    return REG_ESPACE;
+
+  syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (cflags & REG_NEWLINE)
+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~RE_DOT_NEWLINE;
+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+      /* It also changes the matching behavior.  */
+      preg->newline_anchor = 1;
+    }
+  else
+    preg->newline_anchor = 0;
+  preg->no_sub = !!(cflags & REG_NOSUB);
+  preg->translate = NULL;
+
+  ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
+
+  /* POSIX doesn't distinguish between an unmatched open-group and an
+     unmatched close-group: both are REG_EPAREN.  */
+  if (ret == REG_ERPAREN)
+    ret = REG_EPAREN;
+
+  /* We have already checked preg->fastmap != NULL.  */
+  if (BE (ret == REG_NOERROR, 1))
+    /* Compute the fastmap now, since regexec cannot modify the pattern
+       buffer.  This function never fails in this implementation.  */
+    (void) re_compile_fastmap (preg);
+  else
+    {
+      /* Some error occurred while compiling the expression.  */
+      re_free (preg->fastmap);
+      preg->fastmap = NULL;
+    }
+
+  return (int) ret;
+}
+#ifdef _LIBC
+weak_alias (__regcomp, regcomp)
+#endif
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   We don't use PREG here.  */
+
+size_t
+regerror (errcode, preg, errbuf, errbuf_size)
+    int errcode;
+    const regex_t *__restrict preg;
+    char *__restrict errbuf;
+    size_t errbuf_size;
+{
+  const char *msg;
+  size_t msg_size;
+
+  if (BE (errcode < 0
+	  || errcode >= (int) (sizeof (__re_error_msgid_idx)
+			       / sizeof (__re_error_msgid_idx[0])), 0))
+    /* Only error codes returned by the rest of the code should be passed
+       to this routine.  If we are given anything else, or if other regex
+       code generates an invalid error code, then the program has a bug.
+       Dump core so we can fix it.  */
+    abort ();
+
+  msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
+
+  msg_size = strlen (msg) + 1; /* Includes the null.  */
+
+  if (BE (errbuf_size != 0, 1))
+    {
+      if (BE (msg_size > errbuf_size, 0))
+	{
+#if defined HAVE_MEMPCPY || defined _LIBC
+	  *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
+#else
+	  memcpy (errbuf, msg, errbuf_size - 1);
+	  errbuf[errbuf_size - 1] = 0;
+#endif
+	}
+      else
+	memcpy (errbuf, msg, msg_size);
+    }
+
+  return msg_size;
+}
+#ifdef _LIBC
+weak_alias (__regerror, regerror)
+#endif
+
+
+#ifdef RE_ENABLE_I18N
+/* This static array is used for the map to single-byte characters when
+   UTF-8 is used.  Otherwise we would allocate memory just to initialize
+   it the same all the time.  UTF-8 is the preferred encoding so this is
+   a worthwhile optimization.  */
+static const bitset_t utf8_sb_map =
+{
+    /* Set the first 128 bits.  */
+#ifdef _MSC_VER
+  BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, 0, 0, 0, 0
+#else
+  [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
+#endif
+};
+#endif
+
+
+static void
+free_dfa_content (re_dfa_t *dfa)
+{
+  int i, j;
+
+  if (dfa->nodes)
+    for (i = 0; i < dfa->nodes_len; ++i)
+      free_token (dfa->nodes + i);
+  re_free (dfa->nexts);
+  for (i = 0; i < dfa->nodes_len; ++i)
+    {
+      if (dfa->eclosures != NULL)
+	re_node_set_free (dfa->eclosures + i);
+      if (dfa->inveclosures != NULL)
+	re_node_set_free (dfa->inveclosures + i);
+      if (dfa->edests != NULL)
+	re_node_set_free (dfa->edests + i);
+    }
+  re_free (dfa->edests);
+  re_free (dfa->eclosures);
+  re_free (dfa->inveclosures);
+  re_free (dfa->nodes);
+
+  if (dfa->state_table)
+    for (i = 0; i <= dfa->state_hash_mask; ++i)
+      {
+	struct re_state_table_entry *entry = dfa->state_table + i;
+	for (j = 0; j < entry->num; ++j)
+	  {
+	    re_dfastate_t *state = entry->array[j];
+	    free_state (state);
+	  }
+        re_free (entry->array);
+      }
+  re_free (dfa->state_table);
+#ifdef RE_ENABLE_I18N
+  if (dfa->sb_char != utf8_sb_map)
+    re_free (dfa->sb_char);
+#endif
+  re_free (dfa->subexp_map);
+#ifdef DEBUG
+  re_free (dfa->re_str);
+#endif
+
+  re_free (dfa);
+}
+
+
+/* Free dynamically allocated space used by PREG.  */
+
+void
+regfree (preg)
+    regex_t *preg;
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  if (BE (dfa != NULL, 1))
+    free_dfa_content (dfa);
+  preg->buffer = NULL;
+  preg->allocated = 0;
+
+  re_free (preg->fastmap);
+  preg->fastmap = NULL;
+
+  re_free (preg->translate);
+  preg->translate = NULL;
+}
+#ifdef _LIBC
+weak_alias (__regfree, regfree)
+#endif
+
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+
+/* BSD has one and only one pattern buffer.  */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+# ifdef _LIBC
+/* Make these definitions weak in libc, so POSIX programs can redefine
+   these names if they don't use our functions, and still use
+   regcomp/regexec above without link errors.  */
+weak_function
+# endif
+re_comp (s)
+     const char *s;
+{
+  reg_errcode_t ret;
+  char *fastmap;
+
+  if (!s)
+    {
+      if (!re_comp_buf.buffer)
+	return gettext ("No previous regular expression");
+      return 0;
+    }
+
+  if (re_comp_buf.buffer)
+    {
+      fastmap = re_comp_buf.fastmap;
+      re_comp_buf.fastmap = NULL;
+      __regfree (&re_comp_buf);
+      memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
+      re_comp_buf.fastmap = fastmap;
+    }
+
+  if (re_comp_buf.fastmap == NULL)
+    {
+      re_comp_buf.fastmap = (char *) malloc (SBC_MAX);
+      if (re_comp_buf.fastmap == NULL)
+	return (char *) gettext (__re_error_msgid
+				 + __re_error_msgid_idx[(int) REG_ESPACE]);
+    }
+
+  /* Since `re_exec' always passes NULL for the `regs' argument, we
+     don't need to initialize the pattern buffer fields which affect it.  */
+
+  /* Match anchors at newlines.  */
+  re_comp_buf.newline_anchor = 1;
+
+  ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
+
+  if (!ret)
+    return NULL;
+
+  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
+  return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
+}
+
+#ifdef _LIBC
+libc_freeres_fn (free_mem)
+{
+  __regfree (&re_comp_buf);
+}
+#endif
+
+#endif /* _REGEX_RE_COMP */
+
+
+/* Internal entry point.
+   Compile the regular expression PATTERN, whose length is LENGTH.
+   SYNTAX indicate regular expression's syntax.  */
+
+static reg_errcode_t
+re_compile_internal (regex_t *preg, const char * pattern, size_t length,
+		     reg_syntax_t syntax)
+{
+  reg_errcode_t err = REG_NOERROR;
+  re_dfa_t *dfa;
+  re_string_t regexp;
+
+  /* Initialize the pattern buffer.  */
+  preg->fastmap_accurate = 0;
+  preg->syntax = syntax;
+  preg->not_bol = preg->not_eol = 0;
+  preg->used = 0;
+  preg->re_nsub = 0;
+  preg->can_be_null = 0;
+  preg->regs_allocated = REGS_UNALLOCATED;
+
+  /* Initialize the dfa.  */
+  dfa = (re_dfa_t *) preg->buffer;
+  if (BE (preg->allocated < sizeof (re_dfa_t), 0))
+    {
+      /* If zero allocated, but buffer is non-null, try to realloc
+	 enough space.  This loses if buffer's address is bogus, but
+	 that is the user's responsibility.  If ->buffer is NULL this
+	 is a simple allocation.  */
+      dfa = re_realloc (preg->buffer, re_dfa_t, 1);
+      if (dfa == NULL)
+	return REG_ESPACE;
+      preg->allocated = sizeof (re_dfa_t);
+      preg->buffer = (unsigned char *) dfa;
+    }
+  preg->used = sizeof (re_dfa_t);
+
+  err = init_dfa (dfa, length);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_dfa_content (dfa);
+      preg->buffer = NULL;
+      preg->allocated = 0;
+      return err;
+    }
+#ifdef DEBUG
+  /* Note: length+1 will not overflow since it is checked in init_dfa.  */
+  dfa->re_str = re_malloc (char, length + 1);
+  strncpy (dfa->re_str, pattern, length + 1);
+#endif
+
+  __libc_lock_init (dfa->lock);
+
+  err = re_string_construct (&regexp, pattern, length, preg->translate,
+			     syntax & RE_ICASE, dfa);
+  if (BE (err != REG_NOERROR, 0))
+    {
+    re_compile_internal_free_return:
+      free_workarea_compile (preg);
+      re_string_destruct (&regexp);
+      free_dfa_content (dfa);
+      preg->buffer = NULL;
+      preg->allocated = 0;
+      return err;
+    }
+
+  /* Parse the regular expression, and build a structure tree.  */
+  preg->re_nsub = 0;
+  dfa->str_tree = parse (&regexp, preg, syntax, &err);
+  if (BE (dfa->str_tree == NULL, 0))
+    goto re_compile_internal_free_return;
+
+  /* Analyze the tree and create the nfa.  */
+  err = analyze (preg);
+  if (BE (err != REG_NOERROR, 0))
+    goto re_compile_internal_free_return;
+
+#ifdef RE_ENABLE_I18N
+  /* If possible, do searching in single byte encoding to speed things up.  */
+  if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
+    optimize_utf8 (dfa);
+#endif
+
+  /* Then create the initial state of the dfa.  */
+  err = create_initial_state (dfa);
+
+  /* Release work areas.  */
+  free_workarea_compile (preg);
+  re_string_destruct (&regexp);
+
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_dfa_content (dfa);
+      preg->buffer = NULL;
+      preg->allocated = 0;
+    }
+
+  return err;
+}
+
+/* Initialize DFA.  We use the length of the regular expression PAT_LEN
+   as the initial length of some arrays.  */
+
+static reg_errcode_t
+init_dfa (re_dfa_t *dfa, size_t pat_len)
+{
+  unsigned int table_size;
+#ifndef _LIBC
+  char *codeset_name;
+#endif
+
+  memset (dfa, '\0', sizeof (re_dfa_t));
+
+  /* Force allocation of str_tree_storage the first time.  */
+  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
+
+  /* Avoid overflows.  */
+  if (pat_len == SIZE_MAX)
+    return REG_ESPACE;
+
+  dfa->nodes_alloc = pat_len + 1;
+  dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
+
+  /*  table_size = 2 ^ ceil(log pat_len) */
+  for (table_size = 1; ; table_size <<= 1)
+    if (table_size > pat_len)
+      break;
+
+  dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
+  dfa->state_hash_mask = table_size - 1;
+
+  dfa->mb_cur_max = MB_CUR_MAX;
+#ifdef _LIBC
+  if (dfa->mb_cur_max == 6
+      && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
+    dfa->is_utf8 = 1;
+  dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
+		       != 0);
+#else
+# ifdef HAVE_LANGINFO_CODESET
+  codeset_name = nl_langinfo (CODESET);
+# else
+  codeset_name = getenv ("LC_ALL");
+  if (codeset_name == NULL || codeset_name[0] == '\0')
+    codeset_name = getenv ("LC_CTYPE");
+  if (codeset_name == NULL || codeset_name[0] == '\0')
+    codeset_name = getenv ("LANG");
+  if (codeset_name == NULL)
+    codeset_name = "";
+  else if (strchr (codeset_name, '.') !=  NULL)
+    codeset_name = strchr (codeset_name, '.') + 1;
+# endif
+
+  if (strcasecmp (codeset_name, "UTF-8") == 0
+      || strcasecmp (codeset_name, "UTF8") == 0)
+    dfa->is_utf8 = 1;
+
+  /* We check exhaustively in the loop below if this charset is a
+     superset of ASCII.  */
+  dfa->map_notascii = 0;
+#endif
+
+#ifdef RE_ENABLE_I18N
+  if (dfa->mb_cur_max > 1)
+    {
+      if (dfa->is_utf8)
+	dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
+      else
+	{
+	  int i, j, ch;
+
+	  dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+	  if (BE (dfa->sb_char == NULL, 0))
+	    return REG_ESPACE;
+
+	  /* Set the bits corresponding to single byte chars.  */
+	  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+	    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+	      {
+		wint_t wch = __btowc (ch);
+		if (wch != WEOF)
+		  dfa->sb_char[i] |= (bitset_word_t) 1 << j;
+# ifndef _LIBC
+		if (isascii (ch) && wch != ch)
+		  dfa->map_notascii = 1;
+# endif
+	      }
+	}
+    }
+#endif
+
+  if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0))
+    return REG_ESPACE;
+  return REG_NOERROR;
+}
+
+/* Initialize WORD_CHAR table, which indicate which character is
+   "word".  In this case "word" means that it is the word construction
+   character used by some operators like "\<", "\>", etc.  */
+
+static void
+internal_function
+init_word_char (re_dfa_t *dfa)
+{
+  int i, j, ch;
+  dfa->word_ops_used = 1;
+  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+      if (isalnum (ch) || ch == '_')
+	dfa->word_char[i] |= (bitset_word_t) 1 << j;
+}
+
+/* Free the work area which are only used while compiling.  */
+
+static void
+free_workarea_compile (regex_t *preg)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_storage_t *storage, *next;
+  for (storage = dfa->str_tree_storage; storage; storage = next)
+    {
+      next = storage->next;
+      re_free (storage);
+    }
+  dfa->str_tree_storage = NULL;
+  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
+  dfa->str_tree = NULL;
+  re_free (dfa->org_indices);
+  dfa->org_indices = NULL;
+}
+
+/* Create initial states for all contexts.  */
+
+static reg_errcode_t
+create_initial_state (re_dfa_t *dfa)
+{
+  int first, i;
+  reg_errcode_t err;
+  re_node_set init_nodes;
+
+  /* Initial states have the epsilon closure of the node which is
+     the first node of the regular expression.  */
+  first = dfa->str_tree->first->node_idx;
+  dfa->init_node = first;
+  err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+
+  /* The back-references which are in initial states can epsilon transit,
+     since in this case all of the subexpressions can be null.
+     Then we add epsilon closures of the nodes which are the next nodes of
+     the back-references.  */
+  if (dfa->nbackref > 0)
+    for (i = 0; i < init_nodes.nelem; ++i)
+      {
+	int node_idx = init_nodes.elems[i];
+	re_token_type_t type = dfa->nodes[node_idx].type;
+
+	int clexp_idx;
+	if (type != OP_BACK_REF)
+	  continue;
+	for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
+	  {
+	    re_token_t *clexp_node;
+	    clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
+	    if (clexp_node->type == OP_CLOSE_SUBEXP
+		&& clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)
+	      break;
+	  }
+	if (clexp_idx == init_nodes.nelem)
+	  continue;
+
+	if (type == OP_BACK_REF)
+	  {
+	    int dest_idx = dfa->edests[node_idx].elems[0];
+	    if (!re_node_set_contains (&init_nodes, dest_idx))
+	      {
+		re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
+		i = 0;
+	      }
+	  }
+      }
+
+  /* It must be the first time to invoke acquire_state.  */
+  dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
+  /* We don't check ERR here, since the initial state must not be NULL.  */
+  if (BE (dfa->init_state == NULL, 0))
+    return err;
+  if (dfa->init_state->has_constraint)
+    {
+      dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
+						       CONTEXT_WORD);
+      dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
+						     CONTEXT_NEWLINE);
+      dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
+							 &init_nodes,
+							 CONTEXT_NEWLINE
+							 | CONTEXT_BEGBUF);
+      if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL
+	      || dfa->init_state_begbuf == NULL, 0))
+	return err;
+    }
+  else
+    dfa->init_state_word = dfa->init_state_nl
+      = dfa->init_state_begbuf = dfa->init_state;
+
+  re_node_set_free (&init_nodes);
+  return REG_NOERROR;
+}
+
+
+#ifdef RE_ENABLE_I18N
+/* If it is possible to do searching in single byte encoding instead of UTF-8
+   to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
+   DFA nodes where needed.  */
+
+static void
+optimize_utf8 (re_dfa_t *dfa)
+{
+  int node, i, mb_chars = 0, has_period = 0;
+
+  for (node = 0; node < dfa->nodes_len; ++node)
+    switch (dfa->nodes[node].type)
+      {
+      case CHARACTER:
+	if (dfa->nodes[node].opr.c >= 0x80)
+	  mb_chars = 1;
+	break;
+      case ANCHOR:
+	switch (dfa->nodes[node].opr.idx)
+	  {
+	  case LINE_FIRST:
+	  case LINE_LAST:
+	  case BUF_FIRST:
+	  case BUF_LAST:
+	    break;
+	  default:
+	    /* Word anchors etc. cannot be handled.  */
+	    return;
+	  }
+	break;
+      case OP_PERIOD:
+        has_period = 1;
+        break;
+      case OP_BACK_REF:
+      case OP_ALT:
+      case END_OF_RE:
+      case OP_DUP_ASTERISK:
+      case OP_OPEN_SUBEXP:
+      case OP_CLOSE_SUBEXP:
+	break;
+      case COMPLEX_BRACKET:
+	return;
+      case SIMPLE_BRACKET:
+	/* Just double check.  The non-ASCII range starts at 0x80.  */
+	assert (0x80 % BITSET_WORD_BITS == 0);
+        for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
+	  if (dfa->nodes[node].opr.sbcset[i])
+	    return;
+	break;
+      default:
+	abort ();
+      }
+
+  if (mb_chars || has_period)
+    for (node = 0; node < dfa->nodes_len; ++node)
+      {
+	if (dfa->nodes[node].type == CHARACTER
+	    && dfa->nodes[node].opr.c >= 0x80)
+	  dfa->nodes[node].mb_partial = 0;
+	else if (dfa->nodes[node].type == OP_PERIOD)
+	  dfa->nodes[node].type = OP_UTF8_PERIOD;
+      }
+
+  /* The search can be in single byte locale.  */
+  dfa->mb_cur_max = 1;
+  dfa->is_utf8 = 0;
+  dfa->has_mb_node = dfa->nbackref > 0 || has_period;
+}
+#endif
+
+
+/* Analyze the structure tree, and calculate "first", "next", "edest",
+   "eclosure", and "inveclosure".  */
+
+static reg_errcode_t
+analyze (regex_t *preg)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  reg_errcode_t ret;
+
+  /* Allocate arrays.  */
+  dfa->nexts = re_malloc (int, dfa->nodes_alloc);
+  dfa->org_indices = re_malloc (int, dfa->nodes_alloc);
+  dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
+  dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
+  if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
+	  || dfa->eclosures == NULL, 0))
+    return REG_ESPACE;
+
+  dfa->subexp_map = re_malloc (int, preg->re_nsub);
+  if (dfa->subexp_map != NULL)
+    {
+      int i;
+      for (i = 0; i < preg->re_nsub; i++)
+	dfa->subexp_map[i] = i;
+      preorder (dfa->str_tree, optimize_subexps, dfa);
+      for (i = 0; i < preg->re_nsub; i++)
+	if (dfa->subexp_map[i] != i)
+	  break;
+      if (i == preg->re_nsub)
+	{
+	  free (dfa->subexp_map);
+	  dfa->subexp_map = NULL;
+	}
+    }
+
+  ret = postorder (dfa->str_tree, lower_subexps, preg);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  ret = postorder (dfa->str_tree, calc_first, dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  preorder (dfa->str_tree, calc_next, dfa);
+  ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  ret = calc_eclosure (dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+
+  /* We only need this during the prune_impossible_nodes pass in regexec.c;
+     skip it if p_i_n will not run, as calc_inveclosure can be quadratic.  */
+  if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
+      || dfa->nbackref)
+    {
+      dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
+      if (BE (dfa->inveclosures == NULL, 0))
+        return REG_ESPACE;
+      ret = calc_inveclosure (dfa);
+    }
+
+  return ret;
+}
+
+/* Our parse trees are very unbalanced, so we cannot use a stack to
+   implement parse tree visits.  Instead, we use parent pointers and
+   some hairy code in these two functions.  */
+static reg_errcode_t
+postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
+	   void *extra)
+{
+  bin_tree_t *node, *prev;
+
+  for (node = root; ; )
+    {
+      /* Descend down the tree, preferably to the left (or to the right
+	 if that's the only child).  */
+      while (node->left || node->right)
+	if (node->left)
+          node = node->left;
+        else
+          node = node->right;
+
+      do
+	{
+	  reg_errcode_t err = fn (extra, node);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+          if (node->parent == NULL)
+	    return REG_NOERROR;
+	  prev = node;
+	  node = node->parent;
+	}
+      /* Go up while we have a node that is reached from the right.  */
+      while (node->right == prev || node->right == NULL);
+      node = node->right;
+    }
+}
+
+static reg_errcode_t
+preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
+	  void *extra)
+{
+  bin_tree_t *node;
+
+  for (node = root; ; )
+    {
+      reg_errcode_t err = fn (extra, node);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+
+      /* Go to the left node, or up and to the right.  */
+      if (node->left)
+	node = node->left;
+      else
+	{
+	  bin_tree_t *prev = NULL;
+	  while (node->right == prev || node->right == NULL)
+	    {
+	      prev = node;
+	      node = node->parent;
+	      if (!node)
+	        return REG_NOERROR;
+	    }
+	  node = node->right;
+	}
+    }
+}
+
+/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
+   re_search_internal to map the inner one's opr.idx to this one's.  Adjust
+   backreferences as well.  Requires a preorder visit.  */
+static reg_errcode_t
+optimize_subexps (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+
+  if (node->token.type == OP_BACK_REF && dfa->subexp_map)
+    {
+      int idx = node->token.opr.idx;
+      node->token.opr.idx = dfa->subexp_map[idx];
+      dfa->used_bkref_map |= 1 << node->token.opr.idx;
+    }
+
+  else if (node->token.type == SUBEXP
+           && node->left && node->left->token.type == SUBEXP)
+    {
+      int other_idx = node->left->token.opr.idx;
+
+      node->left = node->left->left;
+      if (node->left)
+        node->left->parent = node;
+
+      dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
+      if (other_idx < BITSET_WORD_BITS)
+	  dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
+    }
+
+  return REG_NOERROR;
+}
+
+/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
+   of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP.  */
+static reg_errcode_t
+lower_subexps (void *extra, bin_tree_t *node)
+{
+  regex_t *preg = (regex_t *) extra;
+  reg_errcode_t err = REG_NOERROR;
+
+  if (node->left && node->left->token.type == SUBEXP)
+    {
+      node->left = lower_subexp (&err, preg, node->left);
+      if (node->left)
+	node->left->parent = node;
+    }
+  if (node->right && node->right->token.type == SUBEXP)
+    {
+      node->right = lower_subexp (&err, preg, node->right);
+      if (node->right)
+	node->right->parent = node;
+    }
+
+  return err;
+}
+
+static bin_tree_t *
+lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *body = node->left;
+  bin_tree_t *op, *cls, *tree1, *tree;
+
+  if (preg->no_sub
+      /* We do not optimize empty subexpressions, because otherwise we may
+	 have bad CONCAT nodes with NULL children.  This is obviously not
+	 very common, so we do not lose much.  An example that triggers
+	 this case is the sed "script" /\(\)/x.  */
+      && node->left != NULL
+      && (node->token.opr.idx >= BITSET_WORD_BITS
+	  || !(dfa->used_bkref_map
+	       & ((bitset_word_t) 1 << node->token.opr.idx))))
+    return node->left;
+
+  /* Convert the SUBEXP node to the concatenation of an
+     OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP.  */
+  op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
+  cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
+  tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
+  tree = create_tree (dfa, op, tree1, CONCAT);
+  if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
+  op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
+  return tree;
+}
+
+/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
+   nodes.  Requires a postorder visit.  */
+static reg_errcode_t
+calc_first (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+  if (node->token.type == CONCAT)
+    {
+      node->first = node->left->first;
+      node->node_idx = node->left->node_idx;
+    }
+  else
+    {
+      node->first = node;
+      node->node_idx = re_dfa_add_node (dfa, node->token);
+      if (BE (node->node_idx == -1, 0))
+        return REG_ESPACE;
+    }
+  return REG_NOERROR;
+}
+
+/* Pass 2: compute NEXT on the tree.  Preorder visit.  */
+static reg_errcode_t
+calc_next (void *extra, bin_tree_t *node)
+{
+  switch (node->token.type)
+    {
+    case OP_DUP_ASTERISK:
+      node->left->next = node;
+      break;
+    case CONCAT:
+      node->left->next = node->right->first;
+      node->right->next = node->next;
+      break;
+    default:
+      if (node->left)
+	node->left->next = node->next;
+      if (node->right)
+        node->right->next = node->next;
+      break;
+    }
+  return REG_NOERROR;
+}
+
+/* Pass 3: link all DFA nodes to their NEXT node (any order will do).  */
+static reg_errcode_t
+link_nfa_nodes (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+  int idx = node->node_idx;
+  reg_errcode_t err = REG_NOERROR;
+
+  switch (node->token.type)
+    {
+    case CONCAT:
+      break;
+
+    case END_OF_RE:
+      assert (node->next == NULL);
+      break;
+
+    case OP_DUP_ASTERISK:
+    case OP_ALT:
+      {
+	int left, right;
+	dfa->has_plural_match = 1;
+	if (node->left != NULL)
+	  left = node->left->first->node_idx;
+	else
+	  left = node->next->node_idx;
+	if (node->right != NULL)
+	  right = node->right->first->node_idx;
+	else
+	  right = node->next->node_idx;
+	assert (left > -1);
+	assert (right > -1);
+	err = re_node_set_init_2 (dfa->edests + idx, left, right);
+      }
+      break;
+
+    case ANCHOR:
+    case OP_OPEN_SUBEXP:
+    case OP_CLOSE_SUBEXP:
+      err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
+      break;
+
+    case OP_BACK_REF:
+      dfa->nexts[idx] = node->next->node_idx;
+      if (node->token.type == OP_BACK_REF)
+	re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
+      break;
+
+    default:
+      assert (!IS_EPSILON_NODE (node->token.type));
+      dfa->nexts[idx] = node->next->node_idx;
+      break;
+    }
+
+  return err;
+}
+
+/* Duplicate the epsilon closure of the node ROOT_NODE.
+   Note that duplicated nodes have constraint INIT_CONSTRAINT in addition
+   to their own constraint.  */
+
+static reg_errcode_t
+internal_function
+duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
+			int root_node, unsigned int init_constraint)
+{
+  int org_node, clone_node, ret;
+  unsigned int constraint = init_constraint;
+  for (org_node = top_org_node, clone_node = top_clone_node;;)
+    {
+      int org_dest, clone_dest;
+      if (dfa->nodes[org_node].type == OP_BACK_REF)
+	{
+	  /* If the back reference epsilon-transit, its destination must
+	     also have the constraint.  Then duplicate the epsilon closure
+	     of the destination of the back reference, and store it in
+	     edests of the back reference.  */
+	  org_dest = dfa->nexts[org_node];
+	  re_node_set_empty (dfa->edests + clone_node);
+	  clone_dest = duplicate_node (dfa, org_dest, constraint);
+	  if (BE (clone_dest == -1, 0))
+	    return REG_ESPACE;
+	  dfa->nexts[clone_node] = dfa->nexts[org_node];
+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	  if (BE (ret < 0, 0))
+	    return REG_ESPACE;
+	}
+      else if (dfa->edests[org_node].nelem == 0)
+	{
+	  /* In case of the node can't epsilon-transit, don't duplicate the
+	     destination and store the original destination as the
+	     destination of the node.  */
+	  dfa->nexts[clone_node] = dfa->nexts[org_node];
+	  break;
+	}
+      else if (dfa->edests[org_node].nelem == 1)
+	{
+	  /* In case of the node can epsilon-transit, and it has only one
+	     destination.  */
+	  org_dest = dfa->edests[org_node].elems[0];
+	  re_node_set_empty (dfa->edests + clone_node);
+	  if (dfa->nodes[org_node].type == ANCHOR)
+	    {
+	      /* In case of the node has another constraint, append it.  */
+	      if (org_node == root_node && clone_node != org_node)
+		{
+		  /* ...but if the node is root_node itself, it means the
+		     epsilon closure have a loop, then tie it to the
+		     destination of the root_node.  */
+		  ret = re_node_set_insert (dfa->edests + clone_node,
+					    org_dest);
+		  if (BE (ret < 0, 0))
+		    return REG_ESPACE;
+		  break;
+		}
+	      constraint |= dfa->nodes[org_node].opr.ctx_type;
+	    }
+	  clone_dest = duplicate_node (dfa, org_dest, constraint);
+	  if (BE (clone_dest == -1, 0))
+	    return REG_ESPACE;
+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	  if (BE (ret < 0, 0))
+	    return REG_ESPACE;
+	}
+      else /* dfa->edests[org_node].nelem == 2 */
+	{
+	  /* In case of the node can epsilon-transit, and it has two
+	     destinations. In the bin_tree_t and DFA, that's '|' and '*'.   */
+	  org_dest = dfa->edests[org_node].elems[0];
+	  re_node_set_empty (dfa->edests + clone_node);
+	  /* Search for a duplicated node which satisfies the constraint.  */
+	  clone_dest = search_duplicated_node (dfa, org_dest, constraint);
+	  if (clone_dest == -1)
+	    {
+	      /* There are no such a duplicated node, create a new one.  */
+	      reg_errcode_t err;
+	      clone_dest = duplicate_node (dfa, org_dest, constraint);
+	      if (BE (clone_dest == -1, 0))
+		return REG_ESPACE;
+	      ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	      if (BE (ret < 0, 0))
+		return REG_ESPACE;
+	      err = duplicate_node_closure (dfa, org_dest, clone_dest,
+					    root_node, constraint);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	    }
+	  else
+	    {
+	      /* There are a duplicated node which satisfy the constraint,
+		 use it to avoid infinite loop.  */
+	      ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	      if (BE (ret < 0, 0))
+		return REG_ESPACE;
+	    }
+
+	  org_dest = dfa->edests[org_node].elems[1];
+	  clone_dest = duplicate_node (dfa, org_dest, constraint);
+	  if (BE (clone_dest == -1, 0))
+	    return REG_ESPACE;
+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+	  if (BE (ret < 0, 0))
+	    return REG_ESPACE;
+	}
+      org_node = org_dest;
+      clone_node = clone_dest;
+    }
+  return REG_NOERROR;
+}
+
+/* Search for a node which is duplicated from the node ORG_NODE, and
+   satisfies the constraint CONSTRAINT.  */
+
+static int
+search_duplicated_node (const re_dfa_t *dfa, int org_node,
+			unsigned int constraint)
+{
+  int idx;
+  for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
+    {
+      if (org_node == dfa->org_indices[idx]
+	  && constraint == dfa->nodes[idx].constraint)
+	return idx; /* Found.  */
+    }
+  return -1; /* Not found.  */
+}
+
+/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
+   Return the index of the new node, or -1 if insufficient storage is
+   available.  */
+
+static int
+duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint)
+{
+  int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
+  if (BE (dup_idx != -1, 1))
+    {
+      dfa->nodes[dup_idx].constraint = constraint;
+      if (dfa->nodes[org_idx].type == ANCHOR)
+	dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type;
+      dfa->nodes[dup_idx].duplicated = 1;
+
+      /* Store the index of the original node.  */
+      dfa->org_indices[dup_idx] = org_idx;
+    }
+  return dup_idx;
+}
+
+static reg_errcode_t
+calc_inveclosure (re_dfa_t *dfa)
+{
+  int src, idx, ret;
+  for (idx = 0; idx < dfa->nodes_len; ++idx)
+    re_node_set_init_empty (dfa->inveclosures + idx);
+
+  for (src = 0; src < dfa->nodes_len; ++src)
+    {
+      int *elems = dfa->eclosures[src].elems;
+      for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
+	{
+	  ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
+	  if (BE (ret == -1, 0))
+	    return REG_ESPACE;
+	}
+    }
+
+  return REG_NOERROR;
+}
+
+/* Calculate "eclosure" for all the node in DFA.  */
+
+static reg_errcode_t
+calc_eclosure (re_dfa_t *dfa)
+{
+  int node_idx, incomplete;
+#ifdef DEBUG
+  assert (dfa->nodes_len > 0);
+#endif
+  incomplete = 0;
+  /* For each nodes, calculate epsilon closure.  */
+  for (node_idx = 0; ; ++node_idx)
+    {
+      reg_errcode_t err;
+      re_node_set eclosure_elem;
+      if (node_idx == dfa->nodes_len)
+	{
+	  if (!incomplete)
+	    break;
+	  incomplete = 0;
+	  node_idx = 0;
+	}
+
+#ifdef DEBUG
+      assert (dfa->eclosures[node_idx].nelem != -1);
+#endif
+
+      /* If we have already calculated, skip it.  */
+      if (dfa->eclosures[node_idx].nelem != 0)
+	continue;
+      /* Calculate epsilon closure of `node_idx'.  */
+      err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+
+      if (dfa->eclosures[node_idx].nelem == 0)
+	{
+	  incomplete = 1;
+	  re_node_set_free (&eclosure_elem);
+	}
+    }
+  return REG_NOERROR;
+}
+
+/* Calculate epsilon closure of NODE.  */
+
+static reg_errcode_t
+calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
+{
+  reg_errcode_t err;
+  unsigned int constraint;
+  int i, incomplete;
+  re_node_set eclosure;
+  incomplete = 0;
+  err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+
+  /* This indicates that we are calculating this node now.
+     We reference this value to avoid infinite loop.  */
+  dfa->eclosures[node].nelem = -1;
+
+  constraint = ((dfa->nodes[node].type == ANCHOR)
+		? dfa->nodes[node].opr.ctx_type : 0);
+  /* If the current node has constraints, duplicate all nodes.
+     Since they must inherit the constraints.  */
+  if (constraint
+      && dfa->edests[node].nelem
+      && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
+    {
+      int org_node, cur_node;
+      org_node = cur_node = node;
+      err = duplicate_node_closure (dfa, node, node, node, constraint);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+    }
+
+  /* Expand each epsilon destination nodes.  */
+  if (IS_EPSILON_NODE(dfa->nodes[node].type))
+    for (i = 0; i < dfa->edests[node].nelem; ++i)
+      {
+	re_node_set eclosure_elem;
+	int edest = dfa->edests[node].elems[i];
+	/* If calculating the epsilon closure of `edest' is in progress,
+	   return intermediate result.  */
+	if (dfa->eclosures[edest].nelem == -1)
+	  {
+	    incomplete = 1;
+	    continue;
+	  }
+	/* If we haven't calculated the epsilon closure of `edest' yet,
+	   calculate now. Otherwise use calculated epsilon closure.  */
+	if (dfa->eclosures[edest].nelem == 0)
+	  {
+	    err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0);
+	    if (BE (err != REG_NOERROR, 0))
+	      return err;
+	  }
+	else
+	  eclosure_elem = dfa->eclosures[edest];
+	/* Merge the epsilon closure of `edest'.  */
+	re_node_set_merge (&eclosure, &eclosure_elem);
+	/* If the epsilon closure of `edest' is incomplete,
+	   the epsilon closure of this node is also incomplete.  */
+	if (dfa->eclosures[edest].nelem == 0)
+	  {
+	    incomplete = 1;
+	    re_node_set_free (&eclosure_elem);
+	  }
+      }
+
+  /* Epsilon closures include itself.  */
+  re_node_set_insert (&eclosure, node);
+  if (incomplete && !root)
+    dfa->eclosures[node].nelem = 0;
+  else
+    dfa->eclosures[node] = eclosure;
+  *new_set = eclosure;
+  return REG_NOERROR;
+}
+
+
+/* Functions for token which are used in the parser.  */
+
+/* Fetch a token from INPUT.
+   We must not use this function inside bracket expressions.  */
+
+static void
+internal_function
+fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
+{
+  re_string_skip_bytes (input, peek_token (result, input, syntax));
+}
+
+/* Peek a token from INPUT, and return the length of the token.
+   We must not use this function inside bracket expressions.  */
+
+static int
+internal_function
+peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
+{
+  unsigned char c;
+
+  if (re_string_eoi (input))
+    {
+      token->type = END_OF_RE;
+      return 0;
+    }
+
+  c = re_string_peek_byte (input, 0);
+  token->opr.c = c;
+
+  token->word_char = 0;
+#ifdef RE_ENABLE_I18N
+  token->mb_partial = 0;
+  if (input->mb_cur_max > 1 &&
+      !re_string_first_byte (input, re_string_cur_idx (input)))
+    {
+      token->type = CHARACTER;
+      token->mb_partial = 1;
+      return 1;
+    }
+#endif
+  if (c == '\\')
+    {
+      unsigned char c2;
+      if (re_string_cur_idx (input) + 1 >= re_string_length (input))
+	{
+	  token->type = BACK_SLASH;
+	  return 1;
+	}
+
+      c2 = re_string_peek_byte_case (input, 1);
+      token->opr.c = c2;
+      token->type = CHARACTER;
+#ifdef RE_ENABLE_I18N
+      if (input->mb_cur_max > 1)
+	{
+	  wint_t wc = re_string_wchar_at (input,
+					  re_string_cur_idx (input) + 1);
+	  token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+	}
+      else
+#endif
+	token->word_char = IS_WORD_CHAR (c2) != 0;
+
+      switch (c2)
+	{
+	case '|':
+	  if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
+	    token->type = OP_ALT;
+	  break;
+	case '1': case '2': case '3': case '4': case '5':
+	case '6': case '7': case '8': case '9':
+	  if (!(syntax & RE_NO_BK_REFS))
+	    {
+	      token->type = OP_BACK_REF;
+	      token->opr.idx = c2 - '1';
+	    }
+	  break;
+	case '<':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = WORD_FIRST;
+	    }
+	  break;
+	case '>':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = WORD_LAST;
+	    }
+	  break;
+	case 'b':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = WORD_DELIM;
+	    }
+	  break;
+	case 'B':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = NOT_WORD_DELIM;
+	    }
+	  break;
+	case 'w':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    token->type = OP_WORD;
+	  break;
+	case 'W':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    token->type = OP_NOTWORD;
+	  break;
+	case 's':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    token->type = OP_SPACE;
+	  break;
+	case 'S':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    token->type = OP_NOTSPACE;
+	  break;
+	case '`':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = BUF_FIRST;
+	    }
+	  break;
+	case '\'':
+	  if (!(syntax & RE_NO_GNU_OPS))
+	    {
+	      token->type = ANCHOR;
+	      token->opr.ctx_type = BUF_LAST;
+	    }
+	  break;
+	case '(':
+	  if (!(syntax & RE_NO_BK_PARENS))
+	    token->type = OP_OPEN_SUBEXP;
+	  break;
+	case ')':
+	  if (!(syntax & RE_NO_BK_PARENS))
+	    token->type = OP_CLOSE_SUBEXP;
+	  break;
+	case '+':
+	  if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
+	    token->type = OP_DUP_PLUS;
+	  break;
+	case '?':
+	  if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
+	    token->type = OP_DUP_QUESTION;
+	  break;
+	case '{':
+	  if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
+	    token->type = OP_OPEN_DUP_NUM;
+	  break;
+	case '}':
+	  if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
+	    token->type = OP_CLOSE_DUP_NUM;
+	  break;
+	default:
+	  break;
+	}
+      return 2;
+    }
+
+  token->type = CHARACTER;
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1)
+    {
+      wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
+      token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+    }
+  else
+#endif
+    token->word_char = IS_WORD_CHAR (token->opr.c);
+
+  switch (c)
+    {
+    case '\n':
+      if (syntax & RE_NEWLINE_ALT)
+	token->type = OP_ALT;
+      break;
+    case '|':
+      if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
+	token->type = OP_ALT;
+      break;
+    case '*':
+      token->type = OP_DUP_ASTERISK;
+      break;
+    case '+':
+      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
+	token->type = OP_DUP_PLUS;
+      break;
+    case '?':
+      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
+	token->type = OP_DUP_QUESTION;
+      break;
+    case '{':
+      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+	token->type = OP_OPEN_DUP_NUM;
+      break;
+    case '}':
+      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+	token->type = OP_CLOSE_DUP_NUM;
+      break;
+    case '(':
+      if (syntax & RE_NO_BK_PARENS)
+	token->type = OP_OPEN_SUBEXP;
+      break;
+    case ')':
+      if (syntax & RE_NO_BK_PARENS)
+	token->type = OP_CLOSE_SUBEXP;
+      break;
+    case '[':
+      token->type = OP_OPEN_BRACKET;
+      break;
+    case '.':
+      token->type = OP_PERIOD;
+      break;
+    case '^':
+      if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) &&
+	  re_string_cur_idx (input) != 0)
+	{
+	  char prev = re_string_peek_byte (input, -1);
+	  if (!(syntax & RE_NEWLINE_ALT) || prev != '\n')
+	    break;
+	}
+      token->type = ANCHOR;
+      token->opr.ctx_type = LINE_FIRST;
+      break;
+    case '$':
+      if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
+	  re_string_cur_idx (input) + 1 != re_string_length (input))
+	{
+	  re_token_t next;
+	  re_string_skip_bytes (input, 1);
+	  peek_token (&next, input, syntax);
+	  re_string_skip_bytes (input, -1);
+	  if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
+	    break;
+	}
+      token->type = ANCHOR;
+      token->opr.ctx_type = LINE_LAST;
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/* Peek a token from INPUT, and return the length of the token.
+   We must not use this function out of bracket expressions.  */
+
+static int
+internal_function
+peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
+{
+  unsigned char c;
+  if (re_string_eoi (input))
+    {
+      token->type = END_OF_RE;
+      return 0;
+    }
+  c = re_string_peek_byte (input, 0);
+  token->opr.c = c;
+
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1 &&
+      !re_string_first_byte (input, re_string_cur_idx (input)))
+    {
+      token->type = CHARACTER;
+      return 1;
+    }
+#endif /* RE_ENABLE_I18N */
+
+  if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)
+      && re_string_cur_idx (input) + 1 < re_string_length (input))
+    {
+      /* In this case, '\' escape a character.  */
+      unsigned char c2;
+      re_string_skip_bytes (input, 1);
+      c2 = re_string_peek_byte (input, 0);
+      token->opr.c = c2;
+      token->type = CHARACTER;
+      return 1;
+    }
+  if (c == '[') /* '[' is a special char in a bracket exps.  */
+    {
+      unsigned char c2;
+      int token_len;
+      if (re_string_cur_idx (input) + 1 < re_string_length (input))
+	c2 = re_string_peek_byte (input, 1);
+      else
+	c2 = 0;
+      token->opr.c = c2;
+      token_len = 2;
+      switch (c2)
+	{
+	case '.':
+	  token->type = OP_OPEN_COLL_ELEM;
+	  break;
+	case '=':
+	  token->type = OP_OPEN_EQUIV_CLASS;
+	  break;
+	case ':':
+	  if (syntax & RE_CHAR_CLASSES)
+	    {
+	      token->type = OP_OPEN_CHAR_CLASS;
+	      break;
+	    }
+	  /* else fall through.  */
+	default:
+	  token->type = CHARACTER;
+	  token->opr.c = c;
+	  token_len = 1;
+	  break;
+	}
+      return token_len;
+    }
+  switch (c)
+    {
+    case '-':
+      token->type = OP_CHARSET_RANGE;
+      break;
+    case ']':
+      token->type = OP_CLOSE_BRACKET;
+      break;
+    case '^':
+      token->type = OP_NON_MATCH_LIST;
+      break;
+    default:
+      token->type = CHARACTER;
+    }
+  return 1;
+}
+
+
+/* Functions for parser.  */
+
+/* Entry point of the parser.
+   Parse the regular expression REGEXP and return the structure tree.
+   If an error is occured, ERR is set by error code, and return NULL.
+   This function build the following tree, from regular expression <reg_exp>:
+	   CAT
+	   / \
+	  /   \
+   <reg_exp>  EOR
+
+   CAT means concatenation.
+   EOR means end of regular expression.  */
+
+static bin_tree_t *
+parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
+       reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *tree, *eor, *root;
+  re_token_t current_token;
+  dfa->syntax = syntax;
+  fetch_token (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+  tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+  eor = create_tree (dfa, NULL, NULL, END_OF_RE);
+  if (tree != NULL)
+    root = create_tree (dfa, tree, eor, CONCAT);
+  else
+    root = eor;
+  if (BE (eor == NULL || root == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+  return root;
+}
+
+/* This function build the following tree, from regular expression
+   <branch1>|<branch2>:
+	   ALT
+	   / \
+	  /   \
+   <branch1> <branch2>
+
+   ALT means alternative, which represents the operator `|'.  */
+
+static bin_tree_t *
+parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
+	       reg_syntax_t syntax, int nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *tree, *branch = NULL;
+  tree = parse_branch (regexp, preg, token, syntax, nest, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+
+  while (token->type == OP_ALT)
+    {
+      fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+      if (token->type != OP_ALT && token->type != END_OF_RE
+	  && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
+	{
+	  branch = parse_branch (regexp, preg, token, syntax, nest, err);
+	  if (BE (*err != REG_NOERROR && branch == NULL, 0))
+	    return NULL;
+	}
+      else
+	branch = NULL;
+      tree = create_tree (dfa, tree, branch, OP_ALT);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+    }
+  return tree;
+}
+
+/* This function build the following tree, from regular expression
+   <exp1><exp2>:
+	CAT
+	/ \
+       /   \
+   <exp1> <exp2>
+
+   CAT means concatenation.  */
+
+static bin_tree_t *
+parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
+	      reg_syntax_t syntax, int nest, reg_errcode_t *err)
+{
+  bin_tree_t *tree, *exp;
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  tree = parse_expression (regexp, preg, token, syntax, nest, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+
+  while (token->type != OP_ALT && token->type != END_OF_RE
+	 && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
+    {
+      exp = parse_expression (regexp, preg, token, syntax, nest, err);
+      if (BE (*err != REG_NOERROR && exp == NULL, 0))
+	{
+	  return NULL;
+	}
+      if (tree != NULL && exp != NULL)
+	{
+	  tree = create_tree (dfa, tree, exp, CONCAT);
+	  if (tree == NULL)
+	    {
+	      *err = REG_ESPACE;
+	      return NULL;
+	    }
+	}
+      else if (tree == NULL)
+	tree = exp;
+      /* Otherwise exp == NULL, we don't need to create new tree.  */
+    }
+  return tree;
+}
+
+/* This function build the following tree, from regular expression a*:
+	 *
+	 |
+	 a
+*/
+
+static bin_tree_t *
+parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
+		  reg_syntax_t syntax, int nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *tree;
+  switch (token->type)
+    {
+    case CHARACTER:
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+	{
+	  while (!re_string_eoi (regexp)
+		 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
+	    {
+	      bin_tree_t *mbc_remain;
+	      fetch_token (token, regexp, syntax);
+	      mbc_remain = create_token_tree (dfa, NULL, NULL, token);
+	      tree = create_tree (dfa, tree, mbc_remain, CONCAT);
+	      if (BE (mbc_remain == NULL || tree == NULL, 0))
+		{
+		  *err = REG_ESPACE;
+		  return NULL;
+		}
+	    }
+	}
+#endif
+      break;
+    case OP_OPEN_SUBEXP:
+      tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      break;
+    case OP_OPEN_BRACKET:
+      tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      break;
+    case OP_BACK_REF:
+      if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1))
+	{
+	  *err = REG_ESUBREG;
+	  return NULL;
+	}
+      dfa->used_bkref_map |= 1 << token->opr.idx;
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+      ++dfa->nbackref;
+      dfa->has_mb_node = 1;
+      break;
+    case OP_OPEN_DUP_NUM:
+      if (syntax & RE_CONTEXT_INVALID_DUP)
+	{
+	  *err = REG_BADRPT;
+	  return NULL;
+	}
+      /* FALLTHROUGH */
+    case OP_DUP_ASTERISK:
+    case OP_DUP_PLUS:
+    case OP_DUP_QUESTION:
+      if (syntax & RE_CONTEXT_INVALID_OPS)
+	{
+	  *err = REG_BADRPT;
+	  return NULL;
+	}
+      else if (syntax & RE_CONTEXT_INDEP_OPS)
+	{
+	  fetch_token (token, regexp, syntax);
+	  return parse_expression (regexp, preg, token, syntax, nest, err);
+	}
+      /* else fall through  */
+    case OP_CLOSE_SUBEXP:
+      if ((token->type == OP_CLOSE_SUBEXP) &&
+	  !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
+	{
+	  *err = REG_ERPAREN;
+	  return NULL;
+	}
+      /* else fall through  */
+    case OP_CLOSE_DUP_NUM:
+      /* We treat it as a normal character.  */
+
+      /* Then we can these characters as normal characters.  */
+      token->type = CHARACTER;
+      /* mb_partial and word_char bits should be initialized already
+	 by peek_token.  */
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+      break;
+    case ANCHOR:
+      if ((token->opr.ctx_type
+	   & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
+	  && dfa->word_ops_used == 0)
+	init_word_char (dfa);
+      if (token->opr.ctx_type == WORD_DELIM
+          || token->opr.ctx_type == NOT_WORD_DELIM)
+	{
+	  bin_tree_t *tree_first, *tree_last;
+	  if (token->opr.ctx_type == WORD_DELIM)
+	    {
+	      token->opr.ctx_type = WORD_FIRST;
+	      tree_first = create_token_tree (dfa, NULL, NULL, token);
+	      token->opr.ctx_type = WORD_LAST;
+            }
+          else
+            {
+	      token->opr.ctx_type = INSIDE_WORD;
+	      tree_first = create_token_tree (dfa, NULL, NULL, token);
+	      token->opr.ctx_type = INSIDE_NOTWORD;
+            }
+	  tree_last = create_token_tree (dfa, NULL, NULL, token);
+	  tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
+	  if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0))
+	    {
+	      *err = REG_ESPACE;
+	      return NULL;
+	    }
+	}
+      else
+	{
+	  tree = create_token_tree (dfa, NULL, NULL, token);
+	  if (BE (tree == NULL, 0))
+	    {
+	      *err = REG_ESPACE;
+	      return NULL;
+	    }
+	}
+      /* We must return here, since ANCHORs can't be followed
+	 by repetition operators.
+	 eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
+	     it must not be "<ANCHOR(^)><REPEAT(*)>".  */
+      fetch_token (token, regexp, syntax);
+      return tree;
+    case OP_PERIOD:
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+      if (dfa->mb_cur_max > 1)
+	dfa->has_mb_node = 1;
+      break;
+    case OP_WORD:
+    case OP_NOTWORD:
+      tree = build_charclass_op (dfa, regexp->trans,
+				 (const unsigned char *) "alnum",
+				 (const unsigned char *) "_",
+				 token->type == OP_NOTWORD, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      break;
+    case OP_SPACE:
+    case OP_NOTSPACE:
+      tree = build_charclass_op (dfa, regexp->trans,
+				 (const unsigned char *) "space",
+				 (const unsigned char *) "",
+				 token->type == OP_NOTSPACE, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      break;
+    case OP_ALT:
+    case END_OF_RE:
+      return NULL;
+    case BACK_SLASH:
+      *err = REG_EESCAPE;
+      return NULL;
+    default:
+      /* Must not happen?  */
+#ifdef DEBUG
+      assert (0);
+#endif
+      return NULL;
+    }
+  fetch_token (token, regexp, syntax);
+
+  while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
+	 || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
+    {
+      tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+	return NULL;
+      /* In BRE consecutive duplications are not allowed.  */
+      if ((syntax & RE_CONTEXT_INVALID_DUP)
+	  && (token->type == OP_DUP_ASTERISK
+	      || token->type == OP_OPEN_DUP_NUM))
+	{
+	  *err = REG_BADRPT;
+	  return NULL;
+	}
+    }
+
+  return tree;
+}
+
+/* This function build the following tree, from regular expression
+   (<reg_exp>):
+	 SUBEXP
+	    |
+	<reg_exp>
+*/
+
+static bin_tree_t *
+parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
+	       reg_syntax_t syntax, int nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+  bin_tree_t *tree;
+  size_t cur_nsub;
+  cur_nsub = preg->re_nsub++;
+
+  fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+
+  /* The subexpression may be a null string.  */
+  if (token->type == OP_CLOSE_SUBEXP)
+    tree = NULL;
+  else
+    {
+      tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
+      if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))
+        *err = REG_EPAREN;
+      if (BE (*err != REG_NOERROR, 0))
+	return NULL;
+    }
+
+  if (cur_nsub <= '9' - '1')
+    dfa->completed_bkref_map |= 1 << cur_nsub;
+
+  tree = create_tree (dfa, tree, NULL, SUBEXP);
+  if (BE (tree == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+  tree->token.opr.idx = cur_nsub;
+  return tree;
+}
+
+/* This function parse repetition operators like "*", "+", "{1,3}" etc.  */
+
+static bin_tree_t *
+parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
+	      re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
+{
+  bin_tree_t *tree = NULL, *old_tree = NULL;
+  int i, start, end, start_idx = re_string_cur_idx (regexp);
+  re_token_t start_token = *token;
+
+  if (token->type == OP_OPEN_DUP_NUM)
+    {
+      end = 0;
+      start = fetch_number (regexp, token, syntax);
+      if (start == -1)
+	{
+	  if (token->type == CHARACTER && token->opr.c == ',')
+	    start = 0; /* We treat "{,m}" as "{0,m}".  */
+	  else
+	    {
+	      *err = REG_BADBR; /* <re>{} is invalid.  */
+	      return NULL;
+	    }
+	}
+      if (BE (start != -2, 1))
+	{
+	  /* We treat "{n}" as "{n,n}".  */
+	  end = ((token->type == OP_CLOSE_DUP_NUM) ? start
+		 : ((token->type == CHARACTER && token->opr.c == ',')
+		    ? fetch_number (regexp, token, syntax) : -2));
+	}
+      if (BE (start == -2 || end == -2, 0))
+	{
+	  /* Invalid sequence.  */
+	  if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
+	    {
+	      if (token->type == END_OF_RE)
+		*err = REG_EBRACE;
+	      else
+		*err = REG_BADBR;
+
+	      return NULL;
+	    }
+
+	  /* If the syntax bit is set, rollback.  */
+	  re_string_set_index (regexp, start_idx);
+	  *token = start_token;
+	  token->type = CHARACTER;
+	  /* mb_partial and word_char bits should be already initialized by
+	     peek_token.  */
+	  return elem;
+	}
+
+      if (BE (end != -1 && start > end, 0))
+	{
+	  /* First number greater than second.  */
+	  *err = REG_BADBR;
+	  return NULL;
+	}
+    }
+  else
+    {
+      start = (token->type == OP_DUP_PLUS) ? 1 : 0;
+      end = (token->type == OP_DUP_QUESTION) ? 1 : -1;
+    }
+
+  fetch_token (token, regexp, syntax);
+
+  if (BE (elem == NULL, 0))
+    return NULL;
+  if (BE (start == 0 && end == 0, 0))
+    {
+      postorder (elem, free_tree, NULL);
+      return NULL;
+    }
+
+  /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}".  */
+  if (BE (start > 0, 0))
+    {
+      tree = elem;
+      for (i = 2; i <= start; ++i)
+	{
+	  elem = duplicate_tree (elem, dfa);
+	  tree = create_tree (dfa, tree, elem, CONCAT);
+	  if (BE (elem == NULL || tree == NULL, 0))
+	    goto parse_dup_op_espace;
+	}
+
+      if (start == end)
+	return tree;
+
+      /* Duplicate ELEM before it is marked optional.  */
+      elem = duplicate_tree (elem, dfa);
+      old_tree = tree;
+    }
+  else
+    old_tree = NULL;
+
+  if (elem->token.type == SUBEXP)
+    postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx);
+
+  tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
+  if (BE (tree == NULL, 0))
+    goto parse_dup_op_espace;
+
+  /* This loop is actually executed only when end != -1,
+     to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?...  We have
+     already created the start+1-th copy.  */
+  for (i = start + 2; i <= end; ++i)
+    {
+      elem = duplicate_tree (elem, dfa);
+      tree = create_tree (dfa, tree, elem, CONCAT);
+      if (BE (elem == NULL || tree == NULL, 0))
+        goto parse_dup_op_espace;
+
+      tree = create_tree (dfa, tree, NULL, OP_ALT);
+      if (BE (tree == NULL, 0))
+        goto parse_dup_op_espace;
+    }
+
+  if (old_tree)
+    tree = create_tree (dfa, old_tree, tree, CONCAT);
+
+  return tree;
+
+ parse_dup_op_espace:
+  *err = REG_ESPACE;
+  return NULL;
+}
+
+/* Size of the names for collating symbol/equivalence_class/character_class.
+   I'm not sure, but maybe enough.  */
+#define BRACKET_NAME_BUF_SIZE 32
+
+#ifndef _LIBC
+  /* Local function for parse_bracket_exp only used in case of NOT _LIBC.
+     Build the range expression which starts from START_ELEM, and ends
+     at END_ELEM.  The result are written to MBCSET and SBCSET.
+     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
+     mbcset->range_ends, is a pointer argument sinse we may
+     update it.  */
+
+static reg_errcode_t
+internal_function
+# ifdef RE_ENABLE_I18N
+build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,
+		 bracket_elem_t *start_elem, bracket_elem_t *end_elem)
+# else /* not RE_ENABLE_I18N */
+build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
+		 bracket_elem_t *end_elem)
+# endif /* not RE_ENABLE_I18N */
+{
+  unsigned int start_ch, end_ch;
+  /* Equivalence Classes and Character Classes can't be a range start/end.  */
+  if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
+	  || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
+	  0))
+    return REG_ERANGE;
+
+  /* We can handle no multi character collating elements without libc
+     support.  */
+  if (BE ((start_elem->type == COLL_SYM
+	   && strlen ((char *) start_elem->opr.name) > 1)
+	  || (end_elem->type == COLL_SYM
+	      && strlen ((char *) end_elem->opr.name) > 1), 0))
+    return REG_ECOLLATE;
+
+# ifdef RE_ENABLE_I18N
+  {
+    wchar_t wc;
+    wint_t start_wc;
+    wint_t end_wc;
+    wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
+
+    start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
+		: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
+		   : 0));
+    end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
+	      : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
+		 : 0));
+    start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
+		? __btowc (start_ch) : start_elem->opr.wch);
+    end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
+	      ? __btowc (end_ch) : end_elem->opr.wch);
+    if (start_wc == WEOF || end_wc == WEOF)
+      return REG_ECOLLATE;
+    cmp_buf[0] = start_wc;
+    cmp_buf[4] = end_wc;
+    if (wcscoll (cmp_buf, cmp_buf + 4) > 0)
+      return REG_ERANGE;
+
+    /* Got valid collation sequence values, add them as a new entry.
+       However, for !_LIBC we have no collation elements: if the
+       character set is single byte, the single byte character set
+       that we build below suffices.  parse_bracket_exp passes
+       no MBCSET if dfa->mb_cur_max == 1.  */
+    if (mbcset)
+      {
+        /* Check the space of the arrays.  */
+        if (BE (*range_alloc == mbcset->nranges, 0))
+          {
+	    /* There is not enough space, need realloc.  */
+	    wchar_t *new_array_start, *new_array_end;
+	    int new_nranges;
+
+	    /* +1 in case of mbcset->nranges is 0.  */
+	    new_nranges = 2 * mbcset->nranges + 1;
+	    /* Use realloc since mbcset->range_starts and mbcset->range_ends
+	       are NULL if *range_alloc == 0.  */
+	    new_array_start = re_realloc (mbcset->range_starts, wchar_t,
+				          new_nranges);
+	    new_array_end = re_realloc (mbcset->range_ends, wchar_t,
+				        new_nranges);
+
+	    if (BE (new_array_start == NULL || new_array_end == NULL, 0))
+	      return REG_ESPACE;
+
+	    mbcset->range_starts = new_array_start;
+	    mbcset->range_ends = new_array_end;
+	    *range_alloc = new_nranges;
+          }
+
+        mbcset->range_starts[mbcset->nranges] = start_wc;
+        mbcset->range_ends[mbcset->nranges++] = end_wc;
+      }
+
+    /* Build the table for single byte characters.  */
+    for (wc = 0; wc < SBC_MAX; ++wc)
+      {
+	cmp_buf[2] = wc;
+	if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
+	    && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
+	  bitset_set (sbcset, wc);
+      }
+  }
+# else /* not RE_ENABLE_I18N */
+  {
+    unsigned int ch;
+    start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
+		: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
+		   : 0));
+    end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
+	      : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
+		 : 0));
+    if (start_ch > end_ch)
+      return REG_ERANGE;
+    /* Build the table for single byte characters.  */
+    for (ch = 0; ch < SBC_MAX; ++ch)
+      if (start_ch <= ch  && ch <= end_ch)
+	bitset_set (sbcset, ch);
+  }
+# endif /* not RE_ENABLE_I18N */
+  return REG_NOERROR;
+}
+#endif /* not _LIBC */
+
+#ifndef _LIBC
+/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
+   Build the collating element which is represented by NAME.
+   The result are written to MBCSET and SBCSET.
+   COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
+   pointer argument since we may update it.  */
+
+static reg_errcode_t
+internal_function
+# ifdef RE_ENABLE_I18N
+build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
+			int *coll_sym_alloc, const unsigned char *name)
+# else /* not RE_ENABLE_I18N */
+build_collating_symbol (bitset_t sbcset, const unsigned char *name)
+# endif /* not RE_ENABLE_I18N */
+{
+  size_t name_len = strlen ((const char *) name);
+  if (BE (name_len != 1, 0))
+    return REG_ECOLLATE;
+  else
+    {
+      bitset_set (sbcset, name[0]);
+      return REG_NOERROR;
+    }
+}
+#endif /* not _LIBC */
+
+/* This function parse bracket expression like "[abc]", "[a-c]",
+   "[[.a-a.]]" etc.  */
+
+static bin_tree_t *
+parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
+		   reg_syntax_t syntax, reg_errcode_t *err)
+{
+#ifdef _LIBC
+  const unsigned char *collseqmb;
+  const char *collseqwc;
+  uint32_t nrules;
+  int32_t table_size;
+  const int32_t *symb_table;
+  const unsigned char *extra;
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     Seek the collating symbol entry correspondings to NAME.
+     Return the index of the symbol in the SYMB_TABLE.  */
+
+  auto inline int32_t
+  __attribute ((always_inline))
+  seek_collating_symbol_entry (name, name_len)
+	 const unsigned char *name;
+	 size_t name_len;
+    {
+      int32_t hash = elem_hash ((const char *) name, name_len);
+      int32_t elem = hash % table_size;
+      if (symb_table[2 * elem] != 0)
+	{
+	  int32_t second = hash % (table_size - 2) + 1;
+
+	  do
+	    {
+	      /* First compare the hashing value.  */
+	      if (symb_table[2 * elem] == hash
+		  /* Compare the length of the name.  */
+		  && name_len == extra[symb_table[2 * elem + 1]]
+		  /* Compare the name.  */
+		  && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],
+			     name_len) == 0)
+		{
+		  /* Yep, this is the entry.  */
+		  break;
+		}
+
+	      /* Next entry.  */
+	      elem += second;
+	    }
+	  while (symb_table[2 * elem] != 0);
+	}
+      return elem;
+    }
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     Look up the collation sequence value of BR_ELEM.
+     Return the value if succeeded, UINT_MAX otherwise.  */
+
+  auto inline unsigned int
+  __attribute ((always_inline))
+  lookup_collation_sequence_value (br_elem)
+	 bracket_elem_t *br_elem;
+    {
+      if (br_elem->type == SB_CHAR)
+	{
+	  /*
+	  if (MB_CUR_MAX == 1)
+	  */
+	  if (nrules == 0)
+	    return collseqmb[br_elem->opr.ch];
+	  else
+	    {
+	      wint_t wc = __btowc (br_elem->opr.ch);
+	      return __collseq_table_lookup (collseqwc, wc);
+	    }
+	}
+      else if (br_elem->type == MB_CHAR)
+	{
+	  return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
+	}
+      else if (br_elem->type == COLL_SYM)
+	{
+	  size_t sym_name_len = strlen ((char *) br_elem->opr.name);
+	  if (nrules != 0)
+	    {
+	      int32_t elem, idx;
+	      elem = seek_collating_symbol_entry (br_elem->opr.name,
+						  sym_name_len);
+	      if (symb_table[2 * elem] != 0)
+		{
+		  /* We found the entry.  */
+		  idx = symb_table[2 * elem + 1];
+		  /* Skip the name of collating element name.  */
+		  idx += 1 + extra[idx];
+		  /* Skip the byte sequence of the collating element.  */
+		  idx += 1 + extra[idx];
+		  /* Adjust for the alignment.  */
+		  idx = (idx + 3) & ~3;
+		  /* Skip the multibyte collation sequence value.  */
+		  idx += sizeof (unsigned int);
+		  /* Skip the wide char sequence of the collating element.  */
+		  idx += sizeof (unsigned int) *
+		    (1 + *(unsigned int *) (extra + idx));
+		  /* Return the collation sequence value.  */
+		  return *(unsigned int *) (extra + idx);
+		}
+	      else if (symb_table[2 * elem] == 0 && sym_name_len == 1)
+		{
+		  /* No valid character.  Match it as a single byte
+		     character.  */
+		  return collseqmb[br_elem->opr.name[0]];
+		}
+	    }
+	  else if (sym_name_len == 1)
+	    return collseqmb[br_elem->opr.name[0]];
+	}
+      return UINT_MAX;
+    }
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     Build the range expression which starts from START_ELEM, and ends
+     at END_ELEM.  The result are written to MBCSET and SBCSET.
+     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
+     mbcset->range_ends, is a pointer argument sinse we may
+     update it.  */
+
+  auto inline reg_errcode_t
+  __attribute ((always_inline))
+  build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
+	 re_charset_t *mbcset;
+	 int *range_alloc;
+	 bitset_t sbcset;
+	 bracket_elem_t *start_elem, *end_elem;
+    {
+      unsigned int ch;
+      uint32_t start_collseq;
+      uint32_t end_collseq;
+
+      /* Equivalence Classes and Character Classes can't be a range
+	 start/end.  */
+      if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
+	      || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
+	      0))
+	return REG_ERANGE;
+
+      start_collseq = lookup_collation_sequence_value (start_elem);
+      end_collseq = lookup_collation_sequence_value (end_elem);
+      /* Check start/end collation sequence values.  */
+      if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))
+	return REG_ECOLLATE;
+      if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))
+	return REG_ERANGE;
+
+      /* Got valid collation sequence values, add them as a new entry.
+	 However, if we have no collation elements, and the character set
+	 is single byte, the single byte character set that we
+	 build below suffices. */
+      if (nrules > 0 || dfa->mb_cur_max > 1)
+	{
+          /* Check the space of the arrays.  */
+          if (BE (*range_alloc == mbcset->nranges, 0))
+	    {
+	      /* There is not enough space, need realloc.  */
+	      uint32_t *new_array_start;
+	      uint32_t *new_array_end;
+	      int new_nranges;
+
+	      /* +1 in case of mbcset->nranges is 0.  */
+	      new_nranges = 2 * mbcset->nranges + 1;
+	      new_array_start = re_realloc (mbcset->range_starts, uint32_t,
+					    new_nranges);
+	      new_array_end = re_realloc (mbcset->range_ends, uint32_t,
+				          new_nranges);
+
+	      if (BE (new_array_start == NULL || new_array_end == NULL, 0))
+	        return REG_ESPACE;
+
+	      mbcset->range_starts = new_array_start;
+	      mbcset->range_ends = new_array_end;
+	      *range_alloc = new_nranges;
+	    }
+
+          mbcset->range_starts[mbcset->nranges] = start_collseq;
+          mbcset->range_ends[mbcset->nranges++] = end_collseq;
+	}
+
+      /* Build the table for single byte characters.  */
+      for (ch = 0; ch < SBC_MAX; ch++)
+	{
+	  uint32_t ch_collseq;
+	  /*
+	  if (MB_CUR_MAX == 1)
+	  */
+	  if (nrules == 0)
+	    ch_collseq = collseqmb[ch];
+	  else
+	    ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
+	  if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
+	    bitset_set (sbcset, ch);
+	}
+      return REG_NOERROR;
+    }
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     Build the collating element which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
+     pointer argument sinse we may update it.  */
+
+  auto inline reg_errcode_t
+  __attribute ((always_inline))
+  build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)
+	 re_charset_t *mbcset;
+	 int *coll_sym_alloc;
+	 bitset_t sbcset;
+	 const unsigned char *name;
+    {
+      int32_t elem, idx;
+      size_t name_len = strlen ((const char *) name);
+      if (nrules != 0)
+	{
+	  elem = seek_collating_symbol_entry (name, name_len);
+	  if (symb_table[2 * elem] != 0)
+	    {
+	      /* We found the entry.  */
+	      idx = symb_table[2 * elem + 1];
+	      /* Skip the name of collating element name.  */
+	      idx += 1 + extra[idx];
+	    }
+	  else if (symb_table[2 * elem] == 0 && name_len == 1)
+	    {
+	      /* No valid character, treat it as a normal
+		 character.  */
+	      bitset_set (sbcset, name[0]);
+	      return REG_NOERROR;
+	    }
+	  else
+	    return REG_ECOLLATE;
+
+	  /* Got valid collation sequence, add it as a new entry.  */
+	  /* Check the space of the arrays.  */
+	  if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0))
+	    {
+	      /* Not enough, realloc it.  */
+	      /* +1 in case of mbcset->ncoll_syms is 0.  */
+	      int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
+	      /* Use realloc since mbcset->coll_syms is NULL
+		 if *alloc == 0.  */
+	      int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
+						   new_coll_sym_alloc);
+	      if (BE (new_coll_syms == NULL, 0))
+		return REG_ESPACE;
+	      mbcset->coll_syms = new_coll_syms;
+	      *coll_sym_alloc = new_coll_sym_alloc;
+	    }
+	  mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
+	  return REG_NOERROR;
+	}
+      else
+	{
+	  if (BE (name_len != 1, 0))
+	    return REG_ECOLLATE;
+	  else
+	    {
+	      bitset_set (sbcset, name[0]);
+	      return REG_NOERROR;
+	    }
+	}
+    }
+#endif
+
+  re_token_t br_token;
+  re_bitset_ptr_t sbcset;
+#ifdef RE_ENABLE_I18N
+  re_charset_t *mbcset;
+  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
+  int equiv_class_alloc = 0, char_class_alloc = 0;
+#endif /* not RE_ENABLE_I18N */
+  int non_match = 0;
+  bin_tree_t *work_tree;
+  int token_len;
+  int first_round = 1;
+#ifdef _LIBC
+  collseqmb = (const unsigned char *)
+    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules)
+    {
+      /*
+      if (MB_CUR_MAX > 1)
+      */
+      collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+      table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
+      symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+						  _NL_COLLATE_SYMB_TABLEMB);
+      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+						   _NL_COLLATE_SYMB_EXTRAMB);
+    }
+#endif
+  sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+#ifdef RE_ENABLE_I18N
+  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+#endif /* RE_ENABLE_I18N */
+#ifdef RE_ENABLE_I18N
+  if (BE (sbcset == NULL || mbcset == NULL, 0))
+#else
+  if (BE (sbcset == NULL, 0))
+#endif /* RE_ENABLE_I18N */
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  token_len = peek_token_bracket (token, regexp, syntax);
+  if (BE (token->type == END_OF_RE, 0))
+    {
+      *err = REG_BADPAT;
+      goto parse_bracket_exp_free_return;
+    }
+  if (token->type == OP_NON_MATCH_LIST)
+    {
+#ifdef RE_ENABLE_I18N
+      mbcset->non_match = 1;
+#endif /* not RE_ENABLE_I18N */
+      non_match = 1;
+      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
+	bitset_set (sbcset, '\0');
+      re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+      token_len = peek_token_bracket (token, regexp, syntax);
+      if (BE (token->type == END_OF_RE, 0))
+	{
+	  *err = REG_BADPAT;
+	  goto parse_bracket_exp_free_return;
+	}
+    }
+
+  /* We treat the first ']' as a normal character.  */
+  if (token->type == OP_CLOSE_BRACKET)
+    token->type = CHARACTER;
+
+  while (1)
+    {
+      bracket_elem_t start_elem, end_elem;
+      unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
+      unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
+      reg_errcode_t ret;
+      int token_len2 = 0, is_range_exp = 0;
+      re_token_t token2;
+
+      start_elem.opr.name = start_name_buf;
+      ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
+				   syntax, first_round);
+      if (BE (ret != REG_NOERROR, 0))
+	{
+	  *err = ret;
+	  goto parse_bracket_exp_free_return;
+	}
+      first_round = 0;
+
+      /* Get information about the next token.  We need it in any case.  */
+      token_len = peek_token_bracket (token, regexp, syntax);
+
+      /* Do not check for ranges if we know they are not allowed.  */
+      if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)
+	{
+	  if (BE (token->type == END_OF_RE, 0))
+	    {
+	      *err = REG_EBRACK;
+	      goto parse_bracket_exp_free_return;
+	    }
+	  if (token->type == OP_CHARSET_RANGE)
+	    {
+	      re_string_skip_bytes (regexp, token_len); /* Skip '-'.  */
+	      token_len2 = peek_token_bracket (&token2, regexp, syntax);
+	      if (BE (token2.type == END_OF_RE, 0))
+		{
+		  *err = REG_EBRACK;
+		  goto parse_bracket_exp_free_return;
+		}
+	      if (token2.type == OP_CLOSE_BRACKET)
+		{
+		  /* We treat the last '-' as a normal character.  */
+		  re_string_skip_bytes (regexp, -token_len);
+		  token->type = CHARACTER;
+		}
+	      else
+		is_range_exp = 1;
+	    }
+	}
+
+      if (is_range_exp == 1)
+	{
+	  end_elem.opr.name = end_name_buf;
+	  ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
+				       dfa, syntax, 1);
+	  if (BE (ret != REG_NOERROR, 0))
+	    {
+	      *err = ret;
+	      goto parse_bracket_exp_free_return;
+	    }
+
+	  token_len = peek_token_bracket (token, regexp, syntax);
+
+#ifdef _LIBC
+	  *err = build_range_exp (sbcset, mbcset, &range_alloc,
+				  &start_elem, &end_elem);
+#else
+# ifdef RE_ENABLE_I18N
+	  *err = build_range_exp (sbcset,
+				  dfa->mb_cur_max > 1 ? mbcset : NULL,
+				  &range_alloc, &start_elem, &end_elem);
+# else
+	  *err = build_range_exp (sbcset, &start_elem, &end_elem);
+# endif
+#endif /* RE_ENABLE_I18N */
+	  if (BE (*err != REG_NOERROR, 0))
+	    goto parse_bracket_exp_free_return;
+	}
+      else
+	{
+	  switch (start_elem.type)
+	    {
+	    case SB_CHAR:
+	      bitset_set (sbcset, start_elem.opr.ch);
+	      break;
+#ifdef RE_ENABLE_I18N
+	    case MB_CHAR:
+	      /* Check whether the array has enough space.  */
+	      if (BE (mbchar_alloc == mbcset->nmbchars, 0))
+		{
+		  wchar_t *new_mbchars;
+		  /* Not enough, realloc it.  */
+		  /* +1 in case of mbcset->nmbchars is 0.  */
+		  mbchar_alloc = 2 * mbcset->nmbchars + 1;
+		  /* Use realloc since array is NULL if *alloc == 0.  */
+		  new_mbchars = re_realloc (mbcset->mbchars, wchar_t,
+					    mbchar_alloc);
+		  if (BE (new_mbchars == NULL, 0))
+		    goto parse_bracket_exp_espace;
+		  mbcset->mbchars = new_mbchars;
+		}
+	      mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
+	      break;
+#endif /* RE_ENABLE_I18N */
+	    case EQUIV_CLASS:
+	      *err = build_equiv_class (sbcset,
+#ifdef RE_ENABLE_I18N
+					mbcset, &equiv_class_alloc,
+#endif /* RE_ENABLE_I18N */
+					start_elem.opr.name);
+	      if (BE (*err != REG_NOERROR, 0))
+		goto parse_bracket_exp_free_return;
+	      break;
+	    case COLL_SYM:
+	      *err = build_collating_symbol (sbcset,
+#ifdef RE_ENABLE_I18N
+					     mbcset, &coll_sym_alloc,
+#endif /* RE_ENABLE_I18N */
+					     start_elem.opr.name);
+	      if (BE (*err != REG_NOERROR, 0))
+		goto parse_bracket_exp_free_return;
+	      break;
+	    case CHAR_CLASS:
+	      *err = build_charclass (regexp->trans, sbcset,
+#ifdef RE_ENABLE_I18N
+				      mbcset, &char_class_alloc,
+#endif /* RE_ENABLE_I18N */
+				      start_elem.opr.name, syntax);
+	      if (BE (*err != REG_NOERROR, 0))
+	       goto parse_bracket_exp_free_return;
+	      break;
+	    default:
+	      assert (0);
+	      break;
+	    }
+	}
+      if (BE (token->type == END_OF_RE, 0))
+	{
+	  *err = REG_EBRACK;
+	  goto parse_bracket_exp_free_return;
+	}
+      if (token->type == OP_CLOSE_BRACKET)
+	break;
+    }
+
+  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+
+  /* If it is non-matching list.  */
+  if (non_match)
+    bitset_not (sbcset);
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure only single byte characters are set.  */
+  if (dfa->mb_cur_max > 1)
+    bitset_mask (sbcset, dfa->sb_char);
+
+  if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
+      || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
+						     || mbcset->non_match)))
+    {
+      bin_tree_t *mbc_tree;
+      int sbc_idx;
+      /* Build a tree for complex bracket.  */
+      dfa->has_mb_node = 1;
+      br_token.type = COMPLEX_BRACKET;
+      br_token.opr.mbcset = mbcset;
+      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (mbc_tree == NULL, 0))
+	goto parse_bracket_exp_espace;
+      for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)
+	if (sbcset[sbc_idx])
+	  break;
+      /* If there are no bits set in sbcset, there is no point
+	 of having both SIMPLE_BRACKET and COMPLEX_BRACKET.  */
+      if (sbc_idx < BITSET_WORDS)
+	{
+          /* Build a tree for simple bracket.  */
+          br_token.type = SIMPLE_BRACKET;
+          br_token.opr.sbcset = sbcset;
+          work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+          if (BE (work_tree == NULL, 0))
+            goto parse_bracket_exp_espace;
+
+          /* Then join them by ALT node.  */
+          work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
+          if (BE (work_tree == NULL, 0))
+            goto parse_bracket_exp_espace;
+	}
+      else
+	{
+	  re_free (sbcset);
+	  work_tree = mbc_tree;
+	}
+    }
+  else
+#endif /* not RE_ENABLE_I18N */
+    {
+#ifdef RE_ENABLE_I18N
+      free_charset (mbcset);
+#endif
+      /* Build a tree for simple bracket.  */
+      br_token.type = SIMPLE_BRACKET;
+      br_token.opr.sbcset = sbcset;
+      work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (work_tree == NULL, 0))
+        goto parse_bracket_exp_espace;
+    }
+  return work_tree;
+
+ parse_bracket_exp_espace:
+  *err = REG_ESPACE;
+ parse_bracket_exp_free_return:
+  re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+  free_charset (mbcset);
+#endif /* RE_ENABLE_I18N */
+  return NULL;
+}
+
+/* Parse an element in the bracket expression.  */
+
+static reg_errcode_t
+parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
+		       re_token_t *token, int token_len, re_dfa_t *dfa,
+		       reg_syntax_t syntax, int accept_hyphen)
+{
+#ifdef RE_ENABLE_I18N
+  int cur_char_size;
+  cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
+  if (cur_char_size > 1)
+    {
+      elem->type = MB_CHAR;
+      elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
+      re_string_skip_bytes (regexp, cur_char_size);
+      return REG_NOERROR;
+    }
+#endif /* RE_ENABLE_I18N */
+  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+  if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
+      || token->type == OP_OPEN_EQUIV_CLASS)
+    return parse_bracket_symbol (elem, regexp, token);
+  if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen)
+    {
+      /* A '-' must only appear as anything but a range indicator before
+	 the closing bracket.  Everything else is an error.  */
+      re_token_t token2;
+      (void) peek_token_bracket (&token2, regexp, syntax);
+      if (token2.type != OP_CLOSE_BRACKET)
+	/* The actual error value is not standardized since this whole
+	   case is undefined.  But ERANGE makes good sense.  */
+	return REG_ERANGE;
+    }
+  elem->type = SB_CHAR;
+  elem->opr.ch = token->opr.c;
+  return REG_NOERROR;
+}
+
+/* Parse a bracket symbol in the bracket expression.  Bracket symbols are
+   such as [:<character_class>:], [.<collating_element>.], and
+   [=<equivalent_class>=].  */
+
+static reg_errcode_t
+parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
+		      re_token_t *token)
+{
+  unsigned char ch, delim = token->opr.c;
+  int i = 0;
+  if (re_string_eoi(regexp))
+    return REG_EBRACK;
+  for (;; ++i)
+    {
+      if (i >= BRACKET_NAME_BUF_SIZE)
+	return REG_EBRACK;
+      if (token->type == OP_OPEN_CHAR_CLASS)
+	ch = re_string_fetch_byte_case (regexp);
+      else
+	ch = re_string_fetch_byte (regexp);
+      if (re_string_eoi(regexp))
+	return REG_EBRACK;
+      if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
+	break;
+      elem->opr.name[i] = ch;
+    }
+  re_string_skip_bytes (regexp, 1);
+  elem->opr.name[i] = '\0';
+  switch (token->type)
+    {
+    case OP_OPEN_COLL_ELEM:
+      elem->type = COLL_SYM;
+      break;
+    case OP_OPEN_EQUIV_CLASS:
+      elem->type = EQUIV_CLASS;
+      break;
+    case OP_OPEN_CHAR_CLASS:
+      elem->type = CHAR_CLASS;
+      break;
+    default:
+      break;
+    }
+  return REG_NOERROR;
+}
+
+  /* Helper function for parse_bracket_exp.
+     Build the equivalence class which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
+     is a pointer argument sinse we may update it.  */
+
+static reg_errcode_t
+#ifdef RE_ENABLE_I18N
+build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
+		   int *equiv_class_alloc, const unsigned char *name)
+#else /* not RE_ENABLE_I18N */
+build_equiv_class (bitset_t sbcset, const unsigned char *name)
+#endif /* not RE_ENABLE_I18N */
+{
+#ifdef _LIBC
+  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules != 0)
+    {
+      const int32_t *table, *indirect;
+      const unsigned char *weights, *extra, *cp;
+      unsigned char char_buf[2];
+      int32_t idx1, idx2;
+      unsigned int ch;
+      size_t len;
+      /* This #include defines a local function!  */
+# include <locale/weight.h>
+      /* Calculate the index for equivalence class.  */
+      cp = name;
+      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+      weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+					       _NL_COLLATE_WEIGHTMB);
+      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+						   _NL_COLLATE_EXTRAMB);
+      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+						_NL_COLLATE_INDIRECTMB);
+      idx1 = findidx (&cp);
+      if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0))
+	/* This isn't a valid character.  */
+	return REG_ECOLLATE;
+
+      /* Build single byte matcing table for this equivalence class.  */
+      char_buf[1] = (unsigned char) '\0';
+      len = weights[idx1];
+      for (ch = 0; ch < SBC_MAX; ++ch)
+	{
+	  char_buf[0] = ch;
+	  cp = char_buf;
+	  idx2 = findidx (&cp);
+/*
+	  idx2 = table[ch];
+*/
+	  if (idx2 == 0)
+	    /* This isn't a valid character.  */
+	    continue;
+	  if (len == weights[idx2])
+	    {
+	      int cnt = 0;
+	      while (cnt <= len &&
+		     weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt])
+		++cnt;
+
+	      if (cnt > len)
+		bitset_set (sbcset, ch);
+	    }
+	}
+      /* Check whether the array has enough space.  */
+      if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))
+	{
+	  /* Not enough, realloc it.  */
+	  /* +1 in case of mbcset->nequiv_classes is 0.  */
+	  int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
+	  /* Use realloc since the array is NULL if *alloc == 0.  */
+	  int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
+						   int32_t,
+						   new_equiv_class_alloc);
+	  if (BE (new_equiv_classes == NULL, 0))
+	    return REG_ESPACE;
+	  mbcset->equiv_classes = new_equiv_classes;
+	  *equiv_class_alloc = new_equiv_class_alloc;
+	}
+      mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
+    }
+  else
+#endif /* _LIBC */
+    {
+      if (BE (strlen ((const char *) name) != 1, 0))
+	return REG_ECOLLATE;
+      bitset_set (sbcset, *name);
+    }
+  return REG_NOERROR;
+}
+
+  /* Helper function for parse_bracket_exp.
+     Build the character class which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
+     is a pointer argument sinse we may update it.  */
+
+static reg_errcode_t
+#ifdef RE_ENABLE_I18N
+build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
+		 re_charset_t *mbcset, int *char_class_alloc,
+		 const unsigned char *class_name, reg_syntax_t syntax)
+#else /* not RE_ENABLE_I18N */
+build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
+		 const unsigned char *class_name, reg_syntax_t syntax)
+#endif /* not RE_ENABLE_I18N */
+{
+  int i;
+  const char *name = (const char *) class_name;
+
+  /* In case of REG_ICASE "upper" and "lower" match the both of
+     upper and lower cases.  */
+  if ((syntax & RE_ICASE)
+      && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
+    name = "alpha";
+
+#ifdef RE_ENABLE_I18N
+  /* Check the space of the arrays.  */
+  if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
+    {
+      /* Not enough, realloc it.  */
+      /* +1 in case of mbcset->nchar_classes is 0.  */
+      int new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
+      /* Use realloc since array is NULL if *alloc == 0.  */
+      wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
+					       new_char_class_alloc);
+      if (BE (new_char_classes == NULL, 0))
+	return REG_ESPACE;
+      mbcset->char_classes = new_char_classes;
+      *char_class_alloc = new_char_class_alloc;
+    }
+  mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
+#endif /* RE_ENABLE_I18N */
+
+#define BUILD_CHARCLASS_LOOP(ctype_func)	\
+  do {						\
+    if (BE (trans != NULL, 0))			\
+      {						\
+	for (i = 0; i < SBC_MAX; ++i)		\
+  	  if (ctype_func (i))			\
+	    bitset_set (sbcset, trans[i]);	\
+      }						\
+    else					\
+      {						\
+	for (i = 0; i < SBC_MAX; ++i)		\
+  	  if (ctype_func (i))			\
+	    bitset_set (sbcset, i);		\
+      }						\
+  } while (0)
+
+  if (strcmp (name, "alnum") == 0)
+    BUILD_CHARCLASS_LOOP (isalnum);
+  else if (strcmp (name, "cntrl") == 0)
+    BUILD_CHARCLASS_LOOP (iscntrl);
+  else if (strcmp (name, "lower") == 0)
+    BUILD_CHARCLASS_LOOP (islower);
+  else if (strcmp (name, "space") == 0)
+    BUILD_CHARCLASS_LOOP (isspace);
+  else if (strcmp (name, "alpha") == 0)
+    BUILD_CHARCLASS_LOOP (isalpha);
+  else if (strcmp (name, "digit") == 0)
+    BUILD_CHARCLASS_LOOP (isdigit);
+  else if (strcmp (name, "print") == 0)
+    BUILD_CHARCLASS_LOOP (isprint);
+  else if (strcmp (name, "upper") == 0)
+    BUILD_CHARCLASS_LOOP (isupper);
+  else if (strcmp (name, "blank") == 0)
+    BUILD_CHARCLASS_LOOP (isblank);
+  else if (strcmp (name, "graph") == 0)
+    BUILD_CHARCLASS_LOOP (isgraph);
+  else if (strcmp (name, "punct") == 0)
+    BUILD_CHARCLASS_LOOP (ispunct);
+  else if (strcmp (name, "xdigit") == 0)
+    BUILD_CHARCLASS_LOOP (isxdigit);
+  else
+    return REG_ECTYPE;
+
+  return REG_NOERROR;
+}
+
+static bin_tree_t *
+build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
+		    const unsigned char *class_name,
+		    const unsigned char *extra, int non_match,
+		    reg_errcode_t *err)
+{
+  re_bitset_ptr_t sbcset;
+#ifdef RE_ENABLE_I18N
+  re_charset_t *mbcset;
+  int alloc = 0;
+#endif /* not RE_ENABLE_I18N */
+  reg_errcode_t ret;
+  re_token_t br_token;
+  bin_tree_t *tree;
+
+  sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+#ifdef RE_ENABLE_I18N
+  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+#endif /* RE_ENABLE_I18N */
+
+#ifdef RE_ENABLE_I18N
+  if (BE (sbcset == NULL || mbcset == NULL, 0))
+#else /* not RE_ENABLE_I18N */
+  if (BE (sbcset == NULL, 0))
+#endif /* not RE_ENABLE_I18N */
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  if (non_match)
+    {
+#ifdef RE_ENABLE_I18N
+      /*
+      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
+	bitset_set(cset->sbcset, '\0');
+      */
+      mbcset->non_match = 1;
+#endif /* not RE_ENABLE_I18N */
+    }
+
+  /* We don't care the syntax in this case.  */
+  ret = build_charclass (trans, sbcset,
+#ifdef RE_ENABLE_I18N
+			 mbcset, &alloc,
+#endif /* RE_ENABLE_I18N */
+			 class_name, 0);
+
+  if (BE (ret != REG_NOERROR, 0))
+    {
+      re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+      free_charset (mbcset);
+#endif /* RE_ENABLE_I18N */
+      *err = ret;
+      return NULL;
+    }
+  /* \w match '_' also.  */
+  for (; *extra; extra++)
+    bitset_set (sbcset, *extra);
+
+  /* If it is non-matching list.  */
+  if (non_match)
+    bitset_not (sbcset);
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure only single byte characters are set.  */
+  if (dfa->mb_cur_max > 1)
+    bitset_mask (sbcset, dfa->sb_char);
+#endif
+
+  /* Build a tree for simple bracket.  */
+  br_token.type = SIMPLE_BRACKET;
+  br_token.opr.sbcset = sbcset;
+  tree = create_token_tree (dfa, NULL, NULL, &br_token);
+  if (BE (tree == NULL, 0))
+    goto build_word_op_espace;
+
+#ifdef RE_ENABLE_I18N
+  if (dfa->mb_cur_max > 1)
+    {
+      bin_tree_t *mbc_tree;
+      /* Build a tree for complex bracket.  */
+      br_token.type = COMPLEX_BRACKET;
+      br_token.opr.mbcset = mbcset;
+      dfa->has_mb_node = 1;
+      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (mbc_tree == NULL, 0))
+	goto build_word_op_espace;
+      /* Then join them by ALT node.  */
+      tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
+      if (BE (mbc_tree != NULL, 1))
+	return tree;
+    }
+  else
+    {
+      free_charset (mbcset);
+      return tree;
+    }
+#else /* not RE_ENABLE_I18N */
+  return tree;
+#endif /* not RE_ENABLE_I18N */
+
+ build_word_op_espace:
+  re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+  free_charset (mbcset);
+#endif /* RE_ENABLE_I18N */
+  *err = REG_ESPACE;
+  return NULL;
+}
+
+/* This is intended for the expressions like "a{1,3}".
+   Fetch a number from `input', and return the number.
+   Return -1, if the number field is empty like "{,1}".
+   Return -2, If an error is occured.  */
+
+static int
+fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
+{
+  int num = -1;
+  unsigned char c;
+  while (1)
+    {
+      fetch_token (token, input, syntax);
+      c = token->opr.c;
+      if (BE (token->type == END_OF_RE, 0))
+	return -2;
+      if (token->type == OP_CLOSE_DUP_NUM || c == ',')
+	break;
+      num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
+	     ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));
+      num = (num > RE_DUP_MAX) ? -2 : num;
+    }
+  return num;
+}
+
+
+#ifdef RE_ENABLE_I18N
+static void
+free_charset (re_charset_t *cset)
+{
+  re_free (cset->mbchars);
+# ifdef _LIBC
+  re_free (cset->coll_syms);
+  re_free (cset->equiv_classes);
+  re_free (cset->range_starts);
+  re_free (cset->range_ends);
+# endif
+  re_free (cset->char_classes);
+  re_free (cset);
+}
+#endif /* RE_ENABLE_I18N */
+
+
+/* Functions for binary tree operation.  */
+
+/* Create a tree node.  */
+
+static bin_tree_t *
+create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
+	     re_token_type_t type)
+{
+  re_token_t t;
+  t.type = type;
+  return create_token_tree (dfa, left, right, &t);
+}
+
+static bin_tree_t *
+create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
+		   const re_token_t *token)
+{
+  bin_tree_t *tree;
+  if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0))
+    {
+      bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);
+
+      if (storage == NULL)
+	return NULL;
+      storage->next = dfa->str_tree_storage;
+      dfa->str_tree_storage = storage;
+      dfa->str_tree_storage_idx = 0;
+    }
+  tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];
+
+  tree->parent = NULL;
+  tree->left = left;
+  tree->right = right;
+  tree->token = *token;
+  tree->token.duplicated = 0;
+  tree->token.opt_subexp = 0;
+  tree->first = NULL;
+  tree->next = NULL;
+  tree->node_idx = -1;
+
+  if (left != NULL)
+    left->parent = tree;
+  if (right != NULL)
+    right->parent = tree;
+  return tree;
+}
+
+/* Mark the tree SRC as an optional subexpression.
+   To be called from preorder or postorder.  */
+
+static reg_errcode_t
+mark_opt_subexp (void *extra, bin_tree_t *node)
+{
+  int idx = (int) (long) extra;
+  if (node->token.type == SUBEXP && node->token.opr.idx == idx)
+    node->token.opt_subexp = 1;
+
+  return REG_NOERROR;
+}
+
+/* Free the allocated memory inside NODE. */
+
+static void
+free_token (re_token_t *node)
+{
+#ifdef RE_ENABLE_I18N
+  if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
+    free_charset (node->opr.mbcset);
+  else
+#endif /* RE_ENABLE_I18N */
+    if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
+      re_free (node->opr.sbcset);
+}
+
+/* Worker function for tree walking.  Free the allocated memory inside NODE
+   and its children. */
+
+static reg_errcode_t
+free_tree (void *extra, bin_tree_t *node)
+{
+  free_token (&node->token);
+  return REG_NOERROR;
+}
+
+
+/* Duplicate the node SRC, and return new node.  This is a preorder
+   visit similar to the one implemented by the generic visitor, but
+   we need more infrastructure to maintain two parallel trees --- so,
+   it's easier to duplicate.  */
+
+static bin_tree_t *
+duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)
+{
+  const bin_tree_t *node;
+  bin_tree_t *dup_root;
+  bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
+
+  for (node = root; ; )
+    {
+      /* Create a new tree and link it back to the current parent.  */
+      *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
+      if (*p_new == NULL)
+	return NULL;
+      (*p_new)->parent = dup_node;
+      (*p_new)->token.duplicated = 1;
+      dup_node = *p_new;
+
+      /* Go to the left node, or up and to the right.  */
+      if (node->left)
+	{
+	  node = node->left;
+	  p_new = &dup_node->left;
+	}
+      else
+	{
+	  const bin_tree_t *prev = NULL;
+	  while (node->right == prev || node->right == NULL)
+	    {
+	      prev = node;
+	      node = node->parent;
+	      dup_node = dup_node->parent;
+	      if (!node)
+	        return dup_root;
+	    }
+	  node = node->right;
+	  p_new = &dup_node->right;
+	}
+    }
+}
Index: /tags/kBuild-0.1.4/src/sed/lib/regex.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/regex.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/regex.c	(revision 1780)
@@ -0,0 +1,74 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   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.  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Make sure noone compiles this code with a C++ compiler.  */
+#ifdef __cplusplus
+# error "This is C code, use a C compiler"
+#endif
+
+#ifdef _LIBC
+/* We have to keep the namespace clean.  */
+# define regfree(preg) __regfree (preg)
+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
+# define regerror(errcode, preg, errbuf, errbuf_size) \
+	__regerror(errcode, preg, errbuf, errbuf_size)
+# define re_set_registers(bu, re, nu, st, en) \
+	__re_set_registers (bu, re, nu, st, en)
+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
+	__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+# define re_match(bufp, string, size, pos, regs) \
+	__re_match (bufp, string, size, pos, regs)
+# define re_search(bufp, string, size, startpos, range, regs) \
+	__re_search (bufp, string, size, startpos, range, regs)
+# define re_compile_pattern(pattern, length, bufp) \
+	__re_compile_pattern (pattern, length, bufp)
+# define re_set_syntax(syntax) __re_set_syntax (syntax)
+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
+	__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
+
+# include "../locale/localeinfo.h"
+#endif
+
+/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
+   GNU regex allows.  Include it before <regex.h>, which correctly
+   #undefs RE_DUP_MAX and sets it to the right value.  */
+#include <limits.h>
+
+#include <regex.h>
+#include "regex_internal.h"
+
+#include "regex_internal.c"
+#include "regcomp.c"
+#include "regexec.c"
+
+/* Binary backward compatibility.  */
+#if _LIBC
+# include <shlib-compat.h>
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
+link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
+int re_max_failures = 2000;
+# endif
+#endif
Index: /tags/kBuild-0.1.4/src/sed/lib/regex_.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/regex_.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/regex_.h	(revision 1780)
@@ -0,0 +1,569 @@
+/* Definitions for data structures and routines for the regular
+   expression library.
+   Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005
+   Free Software Foundation, Inc.
+   This file is 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 _REGEX_H
+#define _REGEX_H 1
+
+#include <sys/types.h>
+
+/* Allow the use in C++ code.  */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+   <regex.h>.  */
+
+#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+   should be there.  */
+# include <stddef.h>
+#endif
+
+/* The following two types have to be signed and unsigned integer type
+   wide enough to hold a value of a pointer.  For most ANSI compilers
+   ptrdiff_t and size_t should be likely OK.  Still size of these two
+   types is 2 for Microsoft C.  Ugh... */
+typedef long int s_reg_t;
+typedef unsigned long int active_reg_t;
+
+/* The following bits are used to determine the regexp syntax we
+   recognize.  The set/not-set meanings are chosen so that Emacs syntax
+   remains the value 0.  The bits are given in alphabetical order, and
+   the definitions shifted by one from the previous bit; thus, when we
+   add or remove a bit, only one other definition need change.  */
+typedef unsigned long int reg_syntax_t;
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+   If set, then such a \ quotes the following character.  */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+     literals.
+   If set, then \+ and \? are operators and + and ? are literals.  */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported.  They are:
+     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
+     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+   If not set, then character classes are not supported.  */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+     expressions, of course).
+   If this bit is not set, then it depends:
+        ^  is an anchor if it is at the beginning of a regular
+           expression or after an open-group or an alternation operator;
+        $  is an anchor if it is at the end of a regular expression, or
+           before a close-group or an alternation operator.
+
+   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+   POSIX draft 11.2 says that * etc. in leading positions is undefined.
+   We already implemented a previous draft which made those constructs
+   invalid, though, so we haven't changed the code back.  */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+     regardless of where they are in the pattern.
+   If this bit is not set, then special characters are special only in
+     some contexts; otherwise they are ordinary.  Specifically,
+     * + ? and intervals are only special when not after the beginning,
+     open-group, or alternation operator.  */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+     immediately after an alternation or begin-group operator.  */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+   If not set, then it doesn't.  */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+   If not set, then it does.  */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+   If not set, they do.  */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+     interval, depending on RE_NO_BK_BRACES.
+   If not set, \{, \}, {, and } are literals.  */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+   If not set, they are.  */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+   If not set, newline is literal.  */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+     are literals.
+  If not set, then `\{...\}' defines an interval.  */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+   If not set, \(...\) defines a group, and ( and ) are literals.  */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+   If not set, then \<digit> is a back-reference.  */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal.
+   If not set, then \| is an alternation operator, and | is literal.  */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+     than the starting range point, as in [z-a], is invalid.
+   If not set, then when ending range point collates higher than the
+     starting range point, the range is ignored.  */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+   If not set, then an unmatched ) is invalid.  */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* If this bit is set, succeed as soon as we match the whole pattern,
+   without further backtracking.  */
+#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
+
+/* If this bit is set, do not process the GNU regex operators.
+   If not set, then the GNU regex operators are recognized. */
+#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
+
+/* If this bit is set, turn on internal regex debugging.
+   If not set, and debugging was on, turn it off.
+   This only works if regex.c is compiled -DDEBUG.
+   We define this bit always, so that all that's needed to turn on
+   debugging is to recompile regex.c; the calling code can always have
+   this bit set, and it won't affect anything in the normal case. */
+#define RE_DEBUG (RE_NO_GNU_OPS << 1)
+
+/* If this bit is set, a syntactically invalid interval is treated as
+   a string of ordinary characters.  For example, the ERE 'a{1' is
+   treated as 'a\{1'.  */
+#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
+
+/* If this bit is set, then ignore case when matching.
+   If not set, then case is significant.  */
+#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
+
+/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
+   for ^, because it is difficult to scan the regex backwards to find
+   whether ^ should be special.  */
+#define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
+
+/* If this bit is set, then \{ cannot be first in an bre or
+   immediately after an alternation or begin-group operator.  */
+#define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
+
+/* If this bit is set, then no_sub will be set to 1 during
+   re_compile_pattern.  */
+#define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+   some interfaces).  When a regexp is compiled, the syntax used is
+   stored in the pattern buffer, so changing this does not affect
+   already-compiled regexps.  */
+extern reg_syntax_t re_syntax_options;
+
+
+/* Define combinations of the above bits for the standard possibilities.
+   (The [[[ comments delimit what gets put into the Texinfo file, so
+   don't delete them!)  */
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK							\
+  (RE_BACKSLASH_ESCAPE_IN_LISTS   | RE_DOT_NOT_NULL			\
+   | RE_NO_BK_PARENS              | RE_NO_BK_REFS			\
+   | RE_NO_BK_VBAR                | RE_NO_EMPTY_RANGES			\
+   | RE_DOT_NEWLINE		  | RE_CONTEXT_INDEP_ANCHORS		\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
+
+#define RE_SYNTAX_GNU_AWK						\
+  ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG)	\
+   & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS		\
+       | RE_CONTEXT_INVALID_OPS ))
+
+#define RE_SYNTAX_POSIX_AWK						\
+  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS		\
+   | RE_INTERVALS	    | RE_NO_GNU_OPS)
+
+#define RE_SYNTAX_GREP							\
+  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES				\
+   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS				\
+   | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP							\
+  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE			\
+   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS				\
+   | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP						\
+  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES			\
+   | RE_INVALID_INTERVAL_ORD)
+
+/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */
+#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+
+#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax.  */
+#define _RE_SYNTAX_POSIX_COMMON						\
+  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\
+   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
+
+#define RE_SYNTAX_POSIX_BASIC						\
+  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
+   isn't minimal, since other operators, such as \`, aren't disabled.  */
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+#define RE_SYNTAX_POSIX_EXTENDED					\
+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS   | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS        | RE_NO_BK_VBAR				\
+   | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
+   removed and RE_NO_BK_REFS is added.  */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED				\
+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS        | RE_NO_BK_REFS				\
+   | RE_NO_BK_VBAR	    | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+
+/* Maximum number of duplicates an interval can allow.  Some systems
+   (erroneously) define this in other header files, but we want our
+   value, so remove any previous define.  */
+#ifdef RE_DUP_MAX
+# undef RE_DUP_MAX
+#endif
+/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows.  */
+#define RE_DUP_MAX (0x7fff)
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp').  */
+
+/* If this bit is set, then use extended regular expression syntax.
+   If not set, then use basic regular expression syntax.  */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+   If not set, then case is significant.  */
+#define REG_ICASE (REG_EXTENDED << 1)
+
+/* If this bit is set, then anchors do not match at newline
+     characters in the string.
+   If not set, then anchors do match at newlines.  */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+   If not set, then returns differ between not matching and errors.  */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec).  */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+     the beginning of the string (presumably because it's not the
+     beginning of a line).
+   If not set, then the beginning-of-line operator does match the
+     beginning of the string.  */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line.  */
+#define REG_NOTEOL (1 << 1)
+
+/* Use PMATCH[0] to delimit the start and end of the search in the
+   buffer.  */
+#define REG_STARTEND (1 << 2)
+
+
+/* If any error codes are removed, changed, or added, update the
+   `re_error_msg' table in regex.c.  */
+typedef enum
+{
+#ifdef _XOPEN_SOURCE
+  REG_ENOSYS = -1,	/* This will never happen for this implementation.  */
+#endif
+
+  REG_NOERROR = 0,	/* Success.  */
+  REG_NOMATCH,		/* Didn't find a match (for regexec).  */
+
+  /* POSIX regcomp return error codes.  (In the order listed in the
+     standard.)  */
+  REG_BADPAT,		/* Invalid pattern.  */
+  REG_ECOLLATE,		/* Inalid collating element.  */
+  REG_ECTYPE,		/* Invalid character class name.  */
+  REG_EESCAPE,		/* Trailing backslash.  */
+  REG_ESUBREG,		/* Invalid back reference.  */
+  REG_EBRACK,		/* Unmatched left bracket.  */
+  REG_EPAREN,		/* Parenthesis imbalance.  */
+  REG_EBRACE,		/* Unmatched \{.  */
+  REG_BADBR,		/* Invalid contents of \{\}.  */
+  REG_ERANGE,		/* Invalid range end.  */
+  REG_ESPACE,		/* Ran out of memory.  */
+  REG_BADRPT,		/* No preceding re for repetition op.  */
+
+  /* Error codes we've added.  */
+  REG_EEND,		/* Premature end.  */
+  REG_ESIZE,		/* Compiled pattern bigger than 2^16 bytes.  */
+  REG_ERPAREN		/* Unmatched ) or \); not returned from regcomp.  */
+} reg_errcode_t;
+
+
+/* This data structure represents a compiled pattern.  Before calling
+   the pattern compiler, the fields `buffer', `allocated', `fastmap',
+   `translate', and `no_sub' can be set.  After the pattern has been
+   compiled, the `re_nsub' field is available.  All other fields are
+   private to the regex routines.  */
+
+#ifndef RE_TRANSLATE_TYPE
+# define RE_TRANSLATE_TYPE unsigned char *
+#endif
+
+struct re_pattern_buffer
+{
+  /* Space that holds the compiled pattern.  It is declared as
+     `unsigned char *' because its elements are sometimes used as
+     array indexes.  */
+  unsigned char *buffer;
+
+  /* Number of bytes to which `buffer' points.  */
+  unsigned long int allocated;
+
+  /* Number of bytes actually used in `buffer'.  */
+  unsigned long int used;
+
+  /* Syntax setting with which the pattern was compiled.  */
+  reg_syntax_t syntax;
+
+  /* Pointer to a fastmap, if any, otherwise zero.  re_search uses the
+     fastmap, if there is one, to skip over impossible starting points
+     for matches.  */
+  char *fastmap;
+
+  /* Either a translate table to apply to all characters before
+     comparing them, or zero for no translation.  The translation is
+     applied to a pattern when it is compiled and to a string when it
+     is matched.  */
+  RE_TRANSLATE_TYPE translate;
+
+  /* Number of subexpressions found by the compiler.  */
+  size_t re_nsub;
+
+  /* Zero if this pattern cannot match the empty string, one else.
+     Well, in truth it's used only in `re_search_2', to see whether or
+     not we should use the fastmap, so we don't set this absolutely
+     perfectly; see `re_compile_fastmap' (the `duplicate' case).  */
+  unsigned can_be_null : 1;
+
+  /* If REGS_UNALLOCATED, allocate space in the `regs' structure
+     for `max (RE_NREGS, re_nsub + 1)' groups.
+     If REGS_REALLOCATE, reallocate space if necessary.
+     If REGS_FIXED, use what's there.  */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+  unsigned regs_allocated : 2;
+
+  /* Set to zero when `regex_compile' compiles a pattern; set to one
+     by `re_compile_fastmap' if it updates the fastmap.  */
+  unsigned fastmap_accurate : 1;
+
+  /* If set, `re_match_2' does not return information about
+     subexpressions.  */
+  unsigned no_sub : 1;
+
+  /* If set, a beginning-of-line anchor doesn't match at the beginning
+     of the string.  */
+  unsigned not_bol : 1;
+
+  /* Similarly for an end-of-line anchor.  */
+  unsigned not_eol : 1;
+
+  /* If true, an anchor at a newline matches.  */
+  unsigned newline_anchor : 1;
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+
+/* Type for byte offsets within the string.  POSIX mandates this.  */
+typedef int regoff_t;
+
+
+/* This is the structure we store register match data in.  See
+   regex.texinfo for a full description of what registers match.  */
+struct re_registers
+{
+  unsigned num_regs;
+  regoff_t *start;
+  regoff_t *end;
+};
+
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+   `re_match_2' returns information about at least this many registers
+   the first time a `regs' structure is passed.  */
+#ifndef RE_NREGS
+# define RE_NREGS 30
+#endif
+
+
+/* POSIX specification for registers.  Aside from the different names than
+   `re_registers', POSIX uses an array of structures, instead of a
+   structure of arrays.  */
+typedef struct
+{
+  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
+  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
+} regmatch_t;
+
+
+/* Declarations for routines.  */
+
+/* Sets the current default syntax to SYNTAX, and return the old syntax.
+   You can also simply assign to the `re_syntax_options' variable.  */
+extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
+
+/* Compile the regular expression PATTERN, with length LENGTH
+   and syntax given by the global `re_syntax_options', into the buffer
+   BUFFER.  Return NULL if successful, and an error string if not.  */
+extern const char *re_compile_pattern (const char *__pattern, size_t __length,
+				       struct re_pattern_buffer *__buffer);
+
+
+/* Compile a fastmap for the compiled pattern in BUFFER; used to
+   accelerate searches.  Return 0 if successful and -2 if was an
+   internal error.  */
+extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
+
+
+/* Search in the string STRING (with length LENGTH) for the pattern
+   compiled into BUFFER.  Start searching at position START, for RANGE
+   characters.  Return the starting position of the match, -1 for no
+   match, or -2 for an internal error.  Also return register
+   information in REGS (if REGS and BUFFER->no_sub are nonzero).  */
+extern int re_search (struct re_pattern_buffer *__buffer, const char *__string,
+		      int __length, int __start, int __range,
+		      struct re_registers *__regs);
+
+
+/* Like `re_search', but search in the concatenation of STRING1 and
+   STRING2.  Also, stop searching at index START + STOP.  */
+extern int re_search_2 (struct re_pattern_buffer *__buffer,
+			const char *__string1, int __length1,
+			const char *__string2, int __length2, int __start,
+			int __range, struct re_registers *__regs, int __stop);
+
+
+/* Like `re_search', but return how many characters in STRING the regexp
+   in BUFFER matched, starting at position START.  */
+extern int re_match (struct re_pattern_buffer *__buffer, const char *__string,
+		     int __length, int __start, struct re_registers *__regs);
+
+
+/* Relates to `re_match' as `re_search_2' relates to `re_search'.  */
+extern int re_match_2 (struct re_pattern_buffer *__buffer,
+		       const char *__string1, int __length1,
+		       const char *__string2, int __length2, int __start,
+		       struct re_registers *__regs, int __stop);
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using BUFFER and REGS will use this memory
+   for recording register information.  STARTS and ENDS must be
+   allocated with malloc, and must each be at least `NUM_REGS * sizeof
+   (regoff_t)' bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+extern void re_set_registers (struct re_pattern_buffer *__buffer,
+			      struct re_registers *__regs,
+			      unsigned int __num_regs,
+			      regoff_t *__starts, regoff_t *__ends);
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+# ifndef _CRAY
+/* 4.2 bsd compatibility.  */
+extern char *re_comp (const char *);
+extern int re_exec (const char *);
+# endif
+#endif
+
+/* GCC 2.95 and later have "__restrict"; C99 compilers have
+   "restrict", and "configure" may have defined "restrict".  */
+#ifndef __restrict
+# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
+#  if defined restrict || 199901L <= __STDC_VERSION__
+#   define __restrict restrict
+#  else
+#   define __restrict
+#  endif
+# endif
+#endif
+/* gcc 3.1 and up support the [restrict] syntax.  */
+#ifndef __restrict_arr
+# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+#  define __restrict_arr __restrict
+# else
+#  define __restrict_arr
+# endif
+#endif
+
+/* POSIX compatibility.  */
+extern int regcomp (regex_t *__restrict __preg,
+		    const char *__restrict __pattern,
+		    int __cflags);
+
+extern int regexec (const regex_t *__restrict __preg,
+		    const char *__restrict __string, size_t __nmatch,
+		    regmatch_t __pmatch[__restrict_arr],
+		    int __eflags);
+
+extern size_t regerror (int __errcode, const regex_t *__restrict __preg,
+			char *__restrict __errbuf, size_t __errbuf_size);
+
+extern void regfree (regex_t *__preg);
+
+
+#ifdef __cplusplus
+}
+#endif	/* C++ */
+
+#endif /* regex.h */
Index: /tags/kBuild-0.1.4/src/sed/lib/regex_internal.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/regex_internal.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/regex_internal.c	(revision 1780)
@@ -0,0 +1,1646 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   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.  */
+
+static void re_string_construct_common (const char *str, int len,
+					re_string_t *pstr,
+					RE_TRANSLATE_TYPE trans, int icase,
+					const re_dfa_t *dfa) internal_function;
+static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
+					  const re_node_set *nodes,
+					  unsigned int hash) internal_function;
+static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
+					  const re_node_set *nodes,
+					  unsigned int context,
+					  unsigned int hash) internal_function;
+
+
+/* Functions for string operation.  */
+
+/* This function allocate the buffers.  It is necessary to call
+   re_string_reconstruct before using the object.  */
+
+static reg_errcode_t
+internal_function
+re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
+		    RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
+{
+  reg_errcode_t ret;
+  int init_buf_len;
+
+  /* Ensure at least one character fits into the buffers.  */
+  if (init_len < dfa->mb_cur_max)
+    init_len = dfa->mb_cur_max;
+  init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
+  re_string_construct_common (str, len, pstr, trans, icase, dfa);
+
+  ret = re_string_realloc_buffers (pstr, init_buf_len);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+
+  pstr->word_char = dfa->word_char;
+  pstr->word_ops_used = dfa->word_ops_used;
+  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+  pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
+  pstr->valid_raw_len = pstr->valid_len;
+  return REG_NOERROR;
+}
+
+/* This function allocate the buffers, and initialize them.  */
+
+static reg_errcode_t
+internal_function
+re_string_construct (re_string_t *pstr, const char *str, int len,
+		     RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
+{
+  reg_errcode_t ret;
+  memset (pstr, '\0', sizeof (re_string_t));
+  re_string_construct_common (str, len, pstr, trans, icase, dfa);
+
+  if (len > 0)
+    {
+      ret = re_string_realloc_buffers (pstr, len + 1);
+      if (BE (ret != REG_NOERROR, 0))
+	return ret;
+    }
+  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+
+  if (icase)
+    {
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+	{
+	  while (1)
+	    {
+	      ret = build_wcs_upper_buffer (pstr);
+	      if (BE (ret != REG_NOERROR, 0))
+		return ret;
+	      if (pstr->valid_raw_len >= len)
+		break;
+	      if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
+		break;
+	      ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
+	      if (BE (ret != REG_NOERROR, 0))
+		return ret;
+	    }
+	}
+      else
+#endif /* RE_ENABLE_I18N  */
+	build_upper_buffer (pstr);
+    }
+  else
+    {
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+	build_wcs_buffer (pstr);
+      else
+#endif /* RE_ENABLE_I18N  */
+	{
+	  if (trans != NULL)
+	    re_string_translate_buffer (pstr);
+	  else
+	    {
+	      pstr->valid_len = pstr->bufs_len;
+	      pstr->valid_raw_len = pstr->bufs_len;
+	    }
+	}
+    }
+
+  return REG_NOERROR;
+}
+
+/* Helper functions for re_string_allocate, and re_string_construct.  */
+
+static reg_errcode_t
+internal_function
+re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
+{
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1)
+    {
+      wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
+      if (BE (new_wcs == NULL, 0))
+	return REG_ESPACE;
+      pstr->wcs = new_wcs;
+      if (pstr->offsets != NULL)
+	{
+	  int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len);
+	  if (BE (new_offsets == NULL, 0))
+	    return REG_ESPACE;
+	  pstr->offsets = new_offsets;
+	}
+    }
+#endif /* RE_ENABLE_I18N  */
+  if (pstr->mbs_allocated)
+    {
+      unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
+					   new_buf_len);
+      if (BE (new_mbs == NULL, 0))
+	return REG_ESPACE;
+      pstr->mbs = new_mbs;
+    }
+  pstr->bufs_len = new_buf_len;
+  return REG_NOERROR;
+}
+
+
+static void
+internal_function
+re_string_construct_common (const char *str, int len, re_string_t *pstr,
+			    RE_TRANSLATE_TYPE trans, int icase,
+			    const re_dfa_t *dfa)
+{
+  pstr->raw_mbs = (const unsigned char *) str;
+  pstr->len = len;
+  pstr->raw_len = len;
+  pstr->trans = trans;
+  pstr->icase = icase ? 1 : 0;
+  pstr->mbs_allocated = (trans != NULL || icase);
+  pstr->mb_cur_max = dfa->mb_cur_max;
+  pstr->is_utf8 = dfa->is_utf8;
+  pstr->map_notascii = dfa->map_notascii;
+  pstr->stop = pstr->len;
+  pstr->raw_stop = pstr->stop;
+}
+
+#ifdef RE_ENABLE_I18N
+
+/* Build wide character buffer PSTR->WCS.
+   If the byte sequence of the string are:
+     <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
+   Then wide character buffer will be:
+     <wc1>   , WEOF    , <wc2>   , WEOF    , <wc3>
+   We use WEOF for padding, they indicate that the position isn't
+   a first byte of a multibyte character.
+
+   Note that this function assumes PSTR->VALID_LEN elements are already
+   built and starts from PSTR->VALID_LEN.  */
+
+static void
+internal_function
+build_wcs_buffer (re_string_t *pstr)
+{
+#ifdef _LIBC
+  unsigned char buf[MB_LEN_MAX];
+  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+#else
+  unsigned char buf[64];
+#endif
+  mbstate_t prev_st;
+  int byte_idx, end_idx, remain_len;
+  size_t mbclen;
+
+  /* Build the buffers from pstr->valid_len to either pstr->len or
+     pstr->bufs_len.  */
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+  for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
+    {
+      wchar_t wc;
+      const char *p;
+
+      remain_len = end_idx - byte_idx;
+      prev_st = pstr->cur_state;
+      /* Apply the translation if we need.  */
+      if (BE (pstr->trans != NULL, 0))
+	{
+	  int i, ch;
+
+	  for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+	    {
+	      ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
+	      buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
+	    }
+	  p = (const char *) buf;
+	}
+      else
+	p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
+      mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
+      if (BE (mbclen == (size_t) -2, 0))
+	{
+	  /* The buffer doesn't have enough space, finish to build.  */
+	  pstr->cur_state = prev_st;
+	  break;
+	}
+      else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
+	{
+	  /* We treat these cases as a singlebyte character.  */
+	  mbclen = 1;
+	  wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
+	  if (BE (pstr->trans != NULL, 0))
+	    wc = pstr->trans[wc];
+	  pstr->cur_state = prev_st;
+	}
+
+      /* Write wide character and padding.  */
+      pstr->wcs[byte_idx++] = wc;
+      /* Write paddings.  */
+      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+	pstr->wcs[byte_idx++] = WEOF;
+    }
+  pstr->valid_len = byte_idx;
+  pstr->valid_raw_len = byte_idx;
+}
+
+/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
+   but for REG_ICASE.  */
+
+static int
+internal_function
+build_wcs_upper_buffer (re_string_t *pstr)
+{
+  mbstate_t prev_st;
+  int src_idx, byte_idx, end_idx, remain_len;
+  size_t mbclen;
+#ifdef _LIBC
+  char buf[MB_LEN_MAX];
+  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+#else
+  char buf[64];
+#endif
+
+  byte_idx = pstr->valid_len;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  /* The following optimization assumes that ASCII characters can be
+     mapped to wide characters with a simple cast.  */
+  if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)
+    {
+      while (byte_idx < end_idx)
+	{
+	  wchar_t wc;
+
+	  if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
+	      && mbsinit (&pstr->cur_state))
+	    {
+	      /* In case of a singlebyte character.  */
+	      pstr->mbs[byte_idx]
+		= toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
+	      /* The next step uses the assumption that wchar_t is encoded
+		 ASCII-safe: all ASCII values can be converted like this.  */
+	      pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
+	      ++byte_idx;
+	      continue;
+	    }
+
+	  remain_len = end_idx - byte_idx;
+	  prev_st = pstr->cur_state;
+	  mbclen = mbrtowc (&wc,
+			    ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
+			     + byte_idx), remain_len, &pstr->cur_state);
+	  if (BE (mbclen + 2 > 2, 1))
+	    {
+	      wchar_t wcu = wc;
+	      if (iswlower (wc))
+		{
+		  size_t mbcdlen;
+
+		  wcu = towupper (wc);
+		  mbcdlen = wcrtomb (buf, wcu, &prev_st);
+		  if (BE (mbclen == mbcdlen, 1))
+		    memcpy (pstr->mbs + byte_idx, buf, mbclen);
+		  else
+		    {
+		      src_idx = byte_idx;
+		      goto offsets_needed;
+		    }
+		}
+	      else
+		memcpy (pstr->mbs + byte_idx,
+			pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
+	      pstr->wcs[byte_idx++] = wcu;
+	      /* Write paddings.  */
+	      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+		pstr->wcs[byte_idx++] = WEOF;
+	    }
+	  else if (mbclen == (size_t) -1 || mbclen == 0)
+	    {
+	      /* It is an invalid character or '\0'.  Just use the byte.  */
+	      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
+	      pstr->mbs[byte_idx] = ch;
+	      /* And also cast it to wide char.  */
+	      pstr->wcs[byte_idx++] = (wchar_t) ch;
+	      if (BE (mbclen == (size_t) -1, 0))
+		pstr->cur_state = prev_st;
+	    }
+	  else
+	    {
+	      /* The buffer doesn't have enough space, finish to build.  */
+	      pstr->cur_state = prev_st;
+	      break;
+	    }
+	}
+      pstr->valid_len = byte_idx;
+      pstr->valid_raw_len = byte_idx;
+      return REG_NOERROR;
+    }
+  else
+    for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)
+      {
+	wchar_t wc;
+	const char *p;
+      offsets_needed:
+	remain_len = end_idx - byte_idx;
+	prev_st = pstr->cur_state;
+	if (BE (pstr->trans != NULL, 0))
+	  {
+	    int i, ch;
+
+	    for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+	      {
+		ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
+		buf[i] = pstr->trans[ch];
+	      }
+	    p = (const char *) buf;
+	  }
+	else
+	  p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
+	mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
+	if (BE (mbclen + 2 > 2, 1))
+	  {
+	    wchar_t wcu = wc;
+	    if (iswlower (wc))
+	      {
+		size_t mbcdlen;
+
+		wcu = towupper (wc);
+		mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st);
+		if (BE (mbclen == mbcdlen, 1))
+		  memcpy (pstr->mbs + byte_idx, buf, mbclen);
+		else if (mbcdlen != (size_t) -1)
+		  {
+		    size_t i;
+
+		    if (byte_idx + mbcdlen > pstr->bufs_len)
+		      {
+			pstr->cur_state = prev_st;
+			break;
+		      }
+
+		    if (pstr->offsets == NULL)
+		      {
+			pstr->offsets = re_malloc (int, pstr->bufs_len);
+
+			if (pstr->offsets == NULL)
+			  return REG_ESPACE;
+		      }
+		    if (!pstr->offsets_needed)
+		      {
+			for (i = 0; i < (size_t) byte_idx; ++i)
+			  pstr->offsets[i] = i;
+			pstr->offsets_needed = 1;
+		      }
+
+		    memcpy (pstr->mbs + byte_idx, buf, mbcdlen);
+		    pstr->wcs[byte_idx] = wcu;
+		    pstr->offsets[byte_idx] = src_idx;
+		    for (i = 1; i < mbcdlen; ++i)
+		      {
+			pstr->offsets[byte_idx + i]
+			  = src_idx + (i < mbclen ? i : mbclen - 1);
+			pstr->wcs[byte_idx + i] = WEOF;
+		      }
+		    pstr->len += mbcdlen - mbclen;
+		    if (pstr->raw_stop > src_idx)
+		      pstr->stop += mbcdlen - mbclen;
+		    end_idx = (pstr->bufs_len > pstr->len)
+			      ? pstr->len : pstr->bufs_len;
+		    byte_idx += mbcdlen;
+		    src_idx += mbclen;
+		    continue;
+		  }
+                else
+                  memcpy (pstr->mbs + byte_idx, p, mbclen);
+	      }
+	    else
+	      memcpy (pstr->mbs + byte_idx, p, mbclen);
+
+	    if (BE (pstr->offsets_needed != 0, 0))
+	      {
+		size_t i;
+		for (i = 0; i < mbclen; ++i)
+		  pstr->offsets[byte_idx + i] = src_idx + i;
+	      }
+	    src_idx += mbclen;
+
+	    pstr->wcs[byte_idx++] = wcu;
+	    /* Write paddings.  */
+	    for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+	      pstr->wcs[byte_idx++] = WEOF;
+	  }
+	else if (mbclen == (size_t) -1 || mbclen == 0)
+	  {
+	    /* It is an invalid character or '\0'.  Just use the byte.  */
+	    int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
+
+	    if (BE (pstr->trans != NULL, 0))
+	      ch = pstr->trans [ch];
+	    pstr->mbs[byte_idx] = ch;
+
+	    if (BE (pstr->offsets_needed != 0, 0))
+	      pstr->offsets[byte_idx] = src_idx;
+	    ++src_idx;
+
+	    /* And also cast it to wide char.  */
+	    pstr->wcs[byte_idx++] = (wchar_t) ch;
+	    if (BE (mbclen == (size_t) -1, 0))
+	      pstr->cur_state = prev_st;
+	  }
+	else
+	  {
+	    /* The buffer doesn't have enough space, finish to build.  */
+	    pstr->cur_state = prev_st;
+	    break;
+	  }
+      }
+  pstr->valid_len = byte_idx;
+  pstr->valid_raw_len = src_idx;
+  return REG_NOERROR;
+}
+
+/* Skip characters until the index becomes greater than NEW_RAW_IDX.
+   Return the index.  */
+
+static int
+internal_function
+re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
+{
+  mbstate_t prev_st;
+  int rawbuf_idx;
+  size_t mbclen;
+  wchar_t wc = 0;
+
+  /* Skip the characters which are not necessary to check.  */
+  for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
+       rawbuf_idx < new_raw_idx;)
+    {
+      int remain_len;
+      remain_len = pstr->len - rawbuf_idx;
+      prev_st = pstr->cur_state;
+      mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx,
+			remain_len, &pstr->cur_state);
+      if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
+	{
+	  /* We treat these cases as a singlebyte character.  */
+	  mbclen = 1;
+	  pstr->cur_state = prev_st;
+	}
+      /* Then proceed the next character.  */
+      rawbuf_idx += mbclen;
+    }
+  *last_wc = (wint_t) wc;
+  return rawbuf_idx;
+}
+#endif /* RE_ENABLE_I18N  */
+
+/* Build the buffer PSTR->MBS, and apply the translation if we need.
+   This function is used in case of REG_ICASE.  */
+
+static void
+internal_function
+build_upper_buffer (re_string_t *pstr)
+{
+  int char_idx, end_idx;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
+    {
+      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
+      if (BE (pstr->trans != NULL, 0))
+	ch = pstr->trans[ch];
+      if (islower (ch))
+	pstr->mbs[char_idx] = toupper (ch);
+      else
+	pstr->mbs[char_idx] = ch;
+    }
+  pstr->valid_len = char_idx;
+  pstr->valid_raw_len = char_idx;
+}
+
+/* Apply TRANS to the buffer in PSTR.  */
+
+static void
+internal_function
+re_string_translate_buffer (re_string_t *pstr)
+{
+  int buf_idx, end_idx;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
+    {
+      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
+      pstr->mbs[buf_idx] = pstr->trans[ch];
+    }
+
+  pstr->valid_len = buf_idx;
+  pstr->valid_raw_len = buf_idx;
+}
+
+/* This function re-construct the buffers.
+   Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
+   convert to upper case in case of REG_ICASE, apply translation.  */
+
+static reg_errcode_t
+internal_function
+re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
+{
+  int offset = idx - pstr->raw_mbs_idx;
+  if (BE (offset < 0, 0))
+    {
+      /* Reset buffer.  */
+#ifdef RE_ENABLE_I18N
+      if (pstr->mb_cur_max > 1)
+	memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
+#endif /* RE_ENABLE_I18N */
+      pstr->len = pstr->raw_len;
+      pstr->stop = pstr->raw_stop;
+      pstr->valid_len = 0;
+      pstr->raw_mbs_idx = 0;
+      pstr->valid_raw_len = 0;
+      pstr->offsets_needed = 0;
+      pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
+			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
+      if (!pstr->mbs_allocated)
+	pstr->mbs = (unsigned char *) pstr->raw_mbs;
+      offset = idx;
+    }
+
+  if (BE (offset != 0, 1))
+    {
+      /* Are the characters which are already checked remain?  */
+      if (BE (offset < pstr->valid_raw_len, 1)
+#ifdef RE_ENABLE_I18N
+	  /* Handling this would enlarge the code too much.
+	     Accept a slowdown in that case.  */
+	  && pstr->offsets_needed == 0
+#endif
+	 )
+	{
+	  /* Yes, move them to the front of the buffer.  */
+	  pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags);
+#ifdef RE_ENABLE_I18N
+	  if (pstr->mb_cur_max > 1)
+	    memmove (pstr->wcs, pstr->wcs + offset,
+		     (pstr->valid_len - offset) * sizeof (wint_t));
+#endif /* RE_ENABLE_I18N */
+	  if (BE (pstr->mbs_allocated, 0))
+	    memmove (pstr->mbs, pstr->mbs + offset,
+		     pstr->valid_len - offset);
+	  pstr->valid_len -= offset;
+	  pstr->valid_raw_len -= offset;
+#if DEBUG
+	  assert (pstr->valid_len > 0);
+#endif
+	}
+      else
+	{
+	  /* No, skip all characters until IDX.  */
+#ifdef RE_ENABLE_I18N
+	  if (BE (pstr->offsets_needed, 0))
+	    {
+	      pstr->len = pstr->raw_len - idx + offset;
+	      pstr->stop = pstr->raw_stop - idx + offset;
+	      pstr->offsets_needed = 0;
+	    }
+#endif
+	  pstr->valid_len = 0;
+	  pstr->valid_raw_len = 0;
+#ifdef RE_ENABLE_I18N
+	  if (pstr->mb_cur_max > 1)
+	    {
+	      int wcs_idx;
+	      wint_t wc = WEOF;
+
+	      if (pstr->is_utf8)
+		{
+		  const unsigned char *raw, *p, *q, *end;
+
+		  /* Special case UTF-8.  Multi-byte chars start with any
+		     byte other than 0x80 - 0xbf.  */
+		  raw = pstr->raw_mbs + pstr->raw_mbs_idx;
+		  end = raw + (offset - pstr->mb_cur_max);
+		  p = raw + offset - 1;
+#ifdef _LIBC
+		  /* We know the wchar_t encoding is UCS4, so for the simple
+		     case, ASCII characters, skip the conversion step.  */
+		  if (isascii (*p) && BE (pstr->trans == NULL, 1))
+		    {
+		      memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
+		      pstr->valid_len = 0;
+		      wc = (wchar_t) *p;
+		    }
+		  else
+#endif
+		    for (; p >= end; --p)
+		      if ((*p & 0xc0) != 0x80)
+			{
+			  mbstate_t cur_state;
+			  wchar_t wc2;
+			  int mlen = raw + pstr->len - p;
+			  unsigned char buf[6];
+			  size_t mbclen;
+
+			  q = p;
+			  if (BE (pstr->trans != NULL, 0))
+			    {
+			      int i = mlen < 6 ? mlen : 6;
+			      while (--i >= 0)
+				buf[i] = pstr->trans[p[i]];
+			      q = buf;
+			    }
+			  /* XXX Don't use mbrtowc, we know which conversion
+			     to use (UTF-8 -> UCS4).  */
+			  memset (&cur_state, 0, sizeof (cur_state));
+			  mbclen = mbrtowc (&wc2, (const char *) p, mlen,
+					    &cur_state);
+			  if (raw + offset - p <= mbclen
+			      && mbclen < (size_t) -2)
+			    {
+			      memset (&pstr->cur_state, '\0',
+				      sizeof (mbstate_t));
+			      pstr->valid_len = mbclen - (raw + offset - p);
+			      wc = wc2;
+			    }
+			  break;
+			}
+		}
+
+	      if (wc == WEOF)
+		pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
+	      if (BE (pstr->valid_len, 0))
+		{
+		  for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
+		    pstr->wcs[wcs_idx] = WEOF;
+		  if (pstr->mbs_allocated)
+		    memset (pstr->mbs, 255, pstr->valid_len);
+		}
+	      pstr->valid_raw_len = pstr->valid_len;
+	      pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
+				    && IS_WIDE_WORD_CHAR (wc))
+				   ? CONTEXT_WORD
+				   : ((IS_WIDE_NEWLINE (wc)
+				       && pstr->newline_anchor)
+				      ? CONTEXT_NEWLINE : 0));
+	    }
+	  else
+#endif /* RE_ENABLE_I18N */
+	    {
+	      int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
+	      if (pstr->trans)
+		c = pstr->trans[c];
+	      pstr->tip_context = (bitset_contain (pstr->word_char, c)
+				   ? CONTEXT_WORD
+				   : ((IS_NEWLINE (c) && pstr->newline_anchor)
+				      ? CONTEXT_NEWLINE : 0));
+	    }
+	}
+      if (!BE (pstr->mbs_allocated, 0))
+	pstr->mbs += offset;
+    }
+  pstr->raw_mbs_idx = idx;
+  pstr->len -= offset;
+  pstr->stop -= offset;
+
+  /* Then build the buffers.  */
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1)
+    {
+      if (pstr->icase)
+	{
+	  int ret = build_wcs_upper_buffer (pstr);
+	  if (BE (ret != REG_NOERROR, 0))
+	    return ret;
+	}
+      else
+	build_wcs_buffer (pstr);
+    }
+  else
+#endif /* RE_ENABLE_I18N */
+    if (BE (pstr->mbs_allocated, 0))
+      {
+	if (pstr->icase)
+	  build_upper_buffer (pstr);
+	else if (pstr->trans != NULL)
+	  re_string_translate_buffer (pstr);
+      }
+    else
+      pstr->valid_len = pstr->len;
+
+  pstr->cur_idx = 0;
+  return REG_NOERROR;
+}
+
+static unsigned char
+internal_function __attribute ((pure))
+re_string_peek_byte_case (const re_string_t *pstr, int idx)
+{
+  int ch, off;
+
+  /* Handle the common (easiest) cases first.  */
+  if (BE (!pstr->mbs_allocated, 1))
+    return re_string_peek_byte (pstr, idx);
+
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1
+      && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
+    return re_string_peek_byte (pstr, idx);
+#endif
+
+  off = pstr->cur_idx + idx;
+#ifdef RE_ENABLE_I18N
+  if (pstr->offsets_needed)
+    off = pstr->offsets[off];
+#endif
+
+  ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
+     this function returns CAPITAL LETTER I instead of first byte of
+     DOTLESS SMALL LETTER I.  The latter would confuse the parser,
+     since peek_byte_case doesn't advance cur_idx in any way.  */
+  if (pstr->offsets_needed && !isascii (ch))
+    return re_string_peek_byte (pstr, idx);
+#endif
+
+  return ch;
+}
+
+static unsigned char
+internal_function __attribute ((pure))
+re_string_fetch_byte_case (re_string_t *pstr)
+{
+  if (BE (!pstr->mbs_allocated, 1))
+    return re_string_fetch_byte (pstr);
+
+#ifdef RE_ENABLE_I18N
+  if (pstr->offsets_needed)
+    {
+      int off, ch;
+
+      /* For tr_TR.UTF-8 [[:islower:]] there is
+	 [[: CAPITAL LETTER I WITH DOT lower:]] in mbs.  Skip
+	 in that case the whole multi-byte character and return
+	 the original letter.  On the other side, with
+	 [[: DOTLESS SMALL LETTER I return [[:I, as doing
+	 anything else would complicate things too much.  */
+
+      if (!re_string_first_byte (pstr, pstr->cur_idx))
+	return re_string_fetch_byte (pstr);
+
+      off = pstr->offsets[pstr->cur_idx];
+      ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
+
+      if (! isascii (ch))
+	return re_string_fetch_byte (pstr);
+
+      re_string_skip_bytes (pstr,
+			    re_string_char_size_at (pstr, pstr->cur_idx));
+      return ch;
+    }
+#endif
+
+  return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
+}
+
+static void
+internal_function
+re_string_destruct (re_string_t *pstr)
+{
+#ifdef RE_ENABLE_I18N
+  re_free (pstr->wcs);
+  re_free (pstr->offsets);
+#endif /* RE_ENABLE_I18N  */
+  if (pstr->mbs_allocated)
+    re_free (pstr->mbs);
+}
+
+/* Return the context at IDX in INPUT.  */
+
+static unsigned int
+internal_function
+re_string_context_at (const re_string_t *input, int idx, int eflags)
+{
+  int c;
+  if (BE (idx < 0, 0))
+    /* In this case, we use the value stored in input->tip_context,
+       since we can't know the character in input->mbs[-1] here.  */
+    return input->tip_context;
+  if (BE (idx == input->len, 0))
+    return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
+	    : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1)
+    {
+      wint_t wc;
+      int wc_idx = idx;
+      while(input->wcs[wc_idx] == WEOF)
+	{
+#ifdef DEBUG
+	  /* It must not happen.  */
+	  assert (wc_idx >= 0);
+#endif
+	  --wc_idx;
+	  if (wc_idx < 0)
+	    return input->tip_context;
+	}
+      wc = input->wcs[wc_idx];
+      if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc))
+	return CONTEXT_WORD;
+      return (IS_WIDE_NEWLINE (wc) && input->newline_anchor
+	      ? CONTEXT_NEWLINE : 0);
+    }
+  else
+#endif
+    {
+      c = re_string_byte_at (input, idx);
+      if (bitset_contain (input->word_char, c))
+	return CONTEXT_WORD;
+      return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;
+    }
+}
+
+
+/* Functions for set operation.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_alloc (re_node_set *set, int size)
+{
+  set->alloc = size;
+  set->nelem = 0;
+  set->elems = re_malloc (int, size);
+  if (BE (set->elems == NULL, 0))
+    return REG_ESPACE;
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_1 (re_node_set *set, int elem)
+{
+  set->alloc = 1;
+  set->nelem = 1;
+  set->elems = re_malloc (int, 1);
+  if (BE (set->elems == NULL, 0))
+    {
+      set->alloc = set->nelem = 0;
+      return REG_ESPACE;
+    }
+  set->elems[0] = elem;
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
+{
+  set->alloc = 2;
+  set->elems = re_malloc (int, 2);
+  if (BE (set->elems == NULL, 0))
+    return REG_ESPACE;
+  if (elem1 == elem2)
+    {
+      set->nelem = 1;
+      set->elems[0] = elem1;
+    }
+  else
+    {
+      set->nelem = 2;
+      if (elem1 < elem2)
+	{
+	  set->elems[0] = elem1;
+	  set->elems[1] = elem2;
+	}
+      else
+	{
+	  set->elems[0] = elem2;
+	  set->elems[1] = elem1;
+	}
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
+{
+  dest->nelem = src->nelem;
+  if (src->nelem > 0)
+    {
+      dest->alloc = dest->nelem;
+      dest->elems = re_malloc (int, dest->alloc);
+      if (BE (dest->elems == NULL, 0))
+	{
+	  dest->alloc = dest->nelem = 0;
+	  return REG_ESPACE;
+	}
+      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
+    }
+  else
+    re_node_set_init_empty (dest);
+  return REG_NOERROR;
+}
+
+/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.
+   Note: We assume dest->elems is NULL, when dest->alloc is 0.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
+			   const re_node_set *src2)
+{
+  int i1, i2, is, id, delta, sbase;
+  if (src1->nelem == 0 || src2->nelem == 0)
+    return REG_NOERROR;
+
+  /* We need dest->nelem + 2 * elems_in_intersection; this is a
+     conservative estimate.  */
+  if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
+    {
+      int new_alloc = src1->nelem + src2->nelem + dest->alloc;
+      int *new_elems = re_realloc (dest->elems, int, new_alloc);
+      if (BE (new_elems == NULL, 0))
+        return REG_ESPACE;
+      dest->elems = new_elems;
+      dest->alloc = new_alloc;
+    }
+
+  /* Find the items in the intersection of SRC1 and SRC2, and copy
+     into the top of DEST those that are not already in DEST itself.  */
+  sbase = dest->nelem + src1->nelem + src2->nelem;
+  i1 = src1->nelem - 1;
+  i2 = src2->nelem - 1;
+  id = dest->nelem - 1;
+  for (;;)
+    {
+      if (src1->elems[i1] == src2->elems[i2])
+	{
+	  /* Try to find the item in DEST.  Maybe we could binary search?  */
+	  while (id >= 0 && dest->elems[id] > src1->elems[i1])
+	    --id;
+
+          if (id < 0 || dest->elems[id] != src1->elems[i1])
+            dest->elems[--sbase] = src1->elems[i1];
+
+	  if (--i1 < 0 || --i2 < 0)
+	    break;
+	}
+
+      /* Lower the highest of the two items.  */
+      else if (src1->elems[i1] < src2->elems[i2])
+	{
+	  if (--i2 < 0)
+	    break;
+	}
+      else
+	{
+	  if (--i1 < 0)
+	    break;
+	}
+    }
+
+  id = dest->nelem - 1;
+  is = dest->nelem + src1->nelem + src2->nelem - 1;
+  delta = is - sbase + 1;
+
+  /* Now copy.  When DELTA becomes zero, the remaining
+     DEST elements are already in place; this is more or
+     less the same loop that is in re_node_set_merge.  */
+  dest->nelem += delta;
+  if (delta > 0 && id >= 0)
+    for (;;)
+      {
+        if (dest->elems[is] > dest->elems[id])
+          {
+            /* Copy from the top.  */
+            dest->elems[id + delta--] = dest->elems[is--];
+            if (delta == 0)
+              break;
+          }
+        else
+          {
+            /* Slide from the bottom.  */
+            dest->elems[id + delta] = dest->elems[id];
+            if (--id < 0)
+              break;
+          }
+      }
+
+  /* Copy remaining SRC elements.  */
+  memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int));
+
+  return REG_NOERROR;
+}
+
+/* Calculate the union set of the sets SRC1 and SRC2. And store it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
+			const re_node_set *src2)
+{
+  int i1, i2, id;
+  if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
+    {
+      dest->alloc = src1->nelem + src2->nelem;
+      dest->elems = re_malloc (int, dest->alloc);
+      if (BE (dest->elems == NULL, 0))
+	return REG_ESPACE;
+    }
+  else
+    {
+      if (src1 != NULL && src1->nelem > 0)
+	return re_node_set_init_copy (dest, src1);
+      else if (src2 != NULL && src2->nelem > 0)
+	return re_node_set_init_copy (dest, src2);
+      else
+	re_node_set_init_empty (dest);
+      return REG_NOERROR;
+    }
+  for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
+    {
+      if (src1->elems[i1] > src2->elems[i2])
+	{
+	  dest->elems[id++] = src2->elems[i2++];
+	  continue;
+	}
+      if (src1->elems[i1] == src2->elems[i2])
+	++i2;
+      dest->elems[id++] = src1->elems[i1++];
+    }
+  if (i1 < src1->nelem)
+    {
+      memcpy (dest->elems + id, src1->elems + i1,
+	     (src1->nelem - i1) * sizeof (int));
+      id += src1->nelem - i1;
+    }
+  else if (i2 < src2->nelem)
+    {
+      memcpy (dest->elems + id, src2->elems + i2,
+	     (src2->nelem - i2) * sizeof (int));
+      id += src2->nelem - i2;
+    }
+  dest->nelem = id;
+  return REG_NOERROR;
+}
+
+/* Calculate the union set of the sets DEST and SRC. And store it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_merge (re_node_set *dest, const re_node_set *src)
+{
+  int is, id, sbase, delta;
+  if (src == NULL || src->nelem == 0)
+    return REG_NOERROR;
+  if (dest->alloc < 2 * src->nelem + dest->nelem)
+    {
+      int new_alloc = 2 * (src->nelem + dest->alloc);
+      int *new_buffer = re_realloc (dest->elems, int, new_alloc);
+      if (BE (new_buffer == NULL, 0))
+	return REG_ESPACE;
+      dest->elems = new_buffer;
+      dest->alloc = new_alloc;
+    }
+
+  if (BE (dest->nelem == 0, 0))
+    {
+      dest->nelem = src->nelem;
+      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
+      return REG_NOERROR;
+    }
+
+  /* Copy into the top of DEST the items of SRC that are not
+     found in DEST.  Maybe we could binary search in DEST?  */
+  for (sbase = dest->nelem + 2 * src->nelem,
+       is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; )
+    {
+      if (dest->elems[id] == src->elems[is])
+        is--, id--;
+      else if (dest->elems[id] < src->elems[is])
+        dest->elems[--sbase] = src->elems[is--];
+      else /* if (dest->elems[id] > src->elems[is]) */
+        --id;
+    }
+
+  if (is >= 0)
+    {
+      /* If DEST is exhausted, the remaining items of SRC must be unique.  */
+      sbase -= is + 1;
+      memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int));
+    }
+
+  id = dest->nelem - 1;
+  is = dest->nelem + 2 * src->nelem - 1;
+  delta = is - sbase + 1;
+  if (delta == 0)
+    return REG_NOERROR;
+
+  /* Now copy.  When DELTA becomes zero, the remaining
+     DEST elements are already in place.  */
+  dest->nelem += delta;
+  for (;;)
+    {
+      if (dest->elems[is] > dest->elems[id])
+        {
+	  /* Copy from the top.  */
+          dest->elems[id + delta--] = dest->elems[is--];
+	  if (delta == 0)
+	    break;
+	}
+      else
+        {
+          /* Slide from the bottom.  */
+          dest->elems[id + delta] = dest->elems[id];
+	  if (--id < 0)
+	    {
+	      /* Copy remaining SRC elements.  */
+	      memcpy (dest->elems, dest->elems + sbase,
+	              delta * sizeof (int));
+	      break;
+	    }
+	}
+    }
+
+  return REG_NOERROR;
+}
+
+/* Insert the new element ELEM to the re_node_set* SET.
+   SET should not already have ELEM.
+   return -1 if an error is occured, return 1 otherwise.  */
+
+static int
+internal_function
+re_node_set_insert (re_node_set *set, int elem)
+{
+  int idx;
+  /* In case the set is empty.  */
+  if (set->alloc == 0)
+    {
+      if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
+	return 1;
+      else
+	return -1;
+    }
+
+  if (BE (set->nelem, 0) == 0)
+    {
+      /* We already guaranteed above that set->alloc != 0.  */
+      set->elems[0] = elem;
+      ++set->nelem;
+      return 1;
+    }
+
+  /* Realloc if we need.  */
+  if (set->alloc == set->nelem)
+    {
+      int *new_elems;
+      set->alloc = set->alloc * 2;
+      new_elems = re_realloc (set->elems, int, set->alloc);
+      if (BE (new_elems == NULL, 0))
+	return -1;
+      set->elems = new_elems;
+    }
+
+  /* Move the elements which follows the new element.  Test the
+     first element separately to skip a check in the inner loop.  */
+  if (elem < set->elems[0])
+    {
+      idx = 0;
+      for (idx = set->nelem; idx > 0; idx--)
+        set->elems[idx] = set->elems[idx - 1];
+    }
+  else
+    {
+      for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
+        set->elems[idx] = set->elems[idx - 1];
+    }
+
+  /* Insert the new element.  */
+  set->elems[idx] = elem;
+  ++set->nelem;
+  return 1;
+}
+
+/* Insert the new element ELEM to the re_node_set* SET.
+   SET should not already have any element greater than or equal to ELEM.
+   Return -1 if an error is occured, return 1 otherwise.  */
+
+static int
+internal_function
+re_node_set_insert_last (re_node_set *set, int elem)
+{
+  /* Realloc if we need.  */
+  if (set->alloc == set->nelem)
+    {
+      int *new_elems;
+      set->alloc = (set->alloc + 1) * 2;
+      new_elems = re_realloc (set->elems, int, set->alloc);
+      if (BE (new_elems == NULL, 0))
+	return -1;
+      set->elems = new_elems;
+    }
+
+  /* Insert the new element.  */
+  set->elems[set->nelem++] = elem;
+  return 1;
+}
+
+/* Compare two node sets SET1 and SET2.
+   return 1 if SET1 and SET2 are equivalent, return 0 otherwise.  */
+
+static int
+internal_function __attribute ((pure))
+re_node_set_compare (const re_node_set *set1, const re_node_set *set2)
+{
+  int i;
+  if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
+    return 0;
+  for (i = set1->nelem ; --i >= 0 ; )
+    if (set1->elems[i] != set2->elems[i])
+      return 0;
+  return 1;
+}
+
+/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise.  */
+
+static int
+internal_function __attribute ((pure))
+re_node_set_contains (const re_node_set *set, int elem)
+{
+  unsigned int idx, right, mid;
+  if (set->nelem <= 0)
+    return 0;
+
+  /* Binary search the element.  */
+  idx = 0;
+  right = set->nelem - 1;
+  while (idx < right)
+    {
+      mid = (idx + right) / 2;
+      if (set->elems[mid] < elem)
+	idx = mid + 1;
+      else
+	right = mid;
+    }
+  return set->elems[idx] == elem ? idx + 1 : 0;
+}
+
+static void
+internal_function
+re_node_set_remove_at (re_node_set *set, int idx)
+{
+  if (idx < 0 || idx >= set->nelem)
+    return;
+  --set->nelem;
+  for (; idx < set->nelem; idx++)
+    set->elems[idx] = set->elems[idx + 1];
+}
+
+
+
+/* Add the token TOKEN to dfa->nodes, and return the index of the token.
+   Or return -1, if an error will be occured.  */
+
+static int
+internal_function
+re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
+{
+  int type = token.type;
+  if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
+    {
+      size_t new_nodes_alloc = dfa->nodes_alloc * 2;
+      int *new_nexts, *new_indices;
+      re_node_set *new_edests, *new_eclosures;
+      re_token_t *new_nodes;
+
+      /* Avoid overflows.  */
+      if (BE (new_nodes_alloc < dfa->nodes_alloc, 0))
+	return -1;
+
+      new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
+      if (BE (new_nodes == NULL, 0))
+	return -1;
+      dfa->nodes = new_nodes;
+      new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);
+      new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);
+      new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
+      new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
+      if (BE (new_nexts == NULL || new_indices == NULL
+	      || new_edests == NULL || new_eclosures == NULL, 0))
+	return -1;
+      dfa->nexts = new_nexts;
+      dfa->org_indices = new_indices;
+      dfa->edests = new_edests;
+      dfa->eclosures = new_eclosures;
+      dfa->nodes_alloc = new_nodes_alloc;
+    }
+  dfa->nodes[dfa->nodes_len] = token;
+  dfa->nodes[dfa->nodes_len].constraint = 0;
+#ifdef RE_ENABLE_I18N
+  dfa->nodes[dfa->nodes_len].accept_mb =
+    (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
+#endif
+  dfa->nexts[dfa->nodes_len] = -1;
+  re_node_set_init_empty (dfa->edests + dfa->nodes_len);
+  re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
+  return dfa->nodes_len++;
+}
+
+static inline unsigned int
+internal_function
+calc_state_hash (const re_node_set *nodes, unsigned int context)
+{
+  unsigned int hash = nodes->nelem + context;
+  int i;
+  for (i = 0 ; i < nodes->nelem ; i++)
+    hash += nodes->elems[i];
+  return hash;
+}
+
+/* Search for the state whose node_set is equivalent to NODES.
+   Return the pointer to the state, if we found it in the DFA.
+   Otherwise create the new one and return it.  In case of an error
+   return NULL and set the error code in ERR.
+   Note: - We assume NULL as the invalid state, then it is possible that
+	   return value is NULL and ERR is REG_NOERROR.
+	 - We never return non-NULL value in case of any errors, it is for
+	   optimization.  */
+
+static re_dfastate_t *
+internal_function
+re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
+		  const re_node_set *nodes)
+{
+  unsigned int hash;
+  re_dfastate_t *new_state;
+  struct re_state_table_entry *spot;
+  int i;
+  if (BE (nodes->nelem == 0, 0))
+    {
+      *err = REG_NOERROR;
+      return NULL;
+    }
+  hash = calc_state_hash (nodes, 0);
+  spot = dfa->state_table + (hash & dfa->state_hash_mask);
+
+  for (i = 0 ; i < spot->num ; i++)
+    {
+      re_dfastate_t *state = spot->array[i];
+      if (hash != state->hash)
+	continue;
+      if (re_node_set_compare (&state->nodes, nodes))
+	return state;
+    }
+
+  /* There are no appropriate state in the dfa, create the new one.  */
+  new_state = create_ci_newstate (dfa, nodes, hash);
+  if (BE (new_state == NULL, 0))
+    *err = REG_ESPACE;
+
+  return new_state;
+}
+
+/* Search for the state whose node_set is equivalent to NODES and
+   whose context is equivalent to CONTEXT.
+   Return the pointer to the state, if we found it in the DFA.
+   Otherwise create the new one and return it.  In case of an error
+   return NULL and set the error code in ERR.
+   Note: - We assume NULL as the invalid state, then it is possible that
+	   return value is NULL and ERR is REG_NOERROR.
+	 - We never return non-NULL value in case of any errors, it is for
+	   optimization.  */
+
+static re_dfastate_t *
+internal_function
+re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
+			  const re_node_set *nodes, unsigned int context)
+{
+  unsigned int hash;
+  re_dfastate_t *new_state;
+  struct re_state_table_entry *spot;
+  int i;
+  if (nodes->nelem == 0)
+    {
+      *err = REG_NOERROR;
+      return NULL;
+    }
+  hash = calc_state_hash (nodes, context);
+  spot = dfa->state_table + (hash & dfa->state_hash_mask);
+
+  for (i = 0 ; i < spot->num ; i++)
+    {
+      re_dfastate_t *state = spot->array[i];
+      if (state->hash == hash
+	  && state->context == context
+	  && re_node_set_compare (state->entrance_nodes, nodes))
+	return state;
+    }
+  /* There are no appropriate state in `dfa', create the new one.  */
+  new_state = create_cd_newstate (dfa, nodes, context, hash);
+  if (BE (new_state == NULL, 0))
+    *err = REG_ESPACE;
+
+  return new_state;
+}
+
+/* Finish initialization of the new state NEWSTATE, and using its hash value
+   HASH put in the appropriate bucket of DFA's state table.  Return value
+   indicates the error code if failed.  */
+
+static reg_errcode_t
+register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
+		unsigned int hash)
+{
+  struct re_state_table_entry *spot;
+  reg_errcode_t err;
+  int i;
+
+  newstate->hash = hash;
+  err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);
+  if (BE (err != REG_NOERROR, 0))
+    return REG_ESPACE;
+  for (i = 0; i < newstate->nodes.nelem; i++)
+    {
+      int elem = newstate->nodes.elems[i];
+      if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
+        re_node_set_insert_last (&newstate->non_eps_nodes, elem);
+    }
+
+  spot = dfa->state_table + (hash & dfa->state_hash_mask);
+  if (BE (spot->alloc <= spot->num, 0))
+    {
+      int new_alloc = 2 * spot->num + 2;
+      re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
+					      new_alloc);
+      if (BE (new_array == NULL, 0))
+	return REG_ESPACE;
+      spot->array = new_array;
+      spot->alloc = new_alloc;
+    }
+  spot->array[spot->num++] = newstate;
+  return REG_NOERROR;
+}
+
+static void
+free_state (re_dfastate_t *state)
+{
+  re_node_set_free (&state->non_eps_nodes);
+  re_node_set_free (&state->inveclosure);
+  if (state->entrance_nodes != &state->nodes)
+    {
+      re_node_set_free (state->entrance_nodes);
+      re_free (state->entrance_nodes);
+    }
+  re_node_set_free (&state->nodes);
+  re_free (state->word_trtable);
+  re_free (state->trtable);
+  re_free (state);
+}
+
+/* Create the new state which is independ of contexts.
+   Return the new state if succeeded, otherwise return NULL.  */
+
+static re_dfastate_t *
+internal_function
+create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
+		    unsigned int hash)
+{
+  int i;
+  reg_errcode_t err;
+  re_dfastate_t *newstate;
+
+  newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+  if (BE (newstate == NULL, 0))
+    return NULL;
+  err = re_node_set_init_copy (&newstate->nodes, nodes);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      re_free (newstate);
+      return NULL;
+    }
+
+  newstate->entrance_nodes = &newstate->nodes;
+  for (i = 0 ; i < nodes->nelem ; i++)
+    {
+      re_token_t *node = dfa->nodes + nodes->elems[i];
+      re_token_type_t type = node->type;
+      if (type == CHARACTER && !node->constraint)
+	continue;
+#ifdef RE_ENABLE_I18N
+      newstate->accept_mb |= node->accept_mb;
+#endif /* RE_ENABLE_I18N */
+
+      /* If the state has the halt node, the state is a halt state.  */
+      if (type == END_OF_RE)
+	newstate->halt = 1;
+      else if (type == OP_BACK_REF)
+	newstate->has_backref = 1;
+      else if (type == ANCHOR || node->constraint)
+	newstate->has_constraint = 1;
+    }
+  err = register_state (dfa, newstate, hash);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_state (newstate);
+      newstate = NULL;
+    }
+  return newstate;
+}
+
+/* Create the new state which is depend on the context CONTEXT.
+   Return the new state if succeeded, otherwise return NULL.  */
+
+static re_dfastate_t *
+internal_function
+create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
+		    unsigned int context, unsigned int hash)
+{
+  int i, nctx_nodes = 0;
+  reg_errcode_t err;
+  re_dfastate_t *newstate;
+
+  newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+  if (BE (newstate == NULL, 0))
+    return NULL;
+  err = re_node_set_init_copy (&newstate->nodes, nodes);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      re_free (newstate);
+      return NULL;
+    }
+
+  newstate->context = context;
+  newstate->entrance_nodes = &newstate->nodes;
+
+  for (i = 0 ; i < nodes->nelem ; i++)
+    {
+      unsigned int constraint = 0;
+      re_token_t *node = dfa->nodes + nodes->elems[i];
+      re_token_type_t type = node->type;
+      if (node->constraint)
+	constraint = node->constraint;
+
+      if (type == CHARACTER && !constraint)
+	continue;
+#ifdef RE_ENABLE_I18N
+      newstate->accept_mb |= node->accept_mb;
+#endif /* RE_ENABLE_I18N */
+
+      /* If the state has the halt node, the state is a halt state.  */
+      if (type == END_OF_RE)
+	newstate->halt = 1;
+      else if (type == OP_BACK_REF)
+	newstate->has_backref = 1;
+      else if (type == ANCHOR)
+	constraint = node->opr.ctx_type;
+
+      if (constraint)
+	{
+	  if (newstate->entrance_nodes == &newstate->nodes)
+	    {
+	      newstate->entrance_nodes = re_malloc (re_node_set, 1);
+	      if (BE (newstate->entrance_nodes == NULL, 0))
+		{
+		  free_state (newstate);
+		  return NULL;
+		}
+	      re_node_set_init_copy (newstate->entrance_nodes, nodes);
+	      nctx_nodes = 0;
+	      newstate->has_constraint = 1;
+	    }
+
+	  if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
+	    {
+	      re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
+	      ++nctx_nodes;
+	    }
+	}
+    }
+  err = register_state (dfa, newstate, hash);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_state (newstate);
+      newstate = NULL;
+    }
+  return  newstate;
+}
Index: /tags/kBuild-0.1.4/src/sed/lib/regex_internal.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/regex_internal.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/regex_internal.h	(revision 1780)
@@ -0,0 +1,780 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   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 _REGEX_INTERNAL_H
+#define _REGEX_INTERNAL_H 1
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
+# include <langinfo.h>
+#endif
+#if defined HAVE_LOCALE_H || defined _LIBC
+# include <locale.h>
+#endif
+#if defined HAVE_WCHAR_H || defined _LIBC
+# include <wchar.h>
+#endif /* HAVE_WCHAR_H || _LIBC */
+#if defined HAVE_WCTYPE_H || defined _LIBC
+# include <wctype.h>
+#endif /* HAVE_WCTYPE_H || _LIBC */
+#if defined HAVE_STDBOOL_H || defined _LIBC
+# include <stdbool.h>
+#endif /* HAVE_STDBOOL_H || _LIBC */
+#if defined _LIBC
+# include <bits/libc-lock.h>
+#else
+# define __libc_lock_define(CLASS,NAME)
+# define __libc_lock_init(NAME) do { } while (0)
+# define __libc_lock_lock(NAME) do { } while (0)
+# define __libc_lock_unlock(NAME) do { } while (0)
+#endif
+
+/* In case that the system doesn't have isblank().  */
+#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank
+# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
+#endif
+
+#ifdef _LIBC
+# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
+#  define _RE_DEFINE_LOCALE_FUNCTIONS 1
+#   include <locale/localeinfo.h>
+#   include <locale/elem-hash.h>
+#   include <locale/coll-lookup.h>
+# endif
+#endif
+
+/* This is for other GNU distributions with internationalized messages.  */
+#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
+# include <libintl.h>
+# ifdef _LIBC
+#  undef gettext
+#  define gettext(msgid) \
+  INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES)
+# endif
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef gettext_noop
+/* This define is so xgettext can find the internationalizable
+   strings.  */
+# define gettext_noop(String) String
+#endif
+
+#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC
+# if defined(__OS2__) /* setlocale() misbehaves in LIBC 0.6.1 and earlier, breaking /[a-z]/. */
+#  if defined(__KLIBC_VERSION__)
+#   if __KLIBC_VERSION__ >= 0x00060002
+#    define RE_ENABLE_I18N
+#   endif
+#  endif
+# else
+# define RE_ENABLE_I18N
+# endif
+#endif
+
+#if __GNUC__ >= 3
+# define BE(expr, val) __builtin_expect (expr, val)
+#else
+# define BE(expr, val) (expr)
+# ifndef inline /* bird: silly since the rest of sed depends on this working.. */
+#  define inline
+# endif
+#endif
+
+/* Number of single byte character.  */
+#define SBC_MAX 256
+
+#define COLL_ELEM_LEN_MAX 8
+
+/* The character which represents newline.  */
+#define NEWLINE_CHAR '\n'
+#define WIDE_NEWLINE_CHAR L'\n'
+
+/* Rename to standard API for using out of glibc.  */
+#ifndef _LIBC
+# define __wctype wctype
+# define __iswctype iswctype
+# define __btowc btowc
+# ifndef __mempcpy /* keep quiet if string.h defines it (bird) */
+# define __mempcpy mempcpy
+# endif
+# define __wcrtomb wcrtomb
+# define __regfree regfree
+# define attribute_hidden
+#endif /* not _LIBC */
+
+#ifdef __GNUC__
+# define __attribute(arg) __attribute__ (arg)
+#else
+# define __attribute(arg)
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)-1)
+#endif
+
+extern const char __re_error_msgid[] attribute_hidden;
+extern const size_t __re_error_msgid_idx[] attribute_hidden;
+
+/* An integer used to represent a set of bits.  It must be unsigned,
+   and must be at least as wide as unsigned int.  */
+typedef unsigned long int bitset_word_t;
+/* All bits set in a bitset_word_t.  */
+#define BITSET_WORD_MAX ULONG_MAX
+/* Number of bits in a bitset_word_t.  */
+#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT)
+/* Number of bitset_word_t in a bit_set.  */
+#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS)
+typedef bitset_word_t bitset_t[BITSET_WORDS];
+typedef bitset_word_t *re_bitset_ptr_t;
+typedef const bitset_word_t *re_const_bitset_ptr_t;
+
+#define bitset_set(set,i) \
+  (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS)
+#define bitset_clear(set,i) \
+  (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS))
+#define bitset_contain(set,i) \
+  (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS))
+#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t))
+#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t))
+#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t))
+
+#define PREV_WORD_CONSTRAINT 0x0001
+#define PREV_NOTWORD_CONSTRAINT 0x0002
+#define NEXT_WORD_CONSTRAINT 0x0004
+#define NEXT_NOTWORD_CONSTRAINT 0x0008
+#define PREV_NEWLINE_CONSTRAINT 0x0010
+#define NEXT_NEWLINE_CONSTRAINT 0x0020
+#define PREV_BEGBUF_CONSTRAINT 0x0040
+#define NEXT_ENDBUF_CONSTRAINT 0x0080
+#define WORD_DELIM_CONSTRAINT 0x0100
+#define NOT_WORD_DELIM_CONSTRAINT 0x0200
+
+typedef enum
+{
+  INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
+  WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
+  WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
+  INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
+  LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
+  LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
+  BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
+  BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
+  WORD_DELIM = WORD_DELIM_CONSTRAINT,
+  NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
+} re_context_type;
+
+typedef struct
+{
+  int alloc;
+  int nelem;
+  int *elems;
+} re_node_set;
+
+typedef enum
+{
+  NON_TYPE = 0,
+
+  /* Node type, These are used by token, node, tree.  */
+  CHARACTER = 1,
+  END_OF_RE = 2,
+  SIMPLE_BRACKET = 3,
+  OP_BACK_REF = 4,
+  OP_PERIOD = 5,
+#ifdef RE_ENABLE_I18N
+  COMPLEX_BRACKET = 6,
+  OP_UTF8_PERIOD = 7,
+#endif /* RE_ENABLE_I18N */
+
+  /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used
+     when the debugger shows values of this enum type.  */
+#define EPSILON_BIT 8
+  OP_OPEN_SUBEXP = EPSILON_BIT | 0,
+  OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
+  OP_ALT = EPSILON_BIT | 2,
+  OP_DUP_ASTERISK = EPSILON_BIT | 3,
+  ANCHOR = EPSILON_BIT | 4,
+
+  /* Tree type, these are used only by tree. */
+  CONCAT = 16,
+  SUBEXP = 17,
+
+  /* Token type, these are used only by token.  */
+  OP_DUP_PLUS = 18,
+  OP_DUP_QUESTION,
+  OP_OPEN_BRACKET,
+  OP_CLOSE_BRACKET,
+  OP_CHARSET_RANGE,
+  OP_OPEN_DUP_NUM,
+  OP_CLOSE_DUP_NUM,
+  OP_NON_MATCH_LIST,
+  OP_OPEN_COLL_ELEM,
+  OP_CLOSE_COLL_ELEM,
+  OP_OPEN_EQUIV_CLASS,
+  OP_CLOSE_EQUIV_CLASS,
+  OP_OPEN_CHAR_CLASS,
+  OP_CLOSE_CHAR_CLASS,
+  OP_WORD,
+  OP_NOTWORD,
+  OP_SPACE,
+  OP_NOTSPACE,
+  BACK_SLASH
+
+} re_token_type_t;
+
+#ifdef RE_ENABLE_I18N
+typedef struct
+{
+  /* Multibyte characters.  */
+  wchar_t *mbchars;
+
+  /* Collating symbols.  */
+# ifdef _LIBC
+  int32_t *coll_syms;
+# endif
+
+  /* Equivalence classes. */
+# ifdef _LIBC
+  int32_t *equiv_classes;
+# endif
+
+  /* Range expressions. */
+# ifdef _LIBC
+  uint32_t *range_starts;
+  uint32_t *range_ends;
+# else /* not _LIBC */
+  wchar_t *range_starts;
+  wchar_t *range_ends;
+# endif /* not _LIBC */
+
+  /* Character classes. */
+  wctype_t *char_classes;
+
+  /* If this character set is the non-matching list.  */
+  unsigned int non_match : 1;
+
+  /* # of multibyte characters.  */
+  int nmbchars;
+
+  /* # of collating symbols.  */
+  int ncoll_syms;
+
+  /* # of equivalence classes. */
+  int nequiv_classes;
+
+  /* # of range expressions. */
+  int nranges;
+
+  /* # of character classes. */
+  int nchar_classes;
+} re_charset_t;
+#endif /* RE_ENABLE_I18N */
+
+typedef struct
+{
+  union
+  {
+    unsigned char c;		/* for CHARACTER */
+    re_bitset_ptr_t sbcset;	/* for SIMPLE_BRACKET */
+#ifdef RE_ENABLE_I18N
+    re_charset_t *mbcset;	/* for COMPLEX_BRACKET */
+#endif /* RE_ENABLE_I18N */
+    int idx;			/* for BACK_REF */
+    re_context_type ctx_type;	/* for ANCHOR */
+  } opr;
+#if __GNUC__ >= 2
+  re_token_type_t type : 8;
+#else
+  re_token_type_t type;
+#endif
+  unsigned int constraint : 10;	/* context constraint */
+  unsigned int duplicated : 1;
+  unsigned int opt_subexp : 1;
+#ifdef RE_ENABLE_I18N
+  unsigned int accept_mb : 1;
+  /* These 2 bits can be moved into the union if needed (e.g. if running out
+     of bits; move opr.c to opr.c.c and move the flags to opr.c.flags).  */
+  unsigned int mb_partial : 1;
+#endif
+  unsigned int word_char : 1;
+} re_token_t;
+
+#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
+
+struct re_string_t
+{
+  /* Indicate the raw buffer which is the original string passed as an
+     argument of regexec(), re_search(), etc..  */
+  const unsigned char *raw_mbs;
+  /* Store the multibyte string.  In case of "case insensitive mode" like
+     REG_ICASE, upper cases of the string are stored, otherwise MBS points
+     the same address that RAW_MBS points.  */
+  unsigned char *mbs;
+#ifdef RE_ENABLE_I18N
+  /* Store the wide character string which is corresponding to MBS.  */
+  wint_t *wcs;
+  int *offsets;
+  mbstate_t cur_state;
+#endif
+  /* Index in RAW_MBS.  Each character mbs[i] corresponds to
+     raw_mbs[raw_mbs_idx + i].  */
+  int raw_mbs_idx;
+  /* The length of the valid characters in the buffers.  */
+  int valid_len;
+  /* The corresponding number of bytes in raw_mbs array.  */
+  int valid_raw_len;
+  /* The length of the buffers MBS and WCS.  */
+  int bufs_len;
+  /* The index in MBS, which is updated by re_string_fetch_byte.  */
+  int cur_idx;
+  /* length of RAW_MBS array.  */
+  int raw_len;
+  /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN.  */
+  int len;
+  /* End of the buffer may be shorter than its length in the cases such
+     as re_match_2, re_search_2.  Then, we use STOP for end of the buffer
+     instead of LEN.  */
+  int raw_stop;
+  /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS.  */
+  int stop;
+
+  /* The context of mbs[0].  We store the context independently, since
+     the context of mbs[0] may be different from raw_mbs[0], which is
+     the beginning of the input string.  */
+  unsigned int tip_context;
+  /* The translation passed as a part of an argument of re_compile_pattern.  */
+  RE_TRANSLATE_TYPE trans;
+  /* Copy of re_dfa_t's word_char.  */
+  re_const_bitset_ptr_t word_char;
+  /* 1 if REG_ICASE.  */
+  unsigned char icase;
+  unsigned char is_utf8;
+  unsigned char map_notascii;
+  unsigned char mbs_allocated;
+  unsigned char offsets_needed;
+  unsigned char newline_anchor;
+  unsigned char word_ops_used;
+  int mb_cur_max;
+};
+typedef struct re_string_t re_string_t;
+
+
+struct re_dfa_t;
+typedef struct re_dfa_t re_dfa_t;
+
+#ifndef _LIBC
+# ifdef __i386__
+#  ifdef __OS2__
+#   define internal_function   __attribute ((regparm (3)))
+#  else
+#   define internal_function   __attribute ((regparm (3), stdcall))
+#  endif
+# else
+#  define internal_function
+# endif
+#endif
+
+static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
+						int new_buf_len)
+     internal_function;
+#ifdef RE_ENABLE_I18N
+static void build_wcs_buffer (re_string_t *pstr) internal_function;
+static int build_wcs_upper_buffer (re_string_t *pstr) internal_function;
+#endif /* RE_ENABLE_I18N */
+static void build_upper_buffer (re_string_t *pstr) internal_function;
+static void re_string_translate_buffer (re_string_t *pstr) internal_function;
+static unsigned int re_string_context_at (const re_string_t *input, int idx,
+					  int eflags)
+     internal_function __attribute ((pure));
+#define re_string_peek_byte(pstr, offset) \
+  ((pstr)->mbs[(pstr)->cur_idx + offset])
+#define re_string_fetch_byte(pstr) \
+  ((pstr)->mbs[(pstr)->cur_idx++])
+#define re_string_first_byte(pstr, idx) \
+  ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)
+#define re_string_is_single_byte_char(pstr, idx) \
+  ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \
+				|| (pstr)->wcs[(idx) + 1] != WEOF))
+#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
+#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
+#define re_string_get_buffer(pstr) ((pstr)->mbs)
+#define re_string_length(pstr) ((pstr)->len)
+#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
+#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
+#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
+
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#elif HAVE_MALLOC_H
+# include <malloc.h>
+#endif
+
+#ifndef _LIBC
+# if HAVE_ALLOCA
+/* The OS usually guarantees only one guard page at the bottom of the stack,
+   and a page size can be as small as 4096 bytes.  So we cannot safely
+   allocate anything larger than 4096 bytes.  Also care for the possibility
+   of a few compiler-allocated temporary stack slots.  */
+#  define __libc_use_alloca(n) ((n) < 4032)
+# else
+/* alloca is implemented with malloc, so just use malloc.  */
+#  define __libc_use_alloca(n) 0
+# endif
+#endif
+
+#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
+#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
+#define re_free(p) free (p)
+
+struct bin_tree_t
+{
+  struct bin_tree_t *parent;
+  struct bin_tree_t *left;
+  struct bin_tree_t *right;
+  struct bin_tree_t *first;
+  struct bin_tree_t *next;
+
+  re_token_t token;
+
+  /* `node_idx' is the index in dfa->nodes, if `type' == 0.
+     Otherwise `type' indicate the type of this node.  */
+  int node_idx;
+};
+typedef struct bin_tree_t bin_tree_t;
+
+#define BIN_TREE_STORAGE_SIZE \
+  ((1024 - sizeof (void *)) / sizeof (bin_tree_t))
+
+struct bin_tree_storage_t
+{
+  struct bin_tree_storage_t *next;
+  bin_tree_t data[BIN_TREE_STORAGE_SIZE];
+};
+typedef struct bin_tree_storage_t bin_tree_storage_t;
+
+#define CONTEXT_WORD 1
+#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
+#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
+#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
+
+#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
+#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
+#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
+#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
+#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
+
+#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
+#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
+#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_')
+#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
+
+#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
+ ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
+  || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
+  || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
+  || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
+
+#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
+ ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
+  || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
+  || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
+  || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
+
+struct re_dfastate_t
+{
+  unsigned int hash;
+  re_node_set nodes;
+  re_node_set non_eps_nodes;
+  re_node_set inveclosure;
+  re_node_set *entrance_nodes;
+  struct re_dfastate_t **trtable, **word_trtable;
+  unsigned int context : 4;
+  unsigned int halt : 1;
+  /* If this state can accept `multi byte'.
+     Note that we refer to multibyte characters, and multi character
+     collating elements as `multi byte'.  */
+  unsigned int accept_mb : 1;
+  /* If this state has backreference node(s).  */
+  unsigned int has_backref : 1;
+  unsigned int has_constraint : 1;
+};
+typedef struct re_dfastate_t re_dfastate_t;
+
+struct re_state_table_entry
+{
+  int num;
+  int alloc;
+  re_dfastate_t **array;
+};
+
+/* Array type used in re_sub_match_last_t and re_sub_match_top_t.  */
+
+typedef struct
+{
+  int next_idx;
+  int alloc;
+  re_dfastate_t **array;
+} state_array_t;
+
+/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP.  */
+
+typedef struct
+{
+  int node;
+  int str_idx; /* The position NODE match at.  */
+  state_array_t path;
+} re_sub_match_last_t;
+
+/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
+   And information about the node, whose type is OP_CLOSE_SUBEXP,
+   corresponding to NODE is stored in LASTS.  */
+
+typedef struct
+{
+  int str_idx;
+  int node;
+  state_array_t *path;
+  int alasts; /* Allocation size of LASTS.  */
+  int nlasts; /* The number of LASTS.  */
+  re_sub_match_last_t **lasts;
+} re_sub_match_top_t;
+
+struct re_backref_cache_entry
+{
+  int node;
+  int str_idx;
+  int subexp_from;
+  int subexp_to;
+  char more;
+  char unused;
+  unsigned short int eps_reachable_subexps_map;
+};
+
+typedef struct
+{
+  /* The string object corresponding to the input string.  */
+  re_string_t input;
+#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+  const re_dfa_t *const dfa;
+#else
+  const re_dfa_t *dfa;
+#endif
+  /* EFLAGS of the argument of regexec.  */
+  int eflags;
+  /* Where the matching ends.  */
+  int match_last;
+  int last_node;
+  /* The state log used by the matcher.  */
+  re_dfastate_t **state_log;
+  int state_log_top;
+  /* Back reference cache.  */
+  int nbkref_ents;
+  int abkref_ents;
+  struct re_backref_cache_entry *bkref_ents;
+  int max_mb_elem_len;
+  int nsub_tops;
+  int asub_tops;
+  re_sub_match_top_t **sub_tops;
+} re_match_context_t;
+
+typedef struct
+{
+  re_dfastate_t **sifted_states;
+  re_dfastate_t **limited_states;
+  int last_node;
+  int last_str_idx;
+  re_node_set limits;
+} re_sift_context_t;
+
+struct re_fail_stack_ent_t
+{
+  int idx;
+  int node;
+  regmatch_t *regs;
+  re_node_set eps_via_nodes;
+};
+
+struct re_fail_stack_t
+{
+  int num;
+  int alloc;
+  struct re_fail_stack_ent_t *stack;
+};
+
+struct re_dfa_t
+{
+  re_token_t *nodes;
+  size_t nodes_alloc;
+  size_t nodes_len;
+  int *nexts;
+  int *org_indices;
+  re_node_set *edests;
+  re_node_set *eclosures;
+  re_node_set *inveclosures;
+  struct re_state_table_entry *state_table;
+  re_dfastate_t *init_state;
+  re_dfastate_t *init_state_word;
+  re_dfastate_t *init_state_nl;
+  re_dfastate_t *init_state_begbuf;
+  bin_tree_t *str_tree;
+  bin_tree_storage_t *str_tree_storage;
+  re_bitset_ptr_t sb_char;
+  int str_tree_storage_idx;
+
+  /* number of subexpressions `re_nsub' is in regex_t.  */
+  unsigned int state_hash_mask;
+  int init_node;
+  int nbackref; /* The number of backreference in this dfa.  */
+
+  /* Bitmap expressing which backreference is used.  */
+  bitset_word_t used_bkref_map;
+  bitset_word_t completed_bkref_map;
+
+  unsigned int has_plural_match : 1;
+  /* If this dfa has "multibyte node", which is a backreference or
+     a node which can accept multibyte character or multi character
+     collating element.  */
+  unsigned int has_mb_node : 1;
+  unsigned int is_utf8 : 1;
+  unsigned int map_notascii : 1;
+  unsigned int word_ops_used : 1;
+  int mb_cur_max;
+  bitset_t word_char;
+  reg_syntax_t syntax;
+  int *subexp_map;
+#ifdef DEBUG
+  char* re_str;
+#endif
+  __libc_lock_define (, lock)
+};
+
+#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
+#define re_node_set_remove(set,id) \
+  (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
+#define re_node_set_empty(p) ((p)->nelem = 0)
+#define re_node_set_free(set) re_free ((set)->elems)
+
+
+
+typedef enum
+{
+  SB_CHAR,
+  MB_CHAR,
+  EQUIV_CLASS,
+  COLL_SYM,
+  CHAR_CLASS
+} bracket_elem_type;
+
+typedef struct
+{
+  bracket_elem_type type;
+  union
+  {
+    unsigned char ch;
+    unsigned char *name;
+    wchar_t wch;
+  } opr;
+} bracket_elem_t;
+
+
+/* Inline functions for bitset operation.  */
+static inline void
+bitset_not (bitset_t set)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+    set[bitset_i] = ~set[bitset_i];
+}
+
+static inline void
+bitset_merge (bitset_t dest, const bitset_t src)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+    dest[bitset_i] |= src[bitset_i];
+}
+
+static inline void
+bitset_mask (bitset_t dest, const bitset_t src)
+{
+  int bitset_i;
+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+    dest[bitset_i] &= src[bitset_i];
+}
+
+#ifdef RE_ENABLE_I18N
+/* Inline functions for re_string.  */
+static inline int
+internal_function __attribute ((pure))
+re_string_char_size_at (const re_string_t *pstr, int idx)
+{
+  int byte_idx;
+  if (pstr->mb_cur_max == 1)
+    return 1;
+  for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
+    if (pstr->wcs[idx + byte_idx] != WEOF)
+      break;
+  return byte_idx;
+}
+
+static inline wint_t
+internal_function __attribute ((pure))
+re_string_wchar_at (const re_string_t *pstr, int idx)
+{
+  if (pstr->mb_cur_max == 1)
+    return (wint_t) pstr->mbs[idx];
+  return (wint_t) pstr->wcs[idx];
+}
+
+static int
+internal_function __attribute ((pure))
+re_string_elem_size_at (const re_string_t *pstr, int idx)
+{
+# ifdef _LIBC
+  const unsigned char *p, *extra;
+  const int32_t *table, *indirect;
+  int32_t tmp;
+#  include <locale/weight.h>
+  uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+
+  if (nrules != 0)
+    {
+      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+      extra = (const unsigned char *)
+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+						_NL_COLLATE_INDIRECTMB);
+      p = pstr->mbs + idx;
+      tmp = findidx (&p);
+      return p - pstr->mbs - idx;
+    }
+  else
+# endif /* _LIBC */
+    return 1;
+}
+#endif /* RE_ENABLE_I18N */
+
+#endif /*  _REGEX_INTERNAL_H */
Index: /tags/kBuild-0.1.4/src/sed/lib/regexec.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/regexec.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/regexec.c	(revision 1780)
@@ -0,0 +1,4338 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   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.  */
+
+static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
+				     int n) internal_function;
+static void match_ctx_clean (re_match_context_t *mctx) internal_function;
+static void match_ctx_free (re_match_context_t *cache) internal_function;
+static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node,
+					  int str_idx, int from, int to)
+     internal_function;
+static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
+     internal_function;
+static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node,
+					   int str_idx) internal_function;
+static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,
+						   int node, int str_idx)
+     internal_function;
+static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
+			   re_dfastate_t **limited_sts, int last_node,
+			   int last_str_idx)
+     internal_function;
+static reg_errcode_t re_search_internal (const regex_t *preg,
+					 const char *string, int length,
+					 int start, int range, int stop,
+					 size_t nmatch, regmatch_t pmatch[],
+					 int eflags) internal_function;
+static int re_search_2_stub (struct re_pattern_buffer *bufp,
+			     const char *string1, int length1,
+			     const char *string2, int length2,
+			     int start, int range, struct re_registers *regs,
+			     int stop, int ret_len) internal_function;
+static int re_search_stub (struct re_pattern_buffer *bufp,
+			   const char *string, int length, int start,
+			   int range, int stop, struct re_registers *regs,
+			   int ret_len) internal_function;
+static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
+			      int nregs, int regs_allocated) internal_function;
+static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx)
+     internal_function;
+static int check_matching (re_match_context_t *mctx, int fl_longest_match,
+			   int *p_match_first) internal_function;
+static int check_halt_state_context (const re_match_context_t *mctx,
+				     const re_dfastate_t *state, int idx)
+     internal_function;
+static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
+			 regmatch_t *prev_idx_match, int cur_node,
+			 int cur_idx, int nmatch) internal_function;
+static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
+				      int str_idx, int dest_node, int nregs,
+				      regmatch_t *regs,
+				      re_node_set *eps_via_nodes)
+     internal_function;
+static reg_errcode_t set_regs (const regex_t *preg,
+			       const re_match_context_t *mctx,
+			       size_t nmatch, regmatch_t *pmatch,
+			       int fl_backtrack) internal_function;
+static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs)
+     internal_function;
+
+#ifdef RE_ENABLE_I18N
+static int sift_states_iter_mb (const re_match_context_t *mctx,
+				re_sift_context_t *sctx,
+				int node_idx, int str_idx, int max_str_idx)
+     internal_function;
+#endif /* RE_ENABLE_I18N */
+static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,
+					   re_sift_context_t *sctx)
+     internal_function;
+static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,
+					  re_sift_context_t *sctx, int str_idx,
+					  re_node_set *cur_dest)
+     internal_function;
+static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx,
+					      re_sift_context_t *sctx,
+					      int str_idx,
+					      re_node_set *dest_nodes)
+     internal_function;
+static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa,
+					    re_node_set *dest_nodes,
+					    const re_node_set *candidates)
+     internal_function;
+static int check_dst_limits (const re_match_context_t *mctx,
+			     re_node_set *limits,
+			     int dst_node, int dst_idx, int src_node,
+			     int src_idx) internal_function;
+static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx,
+					int boundaries, int subexp_idx,
+					int from_node, int bkref_idx)
+     internal_function;
+static int check_dst_limits_calc_pos (const re_match_context_t *mctx,
+				      int limit, int subexp_idx,
+				      int node, int str_idx,
+				      int bkref_idx) internal_function;
+static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa,
+					  re_node_set *dest_nodes,
+					  const re_node_set *candidates,
+					  re_node_set *limits,
+					  struct re_backref_cache_entry *bkref_ents,
+					  int str_idx) internal_function;
+static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx,
+					re_sift_context_t *sctx,
+					int str_idx, const re_node_set *candidates)
+     internal_function;
+static reg_errcode_t merge_state_array (const re_dfa_t *dfa,
+					re_dfastate_t **dst,
+					re_dfastate_t **src, int num)
+     internal_function;
+static re_dfastate_t *find_recover_state (reg_errcode_t *err,
+					 re_match_context_t *mctx) internal_function;
+static re_dfastate_t *transit_state (reg_errcode_t *err,
+				     re_match_context_t *mctx,
+				     re_dfastate_t *state) internal_function;
+static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,
+					    re_match_context_t *mctx,
+					    re_dfastate_t *next_state)
+     internal_function;
+static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
+						re_node_set *cur_nodes,
+						int str_idx) internal_function;
+#if 0
+static re_dfastate_t *transit_state_sb (reg_errcode_t *err,
+					re_match_context_t *mctx,
+					re_dfastate_t *pstate)
+     internal_function;
+#endif
+#ifdef RE_ENABLE_I18N
+static reg_errcode_t transit_state_mb (re_match_context_t *mctx,
+				       re_dfastate_t *pstate)
+     internal_function;
+#endif /* RE_ENABLE_I18N */
+static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,
+					  const re_node_set *nodes)
+     internal_function;
+static reg_errcode_t get_subexp (re_match_context_t *mctx,
+				 int bkref_node, int bkref_str_idx)
+     internal_function;
+static reg_errcode_t get_subexp_sub (re_match_context_t *mctx,
+				     const re_sub_match_top_t *sub_top,
+				     re_sub_match_last_t *sub_last,
+				     int bkref_node, int bkref_str)
+     internal_function;
+static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
+			     int subexp_idx, int type) internal_function;
+static reg_errcode_t check_arrival (re_match_context_t *mctx,
+				    state_array_t *path, int top_node,
+				    int top_str, int last_node, int last_str,
+				    int type) internal_function;
+static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx,
+						   int str_idx,
+						   re_node_set *cur_nodes,
+						   re_node_set *next_nodes)
+     internal_function;
+static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa,
+					       re_node_set *cur_nodes,
+					       int ex_subexp, int type)
+     internal_function;
+static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa,
+						   re_node_set *dst_nodes,
+						   int target, int ex_subexp,
+						   int type) internal_function;
+static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx,
+					 re_node_set *cur_nodes, int cur_str,
+					 int subexp_num, int type)
+     internal_function;
+static int build_trtable (const re_dfa_t *dfa,
+			  re_dfastate_t *state) internal_function;
+#ifdef RE_ENABLE_I18N
+static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
+				    const re_string_t *input, int idx)
+     internal_function;
+# ifdef _LIBC
+static unsigned int find_collation_sequence_value (const unsigned char *mbs,
+						   size_t name_len)
+     internal_function;
+# endif /* _LIBC */
+#endif /* RE_ENABLE_I18N */
+static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
+				       const re_dfastate_t *state,
+				       re_node_set *states_node,
+				       bitset_t *states_ch) internal_function;
+static int check_node_accept (const re_match_context_t *mctx,
+			      const re_token_t *node, int idx)
+     internal_function;
+static reg_errcode_t extend_buffers (re_match_context_t *mctx)
+     internal_function;
+
+
+/* Entry point for POSIX code.  */
+
+/* regexec searches for a given pattern, specified by PREG, in the
+   string STRING.
+
+   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
+   least NMATCH elements, and we set them to the offsets of the
+   corresponding matched substrings.
+
+   EFLAGS specifies `execution flags' which affect matching: if
+   REG_NOTBOL is set, then ^ does not match at the beginning of the
+   string; if REG_NOTEOL is set, then $ does not match at the end.
+
+   We return 0 if we find a match and REG_NOMATCH if not.  */
+
+int
+regexec (preg, string, nmatch, pmatch, eflags)
+    const regex_t *__restrict preg;
+    const char *__restrict string;
+    size_t nmatch;
+    regmatch_t pmatch[];
+    int eflags;
+{
+  reg_errcode_t err;
+  int start, length;
+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+
+  if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND))
+    return REG_BADPAT;
+
+  if (eflags & REG_STARTEND)
+    {
+      start = pmatch[0].rm_so;
+      length = pmatch[0].rm_eo;
+    }
+  else
+    {
+      start = 0;
+      length = strlen (string);
+    }
+
+  __libc_lock_lock (dfa->lock);
+  if (preg->no_sub)
+    err = re_search_internal (preg, string, length, start, length - start,
+			      length, 0, NULL, eflags);
+  else
+    err = re_search_internal (preg, string, length, start, length - start,
+			      length, nmatch, pmatch, eflags);
+  __libc_lock_unlock (dfa->lock);
+  return err != REG_NOERROR;
+}
+
+#ifdef _LIBC
+# include <shlib-compat.h>
+versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+__typeof__ (__regexec) __compat_regexec;
+
+int
+attribute_compat_text_section
+__compat_regexec (const regex_t *__restrict preg,
+		  const char *__restrict string, size_t nmatch,
+		  regmatch_t pmatch[], int eflags)
+{
+  return regexec (preg, string, nmatch, pmatch,
+		  eflags & (REG_NOTBOL | REG_NOTEOL));
+}
+compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
+# endif
+#endif
+
+/* Entry points for GNU code.  */
+
+/* re_match, re_search, re_match_2, re_search_2
+
+   The former two functions operate on STRING with length LENGTH,
+   while the later two operate on concatenation of STRING1 and STRING2
+   with lengths LENGTH1 and LENGTH2, respectively.
+
+   re_match() matches the compiled pattern in BUFP against the string,
+   starting at index START.
+
+   re_search() first tries matching at index START, then it tries to match
+   starting from index START + 1, and so on.  The last start position tried
+   is START + RANGE.  (Thus RANGE = 0 forces re_search to operate the same
+   way as re_match().)
+
+   The parameter STOP of re_{match,search}_2 specifies that no match exceeding
+   the first STOP characters of the concatenation of the strings should be
+   concerned.
+
+   If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
+   and all groups is stroed in REGS.  (For the "_2" variants, the offsets are
+   computed relative to the concatenation, not relative to the individual
+   strings.)
+
+   On success, re_match* functions return the length of the match, re_search*
+   return the position of the start of the match.  Return value -1 means no
+   match was found and -2 indicates an internal error.  */
+
+int
+re_match (bufp, string, length, start, regs)
+    struct re_pattern_buffer *bufp;
+    const char *string;
+    int length, start;
+    struct re_registers *regs;
+{
+  return re_search_stub (bufp, string, length, start, 0, length, regs, 1);
+}
+#ifdef _LIBC
+weak_alias (__re_match, re_match)
+#endif
+
+int
+re_search (bufp, string, length, start, range, regs)
+    struct re_pattern_buffer *bufp;
+    const char *string;
+    int length, start, range;
+    struct re_registers *regs;
+{
+  return re_search_stub (bufp, string, length, start, range, length, regs, 0);
+}
+#ifdef _LIBC
+weak_alias (__re_search, re_search)
+#endif
+
+int
+re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop)
+    struct re_pattern_buffer *bufp;
+    const char *string1, *string2;
+    int length1, length2, start, stop;
+    struct re_registers *regs;
+{
+  return re_search_2_stub (bufp, string1, length1, string2, length2,
+			   start, 0, regs, stop, 1);
+}
+#ifdef _LIBC
+weak_alias (__re_match_2, re_match_2)
+#endif
+
+int
+re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop)
+    struct re_pattern_buffer *bufp;
+    const char *string1, *string2;
+    int length1, length2, start, range, stop;
+    struct re_registers *regs;
+{
+  return re_search_2_stub (bufp, string1, length1, string2, length2,
+			   start, range, regs, stop, 0);
+}
+#ifdef _LIBC
+weak_alias (__re_search_2, re_search_2)
+#endif
+
+static int
+re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs,
+		  stop, ret_len)
+    struct re_pattern_buffer *bufp;
+    const char *string1, *string2;
+    int length1, length2, start, range, stop, ret_len;
+    struct re_registers *regs;
+{
+  const char *str;
+  int rval;
+  int len = length1 + length2;
+  int free_str = 0;
+
+  if (BE (length1 < 0 || length2 < 0 || stop < 0, 0))
+    return -2;
+
+  /* Concatenate the strings.  */
+  if (length2 > 0)
+    if (length1 > 0)
+      {
+	char *s = re_malloc (char, len);
+
+	if (BE (s == NULL, 0))
+	  return -2;
+#ifdef _LIBC
+	memcpy (__mempcpy (s, string1, length1), string2, length2);
+#else
+	memcpy (s, string1, length1);
+	memcpy (s + length1, string2, length2);
+#endif
+	str = s;
+	free_str = 1;
+      }
+    else
+      str = string2;
+  else
+    str = string1;
+
+  rval = re_search_stub (bufp, str, len, start, range, stop, regs,
+			 ret_len);
+  if (free_str)
+    re_free ((char *) str);
+  return rval;
+}
+
+/* The parameters have the same meaning as those of re_search.
+   Additional parameters:
+   If RET_LEN is nonzero the length of the match is returned (re_match style);
+   otherwise the position of the match is returned.  */
+
+static int
+re_search_stub (bufp, string, length, start, range, stop, regs, ret_len)
+    struct re_pattern_buffer *bufp;
+    const char *string;
+    int length, start, range, stop, ret_len;
+    struct re_registers *regs;
+{
+  reg_errcode_t result;
+  regmatch_t *pmatch;
+  int nregs, rval;
+  int eflags = 0;
+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
+
+  /* Check for out-of-range.  */
+  if (BE (start < 0 || start > length, 0))
+    return -1;
+  if (BE (start + range > length, 0))
+    range = length - start;
+  else if (BE (start + range < 0, 0))
+    range = -start;
+
+  __libc_lock_lock (dfa->lock);
+
+  eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
+  eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
+
+  /* Compile fastmap if we haven't yet.  */
+  if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate)
+    re_compile_fastmap (bufp);
+
+  if (BE (bufp->no_sub, 0))
+    regs = NULL;
+
+  /* We need at least 1 register.  */
+  if (regs == NULL)
+    nregs = 1;
+  else if (BE (bufp->regs_allocated == REGS_FIXED &&
+	       regs->num_regs < bufp->re_nsub + 1, 0))
+    {
+      nregs = regs->num_regs;
+      if (BE (nregs < 1, 0))
+	{
+	  /* Nothing can be copied to regs.  */
+	  regs = NULL;
+	  nregs = 1;
+	}
+    }
+  else
+    nregs = bufp->re_nsub + 1;
+  pmatch = re_malloc (regmatch_t, nregs);
+  if (BE (pmatch == NULL, 0))
+    {
+      rval = -2;
+      goto out;
+    }
+
+  result = re_search_internal (bufp, string, length, start, range, stop,
+			       nregs, pmatch, eflags);
+
+  rval = 0;
+
+  /* I hope we needn't fill ther regs with -1's when no match was found.  */
+  if (result != REG_NOERROR)
+    rval = -1;
+  else if (regs != NULL)
+    {
+      /* If caller wants register contents data back, copy them.  */
+      bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
+					   bufp->regs_allocated);
+      if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0))
+	rval = -2;
+    }
+
+  if (BE (rval == 0, 1))
+    {
+      if (ret_len)
+	{
+	  assert (pmatch[0].rm_so == start);
+	  rval = pmatch[0].rm_eo - start;
+	}
+      else
+	rval = pmatch[0].rm_so;
+    }
+  re_free (pmatch);
+ out:
+  __libc_lock_unlock (dfa->lock);
+  return rval;
+}
+
+static unsigned
+re_copy_regs (regs, pmatch, nregs, regs_allocated)
+    struct re_registers *regs;
+    regmatch_t *pmatch;
+    int nregs, regs_allocated;
+{
+  int rval = REGS_REALLOCATE;
+  int i;
+  int need_regs = nregs + 1;
+  /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
+     uses.  */
+
+  /* Have the register data arrays been allocated?  */
+  if (regs_allocated == REGS_UNALLOCATED)
+    { /* No.  So allocate them with malloc.  */
+      regs->start = re_malloc (regoff_t, need_regs);
+      regs->end = re_malloc (regoff_t, need_regs);
+      if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0))
+	return REGS_UNALLOCATED;
+      regs->num_regs = need_regs;
+    }
+  else if (regs_allocated == REGS_REALLOCATE)
+    { /* Yes.  If we need more elements than were already
+	 allocated, reallocate them.  If we need fewer, just
+	 leave it alone.  */
+      if (BE (need_regs > regs->num_regs, 0))
+	{
+	  regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs);
+	  regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs);
+	  if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0))
+	    return REGS_UNALLOCATED;
+	  regs->start = new_start;
+	  regs->end = new_end;
+	  regs->num_regs = need_regs;
+	}
+    }
+  else
+    {
+      assert (regs_allocated == REGS_FIXED);
+      /* This function may not be called with REGS_FIXED and nregs too big.  */
+      assert (regs->num_regs >= nregs);
+      rval = REGS_FIXED;
+    }
+
+  /* Copy the regs.  */
+  for (i = 0; i < nregs; ++i)
+    {
+      regs->start[i] = pmatch[i].rm_so;
+      regs->end[i] = pmatch[i].rm_eo;
+    }
+  for ( ; i < regs->num_regs; ++i)
+    regs->start[i] = regs->end[i] = -1;
+
+  return rval;
+}
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
+   this memory for recording register information.  STARTS and ENDS
+   must be allocated using the malloc library routine, and must each
+   be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+
+void
+re_set_registers (bufp, regs, num_regs, starts, ends)
+    struct re_pattern_buffer *bufp;
+    struct re_registers *regs;
+    unsigned num_regs;
+    regoff_t *starts, *ends;
+{
+  if (num_regs)
+    {
+      bufp->regs_allocated = REGS_REALLOCATE;
+      regs->num_regs = num_regs;
+      regs->start = starts;
+      regs->end = ends;
+    }
+  else
+    {
+      bufp->regs_allocated = REGS_UNALLOCATED;
+      regs->num_regs = 0;
+      regs->start = regs->end = (regoff_t *) 0;
+    }
+}
+#ifdef _LIBC
+weak_alias (__re_set_registers, re_set_registers)
+#endif
+
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+int
+# ifdef _LIBC
+weak_function
+# endif
+re_exec (s)
+     const char *s;
+{
+  return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);
+}
+#endif /* _REGEX_RE_COMP */
+
+
+/* Internal entry point.  */
+
+/* Searches for a compiled pattern PREG in the string STRING, whose
+   length is LENGTH.  NMATCH, PMATCH, and EFLAGS have the same
+   mingings with regexec.  START, and RANGE have the same meanings
+   with re_search.
+   Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
+   otherwise return the error code.
+   Note: We assume front end functions already check ranges.
+   (START + RANGE >= 0 && START + RANGE <= LENGTH)  */
+
+static reg_errcode_t
+re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
+		    eflags)
+    const regex_t *preg;
+    const char *string;
+    int length, start, range, stop, eflags;
+    size_t nmatch;
+    regmatch_t pmatch[];
+{
+  reg_errcode_t err;
+  const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
+  int left_lim, right_lim, incr;
+  int fl_longest_match, match_first, match_kind, match_last = -1;
+  int extra_nmatch;
+  int sb, ch;
+#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+  re_match_context_t mctx = { .dfa = dfa };
+#else
+  re_match_context_t mctx;
+#endif
+  char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate
+		   && range && !preg->can_be_null) ? preg->fastmap : NULL;
+  RE_TRANSLATE_TYPE t = preg->translate;
+
+#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
+  memset (&mctx, '\0', sizeof (re_match_context_t));
+  mctx.dfa = dfa;
+#endif
+
+  extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;
+  nmatch -= extra_nmatch;
+
+  /* Check if the DFA haven't been compiled.  */
+  if (BE (preg->used == 0 || dfa->init_state == NULL
+	  || dfa->init_state_word == NULL || dfa->init_state_nl == NULL
+	  || dfa->init_state_begbuf == NULL, 0))
+    return REG_NOMATCH;
+
+#ifdef DEBUG
+  /* We assume front-end functions already check them.  */
+  assert (start + range >= 0 && start + range <= length);
+#endif
+
+  /* If initial states with non-begbuf contexts have no elements,
+     the regex must be anchored.  If preg->newline_anchor is set,
+     we'll never use init_state_nl, so do not check it.  */
+  if (dfa->init_state->nodes.nelem == 0
+      && dfa->init_state_word->nodes.nelem == 0
+      && (dfa->init_state_nl->nodes.nelem == 0
+	  || !preg->newline_anchor))
+    {
+      if (start != 0 && start + range != 0)
+        return REG_NOMATCH;
+      start = range = 0;
+    }
+
+  /* We must check the longest matching, if nmatch > 0.  */
+  fl_longest_match = (nmatch != 0 || dfa->nbackref);
+
+  err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1,
+			    preg->translate, preg->syntax & RE_ICASE, dfa);
+  if (BE (err != REG_NOERROR, 0))
+    goto free_return;
+  mctx.input.stop = stop;
+  mctx.input.raw_stop = stop;
+  mctx.input.newline_anchor = preg->newline_anchor;
+
+  err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2);
+  if (BE (err != REG_NOERROR, 0))
+    goto free_return;
+
+  /* We will log all the DFA states through which the dfa pass,
+     if nmatch > 1, or this dfa has "multibyte node", which is a
+     back-reference or a node which can accept multibyte character or
+     multi character collating element.  */
+  if (nmatch > 1 || dfa->has_mb_node)
+    {
+      mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);
+      if (BE (mctx.state_log == NULL, 0))
+	{
+	  err = REG_ESPACE;
+	  goto free_return;
+	}
+    }
+  else
+    mctx.state_log = NULL;
+
+  match_first = start;
+  mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
+			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF;
+
+  /* Check incrementally whether of not the input string match.  */
+  incr = (range < 0) ? -1 : 1;
+  left_lim = (range < 0) ? start + range : start;
+  right_lim = (range < 0) ? start : start + range;
+  sb = dfa->mb_cur_max == 1;
+  match_kind =
+    (fastmap
+     ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
+	| (range >= 0 ? 2 : 0)
+	| (t != NULL ? 1 : 0))
+     : 8);
+
+  for (;; match_first += incr)
+    {
+      err = REG_NOMATCH;
+      if (match_first < left_lim || right_lim < match_first)
+	goto free_return;
+
+      /* Advance as rapidly as possible through the string, until we
+	 find a plausible place to start matching.  This may be done
+	 with varying efficiency, so there are various possibilities:
+	 only the most common of them are specialized, in order to
+	 save on code size.  We use a switch statement for speed.  */
+      switch (match_kind)
+	{
+	case 8:
+	  /* No fastmap.  */
+	  break;
+
+	case 7:
+	  /* Fastmap with single-byte translation, match forward.  */
+	  while (BE (match_first < right_lim, 1)
+		 && !fastmap[t[(unsigned char) string[match_first]]])
+	    ++match_first;
+	  goto forward_match_found_start_or_reached_end;
+
+	case 6:
+	  /* Fastmap without translation, match forward.  */
+	  while (BE (match_first < right_lim, 1)
+		 && !fastmap[(unsigned char) string[match_first]])
+	    ++match_first;
+
+	forward_match_found_start_or_reached_end:
+	  if (BE (match_first == right_lim, 0))
+	    {
+	      ch = match_first >= length
+		       ? 0 : (unsigned char) string[match_first];
+	      if (!fastmap[t ? t[ch] : ch])
+		goto free_return;
+	    }
+	  break;
+
+	case 4:
+	case 5:
+	  /* Fastmap without multi-byte translation, match backwards.  */
+	  while (match_first >= left_lim)
+	    {
+	      ch = match_first >= length
+		       ? 0 : (unsigned char) string[match_first];
+	      if (fastmap[t ? t[ch] : ch])
+		break;
+	      --match_first;
+	    }
+	  if (match_first < left_lim)
+	    goto free_return;
+	  break;
+
+	default:
+	  /* In this case, we can't determine easily the current byte,
+	     since it might be a component byte of a multibyte
+	     character.  Then we use the constructed buffer instead.  */
+	  for (;;)
+	    {
+	      /* If MATCH_FIRST is out of the valid range, reconstruct the
+		 buffers.  */
+	      unsigned int offset = match_first - mctx.input.raw_mbs_idx;
+	      if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0))
+		{
+		  err = re_string_reconstruct (&mctx.input, match_first,
+					       eflags);
+		  if (BE (err != REG_NOERROR, 0))
+		    goto free_return;
+
+		  offset = match_first - mctx.input.raw_mbs_idx;
+		}
+	      /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
+		 Note that MATCH_FIRST must not be smaller than 0.  */
+	      ch = (match_first >= length
+		    ? 0 : re_string_byte_at (&mctx.input, offset));
+	      if (fastmap[ch])
+		break;
+	      match_first += incr;
+	      if (match_first < left_lim || match_first > right_lim)
+	        {
+	          err = REG_NOMATCH;
+	          goto free_return;
+	        }
+	    }
+	  break;
+	}
+
+      /* Reconstruct the buffers so that the matcher can assume that
+	 the matching starts from the beginning of the buffer.  */
+      err = re_string_reconstruct (&mctx.input, match_first, eflags);
+      if (BE (err != REG_NOERROR, 0))
+	goto free_return;
+
+#ifdef RE_ENABLE_I18N
+     /* Don't consider this char as a possible match start if it part,
+	yet isn't the head, of a multibyte character.  */
+      if (!sb && !re_string_first_byte (&mctx.input, 0))
+	continue;
+#endif
+
+      /* It seems to be appropriate one, then use the matcher.  */
+      /* We assume that the matching starts from 0.  */
+      mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
+      match_last = check_matching (&mctx, fl_longest_match,
+				   range >= 0 ? &match_first : NULL);
+      if (match_last != -1)
+	{
+	  if (BE (match_last == -2, 0))
+	    {
+	      err = REG_ESPACE;
+	      goto free_return;
+	    }
+	  else
+	    {
+	      mctx.match_last = match_last;
+	      if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
+		{
+		  re_dfastate_t *pstate = mctx.state_log[match_last];
+		  mctx.last_node = check_halt_state_context (&mctx, pstate,
+							     match_last);
+		}
+	      if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
+		  || dfa->nbackref)
+		{
+		  err = prune_impossible_nodes (&mctx);
+		  if (err == REG_NOERROR)
+		    break;
+		  if (BE (err != REG_NOMATCH, 0))
+		    goto free_return;
+		  match_last = -1;
+		}
+	      else
+		break; /* We found a match.  */
+	    }
+	}
+
+      match_ctx_clean (&mctx);
+    }
+
+#ifdef DEBUG
+  assert (match_last != -1);
+  assert (err == REG_NOERROR);
+#endif
+
+  /* Set pmatch[] if we need.  */
+  if (nmatch > 0)
+    {
+      int reg_idx;
+
+      /* Initialize registers.  */
+      for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)
+	pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;
+
+      /* Set the points where matching start/end.  */
+      pmatch[0].rm_so = 0;
+      pmatch[0].rm_eo = mctx.match_last;
+
+      if (!preg->no_sub && nmatch > 1)
+	{
+	  err = set_regs (preg, &mctx, nmatch, pmatch,
+			  dfa->has_plural_match && dfa->nbackref > 0);
+	  if (BE (err != REG_NOERROR, 0))
+	    goto free_return;
+	}
+
+      /* At last, add the offset to the each registers, since we slided
+	 the buffers so that we could assume that the matching starts
+	 from 0.  */
+      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
+	if (pmatch[reg_idx].rm_so != -1)
+	  {
+#ifdef RE_ENABLE_I18N
+	    if (BE (mctx.input.offsets_needed != 0, 0))
+	      {
+		pmatch[reg_idx].rm_so =
+		  (pmatch[reg_idx].rm_so == mctx.input.valid_len
+		   ? mctx.input.valid_raw_len
+		   : mctx.input.offsets[pmatch[reg_idx].rm_so]);
+		pmatch[reg_idx].rm_eo =
+		  (pmatch[reg_idx].rm_eo == mctx.input.valid_len
+		   ? mctx.input.valid_raw_len
+		   : mctx.input.offsets[pmatch[reg_idx].rm_eo]);
+	      }
+#else
+	    assert (mctx.input.offsets_needed == 0);
+#endif
+	    pmatch[reg_idx].rm_so += match_first;
+	    pmatch[reg_idx].rm_eo += match_first;
+	  }
+      for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)
+	{
+	  pmatch[nmatch + reg_idx].rm_so = -1;
+	  pmatch[nmatch + reg_idx].rm_eo = -1;
+	}
+
+      if (dfa->subexp_map)
+        for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)
+          if (dfa->subexp_map[reg_idx] != reg_idx)
+            {
+              pmatch[reg_idx + 1].rm_so
+                = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;
+              pmatch[reg_idx + 1].rm_eo
+                = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo;
+            }
+    }
+
+ free_return:
+  re_free (mctx.state_log);
+  if (dfa->nbackref)
+    match_ctx_free (&mctx);
+  re_string_destruct (&mctx.input);
+  return err;
+}
+
+static reg_errcode_t
+prune_impossible_nodes (mctx)
+     re_match_context_t *mctx;
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int halt_node, match_last;
+  reg_errcode_t ret;
+  re_dfastate_t **sifted_states;
+  re_dfastate_t **lim_states = NULL;
+  re_sift_context_t sctx;
+#ifdef DEBUG
+  assert (mctx->state_log != NULL);
+#endif
+  match_last = mctx->match_last;
+  halt_node = mctx->last_node;
+  sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
+  if (BE (sifted_states == NULL, 0))
+    {
+      ret = REG_ESPACE;
+      goto free_return;
+    }
+  if (dfa->nbackref)
+    {
+      lim_states = re_malloc (re_dfastate_t *, match_last + 1);
+      if (BE (lim_states == NULL, 0))
+	{
+	  ret = REG_ESPACE;
+	  goto free_return;
+	}
+      while (1)
+	{
+	  memset (lim_states, '\0',
+		  sizeof (re_dfastate_t *) * (match_last + 1));
+	  sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
+			 match_last);
+	  ret = sift_states_backward (mctx, &sctx);
+	  re_node_set_free (&sctx.limits);
+	  if (BE (ret != REG_NOERROR, 0))
+	      goto free_return;
+	  if (sifted_states[0] != NULL || lim_states[0] != NULL)
+	    break;
+	  do
+	    {
+	      --match_last;
+	      if (match_last < 0)
+		{
+		  ret = REG_NOMATCH;
+		  goto free_return;
+		}
+	    } while (mctx->state_log[match_last] == NULL
+		     || !mctx->state_log[match_last]->halt);
+	  halt_node = check_halt_state_context (mctx,
+						mctx->state_log[match_last],
+						match_last);
+	}
+      ret = merge_state_array (dfa, sifted_states, lim_states,
+			       match_last + 1);
+      re_free (lim_states);
+      lim_states = NULL;
+      if (BE (ret != REG_NOERROR, 0))
+	goto free_return;
+    }
+  else
+    {
+      sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last);
+      ret = sift_states_backward (mctx, &sctx);
+      re_node_set_free (&sctx.limits);
+      if (BE (ret != REG_NOERROR, 0))
+	goto free_return;
+    }
+  re_free (mctx->state_log);
+  mctx->state_log = sifted_states;
+  sifted_states = NULL;
+  mctx->last_node = halt_node;
+  mctx->match_last = match_last;
+  ret = REG_NOERROR;
+ free_return:
+  re_free (sifted_states);
+  re_free (lim_states);
+  return ret;
+}
+
+/* Acquire an initial state and return it.
+   We must select appropriate initial state depending on the context,
+   since initial states may have constraints like "\<", "^", etc..  */
+
+static inline re_dfastate_t *
+__attribute ((always_inline)) internal_function
+acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
+			    int idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  if (dfa->init_state->has_constraint)
+    {
+      unsigned int context;
+      context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags);
+      if (IS_WORD_CONTEXT (context))
+	return dfa->init_state_word;
+      else if (IS_ORDINARY_CONTEXT (context))
+	return dfa->init_state;
+      else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
+	return dfa->init_state_begbuf;
+      else if (IS_NEWLINE_CONTEXT (context))
+	return dfa->init_state_nl;
+      else if (IS_BEGBUF_CONTEXT (context))
+	{
+	  /* It is relatively rare case, then calculate on demand.  */
+	  return re_acquire_state_context (err, dfa,
+					   dfa->init_state->entrance_nodes,
+					   context);
+	}
+      else
+	/* Must not happen?  */
+	return dfa->init_state;
+    }
+  else
+    return dfa->init_state;
+}
+
+/* Check whether the regular expression match input string INPUT or not,
+   and return the index where the matching end, return -1 if not match,
+   or return -2 in case of an error.
+   FL_LONGEST_MATCH means we want the POSIX longest matching.
+   If P_MATCH_FIRST is not NULL, and the match fails, it is set to the
+   next place where we may want to try matching.
+   Note that the matcher assume that the maching starts from the current
+   index of the buffer.  */
+
+static int
+internal_function
+check_matching (re_match_context_t *mctx, int fl_longest_match,
+		int *p_match_first)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int match = 0;
+  int match_last = -1;
+  int cur_str_idx = re_string_cur_idx (&mctx->input);
+  re_dfastate_t *cur_state;
+  int at_init_state = p_match_first != NULL;
+  int next_start_idx = cur_str_idx;
+
+  err = REG_NOERROR;
+  cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
+  /* An initial state must not be NULL (invalid).  */
+  if (BE (cur_state == NULL, 0))
+    {
+      assert (err == REG_ESPACE);
+      return -2;
+    }
+
+  if (mctx->state_log != NULL)
+    {
+      mctx->state_log[cur_str_idx] = cur_state;
+
+      /* Check OP_OPEN_SUBEXP in the initial state in case that we use them
+	 later.  E.g. Processing back references.  */
+      if (BE (dfa->nbackref, 0))
+	{
+	  at_init_state = 0;
+	  err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+
+	  if (cur_state->has_backref)
+	    {
+	      err = transit_state_bkref (mctx, &cur_state->nodes);
+	      if (BE (err != REG_NOERROR, 0))
+	        return err;
+	    }
+	}
+    }
+
+  /* If the RE accepts NULL string.  */
+  if (BE (cur_state->halt, 0))
+    {
+      if (!cur_state->has_constraint
+	  || check_halt_state_context (mctx, cur_state, cur_str_idx))
+	{
+	  if (!fl_longest_match)
+	    return cur_str_idx;
+	  else
+	    {
+	      match_last = cur_str_idx;
+	      match = 1;
+	    }
+	}
+    }
+
+  while (!re_string_eoi (&mctx->input))
+    {
+      re_dfastate_t *old_state = cur_state;
+      int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
+
+      if (BE (next_char_idx >= mctx->input.bufs_len, 0)
+          || (BE (next_char_idx >= mctx->input.valid_len, 0)
+              && mctx->input.valid_len < mctx->input.len))
+        {
+          err = extend_buffers (mctx);
+          if (BE (err != REG_NOERROR, 0))
+	    {
+	      assert (err == REG_ESPACE);
+	      return -2;
+	    }
+        }
+
+      cur_state = transit_state (&err, mctx, cur_state);
+      if (mctx->state_log != NULL)
+	cur_state = merge_state_with_log (&err, mctx, cur_state);
+
+      if (cur_state == NULL)
+	{
+	  /* Reached the invalid state or an error.  Try to recover a valid
+	     state using the state log, if available and if we have not
+	     already found a valid (even if not the longest) match.  */
+	  if (BE (err != REG_NOERROR, 0))
+	    return -2;
+
+	  if (mctx->state_log == NULL
+	      || (match && !fl_longest_match)
+	      || (cur_state = find_recover_state (&err, mctx)) == NULL)
+	    break;
+	}
+
+      if (BE (at_init_state, 0))
+	{
+	  if (old_state == cur_state)
+	    next_start_idx = next_char_idx;
+	  else
+	    at_init_state = 0;
+	}
+
+      if (cur_state->halt)
+	{
+	  /* Reached a halt state.
+	     Check the halt state can satisfy the current context.  */
+	  if (!cur_state->has_constraint
+	      || check_halt_state_context (mctx, cur_state,
+					   re_string_cur_idx (&mctx->input)))
+	    {
+	      /* We found an appropriate halt state.  */
+	      match_last = re_string_cur_idx (&mctx->input);
+	      match = 1;
+
+	      /* We found a match, do not modify match_first below.  */
+	      p_match_first = NULL;
+	      if (!fl_longest_match)
+		break;
+	    }
+	}
+    }
+
+  if (p_match_first)
+    *p_match_first += next_start_idx;
+
+  return match_last;
+}
+
+/* Check NODE match the current context.  */
+
+static int
+internal_function
+check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context)
+{
+  re_token_type_t type = dfa->nodes[node].type;
+  unsigned int constraint = dfa->nodes[node].constraint;
+  if (type != END_OF_RE)
+    return 0;
+  if (!constraint)
+    return 1;
+  if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))
+    return 0;
+  return 1;
+}
+
+/* Check the halt state STATE match the current context.
+   Return 0 if not match, if the node, STATE has, is a halt node and
+   match the context, return the node.  */
+
+static int
+internal_function
+check_halt_state_context (const re_match_context_t *mctx,
+			  const re_dfastate_t *state, int idx)
+{
+  int i;
+  unsigned int context;
+#ifdef DEBUG
+  assert (state->halt);
+#endif
+  context = re_string_context_at (&mctx->input, idx, mctx->eflags);
+  for (i = 0; i < state->nodes.nelem; ++i)
+    if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context))
+      return state->nodes.elems[i];
+  return 0;
+}
+
+/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
+   corresponding to the DFA).
+   Return the destination node, and update EPS_VIA_NODES, return -1 in case
+   of errors.  */
+
+static int
+internal_function
+proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
+		   int *pidx, int node, re_node_set *eps_via_nodes,
+		   struct re_fail_stack_t *fs)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int i, err;
+  if (IS_EPSILON_NODE (dfa->nodes[node].type))
+    {
+      re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
+      re_node_set *edests = &dfa->edests[node];
+      int dest_node;
+      err = re_node_set_insert (eps_via_nodes, node);
+      if (BE (err < 0, 0))
+	return -2;
+      /* Pick up a valid destination, or return -1 if none is found.  */
+      for (dest_node = -1, i = 0; i < edests->nelem; ++i)
+	{
+	  int candidate = edests->elems[i];
+	  if (!re_node_set_contains (cur_nodes, candidate))
+	    continue;
+          if (dest_node == -1)
+	    dest_node = candidate;
+
+          else
+	    {
+	      /* In order to avoid infinite loop like "(a*)*", return the second
+	         epsilon-transition if the first was already considered.  */
+	      if (re_node_set_contains (eps_via_nodes, dest_node))
+	        return candidate;
+
+	      /* Otherwise, push the second epsilon-transition on the fail stack.  */
+	      else if (fs != NULL
+		       && push_fail_stack (fs, *pidx, candidate, nregs, regs,
+				           eps_via_nodes))
+		return -2;
+
+	      /* We know we are going to exit.  */
+	      break;
+	    }
+	}
+      return dest_node;
+    }
+  else
+    {
+      int naccepted = 0;
+      re_token_type_t type = dfa->nodes[node].type;
+
+#ifdef RE_ENABLE_I18N
+      if (dfa->nodes[node].accept_mb)
+	naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);
+      else
+#endif /* RE_ENABLE_I18N */
+      if (type == OP_BACK_REF)
+	{
+	  int subexp_idx = dfa->nodes[node].opr.idx + 1;
+	  naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
+	  if (fs != NULL)
+	    {
+	      if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)
+		return -1;
+	      else if (naccepted)
+		{
+		  char *buf = (char *) re_string_get_buffer (&mctx->input);
+		  if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
+			      naccepted) != 0)
+		    return -1;
+		}
+	    }
+
+	  if (naccepted == 0)
+	    {
+	      int dest_node;
+	      err = re_node_set_insert (eps_via_nodes, node);
+	      if (BE (err < 0, 0))
+		return -2;
+	      dest_node = dfa->edests[node].elems[0];
+	      if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
+					dest_node))
+		return dest_node;
+	    }
+	}
+
+      if (naccepted != 0
+	  || check_node_accept (mctx, dfa->nodes + node, *pidx))
+	{
+	  int dest_node = dfa->nexts[node];
+	  *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
+	  if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
+		     || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
+					       dest_node)))
+	    return -1;
+	  re_node_set_empty (eps_via_nodes);
+	  return dest_node;
+	}
+    }
+  return -1;
+}
+
+static reg_errcode_t
+internal_function
+push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node,
+		 int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
+{
+  reg_errcode_t err;
+  int num = fs->num++;
+  if (fs->num == fs->alloc)
+    {
+      struct re_fail_stack_ent_t *new_array;
+      new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)
+				       * fs->alloc * 2));
+      if (new_array == NULL)
+	return REG_ESPACE;
+      fs->alloc *= 2;
+      fs->stack = new_array;
+    }
+  fs->stack[num].idx = str_idx;
+  fs->stack[num].node = dest_node;
+  fs->stack[num].regs = re_malloc (regmatch_t, nregs);
+  if (fs->stack[num].regs == NULL)
+    return REG_ESPACE;
+  memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
+  err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
+  return err;
+}
+
+static int
+internal_function
+pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
+		regmatch_t *regs, re_node_set *eps_via_nodes)
+{
+  int num = --fs->num;
+  assert (num >= 0);
+  *pidx = fs->stack[num].idx;
+  memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
+  re_node_set_free (eps_via_nodes);
+  re_free (fs->stack[num].regs);
+  *eps_via_nodes = fs->stack[num].eps_via_nodes;
+  return fs->stack[num].node;
+}
+
+/* Set the positions where the subexpressions are starts/ends to registers
+   PMATCH.
+   Note: We assume that pmatch[0] is already set, and
+   pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch.  */
+
+static reg_errcode_t
+internal_function
+set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
+	  regmatch_t *pmatch, int fl_backtrack)
+{
+  const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
+  int idx, cur_node;
+  re_node_set eps_via_nodes;
+  struct re_fail_stack_t *fs;
+  struct re_fail_stack_t fs_body = { 0, 2, NULL };
+  regmatch_t *prev_idx_match;
+  int prev_idx_match_malloced = 0;
+
+#ifdef DEBUG
+  assert (nmatch > 1);
+  assert (mctx->state_log != NULL);
+#endif
+  if (fl_backtrack)
+    {
+      fs = &fs_body;
+      fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
+      if (fs->stack == NULL)
+	return REG_ESPACE;
+    }
+  else
+    fs = NULL;
+
+  cur_node = dfa->init_node;
+  re_node_set_init_empty (&eps_via_nodes);
+
+  if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
+    prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
+  else
+    {
+      prev_idx_match = re_malloc (regmatch_t, nmatch);
+      if (prev_idx_match == NULL)
+	{
+	  free_fail_stack_return (fs);
+	  return REG_ESPACE;
+	}
+      prev_idx_match_malloced = 1;
+    }
+  memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
+
+  for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
+    {
+      update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
+
+      if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
+	{
+	  int reg_idx;
+	  if (fs)
+	    {
+	      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
+		if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
+		  break;
+	      if (reg_idx == nmatch)
+		{
+		  re_node_set_free (&eps_via_nodes);
+		  if (prev_idx_match_malloced)
+		    re_free (prev_idx_match);
+		  return free_fail_stack_return (fs);
+		}
+	      cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+					 &eps_via_nodes);
+	    }
+	  else
+	    {
+	      re_node_set_free (&eps_via_nodes);
+	      if (prev_idx_match_malloced)
+		re_free (prev_idx_match);
+	      return REG_NOERROR;
+	    }
+	}
+
+      /* Proceed to next node.  */
+      cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node,
+				    &eps_via_nodes, fs);
+
+      if (BE (cur_node < 0, 0))
+	{
+	  if (BE (cur_node == -2, 0))
+	    {
+	      re_node_set_free (&eps_via_nodes);
+	      if (prev_idx_match_malloced)
+		re_free (prev_idx_match);
+	      free_fail_stack_return (fs);
+	      return REG_ESPACE;
+	    }
+	  if (fs)
+	    cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+				       &eps_via_nodes);
+	  else
+	    {
+	      re_node_set_free (&eps_via_nodes);
+	      if (prev_idx_match_malloced)
+		re_free (prev_idx_match);
+	      return REG_NOMATCH;
+	    }
+	}
+    }
+  re_node_set_free (&eps_via_nodes);
+  if (prev_idx_match_malloced)
+    re_free (prev_idx_match);
+  return free_fail_stack_return (fs);
+}
+
+static reg_errcode_t
+internal_function
+free_fail_stack_return (struct re_fail_stack_t *fs)
+{
+  if (fs)
+    {
+      int fs_idx;
+      for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)
+	{
+	  re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);
+	  re_free (fs->stack[fs_idx].regs);
+	}
+      re_free (fs->stack);
+    }
+  return REG_NOERROR;
+}
+
+static void
+internal_function
+update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
+	     regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch)
+{
+  int type = dfa->nodes[cur_node].type;
+  if (type == OP_OPEN_SUBEXP)
+    {
+      int reg_num = dfa->nodes[cur_node].opr.idx + 1;
+
+      /* We are at the first node of this sub expression.  */
+      if (reg_num < nmatch)
+	{
+	  pmatch[reg_num].rm_so = cur_idx;
+	  pmatch[reg_num].rm_eo = -1;
+	}
+    }
+  else if (type == OP_CLOSE_SUBEXP)
+    {
+      int reg_num = dfa->nodes[cur_node].opr.idx + 1;
+      if (reg_num < nmatch)
+	{
+	  /* We are at the last node of this sub expression.  */
+	  if (pmatch[reg_num].rm_so < cur_idx)
+	    {
+	      pmatch[reg_num].rm_eo = cur_idx;
+	      /* This is a non-empty match or we are not inside an optional
+		 subexpression.  Accept this right away.  */
+	      memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
+	    }
+	  else
+	    {
+	      if (dfa->nodes[cur_node].opt_subexp
+		  && prev_idx_match[reg_num].rm_so != -1)
+		/* We transited through an empty match for an optional
+		   subexpression, like (a?)*, and this is not the subexp's
+		   first match.  Copy back the old content of the registers
+		   so that matches of an inner subexpression are undone as
+		   well, like in ((a?))*.  */
+		memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch);
+	      else
+		/* We completed a subexpression, but it may be part of
+		   an optional one, so do not update PREV_IDX_MATCH.  */
+		pmatch[reg_num].rm_eo = cur_idx;
+	    }
+	}
+    }
+}
+
+/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0
+   and sift the nodes in each states according to the following rules.
+   Updated state_log will be wrote to STATE_LOG.
+
+   Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...
+     1. When STR_IDX == MATCH_LAST(the last index in the state_log):
+	If `a' isn't the LAST_NODE and `a' can't epsilon transit to
+	the LAST_NODE, we throw away the node `a'.
+     2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts
+	string `s' and transit to `b':
+	i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
+	   away the node `a'.
+	ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
+	    thrown away, we throw away the node `a'.
+     3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b':
+	i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
+	   node `a'.
+	ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away,
+	    we throw away the node `a'.  */
+
+#define STATE_NODE_CONTAINS(state,node) \
+  ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
+
+static reg_errcode_t
+internal_function
+sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
+{
+  reg_errcode_t err;
+  int null_cnt = 0;
+  int str_idx = sctx->last_str_idx;
+  re_node_set cur_dest;
+
+#ifdef DEBUG
+  assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
+#endif
+
+  /* Build sifted state_log[str_idx].  It has the nodes which can epsilon
+     transit to the last_node and the last_node itself.  */
+  err = re_node_set_init_1 (&cur_dest, sctx->last_node);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+  err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
+  if (BE (err != REG_NOERROR, 0))
+    goto free_return;
+
+  /* Then check each states in the state_log.  */
+  while (str_idx > 0)
+    {
+      /* Update counters.  */
+      null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;
+      if (null_cnt > mctx->max_mb_elem_len)
+	{
+	  memset (sctx->sifted_states, '\0',
+		  sizeof (re_dfastate_t *) * str_idx);
+	  re_node_set_free (&cur_dest);
+	  return REG_NOERROR;
+	}
+      re_node_set_empty (&cur_dest);
+      --str_idx;
+
+      if (mctx->state_log[str_idx])
+	{
+	  err = build_sifted_states (mctx, sctx, str_idx, &cur_dest);
+          if (BE (err != REG_NOERROR, 0))
+	    goto free_return;
+	}
+
+      /* Add all the nodes which satisfy the following conditions:
+	 - It can epsilon transit to a node in CUR_DEST.
+	 - It is in CUR_SRC.
+	 And update state_log.  */
+      err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
+      if (BE (err != REG_NOERROR, 0))
+	goto free_return;
+    }
+  err = REG_NOERROR;
+ free_return:
+  re_node_set_free (&cur_dest);
+  return err;
+}
+
+static reg_errcode_t
+internal_function
+build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
+		     int str_idx, re_node_set *cur_dest)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes;
+  int i;
+
+  /* Then build the next sifted state.
+     We build the next sifted state on `cur_dest', and update
+     `sifted_states[str_idx]' with `cur_dest'.
+     Note:
+     `cur_dest' is the sifted state from `state_log[str_idx + 1]'.
+     `cur_src' points the node_set of the old `state_log[str_idx]'
+     (with the epsilon nodes pre-filtered out).  */
+  for (i = 0; i < cur_src->nelem; i++)
+    {
+      int prev_node = cur_src->elems[i];
+      int naccepted = 0;
+      int ret;
+
+#ifdef DEBUG
+      re_token_type_t type = dfa->nodes[prev_node].type;
+      assert (!IS_EPSILON_NODE (type));
+#endif
+#ifdef RE_ENABLE_I18N
+      /* If the node may accept `multi byte'.  */
+      if (dfa->nodes[prev_node].accept_mb)
+	naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
+					 str_idx, sctx->last_str_idx);
+#endif /* RE_ENABLE_I18N */
+
+      /* We don't check backreferences here.
+	 See update_cur_sifted_state().  */
+      if (!naccepted
+	  && check_node_accept (mctx, dfa->nodes + prev_node, str_idx)
+	  && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],
+				  dfa->nexts[prev_node]))
+	naccepted = 1;
+
+      if (naccepted == 0)
+	continue;
+
+      if (sctx->limits.nelem)
+	{
+	  int to_idx = str_idx + naccepted;
+	  if (check_dst_limits (mctx, &sctx->limits,
+				dfa->nexts[prev_node], to_idx,
+				prev_node, str_idx))
+	    continue;
+	}
+      ret = re_node_set_insert (cur_dest, prev_node);
+      if (BE (ret == -1, 0))
+	return REG_ESPACE;
+    }
+
+  return REG_NOERROR;
+}
+
+/* Helper functions.  */
+
+static reg_errcode_t
+internal_function
+clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)
+{
+  int top = mctx->state_log_top;
+
+  if (next_state_log_idx >= mctx->input.bufs_len
+      || (next_state_log_idx >= mctx->input.valid_len
+	  && mctx->input.valid_len < mctx->input.len))
+    {
+      reg_errcode_t err;
+      err = extend_buffers (mctx);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+    }
+
+  if (top < next_state_log_idx)
+    {
+      memset (mctx->state_log + top + 1, '\0',
+	      sizeof (re_dfastate_t *) * (next_state_log_idx - top));
+      mctx->state_log_top = next_state_log_idx;
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,
+		   re_dfastate_t **src, int num)
+{
+  int st_idx;
+  reg_errcode_t err;
+  for (st_idx = 0; st_idx < num; ++st_idx)
+    {
+      if (dst[st_idx] == NULL)
+	dst[st_idx] = src[st_idx];
+      else if (src[st_idx] != NULL)
+	{
+	  re_node_set merged_set;
+	  err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,
+					&src[st_idx]->nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	  dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);
+	  re_node_set_free (&merged_set);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+update_cur_sifted_state (const re_match_context_t *mctx,
+			 re_sift_context_t *sctx, int str_idx,
+			 re_node_set *dest_nodes)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err = REG_NOERROR;
+  const re_node_set *candidates;
+  candidates = ((mctx->state_log[str_idx] == NULL) ? NULL
+		: &mctx->state_log[str_idx]->nodes);
+
+  if (dest_nodes->nelem == 0)
+    sctx->sifted_states[str_idx] = NULL;
+  else
+    {
+      if (candidates)
+	{
+	  /* At first, add the nodes which can epsilon transit to a node in
+	     DEST_NODE.  */
+	  err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+
+	  /* Then, check the limitations in the current sift_context.  */
+	  if (sctx->limits.nelem)
+	    {
+	      err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,
+					 mctx->bkref_ents, str_idx);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	    }
+	}
+
+      sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+    }
+
+  if (candidates && mctx->state_log[str_idx]->has_backref)
+    {
+      err = sift_states_bkref (mctx, sctx, str_idx, candidates);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
+		       const re_node_set *candidates)
+{
+  reg_errcode_t err = REG_NOERROR;
+  int i;
+
+  re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+
+  if (!state->inveclosure.alloc)
+    {
+      err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem);
+      if (BE (err != REG_NOERROR, 0))
+        return REG_ESPACE;
+      for (i = 0; i < dest_nodes->nelem; i++)
+        re_node_set_merge (&state->inveclosure,
+			   dfa->inveclosures + dest_nodes->elems[i]);
+    }
+  return re_node_set_add_intersect (dest_nodes, candidates,
+				    &state->inveclosure);
+}
+
+static reg_errcode_t
+internal_function
+sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes,
+		       const re_node_set *candidates)
+{
+    int ecl_idx;
+    reg_errcode_t err;
+    re_node_set *inv_eclosure = dfa->inveclosures + node;
+    re_node_set except_nodes;
+    re_node_set_init_empty (&except_nodes);
+    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
+      {
+	int cur_node = inv_eclosure->elems[ecl_idx];
+	if (cur_node == node)
+	  continue;
+	if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))
+	  {
+	    int edst1 = dfa->edests[cur_node].elems[0];
+	    int edst2 = ((dfa->edests[cur_node].nelem > 1)
+			 ? dfa->edests[cur_node].elems[1] : -1);
+	    if ((!re_node_set_contains (inv_eclosure, edst1)
+		 && re_node_set_contains (dest_nodes, edst1))
+		|| (edst2 > 0
+		    && !re_node_set_contains (inv_eclosure, edst2)
+		    && re_node_set_contains (dest_nodes, edst2)))
+	      {
+		err = re_node_set_add_intersect (&except_nodes, candidates,
+						 dfa->inveclosures + cur_node);
+		if (BE (err != REG_NOERROR, 0))
+		  {
+		    re_node_set_free (&except_nodes);
+		    return err;
+		  }
+	      }
+	  }
+      }
+    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
+      {
+	int cur_node = inv_eclosure->elems[ecl_idx];
+	if (!re_node_set_contains (&except_nodes, cur_node))
+	  {
+	    int idx = re_node_set_contains (dest_nodes, cur_node) - 1;
+	    re_node_set_remove_at (dest_nodes, idx);
+	  }
+      }
+    re_node_set_free (&except_nodes);
+    return REG_NOERROR;
+}
+
+static int
+internal_function
+check_dst_limits (const re_match_context_t *mctx, re_node_set *limits,
+		  int dst_node, int dst_idx, int src_node, int src_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int lim_idx, src_pos, dst_pos;
+
+  int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);
+  int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);
+  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
+    {
+      int subexp_idx;
+      struct re_backref_cache_entry *ent;
+      ent = mctx->bkref_ents + limits->elems[lim_idx];
+      subexp_idx = dfa->nodes[ent->node].opr.idx;
+
+      dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
+					   subexp_idx, dst_node, dst_idx,
+					   dst_bkref_idx);
+      src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
+					   subexp_idx, src_node, src_idx,
+					   src_bkref_idx);
+
+      /* In case of:
+	 <src> <dst> ( <subexp> )
+	 ( <subexp> ) <src> <dst>
+	 ( <subexp1> <src> <subexp2> <dst> <subexp3> )  */
+      if (src_pos == dst_pos)
+	continue; /* This is unrelated limitation.  */
+      else
+	return 1;
+    }
+  return 0;
+}
+
+static int
+internal_function
+check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
+			     int subexp_idx, int from_node, int bkref_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  const re_node_set *eclosures = dfa->eclosures + from_node;
+  int node_idx;
+
+  /* Else, we are on the boundary: examine the nodes on the epsilon
+     closure.  */
+  for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
+    {
+      int node = eclosures->elems[node_idx];
+      switch (dfa->nodes[node].type)
+	{
+	case OP_BACK_REF:
+	  if (bkref_idx != -1)
+	    {
+	      struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx;
+	      do
+	        {
+		  int dst, cpos;
+
+		  if (ent->node != node)
+		    continue;
+
+		  if (subexp_idx < BITSET_WORD_BITS
+		      && !(ent->eps_reachable_subexps_map
+			   & ((bitset_word_t) 1 << subexp_idx)))
+		    continue;
+
+		  /* Recurse trying to reach the OP_OPEN_SUBEXP and
+		     OP_CLOSE_SUBEXP cases below.  But, if the
+		     destination node is the same node as the source
+		     node, don't recurse because it would cause an
+		     infinite loop: a regex that exhibits this behavior
+		     is ()\1*\1*  */
+		  dst = dfa->edests[node].elems[0];
+		  if (dst == from_node)
+		    {
+		      if (boundaries & 1)
+		        return -1;
+		      else /* if (boundaries & 2) */
+		        return 0;
+		    }
+
+		  cpos =
+		    check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
+						 dst, bkref_idx);
+		  if (cpos == -1 /* && (boundaries & 1) */)
+		    return -1;
+		  if (cpos == 0 && (boundaries & 2))
+		    return 0;
+
+		  if (subexp_idx < BITSET_WORD_BITS)
+		    ent->eps_reachable_subexps_map
+		      &= ~((bitset_word_t) 1 << subexp_idx);
+	        }
+	      while (ent++->more);
+	    }
+	  break;
+
+	case OP_OPEN_SUBEXP:
+	  if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx)
+	    return -1;
+	  break;
+
+	case OP_CLOSE_SUBEXP:
+	  if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx)
+	    return 0;
+	  break;
+
+	default:
+	    break;
+	}
+    }
+
+  return (boundaries & 2) ? 1 : 0;
+}
+
+static int
+internal_function
+check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit,
+			   int subexp_idx, int from_node, int str_idx,
+			   int bkref_idx)
+{
+  struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
+  int boundaries;
+
+  /* If we are outside the range of the subexpression, return -1 or 1.  */
+  if (str_idx < lim->subexp_from)
+    return -1;
+
+  if (lim->subexp_to < str_idx)
+    return 1;
+
+  /* If we are within the subexpression, return 0.  */
+  boundaries = (str_idx == lim->subexp_from);
+  boundaries |= (str_idx == lim->subexp_to) << 1;
+  if (boundaries == 0)
+    return 0;
+
+  /* Else, examine epsilon closure.  */
+  return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
+				      from_node, bkref_idx);
+}
+
+/* Check the limitations of sub expressions LIMITS, and remove the nodes
+   which are against limitations from DEST_NODES. */
+
+static reg_errcode_t
+internal_function
+check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
+		     const re_node_set *candidates, re_node_set *limits,
+		     struct re_backref_cache_entry *bkref_ents, int str_idx)
+{
+  reg_errcode_t err;
+  int node_idx, lim_idx;
+
+  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
+    {
+      int subexp_idx;
+      struct re_backref_cache_entry *ent;
+      ent = bkref_ents + limits->elems[lim_idx];
+
+      if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)
+	continue; /* This is unrelated limitation.  */
+
+      subexp_idx = dfa->nodes[ent->node].opr.idx;
+      if (ent->subexp_to == str_idx)
+	{
+	  int ops_node = -1;
+	  int cls_node = -1;
+	  for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+	    {
+	      int node = dest_nodes->elems[node_idx];
+	      re_token_type_t type = dfa->nodes[node].type;
+	      if (type == OP_OPEN_SUBEXP
+		  && subexp_idx == dfa->nodes[node].opr.idx)
+		ops_node = node;
+	      else if (type == OP_CLOSE_SUBEXP
+		       && subexp_idx == dfa->nodes[node].opr.idx)
+		cls_node = node;
+	    }
+
+	  /* Check the limitation of the open subexpression.  */
+	  /* Note that (ent->subexp_to = str_idx != ent->subexp_from).  */
+	  if (ops_node >= 0)
+	    {
+	      err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes,
+					   candidates);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	    }
+
+	  /* Check the limitation of the close subexpression.  */
+	  if (cls_node >= 0)
+	    for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+	      {
+		int node = dest_nodes->elems[node_idx];
+		if (!re_node_set_contains (dfa->inveclosures + node,
+					   cls_node)
+		    && !re_node_set_contains (dfa->eclosures + node,
+					      cls_node))
+		  {
+		    /* It is against this limitation.
+		       Remove it form the current sifted state.  */
+		    err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
+						 candidates);
+		    if (BE (err != REG_NOERROR, 0))
+		      return err;
+		    --node_idx;
+		  }
+	      }
+	}
+      else /* (ent->subexp_to != str_idx)  */
+	{
+	  for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+	    {
+	      int node = dest_nodes->elems[node_idx];
+	      re_token_type_t type = dfa->nodes[node].type;
+	      if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
+		{
+		  if (subexp_idx != dfa->nodes[node].opr.idx)
+		    continue;
+		  /* It is against this limitation.
+		     Remove it form the current sifted state.  */
+		  err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
+					       candidates);
+		  if (BE (err != REG_NOERROR, 0))
+		    return err;
+		}
+	    }
+	}
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
+		   int str_idx, const re_node_set *candidates)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int node_idx, node;
+  re_sift_context_t local_sctx;
+  int first_idx = search_cur_bkref_entry (mctx, str_idx);
+
+  if (first_idx == -1)
+    return REG_NOERROR;
+
+  local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized.  */
+
+  for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
+    {
+      int enabled_idx;
+      re_token_type_t type;
+      struct re_backref_cache_entry *entry;
+      node = candidates->elems[node_idx];
+      type = dfa->nodes[node].type;
+      /* Avoid infinite loop for the REs like "()\1+".  */
+      if (node == sctx->last_node && str_idx == sctx->last_str_idx)
+	continue;
+      if (type != OP_BACK_REF)
+	continue;
+
+      entry = mctx->bkref_ents + first_idx;
+      enabled_idx = first_idx;
+      do
+	{
+	  int subexp_len;
+	  int to_idx;
+	  int dst_node;
+	  int ret;
+	  re_dfastate_t *cur_state;
+
+	  if (entry->node != node)
+	    continue;
+	  subexp_len = entry->subexp_to - entry->subexp_from;
+	  to_idx = str_idx + subexp_len;
+	  dst_node = (subexp_len ? dfa->nexts[node]
+		      : dfa->edests[node].elems[0]);
+
+	  if (to_idx > sctx->last_str_idx
+	      || sctx->sifted_states[to_idx] == NULL
+	      || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node)
+	      || check_dst_limits (mctx, &sctx->limits, node,
+				   str_idx, dst_node, to_idx))
+	    continue;
+
+	  if (local_sctx.sifted_states == NULL)
+	    {
+	      local_sctx = *sctx;
+	      err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits);
+	      if (BE (err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	  local_sctx.last_node = node;
+	  local_sctx.last_str_idx = str_idx;
+	  ret = re_node_set_insert (&local_sctx.limits, enabled_idx);
+	  if (BE (ret < 0, 0))
+	    {
+	      err = REG_ESPACE;
+	      goto free_return;
+	    }
+	  cur_state = local_sctx.sifted_states[str_idx];
+	  err = sift_states_backward (mctx, &local_sctx);
+	  if (BE (err != REG_NOERROR, 0))
+	    goto free_return;
+	  if (sctx->limited_states != NULL)
+	    {
+	      err = merge_state_array (dfa, sctx->limited_states,
+				       local_sctx.sifted_states,
+				       str_idx + 1);
+	      if (BE (err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	  local_sctx.sifted_states[str_idx] = cur_state;
+	  re_node_set_remove (&local_sctx.limits, enabled_idx);
+
+	  /* mctx->bkref_ents may have changed, reload the pointer.  */
+          entry = mctx->bkref_ents + enabled_idx;
+	}
+      while (enabled_idx++, entry++->more);
+    }
+  err = REG_NOERROR;
+ free_return:
+  if (local_sctx.sifted_states != NULL)
+    {
+      re_node_set_free (&local_sctx.limits);
+    }
+
+  return err;
+}
+
+
+#ifdef RE_ENABLE_I18N
+static int
+internal_function
+sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
+		     int node_idx, int str_idx, int max_str_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int naccepted;
+  /* Check the node can accept `multi byte'.  */
+  naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx);
+  if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
+      !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
+			    dfa->nexts[node_idx]))
+    /* The node can't accept the `multi byte', or the
+       destination was already thrown away, then the node
+       could't accept the current input `multi byte'.   */
+    naccepted = 0;
+  /* Otherwise, it is sure that the node could accept
+     `naccepted' bytes input.  */
+  return naccepted;
+}
+#endif /* RE_ENABLE_I18N */
+
+
+
+/* Functions for state transition.  */
+
+/* Return the next state to which the current state STATE will transit by
+   accepting the current input byte, and update STATE_LOG if necessary.
+   If STATE can accept a multibyte char/collating element/back reference
+   update the destination of STATE_LOG.  */
+
+static re_dfastate_t *
+internal_function
+transit_state (reg_errcode_t *err, re_match_context_t *mctx,
+	       re_dfastate_t *state)
+{
+  re_dfastate_t **trtable;
+  unsigned char ch;
+
+#ifdef RE_ENABLE_I18N
+  /* If the current state can accept multibyte.  */
+  if (BE (state->accept_mb, 0))
+    {
+      *err = transit_state_mb (mctx, state);
+      if (BE (*err != REG_NOERROR, 0))
+	return NULL;
+    }
+#endif /* RE_ENABLE_I18N */
+
+  /* Then decide the next state with the single byte.  */
+#if 0
+  if (0)
+    /* don't use transition table  */
+    return transit_state_sb (err, mctx, state);
+#endif
+
+  /* Use transition table  */
+  ch = re_string_fetch_byte (&mctx->input);
+  for (;;)
+    {
+      trtable = state->trtable;
+      if (BE (trtable != NULL, 1))
+	return trtable[ch];
+
+      trtable = state->word_trtable;
+      if (BE (trtable != NULL, 1))
+        {
+	  unsigned int context;
+	  context
+	    = re_string_context_at (&mctx->input,
+				    re_string_cur_idx (&mctx->input) - 1,
+				    mctx->eflags);
+	  if (IS_WORD_CONTEXT (context))
+	    return trtable[ch + SBC_MAX];
+	  else
+	    return trtable[ch];
+	}
+
+      if (!build_trtable (mctx->dfa, state))
+	{
+	  *err = REG_ESPACE;
+	  return NULL;
+	}
+
+      /* Retry, we now have a transition table.  */
+    }
+}
+
+/* Update the state_log if we need */
+re_dfastate_t *
+internal_function
+merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
+		      re_dfastate_t *next_state)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int cur_idx = re_string_cur_idx (&mctx->input);
+
+  if (cur_idx > mctx->state_log_top)
+    {
+      mctx->state_log[cur_idx] = next_state;
+      mctx->state_log_top = cur_idx;
+    }
+  else if (mctx->state_log[cur_idx] == 0)
+    {
+      mctx->state_log[cur_idx] = next_state;
+    }
+  else
+    {
+      re_dfastate_t *pstate;
+      unsigned int context;
+      re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
+      /* If (state_log[cur_idx] != 0), it implies that cur_idx is
+         the destination of a multibyte char/collating element/
+         back reference.  Then the next state is the union set of
+         these destinations and the results of the transition table.  */
+      pstate = mctx->state_log[cur_idx];
+      log_nodes = pstate->entrance_nodes;
+      if (next_state != NULL)
+        {
+          table_nodes = next_state->entrance_nodes;
+          *err = re_node_set_init_union (&next_nodes, table_nodes,
+					     log_nodes);
+          if (BE (*err != REG_NOERROR, 0))
+	    return NULL;
+        }
+      else
+        next_nodes = *log_nodes;
+      /* Note: We already add the nodes of the initial state,
+	 then we don't need to add them here.  */
+
+      context = re_string_context_at (&mctx->input,
+				      re_string_cur_idx (&mctx->input) - 1,
+				      mctx->eflags);
+      next_state = mctx->state_log[cur_idx]
+        = re_acquire_state_context (err, dfa, &next_nodes, context);
+      /* We don't need to check errors here, since the return value of
+         this function is next_state and ERR is already set.  */
+
+      if (table_nodes != NULL)
+        re_node_set_free (&next_nodes);
+    }
+
+  if (BE (dfa->nbackref, 0) && next_state != NULL)
+    {
+      /* Check OP_OPEN_SUBEXP in the current state in case that we use them
+	 later.  We must check them here, since the back references in the
+	 next state might use them.  */
+      *err = check_subexp_matching_top (mctx, &next_state->nodes,
+					cur_idx);
+      if (BE (*err != REG_NOERROR, 0))
+	return NULL;
+
+      /* If the next state has back references.  */
+      if (next_state->has_backref)
+	{
+	  *err = transit_state_bkref (mctx, &next_state->nodes);
+	  if (BE (*err != REG_NOERROR, 0))
+	    return NULL;
+	  next_state = mctx->state_log[cur_idx];
+	}
+    }
+
+  return next_state;
+}
+
+/* Skip bytes in the input that correspond to part of a
+   multi-byte match, then look in the log for a state
+   from which to restart matching.  */
+re_dfastate_t *
+internal_function
+find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
+{
+  re_dfastate_t *cur_state;
+  do
+    {
+      int max = mctx->state_log_top;
+      int cur_str_idx = re_string_cur_idx (&mctx->input);
+
+      do
+	{
+          if (++cur_str_idx > max)
+            return NULL;
+          re_string_skip_bytes (&mctx->input, 1);
+	}
+      while (mctx->state_log[cur_str_idx] == NULL);
+
+      cur_state = merge_state_with_log (err, mctx, NULL);
+    }
+  while (*err == REG_NOERROR && cur_state == NULL);
+  return cur_state;
+}
+
+/* Helper functions for transit_state.  */
+
+/* From the node set CUR_NODES, pick up the nodes whose types are
+   OP_OPEN_SUBEXP and which have corresponding back references in the regular
+   expression. And register them to use them later for evaluating the
+   correspoding back references.  */
+
+static reg_errcode_t
+internal_function
+check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
+			   int str_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int node_idx;
+  reg_errcode_t err;
+
+  /* TODO: This isn't efficient.
+	   Because there might be more than one nodes whose types are
+	   OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
+	   nodes.
+	   E.g. RE: (a){2}  */
+  for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)
+    {
+      int node = cur_nodes->elems[node_idx];
+      if (dfa->nodes[node].type == OP_OPEN_SUBEXP
+	  && dfa->nodes[node].opr.idx < BITSET_WORD_BITS
+	  && (dfa->used_bkref_map
+	      & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx)))
+	{
+	  err = match_ctx_add_subtop (mctx, node, str_idx);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+    }
+  return REG_NOERROR;
+}
+
+#if 0
+/* Return the next state to which the current state STATE will transit by
+   accepting the current input byte.  */
+
+static re_dfastate_t *
+transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
+		  re_dfastate_t *state)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  re_node_set next_nodes;
+  re_dfastate_t *next_state;
+  int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);
+  unsigned int context;
+
+  *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
+  if (BE (*err != REG_NOERROR, 0))
+    return NULL;
+  for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
+    {
+      int cur_node = state->nodes.elems[node_cnt];
+      if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx))
+	{
+	  *err = re_node_set_merge (&next_nodes,
+				    dfa->eclosures + dfa->nexts[cur_node]);
+	  if (BE (*err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return NULL;
+	    }
+	}
+    }
+  context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags);
+  next_state = re_acquire_state_context (err, dfa, &next_nodes, context);
+  /* We don't need to check errors here, since the return value of
+     this function is next_state and ERR is already set.  */
+
+  re_node_set_free (&next_nodes);
+  re_string_skip_bytes (&mctx->input, 1);
+  return next_state;
+}
+#endif
+
+#ifdef RE_ENABLE_I18N
+static reg_errcode_t
+internal_function
+transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int i;
+
+  for (i = 0; i < pstate->nodes.nelem; ++i)
+    {
+      re_node_set dest_nodes, *new_nodes;
+      int cur_node_idx = pstate->nodes.elems[i];
+      int naccepted, dest_idx;
+      unsigned int context;
+      re_dfastate_t *dest_state;
+
+      if (!dfa->nodes[cur_node_idx].accept_mb)
+        continue;
+
+      if (dfa->nodes[cur_node_idx].constraint)
+	{
+	  context = re_string_context_at (&mctx->input,
+					  re_string_cur_idx (&mctx->input),
+					  mctx->eflags);
+	  if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,
+					   context))
+	    continue;
+	}
+
+      /* How many bytes the node can accept?  */
+      naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,
+					   re_string_cur_idx (&mctx->input));
+      if (naccepted == 0)
+	continue;
+
+      /* The node can accepts `naccepted' bytes.  */
+      dest_idx = re_string_cur_idx (&mctx->input) + naccepted;
+      mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
+			       : mctx->max_mb_elem_len);
+      err = clean_state_log_if_needed (mctx, dest_idx);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+#ifdef DEBUG
+      assert (dfa->nexts[cur_node_idx] != -1);
+#endif
+      new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];
+
+      dest_state = mctx->state_log[dest_idx];
+      if (dest_state == NULL)
+	dest_nodes = *new_nodes;
+      else
+	{
+	  err = re_node_set_init_union (&dest_nodes,
+					dest_state->entrance_nodes, new_nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+      context = re_string_context_at (&mctx->input, dest_idx - 1,
+				      mctx->eflags);
+      mctx->state_log[dest_idx]
+	= re_acquire_state_context (&err, dfa, &dest_nodes, context);
+      if (dest_state != NULL)
+	re_node_set_free (&dest_nodes);
+      if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0))
+	return err;
+    }
+  return REG_NOERROR;
+}
+#endif /* RE_ENABLE_I18N */
+
+static reg_errcode_t
+internal_function
+transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int i;
+  int cur_str_idx = re_string_cur_idx (&mctx->input);
+
+  for (i = 0; i < nodes->nelem; ++i)
+    {
+      int dest_str_idx, prev_nelem, bkc_idx;
+      int node_idx = nodes->elems[i];
+      unsigned int context;
+      const re_token_t *node = dfa->nodes + node_idx;
+      re_node_set *new_dest_nodes;
+
+      /* Check whether `node' is a backreference or not.  */
+      if (node->type != OP_BACK_REF)
+	continue;
+
+      if (node->constraint)
+	{
+	  context = re_string_context_at (&mctx->input, cur_str_idx,
+					  mctx->eflags);
+	  if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
+	    continue;
+	}
+
+      /* `node' is a backreference.
+	 Check the substring which the substring matched.  */
+      bkc_idx = mctx->nbkref_ents;
+      err = get_subexp (mctx, node_idx, cur_str_idx);
+      if (BE (err != REG_NOERROR, 0))
+	goto free_return;
+
+      /* And add the epsilon closures (which is `new_dest_nodes') of
+	 the backreference to appropriate state_log.  */
+#ifdef DEBUG
+      assert (dfa->nexts[node_idx] != -1);
+#endif
+      for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
+	{
+	  int subexp_len;
+	  re_dfastate_t *dest_state;
+	  struct re_backref_cache_entry *bkref_ent;
+	  bkref_ent = mctx->bkref_ents + bkc_idx;
+	  if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)
+	    continue;
+	  subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;
+	  new_dest_nodes = (subexp_len == 0
+			    ? dfa->eclosures + dfa->edests[node_idx].elems[0]
+			    : dfa->eclosures + dfa->nexts[node_idx]);
+	  dest_str_idx = (cur_str_idx + bkref_ent->subexp_to
+			  - bkref_ent->subexp_from);
+	  context = re_string_context_at (&mctx->input, dest_str_idx - 1,
+					  mctx->eflags);
+	  dest_state = mctx->state_log[dest_str_idx];
+	  prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
+			: mctx->state_log[cur_str_idx]->nodes.nelem);
+	  /* Add `new_dest_node' to state_log.  */
+	  if (dest_state == NULL)
+	    {
+	      mctx->state_log[dest_str_idx]
+		= re_acquire_state_context (&err, dfa, new_dest_nodes,
+					    context);
+	      if (BE (mctx->state_log[dest_str_idx] == NULL
+		      && err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	  else
+	    {
+	      re_node_set dest_nodes;
+	      err = re_node_set_init_union (&dest_nodes,
+					    dest_state->entrance_nodes,
+					    new_dest_nodes);
+	      if (BE (err != REG_NOERROR, 0))
+		{
+		  re_node_set_free (&dest_nodes);
+		  goto free_return;
+		}
+	      mctx->state_log[dest_str_idx]
+		= re_acquire_state_context (&err, dfa, &dest_nodes, context);
+	      re_node_set_free (&dest_nodes);
+	      if (BE (mctx->state_log[dest_str_idx] == NULL
+		      && err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	  /* We need to check recursively if the backreference can epsilon
+	     transit.  */
+	  if (subexp_len == 0
+	      && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)
+	    {
+	      err = check_subexp_matching_top (mctx, new_dest_nodes,
+					       cur_str_idx);
+	      if (BE (err != REG_NOERROR, 0))
+		goto free_return;
+	      err = transit_state_bkref (mctx, new_dest_nodes);
+	      if (BE (err != REG_NOERROR, 0))
+		goto free_return;
+	    }
+	}
+    }
+  err = REG_NOERROR;
+ free_return:
+  return err;
+}
+
+/* Enumerate all the candidates which the backreference BKREF_NODE can match
+   at BKREF_STR_IDX, and register them by match_ctx_add_entry().
+   Note that we might collect inappropriate candidates here.
+   However, the cost of checking them strictly here is too high, then we
+   delay these checking for prune_impossible_nodes().  */
+
+static reg_errcode_t
+internal_function
+get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int subexp_num, sub_top_idx;
+  const char *buf = (const char *) re_string_get_buffer (&mctx->input);
+  /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX.  */
+  int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
+  if (cache_idx != -1)
+    {
+      const struct re_backref_cache_entry *entry
+	= mctx->bkref_ents + cache_idx;
+      do
+        if (entry->node == bkref_node)
+	  return REG_NOERROR; /* We already checked it.  */
+      while (entry++->more);
+    }
+
+  subexp_num = dfa->nodes[bkref_node].opr.idx;
+
+  /* For each sub expression  */
+  for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx)
+    {
+      reg_errcode_t err;
+      re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];
+      re_sub_match_last_t *sub_last;
+      int sub_last_idx, sl_str, bkref_str_off;
+
+      if (dfa->nodes[sub_top->node].opr.idx != subexp_num)
+	continue; /* It isn't related.  */
+
+      sl_str = sub_top->str_idx;
+      bkref_str_off = bkref_str_idx;
+      /* At first, check the last node of sub expressions we already
+	 evaluated.  */
+      for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)
+	{
+	  int sl_str_diff;
+	  sub_last = sub_top->lasts[sub_last_idx];
+	  sl_str_diff = sub_last->str_idx - sl_str;
+	  /* The matched string by the sub expression match with the substring
+	     at the back reference?  */
+	  if (sl_str_diff > 0)
+	    {
+	      if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0))
+		{
+		  /* Not enough chars for a successful match.  */
+		  if (bkref_str_off + sl_str_diff > mctx->input.len)
+		    break;
+
+		  err = clean_state_log_if_needed (mctx,
+						   bkref_str_off
+						   + sl_str_diff);
+		  if (BE (err != REG_NOERROR, 0))
+		    return err;
+		  buf = (const char *) re_string_get_buffer (&mctx->input);
+		}
+	      if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0)
+		/* We don't need to search this sub expression any more.  */
+		break;
+	    }
+	  bkref_str_off += sl_str_diff;
+	  sl_str += sl_str_diff;
+	  err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
+				bkref_str_idx);
+
+	  /* Reload buf, since the preceding call might have reallocated
+	     the buffer.  */
+	  buf = (const char *) re_string_get_buffer (&mctx->input);
+
+	  if (err == REG_NOMATCH)
+	    continue;
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+
+      if (sub_last_idx < sub_top->nlasts)
+	continue;
+      if (sub_last_idx > 0)
+	++sl_str;
+      /* Then, search for the other last nodes of the sub expression.  */
+      for (; sl_str <= bkref_str_idx; ++sl_str)
+	{
+	  int cls_node, sl_str_off;
+	  const re_node_set *nodes;
+	  sl_str_off = sl_str - sub_top->str_idx;
+	  /* The matched string by the sub expression match with the substring
+	     at the back reference?  */
+	  if (sl_str_off > 0)
+	    {
+	      if (BE (bkref_str_off >= mctx->input.valid_len, 0))
+		{
+		  /* If we are at the end of the input, we cannot match.  */
+		  if (bkref_str_off >= mctx->input.len)
+		    break;
+
+		  err = extend_buffers (mctx);
+		  if (BE (err != REG_NOERROR, 0))
+		    return err;
+
+		  buf = (const char *) re_string_get_buffer (&mctx->input);
+		}
+	      if (buf [bkref_str_off++] != buf[sl_str - 1])
+		break; /* We don't need to search this sub expression
+			  any more.  */
+	    }
+	  if (mctx->state_log[sl_str] == NULL)
+	    continue;
+	  /* Does this state have a ')' of the sub expression?  */
+	  nodes = &mctx->state_log[sl_str]->nodes;
+	  cls_node = find_subexp_node (dfa, nodes, subexp_num,
+				       OP_CLOSE_SUBEXP);
+	  if (cls_node == -1)
+	    continue; /* No.  */
+	  if (sub_top->path == NULL)
+	    {
+	      sub_top->path = calloc (sizeof (state_array_t),
+				      sl_str - sub_top->str_idx + 1);
+	      if (sub_top->path == NULL)
+		return REG_ESPACE;
+	    }
+	  /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node
+	     in the current context?  */
+	  err = check_arrival (mctx, sub_top->path, sub_top->node,
+			       sub_top->str_idx, cls_node, sl_str,
+			       OP_CLOSE_SUBEXP);
+	  if (err == REG_NOMATCH)
+	      continue;
+	  if (BE (err != REG_NOERROR, 0))
+	      return err;
+	  sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str);
+	  if (BE (sub_last == NULL, 0))
+	    return REG_ESPACE;
+	  err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
+				bkref_str_idx);
+	  if (err == REG_NOMATCH)
+	    continue;
+	}
+    }
+  return REG_NOERROR;
+}
+
+/* Helper functions for get_subexp().  */
+
+/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR.
+   If it can arrive, register the sub expression expressed with SUB_TOP
+   and SUB_LAST.  */
+
+static reg_errcode_t
+internal_function
+get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,
+		re_sub_match_last_t *sub_last, int bkref_node, int bkref_str)
+{
+  reg_errcode_t err;
+  int to_idx;
+  /* Can the subexpression arrive the back reference?  */
+  err = check_arrival (mctx, &sub_last->path, sub_last->node,
+		       sub_last->str_idx, bkref_node, bkref_str,
+		       OP_OPEN_SUBEXP);
+  if (err != REG_NOERROR)
+    return err;
+  err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx,
+			     sub_last->str_idx);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+  to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx;
+  return clean_state_log_if_needed (mctx, to_idx);
+}
+
+/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX.
+   Search '(' if FL_OPEN, or search ')' otherwise.
+   TODO: This function isn't efficient...
+	 Because there might be more than one nodes whose types are
+	 OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
+	 nodes.
+	 E.g. RE: (a){2}  */
+
+static int
+internal_function
+find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
+		  int subexp_idx, int type)
+{
+  int cls_idx;
+  for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)
+    {
+      int cls_node = nodes->elems[cls_idx];
+      const re_token_t *node = dfa->nodes + cls_node;
+      if (node->type == type
+	  && node->opr.idx == subexp_idx)
+	return cls_node;
+    }
+  return -1;
+}
+
+/* Check whether the node TOP_NODE at TOP_STR can arrive to the node
+   LAST_NODE at LAST_STR.  We record the path onto PATH since it will be
+   heavily reused.
+   Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise.  */
+
+static reg_errcode_t
+internal_function
+check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
+	       int top_str, int last_node, int last_str, int type)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err = REG_NOERROR;
+  int subexp_num, backup_cur_idx, str_idx, null_cnt;
+  re_dfastate_t *cur_state = NULL;
+  re_node_set *cur_nodes, next_nodes;
+  re_dfastate_t **backup_state_log;
+  unsigned int context;
+
+  subexp_num = dfa->nodes[top_node].opr.idx;
+  /* Extend the buffer if we need.  */
+  if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0))
+    {
+      re_dfastate_t **new_array;
+      int old_alloc = path->alloc;
+      path->alloc += last_str + mctx->max_mb_elem_len + 1;
+      new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);
+      if (BE (new_array == NULL, 0))
+	{
+	  path->alloc = old_alloc;
+	  return REG_ESPACE;
+	}
+      path->array = new_array;
+      memset (new_array + old_alloc, '\0',
+	      sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
+    }
+
+#ifdef __GNUC__ /* silly buggers. */
+  str_idx = path->next_idx ?: top_str;
+#else
+  str_idx = path->next_idx ? path->next_idx : top_str;
+#endif 
+
+  /* Temporary modify MCTX.  */
+  backup_state_log = mctx->state_log;
+  backup_cur_idx = mctx->input.cur_idx;
+  mctx->state_log = path->array;
+  mctx->input.cur_idx = str_idx;
+
+  /* Setup initial node set.  */
+  context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
+  if (str_idx == top_str)
+    {
+      err = re_node_set_init_1 (&next_nodes, top_node);
+      if (BE (err != REG_NOERROR, 0))
+	return err;
+      err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
+      if (BE (err != REG_NOERROR, 0))
+	{
+	  re_node_set_free (&next_nodes);
+	  return err;
+	}
+    }
+  else
+    {
+      cur_state = mctx->state_log[str_idx];
+      if (cur_state && cur_state->has_backref)
+	{
+	  err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+      else
+	re_node_set_init_empty (&next_nodes);
+    }
+  if (str_idx == top_str || (cur_state && cur_state->has_backref))
+    {
+      if (next_nodes.nelem)
+	{
+	  err = expand_bkref_cache (mctx, &next_nodes, str_idx,
+				    subexp_num, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	}
+      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
+      if (BE (cur_state == NULL && err != REG_NOERROR, 0))
+	{
+	  re_node_set_free (&next_nodes);
+	  return err;
+	}
+      mctx->state_log[str_idx] = cur_state;
+    }
+
+  for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)
+    {
+      re_node_set_empty (&next_nodes);
+      if (mctx->state_log[str_idx + 1])
+	{
+	  err = re_node_set_merge (&next_nodes,
+				   &mctx->state_log[str_idx + 1]->nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	}
+      if (cur_state)
+	{
+	  err = check_arrival_add_next_nodes (mctx, str_idx,
+					      &cur_state->non_eps_nodes,
+					      &next_nodes);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	}
+      ++str_idx;
+      if (next_nodes.nelem)
+	{
+	  err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	  err = expand_bkref_cache (mctx, &next_nodes, str_idx,
+				    subexp_num, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&next_nodes);
+	      return err;
+	    }
+	}
+      context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
+      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
+      if (BE (cur_state == NULL && err != REG_NOERROR, 0))
+	{
+	  re_node_set_free (&next_nodes);
+	  return err;
+	}
+      mctx->state_log[str_idx] = cur_state;
+      null_cnt = cur_state == NULL ? null_cnt + 1 : 0;
+    }
+  re_node_set_free (&next_nodes);
+  cur_nodes = (mctx->state_log[last_str] == NULL ? NULL
+	       : &mctx->state_log[last_str]->nodes);
+  path->next_idx = str_idx;
+
+  /* Fix MCTX.  */
+  mctx->state_log = backup_state_log;
+  mctx->input.cur_idx = backup_cur_idx;
+
+  /* Then check the current node set has the node LAST_NODE.  */
+  if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node))
+    return REG_NOERROR;
+
+  return REG_NOMATCH;
+}
+
+/* Helper functions for check_arrival.  */
+
+/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them
+   to NEXT_NODES.
+   TODO: This function is similar to the functions transit_state*(),
+	 however this function has many additional works.
+	 Can't we unify them?  */
+
+static reg_errcode_t
+internal_function
+check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
+			      re_node_set *cur_nodes, re_node_set *next_nodes)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  int result;
+  int cur_idx;
+  reg_errcode_t err = REG_NOERROR;
+  re_node_set union_set;
+  re_node_set_init_empty (&union_set);
+  for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
+    {
+      int naccepted = 0;
+      int cur_node = cur_nodes->elems[cur_idx];
+#ifdef DEBUG
+      re_token_type_t type = dfa->nodes[cur_node].type;
+      assert (!IS_EPSILON_NODE (type));
+#endif
+#ifdef RE_ENABLE_I18N
+      /* If the node may accept `multi byte'.  */
+      if (dfa->nodes[cur_node].accept_mb)
+	{
+	  naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,
+					       str_idx);
+	  if (naccepted > 1)
+	    {
+	      re_dfastate_t *dest_state;
+	      int next_node = dfa->nexts[cur_node];
+	      int next_idx = str_idx + naccepted;
+	      dest_state = mctx->state_log[next_idx];
+	      re_node_set_empty (&union_set);
+	      if (dest_state)
+		{
+		  err = re_node_set_merge (&union_set, &dest_state->nodes);
+		  if (BE (err != REG_NOERROR, 0))
+		    {
+		      re_node_set_free (&union_set);
+		      return err;
+		    }
+		}
+	      result = re_node_set_insert (&union_set, next_node);
+	      if (BE (result < 0, 0))
+		{
+		  re_node_set_free (&union_set);
+		  return REG_ESPACE;
+		}
+	      mctx->state_log[next_idx] = re_acquire_state (&err, dfa,
+							    &union_set);
+	      if (BE (mctx->state_log[next_idx] == NULL
+		      && err != REG_NOERROR, 0))
+		{
+		  re_node_set_free (&union_set);
+		  return err;
+		}
+	    }
+	}
+#endif /* RE_ENABLE_I18N */
+      if (naccepted
+	  || check_node_accept (mctx, dfa->nodes + cur_node, str_idx))
+	{
+	  result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
+	  if (BE (result < 0, 0))
+	    {
+	      re_node_set_free (&union_set);
+	      return REG_ESPACE;
+	    }
+	}
+    }
+  re_node_set_free (&union_set);
+  return REG_NOERROR;
+}
+
+/* For all the nodes in CUR_NODES, add the epsilon closures of them to
+   CUR_NODES, however exclude the nodes which are:
+    - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN.
+    - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN.
+*/
+
+static reg_errcode_t
+internal_function
+check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
+			  int ex_subexp, int type)
+{
+  reg_errcode_t err;
+  int idx, outside_node;
+  re_node_set new_nodes;
+#ifdef DEBUG
+  assert (cur_nodes->nelem);
+#endif
+  err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+  /* Create a new node set NEW_NODES with the nodes which are epsilon
+     closures of the node in CUR_NODES.  */
+
+  for (idx = 0; idx < cur_nodes->nelem; ++idx)
+    {
+      int cur_node = cur_nodes->elems[idx];
+      const re_node_set *eclosure = dfa->eclosures + cur_node;
+      outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type);
+      if (outside_node == -1)
+	{
+	  /* There are no problematic nodes, just merge them.  */
+	  err = re_node_set_merge (&new_nodes, eclosure);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&new_nodes);
+	      return err;
+	    }
+	}
+      else
+	{
+	  /* There are problematic nodes, re-calculate incrementally.  */
+	  err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,
+					      ex_subexp, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    {
+	      re_node_set_free (&new_nodes);
+	      return err;
+	    }
+	}
+    }
+  re_node_set_free (cur_nodes);
+  *cur_nodes = new_nodes;
+  return REG_NOERROR;
+}
+
+/* Helper function for check_arrival_expand_ecl.
+   Check incrementally the epsilon closure of TARGET, and if it isn't
+   problematic append it to DST_NODES.  */
+
+static reg_errcode_t
+internal_function
+check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
+			      int target, int ex_subexp, int type)
+{
+  int cur_node;
+  for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
+    {
+      int err;
+
+      if (dfa->nodes[cur_node].type == type
+	  && dfa->nodes[cur_node].opr.idx == ex_subexp)
+	{
+	  if (type == OP_CLOSE_SUBEXP)
+	    {
+	      err = re_node_set_insert (dst_nodes, cur_node);
+	      if (BE (err == -1, 0))
+		return REG_ESPACE;
+	    }
+	  break;
+	}
+      err = re_node_set_insert (dst_nodes, cur_node);
+      if (BE (err == -1, 0))
+	return REG_ESPACE;
+      if (dfa->edests[cur_node].nelem == 0)
+	break;
+      if (dfa->edests[cur_node].nelem == 2)
+	{
+	  err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
+					      dfa->edests[cur_node].elems[1],
+					      ex_subexp, type);
+	  if (BE (err != REG_NOERROR, 0))
+	    return err;
+	}
+      cur_node = dfa->edests[cur_node].elems[0];
+    }
+  return REG_NOERROR;
+}
+
+
+/* For all the back references in the current state, calculate the
+   destination of the back references by the appropriate entry
+   in MCTX->BKREF_ENTS.  */
+
+static reg_errcode_t
+internal_function
+expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
+		    int cur_str, int subexp_num, int type)
+{
+  const re_dfa_t *const dfa = mctx->dfa;
+  reg_errcode_t err;
+  int cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
+  struct re_backref_cache_entry *ent;
+
+  if (cache_idx_start == -1)
+    return REG_NOERROR;
+
+ restart:
+  ent = mctx->bkref_ents + cache_idx_start;
+  do
+    {
+      int to_idx, next_node;
+
+      /* Is this entry ENT is appropriate?  */
+      if (!re_node_set_contains (cur_nodes, ent->node))
+	continue; /* No.  */
+
+      to_idx = cur_str + ent->subexp_to - ent->subexp_from;
+      /* Calculate the destination of the back reference, and append it
+	 to MCTX->STATE_LOG.  */
+      if (to_idx == cur_str)
+	{
+	  /* The backreference did epsilon transit, we must re-check all the
+	     node in the current state.  */
+	  re_node_set new_dests;
+	  reg_errcode_t err2, err3;
+	  next_node = dfa->edests[ent->node].elems[0];
+	  if (re_node_set_contains (cur_nodes, next_node))
+	    continue;
+	  err = re_node_set_init_1 (&new_dests, next_node);
+	  err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type);
+	  err3 = re_node_set_merge (cur_nodes, &new_dests);
+	  re_node_set_free (&new_dests);
+	  if (BE (err != REG_NOERROR || err2 != REG_NOERROR
+		  || err3 != REG_NOERROR, 0))
+	    {
+	      err = (err != REG_NOERROR ? err
+		     : (err2 != REG_NOERROR ? err2 : err3));
+	      return err;
+	    }
+	  /* TODO: It is still inefficient...  */
+	  goto restart;
+	}
+      else
+	{
+	  re_node_set union_set;
+	  next_node = dfa->nexts[ent->node];
+	  if (mctx->state_log[to_idx])
+	    {
+	      int ret;
+	      if (re_node_set_contains (&mctx->state_log[to_idx]->nodes,
+					next_node))
+		continue;
+	      err = re_node_set_init_copy (&union_set,
+					   &mctx->state_log[to_idx]->nodes);
+	      ret = re_node_set_insert (&union_set, next_node);
+	      if (BE (err != REG_NOERROR || ret < 0, 0))
+		{
+		  re_node_set_free (&union_set);
+		  err = err != REG_NOERROR ? err : REG_ESPACE;
+		  return err;
+		}
+	    }
+	  else
+	    {
+	      err = re_node_set_init_1 (&union_set, next_node);
+	      if (BE (err != REG_NOERROR, 0))
+		return err;
+	    }
+	  mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set);
+	  re_node_set_free (&union_set);
+	  if (BE (mctx->state_log[to_idx] == NULL
+		  && err != REG_NOERROR, 0))
+	    return err;
+	}
+    }
+  while (ent++->more);
+  return REG_NOERROR;
+}
+
+/* Build transition table for the state.
+   Return 1 if succeeded, otherwise return NULL.  */
+
+static int
+internal_function
+build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
+{
+  reg_errcode_t err;
+  int i, j, ch, need_word_trtable = 0;
+  bitset_word_t elem, mask;
+  bool dests_node_malloced = false;
+  bool dest_states_malloced = false;
+  int ndests; /* Number of the destination states from `state'.  */
+  re_dfastate_t **trtable;
+  re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
+  re_node_set follows, *dests_node;
+  bitset_t *dests_ch;
+  bitset_t acceptable;
+
+  struct dests_alloc
+  {
+    re_node_set dests_node[SBC_MAX];
+    bitset_t dests_ch[SBC_MAX];
+  } *dests_alloc;
+
+  /* We build DFA states which corresponds to the destination nodes
+     from `state'.  `dests_node[i]' represents the nodes which i-th
+     destination state contains, and `dests_ch[i]' represents the
+     characters which i-th destination state accepts.  */
+  if (__libc_use_alloca (sizeof (struct dests_alloc)))
+    dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));
+  else
+    {
+      dests_alloc = re_malloc (struct dests_alloc, 1);
+      if (BE (dests_alloc == NULL, 0))
+	return 0;
+      dests_node_malloced = true;
+    }
+  dests_node = dests_alloc->dests_node;
+  dests_ch = dests_alloc->dests_ch;
+
+  /* Initialize transiton table.  */
+  state->word_trtable = state->trtable = NULL;
+
+  /* At first, group all nodes belonging to `state' into several
+     destinations.  */
+  ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
+  if (BE (ndests <= 0, 0))
+    {
+      if (dests_node_malloced)
+	free (dests_alloc);
+      /* Return 0 in case of an error, 1 otherwise.  */
+      if (ndests == 0)
+	{
+	  state->trtable = (re_dfastate_t **)
+	    calloc (sizeof (re_dfastate_t *), SBC_MAX);
+	  return 1;
+	}
+      return 0;
+    }
+
+  err = re_node_set_alloc (&follows, ndests + 1);
+  if (BE (err != REG_NOERROR, 0))
+    goto out_free;
+
+  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX
+			 + ndests * 3 * sizeof (re_dfastate_t *)))
+    dest_states = (re_dfastate_t **)
+      alloca (ndests * 3 * sizeof (re_dfastate_t *));
+  else
+    {
+      dest_states = (re_dfastate_t **)
+	malloc (ndests * 3 * sizeof (re_dfastate_t *));
+      if (BE (dest_states == NULL, 0))
+	{
+out_free:
+	  if (dest_states_malloced)
+	    free (dest_states);
+	  re_node_set_free (&follows);
+	  for (i = 0; i < ndests; ++i)
+	    re_node_set_free (dests_node + i);
+	  if (dests_node_malloced)
+	    free (dests_alloc);
+	  return 0;
+	}
+      dest_states_malloced = true;
+    }
+  dest_states_word = dest_states + ndests;
+  dest_states_nl = dest_states_word + ndests;
+  bitset_empty (acceptable);
+
+  /* Then build the states for all destinations.  */
+  for (i = 0; i < ndests; ++i)
+    {
+      int next_node;
+      re_node_set_empty (&follows);
+      /* Merge the follows of this destination states.  */
+      for (j = 0; j < dests_node[i].nelem; ++j)
+	{
+	  next_node = dfa->nexts[dests_node[i].elems[j]];
+	  if (next_node != -1)
+	    {
+	      err = re_node_set_merge (&follows, dfa->eclosures + next_node);
+	      if (BE (err != REG_NOERROR, 0))
+		goto out_free;
+	    }
+	}
+      dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);
+      if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0))
+	goto out_free;
+      /* If the new state has context constraint,
+	 build appropriate states for these contexts.  */
+      if (dest_states[i]->has_constraint)
+	{
+	  dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,
+							  CONTEXT_WORD);
+	  if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
+	    goto out_free;
+
+	  if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
+	    need_word_trtable = 1;
+
+	  dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
+							CONTEXT_NEWLINE);
+	  if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))
+	    goto out_free;
+ 	}
+      else
+	{
+	  dest_states_word[i] = dest_states[i];
+	  dest_states_nl[i] = dest_states[i];
+	}
+      bitset_merge (acceptable, dests_ch[i]);
+    }
+
+  if (!BE (need_word_trtable, 0))
+    {
+      /* We don't care about whether the following character is a word
+	 character, or we are in a single-byte character set so we can
+	 discern by looking at the character code: allocate a
+	 256-entry transition table.  */
+      trtable = state->trtable =
+	(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
+      if (BE (trtable == NULL, 0))
+	goto out_free;
+
+      /* For all characters ch...:  */
+      for (i = 0; i < BITSET_WORDS; ++i)
+	for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
+	     elem;
+	     mask <<= 1, elem >>= 1, ++ch)
+	  if (BE (elem & 1, 0))
+	    {
+	      /* There must be exactly one destination which accepts
+		 character ch.  See group_nodes_into_DFAstates.  */
+	      for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
+		;
+
+	      /* j-th destination accepts the word character ch.  */
+	      if (dfa->word_char[i] & mask)
+		trtable[ch] = dest_states_word[j];
+	      else
+		trtable[ch] = dest_states[j];
+	    }
+    }
+  else
+    {
+      /* We care about whether the following character is a word
+	 character, and we are in a multi-byte character set: discern
+	 by looking at the character code: build two 256-entry
+	 transition tables, one starting at trtable[0] and one
+	 starting at trtable[SBC_MAX].  */
+      trtable = state->word_trtable =
+	(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
+      if (BE (trtable == NULL, 0))
+	goto out_free;
+
+      /* For all characters ch...:  */
+      for (i = 0; i < BITSET_WORDS; ++i)
+	for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
+	     elem;
+	     mask <<= 1, elem >>= 1, ++ch)
+	  if (BE (elem & 1, 0))
+	    {
+	      /* There must be exactly one destination which accepts
+		 character ch.  See group_nodes_into_DFAstates.  */
+	      for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
+		;
+
+	      /* j-th destination accepts the word character ch.  */
+	      trtable[ch] = dest_states[j];
+	      trtable[ch + SBC_MAX] = dest_states_word[j];
+	    }
+    }
+
+  /* new line */
+  if (bitset_contain (acceptable, NEWLINE_CHAR))
+    {
+      /* The current state accepts newline character.  */
+      for (j = 0; j < ndests; ++j)
+	if (bitset_contain (dests_ch[j], NEWLINE_CHAR))
+	  {
+	    /* k-th destination accepts newline character.  */
+	    trtable[NEWLINE_CHAR] = dest_states_nl[j];
+	    if (need_word_trtable)
+	      trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j];
+	    /* There must be only one destination which accepts
+	       newline.  See group_nodes_into_DFAstates.  */
+	    break;
+	  }
+    }
+
+  if (dest_states_malloced)
+    free (dest_states);
+
+  re_node_set_free (&follows);
+  for (i = 0; i < ndests; ++i)
+    re_node_set_free (dests_node + i);
+
+  if (dests_node_malloced)
+    free (dests_alloc);
+
+  return 1;
+}
+
+/* Group all nodes belonging to STATE into several destinations.
+   Then for all destinations, set the nodes belonging to the destination
+   to DESTS_NODE[i] and set the characters accepted by the destination
+   to DEST_CH[i].  This function return the number of destinations.  */
+
+static int
+internal_function
+group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
+			    re_node_set *dests_node, bitset_t *dests_ch)
+{
+  reg_errcode_t err;
+  int result;
+  int i, j, k;
+  int ndests; /* Number of the destinations from `state'.  */
+  bitset_t accepts; /* Characters a node can accept.  */
+  const re_node_set *cur_nodes = &state->nodes;
+  bitset_empty (accepts);
+  ndests = 0;
+
+  /* For all the nodes belonging to `state',  */
+  for (i = 0; i < cur_nodes->nelem; ++i)
+    {
+      re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];
+      re_token_type_t type = node->type;
+      unsigned int constraint = node->constraint;
+
+      /* Enumerate all single byte character this node can accept.  */
+      if (type == CHARACTER)
+	bitset_set (accepts, node->opr.c);
+      else if (type == SIMPLE_BRACKET)
+	{
+	  bitset_merge (accepts, node->opr.sbcset);
+	}
+      else if (type == OP_PERIOD)
+	{
+#ifdef RE_ENABLE_I18N
+	  if (dfa->mb_cur_max > 1)
+	    bitset_merge (accepts, dfa->sb_char);
+	  else
+#endif
+	    bitset_set_all (accepts);
+	  if (!(dfa->syntax & RE_DOT_NEWLINE))
+	    bitset_clear (accepts, '\n');
+	  if (dfa->syntax & RE_DOT_NOT_NULL)
+	    bitset_clear (accepts, '\0');
+	}
+#ifdef RE_ENABLE_I18N
+      else if (type == OP_UTF8_PERIOD)
+        {
+	  memset (accepts, '\xff', sizeof (bitset_t) / 2);
+	  if (!(dfa->syntax & RE_DOT_NEWLINE))
+	    bitset_clear (accepts, '\n');
+	  if (dfa->syntax & RE_DOT_NOT_NULL)
+	    bitset_clear (accepts, '\0');
+        }
+#endif
+      else
+	continue;
+
+      /* Check the `accepts' and sift the characters which are not
+	 match it the context.  */
+      if (constraint)
+	{
+	  if (constraint & NEXT_NEWLINE_CONSTRAINT)
+	    {
+	      bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR);
+	      bitset_empty (accepts);
+	      if (accepts_newline)
+		bitset_set (accepts, NEWLINE_CHAR);
+	      else
+		continue;
+	    }
+	  if (constraint & NEXT_ENDBUF_CONSTRAINT)
+	    {
+	      bitset_empty (accepts);
+	      continue;
+	    }
+
+	  if (constraint & NEXT_WORD_CONSTRAINT)
+	    {
+	      bitset_word_t any_set = 0;
+	      if (type == CHARACTER && !node->word_char)
+		{
+		  bitset_empty (accepts);
+		  continue;
+		}
+#ifdef RE_ENABLE_I18N
+	      if (dfa->mb_cur_max > 1)
+		for (j = 0; j < BITSET_WORDS; ++j)
+		  any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
+	      else
+#endif
+		for (j = 0; j < BITSET_WORDS; ++j)
+		  any_set |= (accepts[j] &= dfa->word_char[j]);
+	      if (!any_set)
+		continue;
+	    }
+	  if (constraint & NEXT_NOTWORD_CONSTRAINT)
+	    {
+	      bitset_word_t any_set = 0;
+	      if (type == CHARACTER && node->word_char)
+		{
+		  bitset_empty (accepts);
+		  continue;
+		}
+#ifdef RE_ENABLE_I18N
+	      if (dfa->mb_cur_max > 1)
+		for (j = 0; j < BITSET_WORDS; ++j)
+		  any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
+	      else
+#endif
+		for (j = 0; j < BITSET_WORDS; ++j)
+		  any_set |= (accepts[j] &= ~dfa->word_char[j]);
+	      if (!any_set)
+		continue;
+	    }
+	}
+
+      /* Then divide `accepts' into DFA states, or create a new
+	 state.  Above, we make sure that accepts is not empty.  */
+      for (j = 0; j < ndests; ++j)
+	{
+	  bitset_t intersec; /* Intersection sets, see below.  */
+	  bitset_t remains;
+	  /* Flags, see below.  */
+	  bitset_word_t has_intersec, not_subset, not_consumed;
+
+	  /* Optimization, skip if this state doesn't accept the character.  */
+	  if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))
+	    continue;
+
+	  /* Enumerate the intersection set of this state and `accepts'.  */
+	  has_intersec = 0;
+	  for (k = 0; k < BITSET_WORDS; ++k)
+	    has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];
+	  /* And skip if the intersection set is empty.  */
+	  if (!has_intersec)
+	    continue;
+
+	  /* Then check if this state is a subset of `accepts'.  */
+	  not_subset = not_consumed = 0;
+	  for (k = 0; k < BITSET_WORDS; ++k)
+	    {
+	      not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k];
+	      not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];
+	    }
+
+	  /* If this state isn't a subset of `accepts', create a
+	     new group state, which has the `remains'. */
+	  if (not_subset)
+	    {
+	      bitset_copy (dests_ch[ndests], remains);
+	      bitset_copy (dests_ch[j], intersec);
+	      err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]);
+	      if (BE (err != REG_NOERROR, 0))
+		goto error_return;
+	      ++ndests;
+	    }
+
+	  /* Put the position in the current group. */
+	  result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
+	  if (BE (result < 0, 0))
+	    goto error_return;
+
+	  /* If all characters are consumed, go to next node. */
+	  if (!not_consumed)
+	    break;
+	}
+      /* Some characters remain, create a new group. */
+      if (j == ndests)
+	{
+	  bitset_copy (dests_ch[ndests], accepts);
+	  err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]);
+	  if (BE (err != REG_NOERROR, 0))
+	    goto error_return;
+	  ++ndests;
+	  bitset_empty (accepts);
+	}
+    }
+  return ndests;
+ error_return:
+  for (j = 0; j < ndests; ++j)
+    re_node_set_free (dests_node + j);
+  return -1;
+}
+
+#ifdef RE_ENABLE_I18N
+/* Check how many bytes the node `dfa->nodes[node_idx]' accepts.
+   Return the number of the bytes the node accepts.
+   STR_IDX is the current index of the input string.
+
+   This function handles the nodes which can accept one character, or
+   one collating element like '.', '[a-z]', opposite to the other nodes
+   can only accept one byte.  */
+
+static int
+internal_function
+check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
+			 const re_string_t *input, int str_idx)
+{
+  const re_token_t *node = dfa->nodes + node_idx;
+  int char_len, elem_len;
+  int i;
+
+  if (BE (node->type == OP_UTF8_PERIOD, 0))
+    {
+      unsigned char c = re_string_byte_at (input, str_idx), d;
+      if (BE (c < 0xc2, 1))
+	return 0;
+
+      if (str_idx + 2 > input->len)
+	return 0;
+
+      d = re_string_byte_at (input, str_idx + 1);
+      if (c < 0xe0)
+	return (d < 0x80 || d > 0xbf) ? 0 : 2;
+      else if (c < 0xf0)
+	{
+	  char_len = 3;
+	  if (c == 0xe0 && d < 0xa0)
+	    return 0;
+	}
+      else if (c < 0xf8)
+	{
+	  char_len = 4;
+	  if (c == 0xf0 && d < 0x90)
+	    return 0;
+	}
+      else if (c < 0xfc)
+	{
+	  char_len = 5;
+	  if (c == 0xf8 && d < 0x88)
+	    return 0;
+	}
+      else if (c < 0xfe)
+	{
+	  char_len = 6;
+	  if (c == 0xfc && d < 0x84)
+	    return 0;
+	}
+      else
+	return 0;
+
+      if (str_idx + char_len > input->len)
+	return 0;
+
+      for (i = 1; i < char_len; ++i)
+	{
+	  d = re_string_byte_at (input, str_idx + i);
+	  if (d < 0x80 || d > 0xbf)
+	    return 0;
+	}
+      return char_len;
+    }
+
+  char_len = re_string_char_size_at (input, str_idx);
+  if (node->type == OP_PERIOD)
+    {
+      if (char_len <= 1)
+        return 0;
+      /* FIXME: I don't think this if is needed, as both '\n'
+	 and '\0' are char_len == 1.  */
+      /* '.' accepts any one character except the following two cases.  */
+      if ((!(dfa->syntax & RE_DOT_NEWLINE) &&
+	   re_string_byte_at (input, str_idx) == '\n') ||
+	  ((dfa->syntax & RE_DOT_NOT_NULL) &&
+	   re_string_byte_at (input, str_idx) == '\0'))
+	return 0;
+      return char_len;
+    }
+
+  elem_len = re_string_elem_size_at (input, str_idx);
+  if ((elem_len <= 1 && char_len <= 1) || char_len == 0)
+    return 0;
+
+  if (node->type == COMPLEX_BRACKET)
+    {
+      const re_charset_t *cset = node->opr.mbcset;
+# ifdef _LIBC
+      const unsigned char *pin
+	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
+      int j;
+      uint32_t nrules;
+# endif /* _LIBC */
+      int match_len = 0;
+      wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
+		    ? re_string_wchar_at (input, str_idx) : 0);
+
+      /* match with multibyte character?  */
+      for (i = 0; i < cset->nmbchars; ++i)
+	if (wc == cset->mbchars[i])
+	  {
+	    match_len = char_len;
+	    goto check_node_accept_bytes_match;
+	  }
+      /* match with character_class?  */
+      for (i = 0; i < cset->nchar_classes; ++i)
+	{
+	  wctype_t wt = cset->char_classes[i];
+	  if (__iswctype (wc, wt))
+	    {
+	      match_len = char_len;
+	      goto check_node_accept_bytes_match;
+	    }
+	}
+
+# ifdef _LIBC
+      nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+      if (nrules != 0)
+	{
+	  unsigned int in_collseq = 0;
+	  const int32_t *table, *indirect;
+	  const unsigned char *weights, *extra;
+	  const char *collseqwc;
+	  int32_t idx;
+	  /* This #include defines a local function!  */
+#  include <locale/weight.h>
+
+	  /* match with collating_symbol?  */
+	  if (cset->ncoll_syms)
+	    extra = (const unsigned char *)
+	      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+	  for (i = 0; i < cset->ncoll_syms; ++i)
+	    {
+	      const unsigned char *coll_sym = extra + cset->coll_syms[i];
+	      /* Compare the length of input collating element and
+		 the length of current collating element.  */
+	      if (*coll_sym != elem_len)
+		continue;
+	      /* Compare each bytes.  */
+	      for (j = 0; j < *coll_sym; j++)
+		if (pin[j] != coll_sym[1 + j])
+		  break;
+	      if (j == *coll_sym)
+		{
+		  /* Match if every bytes is equal.  */
+		  match_len = j;
+		  goto check_node_accept_bytes_match;
+		}
+	    }
+
+	  if (cset->nranges)
+	    {
+	      if (elem_len <= char_len)
+		{
+		  collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+		  in_collseq = __collseq_table_lookup (collseqwc, wc);
+		}
+	      else
+		in_collseq = find_collation_sequence_value (pin, elem_len);
+	    }
+	  /* match with range expression?  */
+	  for (i = 0; i < cset->nranges; ++i)
+	    if (cset->range_starts[i] <= in_collseq
+		&& in_collseq <= cset->range_ends[i])
+	      {
+		match_len = elem_len;
+		goto check_node_accept_bytes_match;
+	      }
+
+	  /* match with equivalence_class?  */
+	  if (cset->nequiv_classes)
+	    {
+	      const unsigned char *cp = pin;
+	      table = (const int32_t *)
+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+	      weights = (const unsigned char *)
+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+	      extra = (const unsigned char *)
+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+	      indirect = (const int32_t *)
+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+	      idx = findidx (&cp);
+	      if (idx > 0)
+		for (i = 0; i < cset->nequiv_classes; ++i)
+		  {
+		    int32_t equiv_class_idx = cset->equiv_classes[i];
+		    size_t weight_len = weights[idx];
+		    if (weight_len == weights[equiv_class_idx])
+		      {
+			int cnt = 0;
+			while (cnt <= weight_len
+			       && (weights[equiv_class_idx + 1 + cnt]
+				   == weights[idx + 1 + cnt]))
+			  ++cnt;
+			if (cnt > weight_len)
+			  {
+			    match_len = elem_len;
+			    goto check_node_accept_bytes_match;
+			  }
+		      }
+		  }
+	    }
+	}
+      else
+# endif /* _LIBC */
+	{
+	  /* match with range expression?  */
+#if __GNUC__ >= 2
+	  wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
+#else
+	  wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
+	  cmp_buf[2] = wc;
+#endif
+	  for (i = 0; i < cset->nranges; ++i)
+	    {
+	      cmp_buf[0] = cset->range_starts[i];
+	      cmp_buf[4] = cset->range_ends[i];
+	      if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
+		  && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
+		{
+		  match_len = char_len;
+		  goto check_node_accept_bytes_match;
+		}
+	    }
+	}
+    check_node_accept_bytes_match:
+      if (!cset->non_match)
+	return match_len;
+      else
+	{
+	  if (match_len > 0)
+	    return 0;
+	  else
+	    return (elem_len > char_len) ? elem_len : char_len;
+	}
+    }
+  return 0;
+}
+
+# ifdef _LIBC
+static unsigned int
+internal_function
+find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
+{
+  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules == 0)
+    {
+      if (mbs_len == 1)
+	{
+	  /* No valid character.  Match it as a single byte character.  */
+	  const unsigned char *collseq = (const unsigned char *)
+	    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+	  return collseq[mbs[0]];
+	}
+      return UINT_MAX;
+    }
+  else
+    {
+      int32_t idx;
+      const unsigned char *extra = (const unsigned char *)
+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+      int32_t extrasize = (const unsigned char *)
+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra;
+
+      for (idx = 0; idx < extrasize;)
+	{
+	  int mbs_cnt, found = 0;
+	  int32_t elem_mbs_len;
+	  /* Skip the name of collating element name.  */
+	  idx = idx + extra[idx] + 1;
+	  elem_mbs_len = extra[idx++];
+	  if (mbs_len == elem_mbs_len)
+	    {
+	      for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt)
+		if (extra[idx + mbs_cnt] != mbs[mbs_cnt])
+		  break;
+	      if (mbs_cnt == elem_mbs_len)
+		/* Found the entry.  */
+		found = 1;
+	    }
+	  /* Skip the byte sequence of the collating element.  */
+	  idx += elem_mbs_len;
+	  /* Adjust for the alignment.  */
+	  idx = (idx + 3) & ~3;
+	  /* Skip the collation sequence value.  */
+	  idx += sizeof (uint32_t);
+	  /* Skip the wide char sequence of the collating element.  */
+	  idx = idx + sizeof (uint32_t) * (extra[idx] + 1);
+	  /* If we found the entry, return the sequence value.  */
+	  if (found)
+	    return *(uint32_t *) (extra + idx);
+	  /* Skip the collation sequence value.  */
+	  idx += sizeof (uint32_t);
+	}
+      return UINT_MAX;
+    }
+}
+# endif /* _LIBC */
+#endif /* RE_ENABLE_I18N */
+
+/* Check whether the node accepts the byte which is IDX-th
+   byte of the INPUT.  */
+
+static int
+internal_function
+check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
+		   int idx)
+{
+  unsigned char ch;
+  ch = re_string_byte_at (&mctx->input, idx);
+  switch (node->type)
+    {
+    case CHARACTER:
+      if (node->opr.c != ch)
+        return 0;
+      break;
+
+    case SIMPLE_BRACKET:
+      if (!bitset_contain (node->opr.sbcset, ch))
+        return 0;
+      break;
+
+#ifdef RE_ENABLE_I18N
+    case OP_UTF8_PERIOD:
+      if (ch >= 0x80)
+        return 0;
+      /* FALLTHROUGH */
+#endif
+    case OP_PERIOD:
+      if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE))
+	  || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL)))
+	return 0;
+      break;
+
+    default:
+      return 0;
+    }
+
+  if (node->constraint)
+    {
+      /* The node has constraints.  Check whether the current context
+	 satisfies the constraints.  */
+      unsigned int context = re_string_context_at (&mctx->input, idx,
+						   mctx->eflags);
+      if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
+	return 0;
+    }
+
+  return 1;
+}
+
+/* Extend the buffers, if the buffers have run out.  */
+
+static reg_errcode_t
+internal_function
+extend_buffers (re_match_context_t *mctx)
+{
+  reg_errcode_t ret;
+  re_string_t *pstr = &mctx->input;
+
+  /* Double the lengthes of the buffers.  */
+  ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+
+  if (mctx->state_log != NULL)
+    {
+      /* And double the length of state_log.  */
+      /* XXX We have no indication of the size of this buffer.  If this
+	 allocation fail we have no indication that the state_log array
+	 does not have the right size.  */
+      re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *,
+					      pstr->bufs_len + 1);
+      if (BE (new_array == NULL, 0))
+	return REG_ESPACE;
+      mctx->state_log = new_array;
+    }
+
+  /* Then reconstruct the buffers.  */
+  if (pstr->icase)
+    {
+#ifdef RE_ENABLE_I18N
+      if (pstr->mb_cur_max > 1)
+	{
+	  ret = build_wcs_upper_buffer (pstr);
+	  if (BE (ret != REG_NOERROR, 0))
+	    return ret;
+	}
+      else
+#endif /* RE_ENABLE_I18N  */
+	build_upper_buffer (pstr);
+    }
+  else
+    {
+#ifdef RE_ENABLE_I18N
+      if (pstr->mb_cur_max > 1)
+	build_wcs_buffer (pstr);
+      else
+#endif /* RE_ENABLE_I18N  */
+	{
+	  if (pstr->trans != NULL)
+	    re_string_translate_buffer (pstr);
+	}
+    }
+  return REG_NOERROR;
+}
+
+
+
+/* Functions for matching context.  */
+
+/* Initialize MCTX.  */
+
+static reg_errcode_t
+internal_function
+match_ctx_init (re_match_context_t *mctx, int eflags, int n)
+{
+  mctx->eflags = eflags;
+  mctx->match_last = -1;
+  if (n > 0)
+    {
+      mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
+      mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);
+      if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0))
+	return REG_ESPACE;
+    }
+  /* Already zero-ed by the caller.
+     else
+       mctx->bkref_ents = NULL;
+     mctx->nbkref_ents = 0;
+     mctx->nsub_tops = 0;  */
+  mctx->abkref_ents = n;
+  mctx->max_mb_elem_len = 1;
+  mctx->asub_tops = n;
+  return REG_NOERROR;
+}
+
+/* Clean the entries which depend on the current input in MCTX.
+   This function must be invoked when the matcher changes the start index
+   of the input, or changes the input string.  */
+
+static void
+internal_function
+match_ctx_clean (re_match_context_t *mctx)
+{
+  int st_idx;
+  for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx)
+    {
+      int sl_idx;
+      re_sub_match_top_t *top = mctx->sub_tops[st_idx];
+      for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx)
+	{
+	  re_sub_match_last_t *last = top->lasts[sl_idx];
+	  re_free (last->path.array);
+	  re_free (last);
+	}
+      re_free (top->lasts);
+      if (top->path)
+	{
+	  re_free (top->path->array);
+	  re_free (top->path);
+	}
+      free (top);
+    }
+
+  mctx->nsub_tops = 0;
+  mctx->nbkref_ents = 0;
+}
+
+/* Free all the memory associated with MCTX.  */
+
+static void
+internal_function
+match_ctx_free (re_match_context_t *mctx)
+{
+  /* First, free all the memory associated with MCTX->SUB_TOPS.  */
+  match_ctx_clean (mctx);
+  re_free (mctx->sub_tops);
+  re_free (mctx->bkref_ents);
+}
+
+/* Add a new backreference entry to MCTX.
+   Note that we assume that caller never call this function with duplicate
+   entry, and call with STR_IDX which isn't smaller than any existing entry.
+*/
+
+static reg_errcode_t
+internal_function
+match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from,
+		     int to)
+{
+  if (mctx->nbkref_ents >= mctx->abkref_ents)
+    {
+      struct re_backref_cache_entry* new_entry;
+      new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,
+			      mctx->abkref_ents * 2);
+      if (BE (new_entry == NULL, 0))
+	{
+	  re_free (mctx->bkref_ents);
+	  return REG_ESPACE;
+	}
+      mctx->bkref_ents = new_entry;
+      memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
+	      sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
+      mctx->abkref_ents *= 2;
+    }
+  if (mctx->nbkref_ents > 0
+      && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx)
+    mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1;
+
+  mctx->bkref_ents[mctx->nbkref_ents].node = node;
+  mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx;
+  mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from;
+  mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to;
+
+  /* This is a cache that saves negative results of check_dst_limits_calc_pos.
+     If bit N is clear, means that this entry won't epsilon-transition to
+     an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression.  If
+     it is set, check_dst_limits_calc_pos_1 will recurse and try to find one
+     such node.
+
+     A backreference does not epsilon-transition unless it is empty, so set
+     to all zeros if FROM != TO.  */
+  mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map
+    = (from == to ? ~0 : 0);
+
+  mctx->bkref_ents[mctx->nbkref_ents++].more = 0;
+  if (mctx->max_mb_elem_len < to - from)
+    mctx->max_mb_elem_len = to - from;
+  return REG_NOERROR;
+}
+
+/* Search for the first entry which has the same str_idx, or -1 if none is
+   found.  Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX.  */
+
+static int
+internal_function
+search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
+{
+  int left, right, mid, last;
+  last = right = mctx->nbkref_ents;
+  for (left = 0; left < right;)
+    {
+      mid = (left + right) / 2;
+      if (mctx->bkref_ents[mid].str_idx < str_idx)
+	left = mid + 1;
+      else
+	right = mid;
+    }
+  if (left < last && mctx->bkref_ents[left].str_idx == str_idx)
+    return left;
+  else
+    return -1;
+}
+
+/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches
+   at STR_IDX.  */
+
+static reg_errcode_t
+internal_function
+match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)
+{
+#ifdef DEBUG
+  assert (mctx->sub_tops != NULL);
+  assert (mctx->asub_tops > 0);
+#endif
+  if (BE (mctx->nsub_tops == mctx->asub_tops, 0))
+    {
+      int new_asub_tops = mctx->asub_tops * 2;
+      re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops,
+						   re_sub_match_top_t *,
+						   new_asub_tops);
+      if (BE (new_array == NULL, 0))
+	return REG_ESPACE;
+      mctx->sub_tops = new_array;
+      mctx->asub_tops = new_asub_tops;
+    }
+  mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t));
+  if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0))
+    return REG_ESPACE;
+  mctx->sub_tops[mctx->nsub_tops]->node = node;
+  mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx;
+  return REG_NOERROR;
+}
+
+/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches
+   at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP.  */
+
+static re_sub_match_last_t *
+internal_function
+match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx)
+{
+  re_sub_match_last_t *new_entry;
+  if (BE (subtop->nlasts == subtop->alasts, 0))
+    {
+      int new_alasts = 2 * subtop->alasts + 1;
+      re_sub_match_last_t **new_array = re_realloc (subtop->lasts,
+						    re_sub_match_last_t *,
+						    new_alasts);
+      if (BE (new_array == NULL, 0))
+	return NULL;
+      subtop->lasts = new_array;
+      subtop->alasts = new_alasts;
+    }
+  new_entry = calloc (1, sizeof (re_sub_match_last_t));
+  if (BE (new_entry != NULL, 1))
+    {
+      subtop->lasts[subtop->nlasts] = new_entry;
+      new_entry->node = node;
+      new_entry->str_idx = str_idx;
+      ++subtop->nlasts;
+    }
+  return new_entry;
+}
+
+static void
+internal_function
+sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
+	       re_dfastate_t **limited_sts, int last_node, int last_str_idx)
+{
+  sctx->sifted_states = sifted_sts;
+  sctx->limited_states = limited_sts;
+  sctx->last_node = last_node;
+  sctx->last_str_idx = last_str_idx;
+  re_node_set_init_empty (&sctx->limits);
+}
Index: /tags/kBuild-0.1.4/src/sed/lib/stdbool_.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/stdbool_.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/stdbool_.h	(revision 1780)
@@ -0,0 +1,47 @@
+/* Copyright (C) 2001-2002 Free Software Foundation, Inc.
+   Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _STDBOOL_H
+#define _STDBOOL_H
+
+/* ISO C 99 <stdbool.h> for platforms that lack it.  */
+
+/* 7.16. Boolean type and values */
+
+/* BeOS <sys/socket.h> already #defines false 0, true 1.  We use the same
+   definitions below, but temporarily we have to #undef them.  */
+#ifdef __BEOS__
+# undef false
+# undef true
+#endif
+
+/* For the sake of symbolic names in gdb, define _Bool as an enum type.  */
+#ifndef __cplusplus
+# if !@HAVE__BOOL@
+typedef enum { false = 0, true = 1 } _Bool;
+# endif
+#else
+typedef bool _Bool;
+#endif
+#define bool _Bool
+
+/* The other macros must be usable in preprocessor directives.  */
+#define false 0
+#define true 1
+#define __bool_true_false_are_defined 1
+
+#endif /* _STDBOOL_H */
Index: /tags/kBuild-0.1.4/src/sed/lib/strerror.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/strerror.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/strerror.c	(revision 1780)
@@ -0,0 +1,52 @@
+/* strerror -- return a string corresponding to an error number.
+   This is a quickie version only intended as compatability glue
+   for systems which predate the ANSI C definition of the function;
+   the glibc version is recommended for more general use.
+
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+
+#ifndef HAVE_STRERROR
+
+# ifndef BOOTSTRAP
+#  include <stdio.h>
+# endif
+# ifdef HAVE_STRING_H
+#  include <string.h>
+# endif
+# include <errno.h>
+# undef strerror
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char *
+strerror(e)
+  int e;
+{
+  static char unknown_string[] =
+    "Unknown error code #xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+
+  if (0<=e && e<sys_nerr)
+    return sys_errlist[e];
+  sprintf(unknown_string+20, "%d", e);
+  return unknown_string;
+}
+
+#endif /* !HAVE_STRERROR */
Index: /tags/kBuild-0.1.4/src/sed/lib/strverscmp.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/strverscmp.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/strverscmp.c	(revision 1780)
@@ -0,0 +1,132 @@
+/* Compare strings while treating digits characters numerically.
+   Copyright (C) 1997, 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
+           fractional parts, S_Z: idem but with leading Zeroes only */
+#define S_N    0x0
+#define S_I    0x4
+#define S_F    0x8
+#define S_Z    0xC
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define CMP    2
+#define LEN    3
+
+
+/* ISDIGIT differs from isdigit, as follows:
+   - Its arg may be any int or unsigned int; it need not be an unsigned char.
+   - It's guaranteed to evaluate its argument exactly once.
+   - It's typically faster.
+   POSIX says that only '0' through '9' are digits.  Prefer ISDIGIT to
+   ISDIGIT_LOCALE unless it's important to use the locale's definition
+   of `digit' even when the host does not conform to POSIX.  */
+#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
+
+#undef __strverscmp
+#undef strverscmp
+
+#ifndef weak_alias
+# define __strverscmp strverscmp
+#endif
+
+/* Compare S1 and S2 as strings holding indices/version numbers,
+   returning less than, equal to or greater than zero if S1 is less than,
+   equal to or greater than S2 (for more info, see the texinfo doc).
+*/
+
+int
+__strverscmp (const char *s1, const char *s2)
+{
+  const unsigned char *p1 = (const unsigned char *) s1;
+  const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+  int state;
+  int diff;
+
+  /* Symbol(s)    0       [1-9]   others  (padding)
+     Transition   (10) 0  (01) d  (00) x  (11) -   */
+  static const unsigned int next_state[] =
+  {
+      /* state    x    d    0    - */
+      /* S_N */  S_N, S_I, S_Z, S_N,
+      /* S_I */  S_N, S_I, S_I, S_I,
+      /* S_F */  S_N, S_F, S_F, S_F,
+      /* S_Z */  S_N, S_F, S_Z, S_Z
+  };
+
+  static const int result_type[] =
+  {
+      /* state   x/x  x/d  x/0  x/-  d/x  d/d  d/0  d/-
+                 0/x  0/d  0/0  0/-  -/x  -/d  -/0  -/- */
+
+      /* S_N */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+      /* S_I */  CMP, -1,  -1,  CMP,  1,  LEN, LEN, CMP,
+                  1,  LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+      /* S_F */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+      /* S_Z */  CMP,  1,   1,  CMP, -1,  CMP, CMP, CMP,
+                 -1,  CMP, CMP, CMP
+  };
+
+  if (p1 == p2)
+    return 0;
+
+  c1 = *p1++;
+  c2 = *p2++;
+  /* Hint: '0' is a digit too.  */
+  state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0));
+
+  while ((diff = c1 - c2) == 0 && c1 != '\0')
+    {
+      state = next_state[state];
+      c1 = *p1++;
+      c2 = *p2++;
+      state |= (c1 == '0') + (ISDIGIT (c1) != 0);
+    }
+
+  state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))];
+
+  switch (state)
+    {
+    case CMP:
+      return diff;
+
+    case LEN:
+      while (ISDIGIT (*p1++))
+	if (!ISDIGIT (*p2++))
+	  return 1;
+
+      return ISDIGIT (*p2) ? -1 : diff;
+
+    default:
+      return state;
+    }
+}
+#ifdef weak_alias
+weak_alias (__strverscmp, strverscmp)
+#endif
Index: /tags/kBuild-0.1.4/src/sed/lib/strverscmp.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/strverscmp.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/strverscmp.h	(revision 1780)
@@ -0,0 +1,20 @@
+/* strverscmp.h -- compare strings holding indices/version numbers */
+
+#ifndef STRVERSCMP_H_
+# define STRVERSCMP_H_
+
+# if HAVE_CONFIG_H
+#  include <config.h>
+# endif
+
+# ifndef PARAMS
+#  if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+#   define PARAMS(Args) Args
+#  else
+#   define PARAMS(Args) ()
+#  endif
+# endif
+
+int strverscmp PARAMS ((const char*, const char*));
+
+#endif /* not STRVERSCMP_H_ */
Index: /tags/kBuild-0.1.4/src/sed/lib/utils.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/utils.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/utils.c	(revision 1780)
@@ -0,0 +1,524 @@
+/*  Functions from hack's utils library.
+    Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003
+    Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include <errno.h>
+#ifndef errno
+  extern int errno;
+#endif
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#else
+# include <string.h>
+#endif /* HAVE_STRINGS_H */
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#include "utils.h"
+
+const char *myname;
+
+/* Store information about files opened with ck_fopen
+   so that error messages from ck_fread, ck_fwrite, etc. can print the
+   name of the file that had the error */
+
+struct open_file
+  {
+    FILE *fp;
+    char *name;
+    struct open_file *link;
+    unsigned temp : 1;
+  };
+
+static struct open_file *open_files = NULL;
+static void do_ck_fclose P_((FILE *fp));
+
+/* Print an error message and exit */
+#if !defined __STDC__ || !(__STDC__-0)
+# include <varargs.h>
+# define VSTART(l,a)	va_start(l)
+void
+panic(str, va_alist)
+  char *str;
+  va_dcl
+#else /*__STDC__*/
+# include <stdarg.h>
+# define VSTART(l,a)	va_start(l, a)
+void
+panic(const char *str, ...)
+#endif /* __STDC__ */
+{
+  va_list iggy;
+
+  fprintf(stderr, "%s: ", myname);
+  VSTART(iggy, str);
+#ifndef HAVE_VPRINTF
+# ifndef HAVE_DOPRNT
+  fputs(str, stderr);	/* not great, but perhaps better than nothing... */
+# else /* HAVE_DOPRNT */
+  _doprnt(str, &iggy, stderr);
+# endif /* HAVE_DOPRNT */
+#else /* HAVE_VFPRINTF */
+  vfprintf(stderr, str, iggy);
+#endif /* HAVE_VFPRINTF */
+  va_end(iggy);
+  putc('\n', stderr);
+
+  /* Unlink the temporary files.  */
+  while (open_files)
+    {
+      if (open_files->temp)
+	{
+	  int fd = fileno (open_files->fp);
+	  fclose (open_files->fp);
+	  errno = 0;
+	  unlink (open_files->name);
+          if (errno != 0)
+            fprintf (stderr, _("cannot remove %s: %s"), open_files->name, strerror (errno));
+	}
+
+      open_files = open_files->link;
+    }
+
+  exit(4);
+}
+
+
+
+/* Internal routine to get a filename from open_files */
+static const char *utils_fp_name P_((FILE *fp));
+static const char *
+utils_fp_name(fp)
+  FILE *fp;
+{
+  struct open_file *p;
+
+  for (p=open_files; p; p=p->link)
+    if (p->fp == fp)
+      return p->name;
+  if (fp == stdin)
+    return "stdin";
+  else if (fp == stdout)
+    return "stdout";
+  else if (fp == stderr)
+    return "stderr";
+
+  return "<unknown>";
+}
+
+/* Panic on failing fopen */
+FILE *
+ck_fopen(name, mode, fail)
+  const char *name;
+  const char *mode;
+  bool fail;
+{
+  FILE *fp;
+  struct open_file *p;
+
+  fp = fopen (name, mode);
+  if (!fp)
+    {
+      if (fail)
+        panic(_("couldn't open file %s: %s"), name, strerror(errno));
+
+      return NULL;
+    }
+
+  for (p=open_files; p; p=p->link)
+    {
+      if (fp == p->fp)
+	{
+	  FREE(p->name);
+	  break;
+	}
+    }
+  if (!p)
+    {
+      p = MALLOC(1, struct open_file);
+      p->link = open_files;
+      open_files = p;
+    }
+  p->name = ck_strdup(name);
+  p->fp = fp;
+  p->temp = false;
+  return fp;
+}
+
+FILE *
+ck_mkstemp (p_filename, tmpdir, base)
+  char **p_filename;
+  char *base, *tmpdir;
+{
+  char *template;
+  FILE *fp;
+  int fd;
+  struct open_file *p;
+
+  if (tmpdir == NULL)
+    tmpdir = getenv("TMPDIR");
+  if (tmpdir == NULL)
+    {
+      tmpdir = getenv("TMP");
+      if (tmpdir == NULL)
+#ifdef P_tmpdir
+	tmpdir = P_tmpdir;
+#else
+	tmpdir = "/tmp";
+#endif
+    }
+
+  template = xmalloc (strlen (tmpdir) + strlen (base) + 8);
+  sprintf (template, "%s/%sXXXXXX", tmpdir, base);
+
+  fd = mkstemp (template);
+  if (fd == -1)
+    panic(_("couldn't open temporary file %s: %s"), template, strerror(errno));
+
+  *p_filename = template;
+  fp = fdopen (fd, "w");
+
+  p = MALLOC(1, struct open_file);
+  p->name = ck_strdup (template);
+  p->fp = fp;
+  p->temp = true;
+  p->link = open_files;
+  open_files = p;
+  return fp;
+}
+
+/* Panic on failing fwrite */
+void
+ck_fwrite(ptr, size, nmemb, stream)
+  const VOID *ptr;
+  size_t size;
+  size_t nmemb;
+  FILE *stream;
+{
+  clearerr(stream);
+  if (size && fwrite(ptr, size, nmemb, stream) != nmemb)
+    panic(ngettext("couldn't write %d item to %s: %s",
+		   "couldn't write %d items to %s: %s", nmemb), 
+		nmemb, utils_fp_name(stream), strerror(errno));
+}
+
+/* Panic on failing fread */
+size_t
+ck_fread(ptr, size, nmemb, stream)
+  VOID *ptr;
+  size_t size;
+  size_t nmemb;
+  FILE *stream;
+{
+  clearerr(stream);
+  if (size && (nmemb=fread(ptr, size, nmemb, stream)) <= 0 && ferror(stream))
+    panic(_("read error on %s: %s"), utils_fp_name(stream), strerror(errno));
+
+  return nmemb;
+}
+
+size_t
+ck_getline(text, buflen, stream)
+  char **text;
+  size_t *buflen;
+  FILE *stream;
+{
+  int result;
+  if (!ferror (stream))
+    result = getline (text, buflen, stream);
+
+  if (ferror (stream))
+    panic (_("read error on %s: %s"), utils_fp_name(stream), strerror(errno));
+
+  return result;
+}
+
+/* Panic on failing fflush */
+void
+ck_fflush(stream)
+  FILE *stream;
+{
+  clearerr(stream);
+  if (fflush(stream) == EOF && errno != EBADF)
+    panic("couldn't flush %s: %s", utils_fp_name(stream), strerror(errno));
+}
+
+/* Panic on failing fclose */
+void
+ck_fclose(stream)
+  FILE *stream;
+{
+  struct open_file r;
+  struct open_file *prev;
+  struct open_file *cur;
+
+  /* a NULL stream means to close all files */
+  r.link = open_files;
+  prev = &r;
+  while ( (cur = prev->link) )
+    {
+      if (!stream || stream == cur->fp)
+	{
+	  do_ck_fclose (cur->fp);
+	  prev->link = cur->link;
+	  FREE(cur->name);
+	  FREE(cur);
+	}
+      else
+	prev = cur;
+    }
+
+  open_files = r.link;
+
+  /* Also care about stdout, because if it is redirected the
+     last output operations might fail and it is important
+     to signal this as an error (perhaps to make). */
+  if (!stream)
+    {
+      do_ck_fclose (stdout);
+      do_ck_fclose (stderr);
+    }
+}
+
+/* Close a single file. */
+void
+do_ck_fclose(fp)
+  FILE *fp;
+{
+  int fd;
+  ck_fflush(fp);
+  clearerr(fp);
+
+  /* We want to execute both arms, so use | not ||.  */
+  if (fclose(fp) == EOF)
+    panic("couldn't close %s: %s", utils_fp_name(fp), strerror(errno));
+}
+
+
+
+/* Panic on failing rename */
+void
+ck_rename (from, to, unlink_if_fail)
+  const char *from, *to;
+  const char *unlink_if_fail;
+{
+  int rd = rename (from, to);
+  if (rd != -1)
+    return;
+
+  if (unlink_if_fail)
+    {
+      int save_errno = errno;
+      errno = 0;
+      unlink (unlink_if_fail);
+
+      /* Failure to remove the temporary file is more severe, so trigger it first.  */
+      if (errno != 0)
+        panic (_("cannot remove %s: %s"), unlink_if_fail, strerror (errno));
+
+      errno = save_errno;
+    }
+
+  panic (_("cannot rename %s: %s"), from, strerror (errno));
+}
+
+
+
+
+
+/* Panic on failing malloc */
+VOID *
+ck_malloc(size)
+  size_t size;
+{
+  VOID *ret = calloc(1, size ? size : 1);
+  if (!ret)
+    panic("couldn't allocate memory");
+  return ret;
+}
+
+/* Panic on failing malloc */
+VOID *
+xmalloc(size)
+  size_t size;
+{
+  return ck_malloc(size);
+}
+
+/* Panic on failing realloc */
+VOID *
+ck_realloc(ptr, size)
+  VOID *ptr;
+  size_t size;
+{
+  VOID *ret;
+
+  if (size == 0)
+    {
+      FREE(ptr);
+      return NULL;
+    }
+  if (!ptr)
+    return ck_malloc(size);
+  ret = realloc(ptr, size);
+  if (!ret)
+    panic("couldn't re-allocate memory");
+  return ret;
+}
+
+/* Return a malloc()'d copy of a string */
+char *
+ck_strdup(str)
+  const char *str;
+{
+  char *ret = MALLOC(strlen(str)+1, char);
+  return strcpy(ret, str);
+}
+
+/* Return a malloc()'d copy of a block of memory */
+VOID *
+ck_memdup(buf, len)
+  const VOID *buf;
+  size_t len;
+{
+  VOID *ret = ck_malloc(len);
+  return memcpy(ret, buf, len);
+}
+
+/* Release a malloc'd block of memory */
+void
+ck_free(ptr)
+  VOID *ptr;
+{
+  if (ptr)
+    free(ptr);
+}
+
+
+
+/* Implement a variable sized buffer of `stuff'.  We don't know what it is,
+nor do we care, as long as it doesn't mind being aligned by malloc. */
+
+struct buffer
+  {
+    size_t allocated;
+    size_t length;
+    char *b;
+  };
+
+#define MIN_ALLOCATE 50
+
+struct buffer *
+init_buffer()
+{
+  struct buffer *b = MALLOC(1, struct buffer);
+  b->b = MALLOC(MIN_ALLOCATE, char);
+  b->allocated = MIN_ALLOCATE;
+  b->length = 0;
+  return b;
+}
+
+char *
+get_buffer(b)
+  struct buffer *b;
+{
+  return b->b;
+}
+
+size_t
+size_buffer(b)
+  struct buffer *b;
+{
+  return b->length;
+}
+
+static void resize_buffer P_((struct buffer *b, size_t newlen));
+static void
+resize_buffer(b, newlen)
+  struct buffer *b;
+  size_t newlen;
+{
+  char *try = NULL;
+  size_t alen = b->allocated;
+
+  if (newlen <= alen)
+    return;
+  alen *= 2;
+  if (newlen < alen)
+    try = realloc(b->b, alen);	/* Note: *not* the REALLOC() macro! */
+  if (!try)
+    {
+      alen = newlen;
+      try = REALLOC(b->b, alen, char);
+    }
+  b->allocated = alen;
+  b->b = try;
+}
+
+char *
+add_buffer(b, p, n)
+  struct buffer *b;
+  const char *p;
+  size_t n;
+{
+  char *result;
+  if (b->allocated - b->length < n)
+    resize_buffer(b, b->length+n);
+  result = memcpy(b->b + b->length, p, n);
+  b->length += n;
+  return result;
+}
+
+char *
+add1_buffer(b, c)
+  struct buffer *b;
+  int c;
+{
+  /* This special case should be kept cheap;
+   *  don't make it just a mere convenience
+   *  wrapper for add_buffer() -- even "builtin"
+   *  versions of memcpy(a, b, 1) can become
+   *  expensive when called too often.
+   */
+  if (c != EOF)
+    {
+      char *result;
+      if (b->allocated - b->length < 1)
+	resize_buffer(b, b->length+1);
+      result = b->b + b->length++;
+      *result = c;
+      return result;
+    }
+
+  return NULL;
+}
+
+void
+free_buffer(b)
+  struct buffer *b;
+{
+  if (b)
+    FREE(b->b);
+  FREE(b);
+}
Index: /tags/kBuild-0.1.4/src/sed/lib/utils.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/lib/utils.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/lib/utils.h	(revision 1780)
@@ -0,0 +1,48 @@
+/*  Functions from hack's utils library.
+    Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003
+    Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stdio.h>
+
+#include "basicdefs.h"
+
+void panic P_((const char *str, ...));
+
+FILE *ck_fopen P_((const char *name, const char *mode, bool fail));
+void ck_fwrite P_((const VOID *ptr, size_t size, size_t nmemb, FILE *stream));
+size_t ck_fread P_((VOID *ptr, size_t size, size_t nmemb, FILE *stream));
+void ck_fflush P_((FILE *stream));
+void ck_fclose P_((FILE *stream));
+size_t ck_getline P_((char **text, size_t *buflen, FILE *stream));
+FILE * ck_mkstemp P_((char **p_filename, char *tmpdir, char *base));
+void ck_rename P_((const char *from, const char *to, const char *unlink_if_fail));
+
+VOID *ck_malloc P_((size_t size));
+VOID *xmalloc P_((size_t size));
+VOID *ck_realloc P_((VOID *ptr, size_t size));
+char *ck_strdup P_((const char *str));
+VOID *ck_memdup P_((const VOID *buf, size_t len));
+void ck_free P_((VOID *ptr));
+
+struct buffer *init_buffer P_((void));
+char *get_buffer P_((struct buffer *b));
+size_t size_buffer P_((struct buffer *b));
+char *add_buffer P_((struct buffer *b, const char *p, size_t n));
+char *add1_buffer P_((struct buffer *b, int ch));
+void free_buffer P_((struct buffer *b));
+
+extern const char *myname;
Index: /tags/kBuild-0.1.4/src/sed/po/ChangeLog
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/ChangeLog	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/ChangeLog	(revision 1780)
@@ -0,0 +1,53 @@
+2004-11-11  Paolo Bonzini  <bonzini@gnu.org>
+
+	* Makevars: New.
+
+2004-11-02  gettextize  <bug-gnu-utils@gnu.org>
+
+	* Makefile.in.in: Upgrade to gettext-0.10.40.
+
+2002-10-26  Paolo Bonzini  <bonzini@gnu.org>
+
+	* po/*.po: updated from Translation Project
+
+2001-10-19  gettextize  <bug-gnu-utils@gnu.org>
+
+	* Makefile.in.in: Upgrade to gettext-0.10.40.
+	* cat-id-tbl.c: Remove file.
+	* stamp-cat-id: Remove file.
+
+2001-03-02  Paolo Bonzini  <bonzini@gnu.org>
+
+	* po/it.po: updated
+	* po/sed.pot: likewise.
+	
+2000-12-10  Paolo Bonzini  <bonzini@gnu.org>
+
+	* po/it.po: Italian translation reviewed for new POT file.
+	* po/sed.pot: updated
+
+Mon Mar 15 16:25:53 PST 1999  Ken Pizzini <ken@gnu.org>
+
+	* po/it.po: new translation file.
+
+Sun Feb  7 21:22:17 PST 1999  Ken Pizzini <ken@gnu.org>
+
+	* po/de.po: new translation file.
+
+Sat Dec 12 11:18:55 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* po/ru.po: new translation file.
+
+Sun Dec  6 00:51:23 PST 1998  Ken Pizzini <ken@gnu.org>
+
+	* po/fr.po: new translation file.
+
+Sun Aug 16 02:59:20 PDT 1998  Ken Pizzini <ken@gnu.org>
+
+	* sed/compile.c: added N_() markers and corresponding gettext()
+	  (er, _()) calls.
+	* po/sed.pot: updated to reflect changed and newly marked text.
+
+1998-07-24  Erick Branderhorst  <Erick.Branderhorst@asml.nl>
+
+	* po/nl.po: Dutch translation.
Index: /tags/kBuild-0.1.4/src/sed/po/LINGUAS
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/LINGUAS	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/LINGUAS	(revision 1780)
@@ -0,0 +1,1 @@
+af ca cs da de el eo es et fi fr ga gl he hr hu id it ja ko nl pl pt_BR ro ru sk sl sr sv tr zh_CN
Index: /tags/kBuild-0.1.4/src/sed/po/Makefile.in.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/Makefile.in.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/Makefile.in.in	(revision 1780)
@@ -0,0 +1,300 @@
+# Makefile for PO directory in any package using GNU gettext.
+# Copyright (C) 1995-1997, 2000-2002 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+#
+# This file can be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU General Public
+# License but which still want to provide support for the GNU gettext
+# functionality.
+# Please note that the actual code of GNU gettext is covered by the GNU
+# General Public License and is *not* in the public domain.
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = @datadir@
+localedir = $(datadir)/locale
+gettextsrcdir = $(datadir)/gettext/po
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac`
+
+GMSGFMT = @GMSGFMT@
+MSGFMT = @MSGFMT@
+XGETTEXT = @XGETTEXT@
+MSGMERGE = msgmerge
+MSGMERGE_UPDATE = @MSGMERGE@ --update
+MSGINIT = msginit
+MSGCONV = msgconv
+MSGFILTER = msgfilter
+
+POFILES = @POFILES@
+GMOFILES = @GMOFILES@
+UPDATEPOFILES = @UPDATEPOFILES@
+DUMMYPOFILES = @DUMMYPOFILES@
+DISTFILES.common = Makefile.in.in Makevars \
+$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
+DISTFILES = $(DISTFILES.common) POTFILES.in $(DOMAIN).pot \
+$(POFILES) $(GMOFILES) \
+$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
+
+POTFILES = \
+
+CATALOGS = @CATALOGS@
+
+# Makevars gets inserted here. (Don't remove this line!)
+
+.SUFFIXES:
+.SUFFIXES: .po .gmo .mo .nop .po-update
+
+.po.mo:
+	$(MSGFMT) -c -o $@ $<
+
+.po.gmo:
+	@lang=`echo $* | sed -e 's,.*/,,'`; \
+	test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+	echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \
+	cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po
+
+
+all: all-@USE_NLS@
+
+all-yes: $(CATALOGS)
+all-no:
+
+# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
+# otherwise packages like GCC can not be built if only parts of the source
+# have been downloaded.
+
+$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in
+	$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
+	  --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \
+	  --files-from=$(srcdir)/POTFILES.in \
+	  --copyright-holder='$(COPYRIGHT_HOLDER)' \
+	&& test ! -f $(DOMAIN).po \
+	   || ( rm -f $(srcdir)/$(DOMAIN).pot \
+		&& mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot )
+
+$(srcdir)/$(DOMAIN).pot:
+	$(MAKE) $(DOMAIN).pot-update
+
+$(POFILES): $(srcdir)/$(DOMAIN).pot
+	@lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
+	test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+	echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \
+	cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot
+
+
+install: install-exec install-data
+install-exec:
+install-data: install-data-@USE_NLS@
+	if test "$(PACKAGE)" = "gettext"; then \
+	  $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
+	  for file in $(DISTFILES.common); do \
+	    $(INSTALL_DATA) $(srcdir)/$$file \
+			    $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	else \
+	  : ; \
+	fi
+install-data-no: all
+install-data-yes: all
+	$(mkinstalldirs) $(DESTDIR)$(datadir)
+	@catalogs='$(CATALOGS)'; \
+	for cat in $$catalogs; do \
+	  cat=`basename $$cat`; \
+	  lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
+	  dir=$(localedir)/$$lang/LC_MESSAGES; \
+	  $(mkinstalldirs) $(DESTDIR)$$dir; \
+	  if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \
+	  $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \
+	  echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \
+	  for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
+	    if test -n "$$lc"; then \
+	      if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
+	        link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
+	        mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
+	        mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
+	        (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
+	         for file in *; do \
+	           if test -f $$file; then \
+	             ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
+	           fi; \
+	         done); \
+	        rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
+	      else \
+	        if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
+	          :; \
+	        else \
+	          rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
+	          mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
+	        fi; \
+	      fi; \
+	      rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
+	      ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
+	      ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
+	      cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
+	      echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \
+	    fi; \
+	  done; \
+	done
+
+install-strip: install
+
+installdirs: installdirs-exec installdirs-data
+installdirs-exec:
+installdirs-data: installdirs-data-@USE_NLS@
+	if test "$(PACKAGE)" = "gettext"; then \
+	  $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
+	else \
+	  : ; \
+	fi
+installdirs-data-no:
+installdirs-data-yes:
+	$(mkinstalldirs) $(DESTDIR)$(datadir)
+	@catalogs='$(CATALOGS)'; \
+	for cat in $$catalogs; do \
+	  cat=`basename $$cat`; \
+	  lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
+	  dir=$(localedir)/$$lang/LC_MESSAGES; \
+	  $(mkinstalldirs) $(DESTDIR)$$dir; \
+	  for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
+	    if test -n "$$lc"; then \
+	      if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
+	        link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
+	        mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
+	        mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
+	        (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
+	         for file in *; do \
+	           if test -f $$file; then \
+	             ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
+	           fi; \
+	         done); \
+	        rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
+	      else \
+	        if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
+	          :; \
+	        else \
+	          rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
+	          mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
+	        fi; \
+	      fi; \
+	    fi; \
+	  done; \
+	done
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall: uninstall-exec uninstall-data
+uninstall-exec:
+uninstall-data: uninstall-data-@USE_NLS@
+	if test "$(PACKAGE)" = "gettext"; then \
+	  for file in $(DISTFILES.common); do \
+	    rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+	  done; \
+	else \
+	  : ; \
+	fi
+uninstall-data-no:
+uninstall-data-yes:
+	catalogs='$(CATALOGS)'; \
+	for cat in $$catalogs; do \
+	  cat=`basename $$cat`; \
+	  lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
+	  for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \
+	    rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
+	  done; \
+	done
+
+check: all
+
+dvi info tags TAGS ID:
+
+mostlyclean:
+	rm -f core core.* $(DOMAIN).po *.new.po
+	rm -fr *.o
+
+clean: mostlyclean
+
+distclean: clean
+	rm -f Makefile Makefile.in POTFILES *.mo
+
+maintainer-clean: distclean
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+	rm -f $(GMOFILES)
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir:
+	$(MAKE) update-po
+	@$(MAKE) dist2
+# This is a separate target because 'update-po' must be executed before.
+dist2: $(DISTFILES)
+	dists="$(DISTFILES)"; \
+	if test -f $(srcdir)/ChangeLog; then dists="$$dists ChangeLog"; fi; \
+	if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \
+	for file in $$dists; do \
+	  if test -f $$file; then \
+	    cp -p $$file $(distdir); \
+	  else \
+	    cp -p $(srcdir)/$$file $(distdir); \
+	  fi; \
+	done
+
+update-po: Makefile
+	$(MAKE) $(DOMAIN).pot-update
+	$(MAKE) $(UPDATEPOFILES)
+	$(MAKE) update-gmo
+
+# General rule for updating PO files.
+
+.nop.po-update:
+	@lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
+	if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; fi; \
+	tmpdir=`pwd`; \
+	echo "$$lang:"; \
+	test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+	echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
+	cd $(srcdir); \
+	if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \
+	  if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
+	    rm -f $$tmpdir/$$lang.new.po; \
+	  else \
+	    if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
+	      :; \
+	    else \
+	      echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
+	      exit 1; \
+	    fi; \
+	  fi; \
+	else \
+	  echo "msgmerge for $$lang.po failed!" 1>&2; \
+	  rm -f $$tmpdir/$$lang.new.po; \
+	fi
+
+$(DUMMYPOFILES):
+
+update-gmo: Makefile $(GMOFILES)
+	@:
+
+Makefile: Makefile.in.in $(top_builddir)/config.status POTFILES.in
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
+	       $(SHELL) ./config.status
+
+force:
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /tags/kBuild-0.1.4/src/sed/po/Makevars
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/Makevars	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/Makevars	(revision 1780)
@@ -0,0 +1,41 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding
+# package.  (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.)  Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright.  The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Free Software Foundation, Inc.
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+#   in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+#   understood.
+# - Strings which make invalid assumptions about notation of date, time or
+#   money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS =
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used.  It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
Index: /tags/kBuild-0.1.4/src/sed/po/POTFILES.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/POTFILES.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/POTFILES.in	(revision 1780)
@@ -0,0 +1,8 @@
+sed/compile.c
+sed/execute.c
+sed/regexp.c
+sed/sed.c
+lib/utils.c
+lib/regcomp.c
+lib/regexec.c
+lib/regex_internal.c
Index: /tags/kBuild-0.1.4/src/sed/po/Rules-quot
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/Rules-quot	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/Rules-quot	(revision 1780)
@@ -0,0 +1,42 @@
+# Special Makefile rules for English message catalogs with quotation marks.
+
+DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot
+
+.SUFFIXES: .insert-header .po-update-en
+
+en@quot.po-update: en@quot.po-update-en
+en@boldquot.po-update: en@boldquot.po-update-en
+
+.insert-header.po-update-en:
+	@lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \
+	if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \
+	tmpdir=`pwd`; \
+	echo "$$lang:"; \
+	ll=`echo $$lang | sed -e 's/@.*//'`; \
+	LC_ALL=C; export LC_ALL; \
+	cd $(srcdir); \
+	if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \
+	  if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
+	    rm -f $$tmpdir/$$lang.new.po; \
+	  else \
+	    if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
+	      :; \
+	    else \
+	      echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
+	      exit 1; \
+	    fi; \
+	  fi; \
+	else \
+	  echo "creation of $$lang.po failed!" 1>&2; \
+	  rm -f $$tmpdir/$$lang.new.po; \
+	fi
+
+en@quot.insert-header: insert-header.sin
+	sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header
+
+en@boldquot.insert-header: insert-header.sin
+	sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header
+
+mostlyclean: mostlyclean-quot
+mostlyclean-quot:
+	rm -f *.insert-header
Index: /tags/kBuild-0.1.4/src/sed/po/af.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/af.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/af.po	(revision 1780)
@@ -0,0 +1,448 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sed package.
+# Ysbeer <ysbeer@af.org.za>, 2004
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.9\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-01-11 21:06+0000\n"
+"Last-Translator: Ysbeer <ysbeer@af.org.za>\n"
+"Language-Team: Afrikaans <i18n@af.org.za>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n!=1;\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Meervoudige `!'s"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Onverwagte `,'"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Kan nie +N or ~N as die eerste adres gebruik nie"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Ongepaarde `{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Onverwagte `}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Ekstra karakters na instruksie"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Het \\ na `a', `c' or `i' verwag"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' soek nie 'n adres nie"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": soek nie 'n adres nie"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Kommentare aanvaar nie adresse nie"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Vermiste instruksie"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Instruksie gebruik slegs een adres"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Ongetermineerde adresregex"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Ongetermineerde `s' instruksie"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Ongetermineerde `y' instruksie"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Onbekende opsie vir `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "meervoudige `p' opsies vir `s' instruksie"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "meervoudige `g' opsies vir `s' instruksie"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "meervoudige nommeropsies vir `s' instruksie"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "nommeropsie vir `s' instruksie mag nie nul wees nie"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "stringe vir y-instruksie het verskillende lengtes"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "het nuwer sed-weergawe verwag"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Instruksie gebruik slegs een adres"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Onbekende instruksie:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: lêer %s lyn %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e uitdrukking #%lu, karakter %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Kan nie etiket vir sprong na `%s' kry nie"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: Kan nie %s lees nie: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Kon nie die lêer %s oopmaak nie: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Kon nie die lêer %s oopmaak nie: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Kon nie tydelike lêer %s oopmaak nie: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "fout in subproses"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "opsie `e' word nie ondersteun nie"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "`e' instruksie word nie ondersteun nie"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Geen vorige regex nie"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Kan nie veranderaars vir leë regex spesifiseer nie"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Ongeldige regterhandsverwysing \\%d vir `s' instruksie"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 gebruik Perl 5 se regexsintaks in die skrip.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 gebruik Perl 5 se regexsintaks in die skrip.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Rapporteer foute per e-pos aan: %s .\n"
+"Sluit asb. die woord ``%s'' êrens in die onderwerplyn in.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed weergawe %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"gebaseer op GNU sed weergawe 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed weergawe %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Hierdie is vrye sagteware; raadpleeg die bronkode vir kopiëringsinligting. "
+"Daar is GEEN\n"
+"waarborg nie; nie eens vir BRUIKBAARHEID of GESKIKHEID VIR 'n SPESIFIEK "
+"DOEL,\n"
+"binne regsperke nie.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: Kan nie %s lees nie: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Kon nie die lêer %s oopmaak nie: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "kon nie %d item na %s skryf nie: %s"
+msgstr[1] "kon nie %d items na %s skryf nie: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "leesfout op %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: Kan nie %s lees nie: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Sukses"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Geen paring"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Ongeldige regex"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Ongeldige kollasiekarakter"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Ongeldige karakterklasnaam"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Sleep terugstreep"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Ongeldige terugverwysing"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Ongepaarde [ of [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Ongepaarde ( or \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Ongepaarde \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Ongeldige inhoud binne \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Ongeldige bereikseinde"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Geheue uitgeput"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Ongeldige vorige regex"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Premature einde vir regex"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Regex te groot"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Ongepaarde ) of \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Geen vorige regex nie"
Index: /tags/kBuild-0.1.4/src/sed/po/boldquot.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/boldquot.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/boldquot.sed	(revision 1780)
@@ -0,0 +1,10 @@
+s/"\([^"]*\)"/“\1”/g
+s/`\([^`']*\)'/‘\1’/g
+s/ '\([^`']*\)' / ‘\1’ /g
+s/ '\([^`']*\)'$/ ‘\1’/g
+s/^'\([^`']*\)' /‘\1’ /g
+s/“”/""/g
+s/“/“[1m/g
+s/”/[0m”/g
+s/‘/‘[1m/g
+s/’/[0m’/g
Index: /tags/kBuild-0.1.4/src/sed/po/ca.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/ca.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/ca.po	(revision 1780)
@@ -0,0 +1,463 @@
+# Catalan translation of sed.
+# Copyright © 2002, 2003, 2004 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sed package.
+# Jordi Mallach <jordi@gnu.org>, 2002, 2003, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-07-10 05:51+0200\n"
+"Last-Translator: Jordi Mallach <jordi@gnu.org>\n"
+"Language-Team: Catalan <ca@dodds.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n!=1;\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "múltiples «!»"
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "«,» inesperada"
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "no es pot utilitzar +N o ~N com a primera adreça"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "«{» no emparellat"
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "«}» inesperat"
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "hi ha caràcters extra després de l'ordre"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "s'espera \\ després de «a», «c» i «i»"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "«}» no accepta cap adreça"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": no accepta cap adreça"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "els comentaris no accepten cap adreça"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "cal una ordre"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "l'ordre utilitza només una adreça"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "l'expressió regular d'adreça no està terminada"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "ordre «s» no terminada"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "ordre «y» no terminada"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "opció desconeguda per a «s»"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "múltiples opcions «p» per a l'ordre «s»"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "múltiples opcions «g» per a l'ordre «s»"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "múltiples opcions numèriques per a l'ordre «s»"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "l'opció numèrica per a l'ordre «s» no pot ser zero"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "les cadenes per a l'ordre «y» són de longituds diferents"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "el caràcter delimitador no és un caràcter d'un byte"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "s'esperava una versió més nova de sed"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "ús de l'adreça de línia 0 invàlid"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "ordre desconeguda: «%c»"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: fitxer %s línia %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e expressió #%lu, caràcter %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "no es troba l'etiqueta per al salt a «%s»"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: no es pot llegir %s: %s\n"
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "no s'ha pogut editar %s: és un terminal"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "no s'ha pogut editar %s: no és un fitxer regular"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "no s'ha pogut obrir el fitxer temporal %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "s'ha produït un error en el subprocés"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "l'opció «e» no està suportada"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "l'ordre «e» no està suportada"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "no hi ha una expressió regular prèvia"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "no es poden especificar modificadors en expregs buides"
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "referència \\%d no vàlida en el costat dret de l'ordre «s»"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 usa la sintaxi d'expressions regulars de Perl 5 en aquesta\n"
+"                 sequència.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"Forma d'ús: %s [OPCIÓ]... {script-només-si-no-hi-ha-altres-scripts}\n"
+"               [fitxer-entrada]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"  -n, --quiet, --silent\n"
+"                 suprimeix la impressió automàtica de l'espai de patrons\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e script, --expression=script\n"
+"                 afegeix el script a les ordres a executar\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f fitxer-script, --file=fitxer-script\n"
+"                 afegeix els continguts de fitxer-script a les ordres a "
+"executar\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[SUFIX], --in-place[=SUFIX]\n"
+"                 edita els mateixos fitxers (fa còpia de seguretat si es\n"
+"                 proveeix una extensió)\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                 especifica la longitud desitjada per a l'ajust de final de\n"
+"                 línia per a l'ordre «l»\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 inhabilita totes les extensions GNU.\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 usa expressions regulars exteses en el script.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 considera els fitxers com independents, en compte d'un\n"
+"                 llarg flux continu.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 carrega una quantitat mínima de dades dels fitxers "
+"d'entrada\n"
+"                 i buida els búfers d'eixida més sovint\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     mostra aquest missatge d'ajuda i surt\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  mostra la informació de la versió i surt\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"Si no es donen cap de les opcions -e, --expression, -f o --file, el primer\n"
+"argument no-opció es pren com el script sed a interpretar. Tots els "
+"arguments\n"
+"restants són noms de fitxers d'entrada; si no s'especifiquen fitxers "
+"d'entrada,\n"
+"es llegeix l'entrada estàndard.\n"
+"\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Envieu informes d'error a: %s.\n"
+"Assegureu-vos d'incloure la paraula «%s» en alguna part del camp "
+"«Assumpte:».\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versió %s\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"basat en GNU sed versió %s\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versió %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Aquest és programari lliure; vegeu el codi font per les condicions\n"
+"de còpia.  No hi ha CAP garantia; ni tan sols de COMERCIABILITAT o\n"
+"ADEQUACIÓ A UN PROPÒSIT PARTICULAR, fins on ho permeta la llei.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "no es pot eliminar %s: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "no s'ha pogut obrir el fitxer %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "no s'ha pogut escriure %d element a %s: %s"
+msgstr[1] "no s'han pogut escriure %d elements a %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "error de lectura en %s: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "no es pot reanomenar %s: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Èxit"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Sense parella"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Expressió regular no vàlida"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "El caràcter de comparació no és vàlid"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nom de classe de caràcter no vàlid"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Barra invertida al final"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "La referència cap enrere no és vàlida"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[ o [^ no emparellat"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "«(» o \\( no emparellat"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{ no emparellat"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "El contingut de \\{\\} no és vàlid"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "El rang final no és vàlid"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Memòria exhaurida"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "L'expressió regular precedent no vàlida"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Fi prematur de l'expressió regular"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "L'expressió regular és massa gran"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ") o \\) no emparellat"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "No hi ha una expressió regular prèvia"
Index: /tags/kBuild-0.1.4/src/sed/po/cs.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/cs.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/cs.po	(revision 1780)
@@ -0,0 +1,441 @@
+# Czech translations for GNU sed package.
+# Copyright (C) 1998 Free Software Foundation, Inc.
+# Jaroslav Fojtik <fojtik@cmp.felk.cvut.cz>, 1998.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 3.02.80\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2001-08-05 19:52+02:00\n"
+"Last-Translator: Vladimir Michl <Vladimir.Michl@seznam.cz>\n"
+"Language-Team: Czech <cs@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Vícenásobný `!'"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Neoèekáváná `,'"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "+N nebo ~N nelze pou¾ít jako první adresu"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Neodpovídající `{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Neoèekávaná `}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Nadbyteèné znaky po pøíkazu"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr ""
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' nevy¾aduje jakoukoliv adresu"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": nechce jakoukoliv adresu"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "V komentáøi není pøípustná jakákoliv adresa"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Chybìjící pøíkaz"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Pøíkaz pou¾ívá pouze jedinou adresu"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Neukonèená adresa regulárního výrazu"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Neukonèený pøíkaz `s'"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Neukonèený pøíkaz `y'"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Neznámý pøepínaè pro `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "vícenásobné pou¾ití pøepínaèe `p' s pøíkazem `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "vícenásobné pou¾ití pøepínaèe `g' s pøíkazem `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "pøíkaz `s' mù¾e mít maximálnì jednu èíselnou volbu"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "èíselná volba pøíkazu `s' nemù¾e být nula"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "øetìzce pro pøíkaz `y' musí být stejnì dlouhé"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Chybné pou¾ití adresy modifikátoru"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Neznámý pøíkaz:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: soubor %s, øádek %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e výraz #%lu, znak %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Návì¹tí pro skok na `%s' nelze najít"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: %s nelze èíst: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Soubor %s nelze otevøít"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Soubor %s nelze otevøít"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Soubor %s nelze otevøít"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr ""
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr ""
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr ""
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr ""
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr ""
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr ""
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Chyby v programu oznamujte na adrese: %s (anglicky).\n"
+"Kamkoliv do polo¾ky ``Subject:'' vlo¾te ``%s''.\n"
+"Pøipomínky k pøekladu zasílejte na adresu <cs@li.org> (èesky).\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"  %s\n"
+"  Toto je volné programové vybavení; podmínky pro kopírování a roz¹iøování\n"
+"naleznete ve zdrojových textech. Toto programové vybavení je zcela BEZ "
+"ZÁRUKY,\n"
+"a to i bez záruky PRODEJNOSTI nebo VHODNOSTI PRO NÌJAKÝ KONKRÉTNÍ ÚÈEL.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: %s nelze èíst: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Soubor %s nelze otevøít"
+
+#: lib/utils.c:220
+#, fuzzy, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "%d polo¾ek nelze do %s zapsat: %s"
+msgstr[1] "%d polo¾ek nelze do %s zapsat: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "chyba pøi ètení z %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: %s nelze èíst: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr ""
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr ""
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr ""
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr ""
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr ""
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr ""
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr ""
+
+#: lib/regcomp.c:153
+#, fuzzy
+msgid "Unmatched [ or [^"
+msgstr "Neodpovídající `{'"
+
+#: lib/regcomp.c:156
+#, fuzzy
+msgid "Unmatched ( or \\("
+msgstr "Neodpovídající `{'"
+
+#: lib/regcomp.c:159
+#, fuzzy
+msgid "Unmatched \\{"
+msgstr "Neodpovídající `{'"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr ""
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr ""
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr ""
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr ""
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr ""
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr ""
+
+#: lib/regcomp.c:180
+#, fuzzy
+msgid "Unmatched ) or \\)"
+msgstr "Neodpovídající `{'"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr ""
Index: /tags/kBuild-0.1.4/src/sed/po/da.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/da.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/da.po	(revision 1780)
@@ -0,0 +1,445 @@
+# Danish messages for sed
+# Copyright (C) 2001 Free Software Foundation, Inc.
+# Byrial Ole Jensen <byrial@image.dk>, 2001-2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.8\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-10-25 08:00+0200\n"
+"Last-Translator: Byrial Ole Jensen <byrial@image.dk>\n"
+"Language-Team: Danish <dansk@klid.dk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Flere '!'"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Uventet ','"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Kan ikke bruge +N eller ~N som første adresse"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Uparret '{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Uventet '}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Ekstra tegn efter kommando"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Forventede \\ efter 'a', 'c' eller 'i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "'}' vil ikke have adresser"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": vil ikke have adresser"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Kommentarer vil ikke have adresser"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Der mangler en kommando"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Kommandoen bruger kun én adresse"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Uafsluttet regulært udtryk for adresse"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Uafsluttet 's'-kommando"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Uafsluttet 'y'-kommando"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Ukendt tilvalg til 's'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "Flere 'p'-flag til 's'-kommando"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "Flere 'g'-flag til 's'-kommando"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "Flere tal-flag til 's'-kommando"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "s-kommandoens tal-flag må ikke være nul"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "y-kommandoens strenge har forskellige længder"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "forventede en nyere version af sed"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Forkert brug af adresse-ændrer"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Ukendt kommando:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: fil %s, linje %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e udtryk nr. %lu, tegn %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Kan ikke finde etiket for hop til '%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: kan ikke læse %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "kunne ikke åbne filen %s: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "kunne ikke åbne filen %s: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "kunne ikke åbne midlertidig fil %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "fejl i underproces"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "tilvalg 'e' er ikke understøttet"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "'e'-kommando er ikke understøttet"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Intet forudgående regulært udtryk"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Der kan ikke angives ændrere til tomt regulært udtryk"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Ugyldig reference \\%d på 's'-kommandos højreside"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 brug Perl 5's syntaks for regulære udtryk i skriptet\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 brug Perl 5's syntaks for regulære udtryk i skriptet\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Send fejlrapporter på engelsk pr. e-post til %s.\n"
+"Sørg venligst for at skrive ordet \"%s\" et sted i \"Subject:\"-feltet.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed version %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"baseret på GNU sed version 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed version %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Dette er frit programmel; se kildeteksten for kopieringsbetingelser.\n"
+"Der er INGEN garanti; end ikke for SALGBARHED eller EGNETHED TIL NOGET\n"
+"BESTEMT FORMÅL, i det omfang som loven tillader.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: kan ikke læse %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "kunne ikke åbne filen %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "kunne ikke skrive %d element til %s: %s"
+msgstr[1] "kunne ikke skrive %d elementer til %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "læsefejl på %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: kan ikke læse %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Godt resultat"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Intet resultat"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Ugyldigt regulært udtryk"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Ugyldigt sorteringstegn"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Ugyldigt navn på tegnklasse"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Afsluttende omvendt skråstreg"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Ugyldig reference bagud"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Uparret [ eller [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Uparret ( eller \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Uparret \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Ugyldigt indhold af \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Ugyldig slutning på område"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Hukommelsen opbrugt"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Ugyldigt forudgående regulært udtryk"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Ufuldstændigt regulært udtryk"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Regulært udtryk for stort"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Uparret ) eller \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Intet forudgående regulært udtryk"
Index: /tags/kBuild-0.1.4/src/sed/po/de.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/de.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/de.po	(revision 1780)
@@ -0,0 +1,450 @@
+# sed german translation
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+# Walter Koch <koch@u32.de>, 2001, 2002, 2003
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-03-21 22:03:41+0100\n"
+"Last-Translator: Walter Koch <koch@u32.de>\n"
+"Language-Team: German <de@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Mehrfache `!'"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Unerwartetes `,'"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "+N oder ~N können nicht als erste Adresse benutzt werden"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Nicht paarweises `{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Unerwartetes `}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Zusätzliche Zeichen nach dem Befehl"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Nach `a', `c' oder `i' wird \\ erwartet"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' erwartet keine Adressen"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr "`:' erwartet keine Adressen"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Kommentare erlauben keine Adressen"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Fehlender Befehl"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Befehl verwendet nur eine Adresse"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Nicht beendeter regulärer Adressausdruck"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Nicht beendeter `s'-Befehl"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Nicht beendeter `y'-Befehl"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Unbekannte Option betreffs `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "Mehrere 'p'-Optionen am `s'-Befehl"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "Mehrere 'g'-Optionen am `s'-Befehl"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "Mehrere numerische Optionen am `s'-Befehl"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "Numerisch Option am `s'-Befehl darf nicht Null sein"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "Unterschiedliche Länge der Zeichenketten am `y'-Befehl"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "Neuere Version von sed erwartet"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Befehl verwendet nur eine Adresse"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Unbekannter Befehl:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: Datei %s Zeile %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e Ausdruck #%lu, Zeichen %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Kann das Ziel für den Sprung nach `%s' nicht finden"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: kann %s nicht lesen: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Datei %s kann nicht geöffnet werden: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Datei %s kann nicht geöffnet werden: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Datei %s kann nicht geöffnet werden: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "Fehler im Subprozess"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "Option `e' wird nicht unterstützt"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "`e'-Kommando wird nicht unterstützt"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Kein vorheriger regulärer Ausdruck"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Auf leere reguläre Ausdrücke können keine `modifier' angewandt werden"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Ungültiger Verweis \\%d in den Haltepuffer des `s'-Befehls"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 Verwende die Perl 5 - Syntax für reg.Ausdrücke im Script.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 Verwende die Perl 5 - Syntax für reg.Ausdrücke im Script.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Fehlerberichte (in Englisch!) per E-Mail an: %s .\n"
+"Verwenden Sie dabei den Begriff ``%s'' irgendwo in der ``Betreff:''-Zeile.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "Super-sed version %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"basiert auf GNU sed Version 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed Version %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"(Der folgende Text ist eine nicht überprüfte Übersetzung, die zur\n"
+" Information dient;  in rechtlichen Fragen ist immer das englische\n"
+" Original ausschlaggebend)\n"
+"\n"
+"Dieses Program ist freie Software; In den Quelldateien können Sie die\n"
+"Bedingungen für die Weitergabe nachlesen.\n"
+"Es gibt KEINE GARANTIE; nicht einmal die implizite Garantie der\n"
+"MARKTFÄHIGKEIT oder der ERFÜLLUNG EINES BESTIMMTEN ZWECKES.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: kann %s nicht lesen: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Datei %s kann nicht geöffnet werden: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "Kann %d Feld nicht auf %s schreiben: %s"
+msgstr[1] "Kann %d Felder nicht auf %s schreiben: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "Lesefehler in %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: kann %s nicht lesen: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Erfolgreich"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Keine Übereinstimmung"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Ungültiger regulärer Ausdruck"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Ungültiger Vergleichszeichen"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Ungültige Zeichenklassenname"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Abschliessender Backslash"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Ungültiger Rückwärtsverweis"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Nicht paarweises [ bzw. [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Nicht paarweises ( bzw. \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Nicht paarweises \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Ungültiger Inhalt in \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Ungültiges Bereichende"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Speicher erschöpft"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Vorheriger regulärer Ausdruck ist ungültig"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Regulärer Ausdruck endet zu früh"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Regulärer Ausdruck ist zu groß"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Nicht paarweises ) bzw. \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Kein vorheriger regulärer Ausdruck"
Index: /tags/kBuild-0.1.4/src/sed/po/el.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/el.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/el.po	(revision 1780)
@@ -0,0 +1,451 @@
+# Greek messages for GNU sed.
+# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+# Simos Xenitellis <simos@hellug.gr>, 1998, 1999, 2000, 2001, 2002.
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU sed 3.02.80\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2002-03-08 12:57+0000\n"
+"Last-Translator: Simos Xenitellis <simos@hellug.gr>\n"
+"Language-Team: Greek <nls@tux.hellug.gr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-7\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "ÐïëëáðëÜ `!'s"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "ÁíáðÜíôå÷ï `,'"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Äåí åßíáé äõíáôÞ ç ÷ñÞóç ôùí +N Þ ~N ãéá ðñþôç äéåýèõíóç"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Áôáßñéáóôï `{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Áôáßñéáóôï `}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "ÅðéðëÝïí ÷áñáêôÞñåò ìåôÜ ôçí åíôïëÞ"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Áðáéôåßôáé \\ ìåôÜ ôéò åíôïëÝò `a', `c' Þ `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "ôï `}' äåí ÷ñåéÜæåôáé äéåõèýíóåéò"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": äåí ÷ñåéÜæåôáé äéåõèýíóåéò"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Ôá ó÷üëéá äåí äÝ÷ïíôáé äéåõèýíóåéò"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Ëåßðåé ç åíôïëÞ"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Ç åíôïëÞ ÷ñçóéìïðïéåß ìüíï ìéá äéåýèõíóç"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Ìç ôåñìáôéóìÝíç äéåýèõíóç êáíïíéêÞò Ýêöñáóçò"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Ìç ôåñìáôéóìÝíç åíôïëÞ `s'"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Ìç ôåñìáôéóìÝíç åíôïëÞ `y'"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "¶ãíùóôç åðéëïãÞ ãéá ôï `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "ðïëëáðëÝò åðéëïãÝò `p' óôçí åíôïëÞ `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "ðïëëáðëÝò åðéëïãÝò `g' óôçí åíôïëÞ `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "ðïëëáðëüò åðéëïãÝò áñéèìïý óôçí åíôïëÞ `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "ç åðéëïãÞ áñéèìïý óôçí åíôïëÞ `s' äåí ìðïñåß íá åßíáé ìçäÝí"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "ôá áëöáñéèìçôéêÜ ãéá ôçí åíôïëÞ `y' åßíáé äéáöïñåôéêïý ìåãÝèïõò"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "ÁêáôÜëëçëç ÷ñÞóç ôïõ äéáìïñöùôÞ äéåýèõíóçò"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "¶ãíùóôç åíôïëÞ:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: áñ÷åßï %s ãñáììÞ %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e Ýêöñáóç #%lu, ÷áñáêôÞñáò %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Äåí Þôáí äõíáôÞ ç åýñåóç åôéêÝôôáò ãéá ìåôÜâáóç óôï `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: áäõíáìßá óôçí áíÜãíùóç %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Äåí ìðüñåóá íá áíïßîù ôï áñ÷åßï %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Äåí ìðüñåóá íá áíïßîù ôï áñ÷åßï %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Äåí ìðüñåóá íá áíïßîù ôï áñ÷åßï %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "óöÜëìá óôç õðïäéáäéêáóßá"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "äåí õðïóôçñßæåôáé ç åðéëïãÞ `e'"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "äåí õðïóôçñßæåôáé ç åíôïëÞ `e'"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "äåí åðéôñÝðåôáé ï ïñéóìüò äéáìïñöùôþí óå êåíÞ êáíïíéêÞ Ýêöñáóç"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Ìç Ýãêõñç áíáöïñÜ \\%d óôï äåîß ôìÞìá ôçò åíôïëÞò `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"ÁíáöïñÝò óöáëìÜôùí ìÝóù çëåêôñïíéêïý ôá÷õäñïìåßïõ óôï: %s .\n"
+"ÐñïóÝîôå íá óõìðåñéëÜâåôå ôç ëÝîç ``%s'' êÜðïõ óôï ðåäßï ``Subject:''.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Áõôü ôï ðñüãñáììá åßíáé åëåýèåñï ëïãéóìéêü· äåßôå ôïí ðçãáßï êþäéêá ãéá "
+"ôïõò\n"
+"êáíïíéóìïýò áíôéãñáöÞò. Äåí õðÜñ÷åé ÊÁÌÉÁ ÅÃÃÕÇÓÇ· ïýôå áêüìá ãéá\n"
+"ËÅÉÔÏÕÑÃÉÊÏÔÇÔÁ Þ ÊÁÔÁËËÇËÏÔÇÔÁ ÃÉÁ ÅÍÁ ÓÕÃÊÅÊÑÉÌÅÍÏ ÓÊÏÐÏ, ìÝ÷ñé ôï óçìåßï\n"
+"ðïõ åðéôñÝðåé ï íüìïò.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: áäõíáìßá óôçí áíÜãíùóç %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Äåí ìðüñåóá íá áíïßîù ôï áñ÷åßï %s"
+
+#: lib/utils.c:220
+#, fuzzy, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "áäýíáôç ç åããñáöÞ %d óôïé÷åßùí óôï %s: %s"
+msgstr[1] "áäýíáôç ç åããñáöÞ %d óôïé÷åßùí óôï %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "óöÜëìá áíÜãíùóçò óôï %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: áäõíáìßá óôçí áíÜãíùóç %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr ""
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr ""
+
+#: lib/regcomp.c:138
+#, fuzzy
+msgid "Invalid regular expression"
+msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç"
+
+#: lib/regcomp.c:141
+#, fuzzy
+msgid "Invalid collation character"
+msgstr "ìç Ýãêõñï áêïëïõèßá äéáöõãÞò óå êëÜóç ÷áñáêôÞñùí"
+
+#: lib/regcomp.c:144
+#, fuzzy
+msgid "Invalid character class name"
+msgstr "ìç Ýãêõñï áêïëïõèßá äéáöõãÞò óå êëÜóç ÷áñáêôÞñùí"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr ""
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr ""
+
+#: lib/regcomp.c:153
+#, fuzzy
+msgid "Unmatched [ or [^"
+msgstr "Áôáßñéáóôï `{'"
+
+#: lib/regcomp.c:156
+#, fuzzy
+msgid "Unmatched ( or \\("
+msgstr "Áôáßñéáóôï `{'"
+
+#: lib/regcomp.c:159
+#, fuzzy
+msgid "Unmatched \\{"
+msgstr "Áôáßñéáóôï `{'"
+
+#: lib/regcomp.c:162
+#, fuzzy
+msgid "Invalid content of \\{\\}"
+msgstr "ìç Ýãêõñï ðåñéå÷üìåíï äåéêôþí åðáíÜëçøçò {}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr ""
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr ""
+
+#: lib/regcomp.c:171
+#, fuzzy
+msgid "Invalid preceding regular expression"
+msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç"
+
+#: lib/regcomp.c:174
+#, fuzzy
+msgid "Premature end of regular expression"
+msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç"
+
+#: lib/regcomp.c:177
+#, fuzzy
+msgid "Regular expression too big"
+msgstr "ðïëý ìåãÜëç êáíïíéêÞ Ýêöñáóç"
+
+#: lib/regcomp.c:180
+#, fuzzy
+msgid "Unmatched ) or \\)"
+msgstr "Áôáßñéáóôï `{'"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Äåí âñÝèçêå ðñïçãïýìåíç êáíïíéêÞ Ýêöñáóç"
Index: /tags/kBuild-0.1.4/src/sed/po/en@boldquot.header
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/en@boldquot.header	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/en@boldquot.header	(revision 1780)
@@ -0,0 +1,25 @@
+# All this catalog "translates" are quotation characters.
+# The msgids must be ASCII and therefore cannot contain real quotation
+# characters, only substitutes like grave accent (0x60), apostrophe (0x27)
+# and double quote (0x22). These substitutes look strange; see
+# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
+#
+# This catalog translates grave accent (0x60) and apostrophe (0x27) to
+# left single quotation mark (U+2018) and right single quotation mark (U+2019).
+# It also translates pairs of apostrophe (0x27) to
+# left single quotation mark (U+2018) and right single quotation mark (U+2019)
+# and pairs of quotation mark (0x22) to
+# left double quotation mark (U+201C) and right double quotation mark (U+201D).
+#
+# When output to an UTF-8 terminal, the quotation characters appear perfectly.
+# When output to an ISO-8859-1 terminal, the single quotation marks are
+# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to
+# grave/acute accent (by libiconv), and the double quotation marks are
+# transliterated to 0x22.
+# When output to an ASCII terminal, the single quotation marks are
+# transliterated to apostrophes, and the double quotation marks are
+# transliterated to 0x22.
+#
+# This catalog furthermore displays the text between the quotation marks in
+# bold face, assuming the VT100/XTerm escape sequences.
+#
Index: /tags/kBuild-0.1.4/src/sed/po/en@quot.header
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/en@quot.header	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/en@quot.header	(revision 1780)
@@ -0,0 +1,22 @@
+# All this catalog "translates" are quotation characters.
+# The msgids must be ASCII and therefore cannot contain real quotation
+# characters, only substitutes like grave accent (0x60), apostrophe (0x27)
+# and double quote (0x22). These substitutes look strange; see
+# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
+#
+# This catalog translates grave accent (0x60) and apostrophe (0x27) to
+# left single quotation mark (U+2018) and right single quotation mark (U+2019).
+# It also translates pairs of apostrophe (0x27) to
+# left single quotation mark (U+2018) and right single quotation mark (U+2019)
+# and pairs of quotation mark (0x22) to
+# left double quotation mark (U+201C) and right double quotation mark (U+201D).
+#
+# When output to an UTF-8 terminal, the quotation characters appear perfectly.
+# When output to an ISO-8859-1 terminal, the single quotation marks are
+# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to
+# grave/acute accent (by libiconv), and the double quotation marks are
+# transliterated to 0x22.
+# When output to an ASCII terminal, the single quotation marks are
+# transliterated to apostrophes, and the double quotation marks are
+# transliterated to 0x22.
+#
Index: /tags/kBuild-0.1.4/src/sed/po/eo.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/eo.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/eo.po	(revision 1780)
@@ -0,0 +1,445 @@
+# Esperantaj mesaĝoj por GNU sed.
+# Copyright (C) 2002 Free Software Foundation, Inc.
+# Edmund GRIMLEY EVANS <edmundo@rano.org>, 2001-2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU sed 4.0.8\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-10-26 20:57+0000\n"
+"Last-Translator: Edmund GRIMLEY EVANS <edmundo@rano.org>\n"
+"Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8-bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Pluraj '!'oj"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Neatendita ','"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Ne eblas uzi +N aŭ ~N kiel unuan adreson"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Neparigita '{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Neatendita '}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Kromaj signoj post komando"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Atendita \\ post 'a', 'c' aŭ 'i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "'}' ne deziras adresojn"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": ne deziras adresojn"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Komentoj ne akceptas adresojn"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Mankas komando"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Komando uzas nur unu adreson"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Nefinita adresa regesp"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Nefinita komando 's'"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Nefinita komando 'y'"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Nekonata opcio por 's'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "pluraj 'p'-opcioj por komando 's'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "pluraj 'g'-opcioj por komando 's'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "pluraj nombro-opcioj por komando 's'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "nombro-opcio por komando 's' ne povas esti nul"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "ĉenoj por komando 'y' havas malsamajn longojn"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "atendis pli novan version de sed"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Nevalida uzo de adresmodifilo"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Nekonata komando:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: dosiero %s linio %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e esprimo #%lu, signo %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Ne povas trovi etikedon por salto al '%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: ne povas legi %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Ne povis malfermi dosieron %s: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Ne povis malfermi dosieron %s: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Ne povis malfermi dumtempan dosieron %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "eraro en subprocezo"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "opcio 'e' ne realigita"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "komando 'e' ne realigita"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Mankas antaŭa regula esprimo"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Ne eblas specifi modifilojn ĉe malplena regula esprimo"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Nevalida referenco \\%d ĉe dekstra flanko de komando 's'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 uzi sintakso de Perl 5 por regulaj esprimoj en programo.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 uzi sintakso de Perl 5 por regulaj esprimoj en programo.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Retpoŝtu cimo-raportojn al: %s .\n"
+"Nepre menciu la vorton '%s' ie en la temlinio.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versio %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"bazita sur \"GNU sed\" versio 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versio %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Ĉi tio estas libera programo; vidu la fonton por kopi-kondiĉoj. Estas\n"
+"NENIA GARANTIO; eĉ ne por KOMERCA KVALITO aŭ ADEKVATECO POR DIFINITA CELO,\n"
+"laŭ la grado permesita de juro.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: ne povas legi %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Ne povis malfermi dosieron %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "ne povis skribi %d eron al %s: %s"
+msgstr[1] "ne povis skribi %d erojn al %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "legeraro ĉe %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: ne povas legi %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Sukceso"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Maltrafo"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Nevalida regula esprimo"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Nevalida kunfanda signo"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nevalida nomo de signoklaso"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Malsuprenstreko ĉe fino"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Nevalida retroreferenco"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Neparigita [ aŭ [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Neparigita ( aŭ \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Neparigita \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Nevalida enhavo de \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Nevalida fino de gamo"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Mankas memoro"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Nevalida antaŭa regula esprimo"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Neatendita fino de regula esprimo"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Regula esprimo tro granda"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Neparigita ) aŭ \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Mankas antaŭa regula esprimo"
Index: /tags/kBuild-0.1.4/src/sed/po/es.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/es.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/es.po	(revision 1780)
@@ -0,0 +1,448 @@
+# Mensajes en español para GNU sed.
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+# Cristian Othón Martínez Vera <cfuga@itam.mx>, 2001, 2002, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.8\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-10-24 12:38-0500\n"
+"Last-Translator: Cristian Othón Martínez Vera <cfuga@itam.mx>\n"
+"Language-Team: Spanish <es@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "'!'s múltiples"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "`,' inesperada"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "No se pueden usar +N o ~N como primera dirección"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "`{' sin pareja"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "`}' inesperado"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Caracteres extra después de la orden"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Se esperaba \\ después de `a', `c' ó `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' no acepta ninguna dirección"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": no acepta ninguna dirección"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Los comentarios no aceptan ninguna dirección"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Orden faltante"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "La orden solamente usa una dirección"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Dirección de expresión regular sin terminar"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Orden `s' sin terminar"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Orden `y' sin terminar"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Opción desconocida para `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "múltiples opciones `p' para la orden `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "múltiples opciones `g' para la orden `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "múltiples opciones numéricas para la orden `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "una opción numérica para la orden `s' no puede ser cero"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "las cadenas para la orden y son de longitudes diferentes"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "se esperaba una versión más reciente de sed"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Uso inválido de un modificador de dirección"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Orden desconocida:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: fichero %s línea %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e expresión #%lu, carácter %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "No se puede encontrar la etiqueta para saltar a `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: no se puede leer %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "No se puede abrir el fichero %s: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "No se puede abrir el fichero %s: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "No se puede abrir el fichero temporal %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "error en el subproceso"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "no hay soporte para la opción `e'"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "no hay soporte para el comando `e'"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "No hay una expresión regular previa"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "No se pueden especificar modificadores en expresiones regulares vacías"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Referencia \\%d inválida en el lado derecho del comando `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 utilizar la sintaxis de expresiones regulares de Perl 5\n"
+"                 en el guión.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 utilizar la sintaxis de expresiones regulares de Perl 5\n"
+"                 en el guión.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Envíe reportes de bichos por e-mail a: %s .\n"
+"Asegúrese de incluir la palabra ``%s'' en algún lugar en el campo "
+"``Subject:''.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versión %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"basado en GNU sed versión 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versión %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Esto es software libre; vea el código fuente para las condiciones de copia.\n"
+"No hay NINGUNA garantía; ni siquiera de COMERCIABILIDAD o IDONEIDAD PARA UN\n"
+"FIN DETERMINADO, en la extensión permitida por ley.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: no se puede leer %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "No se puede abrir el fichero %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "no se puede escribir %d elemento a %s: %s"
+msgstr[1] "no se pueden escribir %d elementos a %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "error al leer de %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: no se puede leer %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Éxito"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "No hay coincidencia"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Expresion regular inválida"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Carácter de ordenamiento inválido"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Carácter de nombre de clase inválido"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Diagonal invertida al final"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Referencia hacia atrás inválida"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[ ó [^ sin pareja"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "( ó \\( sin pareja"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{ sin pareja"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Contenido inválido de \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Final de rango inválido"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Memoria agotada"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Expresión regular precedente inválida"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Final prematuro de la expresión regular"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Expresión regular demasiado grande"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ") ó \\) sin pareja"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "No hay una expresión regular previa"
Index: /tags/kBuild-0.1.4/src/sed/po/et.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/et.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/et.po	(revision 1780)
@@ -0,0 +1,453 @@
+# Estonian translations for GNU sed.
+# Copyright (C) 2001 Free Software Foundation, Inc.
+# Toomas Soome <Toomas.Soome@microlink.ee>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-07-09 16:33+0300\n"
+"Last-Translator: Toomas Soome <Toomas.Soome@microlink.ee>\n"
+"Language-Team: Estonian <et@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-15\n"
+"Content-Transfer-Encoding: 8-bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "korduv `!'"
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "ootamatu `,'"
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "+N või ~N ei või kasutada esimese aadressina"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "liigne `{'"
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "ootamatu `}'"
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "lisasümbolid peale käsku"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "peale `a', `c' või `i' peab olema \\"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' ei vaja aadresse"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": ei vaja aadresse"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "kommentaarid ei vaja aadresse"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "käsk puudub"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "käsk kasutab vaid üht aadressi"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "lõpetamata aadressi avaldis"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "lõpetamata `s' käsk"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "lõpetamata `y' käsk"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "tundmatu võti `s' käsule"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "korduv `p' võti `s' käsus"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "korduv `g' võti `s' käsus"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "korduvad numbrivõtmed `s' käsus"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "numbrivõti `s' käsus ei või olla null"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "sõned käsus `y' on erineva pikkusega"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "eraldav sübol ei ole ühe-baidiline sümbol"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "oodati sedi uuemat versiooni"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "vigane rea aadressi 0 kasutamine"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "tundmatu käsk: `%c'"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: fail %s rida %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e avaldis #%lu, sümbol %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "ei leia märgendit, et hüpata kohale `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: ei saa lugeda %s: %s\n"
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "%s ei saa toimetada: see on terminal"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "%s ei saa toimetada: see ei ole tavaline fail"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "ajutist faili %s ei saa avada: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "viga alamprotsessis"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "võtit `e' ei toetata"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "käsku `e' ei toetata"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "eelmist regulaaravaldist pole"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "muudatusi tühjale regulaaravaldisele ei saa määrata"
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "vigane viide \\%d käsu `s' paremas pooles"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 kasuta skriptis Perl 5 regulaaravaldiste süntaksit.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"Kasutamine: %s [võti]... {ainult-skript-kui-teisi-skripte-pole} [sisend-"
+"fail]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"  -n, --quiet, --silent\n"
+"                 keela mustriruumi automaatne väljastamine\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e skript, --expression=skript\n"
+"                 lisa täidetavate käskluste skript\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f skripti-fail, --file=skripti-fail\n"
+"                 lisa skripti-faili sisu täidetavate käskluste hulka\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[SUFIKS], --in-place[=SUFIKS]\n"
+"                 toimeta faile (kui kasutati sifiksit, loob ka varukoopia)\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                 määra `l' käsule soovitatav rea pikkus\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 blokeeri kõik GNU laiendused.\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 kasuta skriptis laiendatud regulaaravaldiste süntaksit.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 käsitle faile ükshaaval, mitte ühe jätkuva voona.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 loe sisendfailist minimaalne kogus andmeid ja tühjenda\n"
+"                 väljundpuhvreid sagedamini\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     väljast see abiinfo ja lõpeta töö\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  väljasta versiooniinfo ja lõpeta töö\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"Kui võtmeid -e, --expression, -f või --file ei kasutata, loetakse\n"
+"esimene argument, mis pole võti, sed skriptiks. Kõik järgnevad argumendid "
+"on\n"
+"sisendfailide nimed; kui sisendfaile ei antud, loetakse standardsisendit.\n"
+"\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Postitage teated vigadest: %s .\n"
+"Lisage kindlasti sõna ``%s'' ``Subject:'' reale.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versioon %s\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"põhineb GNU sed versioonil %s\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versioon %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"See on vaba tarkvara; kopeerimistingimused leiate lähtetekstidest. Garantii\n"
+"PUUDUB; ka müügiks või mingil eesmärgil kasutamiseks, vastavalt seadustega\n"
+"lubatud piiridele.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s ei saa eemaldada: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "faili %s ei saa avada: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "%d elemendi faili %s kirjutamine ebaõnnestus: %s"
+msgstr[1] "%d elemendi faili %s kirjutamine ebaõnnestus: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "lugemisviga %s: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s ei saa ümber nimetada: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Edukas"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Ei leia"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Vigane regulaaravaldis"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Vigane sortimise sümbol"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Vigane sümbolite klassi nimi"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Lõpetav langkriips"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Vigane tagasi viide"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Puudub [ või [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Puudub ( või \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Puudub \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Vigane \\{\\} sisu"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Vigane vahemiku lõpp"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Mälu on otsas"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Vigane eelnev regulaaravaldis"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Ootamatu regulaaravaldise lõpp"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Regulaaravaldis on liiga suur"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Puudub ) või \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Eelmist regulaaravaldist pole"
Index: /tags/kBuild-0.1.4/src/sed/po/fi.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/fi.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/fi.po	(revision 1780)
@@ -0,0 +1,448 @@
+# Finnish translations for GNU sed.
+# Copyright © 2002 Free Software Foundation, Inc.
+# Sami J. Laine <sami.laine@iki.fi>, 2002
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed-4.0.8\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-12-07 09:35+0200\n"
+"Last-Translator: Sami J. Laine <sami.laine@iki.fi>\n"
+"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Useita \"!\"-merkkejä"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Odottamaton \",\""
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Ensimmäisenä osoitteena ei voi olla +N tai ~N"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Pariton \"{\""
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Pariton \"}\""
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Ylimääräisiä merkkejä komennon jälkeen"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "\\ odotettiin merkkien `a', `c' tai `i' jälkeen"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "\"}\" ei tarvitse osoitteita"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": ei tarvitse osoitteita"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Kommentit eivät hyväksy osoitteita"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Puuttuva komento"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Komento käyttää vain yhtä osoitetta"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Päättymätön osoite vakiolauseessa"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Päättymätön \"s\"-komento"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Päättymätön \"y\"-komento"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Tuntematon valitsin \"s\":lle"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "useita \"p\"-valitsimia \"s\"-komennolle"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "useita \"g\"-valitsimia \"s\"-komennolle"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "useita valitsimia \"s\"-komennolle"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "numeerinen valitsin \"s\"-komennolle ei voi olla nolla"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "merkkijonot \"y\"-komennolle ovat pituudeltaan vaihtelevia"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "odotettiin uudempaa versiota sed:stä"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Komento käyttää vain yhtä osoitetta"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Tuntematon komento:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: tiedosto %s rivi %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e lauseke #%lu, merkki %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Nimikettä hypylle kohteeseen \"%s\" ei löydy"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: ei voida lukea syötettä %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Tiedostoa %s ei voitu avata: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Tiedostoa %s ei voitu avata: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Väliaikaistiedostoa %s ei voitu avata: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "virhe lapsiprosessissa"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "valitsin `e' ei ole tuettu"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "komento `e' ei ole tuettu"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Ei aikaisempaa säännöllistä lausetta"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Muuttajia ei voida määritellä tyhjään säännöliseen lausekkeeseen"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Virheellinen viittaus \\%d komennon `s' oikealla puolella"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 käytä Perl 5:en mukaista säännöllisten lauseiden\n"
+"                 syntaksia skriptissä.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 käytä Perl 5:en mukaista säännöllisten lauseiden\n"
+"                 syntaksia skriptissä.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Lähetä virheraportit osoitteeseen %s .\n"
+"Sisällytä sana \"%s\" viestin aihekenttään (\"Subject\"-kenttään).\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versio %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"perustuu GNU sed versioon 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versio %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Tämä ohjelma on vapaa ohjelmisto; tarkista jakeluehdot lähdekoodista.\n"
+"Tälle ohjelmalle ei anneta minkäänlaista takuuta; ei edes takuuta\n"
+"kaupallisesti hyväksyttävästä laadusta tai soveltuvuudesta tiettyyn\n"
+"tarkoitukseen.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: ei voida lukea syötettä %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Tiedostoa %s ei voitu avata: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "%d kohdetta ei voitu kirjoittaa tulosteeseen %s: %s"
+msgstr[1] "%d kohdetta ei voitu kirjoittaa tulosteeseen %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "lukuvirhe syötteessä %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: ei voida lukea syötettä %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Onnistui"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Ei osumaa"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Virheellinen säännöllinen lauseke"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Virheellinen vertailumerkki"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Virhellinen merkkiluokan nimi"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Seuraava kenoviiva"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Virheellinen takaisinviittaus"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Pariton \"[\" tai \"[^\""
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Pariton \"(\" tai \"\\(\""
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Pariton \"\\{\""
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Virheellinen sisältö \\{\\}:ssä"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Virheellinen välin loppu"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Muisti loppu"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Virheellinen edeltävä säännöllinen lauseke"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Ennenaikainen säännöllisen lausekkeen loppu"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Säännöllinen lauseke on liian suuri"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Pariton \")\" tai \"\\)\""
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Ei aikaisempaa säännöllistä lausetta"
Index: /tags/kBuild-0.1.4/src/sed/po/fr.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/fr.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/fr.po	(revision 1780)
@@ -0,0 +1,469 @@
+# French translation of GNU sed.
+# Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+# Gaël Quéri <gael@lautre.net>, 1998.
+#
+# J'ai préféré utiliser le terme <<Expression régulière>> plutôt
+# qu'<<expression rationnelle>> car celui-là est moins déroutant
+# pour ceux qui sont habitués à la formulation anglaise
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-07-12 00:09+0200\n"
+"Last-Translator: Gaël Quéri <gael@lautre.net>\n"
+"Language-Team: French <traduc@traduc.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "`!' multiples"
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "`,' inattendue"
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "utilisation invalide de +N ou ~N comme première adresse"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "`{' non refermée"
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "`}' inattendu"
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "caractères inutiles après la commande"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "\\ attendu après `a', `c' ou `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' n'a besoin d'aucune adresse"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": n'a besoin d'aucune adresse"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "les commentaires n'acceptent aucune adresse"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "commande manquante"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "la commande n'utilise qu'une adresse"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "expression régulière d'adresse inachevée"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "commande `s' inachevée"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "commande `y' inachevée"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "option inconnue pour `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "plusieurs options `p' à la commande `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "plusieurs options `g' à la commande `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "plusieurs options numériques à la commande `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "l'option numérique de la comande `s' ne peut être nulle"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "les chaînes destinées à la commande `y' ont des longueurs différentes"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "le caractère délimiteur n'est pas un caractère à un seul octet"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "une version plus récente de sed est attendue"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "utilisation invalide de l'adresse de ligne 0"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "commande inconnue: `%c'"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: fichier %s ligne %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e expression n°%lu, caractère %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "impossible de trouver l'étiquette pour sauter à `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: impossible de lire %s: %s\n"
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "impossible d'éditer %s: est un terminal"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "impossible d'éditer %s: ce n'est pas un fichier régulier"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "impossible d'ouvrir le fichier temporaire %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "erreur dans le sous-processus"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "l'option `e' n'est pas supportée"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "la commande `e' n'est pas supportée"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "pas d'expression régulière précédente"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr ""
+"impossible de spécifier des modifieurs sur une expression\n"
+"rationnelle vide"
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "référence \\%d invalide dans le côté droit de la commande `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 utiliser la syntaxe des expressions régulières\n"
+"                 de Perl 5 dans le script.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"Utilisation: %s [OPTION]... {script-seulement-si-pas-d'autre-script}\n"
+"[fichier-d'entrée]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"  -n, --quiet, --silent\n"
+"                 supprimer l'écriture automatique de l'espace des motifs\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e script, --expression=script\n"
+"                 ajouter le script aux commandes à être exécutées\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f fichier-script, --file=fichier-script\n"
+"                 ajouter le contenu de fichier-script aux commandes\n"
+"                 à être exécutées\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[SUFFIXE], --in-place[=SUFFIXE]\n"
+"                 éditer les fichiers à leur place (fait une\n"
+"                 sauvegarde si l'extension est fournie)\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                spécifier la longueur de coupure de ligne désirée pour la\n"
+"                commande `l'\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 désactiver toutes les extensions GNU.\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 utiliser la syntaxe des expressions régulières\n"
+"                 étendues dans le script.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                considérer les fichiers comme séparés plutôt que comme un\n"
+"                simple flux long et continu.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 charger des quantités minimales de données depuis les\n"
+"                 fichiers d'entrée et libérer les tampons de sortie plus\n"
+"                 souvent\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     afficher cette aide et sortir\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+"      --version  afficher les informations de version du logiciel et sortir\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"Si aucune option -e, --expression, -f ou --file n'est donnée, le\n"
+"premier argument qui n'est pas une option sera pris comme étant le script\n"
+"sed à interpréter. Tous les arguments restants sont les noms des fichiers\n"
+"d'entrée; si aucun fichier d'entrée n'est spécifiée, l'entrée standard\n"
+"est lue.\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Rapporter toutes anomalies à: %s.\n"
+"N'oubliez pas d'inclure le mot ``%s'' quelque-part dans la zone "
+"``Subject:''\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed version %s\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"fondé sur GNU sed version %s\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed version %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Ce logiciel est libre; voir les sources pour les conditions de "
+"reproduction.\n"
+"AUCUNE garantie n'est donnée; y compris pour des RAISONS COMMERCIALES ou\n"
+"pour RÉPONDRE A UN BESOIN PARTICULIER, à l'étendue permise par la loi.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "impossible de supprimer %s: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "impossible d'ouvrir le fichier %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "impossible d'écrire %d item à %s: %s"
+msgstr[1] "impossible d'écrire %d items à %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "erreur de lecture sur %s: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "impossible de renommer %s: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Succès"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Pas de concordance"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Expression régulière invalide"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Caractère de collation invalide"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nom de classe de caractères invalide"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Antislash de protection"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Référence arrière invalide"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[ ou [^ non refermé"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "( ou \\( non refermé"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{ non refermé"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Contenu de \\{\\} invalide"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Fin d'intervalle invalide"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Mémoire épuisée"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "L'expression régulière précédente est invalide"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Fin prématurée d'une expression régulière"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Expression régulière trop grande"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ") ou \\) non refermé"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Pas d'expression régulière précédente"
Index: /tags/kBuild-0.1.4/src/sed/po/ga.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/ga.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/ga.po	(revision 1780)
@@ -0,0 +1,463 @@
+# Irish translations for sed
+# Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+# Kevin Patrick Scannell <scannell@SLU.EDU>, 2003, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-07-07 11:04-0500\n"
+"Last-Translator: Kevin Patrick Scannell <scannell@SLU.EDU>\n"
+"Language-Team: Irish <ga@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 0 : (n>1 && n<7) ? 1 : (n>6 && n "
+"<11) ? 2 : 3;\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "`!'-anna iomadúla"
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "`,' gan choinne"
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "ní féidir +N nó ~N a úsáid mar an chéad seoladh"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "`{' corr"
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "`}' gan choinne"
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "carachtair breise i ndiaidh an t-ordú"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "bhíothas ag súil le \\ i ndiaidh `a', `c', nó `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "Níl fáilte roimh seoltaí le `}'"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr "Níl fáilte roimh seoltaí le `:'"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "níl fáilte roimh seoltaí le nótaí tráchta"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "ordú ar iarraidh"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "ní úsáidtear an t-ordú ach seoladh amháin"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "seoladh regex gan chríochnú"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "ordú `s' gan chríochnú"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "ordú `y' gan chríochnú"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "rogha anaithnid i ndiaidh `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "an iomarca roghanna `p' i ndiaidh `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "an iomarca roghanna `g' i ndiaidh `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "an iomarca roghanna uimhriúla i ndiaidh `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "ní cheadaítear nialas mar rogha uimhriúil leis an ordú `s'"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "ní aon fad amháin ar na teaghráin leis an ordú `y'"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "tá an teorantóir ina charachtar ilbheart"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "bhíothas ag súil le leagan `sed' níos úire"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "ní féidir an seoladh líne 0 a úsáid"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "ordú anaithnid: `%c'"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: comhad %s líne %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e slonn #%lu, char %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "níl aon fháil ar an lipéad `%s' don léim"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: ní féidir %s a léamh: %s\n"
+
+# Irish is nice this way, no initial mutation on 'rud'! -- KPS
+# Include all three b/c I'm using template version of "Plural-Forms"
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "níorbh fhéidir %s a chur in eagar; is teirminéal é"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "níorbh fhéidir %s a chur in eagar: ní gnáthcomhad é"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "níorbh fhéidir an comhad sealadach %s a oscailt: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "earráid i bhfo-phróiseas"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "níl an rogha `e' ar fáil"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "níl an t-ordú `e' ar fáil"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "níl aon slonn ionadaíochta roimh seo"
+
+# bunathraitheoir is in FARF - KPS
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "ní féidir bunathraitheoirí a shonrú le slonn bán"
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "tagairt neamhbhailí \\%d ar dheis ordú `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 bain úsáid as sloinn ionadaíochta atá ag Perl 5.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"Úsáid: %s [ROGHA]... {script-mura-bhfuil-script-eile} [inchomhad]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"  -n, --quiet, --silent\n"
+"                 stop priontáil uathoibríoch den spás patrúin\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e script, --expression=script\n"
+"                 cuir an script leis na horduithe le rith\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f comhad-script, --file=comhad-script\n"
+"                 cuir na línte i `comhad-script' leis na horduithe le rith\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[IARMHÍR], --in-place[=IARMHÍR]\n"
+"                 cuir eagar ar comhaid san áit a bhfuil siad (agus déan\n"
+"                 cúltaca má tá IARMHÍR tugtha\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                 ceap an fad timfhillte le haghaidh an ordaithe `l'\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 díchumasaigh gach feabhsúchán GNU.\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 úsáid sloinn ionadaíochta feabhsaithe sa script.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 féach ar comhaid ina leith seachas mar sruth leanúnach.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 lódáil cantaí beaga ó na comhaid ionchur agus sruthlaigh\n"
+"                 na maoláin aschur níos minice\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     taispeáin an chabhair seo agus éirigh as\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  taispeáin eolas faoin leagan agus éirigh as\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"Mura bhfuil rogha -e, --expression, -f, nó --file ann, glacfar an chéad\n"
+"argóint nach raibh ina rogha mar an script `sed' a léirmhíniú.  Tá gach\n"
+"argóint eile an t-ainm de comhad ionchuir; mura bhfuil comhad ann\n"
+"léigh ón ionchur caighdeánach.\n"
+"\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Seol tuairiscí fabhtanna chuig: %s .\n"
+"Cuir an focal ``%s'' áit éigin sa líne ``Subject:'' le do thoil.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed, leagan %s\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"bunaithe ar GNU sed, leagan %s\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed, leagan %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Is saorbhogearra an ríomhchlár seo; féach ar an bhunchód le haghaidh\n"
+"coinníollacha cóipeála.  Níl baránta AR BITH ann; go fiú níl baránta ann\n"
+"d'INDÍOLTACHT nó FEILIÚNACHT DO FHEIDHM AR LEITH, an oiread atá ceadaithe\n"
+"de réir dlí.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "ní féidir %s a scriosadh: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "níorbh fhéidir an comhad %s a oscailt: %s"
+
+# Irish is nice this way, no initial mutation on 'rud'! -- KPS
+# Include all three b/c I'm using template version of "Plural-Forms"
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "níorbh fhéidir %d rud a scríobh i %s: %s"
+msgstr[1] "níorbh fhéidir %d rud a scríobh i %s: %s"
+msgstr[2] "níorbh fhéidir %d rud a scríobh i %s: %s"
+msgstr[3] "níorbh fhéidir %d rud a scríobh i %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "earráid ag léamh %s: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "ní féidir %s a athainmniú: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Bua!"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Níl a leithéid ann"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Slonn ionadaíochta neamhbhailí"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Carachtar cóimheasa neamhbhailí"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Aicme charachtair neamhbhailí"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Cúlslais ag deireadh"
+
+# coinage - KPS
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Cúltagairt neamhbhailí"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[ nó [^ corr"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "( nó \\( corr"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{ corr"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Ábhar neamhbhailí idir \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Deireadh raoin neamhbhailí"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Cuimhne ídithe"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Is neamhbhailí an slonn ionadaíochta roimh seo"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Deireadh le slonn ionadaíochta gan choinne"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Slonn ionadaíochta rómhór"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ") nó \\) corr"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Níl aon slonn ionadaíochta roimh seo"
Index: /tags/kBuild-0.1.4/src/sed/po/gl.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/gl.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/gl.po	(revision 1780)
@@ -0,0 +1,448 @@
+# Galician translation of GNU sed
+# Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+# Jacobo Tarrío Barreiro <jtarrio@trasno.net>, 1999, 2002.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2002-10-25 15:57+0200\n"
+"Last-Translator: Jacobo Tarrío Barreiro <jtarrio@trasno.net>\n"
+"Language-Team: Galician <gpul-traduccion@ceu.fi.udc.es>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n!=1;\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Múltiples `!'s"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "`,' inesperada"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Non se pode usar +N ou ~N como primeira dirección"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "`{' sen parella"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "`}' inesperado"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Caracteres extra despois da instrucción"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Esperábase \\ despois de `a', `c' ou `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' non acepta un enderezo"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": non acepta un enderezo"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Os comentarios non aceptan enderezos"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Falta unha instrucción"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "A instrucción só usa un enderezo"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Expresión regular de enderezo non rematada"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Instrucción `s' non rematada"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Instrucción `y' non rematada"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Opción de `s' descoñecida"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "múltiples opcións `p' para a instrucción `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "múltiples opcións `g' para a instrucción `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "múltiples opcións numéricas para a instrucción `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "unha opción numérica para a instrucción `s' non pode ser cero"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "as cadeas para a instrucción y teñen lonxitudes diferentes"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Uso non válido de modificador de dirección"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Instrucción descoñecida:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: ficheiro %s liña %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e expresión #%lu, carácter %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Non se puido atopa-la etiqueta para saltar a `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: non se puido ler %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Non se puido abri-lo ficheiro %s: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Non se puido abri-lo ficheiro %s: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Non se puido abri-lo ficheiro %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "erro no subproceso"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "a opción `e' non está soportada"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "o comando `e' non está soportado"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Non hai unha expresión regular anterior"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Non se poden especificar modificadores nunha expresión regular baleira"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Referencia \\%d non válida no lado dereito do comando `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 usa-la sintaxe de expresións regulares de Perl 5 no "
+"script.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 usa-la sintaxe de expresións regulares de Perl 5 no "
+"script.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Informe dos erros no programa a %s .\n"
+"Informe dos erros na traducción a gpul-traduccion@ceu.fi.udc.es .\n"
+"Asegúrese de incluí-la palabra ``%s'' nalgunha parte do campo ``Subject:''.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versión %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr "baseado en GNU sed versión 3.02.80\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versión %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Isto é software libre; vexa o código fonte polas condicións de copia. NON "
+"hai\n"
+"garantía; nin sequera de COMERCIABILIDADE ou APTITUDE PARA UN FIN "
+"DETERMINADO,\n"
+"ata o que permite a lei.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: non se puido ler %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Non se puido abri-lo ficheiro %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "non se puido escribir %d elemento en %s: %s"
+msgstr[1] "non se puideron escribir %d elementos en %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "erro de lectura en %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: non se puido ler %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Éxito"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Non se atopou"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Expresión regular non válida"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Carácter de ordeamento non válido"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nome de clase de caracteres non válido"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Barra invertida á fin de liña"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Referencia cara a atrás non válida"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[ ou [^ sen parella"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "( ou \\( sen parella"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{ sen parella"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Contido de \\{\\} non válido"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Fin de rango non válida"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Memoria esgotada"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Expresión regular anterior non válida"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Fin prematura da expresión regular"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Expresión regular grande de máis"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ") ou \\) sen parella"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Non hai unha expresión regular anterior"
Index: /tags/kBuild-0.1.4/src/sed/po/he.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/he.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/he.po	(revision 1780)
@@ -0,0 +1,439 @@
+# Hebrew messages for GNU Sed          -*- coding: hebrew-iso-8bit -*-
+# Copyright (C) 2001 Free Software Foundation, Inc.
+# Eli Zaretskii <eliz@is.elta.co.il>, 2001.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 3.02.80\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2001-08-04 20:37+0300\n"
+"Last-Translator: Eli Zaretskii <eliz@gnu.org>\n"
+"Language-Team: Hebrew <eliz@gnu.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-8\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "`!' éåáéø"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "éåôö-éúìá `,'"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "äðåùàø úáåúëë ~N åà +N-á ùîúùäì ïúéð àì"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "âåæ-ïá åì ïéàù `{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "éåôö-éúìá `}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "äãå÷ôä éøçà íéøúåéî íéåú"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr ""
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "úåáåúë ìá÷î åðéà `}'"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr "úåáåúë ìá÷î åðéà :"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "úåáåúë úåìá÷î ïðéà úåøòä"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "äøñç äãå÷ô"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "ãáìá úçà úáåúë úìá÷î åæ äãå÷ô"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "íåéñ àìì úáåúë ìù éøìåâø éåèéá"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "íåéñ àìì `s' úãå÷ô"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "íåéñ àìì `y' úãå÷ô"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "`s' ìù øëåî-éúìá ïééôàî"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "`s' äãå÷ôì íéáåøî `p' éðééôàî"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "`s' äãå÷ôì íéáåøî `g' éðééôàî"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "`s' äãå÷ôì íéáåøî øôñî éðééôàî"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "ñôà úåéäì ìåëé åðéà `s' äãå÷ôì éøôñî ïééôàî"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "äðåù êøåàá ïðéä `y' äãå÷ôì úåæåøçî"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "úáåúëä ïééöîá éåâù ùåîéù"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "úøëåî-éúìá äãå÷ô äðéä"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s úéðëúá (%s õáå÷ ìù %lu äøåù) %s äàéâù\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s úéðëúá (%lu 'ñî -e éåèéá ìù %lu 'ñî åú) %s äàéâù\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "äàöîð àì `%s' äöéô÷ úéååú"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s úéðëúá %s úàéø÷á (%s) äàéâù\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "%s õáå÷ úçéúôá äì÷ú"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "%s õáå÷ úçéúôá äì÷ú"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "%s õáå÷ úçéúôá äì÷ú"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr ""
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr ""
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr ""
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr ""
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr ""
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr ""
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"              .%s úáåúëì (bugs) äì÷ú éçååéã çåìùì àð\n"
+"   .(``Subject'') ``ïåãðä'' úøåùá ``%s'' äìéî ìåìëì åãéô÷ä àðà\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"äååìî äðéà úéðëúä .øå÷îä éöá÷ úà äàø ,èåøéô øúéì ;úéùôç äðëú äðéä åæ úéðëú\n"
+"    äãéîá úàæå ,àéäù úéìëú åæéàì äîàúä åà úåøéçñ íùì àì åìéôà ;úåéøçà áúëá\n"
+"                                                          .úàæ øùôàî ÷åçäù\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s úéðëúá %s úàéø÷á (%s) äàéâù\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "%s õáå÷ úçéúôá äì÷ú"
+
+#: lib/utils.c:220
+#, fuzzy, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "èìôäî íé÷ìç %d ìù %s-ì äáéúëá (%s) äì÷ú"
+msgstr[1] "èìôäî íé÷ìç %d ìù %s-ì äáéúëá (%s) äì÷ú"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "%s úàéø÷á (%s) äì÷ú"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s úéðëúá %s úàéø÷á (%s) äàéâù\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr ""
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr ""
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr ""
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr ""
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr ""
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr ""
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr ""
+
+#: lib/regcomp.c:153
+#, fuzzy
+msgid "Unmatched [ or [^"
+msgstr "âåæ-ïá åì ïéàù `{'"
+
+#: lib/regcomp.c:156
+#, fuzzy
+msgid "Unmatched ( or \\("
+msgstr "âåæ-ïá åì ïéàù `{'"
+
+#: lib/regcomp.c:159
+#, fuzzy
+msgid "Unmatched \\{"
+msgstr "âåæ-ïá åì ïéàù `{'"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr ""
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr ""
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr ""
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr ""
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr ""
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr ""
+
+#: lib/regcomp.c:180
+#, fuzzy
+msgid "Unmatched ) or \\)"
+msgstr "âåæ-ïá åì ïéàù `{'"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr ""
Index: /tags/kBuild-0.1.4/src/sed/po/hr.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/hr.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/hr.po	(revision 1780)
@@ -0,0 +1,447 @@
+# Translation of sed to Croatian
+# Copyright (C) 2002 Free Software Foundation, Inc.
+# Denis Lackovi <delacko@fly.srk.fer.hr>, 2002.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 3.02a\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2002-06-14 15:17-01\n"
+"Last-Translator: Denis Lackovic <delacko@fly.srk.fer.hr>\n"
+"Language-Team: Croatian <lokalizacija@linux.hr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n==1?0:1);\n"
+"X-Generator: TransDict server\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Višestruki `!'"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Neočekivani `,'"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Ne mogu koristiti +N ili ~N kao prvu adresu"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Neuparena `{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Neočekivana `}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Višak znakova nakon komande"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr ""
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' ne želi nikakve adrese"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": ne želi nikakve adrese"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Komentari ne primaju adrese"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Nedostaje naredba"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Naredba koristi samo jednu adresu"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Nezavršeni regularni izraz adrese"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Nezavršena `s' naredba"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Nezavršena `y' naredba"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Nepoznata opcija za `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "višestruke `p' opcije za `s' naredbu"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "višestruke `g' opcije za `s' naredbu"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "višak opcija za za `s' naredbu"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "broj opcija za naredbu `s' ne smije biti nula"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "znakovni nizovi za naredbu y su različitih duljina"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Neispravna uporaba adresnog modifikatora"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Nepoznata naredba:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: datoteka %s redak %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e izraz #%lu, znak %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Ne mogu naći labelu na koju bi trebalo skočiti `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: ne mogu čitati %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Ne mogu otvoriti datoteku %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Ne mogu otvoriti datoteku %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Ne mogu otvoriti datoteku %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr ""
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr ""
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr ""
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Nedostaje prethodni regularni izraz"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr ""
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr ""
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"E-mail bug prijave (na engleskom) pošaljite na: %s .\n"
+"Uključite riječ ``%s'' u polju ``Subject:''.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Ovo je slobodni softver; pogledajte kod kako biste doznali uvjete "
+"kopiranja.\n"
+" NEMA garancije;\n"
+"čak ni tvrdnje o ISPLATIVOSTI ili POGODNOSTI ZA NEKU SVRHU.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: ne mogu čitati %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Ne mogu otvoriti datoteku %s"
+
+#: lib/utils.c:220
+#, fuzzy, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "Ne mogu upisati %d item%s u %s: %s"
+msgstr[1] "Ne mogu upisati %d item%s u %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "Greška u čitanju na %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: ne mogu čitati %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr ""
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr ""
+
+#: lib/regcomp.c:138
+#, fuzzy
+msgid "Invalid regular expression"
+msgstr "Nedostaje prethodni regularni izraz"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr ""
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr ""
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr ""
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr ""
+
+#: lib/regcomp.c:153
+#, fuzzy
+msgid "Unmatched [ or [^"
+msgstr "Neuparena `{'"
+
+#: lib/regcomp.c:156
+#, fuzzy
+msgid "Unmatched ( or \\("
+msgstr "Neuparena `{'"
+
+#: lib/regcomp.c:159
+#, fuzzy
+msgid "Unmatched \\{"
+msgstr "Neuparena `{'"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr ""
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr ""
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr ""
+
+#: lib/regcomp.c:171
+#, fuzzy
+msgid "Invalid preceding regular expression"
+msgstr "Nedostaje prethodni regularni izraz"
+
+#: lib/regcomp.c:174
+#, fuzzy
+msgid "Premature end of regular expression"
+msgstr "Nedostaje prethodni regularni izraz"
+
+#: lib/regcomp.c:177
+#, fuzzy
+msgid "Regular expression too big"
+msgstr "Nedostaje prethodni regularni izraz"
+
+#: lib/regcomp.c:180
+#, fuzzy
+msgid "Unmatched ) or \\)"
+msgstr "Neuparena `{'"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Nedostaje prethodni regularni izraz"
Index: /tags/kBuild-0.1.4/src/sed/po/hu.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/hu.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/hu.po	(revision 1780)
@@ -0,0 +1,446 @@
+# Hungarian translation of GNU sed
+# Copyright (C) 2002 Free Software Foundation, Inc.
+# Gábor István <stive@mezobereny.hu>, 2002.
+# Mihály Gyulai <gyulai@fbi.hu>, 2003.
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.8\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-10-26 09:28+0100\n"
+"Last-Translator: Mihály Gyulai <gyulai@fbi.hu>\n"
+"Language-Team: Hungarian <translation-team-hu@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Több `!'"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Váratlan `,'"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Nem lehet használni a +N-t vagy ~N-t elso címként"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Nincs párban `{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Nincs párban `}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Extra karakterek a parancs után "
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "`a', `c' vagy `i' parancs után \\ szükséges"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' nem igényel címzést"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": nem igényel címzést"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Megjegyzésben nem lehet címzés"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Hiányzó parancs"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "A parancs csak egy címzést használ"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Befejezetlen regex cím"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Befejezetlen `s' parancs"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Befejezetlen `y' parancs"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Ismeretlen `s' opció"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "többszörös `p' opció, `s' parancs mellett"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "többszörös `g' opció, `s' parancs mellett"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "többszörös szám opció, `s' parancs mellett"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "a(z) `s' parancs szám opciója nem lehet nulla"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "a(z) `y' parancs szövegeinek hossza különbözõ"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "a 'sed' program újabb verziójára van szükség"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "A parancs csak egy címzést használ"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Ismeretlen parancs:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: fájl %s sor %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e kifejezés #%lu, karakter %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Az ugráshoz (`%s') nem találom a címkét"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: nem lehet olvasni %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Nem lehet megnyitni a(z) %s fájlt: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Nem lehet megnyitni a(z) %s fájlt: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Nem lehet megnyitni az átmeneti fájlt: %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "hiba az alfolyamatban"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "az `e' opció nincs támogatva"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "az `e' parancs nincs támogatva"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Nincsen elõzõ reguláris kifejezés"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Nem lehet módosítót megadni üres reguláris kifejezéshez"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Hibás hivatkozás (\\%d) a(z) `s' parancs RHS-ére"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R --regexp-perl\n"
+"                Perl 5 reguláris kifejezés nyelvtanának használata.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R --regexp-perl\n"
+"                Perl 5 reguláris kifejezés nyelvtanának használata.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"A fordítási hibákat kérem a gyulai@fbi.hu címre küldeni. \n"
+"Angolul ide: %s . A levél Tárgy mezejében legyen ott a `%s' szó.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed verzió %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"A GNU 3.02.80-as sed verzión alapszik\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed verzió %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Ez egy ingyenes számítógépes program. A forrásban megtalálhatók a másolás "
+"feltételei.\n"
+"SEMMILYEN garanciát nem vállalunk, még azt sem állítjuk, hogy ez a program\n"
+"KERESKEDELMI CÉLOKRA ALKALMAS vagy HASZNÁLHATÓ EGY ADOTT FELADATRA.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: nem lehet olvasni %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Nem lehet megnyitni a(z) %s fájlt: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "nem tudom a(z) %d elemet ide írni %s: %s"
+msgstr[1] "nem tudom a(z) %d elemeket ide írni %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "olvasási hiba %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: nem lehet olvasni %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Sikeres"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Nincs találat"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Hibás reguláris kifejezés"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Érvénytelen összehasonlító karakter"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Érvénytelen karakterosztály-név"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Lezáró visszaperjel"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Érvénytelen vissza-hivatkozás"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Nincs párban [ vagy [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Nincs párban ( vagy \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Nincs párban \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "\\{\\}-nak érvénytelen a tartalma"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Sorozat érvénytelen vége"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Kevés a memória"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Érvénytelen megelõzõ reguláris kifejezés"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Reguláris kifejezés túl korai vége"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Túl nagy reguláris kifejezés"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Nincs párban ) vagy \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Nincsen elõzõ reguláris kifejezés"
Index: /tags/kBuild-0.1.4/src/sed/po/id.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/id.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/id.po	(revision 1780)
@@ -0,0 +1,447 @@
+# translation of sed-4.0.9.id.po to Indonesian
+# sed 4.0.9 (Indonesian)
+# Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+# Tedi Heriyanto <tedi_h@gmx.net>, 2002, 2003, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.9\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-04-27 14:56+0700\n"
+"Last-Translator: Tedi Heriyanto <tedi_h@gmx.net>\n"
+"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: KBabel 1.3\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "`!' ganda"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "`,' tidak diharapkan"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Tidak dapat menggunakan +N atau ~N sebagai alamat pertama"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "`{' tidak sesuai"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "`}' tidak diharapkan"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Karakter tambahan setelah perintah"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Diharapkan \\ setelah `a', `c' atau `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' tidak menginginkan alamat"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": tidak menginginkan alamat"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Komentar tidak menerima alamat"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Perintah hilang"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Perintah hanya menggunakan satu alamat"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Alamat regex yang tidak selesai"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Perintah `s' tidak selesai"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Perintah `y' tidak selesai"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Opsion tidak dikenal bagi `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "opsion `p' ganda bagi perintah `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "opsion `g' ganda bagi perintah `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "opsion beragam untuk perintah `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "opsion angka untuk perintah `s' tidak boleh nol"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "string untuk perintah y dalam panjang yang berbeda"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "mengharapkan versi baru sed"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Penggunaan modifier alamat yang tidak valid"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Perintah tidak dikenal:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: file %s baris %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e ekspresi #%lu, char %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Tidak dapat menemukan label untuk melompat ke `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: tidak dapat membaca %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Tidak dapat membuka file %s %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Tidak dapat membuka file %s %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Tidak dapat membuka file temporer %s %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "kesalahan dalam subproses"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "option `e' tidak didukung"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "perintah `e' tidak didukung"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Tidak ada reguler ekspresi sebelumnya"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Tidak dapat menspesifikasikan modified pada regexp kosong"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Referensi tidak valid \\%d pada perintah `s' RHS"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 gunakan sintaks reguler ekspresi Perl 5 dalam skrip.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 gunakan sintaks reguler ekspresi Perl 5 dalam skrip.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Email laporan kesalahan ke: %s \n"
+"Pastikan untuk menyertakan kata \"%s\" di field \"Subject:\".\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versi %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"berdasarkan pada GNU sed versi 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versi %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: tidak dapat membaca %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Tidak dapat membuka file %s %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "tidak dapat menulis %d item ke %s: %s"
+msgstr[1] "tidak dapat menulis %d item ke %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "kesalahan pembacaan pada %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: tidak dapat membaca %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Sukses"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Tidak cocok"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Reguler ekspresi tidak valid"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Karakter kolasi tidak valid"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nama kelas karakter tidak valid"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Trailing backslash"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Referensi balik tidak valid"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[ atau [^ tidak sesuai"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "( atau \\( tidak sesuai"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{ tidak sesuai"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Isi \\{\\} tidak valid"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Akhir batas tidak valid"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Memori habis"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Reguler ekspresi sebelumnya tidak valid"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Akhir reguler ekspresi prematur"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Reguler ekspresi terlalu besar"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ") atau \\) tidak sesuai"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Tidak ada reguler ekspresi sebelumnya"
Index: /tags/kBuild-0.1.4/src/sed/po/insert-header.sin
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/insert-header.sin	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/insert-header.sin	(revision 1780)
@@ -0,0 +1,23 @@
+# Sed script that inserts the file called HEADER before the header entry.
+#
+# At each occurrence of a line starting with "msgid ", we execute the following
+# commands. At the first occurrence, insert the file. At the following
+# occurrences, do nothing. The distinction between the first and the following
+# occurrences is achieved by looking at the hold space.
+/^msgid /{
+x
+# Test if the hold space is empty.
+s/m/m/
+ta
+# Yes it was empty. First occurrence. Read the file.
+r HEADER
+# Output the file's contents by reading the next line. But don't lose the
+# current line while doing this.
+g
+N
+bb
+:a
+# The hold space was nonempty. Following occurrences. Do nothing.
+x
+:b
+}
Index: /tags/kBuild-0.1.4/src/sed/po/it.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/it.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/it.po	(revision 1780)
@@ -0,0 +1,524 @@
+# traduzione di sed
+# Copyright (C) 1999 Free Software Foundation, Inc.
+# Paolo Bonzini <bonzini@gnu.org>, 2001
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0a\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2002-11-26 12:44+0100\n"
+"Last-Translator: Paolo Bonzini <bonzini@gnu.org>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+# sed/compile.c:166
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "`!' multipli"
+
+# sed/compile.c:167
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "`,' inattesa"
+
+# sed/compile.c:169
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "impossibile usare +N o ~N come primo indirizzo"
+
+# sed/compile.c:170
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "`{' non bilanciata"
+
+# sed/compile.c:171
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "`}' inattesa"
+
+# sed/compile.c:172
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "ci sono altri caratteri dopo il comando"
+
+# sed/compile.c:173
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "atteso \\ dopo `a', `c' o `i'"
+
+# sed/compile.c:174
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' non accetta indirizzi"
+
+# sed/compile.c:175
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": non accetta indirizzi"
+
+# sed/compile.c:176
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "i commenti non accettano indirizzi"
+
+# sed/compile.c:177
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "manca il comando"
+
+# sed/compile.c:178
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "il comando usa solo un indirizzo"
+
+# sed/compile.c:179
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "espressione regolare non terminata nell'indirizzo"
+
+# sed/compile.c:180
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "comando `s' non terminato"
+
+# sed/compile.c:181
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "comando `y' non terminato"
+
+# sed/compile.c:182
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "opzione di `s' sconosciuta"
+
+# sed/compile.c:183
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "opzioni `p' multiple al comando `s'"
+
+# sed/compile.c:184
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "opzioni `g' multiple al comando `s'"
+
+# sed/compile.c:186
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "opzioni numeriche multiple al comando `s'"
+
+# sed/compile.c:188
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "l'opzione numerica del comando `s' non può essere zero"
+
+# sed/compile.c:190
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "le stringhe per il comandi `y' hanno lunghezze diverse"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "il carattere delimitatore è multi-byte"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "attesa una versione piu' recente di sed"
+
+# sed/compile.c:178
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "utilizzo non valido dell'indirizzo 0"
+
+# sed/compile.c:1319
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "comando sconosciuto: `%c'"
+
+# sed/compile.c:1340
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: file %s riga %lu: %s\n"
+
+# sed/compile.c:1343
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: espressione -e #%lu, carattere %lu: %s\n"
+
+# sed/compile.c:1543
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "impossibile trovare un'etichetta per il salto a `%s'"
+
+# sed/execute.c:516
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: impossibile leggere %s: %s\n"
+
+# sed/execute.c:675
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "impossibile modificare %s: è un terminale"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "impossibile modificare %s: non è un file normale"
+
+# lib/utils.c:131
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "impossibile aprire il file temporaneo %s: %s"
+
+# sed/execute.c:1003 sed/execute.c:1183
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "errore in un sottoprocesso"
+
+# sed/execute.c:1005
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "opzione `e' non supportata"
+
+# sed/execute.c:1185
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "comando `e' non supportato"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr "nessun file in ingresso"
+
+# lib/regcomp.c:658 sed/regex.c:47
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "occorre un'espressione regolare precedente"
+
+# sed/regex.c:48
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "non è possibile specificare dei modificatori per l'espressione vuota"
+
+# sed/regex.c:146
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "riferimento non valido \\%d nel secondo membro del comando `s'"
+
+# sed/sed.c:98
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 usa la sintassi Perl 5 per le espressioni regolari\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"Utilizzo: %s [OPZIONE]... {script-se-nessun-altro-specificato} [input-"
+"file]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"  -n, --quiet, --silent\n"
+"                 sopprime la stampa automatica del pattern space\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e script, --expression=script\n"
+"                 aggiunge lo script ai comandi da eseguire\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f script-file, --file=file-script\n"
+"                 aggiunge il contenuto di file-script ai comandi da "
+"eseguire\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 scrive il risultato sul file originale (facendo una copia\n"
+"                 se è fornita un'estensione)\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                 specifica la lunghezza delle linee generate dal comando "
+"`l'\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 disabilita tutte le estensioni GNU.\n"
+
+# sed/sed.c:98
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 usa la sintassi di `egrep' per le espressioni regolari\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 considera i file di input come separati invece che come un\n"
+"                 unico file lungo.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 carica e visualizza i dati una a pezzetti piu' piccoli\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     mostra questo aiuto ed esce\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  stampa le informazioni sulla versione ed esce\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"Se non è usata nessuna delle opzioni -e, --expression, -f o --file allora "
+"il\n"
+"primo argomento che non è una opzione sarà usato come lo script sed da\n"
+"interpretare. Tutti gli argomenti rimanenti sono nomi di file di input; se "
+"non\n"
+"sono specificati file di input sarà letto lo standard input.\n"
+"\n"
+
+# sed/sed.c:132
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Segnalare eventuali bug a: %s .\n"
+"Assicurarsi di includere la parola ``%s'' nell'oggetto del messaggio.\n"
+
+# sed/sed.c:255
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versione %s\n"
+
+# sed/sed.c:256
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"basato su GNU sed versione %s\n"
+"\n"
+
+# sed/sed.c:258
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versione %s\n"
+
+# sed/sed.c:260
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Questo è software libero; si veda il sorgente per le condizioni di "
+"copiatura.\n"
+"NON c'è garanzia; neppure di COMMERCIABILITA' o IDONEITA' AD UN PARTICOLARE\n"
+"SCOPO, nei limiti permessi dalla legge.\n"
+
+# sed/execute.c:516
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "impossibile rimuovere %s: %s"
+
+# lib/utils.c:131
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "impossibile aprire il file %s: %s"
+
+# lib/utils.c:161
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "Impossibile scrivere %d elemento su %s: %s"
+msgstr[1] "Impossibile scrivere %d elementi su %s: %s"
+
+# lib/utils.c:176
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "errore di lettura su %s: %s"
+
+# sed/execute.c:516
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "impossibile rinominare %s: %s"
+
+# lib/regcomp.c:179
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Successo"
+
+# lib/regcomp.c:182
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Nessuna corrispondenza trovata"
+
+# lib/regcomp.c:185
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Espressione regolare non valida"
+
+# lib/regcomp.c:188
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Carattere di ordinamento non valido"
+
+# lib/regcomp.c:191
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nome non valido per una classe di caratteri"
+
+# lib/regcomp.c:194
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Barra rovesciata alla fine dell'espressione regolare"
+
+# lib/regcomp.c:197
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Riferimento non valido"
+
+# lib/regcomp.c:200
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "`[' non bilanciata"
+
+# lib/regcomp.c:203
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "`(' o `\\(' non bilanciata"
+
+# lib/regcomp.c:206
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "`\\{' non bilanciata"
+
+# lib/regcomp.c:209
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "numero di ripetizioni specificato tra graffe non valido"
+
+# lib/regcomp.c:212
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Fine dell'intervallo non valida"
+
+# lib/regcomp.c:215
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Memoria esaurita"
+
+# lib/regcomp.c:218
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Espressione regolare precedente non valida"
+
+# lib/regcomp.c:221
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Fine prematura dell'espressione regolare"
+
+# lib/regcomp.c:224
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Espressione regolare troppo grande"
+
+# lib/regcomp.c:227
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "`)' o `\\)' non bilanciata"
+
+# lib/regcomp.c:658 sed/regex.c:47
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Occorre un'espressione regolare precedente"
Index: /tags/kBuild-0.1.4/src/sed/po/ja.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/ja.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/ja.po	(revision 1780)
@@ -0,0 +1,464 @@
+# Japanese messages for GNU sed
+# Copyright (C) 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+# IIDA Yosiaki <iida@gnu.org>, 1999, 2002, 2003, 2004, 2005.
+# This file is distributed under the same license as the GNU sed package.
+# Contributed by
+# Yasuyuki Furukawa <yasu@on.cs.keio.ac.jp>, 1999.
+# and taken over on 1999-09-24 by Japanese Team.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU sed 4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2005-02-01 21:02+0900\n"
+"Last-Translator: IIDA Yosiaki <iida@gnu.org>\n"
+"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=EUC-JP\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "Ê£¿ô¤Î¡Ö!¡×¤Ç¤¹"
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "Í½´ü¤»¤Ì¡Ö,¡×¤Ç¤¹"
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "ºÇ½é¤Î¥¢¥É¥ì¥¹¤Ø¤Î+N¤ä~N¤Î»ØÄê¤ÏÌµ¸ú¤Ç¤¹"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "Äà¤ê¹ç¤ï¤Ê¤¤¡Ö{¡×¤Ç¤¹"
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "Í½´ü¤»¤Ì¡Ö}¡×¤Ç¤¹"
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "¥³¥Þ¥ó¥É¤Î¸å¤í¤ËÍ¾·×¤ÊÊ¸»ú¤¬¤¢¤ê¤Þ¤¹"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "\\¤¬¡Öa¡×¡Öc¡×¡Öi¡×¤Î¸å¤ËÍ½´ü¤µ¤ì¤Þ¤¹"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "¡Ö}¡×¤Ë¥¢¥É¥ì¥¹¤ÏÉÔÍ×¤Ç¤¹"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ":¤Ë¥¢¥É¥ì¥¹¤ÏÉÔÍ×¤Ç¤¹"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "¥³¥á¥ó¥È¤Ï¥¢¥É¥ì¥¹¤ò¼õ¤±ÉÕ¤±¤Þ¤»¤ó"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "¥³¥Þ¥ó¥É¤¬Â­¤ê¤Þ¤»¤ó"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "¥³¥Þ¥ó¥É¤Ï¥¢¥É¥ì¥¹¤ò1¤Ä¤À¤±»È¤¤¤Þ¤¹"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "¥¢¥É¥ì¥¹regex¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "¡Öy¡×¥³¥Þ¥ó¥É¤¬½ªÎ»¤·¤Æ¤¤¤Þ¤»¤ó"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "¡Ös¡×¤Ø¤Î¥ª¥×¥·¥ç¥ó¤¬Ì¤ÃÎ¤Ç¤¹"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¡Öp¡×¥ª¥×¥·¥ç¥ó"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¡Ög¡×¥ª¥×¥·¥ç¥ó"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤ËÊ£¿ô¤Î¿ôÃÍ¥ª¥×¥·¥ç¥ó"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤Ø¤Î¿ôÃÍ¥ª¥×¥·¥ç¥ó¤ÏÎí¤Ç¤Ï¤¤¤±¤Þ¤»¤ó"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "¡Öy¡×¥³¥Þ¥ó¥É¤Ø¤ÎÊ¸»úÎó¤ÎÄ¹¤µ¤¬¡¢°ã¤¤¤Þ¤¹"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "¶èÀÚ¤êÊ¸»ú¤¬¡¢Ã±°ì¥Ð¥¤¥ÈÊ¸»ú¤Ç¤¢¤ê¤Þ¤»¤ó"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "sed¤Î¿·ÈÇ¤¬Á°Äó¤Ç¤¹"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "Ìµ¸ú¤Ê¹Ô¥¢¥É¥ì¥¹0¤Î»ÈÍÑË¡"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "Ì¤ÃÎ¤Î¥³¥Þ¥ó¥É¤Ç¤¹: ¡Ö%c¡×"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: ¥Õ¥¡¥¤¥ë %s %lu¹Ô: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e É½¸½ #%lu, Ê¸»ú¿ô %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "¡Ö%s¡×¤Ø¤Î¥¸¥ã¥ó¥×¤Î¥é¥Ù¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: %s¤òÆÉ¤ß¹þ¤á¤Þ¤»¤ó: %s\n"
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "%s¤Ï¡¢ÊÔ½¸¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿: Ã¼Ëö¤Ç¤¹"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "%s¤Ï¡¢ÊÔ½¸¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿: ÄÌ¾ï¥Õ¥¡¥¤¥ë¤Ç¤¢¤ê¤Þ¤»¤ó"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "°ì»þ¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó¤Ç¤·¤¿: %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "»Ò¥×¥í¥»¥¹¤Î¥¨¥é¡¼"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "¡Öe¡×¥ª¥×¥·¥ç¥ó¤Ï¡¢¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "¡Öe¡×¥³¥Þ¥ó¥É¤Ï¡¢¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "Ä¾Á°¤ÎÀµµ¬É½¸½¤¬¡¢¤¢¤ê¤Þ¤»¤ó"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "½¤¾þ»Ò¤Ï¡¢¶õ¤ÎÀµµ¬É½¸½¤Ë»ØÄê¤Ç¤­¤Þ¤»¤ó"
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "¡Ös¡×¥³¥Þ¥ó¥É¤Î±¦Â¦¤ËÌµ¸ú¤Ê\\%d¤Î»²¾È"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 ¥¹¥¯¥ê¥×¥È¤ÇPerl 5¤ÎÀµµ¬É½¸½¹½Ê¸¤ò»È¤¦¡£\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"»ÈÍÑË¡: %s [¥ª¥×¥·¥ç¥ó]... {¥¹¥¯¥ê¥×¥È(Â¾¤Ë¤Ê¤±¤ì¤Ð)} [ÆþÎÏ¥Õ¥¡¥¤¥ë]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, fuzzy, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"-n, --quiet, --silent\n"
+"                 ¥Ñ¥¿¡¼¥ó¡¦¥¹¥Ú¡¼¥¹¤Î¼«Æ°½ÐÎÏ¤òÍÞÀ©\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e ¥¹¥¯¥ê¥×¥È, --expression=¥¹¥¯¥ê¥×¥È\n"
+"                 ¼Â¹Ô¤¹¤ë¥³¥Þ¥ó¥É¤È¤·¤Æ¥¹¥¯¥ê¥×¥È¤òÄÉ²Ã\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f ¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë, --file=¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë\n"
+"                 ¼Â¹Ô¤¹¤ë¥³¥Þ¥ó¥É¤È¤·¤Æ¥¹¥¯¥ê¥×¥È¡¦¥Õ¥¡¥¤¥ë¤ÎÆâÍÆ¤òÄÉ²Ã\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[ÀÜÈø¼­], --in-place[=ÀÜÈø¼­]\n"
+"                 ¥Õ¥¡¥¤¥ë¤ò¤½¤Î¾ì¤ÇÊÔ½¸ (³ÈÄ¥»Ò¤¬¤¢¤ì¤Ð¡¢¥Ð¥Ã¥¯¥¢¥Ã¥×¤òºî"
+"À®)\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                 ¡Öl¡×¥³¥Þ¥ó¥ÉÍÑ¤Î¹ÔÀÞÊÖ¤·Ä¹¤ò»ØÄê\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 GNU³ÈÄ¥¤òÁ´Éô¶Ø»ß¡£\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 ¥¹¥¯¥ê¥×¥È¤Ç³ÈÄ¥Àµµ¬É½¸½¤ò»ÈÍÑ¡£\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 ¥Õ¥¡¥¤¥ë¤ò°ìÏ¢¤ÎÆþÎÏ¤Ë¤»¤º¡¢ÊÌ¡¹¤Ë½èÍý¡£\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 ÆþÎÏ¥Õ¥¡¥¤¥ë¤«¤é¶Ë¾®¤Î¥Ç¡¼¥¿¤ò¼è¤ê¹þ¤ß¡¢\n"
+"                 ¤Á¤ç¤¯¤Á¤ç¤¯½ÐÎÏ¥Ð¥Ã¥Õ¥¡¡¼¤ËÁÝ½Ð¤·\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     ¤³¤ÎÀâÌÀ¤òÉ½¼¨¤·¤Æ½ªÎ»\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  ¥Ð¡¼¥¸¥ç¥ó¾ðÊó¤òÉ½¼¨¤·¤Æ½ªÎ»\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"-e¡¢--expression¡¢-f¡¢--file¥ª¥×¥·¥ç¥ó¤Î¤É¤ì¤â¤Ê¤¤¤È¡¢¥ª¥×¥·¥ç¥ó°Ê³°¤Î\n"
+"ºÇ½é¤Î°ú¿ô¤òsed¥¹¥¯¥ê¥×¥È¤È¤·¤Æ²ò¼á¤·¤Þ¤¹¡£»Ä¤ê¤Î°ú¿ô¤ÏÁ´Éô¡¢ÆþÎÏ¥Õ¥¡\n"
+"¥¤¥ëÌ¾¤È¤Ê¤ê¤Þ¤¹¡£ÆþÎÏ¥Õ¥¡¥¤¥ë¤Î»ØÄê¤¬¤Ê¤¤¤È¡¢É¸½àÆþÎÏ¤òÆÉ¤ß¹þ¤ß¤Þ¤¹¡£\n"
+"\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"ÅÅ»Ò¥á¡¼¥ë¤Ë¤è¤ë¥Ð¥°Êó¹ð¤Î°¸Àè: %s\n"
+"Êó¹ð¤ÎºÝ¡¢¡ÈSubject:¡É¥Õ¥£¡¼¥ë¥É¤Î¤É¤³¤«¤Ë¡È%s¡É¤òÆþ¤ì¤Æ¤¯¤À¤µ¤¤¡£\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed %sÈÇ\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"¸¶ºîGNU sed %sÈÇ\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr ""
+"GNU sed %sÈÇ\n"
+"\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+"\n"
+"ÌõÃí: Èó¾ï¤Ë½ÅÍ×¤ÊÊ¸¾Ï¤Î¤¿¤á¡¢¸¶Ê¸¤ò»Ä¤·¤Æ¤¤¤Þ¤¹¡£\n"
+"  -- »²¹ÍÌõ\n"
+"¤³¤ì¤Ï¥Õ¥ê¡¼¡¦¥½¥Õ¥È¥¦¥§¥¢¤Ç¤¹¡£Ê£À½¤Î¾ò·ï¤Ë´Ø¤·¤Æ¤Ï¡¢¥½¡¼¥¹¤ò¤´Í÷¤¯¤À¤µ\n"
+"¤¤¡£ÊÝ¾Ú¤Ï°ìÀÚ¤¢¤ê¤Þ¤»¤ó¡£±ÄÍøÌÜÅª¤äË¡¤ÇÄê¤á¤é¤ì¤¿ÈÏ°Ï¤Ç¤ÎÆÃÄêÌÜÅª¤Î¤¿¤á\n"
+"¤ÎÅ¬¹çÀ­¤â¤¢¤ê¤Þ¤»¤ó¡£\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s¤òºï½ü¤Ç¤­¤Þ¤»¤ó: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "¥Õ¥¡¥¤¥ë%s¤ò³«¤±¤Þ¤»¤ó¤Ç¤·¤¿: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "%d¸Ä¤Î¥¢¥¤¥Æ¥à¤ò%s¤Ø½ñ¤­¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿: %s"
+msgstr[1] "%d¸Ä¤Î¥¢¥¤¥Æ¥à¤ò%s¤Ø½ñ¤­¹þ¤á¤Þ¤»¤ó¤Ç¤·¤¿: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "%s¤ÎÆÉ¹þ¤ß¥¨¥é¡¼: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s¤ÎÌ¾Á°¤òÊÑ¹¹¤Ç¤­¤Þ¤»¤ó: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "À®¸ù"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "¾È¹ç¤·¤Þ¤»¤ó"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Ìµ¸ú¤ÊÀµµ¬É½¸½"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Ìµ¸ú¤Ê¹»¹çÊ¸»ú"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Ìµ¸ú¤ÊÊ¸»ú¥¯¥é¥¹Ì¾"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "¸åÂ³¤ÎµÕ¥¹¥é¥Ã¥·¥å"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Ìµ¸ú¤ÊµÕ»²¾È"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[¤ä[^¤¬Äà¹ç¤¤¤Þ¤»¤ó"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "(¤ä\\(¤¬Äà¹ç¤¤¤Þ¤»¤ó"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{¤¬Äà¹ç¤¤¤Þ¤»¤ó"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Ìµ¸ú¤Ê\\{\\}¤ÎÆâÍÆ\""
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Ìµ¸ú¤ÊÈÏ°Ï¤Î½ªÃ¼"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "¥á¥â¥ê¡¼¤¬Â­¤ê¤Þ¤»¤ó"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Ìµ¸ú¤ÊÀè¹ÔÀµµ¬É½¸½"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Áá²á¤®¤ëÀµµ¬É½¸½½ªÃ¼"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Âç¤­²á¤®¤ëÀµµ¬É½¸½"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Äà¤ê¹ç¤ï¤Ê¤¤)¤ä\\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Ä¾Á°¤ÎÀµµ¬É½¸½¤¬¡¢¤¢¤ê¤Þ¤»¤ó"
Index: /tags/kBuild-0.1.4/src/sed/po/ko.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/ko.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/ko.po	(revision 1780)
@@ -0,0 +1,439 @@
+# ko.po -- Korean messages for GNU sed
+# Copyright (C) 2001 Free Software Foundation, Inc.
+# Jong-Hoon Ryu <redhat4u@netian.com>, 2001.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU sed 3.02.80\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2001-10-12 17:26+0900\n"
+"Last-Translator: Jong-Hoon Ryu <redhat4u@netian.com>\n"
+"Language-Team: Korean <ko@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=EUC-KR\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "`!' °¡ Áßº¹µÇ¾ú½À´Ï´Ù"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "ºÒÇÊ¿äÇÑ `,' °¡ »ç¿ëµÇ°í ÀÖ½À´Ï´Ù"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Ã¹¹øÂ° ÁÖ¼Ò·Î '+N' ¶Ç´Â '~N' À» »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "ºÒÇÊ¿äÇÑ `}' °¡ »ç¿ëµÇ°í ÀÖ½À´Ï´Ù"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "¸í·ÉµÚ¿¡ ÇÊ¿ä¾ø´Â ¹®ÀÚµéÀÌ ÀÖ½À´Ï´Ù"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr ""
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' ¿¡ ¾î¶°ÇÑ ÁÖ¼Òµµ ÇÊ¿äÄ¡ ¾Ê½À´Ï´Ù"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": ¿¡ ¾î¶°ÇÑ ÁÖ¼Òµµ ÇÊ¿äÄ¡ ¾Ê½À´Ï´Ù"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "ÄÚ¸àÆ®¿¡ ¾î¶°ÇÑ ÁÖ¼Òµµ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "¸í·ÉÀÌ ÁöÁ¤µÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "¸í·É¿¡ ÇÏ³ªÀÇ ÁÖ¼Ò¸¸ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "ÁÖ¼Ò Á¤±ÔÇ¥Çö½Ä Á¾·áµÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "`s' ¸í·ÉÀÌ Á¾·áµÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "`y' ¸í·ÉÀÌ Á¾·áµÇÁö ¾Ê¾Ò½À´Ï´Ù"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "`s' ¿¡ ¾Ë ¼ö ¾ø´Â ¿É¼ÇÀÌ ÀÖ½À´Ï´Ù"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "`s' ¸í·É¿¡ `p' ¿É¼ÇÀÌ Áßº¹µÇ¾î ÀÖ½À´Ï´Ù"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "`s' ¸í·É¿¡ `g' ¿É¼ÇÀÌ Áßº¹µÇ¾î ÀÖ½À´Ï´Ù"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "`s' ¸í·É¿¡ ¼ýÀÚ ¿É¼ÇÀÌ Áßº¹µÇ¾î ÀÖ½À´Ï´Ù"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "`s' ¸í·ÉÀÇ ¼ýÀÚ ¿É¼Ç¿¡ '0' À» ÁöÁ¤ÇÒ ¼ö ¾ø½À´Ï´Ù"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "`y' ¸í·ÉÀÇ ¹®ÀÚ¿­ÀÌ ±æÀÌ°¡ ´Ù¸¨´Ï´Ù"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "ÁÖ¼Ò º¯°æÀÚ(modifier)ÀÇ »ç¿ëÀÌ ¿Ã¹Ù¸£Áö ¾Ê½À´Ï´Ù"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "¾Ë ¼ö ¾ø´Â ¸í·É:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: %s ÆÄÀÏÀÇ %lu ¹øÂ° ÁÙ: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e expression #%lu, char %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "`%s' (À¸)·Î Á¡ÇÁÇÒ ·¹ÀÌºíÀ» Ã£À» ¼ö ¾ø½À´Ï´Ù"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: %s (À»)¸¦ ÀÐÀ» ¼ö ¾øÀ½: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr ""
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr ""
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr ""
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr ""
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr ""
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr ""
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"¹ö±×¸¦ º¸°íÇÒ E-mail ÁÖ¼Ò: %s .\n"
+"``Subject:'' Ç×¸ñ¿¡ ¹Ýµå½Ã ``%s'' ´Ü¾î¸¦ Æ÷ÇÔÇØ ÁÖ½Ã±â ¹Ù¶ø´Ï´Ù.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"ÀÌ ÇÁ·Î±×·¥Àº ÀÚÀ¯ ¼ÒÇÁÆ®¿þ¾î ÀÔ´Ï´Ù; ÀÚ¼¼ÇÑ ³»¿ëÀº ÀúÀÛ±Ç ³»¿ëÀÇ ¿ø¹®À»\n"
+"Âü°íÇÏ½Ã±â ¹Ù¶ø´Ï´Ù.  ÀÌ ÇÁ·Î±×·¥Àº ¹ý¿¡ ÀúÃËµÇÁö ¾Ê´Â ¹üÀ§¿¡¼­ »ó¾÷ÀûÀÌ³ª\n"
+"Æ¯¼ö ¸ñÀûÀ¸·Î »ç¿ëµÉ °æ¿ì¸¦ Æ÷ÇÔÇÑ ¾î¶°ÇÑ °æ¿ì¿¡µµ º¸ÁõÇÏÁö ¾Ê½À´Ï´Ù.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: %s (À»)¸¦ ÀÐÀ» ¼ö ¾øÀ½: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù"
+
+#: lib/utils.c:220
+#, fuzzy, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "%2$s ¿¡ %1$d Ç×¸ñ(item)À» ±â·ÏÇÒ ¼ö ¾ø½À´Ï´Ù: %3$s"
+msgstr[1] "%2$s ¿¡ %1$d Ç×¸ñ(item)À» ±â·ÏÇÒ ¼ö ¾ø½À´Ï´Ù: %3$s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "%s ÀÇ ³»¿ë ÀÐ±â ¿À·ù: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: %s (À»)¸¦ ÀÐÀ» ¼ö ¾øÀ½: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr ""
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr ""
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr ""
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr ""
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr ""
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr ""
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr ""
+
+#: lib/regcomp.c:153
+#, fuzzy
+msgid "Unmatched [ or [^"
+msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: lib/regcomp.c:156
+#, fuzzy
+msgid "Unmatched ( or \\("
+msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: lib/regcomp.c:159
+#, fuzzy
+msgid "Unmatched \\{"
+msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr ""
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr ""
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr ""
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr ""
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr ""
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr ""
+
+#: lib/regcomp.c:180
+#, fuzzy
+msgid "Unmatched ) or \\)"
+msgstr "`{' °¡ ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr ""
Index: /tags/kBuild-0.1.4/src/sed/po/nl.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/nl.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/nl.po	(revision 1780)
@@ -0,0 +1,541 @@
+# Dutch translation of sed.
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sed package.
+# Taco Witte <tcwitte@cs.uu.nl>, 2004, 2005.
+# 
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2005-04-12 20:09+0200\n"
+"Last-Translator: Taco Witte <tcwitte@cs.uu.nl>\n"
+"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "meerdere `!'s"
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "onverwachte `,'"
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "ongeldig gebruik van +N of ~N als eerste adres"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "ongepaarde `{'"
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "onverwachte `}'"
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "extra tekens na opdracht"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "verwachtte \\ na `a', `c' of `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' wil geen adressen"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": wil geen adressen"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "opmerkingen accepteren geen adres"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "ontbrekende opdracht"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "opdracht gebruikt slechts één adres"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "onafgemaakte reguliere expressie voor adres"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "onafgemaakte `s'-opdracht"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "onafgemaakte `y'-opdracht"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "onbekende optie voor `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "meerdere `p'-opties voor `s'-opdracht"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "meerdere `g'-opties voor `s'-opdracht"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "meerdere getalopties voor `s'-opdracht"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "getaloptie voor `s'-opdracht mag niet nul zijn"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "tekenreeksen voor `y'-opdracht zijn van verschillende lengte"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "scheidingsteken is geen enkel-byte-teken"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "verwachtte een nieuwere versie van sed"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "ongeldig gebruik van regel-adres 0"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "onbekende opdracht: `%c'"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: bestand %s regel %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e expressie #%lu, teken %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "kan label voor sprong naar `%s' niet vinden"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: kan %s niet lezen: %s\n"
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "kon %s niet bewerken: is een terminal"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "kon %s niet bewerken: geen gewoon bestand"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "kon tijdelijk bestand %s niet openen: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "fout in deelproces"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "optie `e' wordt niet ondersteund"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "`e'-opdracht wordt niet ondersteund"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "geen eerdere reguliere expressie"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "kan geen veranderaars opgeven bij een lege reguliere expressie"
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "ongeldige verwijzing \\%d op rechterhandzijde van `s'-opdracht"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 de syntaxis van Perl 5 voor reguliere expressie gebruiken "
+"in het script.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"Gebruik: %s [OPTIE]... {script-alleen-als-geen-ander-script} "
+"[invoerbestand]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, fuzzy, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"-n, --quiet, --silent\n"
+"                 automatische weergave van patroonruimte onderdrukken\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e script, --expression=SCRIPT\n"
+"                 het SCRIPT toevoegen aan uit te voeren opdrachten\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f script-file, --file=SCRIPTBESTAND\n"
+"                 de inhoud van SCRIPTBESTAND toevoegen aan uit te voeren "
+"opdrachten\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[ACHTERVOEGSEL], --in-place[=ACHTERVOEGSEL]\n"
+"                 bestanden ter plekke bewerken (maakt reservekopie als "
+"extensie gegeven)\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l AANTAL, --line-length=AANTAL\n"
+"                 gewenste regelafbreeklengte opgeven voor `l'-opdracht\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 alle GNU-uitbreidingen uit zetten.\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 uitgebreide reguliere expressies gebruiken in het script.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 bestanden als losstaand beschouwen i.p.v. als enkele "
+"continue stroom.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 minimale hoeveelheid gegevens laden uit invoerbestanden en\n"
+"                 uitvoerbuffers vaker leegmaken\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     deze hulp weergeven en afsluiten\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  versie-informatie weergeven en afsluiten\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"Als geen -e, --expression, -f of --file optie gegeven is, wordt het\n"
+"eerste niet-optie argument genomen als het te interpreteren sed-script.\n"
+"Alle overblijvende argumenten zijn namen van invoerbestanden; als geen\n"
+"invoerbestanden opgegeven zijn, wordt standaardinvoer gelezen.\n"
+"\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Stuur foutrapporten naar: %s .\n"
+"Zorg ervoor dat het woord ``%s'' ergens in het ``Onderwerp:''-veld staat.\n"
+"Rapporteer fouten in de vertalingen bij <vertaling@vrijschrift.org>.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versie %s\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"gebaseerd op GNU sed versie %s\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versie %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Dit is vrije software; zie de bron voor kopieervoorwaarden.  Er is GEEN\n"
+"garantie; zelfs niet voor VERHANDELBAARHEID of GESCHIKTHEID VOOR\n"
+"EEN BEPAALD DOEL, tot het uiterste dat door de wet wordt toegestaan.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "kan %s niet verwijderen: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "kon bestand %s niet openen: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "kon niet %d item naar %s schrijven: %s"
+msgstr[1] "kon niet %d items naar %s schrijven: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "leesfout op %s: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "kon %s niet hernoemen: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Gelukt"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Geen overeenkomst"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Ongeldige reguliere expressie"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Ongeldig sorteerteken"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Ongeldige tekenklassenaam"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Backslash aan het einde"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Ongeldige terugverwijzing"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Ongepaarde [ of [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Ongepaarde ( of \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Ongepaarde \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Ongeldige inhoud van \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Ongeldig bereikeinde"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Onvoldoende geheugen"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Ongeldige voorafgaande reguliere expressie"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Voortijdig einde van reguliere expressie"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Reguliere expressie is te groot"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Ongepaarde ) of \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Geen eerdere reguliere expressie"
+
+#~ msgid "Called savchar() with unexpected pushback (%x)"
+#~ msgstr "savchar() aangeroepen met onverwachte pushback (%x)"
+
+#~ msgid "INTERNAL ERROR: bad address type"
+#~ msgstr "INTERNE FOUT: slechte adressoort"
+
+#~ msgid "INTERNAL ERROR: Bad cmd %c"
+#~ msgstr "INTERNE FOUT: Slechte opdracht %c"
+
+#~ msgid ""
+#~ "Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+#~ "\n"
+#~ "  -n, --quiet, --silent\n"
+#~ "                 suppress automatic printing of pattern space\n"
+#~ "  -e script, --expression=script\n"
+#~ "                 add the script to the commands to be executed\n"
+#~ "  -f script-file, --file=script-file\n"
+#~ "                 add the contents of script-file to the commands to be "
+#~ "executed\n"
+#~ "  -i[suffix], --in-place[=suffix]\n"
+#~ "                 edit files in place (makes backup if extension "
+#~ "supplied)\n"
+#~ "  -l N, --line-length=N\n"
+#~ "                 specify the desired line-wrap length for the `l' "
+#~ "command\n"
+#~ "  -r, --regexp-extended\n"
+#~ "                 use extended regular expressions in the script.\n"
+#~ "%s  -s, --separate\n"
+#~ "                 consider files as separate rather than as a single "
+#~ "continuous\n"
+#~ "                 long stream.\n"
+#~ "  -u, --unbuffered\n"
+#~ "                 load minimal amounts of data from the input files and "
+#~ "flush\n"
+#~ "                 the output buffers more often\n"
+#~ "      --help     display this help and exit\n"
+#~ "  -V, --version  output version information and exit\n"
+#~ "\n"
+#~ "If no -e, --expression, -f, or --file option is given, then the first\n"
+#~ "non-option argument is taken as the sed script to interpret.  All\n"
+#~ "remaining arguments are names of input files; if no input files are\n"
+#~ "specified, then the standard input is read.\n"
+#~ "\n"
+#~ msgstr ""
+#~ "Gebruik: %s [OPTIE]... {script-alleen-als-geen-ander-script} "
+#~ "[invoerbestand]...\n"
+#~ "\n"
+#~ "  -n, --quiet, --silent\n"
+#~ "                 automatische weergave van patroonruimte onderdrukken\n"
+#~ "  -e script, --expression=script\n"
+#~ "                 het script toevoegen aan de uit te voeren opdrachten\n"
+#~ "  -f scriptbestand, --file=scriptbestand\n"
+#~ "                 de inhoud van scriptbestand toevoegen aan de uit te "
+#~ "voeren opdrachten\n"
+#~ "  -i[achtervoegsel], --in-place[=achtervoegsel]\n"
+#~ "                 bestanden ter plekke bewerken (maakt reservekopie als "
+#~ "achtervoegsel is opgegeven)\n"
+#~ "  -l N, --line-length=N\n"
+#~ "                 de gewenste afkaplengte voor regels opgeven voor de `l'-"
+#~ "opdracht\n"
+#~ "  -r, --regexp-extended\n"
+#~ "                 uitgebreide reguliere uitdrukkingen gebruiken in het "
+#~ "script.\n"
+#~ "%s  -s, --separate\n"
+#~ "                 bestanden afzonderlijk beschouwen in plaats van als één "
+#~ "continue, lange stroom.\n"
+#~ "  -u, --unbuffered\n"
+#~ "                 minimale hoeveelheden gegevens van invoerbestanden laden "
+#~ "en vaker de uitvoerbuffers legen\n"
+#~ "      --help     deze hulp weergeven en afsluiten\n"
+#~ "  -V, --version  versie-informatie weergeven en afsluiten\n"
+#~ "\n"
+#~ "Als geen -e, --expression, -f of --file optie gegeven is, wordt het "
+#~ "eerste niet-optie\n"
+#~ "argument gebruikt als sed script om te interpreteren.  Alle overblijvende "
+#~ "argumenten\n"
+#~ "zijn namen van invoerbestanden; als geen invoerbestanden zijn opgegeven, "
+#~ "wordt gelezen\n"
+#~ "vanaf standaard invoer.\n"
+#~ "\n"
Index: /tags/kBuild-0.1.4/src/sed/po/pl.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/pl.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/pl.po	(revision 1780)
@@ -0,0 +1,462 @@
+# Polish translations for GNU sed package.
+# Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+# Wojciech Polak <polak@gnu.org>, 2003, 2004.
+# corrections: Jakub Bogusz <qboosh@pld-linux.org>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-07-08 19:58+0200\n"
+"Last-Translator: Wojciech Polak <polak@gnu.org>\n"
+"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "wielokrotny znak `!'"
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "nieoczekiwany znak `,'"
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "nieprawid³owe u¿ycie +N lub ~N jako pierwszego adresu"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "niedopasowany znak `{'"
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "nieoczekiwany znak `}'"
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "dodatkowe znaki po poleceniu"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "oczekiwano znaku \\ po `a', `c' lub `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' nie chce ¿adnych adresów"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": nie chce ¿adnych adresów"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "komentarze nie akceptuj± ¿adnych adresów"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "brakuje polecenia"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "polecenie u¿ywa tylko jednego adresu"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "niezakoñczony adres wyra¿enia regularnego"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "niezakoñczone polecenie `s'"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "niezakoñczone polecenie `y'"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "nieznana opcja dla polecenia `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "wielokrotne opcje `p' dla polecenia `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "wielokrotne opcje `g' dla polecenia `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "wielokrotne opcje liczbowe dla polecenia `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "opcja liczbowa dla polecenia `s' nie mo¿e byæ zerem"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "³añcuchy dla polecenia `y' s± ró¿nych d³ugo¶ci"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "znak ogranicznika nie jest pojedynczym znakiem-bajtem"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "oczekiwano nowszej wersji programu sed"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "nieprawid³owe u¿ycie adresu linii 0"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "nieznane polecenie: `%c'"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: plik %s linia %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e wyra¿enie #%lu, znak %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "nie mo¿na znale¼æ etykiety dla skoku do `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: nie mo¿na odczytaæ %s: %s\n"
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "nie mo¿na edytowaæ %s: plik jest terminalem"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "nie mo¿na edytowaæ %s: to nie jest regularny plik"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "nie mo¿na otworzyæ tymczasowego pliku %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "b³±d w podprocesie"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "opcja `e' nie jest wspierana"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "polecenie `e' nie jest wspierane"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "brak poprzedniego wyra¿enia regularnego"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "nie mo¿na wyszczególniæ modyfikatorów w pustym wyra¿eniu regularnym"
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "nieprawid³owe odwo³anie \\%d po prawej stronie polecenia `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 u¿ywa w skrypcie wyra¿enia regularne zgodne ze sk³adni± "
+"Perl 5.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"U¿ycie: %s [OPCJE] {skrypt-tylko-wtedy-gdy-¿aden-inny-skrypt} [plik-"
+"wej¶ciowy]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"  -n, --quiet, --silent\n"
+"                 powstrzymuje automatyczne drukowanie przetwarzanych linii.\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e skrypt, --expression=skrypt\n"
+"                 dodaje skrypt do poleceñ, które maj± byæ wykonane.\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f plik-skryptowy, --file=plik-skryptowy\n"
+"                 dodaje zawarto¶æ pliku skryptowego do poleceñ,\n"
+"                 które maj± byæ wykonane.\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[rozszerzenie], --in-place[=rozszerzenie]\n"
+"                 edytuje pliki \"w miejscu\" (tworzy kopie zapasowe\n"
+"                 je¿eli zosta³o podane rozszerzenie).\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                 ustala po¿±dan± d³ugo¶æ ³amanych linii dla polecenia `l'.\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"      --posix\n"
+"                 wy³±cza wszystkie rozszerzenia GNU.\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 u¿ywa w skrypcie rozszerzonych wyra¿eñ regularnych.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 traktuje pliki jako oddzielne, a nie jako pojedynczy,\n"
+"                 d³ugi i ci±g³y strumieñ.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 ³aduje minimaln± ilo¶æ danych z plików wej¶ciowych\n"
+"                 i czê¶ciej oczyszcza bufor wyj¶ciowy.\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     wy¶wietla tê oto pomoc i koñczy pracê.\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  wy¶wietla numer wersji i koñczy pracê.\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"Je¿eli nie zostan± podane opcje -e, --expression, -f, lub --file,\n"
+"to wtedy pierwszy argument, który nie jest opcj± linii poleceñ sed,\n"
+"zostanie wziêty jako skrypt sed do przetworzenia. Wszystkie pozosta³e\n"
+"argumenty s± nazwami plików wej¶ciowych; je¿eli nie zostan± podane\n"
+"¿adne pliki wej¶ciowe, to wtedy odczytane zostanie standardowe wej¶cie.\n"
+"\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Ewentualne b³êdy prosimy zg³aszaæ na adres: %s\n"
+"W tym celu proszê dodaæ s³owo ``%s'' do tematu listu.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed wersja %s\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"na podstawie wersji GNU sed %s\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed wersja %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Niniejszy program jest wolnym oprogramowaniem; warunki kopiowania s± "
+"opisane\n"
+"w ¼ród³ach. Autorzy nie daj± ¯ADNYCH gwarancji, w tym równie¿ gwarancji\n"
+"PRZYDATNO¦CI DO SPRZEDA¯Y LUB DO KONKRETNYCH CELÓW.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "nie mo¿na usun±æ %s: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "nie mo¿na otworzyæ pliku %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "nie mo¿na zapisaæ %d elementu do %s: %s"
+msgstr[1] "nie mo¿na zapisaæ %d elementów do %s: %s"
+msgstr[2] "nie mo¿na zapisaæ %d elementów do %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "b³±d odczytu w %s: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "nie mo¿na zmieniæ nazwy %s: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Sukces"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Brak dopasowania"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Nieprawid³owe wyra¿enie regularne"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Nieprawid³owy znak porównania"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nieprawid³owa nazwa klasy znaku"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Koñcowy znak backslash"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Nieprawid³owe odwo³anie wsteczne"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Niedopasowany znak [ lub [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Niedopasowany znak ( lub \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Niedopasowany znak \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Nieprawid³owa zawarto¶æ \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Nieprawid³owy koniec zakresu"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Pamiêæ wyczerpana"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Nieprawid³owe poprzedzaj±ce wyra¿enie regularne"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Przedwczesny koniec wyra¿enia regularnego"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Wyra¿enie regularne jest zbyt du¿e"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Niedopasowany znak ) lub \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Brak poprzedniego wyra¿enia regularnego"
Index: /tags/kBuild-0.1.4/src/sed/po/pt_BR.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/pt_BR.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/pt_BR.po	(revision 1780)
@@ -0,0 +1,448 @@
+# traduções para o português do Brasil das mensagens de erro do sed
+# Copyright (C) 1999 Free Software Foundation, Inc.
+#   Aurélio Marinho Jargas <aurelio@conectiva.com.br>, 1999, 2002.
+#
+# Tradução original da versão 4.01:
+#   Juan Carlos Castro y Castro <jcastro@vialink.com.br>, 2002.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2002-11-08 17:44-0300\n"
+"Last-Translator: Aurélio Marinho Jargas <aurelio@verde666.org>\n"
+"Language-Team: Brazilian Portuguese <ldp-br@bazar.conectiva.com.br>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Exclamações `!' múltiplas"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Vírgula `,' inesperada"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Não use +N ou ~N como o primeiro endereço"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "`{' não terminada"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "`}' inesperada"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Há caracteres sobrando após o comando"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Deve haver um escape \\ depois dos comandos `a', `c' e `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' não recebe endereços"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr "`:' não recebe endereços"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Comentários não aceitam endereços"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Falta especificar um comando ao endereço"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Este comando usa apenas um endereço"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "A expressão regular do endereço está inacabada (falta a /)"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Comando `s' inacabado (s/// - faltou delimitador)"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Comando `y' inacabado (y/// - faltou delimitador)"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Opção desconhecida para o comando `s' (s///?)"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "opções `p' múltiplas para o comando `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "opções `g' múltiplas para o comando `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "opções numéricas múltiplas para o comando `s' (s///n)"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "A opção numérica para o comando `s' não pode ser zero (s///0)"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "Os textos para o comando `y' têm tamanhos diferentes (y/abc/z/)"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Uso incorreto do modificador de endereço"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Comando desconhecido:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: arquivo %s linha %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e expressão #%lu, caractere %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Não foi possível encontrar a marcação `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: não foi possível ler %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Não foi possível abrir o arquivo %s: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Não foi possível abrir o arquivo %s: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Não foi possível abrir o arquivo %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "erro no subprocesso"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "opção `e' não suportada"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "comando `e' não suportado"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Não há expressão regular anterior"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Não é permitido especificar modificadores numa expressão regular vazia"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Referência inválida \\%d na segunda parte do comando `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 usar sintaxe de expressões regulares do Perl 5 no script.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 usar sintaxe de expressões regulares do Perl 5 no script.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Envie relatórios de erros (em inglês) para: %s .\n"
+"Inclua a palavra ``%s'' no campo ``Assunto:'' ou ``Subject:''.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed versão %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"baseado no GNU sed versão 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versão %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Este programa é Software Livre. Veja os fontes para conhecer as condições\n"
+"de cópia.  NÃO há garantias, nem mesmo para os aspectos mercantis ou de\n"
+"atendimento a finalidades específicas, tanto quanto a lei permita.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: não foi possível ler %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Não foi possível abrir o arquivo %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "não foi possível escrever %d item para %s: %s"
+msgstr[1] "não foi possível escrever %d items para %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "erro de leitura em %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: não foi possível ler %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Sucesso"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Nada encontrado"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Expressão regular inválida"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Caractere de ordenação inválido"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nome inválido de classe de caracteres"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Escape \\ no final"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Retrovisor \\n inválido"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[ ou [^ não terminado"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "( ou \\( não terminado"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{ não terminado"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Conteúdo inválido no \\{\\} (permitidos números e vírgula)"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Fim de intervalo (range) inválido"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Falta de memória"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Expressão regular anterior inválida"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Fim prematuro da expressão regular"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Expressão regular grande demais"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ") or \\) inesperado"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Não há expressão regular anterior"
Index: /tags/kBuild-0.1.4/src/sed/po/quot.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/quot.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/quot.sed	(revision 1780)
@@ -0,0 +1,6 @@
+s/"\([^"]*\)"/“\1”/g
+s/`\([^`']*\)'/‘\1’/g
+s/ '\([^`']*\)' / ‘\1’ /g
+s/ '\([^`']*\)'$/ ‘\1’/g
+s/^'\([^`']*\)' /‘\1’ /g
+s/“”/""/g
Index: /tags/kBuild-0.1.4/src/sed/po/ro.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/ro.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/ro.po	(revision 1780)
@@ -0,0 +1,450 @@
+# Mesajele în limba românã pentru sed.
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# Acest fiºier este distribuit sub aceeaºi licenþã ca ºi pachetul sed.
+# Laurentiu Buzdugan <buzdugan@voyager.net>, 2003.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.8\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-11-22 12:00-0500\n"
+"Last-Translator: Laurentiu Buzdugan <buzdugan@voyager.net>\n"
+"Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "`!'-uri multiple"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "`,' neaºteptat"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Nu se poate folosi +N ºi ~N ca prima adresã"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "`{' fãrã pereche"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "`}' neaºteptat"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Extra caractere dupã comandã"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Este aºteptat \\ dupã `a', `c' sau `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' nu vrea nici o adresã"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": nu vrea nici o adresã"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Comentariile nu acceptã nici o adresã"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Comandã absentã"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Comanda foloseºte numai o adresã"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Adresã regex neterminatã"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Comandã `s' neterminatã"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Comandã `y' neterminatã"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Opþiune necunoscutã pentru `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "multiple opþiuni `p' pentru comanda `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "multiple opþiuni `g' pentru comanda `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "numãr multiplu de opþiuni pentru comanda `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "numãrul de opþiuni pentru comanda `s' nu poate fi zero"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "ºirurile pentru comanda y au lungimi diferite"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "am aºteptat o versiune mai recentã de sed"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Comanda foloseºte numai o adresã"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Comandã necunoscutã:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: fiºierul %s linia %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e expresia #%lu, caracterul %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Nu pot gãsi eticheta pentru saltul la `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: nu pot citi %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Nu am putut deschide fiºierul %s: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Nu am putut deschide fiºierul %s: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Nu am putut deschide fiºierul temporar %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "eroare în subproces"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "opþiunea `e' nu e suportatã"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "comanda `e' nu e suportatã"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Nici o expresie regularã anterioarã"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Nu se pot specifica modificatori pentru regexp vidã"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Referinþã invalidã \\%d pentru RHS-ul comanzii `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                foloseºte sintaxa expresiilor regulare din Perl 5 în "
+"script.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                foloseºte sintaxa expresiilor regulare din Perl 5 în "
+"script.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Raportaþi bug-uri prin e-mail la: %s .\n"
+"Fiþi siguri cã includeþi ``%s'' undeva în câmpul ``Subject:''.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "versiunea super-sed %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"bazat pe GNU sed versiunea 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed versiunea %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Acesta este software liber; vedeþi codul sursã pentru condiþiile de "
+"copiere.\n"
+"Nu existã NICI o garanþie; nici mãcar pentru VANDABILITATE sau POTRIVIRE \n"
+"PENTRU UN ANUME SCOP, conform legilor în vigoare.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: nu pot citi %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Nu am putut deschide fiºierul %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "Nu am putut scrie %d articol în %s: %s"
+msgstr[1] "Nu am putut scrie %d articole în %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "eroare citire pentru %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: nu pot citi %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Succes"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Nici o potrivire"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Expresie regularã incorectã"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Colaþiune de caractere incorectã"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Nume de clasã de caractere incorect"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Backslash în coadã"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Referinþã înapoi incorectã"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "[ sau [^ fãrã pereche"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "( sau \\( fãrã pereche"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "\\{ fãrã pereche"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Conþinut incorect pentru \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Sfârºit de interval incorect"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Memorie epuizatã"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Expresie regularã precedentã incorectã"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Sfârºit prematur al expresiei regulare"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Expresie regularã prea mare"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ") sau \\) fãrã pereche"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Nici o expresie regularã anterioarã"
Index: /tags/kBuild-0.1.4/src/sed/po/ru.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/ru.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/ru.po	(revision 1780)
@@ -0,0 +1,459 @@
+# Translation of sed-4.1.1.po to Russian
+# Copyright (C) 1998, 2004 Free Software Foundation, Inc.
+# Const Kaplinsky <const@ce.cctpu.edu.ru>, 1998.
+# Pavel Maryanov <acid_jack@ukr.net>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed-4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-07-07 17:54+0300\n"
+"Last-Translator: Pavel Maryanov <acid_jack@ukr.net>\n"
+"Language-Team: Russian <ru@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=KOI8-R\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n>1;\n"
+"X-Generator: KBabel 1.3\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "ÎÅÓËÏÌØËÏ ÓÉÍ×ÏÌÏ× `!'"
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "ÎÅÐÒÅÄ×ÉÄÅÎÎÙÊ ÓÉÍ×ÏÌ `,'"
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "ÉÓÐÏÌØÚÏ×ÁÎÉÅ +N ÉÌÉ ~N × ËÁÞÅÓÔ×Å ÐÅÒ×ÏÇÏ ÁÄÒÅÓÁ ÎÅÄÏÐÕÓÔÉÍÏ"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "ÎÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ `{'"
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "ÎÅÐÒÅÄ×ÉÄÅÎÎÙÊ ÓÉÍ×ÏÌ `}'"
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "ÌÉÛÎÉÅ ÓÉÍ×ÏÌÙ ÐÏÓÌÅ ËÏÍÁÎÄÙ"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "ÏÖÉÄÁÌÁÓØ \\ ÐÏÓÌÅ `a', `c' ÉÌÉ `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' ÎÅ ÄÏÐÕÓËÁÅÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr "`:' ÎÅ ÄÏÐÕÓËÁÅÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "ËÏÍÍÅÎÔÁÒÉÉ ÎÅ ÄÏÐÕÓËÁÀÔ ÕËÁÚÁÎÉÑ ËÁËÉÈ-ÌÉÂÏ ÁÄÒÅÓÏ×"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "ÏÔÓÕÔÓÔ×ÕÅÔ ËÏÍÁÎÄÁ"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "ËÏÍÁÎÄÁ ÉÓÐÏÌØÚÕÅÔ ÔÏÌØËÏ ÏÄÉÎ ÁÄÒÅÓ"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "ÎÅÚÁ×ÅÒÛÅÎÎÏÅ ÁÄÒÅÓÎÏÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "ÎÅÚÁ×ÅÒÛÅÎÎÁÑ ËÏÍÁÎÄÁ `s'"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "ÎÅÚÁ×ÅÒÛÅÎÎÁÑ ËÏÍÁÎÄÁ `y'"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "ÎÅÉÚ×ÅÓÔÎÙÊ ÍÏÄÉÆÉËÁÔÏÒ Ë `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "ÎÅÓËÏÌØËÏ ÍÏÄÉÆÉËÁÔÏÒÏ× `p' Ó ËÏÍÁÎÄÏÊ `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "ÎÅÓËÏÌØËÏ ÍÏÄÉÆÉËÁÔÏÒÏ× `g' Ó ËÏÍÁÎÄÏÊ `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "ÎÅÓËÏÌØËÏ ÞÉÓÌÏ×ÙÈ ÍÏÄÉÆÉËÁÔÏÒÏ× Ó ËÏÍÁÎÄÏÊ `s'"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "ÞÉÓÌÏ×ÏÊ ÍÏÄÉÆÉËÁÔÏÒ ÄÌÑ ËÏÍÁÎÄÙ `s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÎÕÌÅ×ÙÍ"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "ÓÔÒÏËÉ ÄÌÑ ËÏÍÁÎÄÙ `y' ÉÍÅÀÔ ÒÁÚÎÕÀ ÄÌÉÎÕ"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "ÓÉÍ×ÏÌ-ÒÁÚÄÅÌÉÔÅÌØ ÎÅ Ñ×ÌÑÅÔÓÑ ÏÄÎÏÂÁÊÔÏ×ÙÍ ÓÉÍ×ÏÌÏÍ"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "ÏÖÉÄÁÌÁÓØ ÂÏÌÅÅ ÎÏ×ÁÑ ×ÅÒÓÉÑ sed"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "ÎÅÄÏÐÕÓÔÉÍÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÓÔÒÏËÉ ÁÄÒÅÓÁ 0"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "ÎÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ: `%c'"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: ÆÁÊÌ %s ÓÔÒÏËÁ %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e ×ÙÒÁÖÅÎÉÅ #%lu, ÓÉÍ×ÏÌ %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÍÅÔËÕ ÄÌÑ ÐÅÒÅÈÏÄÁ Ë `%s'"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ %s: %s\n"
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÒÅÄÁËÔÉÒÏ×ÁÔØ %s: ÜÔÏ ÔÅÒÍÉÎÁÌ"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÒÅÄÁËÔÉÒÏ×ÁÔØ %s: ÜÔÏ ÎÅ ÏÂÙÞÎÙÊ ÆÁÊÌ"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ×ÒÅÍÅÎÎÙÊ ÆÁÊÌ %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "ÏÛÉÂËÁ × ÐÏÄÐÒÏÃÅÓÓÅ"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "ÏÐÃÉÑ `e' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "ËÏÍÁÎÄÁ `e' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "ÎÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÕËÁÚÁÔØ ÍÏÄÉÆÉËÁÔÏÒÙ × ÐÕÓÔÏÍ ÒÅÇÕÌÑÒÎÏÍ ×ÙÒÁÖÅÎÉÉ"
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "ÎÅÄÏÐÕÓÔÉÍÁÑ ÓÓÙÌËÁ \\%d ÎÁ RHS ËÏÍÁÎÄÙ `s'"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 ÉÓÐÏÌØÚÏ×ÁÎÉÅ × ÓËÒÉÐÔÅ ÓÉÎÔÁËÓÉÓÁ ÒÅÇÕÌÑÒÎÙÈ ×ÙÒÁÖÅÎÉÊ "
+"Perl 5.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"éÓÐÏÌØÚÏ×ÁÎÉÅ: %s [ïðãéñ]... {ÔÏÌØËÏ-ÓËÒÉÐÔ-ÅÓÌÉ-ÎÅÔ-ÄÒÕÇÏÇÏ-ÓËÒÉÐÔÁ} "
+"[×ÈÏÄÎÏÊ-ÆÁÊÌ]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"  -n, --quiet, --silent\n"
+"                 ÐÏÄÁ×ÌÅÎÉÅ Á×ÔÏÍÁÔÉÞÅÓËÏÇÏ ×Ù×ÏÄÁ ÐÒÏÍÅÖÕÔËÏ×\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e script, --expression=script\n"
+"                 ÄÏÂÁ×ÌÅÎÉÅ ÓËÒÉÐÔÁ × ÉÓÐÏÌÎÑÅÍÙÅ ËÏÍÁÎÄÙ\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f script-file, --file=script-file\n"
+"                 ÄÏÂÁ×ÌÅÎÉÅ ÓÏÄÅÒÖÉÍÏÇÏ ÆÁÊÌÁ-ÓËÒÉÐÔÁ × ÉÓÐÏÌÎÑÅÍÙÅ ËÏÍÁÎÄÙ\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[óõææéëó], --in-place[=óõææéëó]\n"
+"                 ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ ÆÁÊÌÏ× ÎÁ ÍÅÓÔÅ (ÓÏÚÄÁÅÔ ËÏÐÉÀ, ÅÓÌÉ ÕËÁÚÁÎÏ "
+"ÒÁÓÛÉÒÅÎÉÅ)\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                 ÕËÁÚÁÎÉÅ ÖÅÌÁÅÍÏÊ ÄÌÉÎÙ ÐÅÒÅÎÏÓÉÍÏÊ ÓÔÒÏËÉ ÄÌÑ ËÏÍÁÎÄÙ `l'\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 ÏÔËÌÀÞÅÎÉÅ ×ÓÅÈ ÒÁÓÛÉÒÅÎÉÊ GNU.\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 ÉÓÐÏÌØÚÏ×ÁÎÉÅ × ÓËÒÉÐÔÅ ÒÁÓÛÉÒÅÎÎÙÈ ÒÅÇÕÌÑÒÎÙÈ ×ÙÒÁÖÅÎÉÊ.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 ÄÏÐÕÝÅÎÉÅ, ÞÔÏ ÆÁÊÌÙ ÒÁÚÄÅÌÅÎÙ, Á ÎÅ × ×ÉÄÅ ÏÄÎÏÇÏ\n"
+"                 ÄÌÉÎÎÏÇÏ ÎÅÐÒÅÒÙ×ÎÏÇÏ ÐÏÔÏËÁ.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 ÚÁÇÒÕÚËÁ ÍÉÎÉÍÁÌØÎÏÇÏ ÏÂßÅÍÁ ÄÁÎÎÙÈ ÉÚ ×ÈÏÄÎÙÈ ÆÁÊÌÏ×\n"
+"                 É ÂÏÌÅÅ ÞÁÓÔÙÊ ÓÂÒÏÓ ÎÁ ÄÉÓË ×ÙÈÏÄÎÙÈ ÂÕÆÅÒÏ×\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     ×Ù×ÏÄ ÜÔÏÊ ÓÐÒÁ×ËÉ É ×ÙÈÏÄ\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  ×Ù×ÏÄ ÉÎÆÏÒÍÁÃÉÉ Ï ×ÅÒÓÉÉ É ×ÙÈÏÄ\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"åÓÌÉ ÏÐÃÉÑ -e, --expression, -f, ÉÌÉ --file ÎÅ ÕËÁÚÁÎÁ, ÔÏÇÄÁ ÐÅÒ×ÙÊ\n"
+"ÎÅÏÐÃÉÏÎÁÌØÎÙÊ ÁÒÇÕÍÅÎÔ ÂÅÒÅÔÓÑ ËÁË ÓËÒÉÐÔ sed ÄÌÑ ÉÎÔÅÒÐÒÅÔÁÃÉÉ. ÷ÓÅ\n"
+"ÏÓÔÁ×ÛÉÅÓÑ ÁÒÇÕÍÅÎÔÙ Ñ×ÌÑÀÔÓÑ ÉÍÅÎÁÍÉ ×ÈÏÄÎÙÈ ÆÁÊÌÏ×; ÅÓÌÉ ×ÈÏÄÎÙÅ\n"
+"ÆÁÊÌÙ ÎÅ ÕËÁÚÁÎÙ, ÔÏÇÄÁ ÞÉÔÁÅÔÓÑ ÓÔÁÎÔÁÒÔÎÙÊ ××ÏÄ.\n"
+"\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"ïÔÞÅÔÙ ÏÂ ÏÛÉÂËÁÈ ÏÔÐÒÁ×ÌÑÊÔÅ ÐÏ ÁÄÒÅÓÕ: %s .\n"
+"õÂÅÄÉÔÅÓØ, ÞÔÏ ×ËÌÀÞÉÌÉ ÇÄÅ-ÌÉÂÏ × ÐÏÌÅ ``ôÅÍÁ:'' ÓÌÏ×Ï ``%s''.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed ×ÅÒÓÉÑ %s\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"ÏÓÎÏ×ÁÎ ÎÁ GNU sed ×ÅÒÓÉÉ %s\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed ×ÅÒÓÉÑ %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"üÔÏ Ó×ÏÂÏÄÎÏÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ; ÕÓÌÏ×ÉÑ ÅÇÏ ËÏÐÉÒÏ×ÁÎÉÑ ÓÍÏÔÒÉÔÅ ×\n"
+"ÉÓÈÏÄÎÙÈ ÔÅËÓÔÁÈ. îÅ ÐÒÅÄÏÓÔÁ×ÌÑÅÔÓÑ îéëáëïê ÇÁÒÁÎÔÉÉ; ÄÁÖÅ ÇÁÒÁÎÔÉÉ\n"
+"ðòéçïäîïóôé äìñ ðòïäáöé ÉÌÉ ðòéíåîéíïóôé äìñ ëïîëòåôîïê ãåìé, × ÔÏÊ ÍÅÒÅ,\n"
+"× ËÏÔÏÒÏÊ ÜÔÏ ÍÏÖÅÔ ÂÙÔØ ÄÏÐÕÝÅÎÏ ÚÁËÏÎÏÄÁÔÅÌØÓÔ×ÏÍ.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ %s: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ %d ÜÌÅÍÅÎÔ × %s: %s"
+msgstr[1] "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ %d ÜÌÅÍÅÎÔÏ× × %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "ÏÛÉÂËÁ ÞÔÅÎÉÑ %s: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÉÍÅÎÏ×ÁÔØ %s: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "õÓÐÅÛÎÏ"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "îÅÔ ÓÏÏÔ×ÅÓÔ×ÉÑ"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ ÓÒÁ×ÎÅÎÉÑ"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÉÍÑ ÄÌÑ ËÌÁÓÓÁ ÓÉÍ×ÏÌÁ"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "úÁ×ÅÒÛÁÀÝÁÑ ÏÂÒÁÔÎÁÑ ËÏÓÁÑ ÞÅÒÔÁ"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "îÅÄÏÐÕÓÔÉÍÁÑ ÏÂÒÁÔÎÁÑ ÓÓÙÌËÁ"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ [ ÉÌÉ [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ ( or \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÓÏÄÅÒÖÉÍÏÅ × \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÏËÏÎÞÁÎÉÅ ÄÉÁÐÁÚÏÎÁ"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "ðÁÍÑÔØ ÉÓÞÅÒÐÁÎÁ"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "îÅÄÏÐÕÓÔÉÍÏÅ ÐÒÅÄÛÅÓÔ×ÕÀÝÅÅ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "ðÒÅÖÄÅ×ÒÅÍÅÎÎÏÅ ÏËÏÎÞÁÎÉÅ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "òÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ ÓÌÉÛËÏÍ ÂÏÌØÛÏÅ"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "îÅÐÁÒÎÙÊ ÓÉÍ×ÏÌ ) ÉÌÉ \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "îÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ"
Index: /tags/kBuild-0.1.4/src/sed/po/sed.pot
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/sed.pot	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/sed.pot	(revision 1780)
@@ -0,0 +1,417 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr ""
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr ""
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr ""
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr ""
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr ""
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr ""
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr ""
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr ""
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ""
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr ""
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr ""
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr ""
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr ""
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr ""
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr ""
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr ""
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr ""
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr ""
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr ""
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr ""
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr ""
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr ""
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr ""
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr ""
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr ""
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr ""
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr ""
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr ""
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr ""
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr ""
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr ""
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr ""
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr ""
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr ""
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr ""
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr ""
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr ""
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr ""
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] ""
+msgstr[1] ""
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr ""
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr ""
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr ""
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr ""
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr ""
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr ""
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr ""
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr ""
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr ""
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr ""
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr ""
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr ""
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr ""
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr ""
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr ""
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr ""
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr ""
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr ""
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr ""
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr ""
Index: /tags/kBuild-0.1.4/src/sed/po/sk.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/sk.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/sk.po	(revision 1780)
@@ -0,0 +1,450 @@
+# Slovak translations for GNU sed package.
+# Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+# Marcel Telka <marcel@telka.sk>, 2002, 2003.
+# Miroslav Vasko <vasko@debian.cz>, 1999.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU sed 4.0.8\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-10-25 17:22+0200\n"
+"Last-Translator: Marcel Telka <marcel@telka.sk>\n"
+"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural= (n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Viacnásobný `!'"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Neočakávaná `,'"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "+N alebo ~N sa nedá použiť ako prvá adresa"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Nezodpovedajúca `{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Neočakávaná `}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Nadbytočné znaky po príkaze"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Očakávané \\ po `a', `c' alebo `i'"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "`}' nevyžaduje akúkoľvek adresu"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": nechce akúkoľvek adresu"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "V komentári nie je prípustná akákoľvek adresa"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Chýbajúci príkaz"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Príkaz používa iba jednu adresu"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Neukončený regulárny výraz adresy"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Neukončený príkaz `s'"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Neukončený príkaz `y'"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Neznáma voľba pre `s'"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "viacnásobné použitie voľby `p' s príkazom `s'"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "viacnásobné použitie voľby `g' s príkazom `s'"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "príkaz `s' môže mať maximálne jednu číselnú voľbu"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "číselná voľba príkazu `s' nemôže byť nula"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "reťazce pre príkaz `y' majú rôzne dĺžky"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "očakávaná novšia verzia programu sed"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Príkaz používa iba jednu adresu"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Neznámy príkaz:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: súbor %s, riadok %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e výraz #%lu, znak %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Návestie pre skok na `%s' nie je možné nájsť?"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: %s nie je možné čítať: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Nebolo možné otvoriť súbor %s: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Nebolo možné otvoriť súbor %s: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Nebolo možné otvoriť dočasný súbor %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "chyba v podprocese"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "voľba `e' nie je podporovaná"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "príkaz `e' nie je podporovaný"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Bez predchádzajúceho regulárneho výrazu"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Nie je možné zadať modifikátory pre prázdny regulárny výraz"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Neplatný odkaz \\%d na `s' príkazu RHS"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 použiť syntax regulárnych výrazov z Perlu 5 v skripte.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 použiť syntax regulárnych výrazov z Perlu 5 v skripte.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Správy o chybách zasielajte na adresu %s (iba anglicky).\n"
+"Prosím vložte slovo ``%s'' niekde do položky ``Predmet:''\n"
+"Komentáre k slovenskému prekladu zasielajte na adresu <sk-i18n@lists.linux."
+"sk>.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed verzia %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"založené na GNU sed verzia 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed verzia %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Toto je voľné programové vybavenie; podmienky pre kopírovanie a "
+"rozširovanie\n"
+"nájdete v zdrojových textoch. Toto programové vybavenie je BEZ záruky,\n"
+"a to aj bez záruky PREDAJNOSTI alebo VHODNOSTI PRE NEJAKÝ KONKRÉTNY ÚČEL.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: %s nie je možné čítať: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Nebolo možné otvoriť súbor %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "nebolo možné zapísať %d položiek do %s: %s"
+msgstr[1] "nebolo možné zapísať %d položku do %s: %s"
+msgstr[2] "nebolo možné zapísať %d položky do %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "chyba pri čítaní z %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: %s nie je možné čítať: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Úspech"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Nezodpovedá"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Neplatný regulárny výraz"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Neplatný znak pre porovnávanie"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Neplatný názov triedy znakov"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Ukončovacie opačné lomítko"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Neplatný spätný odkaz"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Nezodpovedajúca [ alebo [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Nezodpovedajúca ( alebo \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Nezodpovedajúca \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Neplatný obsah \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Neplatný koniec rozsahu"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Vyčerpaná pamäť"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Neplatný predchádzajúci regulárny výraz"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Neočakávaný koniec regulárneho výrazu"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Regulárny výraz je príliš veľký"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Nezodpovedajúca ) alebo \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Bez predchádzajúceho regulárneho výrazu"
Index: /tags/kBuild-0.1.4/src/sed/po/sl.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/sl.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/sl.po	(revision 1780)
@@ -0,0 +1,449 @@
+# -*- mode:po; coding:iso-latin-2;-*- Slovenian message catalogue for GNU sed.
+# Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+# Primo¾ Peterlin <primoz.peterlin@biofiz.mf.uni-lj.si>, 2000, 2001, 2002, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2003-04-02 17:20+0200\n"
+"Last-Translator: Primo¾ Peterlin <primoz.peterlin@biofiz.mf.uni-lj.si>\n"
+"Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8-bit\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
+"%100==4 ? 3 : 0);\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Veèterni klicaji \"!\""
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Neprièakovana vejica \",\""
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Obliki +N in ~N nista dovoljeni kot zaèetna naslova"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Oklepaj { brez zaklepaja"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Neprièakovan zaklepaj }"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Ukazu sledijo dodatni znaki"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Za ,a`, ,c` ali ,i` se prièakuje \\"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "Zaklepaj } ne zahteva naslova"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": ne zahteva naslova"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Komentarji ne sprejemajo naslovov"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Ukaz manjka"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Ukaz uporablja le en naslov"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Regularni izraz z nezakljuèenim naslovom"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Nezakljuèen ukaz \"s\""
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Nezakljuèen ukaz \"y\""
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Neznane izbire pri ukazu \"s\""
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "veèterne izbire \"p\" pri ukazu \"s\""
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "veèterne izbire \"g\" pri ukazu \"s\""
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "veèterne ¹tevilène izbire pri ukazu \"s\""
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "¹tevilèna izbira pri ukazu \"s\" mora biti nenièelna"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "niza pri ukazu \"y\" sta razlièno dolga"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "prièakovana novej¹a izdaja programa sed"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Nepravilna uporaba modifikatorja naslova"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Neznan ukaz:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: datoteka %s vrstica %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e izraz #%lu, znak %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Oznake za skok na \"%s\" ni mo¾no najti"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: %s ni mo¾no prebrati: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Datoteke %s ni mogoèe odpreti: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Datoteke %s ni mogoèe odpreti: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Datoteke %s ni mogoèe odpreti: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "Napaka v podprocesu"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "Izbira ,e` ni podprta"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "Ukaz ,e` ni podprt"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Prej¹nji regularni izraz manjka"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Doloèanje modifikatorjev pri praznem regularnem izrazu ni mogoèe"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Neveljavni sklic \\%d na desni strani ukaza ,s`"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 dovoli uporabo regularnih izrazov, ki jih podpira Perl 5\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 dovoli uporabo regularnih izrazov, ki jih podpira Perl 5\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Sporoèila o napakah po¹ljite na %s .\n"
+"Poskrbite, da bo nekje v polju ,,Subject`` nastopal izraz ,,%s``.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed, razlièica %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"na osnovi GNU sed, razlièica 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed, razlièica %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"To je prost program; pogoji, pod katerimi ga lahko uporabljate, "
+"razmno¾ujete\n"
+"in raz¹irjate so navedeni v izvorni kodi. Za program ni NOBENEGA JAMSTVA,\n"
+"niti jamstev USTREZNOSTI ZA PRODAJO ali PRIMERNOSTI ZA UPORABO.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: %s ni mo¾no prebrati: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Datoteke %s ni mogoèe odpreti: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "ni mogoèe zapisati %d elementov na %s: %s"
+msgstr[1] "ni mogoèe zapisati %d elementa na %s: %s"
+msgstr[2] "ni mogoèe zapisati %d elementov na %s: %s"
+msgstr[3] "ni mogoèe zapisati %d elementov na %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "napaka pri branju z %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: %s ni mo¾no prebrati: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Uspe¹no"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Ni ujemanja"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Neveljavni regularni izraz"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Znaka izven abecede"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Neveljavno ime razreda znakov"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Zakljuèna obrnjena po¹evnica"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Neveljavni povratni sklic"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Oklepaj [ ali [^ brez zaklepaja"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Oklepaj ( ali \\( brez zaklepaja"
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Oklepaj \\{ brez zaklepaja"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Neveljavna vsebina \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Neveljavna zgornja meja intervala"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Zmanjkalo pomnilnika"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Neveljaven prej¹nji regularni izraz"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Predèasni zakljuèek regularnega izraza"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Regularni izraz prevelik"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Oklepaj ) ali \\) brez zaklepaja"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Prej¹nji regularni izraz manjka"
Index: /tags/kBuild-0.1.4/src/sed/po/sr.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/sr.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/sr.po	(revision 1780)
@@ -0,0 +1,447 @@
+# Serbian translation of `sed'.
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This file is distributed under the same license as the `sed' package.
+# Aleksandar Jelenak <jelenak@netlinkplus.net>, 2003.
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.9\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-01-13 22:51-0500\n"
+"Last-Translator: Aleksandar Jelenak <jelenak@netlinkplus.net>\n"
+"Language-Team: Serbian <sr@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3;    plural=n%10==1 && n%100!=11 ? 0 :  (n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Више „!“"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Неочекиван „,“"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "Не може се користити +N или ~N као прва адреса"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Неспарена „{“"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Неочекивана „}“"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Вишак знакова после наредбе"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "Очекивано \\ после „a“, „c“ или „i“"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "„}“ не захтева икакве адресе"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": не захтева икакве адресе"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Коментари не прихватају икакве адресе"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Недостаје наредба"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Наредба користи само једну адресу"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Незавршена адреса рег. израза"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Незавршена наредба „s“"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Незавршена наредба „y“"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "Непозната опција за „s“"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "више „p“ опција за „s“ наредбу"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "више „g“ опција за „s“ наредбу"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "више бројчаних опција за „s“ наредбу"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "бројчана опција наредбе „s“ не може бити нула"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "ниске за команду „y“ су различите дужине"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "очекивана новија верзија sed-а"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Наредба користи само једну адресу"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Непозната наредба:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: датотека %s ред %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e израз #%lu, знак %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "Не могу да нађем ознаку за скок на „%s“"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: не може читати  %s: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "Не може се отворити датотека %s: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "Не може се отворити датотека %s: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Не могу отворити привремену датотеку %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "грешка у потпроцесу"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "опција „e“ није подржана"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "наредба „e“ није подржана"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Без претходног регуларног израза"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Не може се навести измењивач празном рег. изразу"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "Неисправна референца \\%d на десној страни наредбе „s“"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 користи у спису синтаксу Перла 5 за регуларне изразе.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 користи у спису синтаксу Перла 5 за регуларне изразе.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Епошта за пријаву грешака: %s .\n"
+"Постарајте се да укључите реч „%s“ негде у „Subject:“ пољу.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed верзија %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"засновано на ГНУ sed верзија 3.02.80\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "ГНУ sed верзија %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Ово је слободан софтвер; видети изворни кôд за услове умножавања. БЕЗ "
+"икакве\n"
+"гаранције; чак ни о ТРЖИШНОСТИ или ИСПУЊАВАЊУ ОДРЕЂЕНЕ ПОТРЕБЕ.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: не може читати  %s: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "Не може се отворити датотека %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "неуспешан запис %d ставке на %s: %s"
+msgstr[1] "неуспешан запис %d ставке на %s: %s"
+msgstr[2] "неуспешан запис %d ставки на %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "грешка учитавања на %s: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: не може читати  %s: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Успех"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Без поклапања"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Неисправни регуларни израз"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Неисправни знак прикупљања"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Неисправно име класе знакова"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Пратећа обрнута коса црта"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Неисправна повратна референца"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Неспарено [ или ^["
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Неспарено ( или \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Неспарено \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Неисправни садржај у \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Неисправни крај опсега"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Меморија исцрпљена"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Неисправан претходећи регуларни израз"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Преран крај регуларног израза"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Регуларни израз сувише велик"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Неспарено ) или \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Без претходног регуларног израза"
Index: /tags/kBuild-0.1.4/src/sed/po/sv.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/sv.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/sv.po	(revision 1780)
@@ -0,0 +1,463 @@
+# Swedish messages for sed.
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+# Christian Rose <menthos@menthos.com>, 1999, 2000, 2001, 2002, 2003, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.1.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-07-11 11:45+0200\n"
+"Last-Translator: Christian Rose <menthos@menthos.com>\n"
+"Language-Team: Swedish <sv@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: sed/compile.c:162
+msgid "multiple `!'s"
+msgstr "flera \"!\""
+
+#: sed/compile.c:163
+msgid "unexpected `,'"
+msgstr "oväntat \",\""
+
+#: sed/compile.c:164
+msgid "invalid usage of +N or ~N as first address"
+msgstr "ogiltig användning av +N eller ~N som första adress"
+
+#: sed/compile.c:165
+msgid "unmatched `{'"
+msgstr "obalanserad \"{\""
+
+#: sed/compile.c:166
+msgid "unexpected `}'"
+msgstr "oväntad \"}\""
+
+#: sed/compile.c:167
+msgid "extra characters after command"
+msgstr "extra tecken efter kommandot"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "\\ förväntades efter \"a\", \"c\" eller \"i\""
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "\"}\" vill inte ha några adresser"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": vill inte ha några adresser"
+
+#: sed/compile.c:171
+msgid "comments don't accept any addresses"
+msgstr "kommentarer accepterar inga adresser"
+
+#: sed/compile.c:172
+msgid "missing command"
+msgstr "kommando saknas"
+
+#: sed/compile.c:173
+msgid "command only uses one address"
+msgstr "kommandot använder endast en adress"
+
+#: sed/compile.c:174
+msgid "unterminated address regex"
+msgstr "oavslutat reguljärt uttryck för adress"
+
+#: sed/compile.c:175
+msgid "unterminated `s' command"
+msgstr "oavslutat \"s\"-kommando"
+
+#: sed/compile.c:176
+msgid "unterminated `y' command"
+msgstr "oavslutat \"y\"-kommando"
+
+#: sed/compile.c:177
+msgid "unknown option to `s'"
+msgstr "flaggan okänd för \"s\""
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "flera \"p\"-flaggor till \"s\"-kommandot"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "flera \"g\"-flaggor till \"s\"-kommandot"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "flera sifferflaggor till \"s\"-kommandot"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "sifferflagga till kommandot \"s\" får inte vara noll"
+
+#: sed/compile.c:182
+msgid "strings for `y' command are different lengths"
+msgstr "strängarna för kommandot \"y\" är olika långa"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr "avgränsningstecknet är inte en ensam byte"
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "nyare version av sed förväntades"
+
+#: sed/compile.c:185
+msgid "invalid usage of line address 0"
+msgstr "felaktig användning av radadress 0"
+
+#: sed/compile.c:186
+#, c-format
+msgid "unknown command: `%c'"
+msgstr "okänt kommando: \"%c\""
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: fil %s rad %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e uttryck #%lu, tecken %lu: %s\n"
+
+#: sed/compile.c:1644
+#, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "kan inte hitta etiketten för hopp till \"%s\""
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: kan inte läsa %s: %s\n"
+
+#: sed/execute.c:673
+#, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "kunde inte redigera %s: är en terminal"
+
+#: sed/execute.c:677
+#, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "kunde inte redigera %s: inte en vanlig fil"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "kunde inte öppna temporära filen %s: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "fel i underprocess"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr "flaggan \"e\" stöds inte"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "kommandot \"e\" stöds inte"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr "inget tidigare reguljärt uttryck"
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr "kan inte ange modifierare på tomt reguljärt uttryck"
+
+# Kommentar från Jan Djärv:
+# Jag antar RHS står för "right hand side".  Man kan då säga
+# "... kommandots högersida"
+#
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "ogiltig referens \\%d på \"s\"-kommandots högersida"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 använd Perl 5:s syntax för reguljära uttryck i skriptet.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+"Användning: %s [FLAGGA]... {skript-endast-om-inga-andra} [indatafil]...\n"
+"\n"
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+"  -n, --quiet, --silent\n"
+"                 förhindrar automatisk utskrift av mönsterutrymme\n"
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+"  -e skript, --expression=skript\n"
+"                 lägg till skript till de kommandon som ska utföras\n"
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+"  -f skriptfil, --file=skriptfil\n"
+"                 lägg till innehållet i skriptfil till de kommandon som ska\n"
+"                 utföras\n"
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+"  -i[ÄNDELSE], --in-place[=ÄNDELSE]\n"
+"                 redigera filer på plats (skapar säkerhetskopia om ändelse\n"
+"                 tillhandahålls)\n"
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+"  -l N, --line-length=N\n"
+"                 ange önskad radbrytningslängd för \"l\"-kommandot\n"
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+"  --posix\n"
+"                 inaktivera alla GNU-utökningar.\n"
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -r, --regexp-extended\n"
+"                 använd utökade reguljära uttryck i skriptet.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+"  -s, --separate\n"
+"                 betrakta filer som separata istället för som en\n"
+"                 kontinuerlig lång dataström.\n"
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+"  -u, --unbuffered\n"
+"                 läs in minimala mängder data från indatafilerna och töm\n"
+"                 utdatabufferterna oftare\n"
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr "      --help     visa denna hjälptext och avsluta\n"
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr "      --version  visa versionsinformation och avsluta\n"
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+"\n"
+"Om ingen av flaggorna -e, --expression, -f, eller --file ges, blir det\n"
+"första argumentet som inte är en flagga det sed-skript som tolkas. Alla\n"
+"återstående argument är namn på indatafiler. Om inga indatafiler är angivna\n"
+"läses standard in.\n"
+"\n"
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Rapportera fel till: %s .\n"
+"Ange ordet \"%s\" på något ställe i \"Ärende:\"-fältet.\n"
+"Skicka anmärkningar på översättningen till <sv@li.org>.\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed version %s\n"
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"baserad på GNU sed version %s\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed version %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"(Följande text är en informell översättning som enbart tillhandahålls\n"
+" i informativt syfte. För alla juridiska tolkningar gäller den engelska\n"
+" originaltexten.)\n"
+"Det här är fri programvara; se källkoden angående villkor för kopiering.\n"
+"Det finns INGEN garanti; inte ens för SÄLJBARHET eller LÄMPLIGHET FÖR NÅGOT\n"
+"SPECIELLT ÄNDAMÅL, i den omfattning som medges av gällande lag.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, c-format
+msgid "cannot remove %s: %s"
+msgstr "kan inte ta bort %s: %s"
+
+#: lib/utils.c:143
+#, c-format
+msgid "couldn't open file %s: %s"
+msgstr "kunde inte öppna filen %s: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "kunde inte skriva %d objekt till %s: %s"
+msgstr[1] "kunde inte skriva %d objekt till %s: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "läsfel vid %s: %s"
+
+#: lib/utils.c:341
+#, c-format
+msgid "cannot rename %s: %s"
+msgstr "kan inte byta namn på %s: %s"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Lyckades"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Ingen träff"
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Ogiltigt reguljärt uttryck"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Ogiltigt sorteringstecken"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Ogiltigt teckenklassnamn"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Eftersläpande omvänt snedstreck"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Ogiltig bakåtreferens"
+
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Obalanserad [ eller [^"
+
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Obalanserad ( eller \\("
+
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Obalanserad \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "Ogiltigt innehåll i \\{\\}"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Ogiltigt intervallslut"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Minnet slut"
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Ogiltigt föregående reguljärt uttryck"
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "För tidigt slut på reguljärt uttryck"
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Reguljärt uttryck för stort"
+
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Obalanserad ) eller \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Inget tidigare reguljärt uttryck"
Index: /tags/kBuild-0.1.4/src/sed/po/tr.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/tr.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/tr.po	(revision 1780)
@@ -0,0 +1,455 @@
+# translation of sed-4.0.9.tr.po to Turkish
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# Deniz Akkus Kanca <deniz@arayan.com>, 2001,2003, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 4.0.9\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2004-05-19 18:06+0300\n"
+"Last-Translator: Deniz Akkus Kanca <deniz@arayan.com>\n"
+"Language-Team: Turkish <gnu-tr-u12a@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.0.2\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "Birden fazla '!'"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "Beklenmeyen ','"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "İlk adres olarak +N veya ~N kullanılamaz"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Eşleşmeyen '{'"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Beklenmeyen '}'"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "Komuttan sonra fazla karakterler var"
+
+#: sed/compile.c:168
+#, fuzzy
+msgid "expected \\ after `a', `c' or `i'"
+msgstr "`a', `c' veya `i' sonrası \\ beklendi"
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "'}' için adres istenmez"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": için hiç adres istenmez"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "Açıklamalarda adres kabul edilmez"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "Komut eksik"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "Komutta yalnızca tek adres kullanılır"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Sonlandırılmamış adres düzenli ifadesi"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Sonlandırılmamış 's' komutu"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Sonlandırılmamış 'y' komutu"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "`s' komutuna bilinmeyen seçenek verilmiş"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "`s' komutuna birden fazla `p' seçeneği verilmiş"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "`s' komutuna birden fazla `g' seçeneği verilmiş"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "`s' komutuna birden fazla sayı seçeneği verilmiş"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "`s' komutuna verilen sayı seçeneği sıfır olamaz"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "y komutu için dizgeler değişik uzunluklarda"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr "sed'in daha yeni bir sürümü beklendi"
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "Adres değiştirici hatalı kullanılmış"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Bilinmeyen komut:"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s: dosya %s satır %lu: %s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s: -e ifade #%lu, harf %lu: %s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "`%s'e atlamak için etiket bulunamıyor"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s: %s okunamıyor: %s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "%d sayıda öğe %s'e yazılamadı: %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "%d sayıda öğe %s'e yazılamadı: %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "Geçici dosya %s açılamadı: %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr "altsüreçte hata"
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr " e' seçeneği desteklenmiyor"
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr "`e' komutu desteklenmiyor"
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+#, fuzzy
+msgid "no previous regular expression"
+msgstr "Daha önce düzenli ifade yok"
+
+#: sed/regexp.c:40
+#, fuzzy
+msgid "cannot specify modifiers on empty regexp"
+msgstr "Boş düzenli ifadeye değiştirici atanamaz"
+
+#: sed/regexp.c:115
+#, fuzzy, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr "`s' komutunun RHS'sinde geçersiz \\%d referansı"
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 betikte Perl 5'in düzenli ifade sözdizimini kullanır.\n"
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, fuzzy, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+"  -R, --regexp-perl\n"
+"                 betikte Perl 5'in düzenli ifade sözdizimini kullanır.\n"
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"Yazılım hatalarını %s adresine, çeviri hatalarını \n"
+"<gnu-tr-u12a@lists.sourceforge.net> adresine bildirin. \n"
+"``%s'' sözcüğünün Konu başlığında yer almasına dikkat edin. \n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr "super-sed sürüm %s\n"
+
+#: sed/sed.c:269
+#, fuzzy, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+"GNU sed sürümü 3.02.80 temel alınmıştır\n"
+"\n"
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr "GNU sed sürümü %s\n"
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+"%s\n"
+"Bu serbest yazılımdır; kopyalama koşulları için kaynak koduna bakınız.\n"
+"Hiçbir garantisi yoktur; hatta SATILABİLİRLİĞİ veya HERHANGİ BİR AMACA\n"
+"UYGUNLUĞU için bile garanti verilmez.\n"
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s: %s okunamıyor: %s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "%s dosyası açılamadı: %s"
+
+#: lib/utils.c:220
+#, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "%d sayıda öğe %s'e yazılamadı: %s"
+msgstr[1] "%d sayıda öğe %s'e yazılamadı: %s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "%s'de okuma hatası: %s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s: %s okunamıyor: %s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr "Başarılı"
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr "Eşleşme bulunamadı"
+
+#
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr "Hatalı düzenli ifade"
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr "Hatalı birleştirme karakteri"
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr "Hatalı karakter sınıf ismi"
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr "Sonda fazla gerikesme var"
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr "Hatalı geri referans"
+
+#
+#: lib/regcomp.c:153
+msgid "Unmatched [ or [^"
+msgstr "Eşleşmeyen [ veya [^"
+
+#
+#: lib/regcomp.c:156
+msgid "Unmatched ( or \\("
+msgstr "Eşleşmeyen ( veya \\("
+
+#
+#: lib/regcomp.c:159
+msgid "Unmatched \\{"
+msgstr "Eşleşmeyen \\{"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr "\\{\\} içeriği hatalı"
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr "Geçersiz kapsam sonu"
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr "Bellek tükendi"
+
+#
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr "Bir önceki düzenli ifade hatalı"
+
+#
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr "Düzenli ifade erken sonlandı"
+
+#
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr "Düzenli ifade fazla büyük"
+
+#
+#: lib/regcomp.c:180
+msgid "Unmatched ) or \\)"
+msgstr "Eşleşmeyen ) or \\)"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr "Daha önce düzenli ifade yok"
Index: /tags/kBuild-0.1.4/src/sed/po/zh_CN.po
===================================================================
--- /tags/kBuild-0.1.4/src/sed/po/zh_CN.po	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/po/zh_CN.po	(revision 1780)
@@ -0,0 +1,435 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2002 Free Software Foundation, Inc.
+# Wang Li <charles@linux.net.cn>, 2002.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sed 3.02.80\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-02-03 10:26+0100\n"
+"PO-Revision-Date: 2002-08-18 11:11+0800\n"
+"Last-Translator: Wang Li <charles@linux.net.cn>\n"
+"Language-Team: Chinese (simplified) <i18n-translation@lists.linux.net.cn>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=gb2312\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: sed/compile.c:162
+#, fuzzy
+msgid "multiple `!'s"
+msgstr "¶à¸ö¡°!¡±"
+
+#: sed/compile.c:163
+#, fuzzy
+msgid "unexpected `,'"
+msgstr "ÒâÍâµÄ¡°,¡±"
+
+#: sed/compile.c:164
+#, fuzzy
+msgid "invalid usage of +N or ~N as first address"
+msgstr "ÎÞ·¨½« +N »ò ~N ×÷ÎªµÚÒ»¸öµØÖ·"
+
+#: sed/compile.c:165
+#, fuzzy
+msgid "unmatched `{'"
+msgstr "Î´Æ¥ÅäµÄ¡°{¡±"
+
+#: sed/compile.c:166
+#, fuzzy
+msgid "unexpected `}'"
+msgstr "Î´Æ¥ÅäµÄ¡°}¡±"
+
+#: sed/compile.c:167
+#, fuzzy
+msgid "extra characters after command"
+msgstr "ÃüÁîºóº¬ÓÐ¶àÓàµÄ×Ö·û"
+
+#: sed/compile.c:168
+msgid "expected \\ after `a', `c' or `i'"
+msgstr ""
+
+#: sed/compile.c:169
+msgid "`}' doesn't want any addresses"
+msgstr "¡°}¡±²»ÐèÒªÈÎºÎµØÖ·"
+
+#: sed/compile.c:170
+msgid ": doesn't want any addresses"
+msgstr ": ²»ÐèÒªÈÎºÎµØÖ·"
+
+#: sed/compile.c:171
+#, fuzzy
+msgid "comments don't accept any addresses"
+msgstr "×¢ÊÍ²»½ÓÊÜÈÎºÎµØÖ·"
+
+#: sed/compile.c:172
+#, fuzzy
+msgid "missing command"
+msgstr "ÒÅÂ©ÃüÁî"
+
+#: sed/compile.c:173
+#, fuzzy
+msgid "command only uses one address"
+msgstr "ÃüÁîÖ»Ê¹ÓÃÒ»¸öµØÖ·"
+
+#: sed/compile.c:174
+#, fuzzy
+msgid "unterminated address regex"
+msgstr "Î´ÖÕÖ¹µÄµØÖ·³£¹æ±í´ïÊ½"
+
+#: sed/compile.c:175
+#, fuzzy
+msgid "unterminated `s' command"
+msgstr "Î´ÖÕÖ¹µÄ¡°s¡±ÃüÁî"
+
+#: sed/compile.c:176
+#, fuzzy
+msgid "unterminated `y' command"
+msgstr "Î´ÖÕÖ¹µÄ¡°y¡±ÃüÁî"
+
+#: sed/compile.c:177
+#, fuzzy
+msgid "unknown option to `s'"
+msgstr "¡°s¡±µÄÎ´ÖªÑ¡Ïî"
+
+#: sed/compile.c:178
+msgid "multiple `p' options to `s' command"
+msgstr "¶à¸ö¡°s¡±ÃüÁîµÄÑ¡Ïî¡°p¡±"
+
+#: sed/compile.c:179
+msgid "multiple `g' options to `s' command"
+msgstr "¶à¸ö¡°s¡±ÃüÁîµÄÑ¡Ïî¡°g¡±"
+
+#: sed/compile.c:180
+msgid "multiple number options to `s' command"
+msgstr "¶à¸ö¡°s¡±ÃüÁîµÄÊýÖµÑ¡Ïî"
+
+#: sed/compile.c:181
+msgid "number option to `s' command may not be zero"
+msgstr "¡°s¡±ÃüÁîµÄÊýÖµÑ¡Ïî²»ÄÜÎªÁã"
+
+#: sed/compile.c:182
+#, fuzzy
+msgid "strings for `y' command are different lengths"
+msgstr "y ÃüÁîµÄ×Ö·û´®³¤¶È²»Í¬"
+
+#: sed/compile.c:183
+msgid "delimiter character is not a single-byte character"
+msgstr ""
+
+#: sed/compile.c:184
+msgid "expected newer version of sed"
+msgstr ""
+
+#: sed/compile.c:185
+#, fuzzy
+msgid "invalid usage of line address 0"
+msgstr "·Ç·¨Ê¹ÓÃµØÖ·ÐÞÊÎ·û"
+
+#: sed/compile.c:186
+#, fuzzy, c-format
+msgid "unknown command: `%c'"
+msgstr "Î´ÖªµÄÃüÁî£º"
+
+#: sed/compile.c:209
+#, c-format
+msgid "%s: file %s line %lu: %s\n"
+msgstr "%s£ºÎÄ¼þ %s ÐÐºÅ£º%lu£º%s\n"
+
+#: sed/compile.c:212
+#, c-format
+msgid "%s: -e expression #%lu, char %lu: %s\n"
+msgstr "%s£º-e ±í´ïÊ½ #%lu£¬×Ö·û %lu£º%s\n"
+
+#: sed/compile.c:1644
+#, fuzzy, c-format
+msgid "can't find label for jump to `%s'"
+msgstr "ÎÞ·¨ÎªÄ¿µÄÎª¡°%s¡±µÄÌø×ªÕÒµ½±êÇ©"
+
+#: sed/execute.c:650
+#, c-format
+msgid "%s: can't read %s: %s\n"
+msgstr "%s£ºÎÞ·¨¶ÁÈ¡ %s£º%s\n"
+
+#: sed/execute.c:673
+#, fuzzy, c-format
+msgid "couldn't edit %s: is a terminal"
+msgstr "ÎÞ·¨´ò¿ªÎÄ¼þ %s"
+
+#: sed/execute.c:677
+#, fuzzy, c-format
+msgid "couldn't edit %s: not a regular file"
+msgstr "ÎÞ·¨´ò¿ªÎÄ¼þ %s"
+
+#: sed/execute.c:684 lib/utils.c:196
+#, fuzzy, c-format
+msgid "couldn't open temporary file %s: %s"
+msgstr "ÎÞ·¨´ò¿ªÎÄ¼þ %s"
+
+#: sed/execute.c:1206 sed/execute.c:1387
+msgid "error in subprocess"
+msgstr ""
+
+#: sed/execute.c:1208
+msgid "option `e' not supported"
+msgstr ""
+
+#: sed/execute.c:1389
+msgid "`e' command not supported"
+msgstr ""
+
+#: sed/execute.c:1714
+msgid "no input files"
+msgstr ""
+
+#: sed/regexp.c:39
+msgid "no previous regular expression"
+msgstr ""
+
+#: sed/regexp.c:40
+msgid "cannot specify modifiers on empty regexp"
+msgstr ""
+
+#: sed/regexp.c:115
+#, c-format
+msgid "invalid reference \\%d on `s' command's RHS"
+msgstr ""
+
+#: sed/sed.c:93
+msgid ""
+"  -R, --regexp-perl\n"
+"                 use Perl 5's regular expressions syntax in the script.\n"
+msgstr ""
+
+#: sed/sed.c:98
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:102
+#, c-format
+msgid ""
+"  -n, --quiet, --silent\n"
+"                 suppress automatic printing of pattern space\n"
+msgstr ""
+
+#: sed/sed.c:104
+#, c-format
+msgid ""
+"  -e script, --expression=script\n"
+"                 add the script to the commands to be executed\n"
+msgstr ""
+
+#: sed/sed.c:106
+#, c-format
+msgid ""
+"  -f script-file, --file=script-file\n"
+"                 add the contents of script-file to the commands to be "
+"executed\n"
+msgstr ""
+
+#: sed/sed.c:108
+#, c-format
+msgid ""
+"  -i[SUFFIX], --in-place[=SUFFIX]\n"
+"                 edit files in place (makes backup if extension supplied)\n"
+msgstr ""
+
+#: sed/sed.c:110
+#, c-format
+msgid ""
+"  -l N, --line-length=N\n"
+"                 specify the desired line-wrap length for the `l' command\n"
+msgstr ""
+
+#: sed/sed.c:112
+#, c-format
+msgid ""
+"  --posix\n"
+"                 disable all GNU extensions.\n"
+msgstr ""
+
+#: sed/sed.c:114
+#, c-format
+msgid ""
+"  -r, --regexp-extended\n"
+"                 use extended regular expressions in the script.\n"
+msgstr ""
+
+#: sed/sed.c:117
+#, c-format
+msgid ""
+"  -s, --separate\n"
+"                 consider files as separate rather than as a single "
+"continuous\n"
+"                 long stream.\n"
+msgstr ""
+
+#: sed/sed.c:120
+#, c-format
+msgid ""
+"  -u, --unbuffered\n"
+"                 load minimal amounts of data from the input files and "
+"flush\n"
+"                 the output buffers more often\n"
+msgstr ""
+
+#: sed/sed.c:123
+#, c-format
+msgid "      --help     display this help and exit\n"
+msgstr ""
+
+#: sed/sed.c:124
+#, c-format
+msgid "      --version  output version information and exit\n"
+msgstr ""
+
+#: sed/sed.c:125
+#, c-format
+msgid ""
+"\n"
+"If no -e, --expression, -f, or --file option is given, then the first\n"
+"non-option argument is taken as the sed script to interpret.  All\n"
+"remaining arguments are names of input files; if no input files are\n"
+"specified, then the standard input is read.\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:131
+#, c-format
+msgid ""
+"E-mail bug reports to: %s .\n"
+"Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"
+msgstr ""
+"½«´íÎó±¨¸æÍ¨¹ýµç×ÓÓÊ¼þ·¢ËÍµ½£º%s .\n"
+"ÇëÎñ±Ø½«µ¥´Ê¡°%s¡±·ÅÔÚ¡°Subject:¡±ÓòµÄÄ³´¦¡£\n"
+
+#: sed/sed.c:268
+#, c-format
+msgid "super-sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:269
+#, c-format
+msgid ""
+"based on GNU sed version %s\n"
+"\n"
+msgstr ""
+
+#: sed/sed.c:271
+#, c-format
+msgid "GNU sed version %s\n"
+msgstr ""
+
+#: sed/sed.c:273
+#, c-format
+msgid ""
+"%s\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n"
+"to the extent permitted by law.\n"
+msgstr ""
+
+#: lib/utils.c:98 lib/utils.c:336
+#, fuzzy, c-format
+msgid "cannot remove %s: %s"
+msgstr "%s£ºÎÞ·¨¶ÁÈ¡ %s£º%s\n"
+
+#: lib/utils.c:143
+#, fuzzy, c-format
+msgid "couldn't open file %s: %s"
+msgstr "ÎÞ·¨´ò¿ªÎÄ¼þ %s"
+
+#: lib/utils.c:220
+#, fuzzy, c-format
+msgid "couldn't write %d item to %s: %s"
+msgid_plural "couldn't write %d items to %s: %s"
+msgstr[0] "ÎÞ·¨½« %d ¸öÏîÄ¿Ð´Èë %s£º%s"
+msgstr[1] "ÎÞ·¨½« %d ¸öÏîÄ¿Ð´Èë %s£º%s"
+
+#: lib/utils.c:235 lib/utils.c:251
+#, c-format
+msgid "read error on %s: %s"
+msgstr "¶ÁÈ¡ %s ³ö´í£º%s"
+
+#: lib/utils.c:341
+#, fuzzy, c-format
+msgid "cannot rename %s: %s"
+msgstr "%s£ºÎÞ·¨¶ÁÈ¡ %s£º%s\n"
+
+#: lib/regcomp.c:132
+msgid "Success"
+msgstr ""
+
+#: lib/regcomp.c:135
+msgid "No match"
+msgstr ""
+
+#: lib/regcomp.c:138
+msgid "Invalid regular expression"
+msgstr ""
+
+#: lib/regcomp.c:141
+msgid "Invalid collation character"
+msgstr ""
+
+#: lib/regcomp.c:144
+msgid "Invalid character class name"
+msgstr ""
+
+#: lib/regcomp.c:147
+msgid "Trailing backslash"
+msgstr ""
+
+#: lib/regcomp.c:150
+msgid "Invalid back reference"
+msgstr ""
+
+#: lib/regcomp.c:153
+#, fuzzy
+msgid "Unmatched [ or [^"
+msgstr "Î´Æ¥ÅäµÄ¡°{¡±"
+
+#: lib/regcomp.c:156
+#, fuzzy
+msgid "Unmatched ( or \\("
+msgstr "Î´Æ¥ÅäµÄ¡°{¡±"
+
+#: lib/regcomp.c:159
+#, fuzzy
+msgid "Unmatched \\{"
+msgstr "Î´Æ¥ÅäµÄ¡°{¡±"
+
+#: lib/regcomp.c:162
+msgid "Invalid content of \\{\\}"
+msgstr ""
+
+#: lib/regcomp.c:165
+msgid "Invalid range end"
+msgstr ""
+
+#: lib/regcomp.c:168
+msgid "Memory exhausted"
+msgstr ""
+
+#: lib/regcomp.c:171
+msgid "Invalid preceding regular expression"
+msgstr ""
+
+#: lib/regcomp.c:174
+msgid "Premature end of regular expression"
+msgstr ""
+
+#: lib/regcomp.c:177
+msgid "Regular expression too big"
+msgstr ""
+
+#: lib/regcomp.c:180
+#, fuzzy
+msgid "Unmatched ) or \\)"
+msgstr "Î´Æ¥ÅäµÄ¡°{¡±"
+
+#: lib/regcomp.c:660
+msgid "No previous regular expression"
+msgstr ""
Index: /tags/kBuild-0.1.4/src/sed/sed/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/Makefile.am	(revision 1780)
@@ -0,0 +1,18 @@
+## Process this file with automake to produce Makefile.in
+bin_PROGRAMS = sed
+
+localedir = $(datadir)/locale
+
+sed_SOURCES = sed.c compile.c execute.c regexp.c fmt.c mbcs.c
+noinst_HEADERS = sed.h
+
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/intl \
+	-I$(top_srcdir) -I$(top_builddir)/lib \
+	-I$(top_builddir)/intl -DLOCALEDIR=\"$(localedir)\"
+
+sed_LDADD = ../lib/libsed.a @INTLLIBS@
+sed_DEPENDENCIES = ../lib/libsed.a
+
+$(PROGRAMS): $(LDADD)
+
+
Index: /tags/kBuild-0.1.4/src/sed/sed/Makefile.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/Makefile.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/Makefile.in	(revision 1780)
@@ -0,0 +1,482 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# 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_MAKE@
+
+
+SOURCES = $(sed_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = sed$(EXEEXT)
+subdir = sed
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \
+	$(top_srcdir)/config/getline.m4 \
+	$(top_srcdir)/config/gettext-ver.m4 \
+	$(top_srcdir)/config/gettext.m4 \
+	$(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \
+	$(top_srcdir)/config/lcmessage.m4 \
+	$(top_srcdir)/config/lib-ld.m4 \
+	$(top_srcdir)/config/lib-link.m4 \
+	$(top_srcdir)/config/lib-prefix.m4 \
+	$(top_srcdir)/config/progtest.m4 \
+	$(top_srcdir)/config/stdbool.m4 \
+	$(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_sed_OBJECTS = sed.$(OBJEXT) compile.$(OBJEXT) execute.$(OBJEXT) \
+	regexp.$(OBJEXT) fmt.$(OBJEXT) mbcs.$(OBJEXT)
+sed_OBJECTS = $(am_sed_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(sed_SOURCES)
+DIST_SOURCES = $(sed_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_HTML_FALSE = @BUILD_HTML_FALSE@
+BUILD_HTML_TRUE = @BUILD_HTML_TRUE@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
+GMSGFMT = @GMSGFMT@
+HAVE__BOOL = @HAVE__BOOL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@
+MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SED_FEATURE_VERSION = @SED_FEATURE_VERSION@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEST_REGEX_FALSE = @TEST_REGEX_FALSE@
+TEST_REGEX_TRUE = @TEST_REGEX_TRUE@
+TEXI2HTML = @TEXI2HTML@
+TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@
+TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+localedir = $(datadir)/locale
+sed_SOURCES = sed.c compile.c execute.c regexp.c fmt.c mbcs.c
+noinst_HEADERS = sed.h
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/intl \
+	-I$(top_srcdir) -I$(top_builddir)/lib \
+	-I$(top_builddir)/intl -DLOCALEDIR=\"$(localedir)\"
+
+sed_LDADD = ../lib/libsed.a @INTLLIBS@
+sed_DEPENDENCIES = ../lib/libsed.a
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits  sed/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnits  sed/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(bindir)/$$f"; \
+	done
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+installcheck-binPROGRAMS: $(bin_PROGRAMS)
+	bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
+	  case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
+	   *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
+	  esac; \
+	  f=`echo "$$p" | \
+	     sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  for opt in --help --version; do \
+	    if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \
+	         2>c$${pid}_.err </dev/null \
+		 && test -n "`cat c$${pid}_.out`" \
+		 && test -z "`cat c$${pid}_.err`"; then :; \
+	    else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
+	  done; \
+	done; rm -f c$${pid}_.???; exit $$bad
+sed$(EXEEXT): $(sed_OBJECTS) $(sed_DEPENDENCIES) 
+	@rm -f sed$(EXEEXT)
+	$(LINK) $(sed_LDFLAGS) $(sed_OBJECTS) $(sed_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbcs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sed.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am: installcheck-binPROGRAMS
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+	clean-generic ctags distclean distclean-compile \
+	distclean-generic distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-binPROGRAMS \
+	install-data install-data-am install-exec install-exec-am \
+	install-info install-info-am install-man install-strip \
+	installcheck installcheck-am installcheck-binPROGRAMS \
+	installdirs maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
+	ps ps-am tags uninstall uninstall-am uninstall-binPROGRAMS \
+	uninstall-info-am
+
+
+$(PROGRAMS): $(LDADD)
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /tags/kBuild-0.1.4/src/sed/sed/compile.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/compile.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/compile.c	(revision 1780)
@@ -0,0 +1,1734 @@
+/*  GNU SED, a batch stream editor.
+    Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003,2004,2005,2006
+    Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* compile.c: translate sed source into internal form */
+
+#include "sed.h"
+#include "strverscmp.h"
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+# ifdef HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+#else
+# include <string.h>
+#endif /* HAVE_STRINGS_H */
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <obstack.h>
+
+
+
+#define YMAP_LENGTH		256 /*XXX shouldn't this be (UCHAR_MAX+1)?*/
+#define VECTOR_ALLOC_INCREMENT	40
+
+/* let's not confuse text editors that have only dumb bracket-matching... */
+#define OPEN_BRACKET	'['
+#define CLOSE_BRACKET	']'
+#define OPEN_BRACE	'{'
+#define CLOSE_BRACE	'}'
+
+struct prog_info {
+  /* When we're reading a script command from a string, `prog.base'
+     points to the first character in the string, 'prog.cur' points
+     to the current character in the string, and 'prog.end' points
+     to the end of the string.  This allows us to compile script
+     strings that contain nulls. */
+  const unsigned char *base;
+  const unsigned char *cur;
+  const unsigned char *end;
+
+  /* This is the current script file.  If it is NULL, we are reading
+     from a string stored at `prog.cur' instead.  If both `prog.file'
+     and `prog.cur' are NULL, we're in trouble! */
+  FILE *file;
+};
+
+/* Information used to give out useful and informative error messages. */
+struct error_info {
+  /* This is the name of the current script file. */
+  const char *name;
+
+  /* This is the number of the current script line that we're compiling. */
+  countT line;
+
+  /* This is the index of the "-e" expressions on the command line. */
+  countT string_expr_count;
+};
+
+
+/* Label structure used to resolve GOTO's, labels, and block beginnings. */
+struct sed_label {
+  countT v_index;		/* index of vector element being referenced */
+  char *name;			/* NUL-terminated name of the label */
+  struct error_info err_info;	/* track where `{}' blocks start */
+  struct sed_label *next;	/* linked list (stack) */
+};
+
+struct special_files {
+  struct output outf;
+  FILE **pfp;
+};
+
+FILE *my_stdin, *my_stdout, *my_stderr;
+struct special_files special_files[] = {
+  { { "/dev/stdin", false, NULL, NULL }, &my_stdin },
+  { { "/dev/stdout", false, NULL, NULL }, &my_stdout },
+  { { "/dev/stderr", false, NULL, NULL }, &my_stderr },
+  { { NULL, false, NULL, NULL }, NULL }
+};
+
+
+
+/* Where we are in the processing of the input. */
+static struct prog_info prog;
+static struct error_info cur_input;
+
+/* Information about labels and jumps-to-labels.  This is used to do
+   the required backpatching after we have compiled all the scripts. */
+static struct sed_label *jumps = NULL;
+static struct sed_label *labels = NULL;
+
+/* We wish to detect #n magic only in the first input argument;
+   this flag tracks when we have consumed the first file of input. */
+static bool first_script = true;
+
+/* Allow for scripts like "sed -e 'i\' -e foo": */
+static struct buffer *pending_text = NULL;
+static struct text_buf *old_text_buf = NULL;
+
+/* Information about block start positions.  This is used to backpatch
+   block end positions. */
+static struct sed_label *blocks = NULL;
+
+/* Use an obstack for compilation. */
+static struct obstack obs;
+
+/* Various error messages we may want to print */
+static const char errors[] =
+  "multiple `!'s\0"
+  "unexpected `,'\0"
+  "invalid usage of +N or ~N as first address\0"
+  "unmatched `{'\0"
+  "unexpected `}'\0"
+  "extra characters after command\0"
+  "expected \\ after `a', `c' or `i'\0"
+  "`}' doesn't want any addresses\0"
+  ": doesn't want any addresses\0"
+  "comments don't accept any addresses\0"
+  "missing command\0"
+  "command only uses one address\0"
+  "unterminated address regex\0"
+  "unterminated `s' command\0"
+  "unterminated `y' command\0"
+  "unknown option to `s'\0"
+  "multiple `p' options to `s' command\0"
+  "multiple `g' options to `s' command\0"
+  "multiple number options to `s' command\0"
+  "number option to `s' command may not be zero\0"
+  "strings for `y' command are different lengths\0"
+  "delimiter character is not a single-byte character\0"
+  "expected newer version of sed\0"
+  "invalid usage of line address 0\0"
+  "unknown command: `%c'";
+
+#define BAD_BANG (errors)
+#define BAD_COMMA (BAD_BANG + sizeof(N_("multiple `!'s")))
+#define BAD_STEP (BAD_COMMA + sizeof(N_("unexpected `,'")))
+#define EXCESS_OPEN_BRACE (BAD_STEP + sizeof(N_("invalid usage of +N or ~N as first address")))
+#define EXCESS_CLOSE_BRACE (EXCESS_OPEN_BRACE + sizeof(N_("unmatched `{'")))
+#define EXCESS_JUNK (EXCESS_CLOSE_BRACE + sizeof(N_("unexpected `}'")))
+#define EXPECTED_SLASH (EXCESS_JUNK + sizeof(N_("extra characters after command")))
+#define NO_CLOSE_BRACE_ADDR (EXPECTED_SLASH + sizeof(N_("expected \\ after `a', `c' or `i'")))
+#define NO_COLON_ADDR (NO_CLOSE_BRACE_ADDR + sizeof(N_("`}' doesn't want any addresses")))
+#define NO_SHARP_ADDR (NO_COLON_ADDR + sizeof(N_(": doesn't want any addresses")))
+#define NO_COMMAND (NO_SHARP_ADDR + sizeof(N_("comments don't accept any addresses")))
+#define ONE_ADDR (NO_COMMAND + sizeof(N_("missing command")))
+#define UNTERM_ADDR_RE (ONE_ADDR + sizeof(N_("command only uses one address")))
+#define UNTERM_S_CMD (UNTERM_ADDR_RE + sizeof(N_("unterminated address regex")))
+#define UNTERM_Y_CMD (UNTERM_S_CMD + sizeof(N_("unterminated `s' command")))
+#define UNKNOWN_S_OPT (UNTERM_Y_CMD + sizeof(N_("unterminated `y' command")))
+#define EXCESS_P_OPT (UNKNOWN_S_OPT + sizeof(N_("unknown option to `s'")))
+#define EXCESS_G_OPT (EXCESS_P_OPT + sizeof(N_("multiple `p' options to `s' command")))
+#define EXCESS_N_OPT (EXCESS_G_OPT + sizeof(N_("multiple `g' options to `s' command")))
+#define ZERO_N_OPT (EXCESS_N_OPT + sizeof(N_("multiple number options to `s' command")))
+#define Y_CMD_LEN (ZERO_N_OPT + sizeof(N_("number option to `s' command may not be zero")))
+#define BAD_DELIM (Y_CMD_LEN + sizeof(N_("strings for `y' command are different lengths")))
+#define ANCIENT_VERSION (BAD_DELIM + sizeof(N_("delimiter character is not a single-byte character")))
+#define INVALID_LINE_0 (ANCIENT_VERSION + sizeof(N_("expected newer version of sed")))
+#define UNKNOWN_CMD (INVALID_LINE_0 + sizeof(N_("invalid usage of line address 0")))
+#define END_ERRORS (UNKNOWN_CMD + sizeof(N_("unknown command: `%c'")))
+
+static struct output *file_read = NULL;
+static struct output *file_write = NULL;
+
+
+
+/* Complain about an unknown command and exit. */
+void
+bad_command(ch)
+  char ch;
+{
+  const char *msg = _(UNKNOWN_CMD);
+  char *unknown_cmd = xmalloc(strlen(msg));
+  sprintf(unknown_cmd, msg, ch);
+  bad_prog(unknown_cmd);
+}
+
+/* Complain about a programming error and exit. */
+void
+bad_prog(why)
+  const char *why;
+{
+  if (cur_input.name)
+    fprintf(stderr, _("%s: file %s line %lu: %s\n"),
+	    myname, cur_input.name, CAST(unsigned long)cur_input.line, why);
+  else
+    fprintf(stderr, _("%s: -e expression #%lu, char %lu: %s\n"),
+	    myname,
+	    CAST(unsigned long)cur_input.string_expr_count,
+	    CAST(unsigned long)(prog.cur-prog.base),
+	    why);
+  exit(EXIT_FAILURE);
+}
+
+
+
+/* Read the next character from the program.  Return EOF if there isn't
+   anything to read.  Keep cur_input.line up to date, so error messages
+   can be meaningful. */
+static int inchar P_((void));
+static int
+inchar()
+{
+  int ch = EOF;
+
+  if (prog.cur)
+    {
+      if (prog.cur < prog.end)
+	ch = *prog.cur++;
+    }
+  else if (prog.file)
+    {
+      if (!feof(prog.file))
+	ch = getc(prog.file);
+    }
+  if (ch == '\n')
+    ++cur_input.line;
+  return ch;
+}
+
+/* unget `ch' so the next call to inchar will return it.   */
+static void savchar P_((int ch));
+static void
+savchar(ch)
+  int ch;
+{
+  if (ch == EOF)
+    return;
+  if (ch == '\n' && cur_input.line > 0)
+    --cur_input.line;
+  if (prog.cur)
+    {
+      if (prog.cur <= prog.base || *--prog.cur != ch)
+	panic("Called savchar() with unexpected pushback (%x)",
+	      CAST(unsigned char)ch);
+    }
+  else
+    ungetc(ch, prog.file);
+}
+
+/* Read the next non-blank character from the program.  */
+static int in_nonblank P_((void));
+static int
+in_nonblank()
+{
+  int ch;
+  do
+    ch = inchar();
+    while (ISBLANK(ch));
+  return ch;
+}
+
+/* Read an integer value from the program.  */
+static countT in_integer P_((int ch));
+static countT
+in_integer(ch)
+  int ch;
+{
+  countT num = 0;
+
+  while (ISDIGIT(ch))
+    {
+      num = num * 10 + ch - '0';
+      ch = inchar();
+    }
+  savchar(ch);
+  return num;
+}
+
+static int add_then_next P_((struct buffer *b, int ch));
+static int
+add_then_next(b, ch)
+  struct buffer *b;
+  int ch;
+{
+  add1_buffer(b, ch);
+  return inchar();
+}
+
+static char * convert_number P_((char *, char *, const char *, int, int, int));
+static char *
+convert_number(result, buf, bufend, base, maxdigits, default_char)
+  char *result;
+  char *buf;
+  const char *bufend;
+  int base;
+  int maxdigits;
+  int default_char;
+{
+  int n = 0;
+  char *p;
+
+  for (p=buf; p < bufend && maxdigits-- > 0; ++p)
+    {
+      int d = -1;
+      switch (*p)
+	{
+	case '0': d = 0x0; break;
+	case '1': d = 0x1; break;
+	case '2': d = 0x2; break;
+	case '3': d = 0x3; break;
+	case '4': d = 0x4; break;
+	case '5': d = 0x5; break;
+	case '6': d = 0x6; break;
+	case '7': d = 0x7; break;
+	case '8': d = 0x8; break;
+	case '9': d = 0x9; break;
+	case 'A': case 'a': d = 0xa; break;
+	case 'B': case 'b': d = 0xb; break;
+	case 'C': case 'c': d = 0xc; break;
+	case 'D': case 'd': d = 0xd; break;
+	case 'E': case 'e': d = 0xe; break;
+	case 'F': case 'f': d = 0xf; break;
+	}
+      if (d < 0 || base <= d)
+	break;
+      n = n * base + d;
+    }
+  if (p == buf)
+    *result = default_char;
+  else
+    *result = n;
+  return p;
+}
+
+
+
+/* Read in a filename for a `r', `w', or `s///w' command. */
+static struct buffer *read_filename P_((void));
+static struct buffer *
+read_filename()
+{
+  struct buffer *b;
+  int ch;
+
+  b = init_buffer();
+  ch = in_nonblank();
+  while (ch != EOF && ch != '\n')
+    {
+#if 0 /*XXX ZZZ 1998-09-12 kpp: added, then had second thoughts*/
+      if (posixicity == POSIXLY_EXTENDED)
+	if (ch == ';' || ch == '#')
+	  {
+	    savchar(ch);
+	    break;
+	  }
+#endif
+      ch = add_then_next(b, ch);
+    }
+  add1_buffer(b, '\0');
+  return b;
+}
+
+static struct output *get_openfile P_((struct output **file_ptrs, char *mode, bool fail));
+static struct output *
+get_openfile(file_ptrs, mode, fail)
+     struct output **file_ptrs;
+     char *mode;
+     bool fail;
+{
+  struct buffer *b;
+  char *file_name;
+  struct output *p;
+  int is_stderr;
+
+  b = read_filename();
+  file_name = get_buffer(b);
+  for (p=*file_ptrs; p; p=p->link)
+    if (strcmp(p->name, file_name) == 0)
+      break;
+
+  if (posixicity == POSIXLY_EXTENDED)
+    {
+      /* Check whether it is a special file (stdin, stdout or stderr) */
+      struct special_files *special = special_files;
+		  
+      /* std* sometimes are not constants, so they
+         cannot be used in the initializer for special_files */
+#ifndef CONFIG_WITHOUT_O_OPT
+      my_stdin = stdin; my_stdout = sed_stdout; my_stderr = stderr;
+#else
+      my_stdin = stdin; my_stdout = stdout; my_stderr = stderr;
+#endif
+      for (special = special_files; special->outf.name; special++)
+        if (strcmp(special->outf.name, file_name) == 0)
+          {
+	    special->outf.fp = *special->pfp;
+	    free_buffer (b);
+	    return &special->outf;
+          }
+    }
+
+  if (!p)
+    {
+      p = OB_MALLOC(&obs, 1, struct output);
+      p->name = ck_strdup(file_name);
+      p->fp = ck_fopen(p->name, mode, fail);
+      p->missing_newline = false;
+      p->link = *file_ptrs;
+      *file_ptrs = p;
+    }
+  free_buffer(b);
+  return p;
+}
+
+
+
+static struct sed_cmd *next_cmd_entry P_((struct vector **vectorp));
+static struct sed_cmd *
+next_cmd_entry(vectorp)
+  struct vector **vectorp;
+{
+  struct sed_cmd *cmd;
+  struct vector *v;
+
+  v = *vectorp;
+  if (v->v_length == v->v_allocated)
+    {
+      v->v_allocated += VECTOR_ALLOC_INCREMENT;
+      v->v = REALLOC(v->v, v->v_allocated, struct sed_cmd);
+    }
+
+  cmd = v->v + v->v_length;
+  cmd->a1 = NULL;
+  cmd->a2 = NULL;
+  cmd->range_state = RANGE_INACTIVE;
+  cmd->addr_bang = false;
+  cmd->cmd = '\0';	/* something invalid, to catch bugs early */
+
+  *vectorp  = v;
+  return cmd;
+}
+
+static int snarf_char_class P_((struct buffer *b, mbstate_t *cur_stat));
+static int
+snarf_char_class(b, cur_stat)
+  struct buffer *b;
+  mbstate_t *cur_stat;
+{
+  int ch;
+  int state = 0;
+  int delim;
+  bool pending_mb = 0;
+  
+  ch = inchar();
+  if (ch == '^')
+    ch = add_then_next(b, ch);
+  if (ch == CLOSE_BRACKET)
+    ch = add_then_next(b, ch);
+  
+  /* States are:
+	0 outside a collation element, character class or collation class
+	1 after the bracket
+	2 after the opening ./:/=
+	3 after the closing ./:/= */
+
+  for (;; ch = add_then_next (b, ch))
+    {
+      pending_mb = BRLEN (ch, cur_stat) != 1;
+
+      switch (ch)
+	{
+	case EOF:
+	case '\n':
+	  return ch;
+
+	case '.':
+	case ':':
+	case '=':
+	  if (pending_mb)
+	    continue;
+
+	  if (state == 1)
+	    {
+	      delim = ch;
+	      state++;
+	    }
+	  else if (ch == delim && state == 2)
+	    state++;
+	  else
+	    break;
+
+	  continue;
+
+	case OPEN_BRACKET:
+	  if (pending_mb)
+	    continue;
+
+	  state++;
+	  continue;
+
+	case CLOSE_BRACKET:
+	  if (pending_mb)
+	    continue;
+
+	  if (state == 0 || state == 1)
+	    return ch;
+	  else if (state == 3)
+	    state = 0;
+
+	  break;
+
+	default:
+	  break;
+	}
+
+      /* Getting a character different from .=: whilst in state 1
+         goes back to state 0, getting a character different from ]
+         whilst in state 3 goes back to state 2.  */
+      state &= ~1;
+    }
+}
+
+static struct buffer *match_slash P_((int slash, bool regex));
+static struct buffer *
+match_slash(slash, regex)
+  int slash;
+  bool regex;
+{
+  struct buffer *b;
+  int ch;
+  bool pending_mb = false;
+  mbstate_t cur_stat;
+
+  memset (&cur_stat, 0, sizeof (mbstate_t));
+
+  if (BRLEN (slash, &cur_stat) == -2)
+  if (BRLEN (slash, &cur_stat) == -2)
+    bad_prog (BAD_DELIM);
+
+  memset (&cur_stat, 0, sizeof (mbstate_t));
+
+  b = init_buffer();
+  while ((ch = inchar()) != EOF && ch != '\n')
+    {
+      pending_mb = BRLEN (ch, &cur_stat) != 1;
+      pending_mb = BRLEN (ch, &cur_stat) != 1;
+
+      if (!pending_mb)
+	{
+	  if (ch == slash)
+	    return b;
+	  else if (ch == '\\')
+	    {
+	      ch = inchar();
+	      if (ch == EOF)
+	        break;
+#ifndef REG_PERL
+	      else if (ch == 'n' && regex)
+	        ch = '\n';
+#endif
+	      else if (ch != '\n' && ch != slash)
+	        add1_buffer(b, '\\');
+	    }
+          else if (ch == OPEN_BRACKET && regex)
+	    {
+	      add1_buffer(b, ch);
+	      ch = snarf_char_class(b, &cur_stat);
+	      if (ch != CLOSE_BRACKET)
+	        break;
+	    }
+	}
+
+      add1_buffer(b, ch);
+    }
+
+  if (ch == '\n')
+    savchar(ch);	/* for proper line number in error report */
+  free_buffer(b);
+  return NULL;
+}
+
+static int mark_subst_opts P_((struct subst *cmd));
+static int
+mark_subst_opts(cmd)
+  struct subst *cmd;
+{
+  int flags = 0;
+  int ch;
+
+  cmd->global = false;
+  cmd->print = false;
+  cmd->eval = false;
+  cmd->numb = 0;
+  cmd->outf = NULL;
+
+  for (;;)
+    switch ( (ch = in_nonblank()) )
+      {
+      case 'i':	/* GNU extension */
+      case 'I':	/* GNU extension */
+	flags |= REG_ICASE;
+	break;
+
+#ifdef REG_PERL
+      case 's':	/* GNU extension */
+      case 'S':	/* GNU extension */
+	if (extended_regexp_flags & REG_PERL)
+	  flags |= REG_DOTALL;
+	break;
+
+      case 'x':	/* GNU extension */
+      case 'X':	/* GNU extension */
+	if (extended_regexp_flags & REG_PERL)
+	  flags |= REG_EXTENDED;
+	break;
+#endif
+
+      case 'm':	/* GNU extension */
+      case 'M':	/* GNU extension */
+	flags |= REG_NEWLINE;
+	break;
+
+      case 'e':
+	cmd->eval = true;
+	break;
+
+      case 'p':
+	if (cmd->print)
+	  bad_prog(_(EXCESS_P_OPT));
+	cmd->print |= (1 << cmd->eval); /* 1=before eval, 2=after */
+	break;
+
+      case 'g':
+	if (cmd->global)
+	  bad_prog(_(EXCESS_G_OPT));
+	cmd->global = true;
+	break;
+
+      case 'w':
+	cmd->outf = get_openfile(&file_write, "w", true);
+	return flags;
+
+      case '0': case '1': case '2': case '3': case '4':
+      case '5': case '6': case '7': case '8': case '9':
+	if (cmd->numb)
+	  bad_prog(_(EXCESS_N_OPT));
+	cmd->numb = in_integer(ch);
+	if (!cmd->numb)
+	  bad_prog(_(ZERO_N_OPT));
+	break;
+
+      case CLOSE_BRACE:
+      case '#':
+	savchar(ch);
+	/* Fall Through */
+      case EOF:
+      case '\n':
+      case ';':
+	return flags;
+
+      case '\r':
+	if (inchar() == '\n')
+	  return flags;
+	/* FALLTHROUGH */
+
+      default:
+	bad_prog(_(UNKNOWN_S_OPT));
+	/*NOTREACHED*/
+      }
+}
+
+
+
+/* read in a label for a `:', `b', or `t' command */
+static char *read_label P_((void));
+static char *
+read_label()
+{
+  struct buffer *b;
+  int ch;
+  char *ret;
+
+  b = init_buffer();
+  ch = in_nonblank();
+
+  while (ch != EOF && ch != '\n'
+	 && !ISBLANK(ch) && ch != ';' && ch != CLOSE_BRACE && ch != '#')
+    ch = add_then_next (b, ch);
+
+  savchar(ch);
+  add1_buffer(b, '\0');
+  ret = ck_strdup(get_buffer(b));
+  free_buffer(b);
+  return ret;
+}
+
+/* Store a label (or label reference) created by a `:', `b', or `t'
+   command so that the jump to/from the label can be backpatched after
+   compilation is complete, or a reference created by a `{' to be
+   backpatched when the corresponding `}' is found.  */
+static struct sed_label *setup_label
+  P_((struct sed_label *, countT, char *, const struct error_info *));
+static struct sed_label *
+setup_label(list, idx, name, err_info)
+  struct sed_label *list;
+  countT idx;
+  char *name;
+  const struct error_info *err_info;
+{
+  struct sed_label *ret = OB_MALLOC(&obs, 1, struct sed_label);
+  ret->v_index = idx;
+  ret->name = name;
+  if (err_info)
+    MEMCPY(&ret->err_info, err_info, sizeof (ret->err_info));
+  ret->next = list;
+  return ret;
+}
+
+static struct sed_label *release_label P_((struct sed_label *list_head));
+static struct sed_label *
+release_label(list_head)
+  struct sed_label *list_head;
+{
+  struct sed_label *ret;
+
+  if (!list_head)
+    return NULL;
+  ret = list_head->next;
+
+  FREE(list_head->name);
+
+#if 0
+  /* We use obstacks */
+  FREE(list_head);
+#endif
+  return ret;
+}
+
+static struct replacement *new_replacement P_((char *, size_t,
+					       enum replacement_types));
+static struct replacement *
+new_replacement(text, length, type)
+  char *text;
+  size_t length;
+  enum replacement_types type;
+{
+  struct replacement *r = OB_MALLOC(&obs, 1, struct replacement);
+
+  r->prefix = text;
+  r->prefix_length = length;
+  r->subst_id = -1;
+  r->repl_type = type;
+
+  /* r-> next = NULL; */
+  return r;
+}
+
+static void setup_replacement P_((struct subst *, const char *, size_t));
+static void
+setup_replacement(sub, text, length)
+     struct subst *sub;
+     const char *text;
+     size_t length;
+{
+  char *base;
+  char *p;
+  char *text_end;
+  enum replacement_types repl_type = REPL_ASIS, save_type = REPL_ASIS;
+  struct replacement root;
+  struct replacement *tail;
+
+  sub->max_id = 0;
+  base = MEMDUP(text, length, char);
+  length = normalize_text(base, length, TEXT_REPLACEMENT);
+
+  text_end = base + length;
+  tail = &root;
+
+  for (p=base; p<text_end; ++p)
+    {
+      if (*p == '\\')
+	{
+	  /* Preceding the backslash may be some literal text: */
+	  tail = tail->next =
+	    new_replacement(base, CAST(size_t)(p - base), repl_type);
+
+	  repl_type = save_type;
+
+	  /* Skip the backslash and look for a numeric back-reference,
+	     or a case-munging escape if not in POSIX mode: */
+	  ++p;
+	  if (p < text_end && (posixicity != POSIXLY_BASIC || ISDIGIT (*p)))
+	    switch (*p)
+	      {
+	      case '0': case '1': case '2': case '3': case '4': 
+	      case '5': case '6': case '7': case '8': case '9': 
+		tail->subst_id = *p - '0';
+		if (sub->max_id < tail->subst_id)
+		  sub->max_id = tail->subst_id;
+		break;
+
+	      case 'L':
+		repl_type = REPL_LOWERCASE;
+		save_type = REPL_LOWERCASE;
+		break;
+
+	      case 'U':
+		repl_type = REPL_UPPERCASE;
+		save_type = REPL_UPPERCASE;
+		break;
+		
+	      case 'E':
+		repl_type = REPL_ASIS;
+		save_type = REPL_ASIS;
+		break;
+
+	      case 'l':
+		save_type = repl_type;
+		repl_type |= REPL_LOWERCASE_FIRST;
+		break;
+
+	      case 'u':
+		save_type = repl_type;
+		repl_type |= REPL_UPPERCASE_FIRST;
+		break;
+		
+	      default:
+		p[-1] = *p;
+		++tail->prefix_length;
+	      }
+
+	  base = p + 1;
+	}
+      else if (*p == '&')
+	{
+	  /* Preceding the ampersand may be some literal text: */
+	  tail = tail->next =
+	    new_replacement(base, CAST(size_t)(p - base), repl_type);
+
+	  repl_type = save_type;
+	  tail->subst_id = 0;
+	  base = p + 1;
+	}
+  }
+  /* There may be some trailing literal text: */
+  if (base < text_end)
+    tail = tail->next =
+      new_replacement(base, CAST(size_t)(text_end - base), repl_type);
+
+  tail->next = NULL;
+  sub->replacement = root.next;
+}
+
+static void read_text P_((struct text_buf *buf, int leadin_ch));
+static void
+read_text(buf, leadin_ch)
+  struct text_buf *buf;
+  int leadin_ch;
+{
+  int ch;
+
+  /* Should we start afresh (as opposed to continue a partial text)? */
+  if (buf)
+    {
+      if (pending_text)
+	free_buffer(pending_text);
+      pending_text = init_buffer();
+      buf->text = NULL;
+      buf->text_length = 0;
+      old_text_buf = buf;
+    }
+  /* assert(old_text_buf != NULL); */
+
+  if (leadin_ch == EOF)
+    return;
+
+  if (leadin_ch != '\n')
+    add1_buffer(pending_text, leadin_ch);
+
+  ch = inchar();
+  while (ch != EOF && ch != '\n')
+    {
+      if (ch == '\\')
+	{
+	  ch = inchar();
+	  if (ch != EOF)
+	    add1_buffer (pending_text, '\\');
+	}
+
+      if (ch == EOF)
+	{
+	  add1_buffer (pending_text, '\n');
+	  return;
+	}
+
+      ch = add_then_next (pending_text, ch);
+    }
+
+  add1_buffer(pending_text, '\n');
+  if (!buf)
+    buf = old_text_buf;
+  buf->text_length = normalize_text (get_buffer (pending_text),
+				     size_buffer (pending_text), TEXT_BUFFER);
+  buf->text = MEMDUP(get_buffer(pending_text), buf->text_length, char);
+  free_buffer(pending_text);
+  pending_text = NULL;
+}
+
+
+
+/* Try to read an address for a sed command.  If it succeeds,
+   return non-zero and store the resulting address in `*addr'.
+   If the input doesn't look like an address read nothing
+   and return zero.  */
+static bool compile_address P_((struct addr *addr, int ch));
+static bool
+compile_address(addr, ch)
+  struct addr *addr;
+  int ch;
+{
+  addr->addr_type = ADDR_IS_NULL;
+  addr->addr_step = 0;
+  addr->addr_number = ~(countT)0;  /* extremely unlikely to ever match */
+  addr->addr_regex = NULL;
+
+  if (ch == '/' || ch == '\\')
+    {
+      int flags = 0;
+      struct buffer *b;
+      addr->addr_type = ADDR_IS_REGEX;
+      if (ch == '\\')
+	ch = inchar();
+      if ( !(b = match_slash(ch, true)) )
+	bad_prog(_(UNTERM_ADDR_RE));
+
+      for(;;)
+	{
+	  ch = in_nonblank();
+          switch(ch)
+	    {
+	    case 'I':	/* GNU extension */
+	      flags |= REG_ICASE;
+	      break;
+
+#ifdef REG_PERL
+	    case 'S':	/* GNU extension */
+	      if (extended_regexp_flags & REG_PERL)
+		flags |= REG_DOTALL;
+	      break;
+
+	    case 'X':	/* GNU extension */
+	      if (extended_regexp_flags & REG_PERL)
+		flags |= REG_EXTENDED;
+	      break;
+#endif
+
+	    case 'M':	/* GNU extension */
+	      flags |= REG_NEWLINE;
+	      break;
+
+	    default:
+	      savchar (ch);
+	      addr->addr_regex = compile_regex (b, flags, 0);
+	      free_buffer(b);
+	      return true;
+	    }
+	}
+    }
+  else if (ISDIGIT(ch))
+    {
+      addr->addr_number = in_integer(ch);
+      addr->addr_type = ADDR_IS_NUM;
+      ch = in_nonblank();
+      if (ch != '~')
+	{
+	  savchar(ch);
+	}
+      else
+	{
+	  countT step = in_integer(in_nonblank());
+	  if (step > 0)
+	    {
+	      addr->addr_step = step;
+	      addr->addr_type = ADDR_IS_NUM_MOD;
+	    }
+	}
+    }
+  else if (ch == '+' || ch == '~')
+    {
+      addr->addr_step = in_integer(in_nonblank());
+      if (addr->addr_step==0)
+	; /* default to ADDR_IS_NULL; forces matching to stop on next line */
+      else if (ch == '+')
+	addr->addr_type = ADDR_IS_STEP;
+      else
+	addr->addr_type = ADDR_IS_STEP_MOD;
+    }
+  else if (ch == '$')
+    {
+      addr->addr_type = ADDR_IS_LAST;
+    }
+  else
+    return false;
+
+  return true;
+}
+
+/* Read a program (or a subprogram within `{' `}' pairs) in and store
+   the compiled form in `*vector'.  Return a pointer to the new vector.  */
+static struct vector *compile_program P_((struct vector *));
+static struct vector *
+compile_program(vector)
+  struct vector *vector;
+{
+  struct sed_cmd *cur_cmd;
+  struct buffer *b;
+  int ch;
+
+  if (!vector)
+    {
+      vector = MALLOC(1, struct vector);
+      vector->v = NULL;
+      vector->v_allocated = 0;
+      vector->v_length = 0;
+
+      obstack_init (&obs);
+    }
+  if (pending_text)
+    read_text(NULL, '\n');
+
+  for (;;)
+    {
+      struct addr a;
+
+      while ((ch=inchar()) == ';' || ISSPACE(ch))
+	;
+      if (ch == EOF)
+	break;
+
+      cur_cmd = next_cmd_entry(&vector);
+      if (compile_address(&a, ch))
+	{
+	  if (a.addr_type == ADDR_IS_STEP
+	      || a.addr_type == ADDR_IS_STEP_MOD)
+	    bad_prog(_(BAD_STEP));
+
+	  cur_cmd->a1 = MEMDUP(&a, 1, struct addr);
+	  ch = in_nonblank();
+	  if (ch == ',')
+	    {
+	      if (!compile_address(&a, in_nonblank()))
+		bad_prog(_(BAD_COMMA));
+
+	      cur_cmd->a2 = MEMDUP(&a, 1, struct addr);
+	      ch = in_nonblank();
+	    }
+
+	  if (cur_cmd->a1->addr_type == ADDR_IS_NUM
+	      && cur_cmd->a1->addr_number == 0
+	      && (!cur_cmd->a2 || cur_cmd->a2->addr_type != ADDR_IS_REGEX))
+	    bad_prog(_(INVALID_LINE_0));
+	}
+      if (ch == '!')
+	{
+	  cur_cmd->addr_bang = true;
+	  ch = in_nonblank();
+	  if (ch == '!')
+	    bad_prog(_(BAD_BANG));
+	}
+
+      /* Do not accept extended commands in --posix mode.  Also,
+	 a few commands only accept one address in that mode.  */
+      if (posixicity == POSIXLY_BASIC)
+	switch (ch)
+	  {
+	    case 'v': case 'L': case 'Q': case 'T':
+	    case 'R': case 'W':
+	      bad_command(ch);
+
+	    case 'a': case 'i': case 'l':
+	    case '=': case 'r':
+	      if (cur_cmd->a2)
+	        bad_prog(_(ONE_ADDR));
+	  }
+
+      cur_cmd->cmd = ch;
+      switch (ch)
+	{
+	case '#':
+	  if (cur_cmd->a1)
+	    bad_prog(_(NO_SHARP_ADDR));
+	  ch = inchar();
+	  if (ch=='n' && first_script && cur_input.line < 2)
+	    if (   (prog.base && prog.cur==2+prog.base)
+		|| (prog.file && !prog.base && 2==ftell(prog.file)))
+	      no_default_output = true;
+	  while (ch != EOF && ch != '\n')
+	    ch = inchar();
+	  continue;	/* restart the for (;;) loop */
+
+	case 'v':
+	  /* This is an extension.  Programs needing GNU sed might start
+	   * with a `v' command so that other seds will stop.
+	   * We compare the version and ignore POSIXLY_CORRECT.
+	   */
+	  {
+	    char *version = read_label ();
+	    char *compared_version;
+	    compared_version = (*version == '\0') ? "4.0" : version;
+	    if (strverscmp (compared_version, SED_FEATURE_VERSION) > 0)
+	      bad_prog(_(ANCIENT_VERSION));
+
+	    free (version);
+	    posixicity = POSIXLY_EXTENDED;
+	  }
+	  continue;
+
+	case '{':
+	  blocks = setup_label(blocks, vector->v_length, NULL, &cur_input);
+	  cur_cmd->addr_bang = !cur_cmd->addr_bang;
+	  break;
+
+	case '}':
+	  if (!blocks)
+	    bad_prog(_(EXCESS_CLOSE_BRACE));
+	  if (cur_cmd->a1)
+	    bad_prog(_(NO_CLOSE_BRACE_ADDR));
+	  ch = in_nonblank();
+	  if (ch == CLOSE_BRACE || ch == '#')
+	    savchar(ch);
+	  else if (ch != EOF && ch != '\n' && ch != ';')
+	    bad_prog(_(EXCESS_JUNK));
+
+	  vector->v[blocks->v_index].x.jump_index = vector->v_length;
+	  blocks = release_label(blocks);	/* done with this entry */
+	  break;
+
+	case 'e':
+	  ch = in_nonblank();
+	  if (ch == EOF || ch == '\n')
+	    {
+	      cur_cmd->x.cmd_txt.text_length = 0;
+	      break;
+	    }
+	  else
+	    goto read_text_to_slash;
+
+	case 'a':
+	case 'i':
+	case 'c':
+	  ch = in_nonblank();
+
+	read_text_to_slash:
+	  if (ch == EOF)
+	    bad_prog(_(EXPECTED_SLASH));
+	      
+	  if (ch == '\\')
+	    ch = inchar();
+	  else
+	    {
+	      savchar(ch);
+	      ch = '\n';
+	    }
+
+	  read_text(&cur_cmd->x.cmd_txt, ch);
+	  break;
+
+	case ':':
+	  if (cur_cmd->a1)
+	    bad_prog(_(NO_COLON_ADDR));
+	  labels = setup_label(labels, vector->v_length, read_label(), NULL);
+	  break;
+	
+	case 'T':
+	case 'b':
+	case 't':
+	  jumps = setup_label(jumps, vector->v_length, read_label(), NULL);
+	  break;
+
+	case 'Q':
+	case 'q':
+	  if (cur_cmd->a2)
+	    bad_prog(_(ONE_ADDR));
+	  /* Fall through */
+
+	case 'L':
+	case 'l':
+	  ch = in_nonblank();
+	  if (ISDIGIT(ch)) 
+	    {
+	      cur_cmd->x.int_arg = in_integer(ch);
+	      ch = in_nonblank();
+	    }
+	  else
+	    cur_cmd->x.int_arg = -1;
+
+	  if (ch == CLOSE_BRACE || ch == '#')
+	    savchar(ch);
+	  else if (ch != EOF && ch != '\n' && ch != ';')
+	    bad_prog(_(EXCESS_JUNK));
+
+	  break;
+
+	case '=':
+	case 'd':
+	case 'D':
+	case 'g':
+	case 'G':
+	case 'h':
+	case 'H':
+	case 'n':
+	case 'N':
+	case 'p':
+	case 'P':
+	case 'x':
+	  ch = in_nonblank();
+	  if (ch == CLOSE_BRACE || ch == '#')
+	    savchar(ch);
+	  else if (ch != EOF && ch != '\n' && ch != ';')
+	    bad_prog(_(EXCESS_JUNK));
+	  break;
+
+	case 'r':
+	  b = read_filename();
+	  cur_cmd->x.fname = ck_strdup(get_buffer(b));
+	  free_buffer(b);
+	  break;
+
+        case 'R':
+	  cur_cmd->x.fp = get_openfile(&file_read, "r", false)->fp;
+	  break;
+
+        case 'W':
+	case 'w':
+	  cur_cmd->x.outf = get_openfile(&file_write, "w", true);
+	  break;
+
+	case 's':
+	  {
+	    struct buffer *b2;
+	    int flags;
+	    int slash;
+
+	    slash = inchar();
+	    if ( !(b  = match_slash(slash, true)) )
+	      bad_prog(_(UNTERM_S_CMD));
+	    if ( !(b2 = match_slash(slash, false)) )
+	      bad_prog(_(UNTERM_S_CMD));
+
+	    cur_cmd->x.cmd_subst = OB_MALLOC(&obs, 1, struct subst);
+	    setup_replacement(cur_cmd->x.cmd_subst,
+			      get_buffer(b2), size_buffer(b2));
+	    free_buffer(b2);
+
+	    flags = mark_subst_opts(cur_cmd->x.cmd_subst);
+	    cur_cmd->x.cmd_subst->regx =
+	      compile_regex(b, flags, cur_cmd->x.cmd_subst->max_id + 1);
+	    free_buffer(b);
+	  }
+	  break;
+
+	case 'y':
+	  {
+	    size_t len, dest_len;
+	    int slash;
+	    struct buffer *b2;
+            char *src_buf, *dest_buf;
+  
+	    slash = inchar();
+	    if ( !(b = match_slash(slash, false)) )
+	      bad_prog(_(UNTERM_Y_CMD));
+            src_buf = get_buffer(b);
+	    len = normalize_text(src_buf, size_buffer (b), TEXT_BUFFER);
+
+            if ( !(b2 = match_slash(slash, false)) )
+ 	      bad_prog(_(UNTERM_Y_CMD));
+            dest_buf = get_buffer(b2);
+	    dest_len = normalize_text(dest_buf, size_buffer (b2), TEXT_BUFFER);
+
+            if (mb_cur_max > 1)
+	      {
+                int i, j, idx, src_char_num;
+                size_t *src_lens = MALLOC(len, size_t);
+                char **trans_pairs;
+                size_t mbclen;
+                mbstate_t cur_stat;
+
+                /* Enumerate how many character the source buffer has.  */
+                memset(&cur_stat, 0, sizeof(mbstate_t));
+                for (i = 0, j = 0; i < len;)
+                  {
+                    mbclen = MBRLEN (src_buf + i, len - i, &cur_stat);
+                    /* An invalid sequence, or a truncated multibyte character.
+                       We treat it as a singlebyte character.  */
+                    if (mbclen == (size_t) -1 || mbclen == (size_t) -2
+                        || mbclen == 0)
+                      mbclen = 1;
+                    src_lens[j++] = mbclen;
+                    i += mbclen;
+                  }
+                src_char_num = j;
+
+                memset(&cur_stat, 0, sizeof(mbstate_t));
+                idx = 0;
+
+                /* trans_pairs = {src(0), dest(0), src(1), dest(1), ..., NULL}
+                     src(i) : pointer to i-th source character.
+                     dest(i) : pointer to i-th destination character.
+                     NULL : terminator */
+                trans_pairs = MALLOC(2 * src_char_num + 1, char*);
+                cur_cmd->x.translatemb = trans_pairs;
+                for (i = 0; i < src_char_num; i++)
+                  {
+                    if (idx >= dest_len)
+                      bad_prog(_(Y_CMD_LEN));
+
+                    /* Set the i-th source character.  */
+                    trans_pairs[2 * i] = MALLOC(src_lens[i] + 1, char);
+                    strncpy(trans_pairs[2 * i], src_buf, src_lens[i]);
+                    trans_pairs[2 * i][src_lens[i]] = '\0';
+                    src_buf += src_lens[i]; /* Forward to next character.  */
+
+                    /* Fetch the i-th destination character.  */
+                    mbclen = MBRLEN (dest_buf + idx, dest_len - idx, &cur_stat);
+                    /* An invalid sequence, or a truncated multibyte character.
+                       We treat it as a singlebyte character.  */
+                    if (mbclen == (size_t) -1 || mbclen == (size_t) -2
+                        || mbclen == 0)
+                      mbclen = 1;
+
+                    /* Set the i-th destination character.  */
+                    trans_pairs[2 * i + 1] = MALLOC(mbclen + 1, char);
+                    strncpy(trans_pairs[2 * i + 1], dest_buf + idx, mbclen);
+                    trans_pairs[2 * i + 1][mbclen] = '\0';
+                    idx += mbclen; /* Forward to next character.  */
+                  }
+                trans_pairs[2 * i] = NULL;
+                if (idx != dest_len)
+                  bad_prog(_(Y_CMD_LEN));
+              }
+            else
+              {
+	        char *translate = OB_MALLOC(&obs, YMAP_LENGTH, char);
+                unsigned char *ustring = CAST(unsigned char *)src_buf;
+
+		if (len != dest_len)
+                  bad_prog(_(Y_CMD_LEN));
+
+	        for (len = 0; len < YMAP_LENGTH; len++)
+	          translate[len] = len;
+
+                while (dest_len--)
+                  translate[(unsigned char)*ustring++] = *dest_buf++;
+
+	        cur_cmd->x.translate = translate;
+	      }
+
+            if ((ch = in_nonblank()) != EOF && ch != '\n' && ch != ';')
+              bad_prog(_(EXCESS_JUNK));
+
+            free_buffer(b);
+            free_buffer(b2);
+	  }
+	break;
+
+	case EOF:
+	  bad_prog(_(NO_COMMAND));
+	  /*NOTREACHED*/
+
+	default:
+	  bad_command (ch);
+	  /*NOTREACHED*/
+	}
+
+      /* this is buried down here so that "continue" statements will miss it */
+      ++vector->v_length;
+    }
+  return vector;
+}
+
+
+
+/* deal with \X escapes */
+size_t
+normalize_text(buf, len, buftype)
+  char *buf;
+  size_t len;
+  enum text_types buftype;
+{
+  const char *bufend = buf + len;
+  char *p = buf;
+  char *q = buf;
+
+  /* This variable prevents normalizing text within bracket
+     subexpressions when conforming to POSIX.  If 0, we
+     are not within a bracket expression.  If -1, we are within a
+     bracket expression but are not within [.FOO.], [=FOO=],
+     or [:FOO:].  Otherwise, this is the '.', '=', or ':'
+     respectively within these three types of subexpressions.  */
+  int bracket_state = 0;
+
+  int mbclen;
+  mbstate_t cur_stat;
+  memset(&cur_stat, 0, sizeof(mbstate_t));
+
+  while (p < bufend)
+    {
+      int c;
+      mbclen = MBRLEN (p, bufend - p, &cur_stat);
+      if (mbclen != 1)
+	{
+          /* An invalid sequence, or a truncated multibyte character.
+             We treat it as a singlebyte character.  */
+          if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0)
+            mbclen = 1;
+
+          memmove (q, p, mbclen);
+          q += mbclen;
+          p += mbclen;
+	  continue;
+	}
+
+      if (*p == '\\' && p+1 < bufend && bracket_state == 0)
+	switch ( (c = *++p) )
+	  {
+#if defined __STDC__ && __STDC__-0
+	  case 'a': *q++ = '\a'; p++; continue;
+#else /* Not STDC; we'll just assume ASCII */
+	  case 'a': *q++ = '\007'; p++; continue;
+#endif
+	  /* case 'b': *q++ = '\b'; p++; continue; --- conflicts with \b RE */
+	  case 'f': *q++ = '\f'; p++; continue;
+	  case '\n': /*fall through */
+	  case 'n': *q++ = '\n'; p++; continue;
+	  case 'r': *q++ = '\r'; p++; continue;
+	  case 't': *q++ = '\t'; p++; continue;
+	  case 'v': *q++ = '\v'; p++; continue;
+
+	  case 'd': /* decimal byte */
+	    p = convert_number(q, p+1, bufend, 10, 3, 'd');
+	    q++;
+	    continue;
+
+	  case 'x': /* hexadecimal byte */
+	    p = convert_number(q, p+1, bufend, 16, 2, 'x');
+	    q++;
+	    continue;
+
+#ifdef REG_PERL
+	  case '0': case '1': case '2': case '3':
+	  case '4': case '5': case '6': case '7':
+	    if ((extended_regexp_flags & REG_PERL)
+		&& p+1 < bufend
+		&& p[1] >= '0' && p[1] <= '9')
+	      {
+		p = convert_number(q, p, bufend, 8, 3, *p);
+		q++;
+	      }
+	    else
+	      {
+		/* we just pass the \ up one level for interpretation */
+	        if (buftype != TEXT_BUFFER)
+		  *q++ = '\\';
+	      }
+
+	    continue;
+
+	  case 'o': /* octal byte */
+	    if (!(extended_regexp_flags & REG_PERL))
+	      {
+	        p = convert_number(q, p+1, bufend,  8, 3, 'o');
+		q++;
+	      }
+	    else
+	      {
+	        /* we just pass the \ up one level for interpretation */
+	        if (buftype != TEXT_BUFFER)
+		  *q++ = '\\';
+	      }
+	    
+	    continue;
+#else
+	  case 'o': /* octal byte */
+	    p = convert_number(q, p+1, bufend,  8, 3, 'o');
+	    q++;
+	    continue;
+#endif
+
+	  case 'c':
+	    if (++p < bufend)
+	      {
+		*q++ = toupper(*p) ^ 0x40;
+		p++;
+		continue;
+	      }
+	    else
+	      {
+	        /* we just pass the \ up one level for interpretation */
+	        if (buftype != TEXT_BUFFER)
+		  *q++ = '\\';
+	        continue;
+	      }
+
+	  default:
+	    /* we just pass the \ up one level for interpretation */
+	    if (buftype != TEXT_BUFFER)
+	      *q++ = '\\';
+	    break;
+	  }
+      else if (buftype == TEXT_REGEX && posixicity != POSIXLY_EXTENDED)
+        switch (*p)
+          {
+          case '[':
+            if (!bracket_state)
+              bracket_state = -1;
+            break;
+ 
+	  case ':':
+	  case '.':
+	  case '=':
+            if (bracket_state == -1 && p[-1] == '[')
+              bracket_state = *p;
+            break;
+
+          case ']':
+            if (bracket_state == 0)
+	      ;
+            else if (bracket_state == -1)
+              bracket_state = 0;
+            else if (p[-2] != bracket_state && p[-1] == bracket_state)
+              bracket_state = -1;
+            break;
+          }
+
+      *q++ = *p++;
+    }
+    return (size_t)(q - buf);
+}
+
+
+/* `str' is a string (from the command line) that contains a sed command.
+   Compile the command, and add it to the end of `cur_program'. */
+struct vector *
+compile_string(cur_program, str, len)
+  struct vector *cur_program;
+  char *str;
+  size_t len;
+{
+  static countT string_expr_count = 0;
+  struct vector *ret;
+
+  prog.file = NULL;
+  prog.base = CAST(unsigned char *)str;
+  prog.cur = prog.base;
+  prog.end = prog.cur + len;
+
+  cur_input.line = 0;
+  cur_input.name = NULL;
+  cur_input.string_expr_count = ++string_expr_count;
+
+  ret = compile_program(cur_program);
+  prog.base = NULL;
+  prog.cur = NULL;
+  prog.end = NULL;
+
+  first_script = false;
+  return ret;
+}
+
+/* `cmdfile' is the name of a file containing sed commands.
+   Read them in and add them to the end of `cur_program'.
+ */
+struct vector *
+compile_file(cur_program, cmdfile)
+  struct vector *cur_program;
+  const char *cmdfile;
+{
+  size_t len;
+  struct vector *ret;
+
+  prog.file = stdin;
+  if (cmdfile[0] != '-' || cmdfile[1] != '\0')
+    prog.file = ck_fopen(cmdfile, "rt", true);
+
+  cur_input.line = 1;
+  cur_input.name = cmdfile;
+  cur_input.string_expr_count = 0;
+
+  ret = compile_program(cur_program);
+  if (prog.file != stdin)
+    ck_fclose(prog.file);
+  prog.file = NULL;
+
+  first_script = false;
+  return ret;
+}
+
+/* Make any checks which require the whole program to have been read.
+   In particular: this backpatches the jump targets.
+   Any cleanup which can be done after these checks is done here also.  */
+void
+check_final_program(program)
+  struct vector *program;
+{
+  struct sed_label *go;
+  struct sed_label *lbl;
+
+  /* do all "{"s have a corresponding "}"? */
+  if (blocks)
+    {
+      /* update info for error reporting: */
+      MEMCPY(&cur_input, &blocks->err_info, sizeof (cur_input));
+      bad_prog(_(EXCESS_OPEN_BRACE));
+    }
+
+  /* was the final command an unterminated a/c/i command? */
+  if (pending_text)
+    {
+      old_text_buf->text_length = size_buffer(pending_text);
+      old_text_buf->text = MEMDUP(get_buffer(pending_text),
+				  old_text_buf->text_length, char);
+      free_buffer(pending_text);
+      pending_text = NULL;
+    }
+
+  for (go = jumps; go; go = release_label(go))
+    {
+      for (lbl = labels; lbl; lbl = lbl->next)
+	if (strcmp(lbl->name, go->name) == 0)
+	  break;
+      if (lbl)
+	{
+	  program->v[go->v_index].x.jump_index = lbl->v_index;
+	}
+      else
+	{
+	  if (*go->name)
+	    panic(_("can't find label for jump to `%s'"), go->name);
+	  program->v[go->v_index].x.jump_index = program->v_length;
+	}
+    }
+  jumps = NULL;
+
+  for (lbl = labels; lbl; lbl = release_label(lbl))
+    ;
+  labels = NULL;
+
+  /* There is no longer a need to track file names: */
+  {
+    struct output *p;
+
+    for (p=file_read; p; p=p->link)
+      if (p->name)
+	{
+	  FREE(p->name);
+	  p->name = NULL;
+	}
+
+    for (p=file_write; p; p=p->link)
+      if (p->name)
+	{
+	  FREE(p->name);
+	  p->name = NULL;
+	}
+  }
+}
+
+/* Rewind all resources which were allocated in this module. */
+void
+rewind_read_files()
+{
+  struct output *p;
+
+  for (p=file_read; p; p=p->link)
+    if (p->fp)
+      rewind(p->fp);
+}
+
+/* Release all resources which were allocated in this module. */
+void
+finish_program(program)
+  struct vector *program;
+{
+  /* close all files... */
+  {
+    struct output *p, *q;
+
+    for (p=file_read; p; p=q)
+      {
+	if (p->fp)
+	  ck_fclose(p->fp);
+	q = p->link;
+#if 0
+	/* We use obstacks. */
+	FREE(p);
+#endif
+      }
+
+    for (p=file_write; p; p=q)
+      {
+	if (p->fp)
+	  ck_fclose(p->fp);
+	q = p->link;
+#if 0
+	/* We use obstacks. */
+	FREE(p);
+#endif
+      }
+    file_read = file_write = NULL;
+  }
+
+#ifdef DEBUG_LEAKS
+  obstack_free (&obs, NULL);
+#endif /*DEBUG_LEAKS*/
+}
Index: /tags/kBuild-0.1.4/src/sed/sed/execute.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/execute.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/execute.c	(revision 1780)
@@ -0,0 +1,1767 @@
+/*  GNU SED, a batch stream editor.
+    Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003,2004,2005,2006
+    Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#undef EXPERIMENTAL_DASH_N_OPTIMIZATION	/*don't use -- is very buggy*/
+#define INITIAL_BUFFER_SIZE	50
+#define FREAD_BUFFER_SIZE	8192
+
+#include "sed.h"
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef __GNUC__
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__-0 >= 7)
+   /* silence warning about unused parameter even for "gcc -W -Wunused" */
+#  define UNUSED	__attribute__((unused))
+# endif
+#endif
+#ifndef UNUSED
+# define UNUSED
+#endif
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#else
+# include <string.h>
+#endif /*HAVE_STRINGS_H*/
+#ifdef HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#ifndef HAVE_STRCHR
+# define strchr index
+# define strrchr rindex
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <sys/stat.h>
+
+
+
+/* Sed operates a line at a time. */
+struct line {
+  char *text;		/* Pointer to line allocated by malloc. */
+  char *active;		/* Pointer to non-consumed part of text. */
+  size_t length;	/* Length of text (or active, if used). */
+  size_t alloc;		/* Allocated space for active. */
+  bool chomped;		/* Was a trailing newline dropped? */
+#ifdef HAVE_MBRTOWC
+  mbstate_t mbstate;
+#endif
+};
+
+/* A queue of text to write out at the end of a cycle
+   (filled by the "a", "r" and "R" commands.) */
+struct append_queue {
+  const char *fname;
+  char *text;
+  size_t textlen;
+  struct append_queue *next;
+  bool free;
+};
+
+/* State information for the input stream. */
+struct input {
+  /* The list of yet-to-be-opened files.  It is invalid for file_list
+     to be NULL.  When *file_list is NULL we are currently processing
+     the last file.  */
+
+  char **file_list;
+
+  /* Count of files we failed to open. */
+  countT bad_count;	    
+
+  /* Current input line number (over all files).  */
+  countT line_number;	    
+
+  /* True if we'll reset line numbers and addresses before
+     starting to process the next (possibly the first) file.  */
+  bool reset_at_next_file;
+
+  /* Function to read one line.  If FP is NULL, read_fn better not
+     be one which uses fp; in particular, read_always_fail() is
+     recommended. */
+  bool (*read_fn) P_((struct input *));	/* read one line */
+
+  char *out_file_name;
+
+  const char *in_file_name;
+
+  /* if NULL, none of the following are valid */
+  FILE *fp;
+
+  bool no_buffering;
+};
+
+
+/* Have we done any replacements lately?  This is used by the `t' command. */
+static bool replaced = false;
+
+/* The current output file (stdout if -i is not being used. */
+static struct output output_file;
+
+/* The `current' input line. */
+static struct line line;
+
+/* An input line used to accumulate the result of the s and e commands. */
+static struct line s_accum;
+
+/* An input line that's been stored by later use by the program */
+static struct line hold;
+
+/* The buffered input look-ahead.  The only field that should be
+   used outside of read_mem_line() or line_init() is buffer.length. */
+static struct line buffer;
+
+static struct append_queue *append_head = NULL;
+static struct append_queue *append_tail = NULL;
+
+
+
+#ifdef BOOTSTRAP
+/* We can't be sure that the system we're boostrapping on has
+   memchr(), and ../lib/memchr.c requires configuration knowledge
+   about how many bits are in a `long'.  This implementation
+   is far from ideal, but it should get us up-and-limping well
+   enough to run the configure script, which is all that matters.
+*/
+# ifdef memchr
+#  undef memchr
+# endif
+# define memchr bootstrap_memchr
+
+static VOID *bootstrap_memchr P_((const VOID *s, int c, size_t n));
+static VOID *
+bootstrap_memchr(s, c, n)
+  const VOID *s;
+  int c;
+  size_t n;
+{
+  char *p;
+
+  for (p=(char *)s; n-- > 0; ++p)
+    if (*p == c)
+      return p;
+  return CAST(VOID *)0;
+}
+#endif /*BOOTSTRAP*/
+
+/* increase a struct line's length, making some attempt at
+   keeping realloc() calls under control by padding for future growth.  */
+static void resize_line P_((struct line *, size_t));
+static void
+resize_line(lb, len)
+  struct line *lb;
+  size_t len;
+{
+  int inactive;
+  inactive = lb->active - lb->text;
+
+  /* If the inactive part has got to more than two thirds of the buffer,
+   * remove it. */
+  if (inactive > lb->alloc * 2)
+    {
+      MEMMOVE(lb->text, lb->active, lb->length);
+      lb->alloc += lb->active - lb->text;
+      lb->active = lb->text;
+      inactive = 0;
+
+      if (lb->alloc > len)
+	return;
+    }
+
+  lb->alloc *= 2;
+  if (lb->alloc < len)
+    lb->alloc = len;
+  if (lb->alloc < INITIAL_BUFFER_SIZE)
+    lb->alloc = INITIAL_BUFFER_SIZE;
+    
+  lb->text = REALLOC(lb->text, inactive + lb->alloc, char);
+  lb->active = lb->text + inactive;
+}
+
+/* Append `length' bytes from `string' to the line `to'. */
+static void str_append P_((struct line *, const char *, size_t));
+static void
+str_append(to, string, length)
+  struct line *to;
+  const char *string;
+  size_t length;
+{
+  size_t new_length = to->length + length;
+
+  if (to->alloc < new_length)
+    resize_line(to, new_length);
+  MEMCPY(to->active + to->length, string, length);
+  to->length = new_length;
+
+#ifdef HAVE_MBRTOWC
+  if (mb_cur_max == 1)
+    return;
+
+  while (length)
+    {
+      int n = MBRLEN (string, length, &to->mbstate);
+
+      /* An invalid sequence is treated like a singlebyte character. */
+      if (n == -1)
+	{
+	  memset (&to->mbstate, 0, sizeof (to->mbstate));
+	  n = 1;
+	}
+
+      if (n > 0)
+	length -= n;
+      else
+	break;
+    }
+#endif
+}
+
+static void str_append_modified P_((struct line *, const char *, size_t,
+				    enum replacement_types));
+static void
+str_append_modified(to, string, length, type)
+  struct line *to;
+  const char *string;
+  size_t length;
+  enum replacement_types type;
+{
+  size_t old_length = to->length;
+  char *start, *end;
+
+  if (length == 0)
+    return;
+
+#ifdef HAVE_MBRTOWC
+  {
+    mbstate_t from_stat;
+
+    if (type == REPL_ASIS)
+      {
+	str_append(to, string, length);
+        return;
+      }
+
+    if (to->alloc - to->length < length * mb_cur_max)
+      resize_line(to, to->length + length * mb_cur_max);
+
+    MEMCPY (&from_stat, &to->mbstate, sizeof(mbstate_t));
+    while (length)
+      {
+	wchar_t wc;
+        int n = MBRTOWC (&wc, string, length, &from_stat);
+
+        /* An invalid sequence is treated like a singlebyte character. */
+        if (n == -1)
+          {
+            memset (&to->mbstate, 0, sizeof (from_stat));
+            n = 1;
+          }
+
+        if (n > 0)
+          string += n, length -= n;
+        else
+	  {
+	    /* Incomplete sequence, copy it manually.  */
+	    str_append(to, string, length);
+	    return;
+	  }
+
+	/* Convert the first character specially... */
+        if (type & (REPL_UPPERCASE_FIRST | REPL_LOWERCASE_FIRST))
+	  {
+            if (type & REPL_UPPERCASE_FIRST)
+              wc = towupper(wc);
+            else
+              wc = towlower(wc);
+
+            type &= ~(REPL_LOWERCASE_FIRST | REPL_UPPERCASE_FIRST);
+	    if (type == REPL_ASIS)
+	      {
+		n = WCRTOMB (to->active + to->length, wc, &to->mbstate);
+		to->length += n;
+		str_append(to, string, length);
+	        return;
+	      }
+          }
+
+        else if (type & REPL_UPPERCASE)
+          wc = towupper(wc);
+        else
+          wc = towlower(wc);
+
+	/* Copy the new wide character to the end of the string. */
+	n = WCRTOMB (to->active + to->length, wc, &to->mbstate);
+        to->length += n;
+	if (n == -1)
+	  {
+	    fprintf (stderr, "Case conversion produced an invalid character!");
+	    abort ();
+	  }
+      }
+  }
+#else
+  str_append(to, string, length);
+  start = to->active + old_length;
+  end = start + length;
+
+  /* Now do the required modifications.  First \[lu]... */
+  if (type & REPL_UPPERCASE_FIRST)
+    {
+      *start = toupper(*start);
+      start++;
+      type &= ~REPL_UPPERCASE_FIRST;
+    }
+  else if (type & REPL_LOWERCASE_FIRST)
+    {
+      *start = tolower(*start);
+      start++;
+      type &= ~REPL_LOWERCASE_FIRST;
+    }
+
+  if (type == REPL_ASIS)
+    return;
+
+  /* ...and then \[LU] */
+  if (type == REPL_UPPERCASE)
+    for (; start != end; start++)
+      *start = toupper(*start);
+  else
+    for (; start != end; start++)
+      *start = tolower(*start);
+#endif
+}
+
+/* initialize a "struct line" buffer */
+static void line_init P_((struct line *, size_t initial_size));
+static void
+line_init(buf, initial_size)
+  struct line *buf;
+  size_t initial_size;
+{
+  buf->text = MALLOC(initial_size, char);
+  buf->active = buf->text;
+  buf->alloc = initial_size;
+  buf->length = 0;
+  buf->chomped = true;
+
+#ifdef HAVE_MBRTOWC
+  memset (&buf->mbstate, 0, sizeof (buf->mbstate));
+#endif
+
+}
+
+/* Copy the contents of the line `from' into the line `to'.
+   This destroys the old contents of `to'. */
+static void line_copy P_((struct line *from, struct line *to));
+static void
+line_copy(from, to)
+  struct line *from;
+  struct line *to;
+{
+  /* Remove the inactive portion in the destination buffer. */
+  to->alloc += to->active - to->text;
+
+  if (to->alloc < from->length)
+    {
+      to->alloc *= 2;
+      if (to->alloc < from->length)
+	to->alloc = from->length;
+      if (to->alloc < INITIAL_BUFFER_SIZE)
+	to->alloc = INITIAL_BUFFER_SIZE;
+      /* Use FREE()+MALLOC() instead of REALLOC() to
+	 avoid unnecessary copying of old text. */
+      FREE(to->text);
+      to->text = MALLOC(to->alloc, char);
+    }
+
+  to->active = to->text;
+  to->length = from->length;
+  to->chomped = from->chomped;
+  MEMCPY(to->active, from->active, from->length);
+
+#ifdef HAVE_MBRTOWC
+  MEMCPY(&to->mbstate, &from->mbstate, sizeof (from->mbstate));
+#endif
+}
+
+/* Append the contents of the line `from' to the line `to'. */
+static void line_append P_((struct line *from, struct line *to));
+static void
+line_append(from, to)
+  struct line *from;
+  struct line *to;
+{
+  str_append(to, "\n", 1);
+  str_append(to, from->active, from->length);
+  to->chomped = from->chomped;
+
+#ifdef HAVE_MBRTOWC
+  MEMCPY (&to->mbstate, &from->mbstate, sizeof (from->mbstate));
+#endif
+}
+
+/* Exchange the contents of two "struct line" buffers. */
+static void line_exchange P_((struct line *, struct line *));
+static void
+line_exchange(a, b)
+  struct line *a;
+  struct line *b;
+{
+  struct line t;
+
+  MEMCPY(&t,  a, sizeof(struct line));
+  MEMCPY( a,  b, sizeof(struct line));
+  MEMCPY( b, &t, sizeof(struct line));
+}
+
+
+
+/* dummy function to simplify read_pattern_space() */
+static bool read_always_fail P_((struct input *));
+static bool
+read_always_fail(input)
+  struct input *input UNUSED;
+{
+  return false;
+}
+
+static bool read_file_line P_((struct input *));
+static bool
+read_file_line(input)
+  struct input *input;
+{
+  static char *b;
+  static size_t blen;
+
+  long result = ck_getline (&b, &blen, input->fp);
+  if (result <= 0)
+    return false;
+
+  /* Remove the trailing new-line that is left by getline. */
+  if (b[result - 1] == '\n')
+    --result;
+  else
+    line.chomped = false;
+
+  str_append(&line, b, result);
+  return true;
+}
+
+
+
+static inline void output_missing_newline P_((struct output *));
+static inline void
+output_missing_newline(outf)
+  struct output *outf;
+{
+  if (outf->missing_newline)
+    {
+      ck_fwrite("\n", 1, 1, outf->fp);
+      outf->missing_newline = false;
+    }
+}
+
+static inline void flush_output P_((FILE *));
+static inline void
+flush_output(fp)
+  FILE *fp;
+{
+#ifndef CONFIG_WITHOUT_O_OPT
+  if (fp != sed_stdout || unbuffered_output)
+#else
+  if (fp != stdout || unbuffered_output)
+#endif
+    ck_fflush(fp);
+}
+
+static void output_line P_((const char *, size_t, bool, struct output *));
+static void
+output_line(text, length, nl, outf)
+  const char *text;
+  size_t length;
+  bool nl;
+  struct output *outf;
+{
+  output_missing_newline(outf);
+
+  if (length)
+    ck_fwrite(text, 1, length, outf->fp);
+
+  if (nl)
+    ck_fwrite("\n", 1, 1, outf->fp);
+  else
+    outf->missing_newline = true;
+
+  flush_output(outf->fp);
+}
+
+static struct append_queue *next_append_slot P_((void));
+static struct append_queue *
+next_append_slot()
+{
+  struct append_queue *n = MALLOC(1, struct append_queue);
+
+  n->fname = NULL;
+  n->text = NULL;
+  n->textlen = 0;
+  n->next = NULL;
+  n->free = false;
+
+  if (append_tail)
+      append_tail->next = n;
+  else
+      append_head = n;
+  return append_tail = n;
+}
+
+static void release_append_queue P_((void));
+static void
+release_append_queue()
+{
+  struct append_queue *p, *q;
+
+  for (p=append_head; p; p=q)
+    {
+      if (p->free)
+        FREE(p->text);
+
+      q = p->next;
+      FREE(p);
+    }
+  append_head = append_tail = NULL;
+}
+
+static void dump_append_queue P_((void));
+static void
+dump_append_queue()
+{
+  struct append_queue *p;
+
+  output_missing_newline(&output_file);
+  for (p=append_head; p; p=p->next)
+    {
+      if (p->text)
+        ck_fwrite(p->text, 1, p->textlen, output_file.fp);
+
+      if (p->fname)
+	{
+	  char buf[FREAD_BUFFER_SIZE];
+	  size_t cnt;
+	  FILE *fp;
+
+	  /* "If _fname_ does not exist or cannot be read, it shall
+	     be treated as if it were an empty file, causing no error
+	     condition."  IEEE Std 1003.2-1992
+	     So, don't fail. */
+	  fp = ck_fopen(p->fname, "r", false);
+	  if (fp)
+	    {
+	      while ((cnt = ck_fread(buf, 1, sizeof buf, fp)) > 0)
+		ck_fwrite(buf, 1, cnt, output_file.fp);
+	      ck_fclose(fp);
+	    }
+	}
+    }
+
+  flush_output(output_file.fp);
+  release_append_queue();
+}
+
+
+
+/* Compute the name of the backup file for in-place editing */
+static char *get_backup_file_name P_((const char *));
+static char *
+get_backup_file_name(name)
+  const char *name;
+{
+  char *old_asterisk, *asterisk, *backup, *p;
+  int name_length = strlen(name), backup_length = strlen(in_place_extension);
+
+  /* Compute the length of the backup file */
+  for (asterisk = in_place_extension - 1, old_asterisk = asterisk + 1;
+       asterisk = strchr(old_asterisk, '*');
+       old_asterisk = asterisk + 1)
+    backup_length += name_length - 1;
+
+  p = backup = xmalloc(backup_length + 1);
+
+  /* Each iteration gobbles up to an asterisk */
+  for (asterisk = in_place_extension - 1, old_asterisk = asterisk + 1;
+       asterisk = strchr(old_asterisk, '*');
+       old_asterisk = asterisk + 1)
+    {
+      MEMCPY (p, old_asterisk, asterisk - old_asterisk);
+      p += asterisk - old_asterisk;
+      strcpy (p, name);
+      p += name_length;
+    }
+
+  /* Tack on what's after the last asterisk */
+  strcpy (p, old_asterisk);
+  return backup;
+}
+
+/* Initialize a struct input for the named file. */
+static void open_next_file P_((const char *name, struct input *));
+static void
+open_next_file(name, input)
+  const char *name;
+  struct input *input;
+{
+  buffer.length = 0;
+
+  if (name[0] == '-' && name[1] == '\0' && !in_place_extension)
+    {
+      clearerr(stdin);	/* clear any stale EOF indication */
+      input->fp = stdin;
+    }
+  else if ( ! (input->fp = ck_fopen(name, "r", false)) )
+    {
+      const char *ptr = strerror(errno);
+      fprintf(stderr, _("%s: can't read %s: %s\n"), myname, name, ptr);
+      input->read_fn = read_always_fail; /* a redundancy */
+      ++input->bad_count;
+      return;
+    }
+
+  input->read_fn = read_file_line;
+
+  if (in_place_extension)
+    {
+      int output_fd;
+      char *tmpdir = ck_strdup(name), *p;
+      struct stat st;
+
+      /* get the base name */
+      if (p = strrchr(tmpdir, '/'))
+	*(p + 1) = 0;
+      else
+	strcpy(tmpdir, ".");
+      
+      input->in_file_name = name;
+
+      if (isatty (fileno (input->fp)))
+        panic(_("couldn't edit %s: is a terminal"), input->in_file_name);
+
+      fstat (fileno (input->fp), &st);
+      if (!S_ISREG (st.st_mode))
+        panic(_("couldn't edit %s: not a regular file"), input->in_file_name);
+
+      output_file.fp = ck_mkstemp (&input->out_file_name, tmpdir, "sed");
+      output_file.missing_newline = false;
+      free (tmpdir);
+
+      if (!output_file.fp)
+        panic(_("couldn't open temporary file %s: %s"), input->out_file_name, strerror(errno));
+
+      output_fd = fileno (output_file.fp);
+#ifdef HAVE_FCHMOD
+      fchmod (output_fd, st.st_mode);
+#endif
+#ifdef HAVE_FCHOWN
+      if (fchown (output_fd, st.st_uid, st.st_gid) == -1)
+        fchown (output_fd, -1, st.st_gid);
+#endif
+    }
+  else
+#ifndef CONFIG_WITHOUT_O_OPT
+    output_file.fp = sed_stdout;
+#else
+    output_file.fp = stdout;
+#endif
+}
+
+
+/* Clean up an input stream that we are done with. */
+static void closedown P_((struct input *));
+static void
+closedown(input)
+  struct input *input;
+{
+  input->read_fn = read_always_fail;
+  if (!input->fp)
+    return;
+  if (input->fp != stdin) /* stdin can be reused on tty and tape devices */
+    ck_fclose(input->fp);
+
+  if (in_place_extension && output_file.fp != NULL)
+    {
+      ck_fclose (output_file.fp);
+      if (strcmp(in_place_extension, "*") != 0)
+        {
+          char *backup_file_name = get_backup_file_name(input->in_file_name);
+	  ck_rename (input->in_file_name, backup_file_name, input->out_file_name);
+          free (backup_file_name);
+	}
+
+      ck_rename (input->out_file_name, input->in_file_name, input->out_file_name);
+      free (input->out_file_name);
+    }
+
+  input->fp = NULL;
+}
+
+/* Reset range commands so that they are marked as non-matching */
+static void reset_addresses P_((struct vector *));
+static void
+reset_addresses(vec)
+     struct vector *vec;
+{
+  struct sed_cmd *cur_cmd;
+  int n;
+
+  for (cur_cmd = vec->v, n = vec->v_length; n--; cur_cmd++)
+    if (cur_cmd->a1
+	&& cur_cmd->a1->addr_type == ADDR_IS_NUM
+	&& cur_cmd->a1->addr_number == 0)
+      cur_cmd->range_state = RANGE_ACTIVE;
+    else
+      cur_cmd->range_state = RANGE_INACTIVE;
+}
+
+/* Read in the next line of input, and store it in the pattern space.
+   Return zero if there is nothing left to input. */
+static bool read_pattern_space P_((struct input *, struct vector *, bool));
+static bool
+read_pattern_space(input, the_program, append)
+  struct input *input;
+  struct vector *the_program;
+  bool append;
+{
+  if (append_head) /* redundant test to optimize for common case */
+    dump_append_queue();
+  replaced = false;
+  if (!append)
+    line.length = 0;
+  line.chomped = true;  /* default, until proved otherwise */
+
+  while ( ! (*input->read_fn)(input) )
+    {
+      closedown(input);
+
+      if (!*input->file_list)
+	return false;
+
+      if (input->reset_at_next_file)
+	{
+	  input->line_number = 0;
+	  reset_addresses (the_program);
+	  rewind_read_files ();
+
+	  /* If doing in-place editing, we will never append the
+	     new-line to this file; but if the output goes to stdout,
+	     we might still have to output the missing new-line.  */
+	  if (in_place_extension)
+	    output_file.missing_newline = false;
+
+	  input->reset_at_next_file = separate_files;
+	}
+
+      open_next_file (*input->file_list++, input);
+    }
+
+  ++input->line_number;
+  return true;
+}
+
+
+
+static bool last_file_with_data_p P_((struct input *));
+static bool
+last_file_with_data_p(input)
+  struct input *input;
+{
+  for (;;)
+    {
+      int ch;
+
+      closedown(input);
+      if (!*input->file_list)
+	return true;
+      open_next_file(*input->file_list++, input);
+      if (input->fp)
+	{
+	  if ((ch = getc(input->fp)) != EOF)
+	    {
+	      ungetc(ch, input->fp);
+	      return false;
+	    }
+	}
+    }
+}
+
+/* Determine if we match the `$' address. */
+static bool test_eof P_((struct input *));
+static bool
+test_eof(input)
+  struct input *input;
+{
+  int ch;
+
+  if (buffer.length)
+    return false;
+  if (!input->fp)
+    return separate_files || last_file_with_data_p(input);
+  if (feof(input->fp))
+    return separate_files || last_file_with_data_p(input);
+  if ((ch = getc(input->fp)) == EOF)
+    return separate_files || last_file_with_data_p(input);
+  ungetc(ch, input->fp);
+  return false;
+}
+
+/* Return non-zero if the current line matches the address
+   pointed to by `addr'. */
+static bool match_an_address_p P_((struct addr *, struct input *));
+static bool
+match_an_address_p(addr, input)
+  struct addr *addr;
+  struct input *input;
+{
+  switch (addr->addr_type)
+    {
+    case ADDR_IS_NULL:
+      return true;
+
+    case ADDR_IS_REGEX:
+      return match_regex(addr->addr_regex, line.active, line.length, 0, NULL, 0);
+
+    case ADDR_IS_NUM_MOD:
+      return (input->line_number >= addr->addr_number
+	      && ((input->line_number - addr->addr_number) % addr->addr_step) == 0);
+
+    case ADDR_IS_STEP:
+    case ADDR_IS_STEP_MOD:
+      /* reminder: these are only meaningful for a2 addresses */
+      /* a2->addr_number needs to be recomputed each time a1 address
+         matches for the step and step_mod types */
+      return (addr->addr_number <= input->line_number);
+
+    case ADDR_IS_LAST:
+      return test_eof(input);
+
+      /* ADDR_IS_NUM is handled in match_address_p.  */
+    case ADDR_IS_NUM:
+    default:
+      panic("INTERNAL ERROR: bad address type");
+    }
+  /*NOTREACHED*/
+  return false;
+}
+
+/* return non-zero if current address is valid for cmd */
+static bool match_address_p P_((struct sed_cmd *, struct input *));
+static bool
+match_address_p(cmd, input)
+  struct sed_cmd *cmd;
+  struct input *input;
+{
+  if (!cmd->a1)
+    return true;
+
+  if (cmd->range_state != RANGE_ACTIVE)
+    {
+      /* Find if we are going to activate a range.  Handle ADDR_IS_NUM
+	 specially: it represent an "absolute" state, it should not
+	 be computed like regexes.  */
+      if (cmd->a1->addr_type == ADDR_IS_NUM)
+	{
+	  if (!cmd->a2)
+	    return (input->line_number == cmd->a1->addr_number);
+
+	  if (cmd->range_state == RANGE_CLOSED
+	      || input->line_number < cmd->a1->addr_number)
+	    return false;
+	}
+      else
+	{
+          if (!cmd->a2)
+	    return match_an_address_p(cmd->a1, input);
+
+	  if (!match_an_address_p(cmd->a1, input))
+            return false;
+	}
+
+      /* Ok, start a new range.  */
+      cmd->range_state = RANGE_ACTIVE;
+      switch (cmd->a2->addr_type)
+	{
+	case ADDR_IS_REGEX:
+	  /* Always include at least two lines.  */
+	  return true;
+	case ADDR_IS_NUM:
+	  /* Same handling as below, but always include at least one line.  */
+          if (input->line_number >= cmd->a2->addr_number)
+	    cmd->range_state = RANGE_CLOSED;
+          return true;
+	case ADDR_IS_STEP:
+	  cmd->a2->addr_number = input->line_number + cmd->a2->addr_step;
+	  return true;
+	case ADDR_IS_STEP_MOD:
+	  cmd->a2->addr_number = input->line_number + cmd->a2->addr_step
+				 - (input->line_number%cmd->a2->addr_step);
+	  return true;
+	default:
+	  break;
+        }
+    }
+
+  /* cmd->range_state == RANGE_ACTIVE.  Check if the range is
+     ending; also handle ADDR_IS_NUM specially in this case.  */
+
+  if (cmd->a2->addr_type == ADDR_IS_NUM)
+    {
+      /* If the second address is a line number, and if we got past
+         that line, fail to match (it can happen when you jump
+	 over such addresses with `b' and `t'.  Use RANGE_CLOSED
+         so that the range is not re-enabled anymore.  */
+      if (input->line_number >= cmd->a2->addr_number)
+	cmd->range_state = RANGE_CLOSED;
+
+      return (input->line_number <= cmd->a2->addr_number);
+   }
+
+  /* Other addresses are treated as usual.  */
+  if (match_an_address_p(cmd->a2, input))
+    cmd->range_state = RANGE_CLOSED;
+
+  return true;
+}
+
+
+
+static void do_list P_((int line_len));
+static void
+do_list(line_len)
+     int line_len;
+{
+  unsigned char *p = CAST(unsigned char *)line.active;
+  countT len = line.length;
+  countT width = 0;
+  char obuf[180];	/* just in case we encounter a 512-bit char (;-) */
+  char *o;
+  size_t olen;
+  FILE *fp = output_file.fp;
+
+  output_missing_newline(&output_file);
+  for (; len--; ++p) {
+      o = obuf;
+      
+      /* Some locales define 8-bit characters as printable.  This makes the
+	 testsuite fail at 8to7.sed because the `l' command in fact will not
+	 convert the 8-bit characters. */
+#if defined isascii || defined HAVE_ISASCII
+      if (isascii(*p) && ISPRINT(*p)) {
+#else
+      if (ISPRINT(*p)) {
+#endif
+	  *o++ = *p;
+	  if (*p == '\\')
+	    *o++ = '\\';
+      } else {
+	  *o++ = '\\';
+	  switch (*p) {
+#if defined __STDC__ && __STDC__-0
+	    case '\a': *o++ = 'a'; break;
+#else /* Not STDC; we'll just assume ASCII */
+	    case 007:  *o++ = 'a'; break;
+#endif
+	    case '\b': *o++ = 'b'; break;
+	    case '\f': *o++ = 'f'; break;
+	    case '\n': *o++ = 'n'; break;
+	    case '\r': *o++ = 'r'; break;
+	    case '\t': *o++ = 't'; break;
+	    case '\v': *o++ = 'v'; break;
+	    default:
+	      sprintf(o, "%03o", *p);
+	      o += strlen(o);
+	      break;
+	    }
+      }
+      olen = o - obuf;
+      if (width+olen >= line_len && line_len > 0) {
+	  ck_fwrite("\\\n", 1, 2, fp);
+	  width = 0;
+      }
+      ck_fwrite(obuf, 1, olen, fp);
+      width += olen;
+  }
+  ck_fwrite("$\n", 1, 2, fp);
+  flush_output (fp);
+}
+
+
+static enum replacement_types append_replacement P_((struct line *, struct replacement *,
+						     struct re_registers *,
+						     enum replacement_types));
+static enum replacement_types
+append_replacement (buf, p, regs, repl_mod)
+  struct line *buf;
+  struct replacement *p;
+  struct re_registers *regs;
+  enum replacement_types repl_mod;
+{
+  for (; p; p=p->next)
+    {
+      int i = p->subst_id;
+      enum replacement_types curr_type;
+
+      /* Apply a \[lu] modifier that was given earlier, but which we
+         have not had yet the occasion to apply.  But don't do it
+         if this replacement has a modifier of its own. */
+      curr_type = (p->repl_type & REPL_MODIFIERS)
+        ? p->repl_type
+        : p->repl_type | repl_mod;
+
+      repl_mod = 0;
+      if (p->prefix_length)
+        {
+          str_append_modified(buf, p->prefix, p->prefix_length,
+    			      curr_type);
+          curr_type &= ~REPL_MODIFIERS;
+        }
+
+      if (0 <= i)
+        if (regs->end[i] == regs->start[i] && p->repl_type & REPL_MODIFIERS)
+          /* Save this modifier, we shall apply it later.
+	     e.g. in s/()([a-z])/\u\1\2/
+	     the \u modifier is applied to \2, not \1 */
+	  repl_mod = curr_type & REPL_MODIFIERS;
+
+	else
+	  str_append_modified(buf, line.active + regs->start[i],
+			      CAST(size_t)(regs->end[i] - regs->start[i]),
+			      curr_type);
+    }
+
+  return repl_mod;
+}
+
+static void do_subst P_((struct subst *));
+static void
+do_subst(sub)
+  struct subst *sub;
+{
+  size_t start = 0;	/* where to start scan for (next) match in LINE */
+  size_t last_end = 0;  /* where did the last successful match end in LINE */
+  countT count = 0;	/* number of matches found */
+  bool again = true;
+
+  static struct re_registers regs;
+
+  if (s_accum.alloc == 0)
+    line_init(&s_accum, INITIAL_BUFFER_SIZE);
+  s_accum.length = 0;
+
+  /* The first part of the loop optimizes s/xxx// when xxx is at the
+     start, and s/xxx$// */
+  if (!match_regex(sub->regx, line.active, line.length, start,
+		   &regs, sub->max_id + 1))
+    return;
+  
+  if (!sub->replacement && sub->numb <= 1)
+    if (regs.start[0] == 0 && !sub->global)
+      {
+	/* We found a match, set the `replaced' flag. */
+	replaced = true;
+
+	line.active += regs.end[0];
+	line.length -= regs.end[0];
+	line.alloc -= regs.end[0];
+	goto post_subst;
+      }
+    else if (regs.end[0] == line.length)
+      {
+	/* We found a match, set the `replaced' flag. */
+	replaced = true;
+
+	line.length = regs.start[0];
+	goto post_subst;
+      }
+
+  do
+    {
+      enum replacement_types repl_mod = 0;
+
+      size_t offset = regs.start[0];
+      size_t matched = regs.end[0] - regs.start[0];
+
+      /* Copy stuff to the left of this match into the output string. */
+      if (start < offset)
+	str_append(&s_accum, line.active + start, offset - start);
+
+      /* If we're counting up to the Nth match, are we there yet?
+         And even if we are there, there is another case we have to
+	 skip: are we matching an empty string immediately following
+         another match?
+
+         This latter case avoids that baaaac, when passed through
+         s,a*,x,g, gives `xbxxcx' instead of xbxcx.  This behavior is
+         unacceptable because it is not consistently applied (for
+         example, `baaaa' gives `xbx', not `xbxx'). */
+      if ((matched > 0 || count == 0 || offset > last_end)
+	  && ++count >= sub->numb)
+        {
+          /* We found a match, set the `replaced' flag. */
+          replaced = true;
+
+          /* Now expand the replacement string into the output string. */
+          repl_mod = append_replacement (&s_accum, sub->replacement, &regs, repl_mod);
+	  again = sub->global;
+        }
+      else
+	{
+          /* The match was not replaced.  Copy the text until its
+             end; if it was vacuous, skip over one character and
+	     add that character to the output.  */
+	  if (matched == 0)
+	    {
+	      if (start < line.length)
+	        matched = 1;
+	      else
+	        break;
+	    }
+
+	  str_append(&s_accum, line.active + offset, matched);
+        }
+
+      /* Start after the match.  last_end is the real end of the matched
+	 substring, excluding characters that were skipped in case the RE
+	 matched the empty string.  */
+      start = offset + matched;
+      last_end = regs.end[0];
+    }
+  while (again
+	 && start <= line.length
+	 && match_regex(sub->regx, line.active, line.length, start,
+			&regs, sub->max_id + 1));
+
+  /* Copy stuff to the right of the last match into the output string. */
+  if (start < line.length)
+    str_append(&s_accum, line.active + start, line.length-start);
+  s_accum.chomped = line.chomped;
+
+  /* Exchange line and s_accum.  This can be much cheaper
+     than copying s_accum.active into line.text (for huge lines). */
+  line_exchange(&line, &s_accum);
+  
+  /* Finish up. */
+  if (count < sub->numb)
+    return;
+
+ post_subst:
+  if (sub->print & 1)
+    output_line(line.active, line.length, line.chomped, &output_file);
+  
+  if (sub->eval) 
+    {
+#ifdef HAVE_POPEN
+      FILE *pipe;
+      s_accum.length = 0;
+      
+      str_append (&line, "", 1);
+      pipe = popen(line.active, "r");
+      
+      if (pipe != NULL) 
+	{
+	  while (!feof (pipe)) 
+	    {
+	      char buf[4096];
+	      int n = fread (buf, sizeof(char), 4096, pipe);
+	      if (n > 0)
+		str_append(&s_accum, buf, n);
+	    }
+	  
+	  pclose (pipe);
+
+	  line_exchange(&line, &s_accum);
+	  if (line.length &&
+	      line.active[line.length - 1] == '\n')
+	    line.length--;
+	}
+      else
+	panic(_("error in subprocess"));
+#else
+      panic(_("option `e' not supported"));
+#endif
+    } 
+  
+  if (sub->print & 2)
+    output_line(line.active, line.length, line.chomped, &output_file);
+  if (sub->outf)
+    output_line(line.active, line.length, line.chomped, sub->outf);
+}
+
+#ifdef EXPERIMENTAL_DASH_N_OPTIMIZATION
+/* Used to attempt a simple-minded optimization. */
+
+static countT branches;
+
+static countT count_branches P_((struct vector *));
+static countT
+count_branches(program)
+  struct vector *program;
+{
+  struct sed_cmd *cur_cmd = program->v;
+  countT isn_cnt = program->v_length;
+  countT cnt = 0;
+
+  while (isn_cnt-- > 0)
+    {
+      switch (cur_cmd->cmd)
+	{
+	case 'b':
+	case 't':
+	case 'T':
+	case '{':
+	  ++cnt;
+	}
+    }
+  return cnt;
+}
+
+static struct sed_cmd *shrink_program P_((struct vector *, struct sed_cmd *));
+static struct sed_cmd *
+shrink_program(vec, cur_cmd)
+  struct vector *vec;
+  struct sed_cmd *cur_cmd;
+{
+  struct sed_cmd *v = vec->v;
+  struct sed_cmd *last_cmd = v + vec->v_length;
+  struct sed_cmd *p;
+  countT cmd_cnt;
+
+  for (p=v; p < cur_cmd; ++p)
+    if (p->cmd != '#')
+      MEMCPY(v++, p, sizeof *v);
+  cmd_cnt = v - vec->v;
+
+  for (; p < last_cmd; ++p)
+    if (p->cmd != '#')
+      MEMCPY(v++, p, sizeof *v);
+  vec->v_length = v - vec->v;
+
+  return (0 < vec->v_length) ? (vec->v + cmd_cnt) : CAST(struct sed_cmd *)0;
+}
+#endif /*EXPERIMENTAL_DASH_N_OPTIMIZATION*/
+
+/* Execute the program `vec' on the current input line.
+   Return exit status if caller should quit, -1 otherwise. */
+static int execute_program P_((struct vector *, struct input *));
+static int
+execute_program(vec, input)
+  struct vector *vec;
+  struct input *input;
+{
+  struct sed_cmd *cur_cmd;
+  struct sed_cmd *end_cmd;
+
+  cur_cmd = vec->v;
+  end_cmd = vec->v + vec->v_length;
+  while (cur_cmd < end_cmd)
+    {
+      if (match_address_p(cur_cmd, input) != cur_cmd->addr_bang)
+	{
+	  switch (cur_cmd->cmd)
+	    {
+	    case 'a':
+	      {
+		struct append_queue *aq = next_append_slot();
+		aq->text = cur_cmd->x.cmd_txt.text;
+		aq->textlen = cur_cmd->x.cmd_txt.text_length;
+	      }
+	      break;
+
+	    case '{':
+	    case 'b':
+	      cur_cmd = vec->v + cur_cmd->x.jump_index;
+	      continue;
+
+	    case '}':
+	    case '#':
+	    case ':':
+	      /* Executing labels and block-ends are easy. */
+	      break;
+
+	    case 'c':
+	      if (cur_cmd->range_state != RANGE_ACTIVE)
+		output_line(cur_cmd->x.cmd_txt.text,
+			    cur_cmd->x.cmd_txt.text_length - 1, true,
+			    &output_file);
+	      /* POSIX.2 is silent about c starting a new cycle,
+		 but it seems to be expected (and make sense). */
+	      /* Fall Through */
+	    case 'd':
+	      return -1;
+
+	    case 'D':
+	      {
+		char *p = memchr(line.active, '\n', line.length);
+		if (!p)
+		  return -1;
+
+		++p;
+		line.alloc -= p - line.active;
+		line.length -= p - line.active;
+		line.active += p - line.active;
+
+		/* reset to start next cycle without reading a new line: */
+		cur_cmd = vec->v;
+		continue;
+	      }
+
+	    case 'e': {
+#ifdef HAVE_POPEN
+	      FILE *pipe;
+	      int cmd_length = cur_cmd->x.cmd_txt.text_length;
+	      if (s_accum.alloc == 0)
+		line_init(&s_accum, INITIAL_BUFFER_SIZE);
+	      s_accum.length = 0;
+
+	      if (!cmd_length)
+		{
+		  str_append (&line, "", 1);
+		  pipe = popen(line.active, "r");
+		} 
+	      else
+		{
+		  cur_cmd->x.cmd_txt.text[cmd_length - 1] = 0;
+		  pipe = popen(cur_cmd->x.cmd_txt.text, "r");
+                  output_missing_newline(&output_file);
+		}
+
+	      if (pipe != NULL) 
+		{
+		  while (!feof (pipe)) 
+		    {
+		      char buf[4096];
+		      int n = fread (buf, sizeof(char), 4096, pipe);
+		      if (n > 0)
+			if (!cmd_length)
+			  str_append(&s_accum, buf, n);
+			else
+			  ck_fwrite(buf, 1, n, output_file.fp);
+		    }
+		  
+		  pclose (pipe);
+		  if (!cmd_length)
+		    {
+		      /* Store into pattern space for plain `e' commands */
+		      if (s_accum.length &&
+			  s_accum.active[s_accum.length - 1] == '\n')
+			s_accum.length--;
+
+		      /* Exchange line and s_accum.  This can be much
+			 cheaper than copying s_accum.active into line.text
+			 (for huge lines). */
+		      line_exchange(&line, &s_accum);
+		    }
+                  else
+                    flush_output(output_file.fp);
+
+		}
+	      else
+		panic(_("error in subprocess"));
+#else
+	      panic(_("`e' command not supported"));
+#endif
+	      break;
+	    }
+
+	    case 'g':
+	      line_copy(&hold, &line);
+	      break;
+
+	    case 'G':
+	      line_append(&hold, &line);
+	      break;
+
+	    case 'h':
+	      line_copy(&line, &hold);
+	      break;
+
+	    case 'H':
+	      line_append(&line, &hold);
+	      break;
+
+	    case 'i':
+	      output_line(cur_cmd->x.cmd_txt.text,
+			  cur_cmd->x.cmd_txt.text_length - 1,
+			  true, &output_file);
+	      break;
+
+	    case 'l':
+	      do_list(cur_cmd->x.int_arg == -1
+		      ? lcmd_out_line_len
+		      : cur_cmd->x.int_arg);
+	      break;
+
+	    case 'L':
+              output_missing_newline(&output_file);
+	      fmt(line.active, line.active + line.length,
+		  cur_cmd->x.int_arg == -1
+		  ? lcmd_out_line_len
+		  : cur_cmd->x.int_arg,
+		  output_file.fp);
+              flush_output(output_file.fp);
+	      break;
+
+	    case 'n':
+	      if (!no_default_output)
+		output_line(line.active, line.length, line.chomped, &output_file);
+	      if (test_eof(input) || !read_pattern_space(input, vec, false))
+		return -1;
+	      break;
+
+	    case 'N':
+	      str_append(&line, "\n", 1);
+ 
+              if (test_eof(input) || !read_pattern_space(input, vec, true))
+                {
+                  line.length--;
+                  if (posixicity == POSIXLY_EXTENDED && !no_default_output)
+                     output_line(line.active, line.length, line.chomped,
+                                 &output_file);
+                  return -1;
+                }
+	      break;
+
+	    case 'p':
+	      output_line(line.active, line.length, line.chomped, &output_file);
+	      break;
+
+	    case 'P':
+	      {
+		char *p = memchr(line.active, '\n', line.length);
+		output_line(line.active, p ? p - line.active : line.length,
+			    p ? true : line.chomped, &output_file);
+	      }
+	      break;
+
+            case 'q':
+              if (!no_default_output)
+                output_line(line.active, line.length, line.chomped, &output_file);
+	      dump_append_queue();
+
+	    case 'Q':
+	      return cur_cmd->x.int_arg == -1 ? 0 : cur_cmd->x.int_arg;
+
+	    case 'r':
+	      if (cur_cmd->x.fname)
+		{
+		  struct append_queue *aq = next_append_slot();
+		  aq->fname = cur_cmd->x.fname;
+		}
+	      break;
+
+	    case 'R':
+	      if (cur_cmd->x.fp && !feof (cur_cmd->x.fp))
+		{
+		  struct append_queue *aq;
+		  size_t buflen;
+		  char *text = NULL;
+		  int result;
+
+		  result = ck_getline (&text, &buflen, cur_cmd->x.fp);
+		  if (result != EOF)
+		    {
+		      aq = next_append_slot();
+		      aq->free = true;
+		      aq->text = text;
+		      aq->textlen = result;
+		    }
+		}
+	      break;
+
+	    case 's':
+	      do_subst(cur_cmd->x.cmd_subst);
+	      break;
+
+	    case 't':
+	      if (replaced)
+		{
+		  replaced = false;
+		  cur_cmd = vec->v + cur_cmd->x.jump_index;
+		  continue;
+		}
+	      break;
+
+	    case 'T':
+	      if (!replaced)
+		{
+		  cur_cmd = vec->v + cur_cmd->x.jump_index;
+		  continue;
+		}
+	      else
+		replaced = false;
+	      break;
+
+	    case 'w':
+	      if (cur_cmd->x.fp)
+		output_line(line.active, line.length,
+			    line.chomped, cur_cmd->x.outf);
+	      break;
+
+	    case 'W':
+	      if (cur_cmd->x.fp)
+	        {
+		  char *p = memchr(line.active, '\n', line.length);
+		  output_line(line.active, p ? p - line.active : line.length,
+			      p ? true : line.chomped, cur_cmd->x.outf);
+	        }
+	      break;
+
+	    case 'x':
+	      line_exchange(&line, &hold);
+	      break;
+
+	    case 'y':
+	      {
+#ifdef HAVE_MBRTOWC
+               if (mb_cur_max > 1)
+                 {
+                   int idx, prev_idx; /* index in the input line.  */
+                   char **trans;
+                   mbstate_t mbstate;
+                   memset(&mbstate, 0, sizeof(mbstate_t));
+                   for (idx = 0; idx < line.length;)
+                     {
+                       int mbclen, i;
+                       mbclen = MBRLEN (line.active + idx, line.length - idx,
+                                          &mbstate);
+                       /* An invalid sequence, or a truncated multibyte
+                          character.  We treat it as a singlebyte character.
+                       */
+                       if (mbclen == (size_t) -1 || mbclen == (size_t) -2
+                           || mbclen == 0)
+                         mbclen = 1;
+
+                       trans = cur_cmd->x.translatemb;
+                       /* `i' indicate i-th translate pair.  */
+                       for (i = 0; trans[2*i] != NULL; i++)
+                         {
+                           if (strncmp(line.active + idx, trans[2*i], mbclen) == 0)
+                             {
+                               bool move_remain_buffer = false;
+                               int trans_len = strlen(trans[2*i+1]);
+
+                               if (mbclen < trans_len)
+                                 {
+                                   int new_len;
+                                   new_len = line.length + 1 + trans_len - mbclen;
+                                   /* We must extend the line buffer.  */
+                                   if (line.alloc < new_len)
+                                     {
+                                       /* And we must resize the buffer.  */
+                                       resize_line(&line, new_len);
+                                     }
+                                   move_remain_buffer = true;
+                                 }
+                               else if (mbclen > trans_len)
+                                 {
+                                   /* We must truncate the line buffer.  */
+                                   move_remain_buffer = true;
+                                 }
+                               prev_idx = idx;
+                               if (move_remain_buffer)
+                                 {
+                                   int move_len, move_offset;
+                                   char *move_from, *move_to;
+                                   /* Move the remaining with \0.  */
+                                   move_from = line.active + idx + mbclen;
+                                   move_to = line.active + idx + trans_len;
+                                   move_len = line.length + 1 - idx - mbclen;
+                                   move_offset = trans_len - mbclen;
+                                   memmove(move_to, move_from, move_len);
+                                   line.length += move_offset;
+                                   idx += move_offset;
+                                 }
+                               strncpy(line.active + prev_idx, trans[2*i+1],
+                                       trans_len);
+                               break;
+                             }
+                         }
+                       idx += mbclen;
+                     }
+                 }
+               else
+#endif /* HAVE_MBRTOWC */
+                 {
+                   unsigned char *p, *e;
+                   p = CAST(unsigned char *)line.active;
+                   for (e=p+line.length; p<e; ++p)
+                     *p = cur_cmd->x.translate[*p];
+                 }
+	      }
+	      break;
+
+	    case '=':
+              output_missing_newline(&output_file);
+              fprintf(output_file.fp, "%lu\n",
+                      CAST(unsigned long)input->line_number);
+              flush_output(output_file.fp);
+	      break;
+
+	    default:
+	      panic("INTERNAL ERROR: Bad cmd %c", cur_cmd->cmd);
+	    }
+	}
+
+#ifdef EXPERIMENTAL_DASH_N_OPTIMIZATION
+      /* If our top-level program consists solely of commands with
+         ADDR_IS_NUM addresses then once we past the last mentioned
+         line we should be able to quit if no_default_output is true,
+         or otherwise quickly copy input to output.  Now whether this
+         optimization is a win or not depends on how cheaply we can
+         implement this for the cases where it doesn't help, as
+         compared against how much time is saved.  One semantic
+         difference (which I think is an improvement) is that *this*
+         version will terminate after printing line two in the script
+         "yes | sed -n 2p". 
+        
+         Don't use this when in-place editing is active, because line
+         numbers restart each time then. */
+      else if (!separate_files)
+	{
+	  if (cur_cmd->a1->addr_type == ADDR_IS_NUM
+	      && (cur_cmd->a2
+		  ? cur_cmd->range_state == RANGE_CLOSED
+		  : cur_cmd->a1->addr_number < input->line_number))
+	    {
+	      /* Skip this address next time */
+	      cur_cmd->addr_bang = !cur_cmd->addr_bang;
+	      cur_cmd->a1->addr_type = ADDR_IS_NULL;
+	      if (cur_cmd->a2)
+		cur_cmd->a2->addr_type = ADDR_IS_NULL;
+
+	      /* can we make an optimization? */
+	      if (cur_cmd->addr_bang)
+		{
+		  if (cur_cmd->cmd == 'b' || cur_cmd->cmd == 't'
+		      || cur_cmd->cmd == 'T' || cur_cmd->cmd == '}')
+		    branches--;
+
+		  cur_cmd->cmd = '#';	/* replace with no-op */
+	          if (branches == 0)
+		    cur_cmd = shrink_program(vec, cur_cmd);
+		  if (!cur_cmd && no_default_output)
+		    return 0;
+		  end_cmd = vec->v + vec->v_length;
+		  if (!cur_cmd)
+		    cur_cmd = end_cmd;
+		  continue;
+		}
+	    }
+	}
+#endif /*EXPERIMENTAL_DASH_N_OPTIMIZATION*/
+
+      /* this is buried down here so that a "continue" statement can skip it */
+      ++cur_cmd;
+    }
+
+    if (!no_default_output)
+      output_line(line.active, line.length, line.chomped, &output_file);
+    return -1;
+}
+
+
+
+
+/* Apply the compiled script to all the named files. */
+int
+process_files(the_program, argv)
+  struct vector *the_program;
+  char **argv;
+{
+  static char dash[] = "-";
+  static char *stdin_argv[2] = { dash, NULL };
+  struct input input;
+  int status;
+
+  line_init(&line, INITIAL_BUFFER_SIZE);
+  line_init(&hold, 0);
+  line_init(&buffer, 0);
+
+#ifdef EXPERIMENTAL_DASH_N_OPTIMIZATION
+  branches = count_branches(the_program);
+#endif /*EXPERIMENTAL_DASH_N_OPTIMIZATION*/
+  input.reset_at_next_file = true;
+  if (argv && *argv)
+    input.file_list = argv;
+  else if (in_place_extension)
+    panic(_("no input files"));
+  else
+    input.file_list = stdin_argv;
+
+  input.bad_count = 0;
+  input.line_number = 0;
+  input.read_fn = read_always_fail;
+  input.fp = NULL;
+
+  status = EXIT_SUCCESS;
+  while (read_pattern_space(&input, the_program, false))
+    {
+      status = execute_program(the_program, &input);
+      if (status == -1)
+	status = EXIT_SUCCESS;
+      else
+	break;
+    }
+  closedown(&input);
+
+#ifdef DEBUG_LEAKS
+  /* We're about to exit, so these free()s are redundant.
+     But if we're running under a memory-leak detecting
+     implementation of malloc(), we want to explicitly
+     deallocate in order to avoid extraneous noise from
+     the allocator. */
+  release_append_queue();
+  FREE(buffer.text);
+  FREE(hold.text);
+  FREE(line.text);
+  FREE(s_accum.text);
+#endif /*DEBUG_LEAKS*/
+
+  if (input.bad_count)
+    status = 2;
+
+  return status;
+}
Index: /tags/kBuild-0.1.4/src/sed/sed/fmt.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/fmt.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/fmt.c	(revision 1780)
@@ -0,0 +1,587 @@
+/* `L' command implementation for GNU sed, based on GNU fmt 1.22.
+   Copyright (C) 1994, 1995, 1996, 2002, 2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* GNU fmt was written by Ross Paterson <rap@doc.ic.ac.uk>.  */
+
+#include "sed.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#ifndef UINT_MAX
+# define UINT_MAX ((unsigned int) ~(unsigned int) 0)
+#endif
+
+#ifndef INT_MAX
+# define INT_MAX ((int) (UINT_MAX >> 1))
+#endif
+
+/* The following parameters represent the program's idea of what is
+   "best".  Adjust to taste, subject to the caveats given.  */
+
+/* Prefer lines to be LEEWAY % shorter than the maximum width, giving
+   room for optimization.  */
+#define	LEEWAY	7
+
+/* Costs and bonuses are expressed as the equivalent departure from the
+   optimal line length, multiplied by 10.  e.g. assigning something a
+   cost of 50 means that it is as bad as a line 5 characters too short
+   or too long.  The definition of SHORT_COST(n) should not be changed.
+   However, EQUIV(n) may need tuning.  */
+
+typedef long COST;
+
+#define	MAXCOST	(~(((unsigned long) 1) << (8 * sizeof (COST) -1)))
+
+#define	SQR(n)		((n) * (n))
+#define	EQUIV(n)	SQR ((COST) (n))
+
+/* Cost of a filled line n chars longer or shorter than best_width.  */
+#define	SHORT_COST(n)	EQUIV ((n) * 10)
+
+/* Cost of the difference between adjacent filled lines.  */
+#define	RAGGED_COST(n)	(SHORT_COST (n) / 2)
+
+/* Basic cost per line.  */
+#define	LINE_COST	EQUIV (70)
+
+/* Cost of breaking a line after the first word of a sentence, where
+   the length of the word is N.  */
+#define	WIDOW_COST(n)	(EQUIV (200) / ((n) + 2))
+
+/* Cost of breaking a line before the last word of a sentence, where
+   the length of the word is N.  */
+#define	ORPHAN_COST(n)	(EQUIV (150) / ((n) + 2))
+
+/* Bonus for breaking a line at the end of a sentence.  */
+#define	SENTENCE_BONUS	EQUIV (50)
+
+/* Cost of breaking a line after a period not marking end of a sentence.
+   With the definition of sentence we are using (borrowed from emacs, see
+   get_line()) such a break would then look like a sentence break.  Hence
+   we assign a very high cost -- it should be avoided unless things are
+   really bad.  */
+#define	NOBREAK_COST	EQUIV (600)
+
+/* Bonus for breaking a line before open parenthesis.  */
+#define	PAREN_BONUS	EQUIV (40)
+
+/* Bonus for breaking a line after other punctuation.  */
+#define	PUNCT_BONUS	EQUIV(40)
+
+/* Credit for breaking a long paragraph one line later.  */
+#define	LINE_CREDIT	EQUIV(3)
+
+/* Size of paragraph buffer in words.  Longer paragraphs are handled
+   neatly (cf. flush_paragraph()), so there's little to gain by making
+   these larger.  */
+#define	MAXWORDS	1000
+
+#define GETC()          (parabuf == end_of_parabuf ? EOF : *parabuf++)
+
+/* Extra ctype(3)-style macros.  */
+
+#define	isopen(c)	(strchr ("([`'\"", (c)) != NULL)
+#define	isclose(c)	(strchr (")]'\"", (c)) != NULL)
+#define	isperiod(c)	(strchr (".?!", (c)) != NULL)
+
+/* Size of a tab stop, for expansion on input and re-introduction on
+   output.  */
+#define	TABWIDTH	8
+
+/* Word descriptor structure.  */
+
+typedef struct Word WORD;
+
+struct Word
+  {
+
+    /* Static attributes determined during input.  */
+
+    const char *text;		/* the text of the word */
+    short length;		/* length of this word */
+    short space;		/* the size of the following space */
+    unsigned paren:1;		/* starts with open paren */
+    unsigned period:1;		/* ends in [.?!])* */
+    unsigned punct:1;		/* ends in punctuation */
+    unsigned final:1;		/* end of sentence */
+
+    /* The remaining fields are computed during the optimization.  */
+
+    short line_length;		/* length of the best line starting here */
+    COST best_cost;		/* cost of best paragraph starting here */
+    WORD *next_break;		/* break which achieves best_cost */
+  };
+
+/* Forward declarations.  */
+
+static bool get_paragraph P_ ((void));
+static int get_line P_ ((int c));
+static int get_space P_ ((int c));
+static int copy_rest P_ ((int c));
+static bool same_para P_ ((int c));
+static void flush_paragraph P_ ((void));
+static void fmt_paragraph P_ ((void));
+static void check_punctuation P_ ((WORD *w));
+static COST base_cost P_ ((WORD *this));
+static COST line_cost P_ ((WORD *next, int len));
+static void put_paragraph P_ ((WORD *finish));
+static void put_line P_ ((WORD *w, int indent));
+static void put_word P_ ((WORD *w));
+static void put_space P_ ((int space));
+
+/* Option values.  */
+
+/* User-supplied maximum line width (default WIDTH).  The only output
+   lines
+   longer than this will each comprise a single word.  */
+static int max_width;
+
+/* Space for the paragraph text.  */
+static const char *parabuf;
+
+/* End of space for the paragraph text.  */
+static const char *end_of_parabuf;
+
+/* The file on which we output */
+static FILE *outfile;
+
+/* Values derived from the option values.  */
+
+/* The preferred width of text lines, set to LEEWAY % less than max_width.  */
+static int best_width;
+
+/* Dynamic variables.  */
+
+/* Start column of the character most recently read from the input file.  */
+static int in_column;
+
+/* Start column of the next character to be written to stdout.  */
+static int out_column;
+
+/* The words of a paragraph -- longer paragraphs are handled neatly
+   (cf. flush_paragraph()).  */
+static WORD words[MAXWORDS];
+
+/* A pointer into the above word array, indicating the first position
+   after the last complete word.  Sometimes it will point at an incomplete
+   word.  */
+static WORD *word_limit;
+
+/* Indentation of the first line of the current paragraph.  */
+static int first_indent;
+
+/* Indentation of other lines of the current paragraph */
+static int other_indent;
+
+/* The last character read from the input file.  */
+static int next_char;
+
+/* If nonzero, the length of the last line output in the current
+   paragraph, used to charge for raggedness at the split point for long
+   paragraphs chosen by fmt_paragraph().  */
+static int last_line_length;
+
+/* read file F and send formatted output to stdout.  */
+
+void
+fmt (const char *line, const char *line_end, int max_length, FILE *output_file)
+{
+  parabuf = line;
+  end_of_parabuf = line_end;
+  outfile = output_file;
+
+  max_width = max_length;
+  best_width = max_width * (201 - 2 * LEEWAY) / 200;
+
+  in_column = 0;
+  other_indent = 0;
+  next_char = GETC();
+  while (get_paragraph ())
+    {
+      fmt_paragraph ();
+      put_paragraph (word_limit);
+    }
+}
+
+/* Read a paragraph from input file F.  A paragraph consists of a
+   maximal number of non-blank (excluding any prefix) lines
+   with the same indent.
+
+   Return false if end-of-file was encountered before the start of a
+   paragraph, else true.  */
+
+static bool
+get_paragraph ()
+{
+  register int c;
+
+  last_line_length = 0;
+  c = next_char;
+
+  /* Scan (and copy) blank lines, and lines not introduced by the prefix.  */
+
+  while (c == '\n' || c == EOF)
+    {
+      c = copy_rest (c);
+      if (c == EOF)
+	{
+	  next_char = EOF;
+	  return false;
+	}
+      putc ('\n', outfile);
+      c = GETC();
+    }
+
+  /* Got a suitable first line for a paragraph.  */
+
+  first_indent = in_column;
+  word_limit = words;
+  c = get_line (c);
+
+  /* Read rest of paragraph.  */
+
+  other_indent = in_column;
+  while (same_para (c) && in_column == other_indent)
+    c = get_line (c);
+
+  (word_limit - 1)->period = (word_limit - 1)->final = true;
+  next_char = c;
+  return true;
+}
+
+/* Copy to the output a blank line.  In the latter, C is \n or EOF.
+   Return the character (\n or EOF) ending the line.  */
+
+static int
+copy_rest (register int c)
+{
+  out_column = 0;
+  while (c != '\n' && c != EOF)
+    {
+      putc (c, outfile);
+      c = GETC();
+    }
+  return c;
+}
+
+/* Return true if a line whose first non-blank character after the
+   prefix (if any) is C could belong to the current paragraph,
+   otherwise false.  */
+
+static bool
+same_para (register int c)
+{
+  return (c != '\n' && c != EOF);
+}
+
+/* Read a line from the input data given first non-blank character C
+   after the prefix, and the following indent, and break it into words.
+   A word is a maximal non-empty string of non-white characters.  A word
+   ending in [.?!]["')\]]* and followed by end-of-line or at least two
+   spaces ends a sentence, as in emacs.
+
+   Return the first non-blank character of the next line.  */
+
+static int
+get_line (register int c)
+{
+  int start;
+  register WORD *end_of_word;
+
+  end_of_word = &words[MAXWORDS - 2];
+
+  do
+    {				/* for each word in a line */
+
+      /* Scan word.  */
+
+      word_limit->text = parabuf - 1;
+      do
+	c = GETC();
+      while (c != EOF && !ISSPACE (c));
+      word_limit->length = parabuf - word_limit->text - (c != EOF);
+      in_column += word_limit->length;
+
+      check_punctuation (word_limit);
+
+      /* Scan inter-word space.  */
+
+      start = in_column;
+      c = get_space (c);
+      word_limit->space = in_column - start;
+      word_limit->final = (c == EOF
+			   || (word_limit->period
+			       && (c == '\n' || word_limit->space > 1)));
+      if (c == '\n' || c == EOF)
+	word_limit->space = word_limit->final ? 2 : 1;
+      if (word_limit == end_of_word)
+	flush_paragraph ();
+      word_limit++;
+      if (c == EOF)
+	{
+	  in_column = first_indent;
+	  return EOF;
+	}
+    }
+  while (c != '\n');
+
+  in_column = 0;
+  c = GETC();
+  return get_space (c);
+}
+
+/* Read blank characters from the input data, starting with C, and keeping
+   in_column up-to-date.  Return first non-blank character.  */
+
+static int
+get_space (register int c)
+{
+  for (;;)
+    {
+      if (c == ' ')
+	in_column++;
+      else if (c == '\t')
+	in_column = (in_column / TABWIDTH + 1) * TABWIDTH;
+      else
+	return c;
+      c = GETC();
+    }
+}
+
+/* Set extra fields in word W describing any attached punctuation.  */
+
+static void
+check_punctuation (register WORD *w)
+{
+  register const char *start, *finish;
+
+  start = w->text;
+  finish = start + (w->length - 1);
+  w->paren = isopen (*start);
+  w->punct = ISPUNCT (*finish);
+  while (isclose (*finish) && finish > start)
+    finish--;
+  w->period = isperiod (*finish);
+}
+
+/* Flush part of the paragraph to make room.  This function is called on
+   hitting the limit on the number of words or characters.  */
+
+static void
+flush_paragraph (void)
+{
+  WORD *split_point;
+  register WORD *w;
+  COST best_break;
+
+  /* - format what you have so far as a paragraph,
+     - find a low-cost line break near the end,
+     - output to there,
+     - make that the start of the paragraph.  */
+
+  fmt_paragraph ();
+
+  /* Choose a good split point.  */
+
+  split_point = word_limit;
+  best_break = MAXCOST;
+  for (w = words->next_break; w != word_limit; w = w->next_break)
+    {
+      if (w->best_cost - w->next_break->best_cost < best_break)
+	{
+	  split_point = w;
+	  best_break = w->best_cost - w->next_break->best_cost;
+	}
+      if (best_break <= MAXCOST - LINE_CREDIT)
+	best_break += LINE_CREDIT;
+    }
+  put_paragraph (split_point);
+
+  /* Copy words from split_point down to word -- we use memmove because
+     the source and target may overlap.  */
+
+  memmove ((char *) words, (char *) split_point,
+	 (word_limit - split_point + 1) * sizeof (WORD));
+  word_limit -= split_point - words;
+}
+
+/* Compute the optimal formatting for the whole paragraph by computing
+   and remembering the optimal formatting for each suffix from the empty
+   one to the whole paragraph.  */
+
+static void
+fmt_paragraph (void)
+{
+  register WORD *start, *w;
+  register int len;
+  register COST wcost, best;
+  int saved_length;
+
+  word_limit->best_cost = 0;
+  saved_length = word_limit->length;
+  word_limit->length = max_width;	/* sentinel */
+
+  for (start = word_limit - 1; start >= words; start--)
+    {
+      best = MAXCOST;
+      len = start == words ? first_indent : other_indent;
+
+      /* At least one word, however long, in the line.  */
+
+      w = start;
+      len += w->length;
+      do
+	{
+	  w++;
+
+	  /* Consider breaking before w.  */
+
+	  wcost = line_cost (w, len) + w->best_cost;
+	  if (start == words && last_line_length > 0)
+	    wcost += RAGGED_COST (len - last_line_length);
+	  if (wcost < best)
+	    {
+	      best = wcost;
+	      start->next_break = w;
+	      start->line_length = len;
+	    }
+	  len += (w - 1)->space + w->length;	/* w > start >= words */
+	}
+      while (len < max_width);
+      start->best_cost = best + base_cost (start);
+    }
+
+  word_limit->length = saved_length;
+}
+
+/* Return the constant component of the cost of breaking before the
+   word THIS.  */
+
+static COST
+base_cost (register WORD *this)
+{
+  register COST cost;
+
+  cost = LINE_COST;
+
+  if (this > words)
+    {
+      if ((this - 1)->period)
+	{
+	  if ((this - 1)->final)
+	    cost -= SENTENCE_BONUS;
+	  else
+	    cost += NOBREAK_COST;
+	}
+      else if ((this - 1)->punct)
+	cost -= PUNCT_BONUS;
+      else if (this > words + 1 && (this - 2)->final)
+	cost += WIDOW_COST ((this - 1)->length);
+    }
+
+  if (this->paren)
+    cost -= PAREN_BONUS;
+  else if (this->final)
+    cost += ORPHAN_COST (this->length);
+
+  return cost;
+}
+
+/* Return the component of the cost of breaking before word NEXT that
+   depends on LEN, the length of the line beginning there.  */
+
+static COST
+line_cost (register WORD *next, register int len)
+{
+  register int n;
+  register COST cost;
+
+  if (next == word_limit)
+    return 0;
+  n = best_width - len;
+  cost = SHORT_COST (n);
+  if (next->next_break != word_limit)
+    {
+      n = len - next->line_length;
+      cost += RAGGED_COST (n);
+    }
+  return cost;
+}
+
+/* Output to stdout a paragraph from word up to (but not including)
+   FINISH, which must be in the next_break chain from word.  */
+
+static void
+put_paragraph (register WORD *finish)
+{
+  register WORD *w;
+
+  put_line (words, first_indent);
+  for (w = words->next_break; w != finish; w = w->next_break)
+    put_line (w, other_indent);
+}
+
+/* Output to stdout the line beginning with word W, beginning in column
+   INDENT, including the prefix (if any).  */
+
+static void
+put_line (register WORD *w, int indent)
+{
+  register WORD *endline;
+  out_column = 0;
+  put_space (indent);
+
+  endline = w->next_break - 1;
+  for (; w != endline; w++)
+    {
+      put_word (w);
+      put_space (w->space);
+    }
+  put_word (w);
+  last_line_length = out_column;
+  putc ('\n', outfile);
+}
+
+/* Output to stdout the word W.  */
+
+static void
+put_word (register WORD *w)
+{
+  register const char *s;
+  register int n;
+
+  s = w->text;
+  for (n = w->length; n != 0; n--)
+    putc (*s++, outfile);
+  out_column += w->length;
+}
+
+/* Output to stdout SPACE spaces, or equivalent tabs.  */
+
+static void
+put_space (int space)
+{
+  out_column += space;
+  while (space--)
+    putc (' ', outfile);
+}
Index: /tags/kBuild-0.1.4/src/sed/sed/mbcs.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/mbcs.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/mbcs.c	(revision 1780)
@@ -0,0 +1,56 @@
+/*  GNU SED, a batch stream editor.
+    Copyright (C) 2003 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sed.h"
+#include <stdlib.h>
+
+int mb_cur_max;
+
+#ifdef HAVE_MBRTOWC
+/* Add a byte to the multibyte character represented by the state
+   CUR_STAT, and answer its length if a character is completed,
+   or -2 if it is yet to be completed.  */
+int brlen (ch, cur_stat)
+     int ch;
+     mbstate_t *cur_stat;
+{
+  char c = ch;
+
+  /* If we use the generic brlen, then MBRLEN == mbrlen.  */
+  int result = mbrtowc(NULL, &c, 1, cur_stat);
+
+  /* An invalid sequence is treated like a singlebyte character. */
+  if (result == -1)
+    {
+      memset (cur_stat, 0, sizeof (mbstate_t));
+      return 1;
+    }
+
+  return result;
+}
+#endif
+
+void
+initialize_mbcs ()
+{
+#ifdef HAVE_MBRTOWC
+  mb_cur_max = MB_CUR_MAX;
+#else
+  mb_cur_max = 1;
+#endif
+}
+
Index: /tags/kBuild-0.1.4/src/sed/sed/regexp.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/regexp.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/regexp.c	(revision 1780)
@@ -0,0 +1,254 @@
+/*  GNU SED, a batch stream editor.
+    Copyright (C) 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sed.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef gettext_noop
+# define N_(String) gettext_noop(String)
+#else
+# define N_(String) (String)
+#endif
+
+extern bool use_extended_syntax_p;
+
+static const char errors[] =
+  "no previous regular expression\0"
+  "cannot specify modifiers on empty regexp";
+
+#define NO_REGEX (errors)
+#define BAD_MODIF (NO_REGEX + sizeof(N_("no previous regular expression")))
+#define END_ERRORS (BAD_MODIF + sizeof(N_("cannot specify modifiers on empty regexp")))
+
+
+
+
+static void
+compile_regex_1 (new_regex, needed_sub)
+  struct regex *new_regex;
+  int needed_sub;
+{
+#ifdef REG_PERL
+  int errcode;
+  errcode = regncomp(&new_regex->pattern, new_regex->re, new_regex->sz,
+		     (needed_sub ? 0 : REG_NOSUB)
+		     | new_regex->flags
+		     | extended_regexp_flags);
+
+  if (errcode)
+    {
+      char errorbuf[200];
+      regerror(errcode, NULL, errorbuf, 200);
+      bad_prog(gettext(errorbuf));
+    }
+#else
+  const char *error;
+  int syntax = ((extended_regexp_flags & REG_EXTENDED)
+		 ? RE_SYNTAX_POSIX_EXTENDED
+                 : RE_SYNTAX_POSIX_BASIC)
+		 & ~RE_UNMATCHED_RIGHT_PAREN_ORD;
+
+  syntax |= RE_NO_POSIX_BACKTRACKING;
+#ifdef RE_ICASE
+  syntax |= (new_regex->flags & REG_ICASE) ? RE_ICASE : 0;
+#endif
+#ifdef RE_NO_SUB
+  syntax |= needed_sub ? 0 : RE_NO_SUB;
+#endif
+
+  new_regex->pattern.fastmap = malloc (1 << (sizeof (char) * 8));
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (new_regex->flags & REG_NEWLINE)
+    {
+      /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~RE_DOT_NEWLINE;
+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+    }
+
+  re_set_syntax (syntax);
+  error = re_compile_pattern (new_regex->re, new_regex->sz,
+			      &new_regex->pattern);
+  new_regex->pattern.newline_anchor = (new_regex->flags & REG_NEWLINE) != 0;
+
+  new_regex->pattern.translate = NULL;
+#ifndef RE_ICASE
+  if (new_regex->flags & REG_ICASE)
+    {
+      static char translate[1 << (sizeof(char) * 8)];
+      int i;
+      for (i = 0; i < sizeof(translate) / sizeof(char); i++)
+	translate[i] = tolower (i);
+
+      new_regex->pattern.translate = translate;
+    }
+#endif
+
+  if (error)
+    bad_prog(error);
+#endif
+
+  /* Just to be sure, I mark this as not POSIXLY_CORRECT behavior */
+  if (needed_sub
+      && new_regex->pattern.re_nsub < needed_sub - 1
+      && posixicity == POSIXLY_EXTENDED)
+    {
+      char buf[200];
+      sprintf(buf, _("invalid reference \\%d on `s' command's RHS"),
+	      needed_sub - 1);
+      bad_prog(buf);
+    }
+}
+
+struct regex *
+compile_regex(b, flags, needed_sub)
+  struct buffer *b;
+  int flags;
+  int needed_sub;
+{
+  struct regex *new_regex;
+  size_t re_len;
+
+  /* // matches the last RE */
+  if (size_buffer(b) == 0)
+    {
+      if (flags > 0)
+	bad_prog(_(BAD_MODIF));
+      return NULL;
+    }
+
+  re_len = size_buffer(b);
+  new_regex = ck_malloc(sizeof (struct regex) + re_len - 1);
+  new_regex->flags = flags;
+  memcpy (new_regex->re, get_buffer(b), re_len);
+
+#ifdef REG_PERL
+  new_regex->sz = re_len;
+#else
+  /* GNU regex does not process \t & co. */
+  new_regex->sz = normalize_text(new_regex->re, re_len, TEXT_REGEX);
+#endif
+
+  compile_regex_1 (new_regex, needed_sub);
+  return new_regex;
+}
+
+#ifdef REG_PERL
+static void
+copy_regs (regs, pmatch, nregs)
+     struct re_registers *regs;
+     regmatch_t *pmatch;
+     int nregs;
+{
+  int i;
+  int need_regs = nregs + 1;
+  /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
+     uses.  */
+
+  /* Have the register data arrays been allocated?  */
+  if (!regs->start)
+    { /* No.  So allocate them with malloc.  */
+      regs->start = MALLOC (need_regs, regoff_t);
+      regs->end = MALLOC (need_regs, regoff_t);
+      regs->num_regs = need_regs;
+    }
+  else if (need_regs > regs->num_regs)
+    { /* Yes.  We also need more elements than were already
+         allocated, so reallocate them.  */
+      regs->start = REALLOC (regs->start, need_regs, regoff_t);
+      regs->end = REALLOC (regs->end, need_regs, regoff_t);
+      regs->num_regs = need_regs;
+    }
+
+  /* Copy the regs.  */
+  for (i = 0; i < nregs; ++i)
+    {
+      regs->start[i] = pmatch[i].rm_so;
+      regs->end[i] = pmatch[i].rm_eo;
+    }
+  for ( ; i < regs->num_regs; ++i)
+    regs->start[i] = regs->end[i] = -1;
+}
+#endif
+
+int
+match_regex(regex, buf, buflen, buf_start_offset, regarray, regsize)
+  struct regex *regex;
+  char *buf;
+  size_t buflen;
+  size_t buf_start_offset;
+  struct re_registers *regarray;
+  int regsize;
+{
+  int ret;
+  static struct regex *regex_last;
+#ifdef REG_PERL
+  regmatch_t rm[10], *regmatch = rm;
+  if (regsize > 10)
+    regmatch = (regmatch_t *) alloca (sizeof (regmatch_t) * regsize);
+#endif
+
+  /* printf ("Matching from %d/%d\n", buf_start_offset, buflen); */
+
+  /* Keep track of the last regexp matched. */
+  if (!regex)
+    {
+      regex = regex_last;
+      if (!regex_last)
+	bad_prog(_(NO_REGEX));
+    }
+  else
+    regex_last = regex;
+
+#ifdef REG_PERL
+  regmatch[0].rm_so = CAST(int)buf_start_offset;
+  regmatch[0].rm_eo = CAST(int)buflen;
+  ret = regexec (&regex->pattern, buf, regsize, regmatch, REG_STARTEND);
+
+  if (regsize)
+    copy_regs (regarray, regmatch, regsize);
+
+  return (ret == 0);
+#else
+  if (regex->pattern.no_sub && regsize)
+    compile_regex_1 (regex, regsize);
+
+  regex->pattern.regs_allocated = REGS_REALLOCATE;
+
+  ret = re_search (&regex->pattern, buf, buflen, buf_start_offset,
+		   buflen - buf_start_offset,
+		   regsize ? regarray : NULL);
+
+  return (ret > -1);
+#endif
+}
+
+
+#ifdef DEBUG_LEAKS
+void
+release_regex(regex)
+  struct regex *regex;
+{
+  regfree(&regex->pattern);
+  FREE(regex);
+}
+#endif /*DEBUG_LEAKS*/
Index: /tags/kBuild-0.1.4/src/sed/sed/sed.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/sed.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/sed.c	(revision 1780)
@@ -0,0 +1,390 @@
+#define COPYRIGHT_NOTICE "Copyright (C) 2003 Free Software Foundation, Inc."
+#define BUG_ADDRESS "bonzini@gnu.org"
+
+/*  GNU SED, a batch stream editor.
+    Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003
+    Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+
+#include "sed.h"
+
+
+#include <stdio.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#else
+# include <string.h>
+#endif /*HAVE_STRINGS_H*/
+#ifdef HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#ifndef HAVE_STRCHR
+# define strchr index
+# define strrchr rindex
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include "getopt.h"
+
+#ifndef BOOTSTRAP
+#ifndef HAVE_STDLIB_H
+ extern char *getenv P_((const char *));
+#endif
+#endif
+
+#ifndef HAVE_STRTOUL
+# define ATOI(x)	atoi(x)
+#else
+# define ATOI(x)	strtoul(x, NULL, 0)
+#endif
+
+int extended_regexp_flags = 0;
+
+#ifndef CONFIG_WITHOUT_O_OPT
+/* The output file, defaults to stdout but can be overridden
+   by the -o or --output option. main sets this to avoid problems. */
+FILE *sed_stdout = NULL;
+#endif
+
+/* If set, fflush(stdout) on every line output. */
+bool unbuffered_output = false;
+
+/* If set, don't write out the line unless explicitly told to */
+bool no_default_output = false;
+
+/* If set, reset line counts on every new file. */
+bool separate_files = false;
+
+/* How do we edit files in-place? (we don't if NULL) */
+char *in_place_extension = NULL;
+
+/* Do we need to be pedantically POSIX compliant? */
+enum posixicity_types posixicity;
+
+/* How long should the `l' command's output line be? */
+countT lcmd_out_line_len = 70;
+
+/* The complete compiled SED program that we are going to run: */
+static struct vector *the_program = NULL;
+
+static void usage P_((int));
+static void
+usage(status)
+  int status;
+{
+  FILE *out = status ? stderr : stdout;
+
+#ifdef REG_PERL
+#define PERL_HELP _("  -R, --regexp-perl\n                 use Perl 5's regular expressions syntax in the script.\n")
+#else
+#define PERL_HELP ""
+#endif
+
+  fprintf(out, _("\
+Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n\
+\n"), myname);
+
+  fprintf(out, _("  -n, --quiet, --silent\n\
+                 suppress automatic printing of pattern space\n"));
+  fprintf(out, _("  -e script, --expression=script\n\
+                 add the script to the commands to be executed\n"));
+  fprintf(out, _("  -f script-file, --file=script-file\n\
+                 add the contents of script-file to the commands to be executed\n"));
+  fprintf(out, _("  -i[SUFFIX], --in-place[=SUFFIX]\n\
+                 edit files in place (makes backup if extension supplied)\n"));
+  fprintf(out, _("  -l N, --line-length=N\n\
+                 specify the desired line-wrap length for the `l' command\n"));
+  fprintf(out, _("  --posix\n\
+                 disable all GNU extensions.\n"));
+#ifndef CONFIG_WITHOUT_O_OPT
+  fprintf(out, _("  -o, --output=file, --append=file, --output-text=file,\n"));
+  fprintf(out, _("  --output-binary=file, --append-text=file, append-binary=file\n\
+                 use the specified file instead of stdout; the first\n\
+                 three uses the default text/binary mode.\n"));
+#endif
+  fprintf(out, _("  -r, --regexp-extended\n\
+                 use extended regular expressions in the script.\n"));
+  fprintf(out, PERL_HELP);
+  fprintf(out, _("  -s, --separate\n\
+                 consider files as separate rather than as a single continuous\n\
+                 long stream.\n"));
+  fprintf(out, _("  -u, --unbuffered\n\
+                 load minimal amounts of data from the input files and flush\n\
+                 the output buffers more often\n"));
+  fprintf(out, _("      --help     display this help and exit\n"));
+  fprintf(out, _("      --version  output version information and exit\n"));
+  fprintf(out, _("\n\
+If no -e, --expression, -f, or --file option is given, then the first\n\
+non-option argument is taken as the sed script to interpret.  All\n\
+remaining arguments are names of input files; if no input files are\n\
+specified, then the standard input is read.\n\
+\n"));
+  fprintf(out, _("E-mail bug reports to: %s .\n\
+Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"),
+	  BUG_ADDRESS, PACKAGE);
+
+  ck_fclose (NULL);
+  exit (status);
+}
+
+int
+main(argc, argv)
+  int argc;
+  char **argv;
+{
+#ifdef REG_PERL
+# ifndef CONFIG_WITHOUT_O_OPT
+#define SHORTOPTS "snrRue:f:l:i::o:V:"
+# else
+#define SHORTOPTS "snrRue:f:l:i::V:"
+# endif
+#else
+# ifndef CONFIG_WITHOUT_O_OPT
+#define SHORTOPTS "snrue:f:l:i::o:V:"
+# else
+#define SHORTOPTS "snrue:f:l:i::V:"
+# endif
+#endif
+
+  static struct option longopts[] = {
+    {"regexp-extended", 0, NULL, 'r'},
+#ifdef REG_PERL
+    {"regexp-perl", 0, NULL, 'R'},
+#endif
+    {"expression", 1, NULL, 'e'},
+    {"file", 1, NULL, 'f'},
+    {"in-place", 2, NULL, 'i'},
+    {"line-length", 1, NULL, 'l'},
+    {"quiet", 0, NULL, 'n'},
+    {"posix", 0, NULL, 'p'},
+    {"silent", 0, NULL, 'n'},
+    {"separate", 0, NULL, 's'},
+    {"unbuffered", 0, NULL, 'u'},
+#ifndef CONFIG_WITHOUT_O_OPT
+    {"output", 1, NULL, 'o'},
+    {"output-binary", 1, NULL, 300},
+    {"output-text", 1, NULL, 301},
+    {"append", 1, NULL, 302},
+    {"append-binary", 1, NULL, 303},
+    {"append-text", 1, NULL, 304},
+#endif
+    {"version", 0, NULL, 'v'},
+    {"help", 0, NULL, 'h'},
+    {NULL, 0, NULL, 0}
+  };
+
+  int opt;
+  int return_code;
+  const char *cols = getenv("COLS");
+
+  initialize_main (&argc, &argv);
+#ifndef CONFIG_WITHOUT_O_OPT
+  sed_stdout = stdout;
+#endif
+#if HAVE_SETLOCALE
+  /* Set locale according to user's wishes.  */
+#ifdef _MSC_VER
+  {
+    /* The redmond guys doesn't listen to the user in the same way... */
+    const char *lc_all = getenv ("LC_ALL");
+    if (lc_all)
+      setlocale (LC_ALL, lc_all);
+    else
+      {
+        const char *lc_lang = getenv ("LANG");
+        const char *lc_ctype = getenv ("LC_TYPE");
+        const char *lc_collate = getenv ("LC_COLLATE");
+
+        setlocale (LC_ALL, lc_lang ? lc_lang : "");
+        if (lc_ctype)
+          setlocale (LC_CTYPE, lc_ctype ? lc_ctype : "");
+        if (lc_collate)
+          setlocale (LC_COLLATE, lc_collate ? lc_collate : "");
+      }
+  }
+#else
+  setlocale (LC_ALL, "");
+#endif
+#endif
+  initialize_mbcs ();
+
+#if ENABLE_NLS
+
+  /* Tell program which translations to use and where to find.  */
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+#endif
+
+  if (getenv("POSIXLY_CORRECT") != NULL)
+    posixicity = POSIXLY_CORRECT;
+  else
+    posixicity = POSIXLY_EXTENDED;
+
+  /* If environment variable `COLS' is set, use its value for
+     the baseline setting of `lcmd_out_line_len'.  The "-1"
+     is to avoid gratuitous auto-line-wrap on ttys.
+   */
+  if (cols)
+    {
+      countT t = ATOI(cols);
+      if (t > 1)
+	lcmd_out_line_len = t-1;
+    }
+
+  myname = *argv;
+  while ((opt = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != EOF)
+    {
+      switch (opt)
+	{
+	case 'n':
+	  no_default_output = true;
+	  break;
+	case 'e':
+	  the_program = compile_string(the_program, optarg, strlen(optarg));
+	  break;
+	case 'f':
+	  the_program = compile_file(the_program, optarg);
+	  break;
+
+	case 'i':
+	  separate_files = true;
+	  if (optarg == NULL)
+	    /* use no backups */
+	    in_place_extension = ck_strdup ("*");
+
+	  else if (strchr(optarg, '*') != NULL)
+	    in_place_extension = ck_strdup(optarg);
+
+	  else
+	    {
+	      in_place_extension = MALLOC (strlen(optarg) + 2, char);
+	      in_place_extension[0] = '*';
+	      strcpy (in_place_extension + 1, optarg);
+	    }
+
+	  break;
+
+	case 'l':
+	  lcmd_out_line_len = ATOI(optarg);
+	  break;
+
+#ifndef CONFIG_WITHOUT_O_OPT
+        case 'o':
+          sed_stdout = ck_fopen (optarg, "w", true /* fail on error */);
+          break;
+
+        case 300:
+          sed_stdout = ck_fopen (optarg, "wb", true /* fail on error */);
+          break;
+
+        case 301:
+          sed_stdout = ck_fopen (optarg, "wt", true /* fail on error */);
+          break;
+
+        case 302:
+          sed_stdout = ck_fopen (optarg, "a", true /* fail on error */);
+          break;
+
+        case 303:
+          sed_stdout = ck_fopen (optarg, "ab", true /* fail on error */);
+          break;
+
+        case 304:
+          sed_stdout = ck_fopen (optarg, "at", true /* fail on error */);
+          break;
+#endif
+
+	case 'p':
+	  posixicity = POSIXLY_BASIC;
+	  break;
+
+	case 'r':
+	  if (extended_regexp_flags)
+	    usage(4);
+	  extended_regexp_flags = REG_EXTENDED;
+	  break;
+
+#ifdef REG_PERL
+	case 'R':
+	  if (extended_regexp_flags)
+	    usage(4);
+	  extended_regexp_flags = REG_PERL;
+	  break;
+#endif
+
+	case 's':
+	  separate_files = true;
+	  break;
+
+	case 'u':
+	  unbuffered_output = true;
+	  break;
+
+	case 'v':
+#ifdef KBUILD_VERSION_MAJOR
+	  fprintf(stdout, _("kmk_sed - kBuild version %d.%d.%d\n"
+                            "\n"
+                            "Based on "),
+	          KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH);
+#endif
+#ifdef REG_PERL
+	  fprintf(stdout, _("super-sed version %s\n"), VERSION);
+	  fprintf(stdout, _("based on GNU sed version %s\n\n"), SED_FEATURE_VERSION);
+#else
+	  fprintf(stdout, _("GNU sed version %s\n"), VERSION);
+#endif
+	  fprintf(stdout, _("%s\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\
+to the extent permitted by law.\n\
+"), COPYRIGHT_NOTICE);
+
+	  ck_fclose (NULL);
+	  exit (0);
+	case 'h':
+	  usage(0);
+	default:
+	  usage(4);
+	}
+    }
+
+  if (!the_program)
+    {
+      if (optind < argc)
+	{
+	  char *arg = argv[optind++];
+	  the_program = compile_string(the_program, arg, strlen(arg));
+	}
+      else
+	usage(4);
+    }
+  check_final_program(the_program);
+
+  return_code = process_files(the_program, argv+optind);
+
+  finish_program(the_program);
+  ck_fclose(NULL);
+
+  return return_code;
+}
Index: /tags/kBuild-0.1.4/src/sed/sed/sed.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/sed/sed.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/sed/sed.h	(revision 1780)
@@ -0,0 +1,276 @@
+/*  GNU SED, a batch stream editor.
+    Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003
+    Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "basicdefs.h"
+#include "regex.h"
+
+#ifndef BOOTSTRAP
+#include <stdio.h>
+#endif
+
+#include "utils.h"
+
+/* Struct vector is used to describe a compiled sed program. */
+struct vector {
+  struct sed_cmd *v;	/* a dynamically allocated array */
+  size_t v_allocated;	/* ... number slots allocated */
+  size_t v_length;	/* ... number of slots in use */
+};
+
+/* This structure tracks files used by sed so that they may all be
+   closed cleanly at normal program termination.  A flag is kept that tells
+   if a missing newline was encountered, so that it is added on the
+   next line and the two lines are not concatenated.  */
+struct output {
+  char *name;
+  bool missing_newline;
+  FILE *fp;
+  struct output *link;
+};
+
+struct text_buf {
+  char *text;
+  size_t text_length;
+};
+
+struct regex {
+  regex_t pattern;
+  int flags;
+  size_t sz;
+  char re[1];
+};
+  
+enum replacement_types {
+  REPL_ASIS = 0,
+  REPL_UPPERCASE = 1,
+  REPL_LOWERCASE = 2,
+  REPL_UPPERCASE_FIRST = 4,
+  REPL_LOWERCASE_FIRST = 8,
+  REPL_MODIFIERS = REPL_UPPERCASE_FIRST | REPL_LOWERCASE_FIRST,
+
+  /* These are given to aid in debugging */
+  REPL_UPPERCASE_UPPERCASE = REPL_UPPERCASE_FIRST | REPL_UPPERCASE,
+  REPL_UPPERCASE_LOWERCASE = REPL_UPPERCASE_FIRST | REPL_LOWERCASE,
+  REPL_LOWERCASE_UPPERCASE = REPL_LOWERCASE_FIRST | REPL_UPPERCASE,
+  REPL_LOWERCASE_LOWERCASE = REPL_LOWERCASE_FIRST | REPL_LOWERCASE
+};
+
+enum text_types {
+  TEXT_BUFFER,
+  TEXT_REPLACEMENT,
+  TEXT_REGEX
+};
+
+enum posixicity_types {
+  POSIXLY_EXTENDED,	/* with GNU extensions */
+  POSIXLY_CORRECT,	/* with POSIX-compatible GNU extensions */
+  POSIXLY_BASIC		/* pedantically POSIX */
+};
+
+enum addr_state {
+  RANGE_INACTIVE,	/* never been active */
+  RANGE_ACTIVE,		/* between first and second address */
+  RANGE_CLOSED		/* like RANGE_INACTIVE, but range has ended once */
+};
+
+enum addr_types {
+  ADDR_IS_NULL,		/* null address */
+  ADDR_IS_REGEX,	/* a.addr_regex is valid */
+  ADDR_IS_NUM,		/* a.addr_number is valid */
+  ADDR_IS_NUM_MOD,	/* a.addr_number is valid, addr_step is modulo */
+  ADDR_IS_STEP,		/* address is +N (only valid for addr2) */
+  ADDR_IS_STEP_MOD,	/* address is ~N (only valid for addr2) */
+  ADDR_IS_LAST		/* address is $ */
+};
+
+struct addr {
+  enum addr_types addr_type;
+  countT addr_number;
+  countT addr_step;
+  struct regex *addr_regex;
+};
+
+
+struct replacement {
+  char *prefix;
+  size_t prefix_length;
+  int subst_id;
+  enum replacement_types repl_type;
+  struct replacement *next;
+};
+
+struct subst {
+  struct regex *regx;
+  struct replacement *replacement;
+  countT numb;		/* if >0, only substitute for match number "numb" */
+  struct output *outf;	/* 'w' option given */
+  unsigned global : 1;	/* 'g' option given */
+  unsigned print : 2;	/* 'p' option given (before/after eval) */
+  unsigned eval : 1;	/* 'e' option given */
+  unsigned max_id : 4;  /* maximum backreference on the RHS */
+};
+
+#ifdef REG_PERL
+/* This is the structure we store register match data in.  See
+   regex.texinfo for a full description of what registers match.  */
+struct re_registers
+{
+  unsigned num_regs;
+  regoff_t *start;
+  regoff_t *end;
+};
+#endif
+
+
+
+struct sed_cmd {
+  struct addr *a1;	/* save space: usually is NULL */
+  struct addr *a2;
+
+  /* See description the enum, above.  */
+  enum addr_state range_state;
+
+  /* Non-zero if command is to be applied to non-matches. */
+  char addr_bang;
+
+  /* The actual command character. */
+  char cmd;
+
+  /* auxiliary data for various commands */
+  union {
+    /* This structure is used for a, i, and c commands. */
+    struct text_buf cmd_txt;
+
+    /* This is used for the l, q and Q commands. */
+    int int_arg;
+
+    /* This is used for the {}, b, and t commands. */
+    countT jump_index;
+
+    /* This is used for the r command. */
+    char *fname;
+
+    /* This is used for the hairy s command. */
+    struct subst *cmd_subst;
+
+    /* This is used for the w command. */
+    struct output *outf;
+
+    /* This is used for the R command. */
+    FILE *fp;
+
+    /* This is used for the y command. */
+    unsigned char *translate;
+    char **translatemb;
+  } x;
+};
+
+
+
+
+void bad_prog P_((const char *why));
+size_t normalize_text P_((char *text, size_t len, enum text_types buftype));
+struct vector *compile_string P_((struct vector *, char *str, size_t len));
+struct vector *compile_file P_((struct vector *, const char *cmdfile));
+void check_final_program P_((struct vector *));
+void rewind_read_files P_((void));
+void finish_program P_((struct vector *));
+
+struct regex *compile_regex P_((struct buffer *b, int flags, int needed_sub));
+int match_regex P_((struct regex *regex,
+		    char *buf, size_t buflen, size_t buf_start_offset,
+		    struct re_registers *regarray, int regsize));
+#ifdef DEBUG_LEAKS
+void release_regex P_((struct regex *));
+#endif
+
+int process_files P_((struct vector *, char **argv));
+
+int main P_((int, char **));
+
+extern void fmt P_ ((const char *line, const char *line_end, int max_length, FILE *output_file));
+
+extern int extended_regexp_flags;
+
+#ifndef CONFIG_WITHOUT_O_OPT
+/* The output file, defaults to stdout but can be overridden
+   by the -o or --output option. main sets this to avoid problems. */
+extern FILE *sed_stdout;
+#endif
+
+/* If set, fflush(stdout) on every line output. */
+extern bool unbuffered_output;
+
+/* If set, don't write out the line unless explicitly told to. */
+extern bool no_default_output;
+
+/* If set, reset line counts on every new file. */
+extern bool separate_files;
+
+/* Do we need to be pedantically POSIX compliant? */
+extern enum posixicity_types posixicity;
+
+/* How long should the `l' command's output line be? */
+extern countT lcmd_out_line_len;
+
+/* How do we edit files in-place? (we don't if NULL) */
+extern char *in_place_extension;
+
+/* Should we use EREs? */
+extern bool use_extended_syntax_p;
+
+/* Declarations for multibyte character sets.  */
+extern int mb_cur_max;
+
+#ifdef HAVE_MBRTOWC
+#ifdef HAVE_BTOWC
+#define MBRTOWC(pwc, s, n, ps) \
+  (mb_cur_max == 1 ? \
+   (*(pwc) = btowc (*(unsigned char *) (s)), 1) : \
+   mbrtowc ((pwc), (s), (n), (ps)))
+
+#define WCRTOMB(s, wc, ps) \
+  (mb_cur_max == 1 ? \
+   (*(s) = wctob ((wint_t) (wc)), 1) : \
+   wcrtomb ((s), (wc), (ps)))
+#else
+#define MBRTOWC(pwc, s, n, ps) \
+  mbrtowc ((pwc), (s), (n), (ps))
+
+#define WCRTOMB(s, wc, ps) \
+  wcrtomb ((s), (wc), (ps))
+#endif
+
+#define MBRLEN(s, n, ps) \
+  (mb_cur_max == 1 ? 1 : mbrtowc (NULL, s, n, ps))
+
+#define BRLEN(ch, ps) \
+  (mb_cur_max == 1 ? 1 : brlen (ch, ps))
+
+#else
+#define MBRLEN(s, n, ps) 1
+#define BRLEN(ch, ps) 1
+#endif
+
+extern int brlen P_ ((int ch, mbstate_t *ps));
+extern void initialize_mbcs P_ ((void));
+
Index: /tags/kBuild-0.1.4/src/sed/testsuite/0range.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/0range.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/0range.good	(revision 1780)
@@ -0,0 +1,1 @@
+yes
Index: /tags/kBuild-0.1.4/src/sed/testsuite/0range.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/0range.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/0range.inp	(revision 1780)
@@ -0,0 +1,6 @@
+1
+2
+3
+4
+aaa
+yes
Index: /tags/kBuild-0.1.4/src/sed/testsuite/0range.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/0range.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/0range.sed	(revision 1780)
@@ -0,0 +1,1 @@
+0,/aaa/d
Index: /tags/kBuild-0.1.4/src/sed/testsuite/8bit.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/8bit.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/8bit.sed	(revision 1780)
@@ -0,0 +1,21 @@
+# The first poem from the Man'yoshu.  I like Hitomaro's poems better
+# but I couldn't find a copy of any of them in Japanese.  This version
+# of this poem is from $BNc2r8E8l<-E5(B($BBh;0HG(B)$B;0>JF2(B.
+#
+# Speaking of Hitomaro, here is the english translation of one of my
+# favorites.  I just know that everyone reading these test cases wants
+# to see this.
+#
+#  In the autumn mountains
+#  The yellow leaves are so thick.
+#  Alas, how shall I seek my love
+#  Who has wandered away?
+#
+#  I see the messenger come
+#  As the yellow leaves are falling.
+#  Oh, well I remember
+#  How on such a day we used to meet--
+#  My lover and I!
+#       -- Kakinomoto Hitomaro 
+#
+s/ÂçÏÂ/ÆüËÜ/
Index: /tags/kBuild-0.1.4/src/sed/testsuite/8to7.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/8to7.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/8to7.good	(revision 1780)
@@ -0,0 +1,14 @@
+\344\306\244\342\244\350 \244\337\344\306\273\375\244\301$
+\267\241\266\372\244\342\244\350 \244\337\267\241\266\372\273\375\244\
+\301$
+\244\263\244\316\265\326\244\313 \272\332\305\246\244\336\244\271\273\
+\371$
+\262\310\264\326\244\253\244\312 \271\360\244\351\244\265\244\315$
+\244\275\244\351\244\337\244\304 \302\347\317\302\244\316\271\361\244\
+\317$
+\244\252\244\267\244\343\244\312\244\331\244\306 \244\357\244\354\244\
+\263\244\275\265\357\244\354$
+\244\267\244\255\244\312\244\331\244\306 \244\357\244\354\244\263\244\
+\275 \272\302\244\273$
+\244\357\244\313\244\263\244\275\244\317 \271\360\244\351\244\341$
+\262\310\244\362\244\342\314\276\244\362\244\342$
Index: /tags/kBuild-0.1.4/src/sed/testsuite/8to7.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/8to7.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/8to7.sed	(revision 1780)
@@ -0,0 +1,1 @@
+l;d
Index: /tags/kBuild-0.1.4/src/sed/testsuite/BOOST.tests
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/BOOST.tests	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/BOOST.tests	(revision 1780)
@@ -0,0 +1,829 @@
+; 
+; 
+; this file contains a script of tests to run through regress.exe
+;
+; comments start with a semicolon and proceed to the end of the line
+;
+; changes to regular expression compile flags start with a "-" as the first
+; non-whitespace character and consist of a list of the printable names
+; of the flags, for example "match_default"
+;
+; Other lines contain a test to perform using the current flag status
+; the first token contains the expression to compile, the second the string
+; to match it against. If the second string is "!" then the expression should
+; not compile, that is the first string is an invalid regular expression.
+; This is then followed by a list of integers that specify what should match,
+; each pair represents the starting and ending positions of a subexpression
+; starting with the zeroth subexpression (the whole match).
+; A value of -1 indicates that the subexpression should not take part in the
+; match at all, if the first value is -1 then no part of the expression should
+; match the string.
+;
+; Tests taken from BOOST testsuite and adapted to glibc regex.
+;
+; Boost Software License - Version 1.0 - August 17th, 2003
+;
+; Permission is hereby granted, free of charge, to any person or organization
+; obtaining a copy of the software and accompanying documentation covered by
+; this license (the "Software") to use, reproduce, display, distribute,
+; execute, and transmit the Software, and to prepare derivative works of the
+; Software, and to permit third-parties to whom the Software is furnished to
+; do so, all subject to the following:
+;
+; The copyright notices in the Software and this entire statement, including
+; the above license grant, this restriction and the following disclaimer,
+; must be included in all copies of the Software, in whole or in part, and
+; all derivative works of the Software, unless such copies or derivative
+; works are solely in the form of machine-executable object code generated by
+; a source language processor.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+; FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+; SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+; FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+; ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+; DEALINGS IN THE SOFTWARE.
+;
+
+- match_default normal REG_EXTENDED
+
+;
+; try some really simple literals:
+a a 0 1
+Z Z 0 1
+Z aaa -1 -1
+Z xxxxZZxxx 4 5
+
+; and some simple brackets:
+(a) zzzaazz 3 4 3 4
+() zzz 0 0 0 0
+() "" 0 0 0 0
+( !
+) ) 0 1
+(aa !
+aa) baa)b 1 4
+a b -1 -1
+\(\) () 0 2
+\(a\) (a) 0 3
+\() () 0 2
+(\) !
+p(a)rameter ABCparameterXYZ 3 12 4 5
+[pq](a)rameter ABCparameterXYZ 3 12 4 5
+
+; now try escaped brackets:
+- match_default bk_parens REG_BASIC
+\(a\) zzzaazz 3 4 3 4
+\(\) zzz 0 0 0 0
+\(\) "" 0 0 0 0
+\( !
+\) !
+\(aa !
+aa\) !
+() () 0 2
+(a) (a) 0 3
+(\) !
+\() !
+
+; now move on to "." wildcards
+- match_default normal REG_EXTENDED REG_STARTEND
+. a 0 1
+. \n 0 1
+. \r 0 1
+. \0 0 1
+
+;
+; now move on to the repetion ops,
+; starting with operator *
+- match_default normal REG_EXTENDED
+a* b 0 0
+ab* a 0 1
+ab* ab 0 2
+ab* sssabbbbbbsss 3 10
+ab*c* a 0 1
+ab*c* abbb 0 4
+ab*c* accc 0 4
+ab*c* abbcc 0 5
+*a !
+\<* !
+\>* !
+\n* \n\n 0 2
+\** ** 0 2
+\* * 0 1
+
+; now try operator +
+ab+ a -1 -1
+ab+ ab 0 2
+ab+ sssabbbbbbsss 3 10
+ab+c+ a -1 -1
+ab+c+ abbb -1 -1
+ab+c+ accc -1 -1
+ab+c+ abbcc 0 5
++a !
+\<+ !
+\>+ !
+\n+ \n\n 0 2
+\+ + 0 1
+\+ ++ 0 1
+\++ ++ 0 2
+
+; now try operator ?
+- match_default normal REG_EXTENDED
+a? b 0 0
+ab? a 0 1
+ab? ab 0 2
+ab? sssabbbbbbsss 3 5
+ab?c? a 0 1
+ab?c? abbb 0 2
+ab?c? accc 0 2
+ab?c? abcc 0 3
+?a !
+\<? !
+\>? !
+\n? \n\n 0 1
+\? ? 0 1
+\? ?? 0 1
+\?? ?? 0 1
+
+; now try operator {}
+- match_default normal REG_EXTENDED
+a{2} a -1 -1
+a{2} aa 0 2
+a{2} aaa 0 2
+a{2,} a -1 -1
+a{2,} aa 0 2
+a{2,} aaaaa 0 5
+a{2,4} a -1 -1
+a{2,4} aa 0 2
+a{2,4} aaa 0 3
+a{2,4} aaaa 0 4
+a{2,4} aaaaa 0 4
+a{} !
+a{2 !
+a} a} 0 2
+\{\} {} 0 2
+
+- match_default normal REG_BASIC
+a\{2\} a -1 -1
+a\{2\} aa 0 2
+a\{2\} aaa 0 2
+a\{2,\} a -1 -1
+a\{2,\} aa 0 2
+a\{2,\} aaaaa 0 5
+a\{2,4\} a -1 -1
+a\{2,4\} aa 0 2
+a\{2,4\} aaa 0 3
+a\{2,4\} aaaa 0 4
+a\{2,4\} aaaaa 0 4
+{} {} 0 2
+
+; now test the alternation operator |
+- match_default normal REG_EXTENDED
+a|b a 0 1
+a|b b 0 1
+a(b|c) ab 0 2 1 2
+a(b|c) ac 0 2 1 2
+a(b|c) ad -1 -1 -1 -1
+a\| a| 0 2
+
+; now test the set operator []
+- match_default normal REG_EXTENDED
+; try some literals first
+[abc] a 0 1
+[abc] b 0 1
+[abc] c 0 1
+[abc] d -1 -1
+[^bcd] a 0 1
+[^bcd] b -1 -1
+[^bcd] d -1 -1
+[^bcd] e 0 1
+a[b]c abc 0 3
+a[ab]c abc 0 3
+a[^ab]c adc 0 3
+a[]b]c a]c 0 3
+a[[b]c a[c 0 3
+a[-b]c a-c 0 3
+a[^]b]c adc 0 3
+a[^-b]c adc 0 3
+a[b-]c a-c 0 3
+a[b !
+a[] !
+
+; then some ranges
+[b-e] a -1 -1
+[b-e] b 0 1
+[b-e] e 0 1
+[b-e] f -1 -1
+[^b-e] a 0 1
+[^b-e] b -1 -1
+[^b-e] e -1 -1
+[^b-e] f 0 1
+a[1-3]c a2c 0 3
+a[3-1]c !
+a[1-3-5]c !
+a[1- !
+
+; and some classes
+a[[:alpha:]]c abc 0 3
+a[[:unknown:]]c !
+a[[: !
+a[[:alpha !
+a[[:alpha:] !
+a[[:alpha,:] !
+a[[:]:]]b !
+a[[:-:]]b !
+a[[:alph:]] !
+a[[:alphabet:]] !
+[[:alnum:]]+ -%@a0X_- 3 6
+[[:alpha:]]+ -%@aX_0- 3 5
+[[:blank:]]+ "a  \tb" 1 4
+[[:cntrl:]]+ a\n\tb 1 3
+[[:digit:]]+ a019b 1 4
+[[:graph:]]+ " a%b " 1 4
+[[:lower:]]+ AabC 1 3
+; This test fails with STLPort, disable for now as this is a corner case anyway...
+;[[:print:]]+ "\na b\n" 1 4
+[[:punct:]]+ " %-&\t" 1 4
+[[:space:]]+ "a \n\t\rb" 1 5
+[[:upper:]]+ aBCd 1 3
+[[:xdigit:]]+ p0f3Cx 1 5
+
+; now test flag settings:
+- escape_in_lists REG_NO_POSIX_TEST
+[\n] \n 0 1
+- REG_NO_POSIX_TEST
+
+; line anchors
+- match_default normal REG_EXTENDED
+^ab ab 0 2
+^ab xxabxx -1 -1
+ab$ ab 0 2
+ab$ abxx -1 -1
+- match_default match_not_bol match_not_eol normal REG_EXTENDED REG_NOTBOL REG_NOTEOL
+^ab ab -1 -1
+^ab xxabxx -1 -1
+ab$ ab -1 -1
+ab$ abxx -1 -1
+
+; back references
+- match_default normal REG_PERL
+a(b)\2c	!
+a(b\1)c	!
+a(b*)c\1d abbcbbd 0 7 1 3
+a(b*)c\1d abbcbd -1 -1
+a(b*)c\1d abbcbbbd -1 -1
+^(.)\1 abc -1 -1
+a([bc])\1d abcdabbd	4 8 5 6
+; strictly speaking this is at best ambiguous, at worst wrong, this is what most
+; re implimentations will match though.
+a(([bc])\2)*d abbccd 0 6 3 5 3 4
+
+a(([bc])\2)*d abbcbd -1 -1
+a((b)*\2)*d abbbd 0 5 1 4 2 3
+; perl only:
+(ab*)[ab]*\1 ababaaa 0 7 0 1
+(a)\1bcd aabcd 0 5 0 1
+(a)\1bc*d aabcd 0 5 0 1
+(a)\1bc*d aabd 0 4 0 1
+(a)\1bc*d aabcccd 0 7 0 1
+(a)\1bc*[ce]d aabcccd 0 7 0 1
+^(a)\1b(c)*cd$ aabcccd 0 7 0 1 4 5
+
+; posix only: 
+- match_default extended REG_EXTENDED
+(ab*)[ab]*\1 ababaaa 0 7 0 1
+
+;
+; word operators:
+\w a 0 1
+\w z 0 1
+\w A 0 1
+\w Z 0 1
+\w _ 0 1
+\w } -1 -1
+\w ` -1 -1
+\w [ -1 -1
+\w @ -1 -1
+; non-word:
+\W a -1 -1
+\W z -1 -1
+\W A -1 -1
+\W Z -1 -1
+\W _ -1 -1
+\W } 0 1
+\W ` 0 1
+\W [ 0 1
+\W @ 0 1
+; word start:
+\<abcd "  abcd" 2 6
+\<ab cab -1 -1
+\<ab "\nab" 1 3
+\<tag ::tag 2 5
+;word end:
+abc\> abc 0 3
+abc\> abcd -1 -1
+abc\> abc\n 0 3
+abc\> abc:: 0 3
+; word boundary:
+\babcd "  abcd" 2 6
+\bab cab -1 -1
+\bab "\nab" 1 3
+\btag ::tag 2 5
+abc\b abc 0 3
+abc\b abcd -1 -1
+abc\b abc\n 0 3
+abc\b abc:: 0 3
+; within word:
+\B ab 1 1
+a\Bb ab 0 2
+a\B ab 0 1
+a\B a -1 -1
+a\B "a " -1 -1
+
+;
+; buffer operators:
+\`abc abc 0 3
+\`abc \nabc -1 -1
+\`abc " abc" -1 -1
+abc\' abc 0 3
+abc\' abc\n -1 -1
+abc\' "abc " -1 -1
+
+;
+; now follows various complex expressions designed to try and bust the matcher:
+a(((b)))c abc 0 3 1 2 1 2 1 2
+a(b|(c))d abd 0 3 1 2 -1 -1
+a(b|(c))d acd 0 3 1 2 1 2
+a(b*|c)d abbd 0 4 1 3
+; just gotta have one DFA-buster, of course
+a[ab]{20} aaaaabaaaabaaaabaaaab 0 21
+; and an inline expansion in case somebody gets tricky
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] aaaaabaaaabaaaabaaaab 0 21
+; and in case somebody just slips in an NFA...
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) aaaaabaaaabaaaabaaaabweeknights 0 31 21 24 24 31
+; one really big one
+1234567890123456789012345678901234567890123456789012345678901234567890 a1234567890123456789012345678901234567890123456789012345678901234567890b 1 71
+; fish for problems as brackets go past 8
+[ab][cd][ef][gh][ij][kl][mn] xacegikmoq 1 8
+[ab][cd][ef][gh][ij][kl][mn][op] xacegikmoq 1 9
+[ab][cd][ef][gh][ij][kl][mn][op][qr] xacegikmoqy 1 10
+[ab][cd][ef][gh][ij][kl][mn][op][q] xacegikmoqy 1 10
+; and as parenthesis go past 9:
+(a)(b)(c)(d)(e)(f)(g)(h) zabcdefghi 1 9 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9
+(a)(b)(c)(d)(e)(f)(g)(h)(i) zabcdefghij 1 10 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10
+(a)(b)(c)(d)(e)(f)(g)(h)(i)(j) zabcdefghijk 1 11 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11
+(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k) zabcdefghijkl 1 12 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12
+(a)d|(b)c abc 1 3 -1 -1 1 2
+_+((www)|(ftp)|(mailto)):_* "_wwwnocolon _mailto:" 12 20 13 19 -1 -1 -1 -1 13 19
+
+; subtleties of matching
+;a(b)?c\1d acd 0 3 -1 -1
+; POSIX is about the following test:
+a(b)?c\1d acd -1 -1 -1 -1
+a(b?c)+d accd 0 4 2 3
+(wee|week)(knights|night) weeknights 0 10 0 3 3 10
+.* abc 0 3
+a(b|(c))d abd 0 3 1 2 -1 -1
+a(b|(c))d acd 0 3 1 2 1 2
+a(b*|c|e)d abbd 0 4 1 3
+a(b*|c|e)d acd 0 3 1 2
+a(b*|c|e)d ad 0 2 1 1
+a(b?)c abc 0 3 1 2
+a(b?)c ac 0 2 1 1
+a(b+)c abc 0 3 1 2
+a(b+)c abbbc 0 5 1 4 
+a(b*)c ac 0 2 1 1 
+(a|ab)(bc([de]+)f|cde) abcdef 0 6 0 1 1 6 3 5
+a([bc]?)c abc 0 3 1 2
+a([bc]?)c ac 0 2 1 1 
+a([bc]+)c abc 0 3 1 2
+a([bc]+)c abcc 0 4 1 3
+a([bc]+)bc abcbc 0 5 1 3
+a(bb+|b)b abb 0 3 1 2
+a(bbb+|bb+|b)b abb 0 3 1 2
+a(bbb+|bb+|b)b abbb 0 4 1 3
+a(bbb+|bb+|b)bb abbb 0 4 1 2
+(.*).* abcdef 0 6 0 6
+(a*)* bc 0 0 0 0
+xyx*xz xyxxxxyxxxz 5 11
+
+; do we get the right subexpression when it is used more than once?
+a(b|c)*d ad 0 2 -1 -1
+a(b|c)*d abcd 0 4 2 3
+a(b|c)+d abd 0 3 1 2
+a(b|c)+d abcd 0 4 2 3
+a(b|c?)+d ad 0 2 1 1
+a(b|c){0,0}d ad 0 2 -1 -1
+a(b|c){0,1}d ad 0 2 -1 -1
+a(b|c){0,1}d abd 0 3 1 2
+a(b|c){0,2}d ad 0 2 -1 -1
+a(b|c){0,2}d abcd 0 4 2 3
+a(b|c){0,}d ad 0 2 -1 -1
+a(b|c){0,}d abcd 0 4 2 3
+a(b|c){1,1}d abd 0 3 1 2
+a(b|c){1,2}d abd 0 3 1 2
+a(b|c){1,2}d abcd 0 4 2 3
+a(b|c){1,}d abd 0 3 1 2
+a(b|c){1,}d abcd 0 4 2 3
+a(b|c){2,2}d acbd 0 4 2 3
+a(b|c){2,2}d abcd 0 4 2 3
+a(b|c){2,4}d abcd 0 4 2 3
+a(b|c){2,4}d abcbd 0 5 3 4
+a(b|c){2,4}d abcbcd 0 6 4 5
+a(b|c){2,}d abcd 0 4 2 3
+a(b|c){2,}d abcbd 0 5 3 4
+; perl only: these conflict with the POSIX test below
+;a(b|c?)+d abcd 0 4 3 3
+;a(b+|((c)*))+d abd 0 3 2 2 2 2 -1 -1
+;a(b+|((c)*))+d abcd 0 4 3 3 3 3 2 3
+
+; posix only:
+- match_default extended REG_EXTENDED REG_STARTEND
+
+a(b|c?)+d abcd 0 4 2 3
+a(b|((c)*))+d abcd 0 4 2 3 2 3 2 3
+a(b+|((c)*))+d abd 0 3 1 2 -1 -1 -1 -1
+a(b+|((c)*))+d abcd 0 4 2 3 2 3 2 3
+a(b|((c)*))+d ad 0 2 1 1 1 1 -1 -1
+a(b|((c)*))*d abcd 0 4 2 3 2 3 2 3
+a(b+|((c)*))*d abd 0 3 1 2 -1 -1 -1 -1
+a(b+|((c)*))*d abcd 0 4 2 3 2 3 2 3
+a(b|((c)*))*d ad 0 2 1 1 1 1 -1 -1
+
+- match_default normal REG_PERL
+; try to match C++ syntax elements:
+; line comment:
+//[^\n]* "++i //here is a line comment\n" 4 28
+; block comment:
+/\*([^*]|\*+[^*/])*\*+/ "/* here is a block comment */" 0 29 26 27
+/\*([^*]|\*+[^*/])*\*+/ "/**/" 0 4 -1 -1
+/\*([^*]|\*+[^*/])*\*+/ "/***/" 0 5 -1 -1
+/\*([^*]|\*+[^*/])*\*+/ "/****/" 0 6 -1 -1
+/\*([^*]|\*+[^*/])*\*+/ "/*****/" 0 7 -1 -1
+/\*([^*]|\*+[^*/])*\*+/ "/*****/*/" 0 7 -1 -1
+; preprossor directives:
+^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol" 0 19 -1 -1
+^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol(x) #x" 0 25 -1 -1
+; perl only:
+^[[:blank:]]*#([^\n]*\\[[:space:]]+)*[^\n]* "#define some_symbol(x) \\  \r\n  foo();\\\r\n   printf(#x);" 0 53 30 42
+; literals:
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFF         						0 4		0 4		0 4 	-1 -1 	-1 -1 	-1 -1 	-1 -1
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 35 									0 2 	0 2		-1 -1 	0 2 	-1 -1 	-1 -1 	-1 -1
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFu 								0 5		0 4		0 4 	-1 -1 	-1 -1 	-1 -1 	-1 -1
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFL 								0 5		0 4		0 4 	-1 -1 	4 5 	-1 -1 	-1 -1
+((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)? 0xFFFFFFFFFFFFFFFFuint64 			0 24	0 18	0 18 	-1 -1 	19 24 	19 24 	22 24
+; strings:
+'([^\\']|\\.)*' '\\x3A' 0 6 4 5
+'([^\\']|\\.)*' '\\'' 0 4 1 3
+'([^\\']|\\.)*' '\\n' 0 4 1 3
+
+; finally try some case insensitive matches:
+- match_default normal REG_EXTENDED REG_ICASE
+; upper and lower have no meaning here so they fail, however these
+; may compile with other libraries...
+;[[:lower:]] !
+;[[:upper:]] !
+0123456789@abcdefghijklmnopqrstuvwxyz\[\\\]\^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ\{\|\} 0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\^_`abcdefghijklmnopqrstuvwxyz\{\|\} 0 72
+
+; known and suspected bugs:
+- match_default normal REG_EXTENDED
+\( ( 0 1
+\) ) 0 1
+\$ $ 0 1
+\^ ^ 0 1
+\. . 0 1
+\* * 0 1
+\+ + 0 1
+\? ? 0 1
+\[ [ 0 1
+\] ] 0 1
+\| | 0 1
+\\ \\ 0 1
+# # 0 1
+\# # 0 1
+a- a- 0 2
+\- - 0 1
+\{ { 0 1
+\} } 0 1
+0 0 0 1
+1 1 0 1
+9 9 0 1
+b b 0 1
+B B 0 1
+< < 0 1
+> > 0 1
+w w 0 1
+W W 0 1
+` ` 0 1
+' ' 0 1
+\n \n 0 1
+, , 0 1
+a a 0 1
+f f 0 1
+n n 0 1
+r r 0 1
+t t 0 1
+v v 0 1
+c c 0 1
+x x 0 1
+: : 0 1
+(\.[[:alnum:]]+){2} "w.a.b " 1 5 3 5
+
+- match_default normal REG_EXTENDED REG_ICASE
+a A 0 1
+A a 0 1
+[abc]+ abcABC 0 6
+[ABC]+ abcABC 0 6
+[a-z]+ abcABC 0 6
+[A-Z]+ abzANZ 0 6
+[a-Z]+ abzABZ 0 6
+[A-z]+ abzABZ 0 6
+[[:lower:]]+ abyzABYZ 0 8
+[[:upper:]]+ abzABZ 0 6
+[[:alpha:]]+ abyzABYZ 0 8
+[[:alnum:]]+ 09abyzABYZ 0 10
+
+; word start:
+\<abcd "  abcd" 2 6
+\<ab cab -1 -1
+\<ab "\nab" 1 3
+\<tag ::tag 2 5
+;word end:
+abc\> abc 0 3
+abc\> abcd -1 -1
+abc\> abc\n 0 3
+abc\> abc:: 0 3
+
+; collating elements and rewritten set code:
+- match_default normal REG_EXTENDED REG_STARTEND
+;[[.zero.]] 0 0 1
+;[[.one.]] 1 0 1
+;[[.two.]] 2 0 1
+;[[.three.]] 3 0 1
+[[.a.]] baa 1 2
+;[[.right-curly-bracket.]] } 0 1
+;[[.NUL.]] \0 0 1
+[[:<:]z] !
+[a[:>:]] !
+[[=a=]] a 0 1
+;[[=right-curly-bracket=]] } 0 1
+- match_default normal REG_EXTENDED REG_STARTEND REG_ICASE
+[[.A.]] A 0 1
+[[.A.]] a 0 1
+[[.A.]-b]+ AaBb 0 4
+[A-[.b.]]+ AaBb 0 4
+[[.a.]-B]+ AaBb 0 4
+[a-[.B.]]+ AaBb 0 4
+- match_default normal REG_EXTENDED REG_STARTEND
+[[.a.]-c]+ abcd 0 3
+[a-[.c.]]+ abcd 0 3
+[[:alpha:]-a] !
+[a-[:alpha:]] !
+
+; try mutli-character ligatures:
+;[[.ae.]] ae 0 2
+;[[.ae.]] aE -1 -1
+;[[.AE.]] AE 0 2
+;[[.Ae.]] Ae 0 2
+;[[.ae.]-b] a -1 -1
+;[[.ae.]-b] b 0 1
+;[[.ae.]-b] ae 0 2
+;[a-[.ae.]] a 0 1
+;[a-[.ae.]] b -1 -1
+;[a-[.ae.]] ae 0 2
+- match_default normal REG_EXTENDED REG_STARTEND REG_ICASE
+;[[.ae.]] AE 0 2
+;[[.ae.]] Ae 0 2
+;[[.AE.]] Ae 0 2
+;[[.Ae.]] aE 0 2
+;[[.AE.]-B] a -1 -1
+;[[.Ae.]-b] b 0 1
+;[[.Ae.]-b] B 0 1
+;[[.ae.]-b] AE 0 2
+
+- match_default normal REG_EXTENDED REG_STARTEND REG_NO_POSIX_TEST
+\s+ "ab   ab" 2 5
+\S+ "  abc  " 2 5
+
+- match_default normal REG_EXTENDED REG_STARTEND
+\`abc abc 0 3
+\`abc aabc -1 -1
+abc\' abc 0 3
+abc\' abcd -1 -1
+abc\' abc\n\n -1 -1
+abc\' abc 0 3
+
+; extended repeat checking to exercise new algorithms:
+ab.*xy abxy_ 0 4
+ab.*xy ab_xy_ 0 5
+ab.*xy abxy 0 4
+ab.*xy ab_xy 0 5
+ab.* ab 0 2
+ab.* ab__ 0 4
+
+ab.{2,5}xy ab__xy_ 0 6
+ab.{2,5}xy ab____xy_ 0 8
+ab.{2,5}xy ab_____xy_ 0 9
+ab.{2,5}xy ab__xy 0 6
+ab.{2,5}xy ab_____xy 0 9
+ab.{2,5} ab__ 0 4
+ab.{2,5} ab_______ 0 7
+ab.{2,5}xy ab______xy -1 -1
+ab.{2,5}xy ab_xy -1 -1
+
+ab.*?xy abxy_ 0 4
+ab.*?xy ab_xy_ 0 5
+ab.*?xy abxy 0 4
+ab.*?xy ab_xy 0 5
+ab.*? ab 0 2
+ab.*? ab__ 0 4
+
+ab.{2,5}?xy ab__xy_ 0 6
+ab.{2,5}?xy ab____xy_ 0 8
+ab.{2,5}?xy ab_____xy_ 0 9
+ab.{2,5}?xy ab__xy 0 6
+ab.{2,5}?xy ab_____xy 0 9
+ab.{2,5}? ab__ 0 4
+ab.{2,5}? ab_______ 0 7
+ab.{2,5}?xy ab______xy -1 -1
+ab.{2,5}xy ab_xy -1 -1
+
+; again but with slower algorithm variant:
+- match_default REG_EXTENDED
+; now again for single character repeats:
+
+ab_*xy abxy_ 0 4
+ab_*xy ab_xy_ 0 5
+ab_*xy abxy 0 4
+ab_*xy ab_xy 0 5
+ab_* ab 0 2
+ab_* ab__ 0 4
+
+ab_{2,5}xy ab__xy_ 0 6
+ab_{2,5}xy ab____xy_ 0 8
+ab_{2,5}xy ab_____xy_ 0 9
+ab_{2,5}xy ab__xy 0 6
+ab_{2,5}xy ab_____xy 0 9
+ab_{2,5} ab__ 0 4
+ab_{2,5} ab_______ 0 7
+ab_{2,5}xy ab______xy -1 -1
+ab_{2,5}xy ab_xy -1 -1
+
+ab_*?xy abxy_ 0 4
+ab_*?xy ab_xy_ 0 5
+ab_*?xy abxy 0 4
+ab_*?xy ab_xy 0 5
+ab_*? ab 0 2
+ab_*? ab__ 0 4
+
+ab_{2,5}?xy ab__xy_ 0 6
+ab_{2,5}?xy ab____xy_ 0 8
+ab_{2,5}?xy ab_____xy_ 0 9
+ab_{2,5}?xy ab__xy 0 6
+ab_{2,5}?xy ab_____xy 0 9
+ab_{2,5}? ab__ 0 4
+ab_{2,5}? ab_______ 0 7
+ab_{2,5}?xy ab______xy -1 -1
+ab_{2,5}xy ab_xy -1 -1
+
+; and again for sets:
+ab[_,;]*xy abxy_ 0 4
+ab[_,;]*xy ab_xy_ 0 5
+ab[_,;]*xy abxy 0 4
+ab[_,;]*xy ab_xy 0 5
+ab[_,;]* ab 0 2
+ab[_,;]* ab__ 0 4
+
+ab[_,;]{2,5}xy ab__xy_ 0 6
+ab[_,;]{2,5}xy ab____xy_ 0 8
+ab[_,;]{2,5}xy ab_____xy_ 0 9
+ab[_,;]{2,5}xy ab__xy 0 6
+ab[_,;]{2,5}xy ab_____xy 0 9
+ab[_,;]{2,5} ab__ 0 4
+ab[_,;]{2,5} ab_______ 0 7
+ab[_,;]{2,5}xy ab______xy -1 -1
+ab[_,;]{2,5}xy ab_xy -1 -1
+
+ab[_,;]*?xy abxy_ 0 4
+ab[_,;]*?xy ab_xy_ 0 5
+ab[_,;]*?xy abxy 0 4
+ab[_,;]*?xy ab_xy 0 5
+ab[_,;]*? ab 0 2
+ab[_,;]*? ab__ 0 4
+
+ab[_,;]{2,5}?xy ab__xy_ 0 6
+ab[_,;]{2,5}?xy ab____xy_ 0 8
+ab[_,;]{2,5}?xy ab_____xy_ 0 9
+ab[_,;]{2,5}?xy ab__xy 0 6
+ab[_,;]{2,5}?xy ab_____xy 0 9
+ab[_,;]{2,5}? ab__ 0 4
+ab[_,;]{2,5}? ab_______ 0 7
+ab[_,;]{2,5}?xy ab______xy -1 -1
+ab[_,;]{2,5}xy ab_xy -1 -1
+
+; and again for tricky sets with digraphs:
+;ab[_[.ae.]]*xy abxy_ 0 4
+;ab[_[.ae.]]*xy ab_xy_ 0 5
+;ab[_[.ae.]]*xy abxy 0 4
+;ab[_[.ae.]]*xy ab_xy 0 5
+;ab[_[.ae.]]* ab 0 2
+;ab[_[.ae.]]* ab__ 0 4
+
+;ab[_[.ae.]]{2,5}xy ab__xy_ 0 6
+;ab[_[.ae.]]{2,5}xy ab____xy_ 0 8
+;ab[_[.ae.]]{2,5}xy ab_____xy_ 0 9
+;ab[_[.ae.]]{2,5}xy ab__xy 0 6
+;ab[_[.ae.]]{2,5}xy ab_____xy 0 9
+;ab[_[.ae.]]{2,5} ab__ 0 4
+;ab[_[.ae.]]{2,5} ab_______ 0 7
+;ab[_[.ae.]]{2,5}xy ab______xy -1 -1
+;ab[_[.ae.]]{2,5}xy ab_xy -1 -1
+
+;ab[_[.ae.]]*?xy abxy_ 0 4
+;ab[_[.ae.]]*?xy ab_xy_ 0 5
+;ab[_[.ae.]]*?xy abxy 0 4
+;ab[_[.ae.]]*?xy ab_xy 0 5
+;ab[_[.ae.]]*? ab 0 2
+;ab[_[.ae.]]*? ab__ 0 2
+
+;ab[_[.ae.]]{2,5}?xy ab__xy_ 0 6
+;ab[_[.ae.]]{2,5}?xy ab____xy_ 0 8
+;ab[_[.ae.]]{2,5}?xy ab_____xy_ 0 9
+;ab[_[.ae.]]{2,5}?xy ab__xy 0 6
+;ab[_[.ae.]]{2,5}?xy ab_____xy 0 9
+;ab[_[.ae.]]{2,5}? ab__ 0 4
+;ab[_[.ae.]]{2,5}? ab_______ 0 4
+;ab[_[.ae.]]{2,5}?xy ab______xy -1 -1
+;ab[_[.ae.]]{2,5}xy ab_xy -1 -1
+
+; new bugs detected in spring 2003:
+- normal match_continuous REG_NO_POSIX_TEST
+b abc 1 2
+
+() abc 0 0 0 0
+^() abc 0 0 0 0
+^()+ abc 0 0 0 0
+^(){1} abc 0 0 0 0
+^(){2} abc 0 0 0 0
+^((){2}) abc 0 0 0 0 0 0
+() "" 0 0 0 0
+()\1 "" 0 0 0 0
+()\1 a 0 0 0 0
+a()\1b ab 0 2 1 1
+a()b\1 ab 0 2 1 1
+
+; subtleties of matching with no sub-expressions marked
+- normal match_nosubs REG_NO_POSIX_TEST
+a(b?c)+d accd 0 4 
+(wee|week)(knights|night) weeknights 0 10 
+.* abc 0 3
+a(b|(c))d abd 0 3 
+a(b|(c))d acd 0 3
+a(b*|c|e)d abbd 0 4
+a(b*|c|e)d acd 0 3 
+a(b*|c|e)d ad 0 2
+a(b?)c abc 0 3
+a(b?)c ac 0 2
+a(b+)c abc 0 3
+a(b+)c abbbc 0 5
+a(b*)c ac 0 2
+(a|ab)(bc([de]+)f|cde) abcdef 0 6
+a([bc]?)c abc 0 3
+a([bc]?)c ac 0 2
+a([bc]+)c abc 0 3
+a([bc]+)c abcc 0 4
+a([bc]+)bc abcbc 0 5
+a(bb+|b)b abb 0 3
+a(bbb+|bb+|b)b abb 0 3
+a(bbb+|bb+|b)b abbb 0 4
+a(bbb+|bb+|b)bb abbb 0 4
+(.*).* abcdef 0 6
+(a*)* bc 0 0
+
+- normal nosubs REG_NO_POSIX_TEST
+a(b?c)+d accd 0 4 
+(wee|week)(knights|night) weeknights 0 10 
+.* abc 0 3
+a(b|(c))d abd 0 3 
+a(b|(c))d acd 0 3
+a(b*|c|e)d abbd 0 4
+a(b*|c|e)d acd 0 3 
+a(b*|c|e)d ad 0 2
+a(b?)c abc 0 3
+a(b?)c ac 0 2
+a(b+)c abc 0 3
+a(b+)c abbbc 0 5
+a(b*)c ac 0 2
+(a|ab)(bc([de]+)f|cde) abcdef 0 6
+a([bc]?)c abc 0 3
+a([bc]?)c ac 0 2
+a([bc]+)c abc 0 3
+a([bc]+)c abcc 0 4
+a([bc]+)bc abcbc 0 5
+a(bb+|b)b abb 0 3
+a(bbb+|bb+|b)b abb 0 3
+a(bbb+|bb+|b)b abbb 0 4
+a(bbb+|bb+|b)bb abbb 0 4
+(.*).* abcdef 0 6
+(a*)* bc 0 0
+
Index: /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.am
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.am	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.am	(revision 1780)
@@ -0,0 +1,94 @@
+CLEANFILES = tmp* core *.core $(EXTRA_PROGRAMS) *.*out *.log
+
+TESTS = $(check_PROGRAMS) $(SEDTESTS)
+SEDTESTS =
+
+LDADD = ../lib/libsed.a
+noinst_HEADERS = testcases.h ptestcases.h
+AM_CPPFLAGS = -I../lib
+
+if TEST_REGEX
+check_PROGRAMS = bug-regex7 \
+                 bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \
+                 bug-regex13 bug-regex14 bug-regex15 bug-regex16 bug-regex21 \
+                 tst-pcre tst-boost runtests runptests tst-rxspencer tst-regex2
+
+SEDTESTS += space
+endif
+
+SEDTESTS += \
+        appquit enable sep inclib 8bit newjis xabcx dollar noeol noeolw \
+  	modulo numsub numsub2 numsub3 numsub4 numsub5 0range bkslashes \
+  	head madding mac-mf empty xbxcx xbxcx3 recall recall2 xemacs \
+  	fasts uniq manis khadafy linecnt eval distrib 8to7 y-bracket \
+	y-newline allsub cv-vars classes middle bsd stdin flipcase \
+	insens subwrite writeout readin \
+	help version file quiet \
+	factor binary3 binary2 binary dc
+
+TESTS_ENVIRONMENT = MAKE="$(MAKE)" VERSION="$(VERSION)" $(srcdir)/runtest
+
+EXTRA_DIST = \
+	PCRE.tests BOOST.tests SPENCER.tests \
+	runtest Makefile.tests \
+	0range.good 0range.inp 0range.sed \
+	8bit.good 8bit.inp 8bit.sed \
+	8to7.good 8to7.inp 8to7.sed \
+	allsub.good allsub.inp allsub.sed \
+	appquit.good appquit.inp appquit.sed \
+	binary.good binary.inp binary.sed binary2.sed binary3.sed \
+	bkslashes.good bkslashes.inp bkslashes.sed \
+	bsd.good bsd.sh \
+	cv-vars.good cv-vars.inp cv-vars.sed \
+	classes.good classes.inp classes.sed \
+	dc.good dc.inp dc.sed \
+	distrib.good distrib.inp distrib.sed distrib.sh \
+	dollar.good dollar.inp dollar.sed \
+	empty.good empty.inp empty.sed \
+	enable.good enable.inp enable.sed \
+	eval.good eval.inp eval.sed \
+	factor.good factor.inp factor.sed \
+	fasts.good fasts.inp fasts.sed \
+	flipcase.good flipcase.inp flipcase.sed \
+	head.good head.inp head.sed \
+	inclib.good inclib.inp inclib.sed \
+	insens.good insens.inp insens.sed \
+	khadafy.good khadafy.inp khadafy.sed \
+	linecnt.good linecnt.inp linecnt.sed \
+	space.good space.inp space.sed \
+	mac-mf.good mac-mf.inp mac-mf.sed \
+	madding.good madding.inp madding.sed \
+	manis.good manis.inp manis.sed \
+	middle.good middle.sed middle.inp \
+	modulo.good modulo.sed modulo.inp \
+	newjis.good newjis.inp  newjis.sed \
+	noeol.good noeol.inp noeol.sed \
+	noeolw.good noeolw.1good noeolw.2good noeolw.sed \
+	numsub.good numsub.inp numsub.sed \
+	numsub2.good numsub2.inp numsub2.sed \
+	numsub3.good numsub3.inp numsub3.sed \
+	numsub4.good numsub4.inp numsub4.sed \
+	numsub5.good numsub5.inp numsub5.sed \
+	readin.good readin.in2 readin.inp readin.sed \
+	recall.good recall.inp recall.sed \
+	recall2.good recall2.inp recall2.sed \
+	sep.good sep.inp sep.sed \
+	subwrite.inp subwrite.sed  subwrt1.good subwrt2.good \
+	uniq.good uniq.inp uniq.sed \
+	version.gin \
+	writeout.inp writeout.sed wrtout1.good wrtout2.good \
+	xabcx.good xabcx.inp xabcx.sed \
+	xbxcx.good xbxcx.inp xbxcx.sed \
+	xbxcx3.good xbxcx3.inp xbxcx3.sed \
+	xemacs.good xemacs.inp xemacs.sed \
+	y-bracket.good y-bracket.sed y-bracket.inp \
+	y-newline.good y-newline.sed y-newline.inp
+
+clean-local:
+	test x$(srcdir) = x. || rm -f readin.in2 eval.in2
+
+# automake makes `check' depend on $(TESTS).  Declare
+# dummy targets for $(TESTS) so that make does not complain.
+
+.PHONY: $(SEDTESTS)
+$(SEDTESTS):
Index: /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.in
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.in	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.in	(revision 1780)
@@ -0,0 +1,720 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# 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_MAKE@
+
+SOURCES = bug-regex10.c bug-regex11.c bug-regex12.c bug-regex13.c bug-regex14.c bug-regex15.c bug-regex16.c bug-regex21.c bug-regex7.c bug-regex8.c bug-regex9.c runptests.c runtests.c tst-boost.c tst-pcre.c tst-regex2.c tst-rxspencer.c
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@TEST_REGEX_TRUE@check_PROGRAMS = bug-regex7$(EXEEXT) \
+@TEST_REGEX_TRUE@	bug-regex8$(EXEEXT) bug-regex9$(EXEEXT) \
+@TEST_REGEX_TRUE@	bug-regex10$(EXEEXT) bug-regex11$(EXEEXT) \
+@TEST_REGEX_TRUE@	bug-regex12$(EXEEXT) bug-regex13$(EXEEXT) \
+@TEST_REGEX_TRUE@	bug-regex14$(EXEEXT) bug-regex15$(EXEEXT) \
+@TEST_REGEX_TRUE@	bug-regex16$(EXEEXT) bug-regex21$(EXEEXT) \
+@TEST_REGEX_TRUE@	tst-pcre$(EXEEXT) tst-boost$(EXEEXT) \
+@TEST_REGEX_TRUE@	runtests$(EXEEXT) runptests$(EXEEXT) \
+@TEST_REGEX_TRUE@	tst-rxspencer$(EXEEXT) tst-regex2$(EXEEXT)
+@TEST_REGEX_TRUE@am__append_1 = space
+subdir = testsuite
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/codeset.m4 \
+	$(top_srcdir)/config/getline.m4 \
+	$(top_srcdir)/config/gettext-ver.m4 \
+	$(top_srcdir)/config/gettext.m4 \
+	$(top_srcdir)/config/glibc21.m4 $(top_srcdir)/config/iconv.m4 \
+	$(top_srcdir)/config/lcmessage.m4 \
+	$(top_srcdir)/config/lib-ld.m4 \
+	$(top_srcdir)/config/lib-link.m4 \
+	$(top_srcdir)/config/lib-prefix.m4 \
+	$(top_srcdir)/config/progtest.m4 \
+	$(top_srcdir)/config/stdbool.m4 \
+	$(top_srcdir)/config/strverscmp.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+bug_regex10_SOURCES = bug-regex10.c
+bug_regex10_OBJECTS = bug-regex10.$(OBJEXT)
+bug_regex10_LDADD = $(LDADD)
+bug_regex10_DEPENDENCIES = ../lib/libsed.a
+bug_regex11_SOURCES = bug-regex11.c
+bug_regex11_OBJECTS = bug-regex11.$(OBJEXT)
+bug_regex11_LDADD = $(LDADD)
+bug_regex11_DEPENDENCIES = ../lib/libsed.a
+bug_regex12_SOURCES = bug-regex12.c
+bug_regex12_OBJECTS = bug-regex12.$(OBJEXT)
+bug_regex12_LDADD = $(LDADD)
+bug_regex12_DEPENDENCIES = ../lib/libsed.a
+bug_regex13_SOURCES = bug-regex13.c
+bug_regex13_OBJECTS = bug-regex13.$(OBJEXT)
+bug_regex13_LDADD = $(LDADD)
+bug_regex13_DEPENDENCIES = ../lib/libsed.a
+bug_regex14_SOURCES = bug-regex14.c
+bug_regex14_OBJECTS = bug-regex14.$(OBJEXT)
+bug_regex14_LDADD = $(LDADD)
+bug_regex14_DEPENDENCIES = ../lib/libsed.a
+bug_regex15_SOURCES = bug-regex15.c
+bug_regex15_OBJECTS = bug-regex15.$(OBJEXT)
+bug_regex15_LDADD = $(LDADD)
+bug_regex15_DEPENDENCIES = ../lib/libsed.a
+bug_regex16_SOURCES = bug-regex16.c
+bug_regex16_OBJECTS = bug-regex16.$(OBJEXT)
+bug_regex16_LDADD = $(LDADD)
+bug_regex16_DEPENDENCIES = ../lib/libsed.a
+bug_regex21_SOURCES = bug-regex21.c
+bug_regex21_OBJECTS = bug-regex21.$(OBJEXT)
+bug_regex21_LDADD = $(LDADD)
+bug_regex21_DEPENDENCIES = ../lib/libsed.a
+bug_regex7_SOURCES = bug-regex7.c
+bug_regex7_OBJECTS = bug-regex7.$(OBJEXT)
+bug_regex7_LDADD = $(LDADD)
+bug_regex7_DEPENDENCIES = ../lib/libsed.a
+bug_regex8_SOURCES = bug-regex8.c
+bug_regex8_OBJECTS = bug-regex8.$(OBJEXT)
+bug_regex8_LDADD = $(LDADD)
+bug_regex8_DEPENDENCIES = ../lib/libsed.a
+bug_regex9_SOURCES = bug-regex9.c
+bug_regex9_OBJECTS = bug-regex9.$(OBJEXT)
+bug_regex9_LDADD = $(LDADD)
+bug_regex9_DEPENDENCIES = ../lib/libsed.a
+runptests_SOURCES = runptests.c
+runptests_OBJECTS = runptests.$(OBJEXT)
+runptests_LDADD = $(LDADD)
+runptests_DEPENDENCIES = ../lib/libsed.a
+runtests_SOURCES = runtests.c
+runtests_OBJECTS = runtests.$(OBJEXT)
+runtests_LDADD = $(LDADD)
+runtests_DEPENDENCIES = ../lib/libsed.a
+tst_boost_SOURCES = tst-boost.c
+tst_boost_OBJECTS = tst-boost.$(OBJEXT)
+tst_boost_LDADD = $(LDADD)
+tst_boost_DEPENDENCIES = ../lib/libsed.a
+tst_pcre_SOURCES = tst-pcre.c
+tst_pcre_OBJECTS = tst-pcre.$(OBJEXT)
+tst_pcre_LDADD = $(LDADD)
+tst_pcre_DEPENDENCIES = ../lib/libsed.a
+tst_regex2_SOURCES = tst-regex2.c
+tst_regex2_OBJECTS = tst-regex2.$(OBJEXT)
+tst_regex2_LDADD = $(LDADD)
+tst_regex2_DEPENDENCIES = ../lib/libsed.a
+tst_rxspencer_SOURCES = tst-rxspencer.c
+tst_rxspencer_OBJECTS = tst-rxspencer.$(OBJEXT)
+tst_rxspencer_LDADD = $(LDADD)
+tst_rxspencer_DEPENDENCIES = ../lib/libsed.a
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = bug-regex10.c bug-regex11.c bug-regex12.c bug-regex13.c \
+	bug-regex14.c bug-regex15.c bug-regex16.c bug-regex21.c \
+	bug-regex7.c bug-regex8.c bug-regex9.c runptests.c runtests.c \
+	tst-boost.c tst-pcre.c tst-regex2.c tst-rxspencer.c
+DIST_SOURCES = bug-regex10.c bug-regex11.c bug-regex12.c bug-regex13.c \
+	bug-regex14.c bug-regex15.c bug-regex16.c bug-regex21.c \
+	bug-regex7.c bug-regex8.c bug-regex9.c runptests.c runtests.c \
+	tst-boost.c tst-pcre.c tst-regex2.c tst-rxspencer.c
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_HTML_FALSE = @BUILD_HTML_FALSE@
+BUILD_HTML_TRUE = @BUILD_HTML_TRUE@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
+GMSGFMT = @GMSGFMT@
+HAVE__BOOL = @HAVE__BOOL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKEINFO_HTML_FALSE = @MAKEINFO_HTML_FALSE@
+MAKEINFO_HTML_TRUE = @MAKEINFO_HTML_TRUE@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SED_FEATURE_VERSION = @SED_FEATURE_VERSION@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEST_REGEX_FALSE = @TEST_REGEX_FALSE@
+TEST_REGEX_TRUE = @TEST_REGEX_TRUE@
+TEXI2HTML = @TEXI2HTML@
+TEXI2HTML_HTML_FALSE = @TEXI2HTML_HTML_FALSE@
+TEXI2HTML_HTML_TRUE = @TEXI2HTML_HTML_TRUE@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+CLEANFILES = tmp* core *.core $(EXTRA_PROGRAMS) *.*out *.log
+TESTS = $(check_PROGRAMS) $(SEDTESTS)
+SEDTESTS = $(am__append_1) appquit enable sep inclib 8bit newjis xabcx \
+	dollar noeol noeolw modulo numsub numsub2 numsub3 numsub4 \
+	numsub5 0range bkslashes head madding mac-mf empty xbxcx \
+	xbxcx3 recall recall2 xemacs fasts uniq manis khadafy linecnt \
+	eval distrib 8to7 y-bracket y-newline allsub cv-vars classes \
+	middle bsd stdin flipcase insens subwrite writeout readin help \
+	version file quiet factor binary3 binary2 binary dc
+LDADD = ../lib/libsed.a
+noinst_HEADERS = testcases.h ptestcases.h
+AM_CPPFLAGS = -I../lib
+TESTS_ENVIRONMENT = MAKE="$(MAKE)" VERSION="$(VERSION)" $(srcdir)/runtest
+EXTRA_DIST = \
+	PCRE.tests BOOST.tests SPENCER.tests \
+	runtest Makefile.tests \
+	0range.good 0range.inp 0range.sed \
+	8bit.good 8bit.inp 8bit.sed \
+	8to7.good 8to7.inp 8to7.sed \
+	allsub.good allsub.inp allsub.sed \
+	appquit.good appquit.inp appquit.sed \
+	binary.good binary.inp binary.sed binary2.sed binary3.sed \
+	bkslashes.good bkslashes.inp bkslashes.sed \
+	bsd.good bsd.sh \
+	cv-vars.good cv-vars.inp cv-vars.sed \
+	classes.good classes.inp classes.sed \
+	dc.good dc.inp dc.sed \
+	distrib.good distrib.inp distrib.sed distrib.sh \
+	dollar.good dollar.inp dollar.sed \
+	empty.good empty.inp empty.sed \
+	enable.good enable.inp enable.sed \
+	eval.good eval.inp eval.sed \
+	factor.good factor.inp factor.sed \
+	fasts.good fasts.inp fasts.sed \
+	flipcase.good flipcase.inp flipcase.sed \
+	head.good head.inp head.sed \
+	inclib.good inclib.inp inclib.sed \
+	insens.good insens.inp insens.sed \
+	khadafy.good khadafy.inp khadafy.sed \
+	linecnt.good linecnt.inp linecnt.sed \
+	space.good space.inp space.sed \
+	mac-mf.good mac-mf.inp mac-mf.sed \
+	madding.good madding.inp madding.sed \
+	manis.good manis.inp manis.sed \
+	middle.good middle.sed middle.inp \
+	modulo.good modulo.sed modulo.inp \
+	newjis.good newjis.inp  newjis.sed \
+	noeol.good noeol.inp noeol.sed \
+	noeolw.good noeolw.1good noeolw.2good noeolw.sed \
+	numsub.good numsub.inp numsub.sed \
+	numsub2.good numsub2.inp numsub2.sed \
+	numsub3.good numsub3.inp numsub3.sed \
+	numsub4.good numsub4.inp numsub4.sed \
+	numsub5.good numsub5.inp numsub5.sed \
+	readin.good readin.in2 readin.inp readin.sed \
+	recall.good recall.inp recall.sed \
+	recall2.good recall2.inp recall2.sed \
+	sep.good sep.inp sep.sed \
+	subwrite.inp subwrite.sed  subwrt1.good subwrt2.good \
+	uniq.good uniq.inp uniq.sed \
+	version.gin \
+	writeout.inp writeout.sed wrtout1.good wrtout2.good \
+	xabcx.good xabcx.inp xabcx.sed \
+	xbxcx.good xbxcx.inp xbxcx.sed \
+	xbxcx3.good xbxcx3.inp xbxcx3.sed \
+	xemacs.good xemacs.inp xemacs.sed \
+	y-bracket.good y-bracket.sed y-bracket.inp \
+	y-newline.good y-newline.sed y-newline.inp
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits  testsuite/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnits  testsuite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-checkPROGRAMS:
+	-test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
+bug-regex10$(EXEEXT): $(bug_regex10_OBJECTS) $(bug_regex10_DEPENDENCIES) 
+	@rm -f bug-regex10$(EXEEXT)
+	$(LINK) $(bug_regex10_LDFLAGS) $(bug_regex10_OBJECTS) $(bug_regex10_LDADD) $(LIBS)
+bug-regex11$(EXEEXT): $(bug_regex11_OBJECTS) $(bug_regex11_DEPENDENCIES) 
+	@rm -f bug-regex11$(EXEEXT)
+	$(LINK) $(bug_regex11_LDFLAGS) $(bug_regex11_OBJECTS) $(bug_regex11_LDADD) $(LIBS)
+bug-regex12$(EXEEXT): $(bug_regex12_OBJECTS) $(bug_regex12_DEPENDENCIES) 
+	@rm -f bug-regex12$(EXEEXT)
+	$(LINK) $(bug_regex12_LDFLAGS) $(bug_regex12_OBJECTS) $(bug_regex12_LDADD) $(LIBS)
+bug-regex13$(EXEEXT): $(bug_regex13_OBJECTS) $(bug_regex13_DEPENDENCIES) 
+	@rm -f bug-regex13$(EXEEXT)
+	$(LINK) $(bug_regex13_LDFLAGS) $(bug_regex13_OBJECTS) $(bug_regex13_LDADD) $(LIBS)
+bug-regex14$(EXEEXT): $(bug_regex14_OBJECTS) $(bug_regex14_DEPENDENCIES) 
+	@rm -f bug-regex14$(EXEEXT)
+	$(LINK) $(bug_regex14_LDFLAGS) $(bug_regex14_OBJECTS) $(bug_regex14_LDADD) $(LIBS)
+bug-regex15$(EXEEXT): $(bug_regex15_OBJECTS) $(bug_regex15_DEPENDENCIES) 
+	@rm -f bug-regex15$(EXEEXT)
+	$(LINK) $(bug_regex15_LDFLAGS) $(bug_regex15_OBJECTS) $(bug_regex15_LDADD) $(LIBS)
+bug-regex16$(EXEEXT): $(bug_regex16_OBJECTS) $(bug_regex16_DEPENDENCIES) 
+	@rm -f bug-regex16$(EXEEXT)
+	$(LINK) $(bug_regex16_LDFLAGS) $(bug_regex16_OBJECTS) $(bug_regex16_LDADD) $(LIBS)
+bug-regex21$(EXEEXT): $(bug_regex21_OBJECTS) $(bug_regex21_DEPENDENCIES) 
+	@rm -f bug-regex21$(EXEEXT)
+	$(LINK) $(bug_regex21_LDFLAGS) $(bug_regex21_OBJECTS) $(bug_regex21_LDADD) $(LIBS)
+bug-regex7$(EXEEXT): $(bug_regex7_OBJECTS) $(bug_regex7_DEPENDENCIES) 
+	@rm -f bug-regex7$(EXEEXT)
+	$(LINK) $(bug_regex7_LDFLAGS) $(bug_regex7_OBJECTS) $(bug_regex7_LDADD) $(LIBS)
+bug-regex8$(EXEEXT): $(bug_regex8_OBJECTS) $(bug_regex8_DEPENDENCIES) 
+	@rm -f bug-regex8$(EXEEXT)
+	$(LINK) $(bug_regex8_LDFLAGS) $(bug_regex8_OBJECTS) $(bug_regex8_LDADD) $(LIBS)
+bug-regex9$(EXEEXT): $(bug_regex9_OBJECTS) $(bug_regex9_DEPENDENCIES) 
+	@rm -f bug-regex9$(EXEEXT)
+	$(LINK) $(bug_regex9_LDFLAGS) $(bug_regex9_OBJECTS) $(bug_regex9_LDADD) $(LIBS)
+runptests$(EXEEXT): $(runptests_OBJECTS) $(runptests_DEPENDENCIES) 
+	@rm -f runptests$(EXEEXT)
+	$(LINK) $(runptests_LDFLAGS) $(runptests_OBJECTS) $(runptests_LDADD) $(LIBS)
+runtests$(EXEEXT): $(runtests_OBJECTS) $(runtests_DEPENDENCIES) 
+	@rm -f runtests$(EXEEXT)
+	$(LINK) $(runtests_LDFLAGS) $(runtests_OBJECTS) $(runtests_LDADD) $(LIBS)
+tst-boost$(EXEEXT): $(tst_boost_OBJECTS) $(tst_boost_DEPENDENCIES) 
+	@rm -f tst-boost$(EXEEXT)
+	$(LINK) $(tst_boost_LDFLAGS) $(tst_boost_OBJECTS) $(tst_boost_LDADD) $(LIBS)
+tst-pcre$(EXEEXT): $(tst_pcre_OBJECTS) $(tst_pcre_DEPENDENCIES) 
+	@rm -f tst-pcre$(EXEEXT)
+	$(LINK) $(tst_pcre_LDFLAGS) $(tst_pcre_OBJECTS) $(tst_pcre_LDADD) $(LIBS)
+tst-regex2$(EXEEXT): $(tst_regex2_OBJECTS) $(tst_regex2_DEPENDENCIES) 
+	@rm -f tst-regex2$(EXEEXT)
+	$(LINK) $(tst_regex2_LDFLAGS) $(tst_regex2_OBJECTS) $(tst_regex2_LDADD) $(LIBS)
+tst-rxspencer$(EXEEXT): $(tst_rxspencer_OBJECTS) $(tst_rxspencer_DEPENDENCIES) 
+	@rm -f tst-rxspencer$(EXEEXT)
+	$(LINK) $(tst_rxspencer_LDFLAGS) $(tst_rxspencer_OBJECTS) $(tst_rxspencer_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex10.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex11.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex12.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex13.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex14.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex15.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex16.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex21.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex7.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex8.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-regex9.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runptests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-boost.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-pcre.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-regex2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-rxspencer.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list='$(TESTS)'; \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *" $$tst "*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		echo "XPASS: $$tst"; \
+	      ;; \
+	      *) \
+		echo "PASS: $$tst"; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *" $$tst "*) \
+		xfail=`expr $$xfail + 1`; \
+		echo "XFAIL: $$tst"; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		echo "FAIL: $$tst"; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      echo "SKIP: $$tst"; \
+	    fi; \
+	  done; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="All $$all tests passed"; \
+	    else \
+	      banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all tests failed"; \
+	    else \
+	      banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    skipped="($$skip tests were not run)"; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  echo "$$dashes"; \
+	  echo "$$banner"; \
+	  test -z "$$skipped" || echo "$$skipped"; \
+	  test -z "$$report" || echo "$$report"; \
+	  echo "$$dashes"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-local mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+	clean-checkPROGRAMS clean-generic clean-local ctags distclean \
+	distclean-compile distclean-generic distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-exec install-exec-am \
+	install-info install-info-am install-man install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-info-am
+
+
+clean-local:
+	test x$(srcdir) = x. || rm -f readin.in2 eval.in2
+
+# automake makes `check' depend on $(TESTS).  Declare
+# dummy targets for $(TESTS) so that make does not complain.
+
+.PHONY: $(SEDTESTS)
+$(SEDTESTS):
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.tests
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.tests	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/Makefile.tests	(revision 1780)
@@ -0,0 +1,158 @@
+# Testsuite makefile for GNU sed
+
+SHELL = /bin/sh
+
+# These are only fallback values. They are usually overridden by runtest.
+srcdir = .
+SED = ../sed/sed
+SEDENV = LC_ALL=C $(TIME)
+
+#TIME=time
+CMP=cmp
+RM=rm -f
+
+enable sep inclib 8bit 8to7 newjis xabcx dollar noeol bkslashes \
+numsub head madding mac-mf empty xbxcx xbxcx3 recall recall2 xemacs \
+appquit fasts uniq manis linecnt khadafy allsub flipcase space modulo \
+y-bracket y-newline::
+	$(SEDENV) $(SED) -f $(srcdir)/$@.sed \
+		< $(srcdir)/$@.inp > $@.out 
+	$(CMP) $(srcdir)/$@.good $@.out 
+	@$(RM) $@.out 
+
+0range::
+	$(SEDENV) $(SED) -s -f $(srcdir)/$@.sed < $(srcdir)/$@.inp > $@.out 
+	$(CMP) $(srcdir)/$@.good $@.out 
+	@$(RM) $@.out 
+
+# This checks for a bug in 3.02 and 3.02.80
+stdin::
+	($(SEDENV) $(SED) d; $(SEDENV) $(SED) G) < $(srcdir)/numsub.inp > $@.1out 
+	$(SEDENV) cat $(srcdir)/numsub.inp | ($(SEDENV) $(SED) d; $(SEDENV) $(SED) G) > $@.2out 
+	$(CMP) $@.1out $@.2out 
+	@$(RM) $@.1out $@.2out 
+
+cv-vars classes middle dc distrib factor numsub2 numsub3 numsub4 numsub5 \
+insens::
+	$(SEDENV) $(SED) -n -f $(srcdir)/$@.sed < $(srcdir)/$@.inp > $@.out 
+	$(CMP) $(srcdir)/$@.good $@.out 
+	@$(RM) $@.out 
+
+noeolw::
+	$(SEDENV) $(SED) -n -f $(srcdir)/$@.sed \
+	  $(srcdir)/noeol.inp $(srcdir)/noeol.inp > $@.out 
+	$(CMP) $(srcdir)/$@.good $@.out 
+	$(CMP) $(srcdir)/$@.1good $@.1out
+	$(CMP) $(srcdir)/$@.2good $@.2out
+	@$(RM) $@.1out $@.2out $@.out
+
+subwrite::
+	$(SEDENV) $(SED) -f $(srcdir)/$@.sed < $(srcdir)/$@.inp > $@.1out 
+	$(CMP) $(srcdir)/subwrt1.good $@.1out 
+	$(CMP) $(srcdir)/subwrt2.good $@.wout
+	@$(RM) $@.1out $@.wout
+
+bsd::
+	$(SEDENV) sh $(srcdir)/$@.sh '$(SED)' bsd.out
+	$(CMP) $(srcdir)/$@.good $@.out 
+	@$(RM) $@.out 
+
+writeout::
+	$(SEDENV) $(SED) -f $(srcdir)/$@.sed < $(srcdir)/$@.inp >$@.1out 
+	$(CMP) $(srcdir)/wrtout1.good $@.1out 
+	$(CMP) $(srcdir)/wrtout2.good $@.wout
+	@$(RM) $@.1out $@.wout
+
+readin.in2: $(srcdir)/readin.in2
+	cat $(srcdir)/readin.in2 > $@
+
+readin:: readin.in2
+	$(SEDENV) $(SED) -f $(srcdir)/$@.sed < $(srcdir)/$@.inp >$@.out 
+	$(CMP) $(srcdir)/$@.good $@.out 
+	@$(RM) $@.out 
+
+eval.in2: $(srcdir)/eval.inp
+	cat $(srcdir)/eval.inp > $@
+
+eval:: eval.in2
+	$(SEDENV) $(SED) -f $(srcdir)/$@.sed < $(srcdir)/$@.inp > $@.out 
+	$(CMP) $(srcdir)/$@.good $@.out 
+	@$(RM) $@.out 
+
+binary binary2 binary3::
+	$(SEDENV) $(SED) -n -f $(srcdir)/$@.sed < $(srcdir)/binary.inp >$@.out 
+	$(CMP) $(srcdir)/binary.good $@.out 
+	@$(RM) $@.out 
+
+#
+# cmdlines targets
+#
+
+help::
+	$(SED) --help | $(SED) '1s/ [^ ]* / sed /' > $@.1out 
+	$(SED) 2>&1 | $(SED) '1s/ [^ ]* / sed /' > $@.2out || :
+	$(CMP) $@.1out $@.2out 
+	@$(RM) $@.1out $@.2out
+
+version::
+	$(SED) 's^@'VERSION'@^$(VERSION)^' $(srcdir)/version.gin > $@.good 
+	$(SEDENV) $(SED) --version > $@.out 2>&1
+	$(CMP) $@.good $@.out 
+	@$(RM) $@.good $@.out
+
+file::
+	$(SEDENV) $(SED) --file=$(srcdir)/newjis.sed \
+		< $(srcdir)/newjis.inp > $@.out 
+	$(CMP) $(srcdir)/newjis.good $@.out 
+	@$(RM) $@.out 
+
+quiet::
+	$(SEDENV) $(SED) --quiet -f $(srcdir)/cv-vars.sed \
+		< $(srcdir)/cv-vars.inp > $@.out 
+	$(CMP) $(srcdir)/cv-vars.good $@.out 
+	@$(RM) $@.out 
+
+# The following target is not used in super sed builds (only GNU sed)
+
+bug-regex7$(EXEEXT) bug-regex8$(EXEEXT) bug-regex9$(EXEEXT) \
+bug-regex10$(EXEEXT) bug-regex11$(EXEEXT) bug-regex12$(EXEEXT) \
+bug-regex13$(EXEEXT) bug-regex14$(EXEEXT) bug-regex15$(EXEEXT) bug-regex16$(EXEEXT) \
+bug-regex21$(EXEEXT) runtests$(EXEEXT) runptests$(EXEEXT)::
+	echo "$(SEDENV) ./$@ > `echo $@ | $(SED) s/$(EXEEXT)$$/.log/`"
+	@$(SEDENV) ./$@ > `echo $@ | $(SED) s/$(EXEEXT)$$/.log/`
+
+tst-pcre$(EXEEXT)::
+	$(SEDENV) ./tst-pcre $(srcdir)/PCRE.tests > tst-pcre.log
+
+tst-boost$(EXEEXT)::
+	$(SEDENV) ./tst-boost $(srcdir)/BOOST.tests > tst-boost.log
+
+tst-rxspencer$(EXEEXT)::
+	$(SEDENV) ./tst-rxspencer $(srcdir)/SPENCER.tests > tst-spencer.log
+
+tst-regex2$(EXEEXT)::
+	$(SEDENV) ./tst-regex2 $(srcdir)/tst-regex2.c > tst-regex2.log
+
+# The following target is not used in GNU sed builds (only super-sed)
+
+pcretest$(EXEEXT)::
+	$(SEDENV) ./pcretest $(srcdir)/pcre1.inp pcre1.out
+	$(CMP) $(srcdir)/pcre1.good pcre1.out
+	#$(SEDENV) ./pcretest -p $(srcdir)/pcre1.inp pcre1p.out
+	#$(CMP) $(srcdir)/pcre1p.good pcre1p.out
+	$(SEDENV) ./pcretest -P $(srcdir)/pcre2.inp pcre2.out
+	$(CMP) $(srcdir)/pcre2.good pcre2.out
+	$(SEDENV) ./pcretest -P -p $(srcdir)/pcre2.inp pcre2p.out
+	$(CMP) $(srcdir)/pcre2p.good pcre2p.out
+	$(SEDENV) ./pcretest $(srcdir)/pcre3.inp pcre3.out
+	$(CMP) $(srcdir)/pcre3.good pcre3.out
+	$(SEDENV) ./pcretest -p $(srcdir)/pcre3.inp pcre3p.out
+	$(CMP) $(srcdir)/pcre3p.good pcre3p.out
+	@$(RM) pcre*.out
+
+.PHONY: \
+bug-regex7$(EXEEXT) bug-regex8$(EXEEXT) bug-regex9$(EXEEXT) \
+bug-regex10$(EXEEXT) bug-regex11$(EXEEXT) bug-regex12$(EXEEXT) \
+bug-regex13$(EXEEXT) bug-regex14$(EXEEXT) bug-regex15$(EXEEXT) bug-regex16$(EXEEXT) \
+bug-regex21$(EXEEXT) runtests$(EXEEXT) runptests$(EXEEXT) tst-regex2$(EXEEXT) \
+tst-pcre$(EXEEXT) tst-boost$(EXEEXT) tst-rxspencer$(EXEEXT) pcretest$(EXEEXT)
Index: /tags/kBuild-0.1.4/src/sed/testsuite/PCRE.tests
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/PCRE.tests	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/PCRE.tests	(revision 1780)
@@ -0,0 +1,2386 @@
+# PCRE version 4.4 21-August-2003
+
+# Tests taken from PCRE and modified to suit glibc regex.
+#
+# PCRE LICENCE
+# ------------
+#
+# PCRE is a library of functions to support regular expressions whose syntax
+# and semantics are as close as possible to those of the Perl 5 language.
+#
+# Written by: Philip Hazel <ph10@cam.ac.uk>
+#
+# University of Cambridge Computing Service,
+# Cambridge, England. Phone: +44 1223 334714.
+#
+# Copyright (c) 1997-2003 University of Cambridge
+#
+# Permission is granted to anyone to use this software for any purpose on any
+# computer system, and to redistribute it freely, subject to the following
+# restrictions:
+#
+# 1. This software 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.
+#
+# 2. The origin of this software must not be misrepresented, either by
+#    explicit claim or by omission. In practice, this means that if you use
+#    PCRE in software that you distribute to others, commercially or
+#    otherwise, you must put a sentence like this
+#
+#      Regular expression support is provided by the PCRE library package,
+#      which is open source software, written by Philip Hazel, and copyright
+#      by the University of Cambridge, England.
+#
+#    somewhere reasonably visible in your documentation and in any relevant
+#    files or online help data or similar. A reference to the ftp site for
+#    the source, that is, to
+#
+#      ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
+#
+#    should also be given in the documentation. However, this condition is not
+#    intended to apply to whole chains of software. If package A includes PCRE,
+#    it must acknowledge it, but if package B is software that includes package
+#    A, the condition is not imposed on package B (unless it uses PCRE
+#    independently).
+#
+# 3. Altered versions must be plainly marked as such, and must not be
+#    misrepresented as being the original software.
+#
+# 4. If PCRE is embedded in any software that is released under the GNU
+#   General Purpose Licence (GPL), or Lesser General Purpose Licence (LGPL),
+#   then the terms of that licence shall supersede any condition above with
+#   which it is incompatible.
+#
+# The documentation for PCRE, supplied in the "doc" directory, is distributed
+# under the same terms as the software itself.
+#
+# End
+#
+
+/the quick brown fox/
+    the quick brown fox
+ 0: the quick brown fox
+    The quick brown FOX
+No match
+    What do you know about the quick brown fox?
+ 0: the quick brown fox
+    What do you know about THE QUICK BROWN FOX?
+No match
+
+/The quick brown fox/i
+    the quick brown fox
+ 0: the quick brown fox
+    The quick brown FOX
+ 0: The quick brown FOX
+    What do you know about the quick brown fox?
+ 0: the quick brown fox
+    What do you know about THE QUICK BROWN FOX?
+ 0: THE QUICK BROWN FOX
+
+/a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/
+    abxyzpqrrrabbxyyyypqAzz
+ 0: abxyzpqrrrabbxyyyypqAzz
+    abxyzpqrrrabbxyyyypqAzz
+ 0: abxyzpqrrrabbxyyyypqAzz
+    aabxyzpqrrrabbxyyyypqAzz
+ 0: aabxyzpqrrrabbxyyyypqAzz
+    aaabxyzpqrrrabbxyyyypqAzz
+ 0: aaabxyzpqrrrabbxyyyypqAzz
+    aaaabxyzpqrrrabbxyyyypqAzz
+ 0: aaaabxyzpqrrrabbxyyyypqAzz
+    abcxyzpqrrrabbxyyyypqAzz
+ 0: abcxyzpqrrrabbxyyyypqAzz
+    aabcxyzpqrrrabbxyyyypqAzz
+ 0: aabcxyzpqrrrabbxyyyypqAzz
+    aaabcxyzpqrrrabbxyyyypAzz
+ 0: aaabcxyzpqrrrabbxyyyypAzz
+    aaabcxyzpqrrrabbxyyyypqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqAzz
+    aaabcxyzpqrrrabbxyyyypqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqAzz
+    aaabcxyzpqrrrabbxyyyypqqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqqAzz
+    aaabcxyzpqrrrabbxyyyypqqqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqqqAzz
+    aaabcxyzpqrrrabbxyyyypqqqqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz
+    aaabcxyzpqrrrabbxyyyypqqqqqqAzz
+ 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz
+    aaaabcxyzpqrrrabbxyyyypqAzz
+ 0: aaaabcxyzpqrrrabbxyyyypqAzz
+    abxyzzpqrrrabbxyyyypqAzz
+ 0: abxyzzpqrrrabbxyyyypqAzz
+    aabxyzzzpqrrrabbxyyyypqAzz
+ 0: aabxyzzzpqrrrabbxyyyypqAzz
+    aaabxyzzzzpqrrrabbxyyyypqAzz
+ 0: aaabxyzzzzpqrrrabbxyyyypqAzz
+    aaaabxyzzzzpqrrrabbxyyyypqAzz
+ 0: aaaabxyzzzzpqrrrabbxyyyypqAzz
+    abcxyzzpqrrrabbxyyyypqAzz
+ 0: abcxyzzpqrrrabbxyyyypqAzz
+    aabcxyzzzpqrrrabbxyyyypqAzz
+ 0: aabcxyzzzpqrrrabbxyyyypqAzz
+    aaabcxyzzzzpqrrrabbxyyyypqAzz
+ 0: aaabcxyzzzzpqrrrabbxyyyypqAzz
+    aaaabcxyzzzzpqrrrabbxyyyypqAzz
+ 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz
+    aaaabcxyzzzzpqrrrabbbxyyyypqAzz
+ 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz
+    aaaabcxyzzzzpqrrrabbbxyyyyypqAzz
+ 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz
+    aaabcxyzpqrrrabbxyyyypABzz
+ 0: aaabcxyzpqrrrabbxyyyypABzz
+    aaabcxyzpqrrrabbxyyyypABBzz
+ 0: aaabcxyzpqrrrabbxyyyypABBzz
+    >>>aaabxyzpqrrrabbxyyyypqAzz
+ 0: aaabxyzpqrrrabbxyyyypqAzz
+    >aaaabxyzpqrrrabbxyyyypqAzz
+ 0: aaaabxyzpqrrrabbxyyyypqAzz
+    >>>>abcxyzpqrrrabbxyyyypqAzz
+ 0: abcxyzpqrrrabbxyyyypqAzz
+    *** Failers
+No match
+    abxyzpqrrabbxyyyypqAzz
+No match
+    abxyzpqrrrrabbxyyyypqAzz
+No match
+    abxyzpqrrrabxyyyypqAzz
+No match
+    aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz
+No match
+    aaaabcxyzzzzpqrrrabbbxyyypqAzz
+No match
+    aaabcxyzpqrrrabbxyyyypqqqqqqqAzz
+No match
+
+/^(abc){1,2}zz/
+    abczz
+ 0: abczz
+ 1: abc
+    abcabczz
+ 0: abcabczz
+ 1: abc
+    *** Failers
+No match
+    zz
+No match
+    abcabcabczz
+No match
+    >>abczz
+No match
+
+/^(b+|a){1,2}c/
+    bc
+ 0: bc
+ 1: b
+    bbc
+ 0: bbc
+ 1: bb
+    bbbc
+ 0: bbbc
+ 1: bbb
+    bac
+ 0: bac
+ 1: a
+    bbac
+ 0: bbac
+ 1: a
+    aac
+ 0: aac
+ 1: a
+    abbbbbbbbbbbc
+ 0: abbbbbbbbbbbc
+ 1: bbbbbbbbbbb
+    bbbbbbbbbbbac
+ 0: bbbbbbbbbbbac
+ 1: a
+    *** Failers
+No match
+    aaac
+No match
+    abbbbbbbbbbbac
+No match
+
+/^[]cde]/
+    ]thing
+ 0: ]
+    cthing
+ 0: c
+    dthing
+ 0: d
+    ething
+ 0: e
+    *** Failers
+No match
+    athing
+No match
+    fthing
+No match
+
+/^[^]cde]/
+    athing
+ 0: a
+    fthing
+ 0: f
+    *** Failers
+ 0: *
+    ]thing
+No match
+    cthing
+No match
+    dthing
+No match
+    ething
+No match
+
+/^[0-9]+$/
+    0
+ 0: 0
+    1
+ 0: 1
+    2
+ 0: 2
+    3
+ 0: 3
+    4
+ 0: 4
+    5
+ 0: 5
+    6
+ 0: 6
+    7
+ 0: 7
+    8
+ 0: 8
+    9
+ 0: 9
+    10
+ 0: 10
+    100
+ 0: 100
+    *** Failers
+No match
+    abc
+No match
+
+/^.*nter/
+    enter
+ 0: enter
+    inter
+ 0: inter
+    uponter
+ 0: uponter
+
+/^xxx[0-9]+$/
+    xxx0
+ 0: xxx0
+    xxx1234
+ 0: xxx1234
+    *** Failers
+No match
+    xxx
+No match
+
+/^.+[0-9][0-9][0-9]$/
+    x123
+ 0: x123
+    xx123
+ 0: xx123
+    123456
+ 0: 123456
+    *** Failers
+No match
+    123
+No match
+    x1234
+ 0: x1234
+
+/^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/
+    abc!pqr=apquxz.ixr.zzz.ac.uk
+ 0: abc!pqr=apquxz.ixr.zzz.ac.uk
+ 1: abc
+ 2: pqr
+    *** Failers
+No match
+    !pqr=apquxz.ixr.zzz.ac.uk
+No match
+    abc!=apquxz.ixr.zzz.ac.uk
+No match
+    abc!pqr=apquxz:ixr.zzz.ac.uk
+No match
+    abc!pqr=apquxz.ixr.zzz.ac.ukk
+No match
+
+/:/
+    Well, we need a colon: somewhere
+ 0: :
+    *** Fail if we don't
+No match
+
+/([0-9a-f:]+)$/i
+    0abc
+ 0: 0abc
+ 1: 0abc
+    abc
+ 0: abc
+ 1: abc
+    fed
+ 0: fed
+ 1: fed
+    E
+ 0: E
+ 1: E
+    ::
+ 0: ::
+ 1: ::
+    5f03:12C0::932e
+ 0: 5f03:12C0::932e
+ 1: 5f03:12C0::932e
+    fed def
+ 0: def
+ 1: def
+    Any old stuff
+ 0: ff
+ 1: ff
+    *** Failers
+No match
+    0zzz
+No match
+    gzzz
+No match
+    Any old rubbish
+No match
+
+/^.*\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/
+    .1.2.3
+ 0: .1.2.3
+ 1: 1
+ 2: 2
+ 3: 3
+    A.12.123.0
+ 0: A.12.123.0
+ 1: 12
+ 2: 123
+ 3: 0
+    *** Failers
+No match
+    .1.2.3333
+No match
+    1.2.3
+No match
+    1234.2.3
+No match
+
+/^([0-9]+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/
+    1 IN SOA non-sp1 non-sp2(
+ 0: 1 IN SOA non-sp1 non-sp2(
+ 1: 1
+ 2: non-sp1
+ 3: non-sp2
+    1    IN    SOA    non-sp1    non-sp2   (
+ 0: 1    IN    SOA    non-sp1    non-sp2   (
+ 1: 1
+ 2: non-sp1
+ 3: non-sp2
+    *** Failers
+No match
+    1IN SOA non-sp1 non-sp2(
+No match
+
+/^[a-zA-Z0-9][a-zA-Z0-9-]*(\.[a-zA-Z0-9][a-zA-z0-9-]*)*\.$/
+    a.
+ 0: a.
+    Z.
+ 0: Z.
+    2.
+ 0: 2.
+    ab-c.pq-r.
+ 0: ab-c.pq-r.
+ 1: .pq-r
+    sxk.zzz.ac.uk.
+ 0: sxk.zzz.ac.uk.
+ 1: .uk
+    x-.y-.
+ 0: x-.y-.
+ 1: .y-
+    *** Failers
+No match
+    -abc.peq.
+No match
+
+/^\*\.[a-z]([a-z0-9-]*[a-z0-9]+)?(\.[a-z]([a-z0-9-]*[a-z0-9]+)?)*$/
+    *.a
+ 0: *.a
+    *.b0-a
+ 0: *.b0-a
+ 1: 0-a
+    *.c3-b.c
+ 0: *.c3-b.c
+ 1: 3-b
+ 2: .c
+    *.c-a.b-c
+ 0: *.c-a.b-c
+ 1: -a
+ 2: .b-c
+ 3: -c
+    *** Failers
+No match
+    *.0
+No match
+    *.a-
+No match
+    *.a-b.c-
+No match
+    *.c-a.0-c
+No match
+
+/^[0-9a-f](\.[0-9a-f])*$/i
+    a.b.c.d
+ 0: a.b.c.d
+ 1: .d
+    A.B.C.D
+ 0: A.B.C.D
+ 1: .D
+    a.b.c.1.2.3.C
+ 0: a.b.c.1.2.3.C
+ 1: .C
+
+/^".*"\s*(;.*)?$/
+    "1234"
+ 0: "1234"
+    "abcd" ;
+ 0: "abcd" ;
+ 1: ;
+    "" ; rhubarb
+ 0: "" ; rhubarb
+ 1: ; rhubarb
+    *** Failers
+No match
+    "1234" : things
+No match
+
+/^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/
+    abcdefhijklm
+ 0: abcdefhijklm
+ 1: abc
+ 2: bc
+ 3: c
+ 4: def
+ 5: ef
+ 6: f
+ 7: hij
+ 8: ij
+ 9: j
+10: klm
+11: lm
+12: m
+
+/^a*\w/
+    z
+ 0: z
+    az
+ 0: az
+    aaaz
+ 0: aaaz
+    a
+ 0: a
+    aa
+ 0: aa
+    aaaa
+ 0: aaaa
+    a+
+ 0: a
+    aa+
+ 0: aa
+
+/^a+\w/
+    az
+ 0: az
+    aaaz
+ 0: aaaz
+    aa
+ 0: aa
+    aaaa
+ 0: aaaa
+    aa+
+ 0: aa
+
+/^[0-9]{8}\w{2,}/
+    1234567890
+ 0: 1234567890
+    12345678ab
+ 0: 12345678ab
+    12345678__
+ 0: 12345678__
+    *** Failers
+No match
+    1234567
+No match
+
+/^[aeiou0-9]{4,5}$/
+    uoie
+ 0: uoie
+    1234
+ 0: 1234
+    12345
+ 0: 12345
+    aaaaa
+ 0: aaaaa
+    *** Failers
+No match
+    123456
+No match
+
+/\`(abc|def)=(\1){2,3}\'/
+    abc=abcabc
+ 0: abc=abcabc
+ 1: abc
+ 2: abc
+    def=defdefdef
+ 0: def=defdefdef
+ 1: def
+ 2: def
+    *** Failers
+No match
+    abc=defdef
+No match
+
+/(cat(a(ract|tonic)|erpillar)) \1()2(3)/
+    cataract cataract23
+ 0: cataract cataract23
+ 1: cataract
+ 2: aract
+ 3: ract
+ 4: 
+ 5: 3
+    catatonic catatonic23
+ 0: catatonic catatonic23
+ 1: catatonic
+ 2: atonic
+ 3: tonic
+ 4: 
+ 5: 3
+    caterpillar caterpillar23
+ 0: caterpillar caterpillar23
+ 1: caterpillar
+ 2: erpillar
+ 3: <unset>
+ 4: 
+ 5: 3
+
+
+/^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/
+    From abcd  Mon Sep 01 12:33:02 1997
+ 0: From abcd  Mon Sep 01 12:33
+ 1: abcd
+
+/^From\s+\S+\s+([a-zA-Z]{3}\s+){2}[0-9]{1,2}\s+[0-9][0-9]:[0-9][0-9]/
+    From abcd  Mon Sep 01 12:33:02 1997
+ 0: From abcd  Mon Sep 01 12:33
+ 1: Sep 
+    From abcd  Mon Sep  1 12:33:02 1997
+ 0: From abcd  Mon Sep  1 12:33
+ 1: Sep  
+    *** Failers
+No match
+    From abcd  Sep 01 12:33:02 1997
+No match
+
+/^(a)\1{2,3}(.)/
+    aaab
+ 0: aaab
+ 1: a
+ 2: b
+    aaaab
+ 0: aaaab
+ 1: a
+ 2: b
+    aaaaab
+ 0: aaaaa
+ 1: a
+ 2: a
+    aaaaaab
+ 0: aaaaa
+ 1: a
+ 2: a
+
+/^[ab]{1,3}(ab*|b)/
+    aabbbbb
+ 0: aabbbbb
+ 1: abbbbb
+
+/^(cow|)\1(bell)/
+    cowcowbell
+ 0: cowcowbell
+ 1: cow
+ 2: bell
+    bell
+ 0: bell
+ 1: 
+ 2: bell
+    *** Failers
+No match
+    cowbell
+No match
+
+/^(a|)\1+b/
+    aab
+ 0: aab
+ 1: a
+    aaaab
+ 0: aaaab
+ 1: a
+    b
+ 0: b
+ 1: 
+    *** Failers
+No match
+    ab
+No match
+
+/^(a|)\1{2}b/
+    aaab
+ 0: aaab
+ 1: a
+    b
+ 0: b
+ 1: 
+    *** Failers
+No match
+    ab
+No match
+    aab
+No match
+    aaaab
+No match
+
+/^(a|)\1{2,3}b/
+    aaab
+ 0: aaab
+ 1: a
+    aaaab
+ 0: aaaab
+ 1: a
+    b
+ 0: b
+ 1: 
+    *** Failers
+No match
+    ab
+No match
+    aab
+No match
+    aaaaab
+No match
+
+/ab{1,3}bc/
+    abbbbc
+ 0: abbbbc
+    abbbc
+ 0: abbbc
+    abbc
+ 0: abbc
+    *** Failers
+No match
+    abc
+No match
+    abbbbbc
+No match
+
+/([^.]*)\.([^:]*):[T ]+(.*)/
+    track1.title:TBlah blah blah
+ 0: track1.title:TBlah blah blah
+ 1: track1
+ 2: title
+ 3: Blah blah blah
+
+/([^.]*)\.([^:]*):[T ]+(.*)/i
+    track1.title:TBlah blah blah
+ 0: track1.title:TBlah blah blah
+ 1: track1
+ 2: title
+ 3: Blah blah blah
+
+/([^.]*)\.([^:]*):[t ]+(.*)/i
+    track1.title:TBlah blah blah
+ 0: track1.title:TBlah blah blah
+ 1: track1
+ 2: title
+ 3: Blah blah blah
+
+/^abc$/
+    abc
+ 0: abc
+    *** Failers
+No match
+
+/[-az]+/
+    az-
+ 0: az-
+    *** Failers
+ 0: a
+    b
+No match
+
+/[az-]+/
+    za-
+ 0: za-
+    *** Failers
+ 0: a
+    b
+No match
+
+/[a-z]+/
+    abcdxyz
+ 0: abcdxyz
+
+/[0-9-]+/
+    12-34
+ 0: 12-34
+    *** Failers
+No match
+    aaa
+No match
+
+/(abc)\1/i
+    abcabc
+ 0: abcabc
+ 1: abc
+    ABCabc
+ 0: ABCabc
+ 1: ABC
+    abcABC
+ 0: abcABC
+ 1: abc
+
+/a{0}bc/
+    bc
+ 0: bc
+
+/^([^a])([^b])([^c]*)([^d]{3,4})/
+    baNOTccccd
+ 0: baNOTcccc
+ 1: b
+ 2: a
+ 3: NOT
+ 4: cccc
+    baNOTcccd
+ 0: baNOTccc
+ 1: b
+ 2: a
+ 3: NOT
+ 4: ccc
+    baNOTccd
+ 0: baNOTcc
+ 1: b
+ 2: a
+ 3: NO
+ 4: Tcc
+    bacccd
+ 0: baccc
+ 1: b
+ 2: a
+ 3: 
+ 4: ccc
+    *** Failers
+ 0: *** Failers
+ 1: *
+ 2: *
+ 3: * Fail
+ 4: ers
+    anything
+No match
+    baccd
+No match
+
+/[^a]/
+    Abc
+ 0: A
+
+/[^a]/i
+    Abc 
+ 0: b
+
+/[^a]+/
+    AAAaAbc
+ 0: AAA
+
+/[^a]+/i
+    AAAaAbc
+ 0: bc
+
+/[^k]$/
+    abc
+ 0: c
+    *** Failers
+ 0: s
+    abk
+No match
+
+/[^k]{2,3}$/
+    abc
+ 0: abc
+    kbc
+ 0: bc
+    kabc
+ 0: abc
+    *** Failers
+ 0: ers
+    abk
+No match
+    akb
+No match
+    akk 
+No match
+
+/^[0-9]{8,}@.+[^k]$/
+    12345678@a.b.c.d
+ 0: 12345678@a.b.c.d
+    123456789@x.y.z
+ 0: 123456789@x.y.z
+    *** Failers
+No match
+    12345678@x.y.uk
+No match
+    1234567@a.b.c.d       
+No match
+
+/(a)\1{8,}/
+    aaaaaaaaa
+ 0: aaaaaaaaa
+ 1: a
+    aaaaaaaaaa
+ 0: aaaaaaaaaa
+ 1: a
+    *** Failers
+No match
+    aaaaaaa   
+No match
+
+/[^a]/
+    aaaabcd
+ 0: b
+    aaAabcd 
+ 0: A
+
+/[^a]/i
+    aaaabcd
+ 0: b
+    aaAabcd 
+ 0: b
+
+/[^az]/
+    aaaabcd
+ 0: b
+    aaAabcd 
+ 0: A
+
+/[^az]/i
+    aaaabcd
+ 0: b
+    aaAabcd 
+ 0: b
+
+/P[^*]TAIRE[^*]{1,6}LL/
+    xxxxxxxxxxxPSTAIREISLLxxxxxxxxx
+ 0: PSTAIREISLL
+
+/P[^*]TAIRE[^*]{1,}LL/
+    xxxxxxxxxxxPSTAIREISLLxxxxxxxxx
+ 0: PSTAIREISLL
+
+/(\.[0-9][0-9][1-9]?)[0-9]+/
+    1.230003938
+ 0: .230003938
+ 1: .23
+    1.875000282   
+ 0: .875000282
+ 1: .875
+    1.235  
+ 0: .235
+ 1: .23
+                  
+/\b(foo)\s+(\w+)/i
+    Food is on the foo table
+ 0: foo table
+ 1: foo
+ 2: table
+    
+/foo(.*)bar/
+    The food is under the bar in the barn.
+ 0: food is under the bar in the bar
+ 1: d is under the bar in the 
+    
+/(.*)([0-9]*)/
+    I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers: 53147
+ 2: 
+    
+/(.*)([0-9]+)/
+    I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers: 5314
+ 2: 7
+
+/(.*)([0-9]+)$/
+    I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers: 5314
+ 2: 7
+
+/(.*)\b([0-9]+)$/
+    I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers: 
+ 2: 53147
+
+/(.*[^0-9])([0-9]+)$/
+    I have 2 numbers: 53147
+ 0: I have 2 numbers: 53147
+ 1: I have 2 numbers: 
+ 2: 53147
+
+/[[:digit:]][[:digit:]]\/[[:digit:]][[:digit:]]\/[[:digit:]][[:digit:]][[:digit:]][[:digit:]]/
+    01/01/2000
+ 0: 01/01/2000
+
+/^(a){0,0}/
+    bcd
+ 0: 
+    abc
+ 0: 
+    aab     
+ 0: 
+
+/^(a){0,1}/
+    bcd
+ 0: 
+    abc
+ 0: a
+ 1: a
+    aab  
+ 0: a
+ 1: a
+
+/^(a){0,2}/
+    bcd
+ 0: 
+    abc
+ 0: a
+ 1: a
+    aab  
+ 0: aa
+ 1: a
+
+/^(a){0,3}/
+    bcd
+ 0: 
+    abc
+ 0: a
+ 1: a
+    aab
+ 0: aa
+ 1: a
+    aaa   
+ 0: aaa
+ 1: a
+
+/^(a){0,}/
+    bcd
+ 0: 
+    abc
+ 0: a
+ 1: a
+    aab
+ 0: aa
+ 1: a
+    aaa
+ 0: aaa
+ 1: a
+    aaaaaaaa    
+ 0: aaaaaaaa
+ 1: a
+
+/^(a){1,1}/
+    bcd
+No match
+    abc
+ 0: a
+ 1: a
+    aab  
+ 0: a
+ 1: a
+
+/^(a){1,2}/
+    bcd
+No match
+    abc
+ 0: a
+ 1: a
+    aab  
+ 0: aa
+ 1: a
+
+/^(a){1,3}/
+    bcd
+No match
+    abc
+ 0: a
+ 1: a
+    aab
+ 0: aa
+ 1: a
+    aaa   
+ 0: aaa
+ 1: a
+
+/^(a){1,}/
+    bcd
+No match
+    abc
+ 0: a
+ 1: a
+    aab
+ 0: aa
+ 1: a
+    aaa
+ 0: aaa
+ 1: a
+    aaaaaaaa    
+ 0: aaaaaaaa
+ 1: a
+
+/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/
+    123456654321
+ 0: 123456654321
+
+/^[[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]]/
+    123456654321 
+ 0: 123456654321
+
+/^[abc]{12}/
+    abcabcabcabc
+ 0: abcabcabcabc
+    
+/^[a-c]{12}/
+    abcabcabcabc
+ 0: abcabcabcabc
+    
+/^(a|b|c){12}/
+    abcabcabcabc 
+ 0: abcabcabcabc
+ 1: c
+
+/^[abcdefghijklmnopqrstuvwxy0123456789]/
+    n
+ 0: n
+    *** Failers 
+No match
+    z 
+No match
+
+/abcde{0,0}/
+    abcd
+ 0: abcd
+    *** Failers
+No match
+    abce  
+No match
+
+/ab[cd]{0,0}e/
+    abe
+ 0: abe
+    *** Failers
+No match
+    abcde 
+No match
+    
+/ab(c){0,0}d/
+    abd
+ 0: abd
+    *** Failers
+No match
+    abcd   
+No match
+
+/a(b*)/
+    a
+ 0: a
+ 1: 
+    ab
+ 0: ab
+ 1: b
+    abbbb
+ 0: abbbb
+ 1: bbbb
+    *** Failers
+ 0: a
+ 1: 
+    bbbbb    
+No match
+    
+/ab[0-9]{0}e/
+    abe
+ 0: abe
+    *** Failers
+No match
+    ab1e   
+No match
+    
+/(A|B)*CD/
+    CD 
+ 0: CD
+
+/(AB)*\1/
+    ABABAB
+ 0: ABABAB
+ 1: AB
+    
+/([0-9]+)(\w)/
+    12345a
+ 0: 12345a
+ 1: 12345
+ 2: a
+    12345+ 
+ 0: 12345
+ 1: 1234
+ 2: 5
+
+/(abc|)+/
+    abc
+ 0: abc
+ 1: abc
+    abcabc
+ 0: abcabc
+ 1: abc
+    abcabcabc
+ 0: abcabcabc
+ 1: abc
+    xyz      
+ 0: 
+ 1: 
+
+/([a]*)*/
+    a
+ 0: a
+ 1: a
+    aaaaa 
+ 0: aaaaa
+ 1: aaaaa
+
+/([ab]*)*/
+    a
+ 0: a
+ 1: a
+    b
+ 0: b
+ 1: b
+    ababab
+ 0: ababab
+ 1: ababab
+    aaaabcde
+ 0: aaaab
+ 1: aaaab
+    bbbb    
+ 0: bbbb
+ 1: bbbb
+
+/([^a]*)*/
+    b
+ 0: b
+ 1: b
+    bbbb
+ 0: bbbb
+ 1: bbbb
+    aaa   
+ 0: 
+
+/([^ab]*)*/
+    cccc
+ 0: cccc
+ 1: cccc
+    abab  
+ 0: 
+
+/abc/
+    abc
+ 0: abc
+    xabcy
+ 0: abc
+    ababc
+ 0: abc
+    *** Failers
+No match
+    xbc
+No match
+    axc
+No match
+    abx
+No match
+
+/ab*c/
+    abc
+ 0: abc
+
+/ab*bc/
+    abc
+ 0: abc
+    abbc
+ 0: abbc
+    abbbbc
+ 0: abbbbc
+
+/.{1}/
+    abbbbc
+ 0: a
+
+/.{3,4}/
+    abbbbc
+ 0: abbb
+
+/ab{0,}bc/
+    abbbbc
+ 0: abbbbc
+
+/ab+bc/
+    abbc
+ 0: abbc
+    *** Failers
+No match
+    abc
+No match
+    abq
+No match
+
+/ab+bc/
+    abbbbc
+ 0: abbbbc
+
+/ab{1,}bc/
+    abbbbc
+ 0: abbbbc
+
+/ab{1,3}bc/
+    abbbbc
+ 0: abbbbc
+
+/ab{3,4}bc/
+    abbbbc
+ 0: abbbbc
+
+/ab{4,5}bc/
+    *** Failers
+No match
+    abq
+No match
+    abbbbc
+No match
+
+/ab?bc/
+    abbc
+ 0: abbc
+    abc
+ 0: abc
+
+/ab{0,1}bc/
+    abc
+ 0: abc
+
+/ab?c/
+    abc
+ 0: abc
+
+/ab{0,1}c/
+    abc
+ 0: abc
+
+/^abc$/
+    abc
+ 0: abc
+    *** Failers
+No match
+    abbbbc
+No match
+    abcc
+No match
+
+/^abc/
+    abcc
+ 0: abc
+
+/abc$/
+    aabc
+ 0: abc
+    *** Failers
+No match
+    aabc
+ 0: abc
+    aabcd
+No match
+
+/^/
+    abc
+ 0: 
+
+/$/
+    abc
+ 0: 
+
+/a.c/
+    abc
+ 0: abc
+    axc
+ 0: axc
+
+/a.*c/
+    axyzc
+ 0: axyzc
+
+/a[bc]d/
+    abd
+ 0: abd
+    *** Failers
+No match
+    axyzd
+No match
+    abc
+No match
+
+/a[b-d]e/
+    ace
+ 0: ace
+
+/a[b-d]/
+    aac
+ 0: ac
+
+/a[-b]/
+    a-
+ 0: a-
+
+/a[b-]/
+    a-
+ 0: a-
+
+/a[]]b/
+    a]b
+ 0: a]b
+
+/a[^bc]d/
+    aed
+ 0: aed
+    *** Failers
+No match
+    abd
+No match
+    abd
+No match
+
+/a[^-b]c/
+    adc
+ 0: adc
+
+/a[^]b]c/
+    adc
+ 0: adc
+    *** Failers
+No match
+    a-c
+ 0: a-c
+    a]c
+No match
+
+/\ba\b/
+    a-
+ 0: a
+    -a
+ 0: a
+    -a-
+ 0: a
+
+/\by\b/
+    *** Failers
+No match
+    xy
+No match
+    yz
+No match
+    xyz
+No match
+
+/\Ba\B/
+    *** Failers
+ 0: a
+    a-
+No match
+    -a
+No match
+    -a-
+No match
+
+/\By\b/
+    xy
+ 0: y
+
+/\by\B/
+    yz
+ 0: y
+
+/\By\B/
+    xyz
+ 0: y
+
+/\w/
+    a
+ 0: a
+
+/\W/
+    -
+ 0: -
+    *** Failers
+ 0: *
+    -
+ 0: -
+    a
+No match
+
+/a\sb/
+    a b
+ 0: a b
+
+/a\Sb/
+    a-b
+ 0: a-b
+    *** Failers
+No match
+    a-b
+ 0: a-b
+    a b
+No match
+
+/[0-9]/
+    1
+ 0: 1
+
+/[^0-9]/
+    -
+ 0: -
+    *** Failers
+ 0: *
+    -
+ 0: -
+    1
+No match
+
+/ab|cd/
+    abc
+ 0: ab
+    abcd
+ 0: ab
+
+/()ef/
+    def
+ 0: ef
+ 1: 
+
+/a\(b/
+    a(b
+ 0: a(b
+
+/a\(*b/
+    ab
+ 0: ab
+    a((b
+ 0: a((b
+
+/((a))/
+    abc
+ 0: a
+ 1: a
+ 2: a
+
+/(a)b(c)/
+    abc
+ 0: abc
+ 1: a
+ 2: c
+
+/a+b+c/
+    aabbabc
+ 0: abc
+
+/a{1,}b{1,}c/
+    aabbabc
+ 0: abc
+
+/(a+|b)*/
+    ab
+ 0: ab
+ 1: b
+
+/(a+|b){0,}/
+    ab
+ 0: ab
+ 1: b
+
+/(a+|b)+/
+    ab
+ 0: ab
+ 1: b
+
+/(a+|b){1,}/
+    ab
+ 0: ab
+ 1: b
+
+/(a+|b)?/
+    ab
+ 0: a
+ 1: a
+
+/(a+|b){0,1}/
+    ab
+ 0: a
+ 1: a
+
+/[^ab]*/
+    cde
+ 0: cde
+
+/abc/
+    *** Failers
+No match
+    b
+No match
+    
+
+/a*/
+    
+
+/([abc])*d/
+    abbbcd
+ 0: abbbcd
+ 1: c
+
+/([abc])*bcd/
+    abcd
+ 0: abcd
+ 1: a
+
+/a|b|c|d|e/
+    e
+ 0: e
+
+/(a|b|c|d|e)f/
+    ef
+ 0: ef
+ 1: e
+
+/abcd*efg/
+    abcdefg
+ 0: abcdefg
+
+/ab*/
+    xabyabbbz
+ 0: ab
+    xayabbbz
+ 0: a
+
+/(ab|cd)e/
+    abcde
+ 0: cde
+ 1: cd
+
+/[abhgefdc]ij/
+    hij
+ 0: hij
+
+/(abc|)ef/
+    abcdef
+ 0: ef
+ 1: 
+
+/(a|b)c*d/
+    abcd
+ 0: bcd
+ 1: b
+
+/(ab|ab*)bc/
+    abc
+ 0: abc
+ 1: a
+
+/a([bc]*)c*/
+    abc
+ 0: abc
+ 1: bc
+
+/a([bc]*)(c*d)/
+    abcd
+ 0: abcd
+ 1: bc
+ 2: d
+
+/a([bc]+)(c*d)/
+    abcd
+ 0: abcd
+ 1: bc
+ 2: d
+
+/a([bc]*)(c+d)/
+    abcd
+ 0: abcd
+ 1: b
+ 2: cd
+
+/a[bcd]*dcdcde/
+    adcdcde
+ 0: adcdcde
+
+/a[bcd]+dcdcde/
+    *** Failers
+No match
+    abcde
+No match
+    adcdcde
+No match
+
+/(ab|a)b*c/
+    abc
+ 0: abc
+ 1: ab
+
+/((a)(b)c)(d)/
+    abcd
+ 0: abcd
+ 1: abc
+ 2: a
+ 3: b
+ 4: d
+
+/[a-zA-Z_][a-zA-Z0-9_]*/
+    alpha
+ 0: alpha
+
+/^a(bc+|b[eh])g|.h$/
+    abh
+ 0: bh
+
+/(bc+d$|ef*g.|h?i(j|k))/
+    effgz
+ 0: effgz
+ 1: effgz
+    ij
+ 0: ij
+ 1: ij
+ 2: j
+    reffgz
+ 0: effgz
+ 1: effgz
+    *** Failers
+No match
+    effg
+No match
+    bcdd
+No match
+
+/((((((((((a))))))))))/
+    a
+ 0: a
+ 1: a
+ 2: a
+ 3: a
+ 4: a
+ 5: a
+ 6: a
+ 7: a
+ 8: a
+ 9: a
+10: a
+
+/((((((((((a))))))))))\9/
+    aa
+ 0: aa
+ 1: a
+ 2: a
+ 3: a
+ 4: a
+ 5: a
+ 6: a
+ 7: a
+ 8: a
+ 9: a
+10: a
+
+/(((((((((a)))))))))/
+    a
+ 0: a
+ 1: a
+ 2: a
+ 3: a
+ 4: a
+ 5: a
+ 6: a
+ 7: a
+ 8: a
+ 9: a
+
+/multiple words of text/
+    *** Failers
+No match
+    aa
+No match
+    uh-uh
+No match
+
+/multiple words/
+    multiple words, yeah
+ 0: multiple words
+
+/(.*)c(.*)/
+    abcde
+ 0: abcde
+ 1: ab
+ 2: de
+
+/\((.*), (.*)\)/
+    (a, b)
+ 0: (a, b)
+ 1: a
+ 2: b
+
+/abcd/
+    abcd
+ 0: abcd
+
+/a(bc)d/
+    abcd
+ 0: abcd
+ 1: bc
+
+/a[-]?c/
+    ac
+ 0: ac
+
+/(abc)\1/
+    abcabc
+ 0: abcabc
+ 1: abc
+
+/([a-c]*)\1/
+    abcabc
+ 0: abcabc
+ 1: abc
+
+/(a)|\1/
+    a
+ 0: a
+ 1: a
+    *** Failers
+ 0: a
+ 1: a
+    ab
+ 0: a
+ 1: a
+    x
+No match
+
+/abc/i
+    ABC
+ 0: ABC
+    XABCY
+ 0: ABC
+    ABABC
+ 0: ABC
+    *** Failers
+No match
+    aaxabxbaxbbx
+No match
+    XBC
+No match
+    AXC
+No match
+    ABX
+No match
+
+/ab*c/i
+    ABC
+ 0: ABC
+
+/ab*bc/i
+    ABC
+ 0: ABC
+    ABBC
+ 0: ABBC
+
+/ab+bc/i
+    *** Failers
+No match
+    ABC
+No match
+    ABQ
+No match
+
+/ab+bc/i
+    ABBBBC
+ 0: ABBBBC
+
+/^abc$/i
+    ABC
+ 0: ABC
+    *** Failers
+No match
+    ABBBBC
+No match
+    ABCC
+No match
+
+/^abc/i
+    ABCC
+ 0: ABC
+
+/abc$/i
+    AABC
+ 0: ABC
+
+/^/i
+    ABC
+ 0: 
+
+/$/i
+    ABC
+ 0: 
+
+/a.c/i
+    ABC
+ 0: ABC
+    AXC
+ 0: AXC
+
+/a.*c/i
+    *** Failers
+No match
+    AABC
+ 0: AABC
+    AXYZD
+No match
+
+/a[bc]d/i
+    ABD
+ 0: ABD
+
+/a[b-d]e/i
+    ACE
+ 0: ACE
+    *** Failers
+No match
+    ABC
+No match
+    ABD
+No match
+
+/a[b-d]/i
+    AAC
+ 0: AC
+
+/a[-b]/i
+    A-
+ 0: A-
+
+/a[b-]/i
+    A-
+ 0: A-
+
+/a[]]b/i
+    A]B
+ 0: A]B
+
+/a[^bc]d/i
+    AED
+ 0: AED
+
+/a[^-b]c/i
+    ADC
+ 0: ADC
+    *** Failers
+No match
+    ABD
+No match
+    A-C
+No match
+
+/a[^]b]c/i
+    ADC
+ 0: ADC
+
+/ab|cd/i
+    ABC
+ 0: AB
+    ABCD
+ 0: AB
+
+/()ef/i
+    DEF
+ 0: EF
+ 1: 
+
+/$b/i
+    *** Failers
+No match
+    A]C
+No match
+    B
+No match
+
+/a\(b/i
+    A(B
+ 0: A(B
+
+/a\(*b/i
+    AB
+ 0: AB
+    A((B
+ 0: A((B
+
+/((a))/i
+    ABC
+ 0: A
+ 1: A
+ 2: A
+
+/(a)b(c)/i
+    ABC
+ 0: ABC
+ 1: A
+ 2: C
+
+/a+b+c/i
+    AABBABC
+ 0: ABC
+
+/a{1,}b{1,}c/i
+    AABBABC
+ 0: ABC
+
+/(a+|b)*/i
+    AB
+ 0: AB
+ 1: B
+
+/(a+|b){0,}/i
+    AB
+ 0: AB
+ 1: B
+
+/(a+|b)+/i
+    AB
+ 0: AB
+ 1: B
+
+/(a+|b){1,}/i
+    AB
+ 0: AB
+ 1: B
+
+/(a+|b)?/i
+    AB
+ 0: A
+ 1: A
+
+/(a+|b){0,1}/i
+    AB
+ 0: A
+ 1: A
+
+/[^ab]*/i
+    CDE
+ 0: CDE
+
+/([abc])*d/i
+    ABBBCD
+ 0: ABBBCD
+ 1: C
+
+/([abc])*bcd/i
+    ABCD
+ 0: ABCD
+ 1: A
+
+/a|b|c|d|e/i
+    E
+ 0: E
+
+/(a|b|c|d|e)f/i
+    EF
+ 0: EF
+ 1: E
+
+/abcd*efg/i
+    ABCDEFG
+ 0: ABCDEFG
+
+/ab*/i
+    XABYABBBZ
+ 0: AB
+    XAYABBBZ
+ 0: A
+
+/(ab|cd)e/i
+    ABCDE
+ 0: CDE
+ 1: CD
+
+/[abhgefdc]ij/i
+    HIJ
+ 0: HIJ
+
+/^(ab|cd)e/i
+    ABCDE
+No match
+
+/(abc|)ef/i
+    ABCDEF
+ 0: EF
+ 1: 
+
+/(a|b)c*d/i
+    ABCD
+ 0: BCD
+ 1: B
+
+/(ab|ab*)bc/i
+    ABC
+ 0: ABC
+ 1: A
+
+/a([bc]*)c*/i
+    ABC
+ 0: ABC
+ 1: BC
+
+/a([bc]*)(c*d)/i
+    ABCD
+ 0: ABCD
+ 1: BC
+ 2: D
+
+/a([bc]+)(c*d)/i
+    ABCD
+ 0: ABCD
+ 1: BC
+ 2: D
+
+/a([bc]*)(c+d)/i
+    ABCD
+ 0: ABCD
+ 1: B
+ 2: CD
+
+/a[bcd]*dcdcde/i
+    ADCDCDE
+ 0: ADCDCDE
+
+/a[bcd]+dcdcde/i
+
+/(ab|a)b*c/i
+    ABC
+ 0: ABC
+ 1: AB
+
+/((a)(b)c)(d)/i
+    ABCD
+ 0: ABCD
+ 1: ABC
+ 2: A
+ 3: B
+ 4: D
+
+/[a-zA-Z_][a-zA-Z0-9_]*/i
+    ALPHA
+ 0: ALPHA
+
+/^a(bc+|b[eh])g|.h$/i
+    ABH
+ 0: BH
+
+/(bc+d$|ef*g.|h?i(j|k))/i
+    EFFGZ
+ 0: EFFGZ
+ 1: EFFGZ
+    IJ
+ 0: IJ
+ 1: IJ
+ 2: J
+    REFFGZ
+ 0: EFFGZ
+ 1: EFFGZ
+    *** Failers
+No match
+    ADCDCDE
+No match
+    EFFG
+No match
+    BCDD
+No match
+
+/((((((((((a))))))))))/i
+    A
+ 0: A
+ 1: A
+ 2: A
+ 3: A
+ 4: A
+ 5: A
+ 6: A
+ 7: A
+ 8: A
+ 9: A
+10: A
+
+/((((((((((a))))))))))\9/i
+    AA
+ 0: AA
+ 1: A
+ 2: A
+ 3: A
+ 4: A
+ 5: A
+ 6: A
+ 7: A
+ 8: A
+ 9: A
+10: A
+
+/(((((((((a)))))))))/i
+    A
+ 0: A
+ 1: A
+ 2: A
+ 3: A
+ 4: A
+ 5: A
+ 6: A
+ 7: A
+ 8: A
+ 9: A
+
+/multiple words of text/i
+    *** Failers
+No match
+    AA
+No match
+    UH-UH
+No match
+
+/multiple words/i
+    MULTIPLE WORDS, YEAH
+ 0: MULTIPLE WORDS
+
+/(.*)c(.*)/i
+    ABCDE
+ 0: ABCDE
+ 1: AB
+ 2: DE
+
+/\((.*), (.*)\)/i
+    (A, B)
+ 0: (A, B)
+ 1: A
+ 2: B
+
+/abcd/i
+    ABCD
+ 0: ABCD
+
+/a(bc)d/i
+    ABCD
+ 0: ABCD
+ 1: BC
+
+/a[-]?c/i
+    AC
+ 0: AC
+
+/(abc)\1/i
+    ABCABC
+ 0: ABCABC
+ 1: ABC
+
+/([a-c]*)\1/i
+    ABCABC
+ 0: ABCABC
+ 1: ABC
+
+/((foo)|(bar))*/
+    foobar
+ 0: foobar
+ 1: bar
+ 2: foo
+ 3: bar
+
+/^(.+)?B/
+    AB
+ 0: AB
+ 1: A
+
+/^([^a-z])|(\^)$/
+    .
+ 0: .
+ 1: .
+
+/^[<>]&/
+    <&OUT
+ 0: <&
+
+/^(){3,5}/
+    abc
+ 0: 
+ 1: 
+
+/^(a+)*ax/
+    aax
+ 0: aax
+ 1: a
+
+/^((a|b)+)*ax/
+    aax
+ 0: aax
+ 1: a
+ 2: a
+
+/^((a|bc)+)*ax/
+    aax
+ 0: aax
+ 1: a
+ 2: a
+
+/(a|x)*ab/
+    cab
+ 0: ab
+
+/(a)*ab/
+    cab
+ 0: ab
+
+/(ab)[0-9]\1/i
+    Ab4ab
+ 0: Ab4ab
+ 1: Ab
+    ab4Ab
+ 0: ab4Ab
+ 1: ab
+
+/foo\w*[0-9]{4}baz/
+    foobar1234baz
+ 0: foobar1234baz
+
+/(\w+:)+/
+    one:
+ 0: one:
+ 1: one:
+
+/((\w|:)+::)?(\w+)$/
+    abcd
+ 0: abcd
+ 1: <unset>
+ 2: <unset>
+ 3: abcd
+    xy:z:::abcd
+ 0: xy:z:::abcd
+ 1: xy:z:::
+ 2: :
+ 3: abcd
+
+/^[^bcd]*(c+)/
+    aexycd
+ 0: aexyc
+ 1: c
+
+/(a*)b+/
+    caab
+ 0: aab
+ 1: aa
+
+/((\w|:)+::)?(\w+)$/
+    abcd
+ 0: abcd
+ 1: <unset>
+ 2: <unset>
+ 3: abcd
+    xy:z:::abcd
+ 0: xy:z:::abcd
+ 1: xy:z:::
+ 2: :
+ 3: abcd
+    *** Failers
+ 0: Failers
+ 1: <unset>
+ 2: <unset>
+ 3: Failers
+    abcd:
+No match
+    abcd:
+No match
+
+/^[^bcd]*(c+)/
+    aexycd
+ 0: aexyc
+ 1: c
+
+/((Z)+|A)*/
+    ZABCDEFG
+ 0: ZA
+ 1: A
+ 2: Z
+
+/(Z()|A)*/
+    ZABCDEFG
+ 0: ZA
+ 1: A
+ 2: 
+
+/(Z(())|A)*/
+    ZABCDEFG
+ 0: ZA
+ 1: A
+ 2: 
+ 3: 
+
+/(.*)[0-9]+\1/
+    abc123abc
+ 0: abc123abc
+ 1: abc
+    abc123bc 
+ 0: bc123bc
+ 1: bc
+
+/((.*))[0-9]+\1/
+    abc123abc
+ 0: abc123abc
+ 1: abc
+ 2: abc
+    abc123bc  
+ 0: bc123bc
+ 1: bc
+ 2: bc
+
+/^a{2,5}$/
+    aa
+ 0: aa
+    aaa
+ 0: aaa
+    aaaa
+ 0: aaaa
+    aaaaa
+ 0: aaaaa
+    *** Failers
+No match
+    a
+No match
+    b
+No match
+    aaaaab
+No match
+    aaaaaa
Index: /tags/kBuild-0.1.4/src/sed/testsuite/SPENCER.tests
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/SPENCER.tests	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/SPENCER.tests	(revision 1780)
@@ -0,0 +1,538 @@
+# regular expression test set
+# Lines are at least three fields, separated by one or more tabs.  "" stands
+# for an empty field.  First field is an RE.  Second field is flags.  If
+# C flag given, regcomp() is expected to fail, and the third field is the
+# error name (minus the leading REG_).
+#
+# Otherwise it is expected to succeed, and the third field is the string to
+# try matching it against.  If there is no fourth field, the match is
+# expected to fail.  If there is a fourth field, it is the substring that
+# the RE is expected to match.  If there is a fifth field, it is a comma-
+# separated list of what the subexpressions should match, with - indicating
+# no match for that one.  In both the fourth and fifth fields, a (sub)field
+# starting with @ indicates that the (sub)expression is expected to match
+# a null string followed by the stuff after the @; this provides a way to
+# test where null strings match.  The character `N' in REs and strings
+# is newline, `S' is space, `T' is tab, `Z' is NUL.
+#
+# The full list of flags:
+#	-	placeholder, does nothing
+#	b	RE is a BRE, not an ERE
+#	&	try it as both an ERE and a BRE
+#	C	regcomp() error expected, third field is error name
+#	i	REG_ICASE
+#	m	("mundane") REG_NOSPEC
+#	s	REG_NOSUB (not really testable)
+#	n	REG_NEWLINE
+#	^	REG_NOTBOL
+#	$	REG_NOTEOL
+#	#	REG_STARTEND (see below)
+#	p	REG_PEND
+#
+# For REG_STARTEND, the start/end offsets are those of the substring
+# enclosed in ().
+
+# basics
+a		&	a	a
+abc		&	abc	abc
+abc|de		-	abc	abc
+a|b|c		-	abc	a
+
+# parentheses and perversions thereof
+a(b)c		-	abc	abc
+a\(b\)c		b	abc	abc
+a(		C	EPAREN
+a(		b	a(	a(
+a\(		-	a(	a(
+a\(		bC	EPAREN
+a\(b		bC	EPAREN
+a(b		C	EPAREN
+a(b		b	a(b	a(b
+# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly)
+a)		-	a)	a)
+)		-	)	)
+# end gagging (in a just world, those *should* give EPAREN)
+a)		b	a)	a)
+a\)		bC	EPAREN
+\)		bC	EPAREN
+a()b		-	ab	ab
+a\(\)b		b	ab	ab
+
+# anchoring and REG_NEWLINE
+^abc$		&	abc	abc
+a^b		-	a^b
+a^b		b	a^b	a^b
+a$b		-	a$b
+a$b		b	a$b	a$b
+^		&	abc	@abc
+$		&	abc	@
+^$		&	""	@
+$^		-	""	@
+\($\)\(^\)	b	""	@
+# stop retching, those are legitimate (although disgusting)
+^^		-	""	@
+$$		-	""	@
+b$		&	abNc
+b$		&n	abNc	b
+^b$		&	aNbNc
+^b$		&n	aNbNc	b
+^$		&n	aNNb	@Nb
+^$		n	abc
+^$		n	abcN	@
+$^		n	aNNb	@Nb
+\($\)\(^\)	bn	aNNb	@Nb
+^^		n^	aNNb	@Nb
+$$		n	aNNb	@NN
+^a		^	a
+a$		$	a
+^a		^n	aNb
+^b		^n	aNb	b
+a$		$n	bNa
+b$		$n	bNa	b
+a*(^b$)c*	-	b	b
+a*\(^b$\)c*	b	b	b
+
+# certain syntax errors and non-errors
+|		C	EMPTY
+|		b	|	|
+*		C	BADRPT
+*		b	*	*
++		C	BADRPT
+?		C	BADRPT
+""		&C	EMPTY
+()		-	abc	@abc
+\(\)		b	abc	@abc
+a||b		C	EMPTY
+|ab		C	EMPTY
+ab|		C	EMPTY
+(|a)b		C	EMPTY
+(a|)b		C	EMPTY
+(*a)		C	BADRPT
+(+a)		C	BADRPT
+(?a)		C	BADRPT
+({1}a)		C	BADRPT
+\(\{1\}a\)	bC	BADRPT
+(a|*b)		C	BADRPT
+(a|+b)		C	BADRPT
+(a|?b)		C	BADRPT
+(a|{1}b)	C	BADRPT
+^*		C	BADRPT
+^*		b	*	*
+^+		C	BADRPT
+^?		C	BADRPT
+^{1}		C	BADRPT
+^\{1\}		bC	BADRPT
+
+# metacharacters, backslashes
+a.c		&	abc	abc
+a[bc]d		&	abd	abd
+a\*c		&	a*c	a*c
+a\\b		&	a\b	a\b
+a\\\*b		&	a\*b	a\*b
+# The following test is wrong.  Using \b in an BRE or ERE is undefined.
+# a\bc		&	abc	abc
+a\		&C	EESCAPE
+a\\bc		&	a\bc	a\bc
+\{		bC	BADRPT
+a\[b		&	a[b	a[b
+a[b		&C	EBRACK
+# trailing $ is a peculiar special case for the BRE code
+a$		&	a	a
+a$		&	a$
+a\$		&	a
+a\$		&	a$	a$
+a\\$		&	a
+a\\$		&	a$
+a\\$		&	a\$
+a\\$		&	a\	a\
+
+# back references, ugh
+a\(b\)\2c	bC	ESUBREG
+a\(b\1\)c	bC	ESUBREG
+a\(b*\)c\1d	b	abbcbbd	abbcbbd	bb
+a\(b*\)c\1d	b	abbcbd
+a\(b*\)c\1d	b	abbcbbbd
+^\(.\)\1	b	abc
+a\([bc]\)\1d	b	abcdabbd	abbd	b
+a\(\([bc]\)\2\)*d	b	abbccd	abbccd
+a\(\([bc]\)\2\)*d	b	abbcbd
+# actually, this next one probably ought to fail, but the spec is unclear
+a\(\(b\)*\2\)*d		b	abbbd	abbbd
+# here is a case that no NFA implementation does right
+\(ab*\)[ab]*\1	b	ababaaa	ababaaa	a
+# check out normal matching in the presence of back refs
+\(a\)\1bcd	b	aabcd	aabcd
+\(a\)\1bc*d	b	aabcd	aabcd
+\(a\)\1bc*d	b	aabd	aabd
+\(a\)\1bc*d	b	aabcccd	aabcccd
+\(a\)\1bc*[ce]d	b	aabcccd	aabcccd
+^\(a\)\1b\(c\)*cd$	b	aabcccd	aabcccd
+
+# ordinary repetitions
+ab*c		&	abc	abc
+ab+c		-	abc	abc
+ab?c		-	abc	abc
+a\(*\)b		b	a*b	a*b
+a\(**\)b	b	ab	ab
+a\(***\)b	bC	BADRPT
+*a		b	*a	*a
+**a		b	a	a
+***a		bC	BADRPT
+
+# the dreaded bounded repetitions
+# The following two tests are not correct:
+#{		&	{	{
+#{abc		&	{abc	{abc
+# '{' is always a special char outside bracket expressions.  So test ony BRE:
+{		b	{	{
+{abc		b	{abc	{abc
+{1		C	BADRPT
+{1}		C	BADRPT
+# Same reason as for the two tests above:
+#a{b		&	a{b	a{b
+a{b		b	a{b	a{b
+a{1}b		-	ab	ab
+a\{1\}b		b	ab	ab
+a{1,}b		-	ab	ab
+a\{1,\}b	b	ab	ab
+a{1,2}b		-	aab	aab
+a\{1,2\}b	b	aab	aab
+a{1		C	EBRACE
+a\{1		bC	EBRACE
+a{1a		C	EBRACE
+a\{1a		bC	EBRACE
+a{1a}		C	BADBR
+a\{1a\}		bC	BADBR
+# These four tests checks for undefined behavior.  Our implementation does
+# something different.
+#a{,2}		-	a{,2}	a{,2}
+#a\{,2\}		bC	BADBR
+#a{,}		-	a{,}	a{,}
+#a\{,\}		bC	BADBR
+a{1,x}		C	BADBR
+a\{1,x\}	bC	BADBR
+a{1,x		C	EBRACE
+a\{1,x		bC	EBRACE
+# These two tests probably fails due to an arbitrary limit on the number of
+# repetitions in the other implementation.
+#a{300}		C	BADBR
+#a\{300\}	bC	BADBR
+a{1,0}		C	BADBR
+a\{1,0\}	bC	BADBR
+ab{0,0}c	-	abcac	ac
+ab\{0,0\}c	b	abcac	ac
+ab{0,1}c	-	abcac	abc
+ab\{0,1\}c	b	abcac	abc
+ab{0,3}c	-	abbcac	abbc
+ab\{0,3\}c	b	abbcac	abbc
+ab{1,1}c	-	acabc	abc
+ab\{1,1\}c	b	acabc	abc
+ab{1,3}c	-	acabc	abc
+ab\{1,3\}c	b	acabc	abc
+ab{2,2}c	-	abcabbc	abbc
+ab\{2,2\}c	b	abcabbc	abbc
+ab{2,4}c	-	abcabbc	abbc
+ab\{2,4\}c	b	abcabbc	abbc
+((a{1,10}){1,10}){1,10}	-	a	a	a,a
+
+# multiple repetitions
+# Wow, there is serious disconnect here.  The ERE grammar is like this:
+# ERE_expression : one_char_or_coll_elem_ERE
+#                | '^'
+#                | '$'
+#                | '(' extended_reg_exp ')'
+#                | ERE_expression ERE_dupl_symbol
+#                ;
+# where ERE_dupl_symbol is any of the repetition methods.  It is clear from
+# this that consecutive repetition is OK.  On top of this, the one test not
+# marked as failing must fail.  For BREs the situation is different, so we
+# use the four tests.
+#a**		&C	BADRPT
+a**		bC	BADRPT
+#a++		C	BADRPT
+#a??		C	BADRPT
+#a*+		C	BADRPT
+#a*?		C	BADRPT
+#a+*		C	BADRPT
+#a+?		C	BADRPT
+#a?*		C	BADRPT
+#a?+		C	BADRPT
+#a{1}{1}		C	BADRPT
+#a*{1}		C	BADRPT
+#a+{1}		C	BADRPT
+#a?{1}		C	BADRPT
+#a{1}*		C	BADRPT
+#a{1}+		C	BADRPT
+#a{1}?		C	BADRPT
+#a*{b}		-	a{b}	a{b}
+a\{1\}\{1\}	bC	BADRPT
+a*\{1\}		bC	BADRPT
+a\{1\}*		bC	BADRPT
+
+# brackets, and numerous perversions thereof
+a[b]c		&	abc	abc
+a[ab]c		&	abc	abc
+a[^ab]c		&	adc	adc
+a[]b]c		&	a]c	a]c
+a[[b]c		&	a[c	a[c
+a[-b]c		&	a-c	a-c
+a[^]b]c		&	adc	adc
+a[^-b]c		&	adc	adc
+a[b-]c		&	a-c	a-c
+a[b		&C	EBRACK
+a[]		&C	EBRACK
+a[1-3]c		&	a2c	a2c
+a[3-1]c		&C	ERANGE
+a[1-3-5]c	&C	ERANGE
+a[[.-.]--]c	&	a-c	a-c
+# I don't thing the error value should be ERANGE since a[1-] would be
+# valid, too.  Expect EBRACK.
+#a[1-		&C	ERANGE
+a[1-		&C	EBRACK
+a[[.		&C	EBRACK
+a[[.x		&C	EBRACK
+a[[.x.		&C	EBRACK
+a[[.x.]		&C	EBRACK
+a[[.x.]]	&	ax	ax
+a[[.x,.]]	&C	ECOLLATE
+# This test is invalid.  "one" is no collating symbol in any standardized
+# locale.
+# a[[.one.]]b	&	a1b	a1b
+a[[.notdef.]]b	&C	ECOLLATE
+a[[.].]]b	&	a]b	a]b
+a[[:alpha:]]c	&	abc	abc
+a[[:notdef:]]c	&C	ECTYPE
+a[[:		&C	EBRACK
+a[[:alpha	&C	EBRACK
+a[[:alpha:]	&C	EBRACK
+a[[:alpha,:]	&C	ECTYPE
+a[[:]:]]b	&C	ECTYPE
+a[[:-:]]b	&C	ECTYPE
+a[[:alph:]]	&C	ECTYPE
+a[[:alphabet:]]	&C	ECTYPE
+[[:alnum:]]+	-	-%@a0X-	a0X
+[[:alpha:]]+	-	-%@aX0-	aX
+[[:blank:]]+	-	aSSTb	SST
+[[:cntrl:]]+	-	aNTb	NT
+[[:digit:]]+	-	a019b	019
+[[:graph:]]+	-	Sa%bS	a%b
+[[:lower:]]+	-	AabC	ab
+[[:print:]]+	-	NaSbN	aSb
+[[:punct:]]+	-	S%-&T	%-&
+[[:space:]]+	-	aSNTb	SNT
+[[:upper:]]+	-	aBCd	BC
+[[:xdigit:]]+	-	p0f3Cq	0f3C
+a[[=b=]]c	&	abc	abc
+a[[=		&C	EBRACK
+a[[=b		&C	EBRACK
+a[[=b=		&C	EBRACK
+a[[=b=]		&C	EBRACK
+a[[=b,=]]	&C	ECOLLATE
+# This test is invalid.  "one" is no collating symbol in any standardized
+# locale.
+#a[[=one=]]b	&	a1b	a1b
+
+# complexities
+a(((b)))c	-	abc	abc
+a(b|(c))d	-	abd	abd
+a(b*|c)d	-	abbd	abbd
+# just gotta have one DFA-buster, of course
+a[ab]{20}	-	aaaaabaaaabaaaabaaaab	aaaaabaaaabaaaabaaaab
+# and an inline expansion in case somebody gets tricky
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab]	-	aaaaabaaaabaaaabaaaab	aaaaabaaaabaaaabaaaab
+# and in case somebody just slips in an NFA...
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night)	-	aaaaabaaaabaaaabaaaabweeknights	aaaaabaaaabaaaabaaaabweeknights
+# fish for anomalies as the number of states passes 32
+12345678901234567890123456789	-	a12345678901234567890123456789b	12345678901234567890123456789
+123456789012345678901234567890	-	a123456789012345678901234567890b	123456789012345678901234567890
+1234567890123456789012345678901	-	a1234567890123456789012345678901b	1234567890123456789012345678901
+12345678901234567890123456789012	-	a12345678901234567890123456789012b	12345678901234567890123456789012
+123456789012345678901234567890123	-	a123456789012345678901234567890123b	123456789012345678901234567890123
+# and one really big one, beyond any plausible word width
+1234567890123456789012345678901234567890123456789012345678901234567890	-	a1234567890123456789012345678901234567890123456789012345678901234567890b	1234567890123456789012345678901234567890123456789012345678901234567890
+# fish for problems as brackets go past 8
+[ab][cd][ef][gh][ij][kl][mn]	-	xacegikmoq	acegikm
+[ab][cd][ef][gh][ij][kl][mn][op]	-	xacegikmoq	acegikmo
+[ab][cd][ef][gh][ij][kl][mn][op][qr]	-	xacegikmoqy	acegikmoq
+[ab][cd][ef][gh][ij][kl][mn][op][q]	-	xacegikmoqy	acegikmoq
+
+# subtleties of matching
+abc		&	xabcy	abc
+a\(b\)?c\1d	b	acd
+aBc		i	Abc	Abc
+a[Bc]*d		i	abBCcd	abBCcd
+0[[:upper:]]1	&i	0a1	0a1
+0[[:lower:]]1	&i	0A1	0A1
+a[^b]c		&i	abc
+a[^b]c		&i	aBc
+a[^b]c		&i	adc	adc
+[a]b[c]		-	abc	abc
+[a]b[a]		-	aba	aba
+[abc]b[abc]	-	abc	abc
+[abc]b[abd]	-	abd	abd
+a(b?c)+d	-	accd	accd
+(wee|week)(knights|night)	-	weeknights	weeknights
+(we|wee|week|frob)(knights|night|day)	-	weeknights	weeknights
+a[bc]d		-	xyzaaabcaababdacd	abd
+a[ab]c		-	aaabc	abc
+abc		s	abc	abc
+()		s	abc	@abc
+a*		&	b	@b
+
+# Let's have some fun -- try to match a C comment.
+# first the obvious, which looks okay at first glance...
+/\*.*\*/	-	/*x*/	/*x*/
+# but...
+/\*.*\*/	-	/*x*/y/*z*/	/*x*/y/*z*/
+# okay, we must not match */ inside; try to do that...
+/\*([^*]|\*[^/])*\*/	-	/*x*/	/*x*/
+/\*([^*]|\*[^/])*\*/	-	/*x*/y/*z*/	/*x*/
+# but...
+/\*([^*]|\*[^/])*\*/	-	/*x**/y/*z*/	/*x**/y/*z*/
+# and a still fancier version, which does it right (I think)...
+/\*([^*]|\*+[^*/])*\*+/	-	/*x*/	/*x*/
+/\*([^*]|\*+[^*/])*\*+/	-	/*x*/y/*z*/	/*x*/
+/\*([^*]|\*+[^*/])*\*+/	-	/*x**/y/*z*/	/*x**/
+/\*([^*]|\*+[^*/])*\*+/	-	/*x****/y/*z*/	/*x****/
+/\*([^*]|\*+[^*/])*\*+/	-	/*x**x*/y/*z*/	/*x**x*/
+/\*([^*]|\*+[^*/])*\*+/	-	/*x***x/y/*z*/	/*x***x/y/*z*/
+
+# subexpressions
+.*		-	abc	abc	-
+a(b)(c)d	-	abcd	abcd	b,c
+a(((b)))c	-	abc	abc	b,b,b
+a(b|(c))d	-	abd	abd	b,-
+a(b*|c|e)d	-	abbd	abbd	bb
+a(b*|c|e)d	-	acd	acd	c
+a(b*|c|e)d	-	ad	ad	@d
+a(b?)c		-	abc	abc	b
+a(b?)c		-	ac	ac	@c
+a(b+)c		-	abc	abc	b
+a(b+)c		-	abbbc	abbbc	bbb
+a(b*)c		-	ac	ac	@c
+(a|ab)(bc([de]+)f|cde)	-	abcdef	abcdef	a,bcdef,de
+# the regression tester only asks for 9 subexpressions
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)k	-	abcdefghijk	abcdefghijk	b,c,d,e,f,g,h,i,j
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l	-	abcdefghijkl	abcdefghijkl	b,c,d,e,f,g,h,i,j,k
+a([bc]?)c	-	abc	abc	b
+a([bc]?)c	-	ac	ac	@c
+a([bc]+)c	-	abc	abc	b
+a([bc]+)c	-	abcc	abcc	bc
+a([bc]+)bc	-	abcbc	abcbc	bc
+a(bb+|b)b	-	abb	abb	b
+a(bbb+|bb+|b)b	-	abb	abb	b
+a(bbb+|bb+|b)b	-	abbb	abbb	bb
+a(bbb+|bb+|b)bb	-	abbb	abbb	b
+(.*).*		-	abcdef	abcdef	abcdef
+(a*)*		-	bc	@b	@b
+
+# do we get the right subexpression when it is used more than once?
+a(b|c)*d	-	ad	ad	-
+a(b|c)*d	-	abcd	abcd	c
+a(b|c)+d	-	abd	abd	b
+a(b|c)+d	-	abcd	abcd	c
+a(b|c?)+d	-	ad	ad	@d
+a(b|c?)+d	-	abcd	abcd	c
+a(b|c){0,0}d	-	ad	ad	-
+a(b|c){0,1}d	-	ad	ad	-
+a(b|c){0,1}d	-	abd	abd	b
+a(b|c){0,2}d	-	ad	ad	-
+a(b|c){0,2}d	-	abcd	abcd	c
+a(b|c){0,}d	-	ad	ad	-
+a(b|c){0,}d	-	abcd	abcd	c
+a(b|c){1,1}d	-	abd	abd	b
+a(b|c){1,1}d	-	acd	acd	c
+a(b|c){1,2}d	-	abd	abd	b
+a(b|c){1,2}d	-	abcd	abcd	c
+a(b|c){1,}d	-	abd	abd	b
+a(b|c){1,}d	-	abcd	abcd	c
+a(b|c){2,2}d	-	acbd	acbd	b
+a(b|c){2,2}d	-	abcd	abcd	c
+a(b|c){2,4}d	-	abcd	abcd	c
+a(b|c){2,4}d	-	abcbd	abcbd	b
+a(b|c){2,4}d	-	abcbcd	abcbcd	c
+a(b|c){2,}d	-	abcd	abcd	c
+a(b|c){2,}d	-	abcbd	abcbd	b
+a(b+|((c)*))+d	-	abd	abd	b,-,-
+a(b+|((c)*))+d	-	abcd	abcd	c,c,c
+
+# check out the STARTEND option
+[abc]		&#	a(b)c	b
+[abc]		&#	a(d)c
+[abc]		&#	a(bc)d	b
+[abc]		&#	a(dc)d	c
+.		&#	a()c
+b.*c		&#	b(bc)c	bc
+b.*		&#	b(bc)c	bc
+.*c		&#	b(bc)c	bc
+
+# plain strings, with the NOSPEC flag
+abc		m	abc	abc
+abc		m	xabcy	abc
+abc		m	xyz
+a*b		m	aba*b	a*b
+a*b		m	ab
+""		mC	EMPTY
+
+# cases involving NULs
+aZb		&	a	a
+aZb		&p	a
+aZb		&p#	(aZb)	aZb
+aZ*b		&p#	(ab)	ab
+a.b		&#	(aZb)	aZb
+a.*		&#	(aZb)c	aZb
+
+# word boundaries (ick)
+[[:<:]]a	&	a	a
+[[:<:]]a	&	ba
+[[:<:]]a	&	-a	a
+a[[:>:]]	&	a	a
+a[[:>:]]	&	ab
+a[[:>:]]	&	a-	a
+[[:<:]]a.c[[:>:]]	&	axcd-dayc-dazce-abc	abc
+[[:<:]]a.c[[:>:]]	&	axcd-dayc-dazce-abc-q	abc
+[[:<:]]a.c[[:>:]]	&	axc-dayc-dazce-abc	axc
+[[:<:]]b.c[[:>:]]	&	a_bxc-byc_d-bzc-q	bzc
+[[:<:]].x..[[:>:]]	&	y_xa_-_xb_y-_xc_-axdc	_xc_
+[[:<:]]a_b[[:>:]]	&	x_a_b
+
+# past problems, and suspected problems
+(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A])	-	A1	A1
+abcdefghijklmnop	i	abcdefghijklmnop	abcdefghijklmnop
+abcdefghijklmnopqrstuv	i	abcdefghijklmnopqrstuv	abcdefghijklmnopqrstuv
+(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN])	-	CC11	CC11
+CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a	-	CC11	CC11
+Char \([a-z0-9_]*\)\[.*	b	Char xyz[k	Char xyz[k	xyz
+a?b	-	ab	ab
+-\{0,1\}[0-9]*$	b	-5	-5
+a*a*a*a*a*a*a*	&	aaaaaa	aaaaaa
+(\b){0}	-	x	@x	-
+\(\b\)\{0,0\}	b	abc	@abc	-
+a(\b){0}c	-	ac	ac	-
+a(.*)b(\1){0}c	-	abc	abc	@bc,-
+a(.*)b(\1){0}c	-	axbc	axbc	x,-
+
+a\(\(b*\)\)c\1d	b	abbcbbd	abbcbbd	bb,bb
+a\(\([bc]\)\)\2d	b	abcdabbd	abbd	b,b
+a\(\(\(\([bc]\)\)\3\)\)*d	b	abbccd	abbccd	cc,cc,c,c
+a(b)(c)d	-	abcd	abcd	b,c
+a(((b)))c	-	abc	abc	b,b,b
+a(((b|(((c))))))d	-	abd	abd	b,b,b,-,-,-
+a(((b*|c|e)))d	-	abbd	abbd	bb,bb,bb
+a((b|c)){0,0}d	-	ad	ad	-,-
+a((b|c)){0,1}d	-	abd	abd	b,b
+a((b|c)){0,2}d	-	abcd	abcd	c,c
+a((b+|((c)*)))+d	-	abd	abd	b,b,-,-
+a((b+|((c)*)))+d	-	abcd	abcd	c,c,c,c
+(((\b))){0}	-	x	@x	-,-,-
+a(((.*)))b((\2)){0}c	-	abc	abc	@bc,@bc,@bc,-,-
+a(((.*)))b((\1)){0}c	-	axbc	axbc	x,x,x,-,-
+
+\b	&	SaT	@aT
+\b	&	aT	@aT
+a.*\b	&	abT	ab
+\b	&	STSS
+\B	&	abc	@bc
+\B	&	aSbTc
+\B	&	SaT	@SaT
+\B	&	aSTSb	@TSb
Index: /tags/kBuild-0.1.4/src/sed/testsuite/allsub.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/allsub.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/allsub.good	(revision 1780)
@@ -0,0 +1,1 @@
+bar bar fo oo f oo bar bar bar bar bar bar bar bar bar bar bar bar bar
Index: /tags/kBuild-0.1.4/src/sed/testsuite/allsub.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/allsub.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/allsub.inp	(revision 1780)
@@ -0,0 +1,1 @@
+foo foo fo oo f oo foo foo foo foo foo foo foo foo foo foo foo foo foo
Index: /tags/kBuild-0.1.4/src/sed/testsuite/allsub.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/allsub.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/allsub.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/foo/bar/g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/appquit.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/appquit.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/appquit.good	(revision 1780)
@@ -0,0 +1,2 @@
+doh
+ok
Index: /tags/kBuild-0.1.4/src/sed/testsuite/appquit.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/appquit.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/appquit.inp	(revision 1780)
@@ -0,0 +1,1 @@
+doh
Index: /tags/kBuild-0.1.4/src/sed/testsuite/appquit.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/appquit.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/appquit.sed	(revision 1780)
@@ -0,0 +1,4 @@
+# Test appending quit
+a\
+ok
+q
Index: /tags/kBuild-0.1.4/src/sed/testsuite/binary.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/binary.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/binary.good	(revision 1780)
@@ -0,0 +1,8 @@
+192
+168
+1
+0
+192
+168
+1
+255
Index: /tags/kBuild-0.1.4/src/sed/testsuite/binary.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/binary.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/binary.inp	(revision 1780)
@@ -0,0 +1,4 @@
+192.168.1.2 br b8<r b16<r b24< R|R|R| D
+255.255.255.0 br b8<r b16<r b24< R|R|R| D~r
+& DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP
+| DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP
Index: /tags/kBuild-0.1.4/src/sed/testsuite/binary.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/binary.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/binary.sed	(revision 1780)
@@ -0,0 +1,189 @@
+# A kind of clone of dc geared towards binary operations.
+# by Paolo Bonzini
+#
+# commands available:
+#   conversion commands
+#     b      convert decimal to binary
+#     d      convert binary to decimal
+#
+#   arithmetic commands
+#     <      shift left binary by decimal number of bits (11 3< gives 11000)
+#     >      shift right binary by decimal number of bits (1011 2> gives 10)
+#     &      binary AND (between two binary operands)
+#     |      binary OR (between two binary operands)
+#     ^      binary XOR (between two binary operands)
+#     ~      binary NOT (between one binary operand)
+#
+#   stack manipulation commands
+#     c      clear stack
+#     P      pop stack top
+#     D      duplicate stack top
+#     x      exchange top two elements
+#     r      rotate stack counter-clockwise (second element becomes first)
+#     R      rotate stack clockwise (last element becomes first)
+#
+#   other commands
+#     l      print stack (stack top is first)
+#     p      print stack top
+#     q      quit, print stack top if any (cq is quiet quit)
+#
+# The only shortcoming is that you'd better not attempt conversions of
+# values above 1000 or so.
+#
+# This version does everything in pattern space (a la dc.sed).
+# --------------------------------------------------------------------------
+# This was actually used in a one-disk distribution of Linux to compute
+# netmasks as follows (1 parameter => compute netmask e.g. 24 becomes
+# 255.255.255.0; 2 parameters => given host address and netmask compute
+# network and broadcast addresses):
+#
+# if [ $# = 1 ]; then 
+#   OUTPUT='$1.$2.$3.$4'
+#   set 255.255.255.255 $1
+# else
+#   OUTPUT='$1.$2.$3.$4 $5.$6.$7.$8'
+# fi
+# 
+# if [ `expr $2 : ".*\\."` -gt 0 ]; then
+#   MASK="$2 br b8<r b16<r b24< R|R|R|"
+# else
+#   MASK="$2b 31b ^d D
+#         11111111111111111111111111111111 x>1> x<1<"
+# fi
+# 
+# set `echo "$1 br b8<r b16<r b24< R|R|R| D    # Load address
+#            $MASK D ~r                        # Load mask
+# 
+#            & DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP
+#            | DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP
+#       " | sed -f binary.sed`
+#
+# eval echo $OUTPUT
+# --------------------------------------------------------------------------
+
+
+1s/^/%%/
+
+:cmd
+s/\(.*%%\) *\([0-9][0-9]*\)/\2\
+\1/
+tcmd
+s/%% *#.*/%%/
+/%%$/ {
+  $b quit
+  N
+}
+
+/^.*%%D/ s/^[^\n]*\n/&&/
+/^.*%%P/ s/^[^\n]*\n//
+/^.*%%x/ s/^\([^\n]*\n\)\([^\n]*\n\)/\2\1/
+/^.*%%r/ s/^\([^\n]*\n\)\([^%]*\)/\2\1/
+/^.*%%R/ s/^\([^%]*\n\)\([^\n]*\n\)/\2\1/
+/^.*%%c/ s/^.*%%/%%/
+/^.*%%p/ P
+
+/^.*%%l/ {
+  h
+  s/.%%.*//
+  p
+  g
+}
+
+/^.*%%q/ {
+  :quit
+  /^%%/!P
+  d
+}
+
+/^.*%%b/ {
+  # Decimal to binary via analog form
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :d2bloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t d2bloop1
+  s/-;9876543210aaaaaaaaa/;a01!/
+  :d2bloop2
+  s/\(a*\)\1\(a\{0,1\}\)\(;\2.\(.\)[^!]*!\)/\1\3\4/
+  /^a/b d2bloop2
+  s/[^!]*!//
+}
+
+/^.*%%d/ {
+  # Binary to decimal via analog form
+  s/^\([^\n]*\)/-&;10a/
+  :b2dloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\(a*\)\)/\1\1\4-\3/
+  t b2dloop1
+  s/-;10a/;aaaaaaaaa0123456789!/
+  :b2dloop2
+  s/\(a*\)\1\1\1\1\1\1\1\1\1\(a\{0,9\}\)\(;\2.\{9\}\(.\)[^!]*!\)/\1\3\4/
+  /^a/b b2dloop2
+  s/[^!]*!//
+}
+
+/^.*%%&/ {
+  # Binary AND
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-111 01000/
+  :andloop
+  s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/
+  t andloop
+  s/^0*\([^-]*\)-[^\n]*/\1/
+  s/^\n/0&/
+}
+
+/^.*%%^/ {
+  # Binary XOR
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 01101/
+  b orloop
+}
+
+/^.*%%|/ {
+  # Binary OR
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 10111/
+  :orloop
+  s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/
+  t orloop
+  s/\([^-]*\)-\([^-]*\)-\([^-]*\)-[^\n]*/\2\3\1/
+}
+
+/^.*%%~/ {
+  # Binary NOT
+  s/^\(.\)\([^\n]*\n\)/\1-010-\2/
+  :notloop
+  s/\(.\)-0\{0,1\}\1\(.\)0\{0,1\}-\([01\n]\)/\2\3-010-/
+  t notloop
+
+  # If result is 00001..., \3 does not match (it looks for -10) and we just
+  # remove the table and leading zeros.  If result is 0000...0, \3 matches
+  # (it looks for -0), \4 is a zero and we leave a lone zero as top of the
+  # stack.
+
+  s/0*\(1\{0,1\}\)\([^-]*\)-\(\1\(0\)\)\{0,1\}[^-]*-/\4\1\2/
+}
+
+/^.*%%</ {
+  # Left shift, convert to analog and add a binary digit for each analog digit
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :lshloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t lshloop1
+  s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/
+  s/a/0/g
+}
+
+/^.*%%>/ {
+  # Right shift, convert to analog and remove a binary digit for each analog digit
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :rshloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t rshloop1
+  s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/
+  :rshloop2
+  s/.a//
+  s/^aa*/0/
+  /a\n/b rshloop2
+}
+
+
+s/%%./%%/
+tcmd
Index: /tags/kBuild-0.1.4/src/sed/testsuite/binary2.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/binary2.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/binary2.sed	(revision 1780)
@@ -0,0 +1,226 @@
+# A kind of clone of dc geared towards binary operations.
+# by Paolo Bonzini
+#
+# commands available:
+#   conversion commands
+#     b      convert decimal to binary
+#     d      convert binary to decimal
+#
+#   arithmetic commands
+#     <      shift left binary by decimal number of bits (11 3< gives 11000)
+#     >      shift right binary by decimal number of bits (1011 2> gives 10)
+#     &      binary AND (between two binary operands)
+#     |      binary OR (between two binary operands)
+#     ^      binary XOR (between two binary operands)
+#     ~      binary NOT (between one binary operand)
+#
+#   stack manipulation commands
+#     c      clear stack
+#     P      pop stack top
+#     D      duplicate stack top
+#     x      exchange top two elements
+#     r      rotate stack counter-clockwise (second element becomes first)
+#     R      rotate stack clockwise (last element becomes first)
+#
+#   other commands
+#     l      print stack (stack top is first)
+#     p      print stack top
+#     q      quit, print stack top if any (cq is quiet quit)
+#
+# The only shortcoming is that you'd better not attempt conversions of
+# values above 1000 or so.
+#
+# This version keeps the stack in hold space and the command in pattern
+# space; it is the fastest one (though the gap with binary3.sed is small).
+# --------------------------------------------------------------------------
+# This was actually used in a one-disk distribution of Linux to compute
+# netmasks as follows (1 parameter => compute netmask e.g. 24 becomes
+# 255.255.255.0; 2 parameters => given host address and netmask compute
+# network and broadcast addresses):
+#
+# if [ $# = 1 ]; then 
+#   OUTPUT='$1.$2.$3.$4'
+#   set 255.255.255.255 $1
+# else
+#   OUTPUT='$1.$2.$3.$4 $5.$6.$7.$8'
+# fi
+# 
+# if [ `expr $2 : ".*\\."` -gt 0 ]; then
+#   MASK="$2 br b8<r b16<r b24< R|R|R|"
+# else
+#   MASK="$2b 31b ^d D
+#         11111111111111111111111111111111 x>1> x<1<"
+# fi
+# 
+# set `echo "$1 br b8<r b16<r b24< R|R|R| D    # Load address
+#            $MASK D ~r                        # Load mask
+# 
+#            & DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP
+#            | DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP
+#       " | sed -f binary.sed`
+#
+# eval echo $OUTPUT
+# --------------------------------------------------------------------------
+
+:cmd
+s/^[\n\t ]*//
+s/^#.*//
+/^$/ {
+  $b quit
+  N
+  t cmd
+}
+/^[0-9][0-9]*/ {
+  G
+  h
+  s/^[0-9][0-9]* *\([^\n]*\).*/\1/
+  x
+  s/^\([0-9][0-9]*\)[^\n]*/\1/
+  x
+  t cmd
+}
+
+/^[^DPxrRcplqbd&|^~<>]/b bad
+
+/^D/ {
+  x
+  s/^[^\n]*\n/&&/
+}
+/^P/ {
+  x
+  s/^[^\n]*\n//
+}
+/^x/ {
+  x
+  s/^\([^\n]*\n\)\([^\n]*\n\)/\2\1/
+}
+/^r/ {
+  x
+  s/^\([^\n]*\n\)\(.*\)/\2\1/
+}
+/^R/ {
+  x
+  s/^\(.*\n\)\([^\n]*\n\)/\2\1/
+}
+/^c/ {
+  x
+  s/.*//
+}
+/^p/ {
+  x
+  P
+}
+
+/^l/ {
+  x
+  p
+}
+
+/^q/ {
+  :quit
+  x
+  /./P
+  d
+}
+
+/^b/ {
+  # Decimal to binary via analog form
+  x
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :d2bloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t d2bloop1
+  s/-;9876543210aaaaaaaaa/;a01!/
+  :d2bloop2
+  s/\(a*\)\1\(a\{0,1\}\)\(;\2.\(.\)[^!]*!\)/\1\3\4/
+  /^a/b d2bloop2
+  s/[^!]*!//
+}
+
+/^d/ {
+  # Binary to decimal via analog form
+  x
+  s/^\([^\n]*\)/-&;10a/
+  :b2dloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\(a*\)\)/\1\1\4-\3/
+  t b2dloop1
+  s/-;10a/;aaaaaaaaa0123456789!/
+  :b2dloop2
+  s/\(a*\)\1\1\1\1\1\1\1\1\1\(a\{0,9\}\)\(;\2.\{9\}\(.\)[^!]*!\)/\1\3\4/
+  /^a/b b2dloop2
+  s/[^!]*!//
+}
+
+/^&/ {
+  # Binary AND
+  x
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-111 01000/
+  :andloop
+  s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/
+  t andloop
+  s/^0*\([^-]*\)-[^\n]*/\1/
+  s/^\n/0&/
+}
+
+/^\^/ {
+  # Binary XOR
+  x
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 01101/
+  b orloop
+}
+
+/^|/ {
+  # Binary OR
+  x
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 10111/
+  :orloop
+  s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/
+  t orloop
+  s/\([^-]*\)-\([^-]*\)-\([^-]*\)-[^\n]*/\2\3\1/
+}
+
+/^~/ {
+  # Binary NOT
+  x
+  s/^\(.\)\([^\n]*\n\)/\1-010-\2/
+  :notloop
+  s/\(.\)-0\{0,1\}\1\(.\)0\{0,1\}-\([01\n]\)/\2\3-010-/
+  t notloop
+
+  # If result is 00001..., \3 does not match (it looks for -10) and we just
+  # remove the table and leading zeros.  If result is 0000...0, \3 matches
+  # (it looks for -0), \4 is a zero and we leave a lone zero as top of the
+  # stack.
+
+  s/0*\(1\{0,1\}\)\([^-]*\)-\(\1\(0\)\)\{0,1\}[^-]*-/\4\1\2/
+}
+
+/^</ {
+  # Left shift, convert to analog and add a binary digit for each analog digit
+  x
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :lshloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t lshloop1
+  s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/
+  s/a/0/g
+}
+
+/^>/ {
+  # Right shift, convert to analog and remove a binary digit for each analog digit
+  x
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :rshloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t rshloop1
+  s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/
+  :rshloop2
+  s/.a//
+  s/^aa*/0/
+  /a\n/b rshloop2
+}
+
+x
+:bad
+s/^.//
+tcmd
Index: /tags/kBuild-0.1.4/src/sed/testsuite/binary3.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/binary3.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/binary3.sed	(revision 1780)
@@ -0,0 +1,204 @@
+# A kind of clone of dc geared towards binary operations.
+# by Paolo Bonzini
+#
+# commands available:
+#   conversion commands
+#     b      convert decimal to binary
+#     d      convert binary to decimal
+#
+#   arithmetic commands
+#     <      shift left binary by decimal number of bits (11 3< gives 11000)
+#     >      shift right binary by decimal number of bits (1011 2> gives 10)
+#     &      binary AND (between two binary operands)
+#     |      binary OR (between two binary operands)
+#     ^      binary XOR (between two binary operands)
+#     ~      binary NOT (between one binary operand)
+#
+#   stack manipulation commands
+#     c      clear stack
+#     P      pop stack top
+#     D      duplicate stack top
+#     x      exchange top two elements
+#     r      rotate stack counter-clockwise (second element becomes first)
+#     R      rotate stack clockwise (last element becomes first)
+#
+#   other commands
+#     l      print stack (stack top is first)
+#     p      print stack top
+#     q      quit, print stack top if any (cq is quiet quit)
+#
+# The only shortcoming is that you'd better not attempt conversions of
+# values above 1000 or so.
+#
+# This version keeps the stack and the current command in hold space and
+# the commands in pattern space; it is just a bit slower than binary2.sed
+# but more size optimized for broken seds which have a 199-command limit
+# (though binary2.sed does not have this much).
+#
+# --------------------------------------------------------------------------
+# This was actually used in a one-disk distribution of Linux to compute
+# netmasks as follows (1 parameter => compute netmask e.g. 24 becomes
+# 255.255.255.0; 2 parameters => given host address and netmask compute
+# network and broadcast addresses):
+#
+# if [ $# = 1 ]; then 
+#   OUTPUT='$1.$2.$3.$4'
+#   set 255.255.255.255 $1
+# else
+#   OUTPUT='$1.$2.$3.$4 $5.$6.$7.$8'
+# fi
+# 
+# if [ `expr $2 : ".*\\."` -gt 0 ]; then
+#   MASK="$2 br b8<r b16<r b24< R|R|R|"
+# else
+#   MASK="$2b 31b ^d D
+#         11111111111111111111111111111111 x>1> x<1<"
+# fi
+# 
+# set `echo "$1 br b8<r b16<r b24< R|R|R| D    # Load address
+#            $MASK D ~r                        # Load mask
+# 
+#            & DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP
+#            | DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP
+#       " | sed -f binary.sed`
+#
+# eval echo $OUTPUT
+# --------------------------------------------------------------------------
+
+:cmd
+s/^[\n\t ]*//
+s/^#.*//
+/^$/ {
+  $b quit
+  N
+  t cmd
+}
+/^[0-9][0-9]*/ {
+  G
+  h
+  s/^[0-9][0-9]* *\([^\n]*\).*/\1/
+  x
+  s/^\([0-9][0-9]*\)[^\n]*/\1/
+  x
+  t cmd
+}
+
+/^[^DPxrRcplqbd&|^~<>]/bbad
+
+H
+x
+s/\(\n[^\n]\)[^\n]*$/\1/
+
+/D$/ s/^[^\n]*\n/&&/
+/P$/ s/^[^\n]*\n//
+/x$/ s/^\([^\n]*\n\)\([^\n]*\n\)/\2\1/
+/r$/ s/^\([^\n]*\n\)\(.*\)\(..\)/\2\1\3/
+/R$/ s/^\(.*\n\)\([^\n]*\n\)\(..\)/\2\1\3/
+/c$/ s/.*//
+/p$/ P
+/l$/ {
+  s/...$//
+  p
+  t cmd
+}
+
+/q$/ {
+  :quit
+  /.../P
+  d
+}
+
+/b$/ {
+  # Decimal to binary via analog form
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :d2bloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t d2bloop1
+  s/-;9876543210aaaaaaaaa/;a01!/
+  :d2bloop2
+  s/\(a*\)\1\(a\{0,1\}\)\(;\2.\(.\)[^!]*!\)/\1\3\4/
+  /^a/b d2bloop2
+  s/[^!]*!//
+}
+
+/d$/ {
+  # Binary to decimal via analog form
+  s/^\([^\n]*\)/-&;10a/
+  :b2dloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\(a*\)\)/\1\1\4-\3/
+  t b2dloop1
+  s/-;10a/;aaaaaaaaa0123456789!/
+  :b2dloop2
+  s/\(a*\)\1\1\1\1\1\1\1\1\1\(a\{0,9\}\)\(;\2.\{9\}\(.\)[^!]*!\)/\1\3\4/
+  /^a/b b2dloop2
+  s/[^!]*!//
+}
+
+/&$/ {
+  # Binary AND
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-111 01000/
+  :andloop
+  s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/
+  t andloop
+  s/^0*\([^-]*\)-[^\n]*/\1/
+  s/^\n/0&/
+}
+
+/\^$/ {
+  # Binary XOR
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 01101/
+  b orloop
+}
+
+/|$/ {
+  # Binary OR
+  s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 10111/
+  :orloop
+  s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/
+  t orloop
+  s/\([^-]*\)-\([^-]*\)-\([^-]*\)-[^\n]*/\2\3\1/
+}
+
+/~$/ {
+  # Binary NOT
+  s/^\(.\)\([^\n]*\n\)/\1-010-\2/
+  :notloop
+  s/\(.\)-0\{0,1\}\1\(.\)0\{0,1\}-\([01\n]\)/\2\3-010-/
+  t notloop
+
+  # If result is 00001..., \3 does not match (it looks for -10) and we just
+  # remove the table and leading zeros.  If result is 0000...0, \3 matches
+  # (it looks for -0), \4 is a zero and we leave a lone zero as top of the
+  # stack.
+
+  s/0*\(1\{0,1\}\)\([^-]*\)-\(\1\(0\)\)\{0,1\}[^-]*-/\4\1\2/
+}
+
+/<$/ {
+  # Left shift, convert to analog and add a binary digit for each analog digit
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :lshloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t lshloop1
+  s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/
+  s/a/0/g
+}
+
+/>$/ {
+  # Right shift, convert to analog and remove a binary digit for each analog digit
+  s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/
+  :rshloop1
+  s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/
+  t rshloop1
+  s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/
+  :rshloop2
+  s/.a//
+  s/^aa*/0/
+  /a\n/b rshloop2
+}
+
+s/..$//
+x
+:bad
+s/^.//
+tcmd
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.good	(revision 1780)
@@ -0,0 +1,2 @@
+a\
+
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.inp	(revision 1780)
@@ -0,0 +1,1 @@
+a
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bkslashes.sed	(revision 1780)
@@ -0,0 +1,3 @@
+# bug in sed 4.0b
+s/$/\\\
+/
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bsd.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bsd.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bsd.good	(revision 1780)
@@ -0,0 +1,1737 @@
+============
+Test 1.1:101
+============
+Testing argument parsing
+First type
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
+
+============
+Test 1.2:102
+============
+e1_l1_1
+e1_l1_2
+e1_l1_3
+e1_l1_4
+e1_l1_5
+e1_l1_6
+e1_l1_7
+e1_l1_8
+e1_l1_9
+e1_l1_10
+e1_l1_11
+e1_l1_12
+e1_l1_13
+e1_l1_14
+
+============
+Test 1.3:103
+============
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
+
+============
+Test 1.4:104
+============
+e1_l1_1
+e1_l1_2
+e1_l1_3
+e1_l1_4
+e1_l1_5
+e1_l1_6
+e1_l1_7
+e1_l1_8
+e1_l1_9
+e1_l1_10
+e1_l1_11
+e1_l1_12
+e1_l1_13
+e1_l1_14
+Second type
+
+==============
+Test 1.4.1:105
+==============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 1.5:106
+============
+s1_l1_1
+s1_l1_1
+s1_l1_2
+s1_l1_2
+s1_l1_3
+s1_l1_3
+s1_l1_4
+s1_l1_4
+s1_l1_5
+s1_l1_5
+s1_l1_6
+s1_l1_6
+s1_l1_7
+s1_l1_7
+s1_l1_8
+s1_l1_8
+s1_l1_9
+s1_l1_9
+s1_l1_10
+s1_l1_10
+s1_l1_11
+s1_l1_11
+s1_l1_12
+s1_l1_12
+s1_l1_13
+s1_l1_13
+s1_l1_14
+s1_l1_14
+
+============
+Test 1.6:107
+============
+s1_l1_1
+s1_l1_1
+s1_l1_2
+s1_l1_2
+s1_l1_3
+s1_l1_3
+s1_l1_4
+s1_l1_4
+s1_l1_5
+s1_l1_5
+s1_l1_6
+s1_l1_6
+s1_l1_7
+s1_l1_7
+s1_l1_8
+s1_l1_8
+s1_l1_9
+s1_l1_9
+s1_l1_10
+s1_l1_10
+s1_l1_11
+s1_l1_11
+s1_l1_12
+s1_l1_12
+s1_l1_13
+s1_l1_13
+s1_l1_14
+s1_l1_14
+
+============
+Test 1.7:108
+============
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
+
+============
+Test 1.8:109
+============
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
+
+============
+Test 1.9:110
+============
+s1_l1_1
+s1_l1_2
+s1_l1_3
+s1_l1_4
+s1_l1_5
+s1_l1_6
+s1_l1_7
+s1_l1_8
+s1_l1_9
+s1_l1_10
+s1_l1_11
+s1_l1_12
+s1_l1_13
+s1_l1_14
+
+=============
+Test 1.10:111
+=============
+s1_l1_1
+s1_l1_2
+s1_l1_3
+s1_l1_4
+s1_l1_5
+s1_l1_6
+s1_l1_7
+s1_l1_8
+s1_l1_9
+s1_l1_10
+s1_l1_11
+s1_l1_12
+s1_l1_13
+s1_l1_14
+
+=============
+Test 1.11:112
+=============
+e1_l1_1
+e1_l1_2
+e1_l1_3
+e1_l1_4
+e1_l1_5
+e1_l1_6
+e1_l1_7
+e1_l1_8
+e1_l1_9
+e1_l1_10
+e1_l1_11
+e1_l1_12
+e1_l1_13
+e1_l1_14
+
+=============
+Test 1.12:113
+=============
+e1_l1_1
+e1_l1_2
+e1_l1_3
+e1_l1_4
+e1_l1_5
+e1_l1_6
+e1_l1_7
+e1_l1_8
+e1_l1_9
+e1_l1_10
+e1_l1_11
+e1_l1_12
+e1_l1_13
+e1_l1_14
+
+=============
+Test 1.13:114
+=============
+e1_l1_1
+e2_e1_l1_1
+e2_e1_l1_1
+e1_l1_2
+e2_e1_l1_2
+e2_e1_l1_2
+e1_l1_3
+e2_e1_l1_3
+e2_e1_l1_3
+e1_l1_4
+e2_e1_l1_4
+e2_e1_l1_4
+e1_l1_5
+e2_e1_l1_5
+e2_e1_l1_5
+e1_l1_6
+e2_e1_l1_6
+e2_e1_l1_6
+e1_l1_7
+e2_e1_l1_7
+e2_e1_l1_7
+e1_l1_8
+e2_e1_l1_8
+e2_e1_l1_8
+e1_l1_9
+e2_e1_l1_9
+e2_e1_l1_9
+e1_l1_10
+e2_e1_l1_10
+e2_e1_l1_10
+e1_l1_11
+e2_e1_l1_11
+e2_e1_l1_11
+e1_l1_12
+e2_e1_l1_12
+e2_e1_l1_12
+e1_l1_13
+e2_e1_l1_13
+e2_e1_l1_13
+e1_l1_14
+e2_e1_l1_14
+e2_e1_l1_14
+
+=============
+Test 1.14:115
+=============
+s1_l1_1
+s2_s1_l1_1
+s2_s1_l1_1
+s1_l1_2
+s2_s1_l1_2
+s2_s1_l1_2
+s1_l1_3
+s2_s1_l1_3
+s2_s1_l1_3
+s1_l1_4
+s2_s1_l1_4
+s2_s1_l1_4
+s1_l1_5
+s2_s1_l1_5
+s2_s1_l1_5
+s1_l1_6
+s2_s1_l1_6
+s2_s1_l1_6
+s1_l1_7
+s2_s1_l1_7
+s2_s1_l1_7
+s1_l1_8
+s2_s1_l1_8
+s2_s1_l1_8
+s1_l1_9
+s2_s1_l1_9
+s2_s1_l1_9
+s1_l1_10
+s2_s1_l1_10
+s2_s1_l1_10
+s1_l1_11
+s2_s1_l1_11
+s2_s1_l1_11
+s1_l1_12
+s2_s1_l1_12
+s2_s1_l1_12
+s1_l1_13
+s2_s1_l1_13
+s2_s1_l1_13
+s1_l1_14
+s2_s1_l1_14
+s2_s1_l1_14
+
+=============
+Test 1.15:116
+=============
+e1_l1_1
+s1_e1_l1_1
+s1_e1_l1_1
+e1_l1_2
+s1_e1_l1_2
+s1_e1_l1_2
+e1_l1_3
+s1_e1_l1_3
+s1_e1_l1_3
+e1_l1_4
+s1_e1_l1_4
+s1_e1_l1_4
+e1_l1_5
+s1_e1_l1_5
+s1_e1_l1_5
+e1_l1_6
+s1_e1_l1_6
+s1_e1_l1_6
+e1_l1_7
+s1_e1_l1_7
+s1_e1_l1_7
+e1_l1_8
+s1_e1_l1_8
+s1_e1_l1_8
+e1_l1_9
+s1_e1_l1_9
+s1_e1_l1_9
+e1_l1_10
+s1_e1_l1_10
+s1_e1_l1_10
+e1_l1_11
+s1_e1_l1_11
+s1_e1_l1_11
+e1_l1_12
+s1_e1_l1_12
+s1_e1_l1_12
+e1_l1_13
+s1_e1_l1_13
+s1_e1_l1_13
+e1_l1_14
+s1_e1_l1_14
+s1_e1_l1_14
+
+=============
+Test 1.16:117
+=============
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
+
+=============
+Test 1.17:118
+=============
+l1_1
+l1_1
+l1_2
+l1_2
+l1_3
+l1_3
+l1_4
+l1_4
+l1_5
+l1_5
+l1_6
+l1_6
+l1_7
+l1_7
+l1_8
+l1_8
+l1_9
+l1_9
+l1_10
+l1_10
+l1_11
+l1_11
+l1_12
+l1_12
+l1_13
+l1_13
+l1_14
+l1_14
+
+=============
+Test 1.18:119
+=============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+Testing address ranges
+
+============
+Test 2.1:120
+============
+l1_4
+
+============
+Test 2.2:121
+============
+l2_6
+
+============
+Test 2.3:122
+============
+l1_14
+
+============
+Test 2.4:123
+============
+l2_9
+
+============
+Test 2.5:124
+============
+
+============
+Test 2.6:125
+============
+l2_9
+
+============
+Test 2.7:126
+============
+
+============
+Test 2.9:127
+============
+l1_7
+
+=============
+Test 2.10:128
+=============
+l1_7
+
+=============
+Test 2.11:129
+=============
+l1_7
+
+=============
+Test 2.12:130
+=============
+l1_1
+l1_2
+l1_3
+l1_4
+
+=============
+Test 2.13:131
+=============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
+
+=============
+Test 2.14:132
+=============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
+
+=============
+Test 2.15:133
+=============
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
+
+=============
+Test 2.16:134
+=============
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+
+=============
+Test 2.17:135
+=============
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
+
+=============
+Test 2.18:136
+=============
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
+
+=============
+Test 2.19:137
+=============
+l1_12
+
+=============
+Test 2.20:138
+=============
+l1_7
+Brace and other grouping
+
+============
+Test 3.1:139
+============
+l1_1
+l1_2
+l1_3
+^l1T4$
+^l1T5$
+^l1T6$
+^l1T7$
+^l1T8$
+^l1T9$
+^l1T10$
+^l1T11$
+^l1T12$
+l1_13
+l1_14
+
+============
+Test 3.2:140
+============
+l1_1
+l1_2
+l1_3
+^l1_4
+^l1_5
+^l1_6$
+^l1_7$
+^l1T8$
+^l1_9$
+^l1_10$
+^l1_11
+^l1_12
+l1_13
+l1_14
+
+============
+Test 3.3:141
+============
+^l1T1$
+^l1T2$
+^l1T3$
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+^l1T13$
+^l1T14$
+
+============
+Test 3.4:142
+============
+^l1_1
+^l1_2
+^l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+^l1_13
+^l1_14
+Testing a c d and i commands
+
+============
+Test 4.1:143
+============
+before_il1_1
+after_ibefore_il1_1
+before_il1_2
+after_ibefore_il1_2
+before_il1_3
+after_ibefore_il1_3
+before_il1_4
+after_ibefore_il1_4
+before_il1_5
+after_ibefore_il1_5
+before_il1_6
+after_ibefore_il1_6
+before_il1_7
+after_ibefore_il1_7
+before_il1_8
+after_ibefore_il1_8
+before_il1_9
+after_ibefore_il1_9
+before_il1_10
+after_ibefore_il1_10
+before_il1_11
+after_ibefore_il1_11
+before_il1_12
+after_ibefore_il1_12
+before_il1_13
+after_ibefore_il1_13
+before_il1_14
+after_ibefore_il1_14
+before_il2_1
+after_ibefore_il2_1
+before_il2_2
+after_ibefore_il2_2
+before_il2_3
+after_ibefore_il2_3
+before_il2_4
+after_ibefore_il2_4
+before_il2_5
+after_ibefore_il2_5
+before_il2_6
+inserted
+after_ibefore_il2_6
+before_il2_7
+after_ibefore_il2_7
+before_il2_8
+after_ibefore_il2_8
+before_il2_9
+after_ibefore_il2_9
+
+============
+Test 4.2:144
+============
+before_al1_1
+after_abefore_al1_1
+before_al1_2
+after_abefore_al1_2
+before_al1_3
+after_abefore_al1_3
+before_al1_4
+after_abefore_al1_4
+before_a5-12l1_5
+after_abefore_a5-12l1_5
+appended
+before_a5-12l1_6
+after_abefore_a5-12l1_6
+appended
+before_a5-12l1_7
+after_abefore_a5-12l1_7
+appended
+before_a5-12l1_8
+after_abefore_a5-12l1_8
+appended
+before_a5-12l1_9
+after_abefore_a5-12l1_9
+appended
+before_a5-12l1_10
+after_abefore_a5-12l1_10
+appended
+before_a5-12l1_11
+after_abefore_a5-12l1_11
+appended
+before_a5-12l1_12
+after_abefore_a5-12l1_12
+appended
+before_al1_13
+after_abefore_al1_13
+before_al1_14
+after_abefore_al1_14
+before_al2_1
+after_abefore_al2_1
+before_al2_2
+after_abefore_al2_2
+before_al2_3
+after_abefore_al2_3
+before_al2_4
+after_abefore_al2_4
+before_al2_5
+after_abefore_al2_5
+before_al2_6
+after_abefore_al2_6
+before_al2_7
+after_abefore_al2_7
+before_al2_8
+after_abefore_al2_8
+before_al2_9
+after_abefore_al2_9
+
+============
+Test 4.3:145
+============
+^l1_1
+^l1_1$
+appended
+^l1_2
+^l1_2$
+appended
+^l1_3
+^l1_3$
+appended
+^l1_4
+^l1_4$
+appended
+^l1_5
+^l1_5$
+appended
+^l1_6
+^l1_6$
+appended
+^l1_7
+^l1_7$
+appended
+^l1_8
+appended
+^l1_8
+l1_9$
+^l1_10
+appended
+^l1_10
+l1_11$
+^l1_12
+^l1_12$
+appended
+^l1_13
+^l1_13$
+appended
+^l1_14
+^l1_14$
+appended
+^l2_1
+^l2_1$
+^l2_2
+^l2_2$
+^l2_3
+^l2_3$
+^l2_4
+^l2_4$
+^l2_5
+^l2_5$
+^l2_6
+^l2_6$
+^l2_7
+^l2_7$
+^l2_8
+^l2_8$
+^l2_9
+^l2_9$
+
+============
+Test 4.4:146
+============
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+
+============
+Test 4.5:147
+============
+hello
+
+============
+Test 4.6:148
+============
+hello
+
+============
+Test 4.7:149
+============
+hello
+
+============
+Test 4.8:150
+============
+Testing labels and branching
+
+============
+Test 5.1:151
+============
+label2_l1_1
+label3_label2_l1_1
+label1_l1_2
+label1_l1_3
+label1_l1_4
+label1_l1_5
+label1_l1_6
+label1_l1_7
+label1_l1_8
+label1_l1_9
+label1_l1_10
+label1_l1_11
+label1_l1_12
+label2_l1_13
+label3_label2_l1_13
+label2_l1_14
+label3_label2_l1_14
+
+============
+Test 5.2:152
+============
+tested l2_1
+tested l2_2
+tested l2_3
+tested l2_4
+tested l2_5
+tested l2_6
+tested l2_7
+tested l2_8
+tested l2_9
+tested l2_10
+tested l2_11
+tested l2_12
+tested l2_13
+tested l2_14
+
+============
+Test 5.3:153
+============
+^l1_1
+^l1_1$
+^l1_2
+^l1_2$
+^l1_3
+^l1_3$
+^l1_4
+^l1_4$
+l1_5$
+l1_6$
+l1_7$
+l1_8$
+
+============
+Test 5.4:154
+============
+^l1_1$
+^l1_2$
+^l1_3$
+^l1_4$
+^l1_5$
+^l1_6$
+^l1_7$
+^l1_8$
+l1_9$
+l1_10$
+l1_11$
+l1_12$
+l1_13$
+l1_14$
+
+============
+Test 5.5:155
+============
+^l1_1
+^l1_2
+^l1_4
+^l1_6
+^l1_8
+
+============
+Test 5.6:156
+============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+
+============
+Test 5.7:157
+============
+l1_1
+l1_2
+l1_3
+l1_4
+hello
+l1_5
+
+============
+Test 5.8:158
+============
+m1_1
+m1_2
+m1_3
+m1_4
+m1_5
+m1_6
+m1_7
+m1_8
+m1_9
+m1_10
+m1_11
+m1_12
+m1_13
+m1_14
+Pattern space commands
+
+============
+Test 6.1:159
+============
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+
+============
+Test 6.2:160
+============
+l1_1
+l1_2
+l1_3
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 6.3:161
+============
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 6.4:162
+============
+l1_1
+l1_2
+l1_3
+l1_2
+l1_3
+l1_5
+l1_2
+l1_3
+l1_2
+l1_3
+l1_6
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 6.5:163
+============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 6.6:164
+============
+Testing print and file routines
+
+============
+Test 7.1:165
+============
+\001\002\003\004\005\006\a\b\t$
+\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\
+\035\036\037 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX\
+YZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\
+\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\
+\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\
+\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\
+\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\
+\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\
+\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\
+\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\
+\375\376\377$
+$
+
+============
+Test 7.2:166
+============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+15
+l2_1
+16
+l2_2
+17
+l2_3
+18
+l2_4
+19
+l2_5
+20
+l2_6
+21
+l2_7
+22
+l2_8
+23
+l2_9
+
+============
+Test 7.3:167
+============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+w results
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+
+============
+Test 7.4:168
+============
+l1_1
+l1_2
+l1_3
+l1_4
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 7.5:169
+============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 7.6:170
+============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 7.8:171
+============
+
+Testing substitution commands
+
+============
+Test 8.1:172
+============
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+
+============
+Test 8.2:173
+============
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+
+============
+Test 8.3:174
+============
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+
+============
+Test 8.4:175
+============
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+============
+Test 8.5:176
+============
+l1X1
+l1X2
+l1X3
+l1X4
+l1X5
+l1X6
+l1X7
+l1X8
+l1X9
+l1X10
+l1X11
+l1X12
+l1X13
+l1X14
+
+============
+Test 8.6:177
+============
+(l)(1)(_)(1)
+(l)(1)(_)(2)
+(l)(1)(_)(3)
+(l)(1)(_)(4)
+(l)(1)(_)(5)
+(l)(1)(_)(6)
+(l)(1)(_)(7)
+(l)(1)(_)(8)
+(l)(1)(_)(9)
+(l)(1)(_)(1)(0)
+(l)(1)(_)(1)(1)
+(l)(1)(_)(1)(2)
+(l)(1)(_)(1)(3)
+(l)(1)(_)(1)(4)
+
+============
+Test 8.7:178
+============
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+
+============
+Test 8.8:179
+============
+x_x1xl1
+x_x1xl2
+x_x1xl3
+x_x1xl4
+x_x1xl5
+x_x1xl6
+x_x1xl7
+x_x1xl8
+x_x1xl9
+x_x1xl10
+x_x1xl11
+x_x1xl12
+x_x1xl13
+x_x1xl14
+
+============
+Test 8.9:180
+============
+l1u0
+u1
+u21
+l1u0
+u1
+u22
+l1u0
+u1
+u23
+l1u0
+u1
+u24
+l1u0
+u1
+u25
+l1u0
+u1
+u26
+l1u0
+u1
+u27
+l1u0
+u1
+u28
+l1u0
+u1
+u29
+l1u0
+u1
+u210
+l1u0
+u1
+u211
+l1u0
+u1
+u212
+l1u0
+u1
+u213
+l1u0
+u1
+u214
+
+=============
+Test 8.10:181
+=============
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X0
+l1_X1
+l1_X2
+l1_X3
+l1_X4
+
+=============
+Test 8.11:182
+=============
+lX_1
+lX_2
+lX_3
+lX_4
+lX_5
+lX_6
+lX_7
+lX_8
+lX_9
+lX_10
+lX_11
+lX_12
+lX_13
+lX_14
+s wfile results
+lX_1
+lX_2
+lX_3
+lX_4
+lX_5
+lX_6
+lX_7
+lX_8
+lX_9
+lX_10
+lX_11
+lX_12
+lX_13
+lX_14
+
+=============
+Test 8.12:183
+=============
+lX_X
+lX_X
+lX_X
+lX_4
+lX_5
+lX_6
+lX_7
+lX_8
+lX_9
+lX_X0
+lX_XX
+lX_XX
+lX_XX
+lX_X4
+
+=============
+Test 8.13:184
+=============
+l8_8
+l8_7
+l8_6
+l8_5
+l8_4
+l8_3
+l8_2
+l8_1
+l8_0
+l8_89
+l8_88
+l8_87
+l8_86
+l8_85
+
+=============
+Test 8.14:185
+=============
+l8_8
+l8_7
+l8_6
+l8_5
+l8_4
+l8_3
+l8_2
+l8_1
+l8_0
+l8_89
+l8_88
+l8_87
+l8_86
+l8_85
+
+=============
+Test 8.15:186
+=============
+l1_1Xl1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+
+=============
+Test 8.16:187
+=============
+eeefff
+Xeefff
+XYefff
+XYeYff
+XYeYYf
+XYeYYY
+XYeYYY
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bsd.sh
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bsd.sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bsd.sh	(revision 1780)
@@ -0,0 +1,434 @@
+#!/bin/sh -
+#	$NetBSD: sed.test,v 1.3 1997/01/09 20:21:37 tls Exp $
+#
+# Copyright (c) 1992 Diomidis Spinellis.
+# Copyright (c) 1992, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the University of
+#	California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#	from: @(#)sed.test	8.1 (Berkeley) 6/6/93
+#	$NetBSD: sed.test,v 1.3 1997/01/09 20:21:37 tls Exp $
+#
+
+# sed Regression Tests
+
+# Modified by Paolo Bonzini to:
+# - not warn about buggy seds
+# - run tests once instead of comparing them to the system sed
+# - remove most uses of awk
+# - cleanup at exit
+# - comment tests that broke because of extensions
+
+main()
+{
+	TEST="${1-../sed/sed}"
+	TESTLOG="${2-sed.out}"
+	# DICT="${3-/usr/share/dict/words}"
+
+	: > lines1
+	: > lines2
+	for i in 1 2 3 4 5 6 7 8 9; do
+	  echo l1_$i >> lines1
+	  echo l2_$i >> lines2
+	done
+	for i in 10 11 12 13 14; do
+	  echo l1_$i >> lines1
+	done
+
+	# Set these flags to get messages about known problems
+	tests "$TEST" "$TESTLOG"
+
+	rm -f lines[1234] script[12]
+}
+
+tests()
+{
+	SED="$1"
+	LOG="$2"
+	MARK=100
+	rm -f "$LOG"
+
+	exec 3>&0 4>&1 5>&2
+	exec 0</dev/null 1>/dev/null 2>/dev/null
+	test_error
+	exec 0>&3 1>&4 2>&5
+
+	exec 4>&1 5>&2
+	test_args
+	test_addr
+	test_group
+	test_acid
+	test_branch
+	test_pattern
+	test_print
+	test_subst
+	exec 1>&4 2>&5
+}
+
+mark()
+{
+	exec 2>&1 >>$LOG
+	test $MARK = 100 || echo
+	MARK=`expr $MARK + 1`
+	echo "Test $1:$MARK" | sed 's/./=/g'
+	echo "Test $1:$MARK"
+	echo "Test $1:$MARK" | sed 's/./=/g'
+}
+
+test_args()
+{
+	mark '1.1'
+	echo Testing argument parsing
+	echo First type
+	$SED 's/^/e1_/p' lines1
+	mark '1.2' ; $SED -n 's/^/e1_/p' lines1
+	mark '1.3' ; $SED 's/^/e1_/p' <lines1
+	mark '1.4' ; $SED -n 's/^/e1_/p' <lines1
+	echo Second type
+	mark '1.4.1'
+	$SED -e '' <lines1
+	echo 's/^/s1_/p' >script1
+	echo 's/^/s2_/p' >script2
+	mark '1.5' ; $SED -f script1 lines1
+	mark '1.6' ; $SED -f script1 <lines1
+	mark '1.7' ; $SED -e 's/^/e1_/p' lines1
+	mark '1.8' ; $SED -e 's/^/e1_/p' <lines1
+	mark '1.9' ; $SED -n -f script1 lines1
+	mark '1.10' ; $SED -n -f script1 <lines1
+	mark '1.11' ; $SED -n -e 's/^/e1_/p' lines1
+	mark '1.12' ; $SED -n -e 's/^/e1_/p' <lines1
+	mark '1.13' ; $SED -e 's/^/e1_/p' -e 's/^/e2_/p' lines1
+	mark '1.14' ; $SED -f script1 -f script2 lines1
+	mark '1.15' ; $SED -e 's/^/e1_/p' -f script1 lines1
+	mark '1.16' ; $SED -e 's/^/e1_/p' lines1 lines1
+	# POSIX D11.2:11251
+	mark '1.17' ; $SED p <lines1 lines1
+cat >script1 <<EOF
+#n
+# A comment
+
+p
+EOF
+	mark '1.18' ; $SED -f script1 <lines1 lines1
+}
+
+test_addr()
+{
+	echo Testing address ranges
+	mark '2.1' ; $SED -n -e '4p' lines1
+	mark '2.2' ; $SED -n -e '20p' lines1 lines2
+	mark '2.3' ; $SED -n -e '$p' lines1
+	mark '2.4' ; $SED -n -e '$p' lines1 lines2
+	mark '2.5' ; $SED -n -e '$a\
+hello' /dev/null
+	mark '2.6' ; $SED -n -e '$p' lines1 /dev/null lines2
+	# Should not print anything
+	mark '2.7' ; $SED -n -e '20p' lines1
+	# Disabled because it is undefined behavior
+	# mark '2.8' ; $SED -n -e '0p' lines1
+	mark '2.9' ; $SED -n '/l1_7/p' lines1
+	mark '2.10' ; $SED -n ' /l1_7/ p' lines1
+	mark '2.11' ; $SED -n '\_l1\_7_p' lines1
+	mark '2.12' ; $SED -n '1,4p' lines1
+	mark '2.13' ; $SED -n '1,$p' lines1 lines2
+	mark '2.14' ; $SED -n '1,/l2_9/p' lines1 lines2
+	mark '2.15' ; $SED -n '/4/,$p' lines1 lines2
+	mark '2.16' ; $SED -n '/4/,20p' lines1 lines2
+	mark '2.17' ; $SED -n '/4/,/10/p' lines1 lines2
+	mark '2.18' ; $SED -n '/l2_3/,/l1_8/p' lines1 lines2
+	mark '2.19' ; $SED -n '12,3p' lines1 lines2
+	mark '2.20' ; $SED -n '/l1_7/,3p' lines1 lines2
+}
+
+test_group()
+{
+	echo Brace and other grouping
+	mark '3.1' ; $SED -e '
+4,12 {
+	s/^/^/
+	s/$/$/
+	s/_/T/
+}' lines1
+	mark '3.2' ; $SED -e '
+4,12 {
+	s/^/^/
+	/6/,/10/ {
+		s/$/$/
+		/8/ s/_/T/
+	}
+}' lines1
+	mark '3.3' ; $SED -e '
+4,12 !{
+	s/^/^/
+	/6/,/10/ !{
+		s/$/$/
+		/8/ !s/_/T/
+	}
+}' lines1
+	mark '3.4' ; $SED -e '4,12!s/^/^/' lines1
+}
+
+test_acid()
+{
+	echo Testing a c d and i commands
+	mark '4.1' ; $SED -n -e '
+s/^/before_i/p
+20i\
+inserted
+s/^/after_i/p
+' lines1 lines2
+	mark '4.2' ; $SED -n -e '
+5,12s/^/5-12/
+s/^/before_a/p
+/5-12/a\
+appended
+s/^/after_a/p
+' lines1 lines2
+	mark '4.3' ; $SED -n -e '
+s/^/^/p
+/l1_/a\
+appended
+8,10N
+s/$/$/p
+' lines1 lines2
+	mark '4.4' ; $SED -n -e '
+c\
+hello
+' lines1
+	mark '4.5' ; $SED -n -e '
+8c\
+hello
+' lines1
+	mark '4.6' ; $SED -n -e '
+3,14c\
+hello
+' lines1
+	mark '4.7' ; $SED -n -e '
+8,3c\
+hello
+' lines1
+	mark '4.8' ; $SED d <lines1
+}
+
+test_branch()
+{
+	echo Testing labels and branching
+	mark '5.1' ; $SED -n -e '
+b label4
+:label3
+s/^/label3_/p
+b end
+:label4
+2,12b label1
+b label2
+:label1
+s/^/label1_/p
+b
+:label2
+s/^/label2_/p
+b label3
+:end
+' lines1
+	mark '5.2' ; $SED -n -e '
+s/l1_/l2_/
+t ok
+b
+:ok
+s/^/tested /p
+' lines1 lines2
+	mark '5.3' ; $SED -n -e '
+5,8b inside
+1,5 {
+	s/^/^/p
+	:inside
+	s/$/$/p
+}
+' lines1
+# Check that t clears the substitution done flag
+	mark '5.4' ; $SED -n -e '
+1,8s/^/^/
+t l1
+:l1
+t l2
+s/$/$/p
+b
+:l2
+s/^/ERROR/
+' lines1
+# Check that reading a line clears the substitution done flag
+	mark '5.5' ; $SED -n -e '
+t l2
+1,8s/^/^/p
+2,7N
+b
+:l2
+s/^/ERROR/p
+' lines1
+	mark '5.6' ; $SED 5q lines1
+	mark '5.7' ; $SED -e '
+5i\
+hello
+5q' lines1
+# Branch across block boundary
+	mark '5.8' ; $SED -e '
+{
+:b
+}
+s/l/m/
+tb' lines1
+}
+
+test_pattern()
+{
+echo Pattern space commands
+# Check that the pattern space is deleted
+	mark '6.1' ; $SED -n -e '
+c\
+changed
+p
+' lines1
+	mark '6.2' ; $SED -n -e '
+4d
+p
+' lines1
+	mark '6.3' ; $SED -e '
+N
+N
+N
+D
+P
+4p
+' lines1
+	mark '6.4' ; $SED -e '
+2h
+3H
+4g
+5G
+6x
+6p
+6x
+6p
+' lines1
+	mark '6.5' ; $SED -e '4n' lines1
+	mark '6.6' ; $SED -n -e '4n' lines1
+}
+
+test_print()
+{
+	echo Testing print and file routines
+	awk 'END {for (i = 1; i < 256; i++) printf("%c", i);print "\n"}' \
+		</dev/null >lines3
+	mark '7.1' ; $SED -n l lines3
+	mark '7.2' ; $SED -e '/l2_/=' lines1 lines2
+	rm -f lines4
+	mark '7.3' ; $SED -e '3,12w lines4' lines1
+	echo w results
+	cat lines4
+	mark '7.4' ; $SED -e '4r lines2' lines1
+	mark '7.5' ; $SED -e '5r /dev/dds' lines1
+	mark '7.6' ; $SED -e '6r /dev/null' lines1
+	# mark '7.7'
+	# sed '200q' $DICT | sed 's$.*$s/^/&/w tmpdir/&$' >script1
+	# rm -rf tmpdir
+	# mkdir tmpdir
+	# $SED -f script1 lines1
+	# cat tmpdir/*
+	# rm -rf tmpdir
+	mark '7.8'
+	echo line1 > lines3
+	echo "" >> lines3
+	$SED -n -e '$p' lines3 /dev/null
+}
+
+test_subst()
+{
+	echo Testing substitution commands
+	mark '8.1' ; $SED -e 's/./X/g' lines1
+	mark '8.2' ; $SED -e 's,.,X,g' lines1
+	mark '8.3' ; $SED -e 's.\..X.g' lines1
+# POSIX does not say that this should work
+#	mark '8.4' ; $SED -e 's/[/]/Q/' lines1
+	mark '8.4' ; $SED -e 's/[\/]/Q/' lines1
+	mark '8.5' ; $SED -e 's_\__X_' lines1
+	mark '8.6' ; $SED -e 's/./(&)/g' lines1
+	mark '8.7' ; $SED -e 's/./(\&)/g' lines1
+	mark '8.8' ; $SED -e 's/\(.\)\(.\)\(.\)/x\3x\2x\1/g' lines1
+	mark '8.9' ; $SED -e 's/_/u0\
+u1\
+u2/g' lines1
+	mark '8.10' ; $SED -e 's/./X/4' lines1
+	rm -f lines4
+	mark '8.11' ; $SED -e 's/1/X/w lines4' lines1
+	echo s wfile results
+	cat lines4
+	mark '8.12' ; $SED -e 's/[123]/X/g' lines1
+	mark '8.13' ; $SED -e 'y/0123456789/9876543210/' lines1
+	mark '8.14' ; $SED -e 'y10\123456789198765432\101' lines1
+	mark '8.15' ; $SED -e '1N;2y/\n/X/' lines1
+	mark '8.16'
+	echo 'eeefff' | $SED -e 'p' -e 's/e/X/p' -e ':x' \
+	    -e 's//Y/p' -e '/f/bx'
+}
+
+test_error()
+{
+	$SED -x && exit 1
+	$SED -f && exit 1
+	$SED -e && exit 1
+	$SED -f /dev/dds && exit 1
+	$SED p /dev/dds && exit 1
+	$SED -f /bin/sh && exit 1
+	$SED '{' && exit 1
+	$SED '{' && exit 1
+	$SED '/hello/' && exit 1
+	$SED '1,/hello/' && exit 1
+	$SED -e '-5p' && exit 1
+	$SED '/jj' && exit 1
+	# $SED 'a hello' && exit 1
+	# $SED 'a \ hello' && exit 1
+	$SED 'b foo' && exit 1
+	$SED 'd hello' && exit 1
+	$SED 's/aa' && exit 1
+	$SED 's/aa/' && exit 1
+	$SED 's/a/b' && exit 1
+	$SED 's/a/b/c/d' && exit 1
+	$SED 's/a/b/ 1 2' && exit 1
+	# $SED 's/a/b/ 1 g' && exit 1
+	$SED 's/a/b/w' && exit 1
+	$SED 'y/aa' && exit 1
+	$SED 'y/aa/b/' && exit 1
+	$SED 'y/aa/' && exit 1
+	$SED 'y/a/b' && exit 1
+	$SED 'y/a/b/c/d' && exit 1
+	$SED '!' && exit 1
+	$SED supercalifrangolisticexprialidociussupercalifrangolisticexcius
+}
+
+main ${1+"$@"}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex10.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex10.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex10.c	(revision 1780)
@@ -0,0 +1,61 @@
+/* Test for re_match with non-zero start.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <regex.h>
+
+int
+main (void)
+{
+  struct re_pattern_buffer regex;
+  struct re_registers regs;
+  const char *s;
+  int match;
+  int result = 0;
+
+  regs.num_regs = 1;
+  memset (&regex, '\0', sizeof (regex));
+  s = re_compile_pattern ("[abc]*d", 7, &regex);
+  if (s != NULL)
+    {
+      puts ("re_compile_pattern return non-NULL value");
+      result = 1;
+    }
+  else
+    {
+      match = re_match (&regex, "foacabdxy", 9, 2, &regs);
+      if (match != 5)
+	{
+	  printf ("re_match returned %d, expected 5\n", match);
+	  result = 1;
+	}
+      else if (regs.start[0] != 2 || regs.end[0] != 7)
+	{
+	  printf ("re_match returned %d..%d, expected 2..7\n",
+		  regs.start[0], regs.end[0]);
+	  result = 1;
+	}
+	puts (" -> OK");
+    }
+
+  return result;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex11.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex11.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex11.c	(revision 1780)
@@ -0,0 +1,141 @@
+/* Regular expression tests.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Tests supposed to match.  */
+struct
+{
+  const char *pattern;
+  const char *string;
+  int flags, nmatch;
+  regmatch_t rm[5];
+} tests[] = {
+  /* Test for newline handling in regex.  */
+  { "[^~]*~", "\nx~y", 0, 2, { { 0, 3 }, { -1, -1 } } },
+  /* Other tests.  */
+  { "a(.*)b", "a b", REG_EXTENDED, 2, { { 0, 3 }, { 1, 2 } } },
+  { ".*|\\([KIO]\\)\\([^|]*\\).*|?[KIO]", "10~.~|P|K0|I10|O16|?KSb", 0, 3,
+    { { 0, 21 }, { 15, 16 }, { 16, 18 } } },
+  { ".*|\\([KIO]\\)\\([^|]*\\).*|?\\1", "10~.~|P|K0|I10|O16|?KSb", 0, 3,
+    { { 0, 21 }, { 8, 9 }, { 9, 10 } } },
+  { "^\\(a*\\)\\1\\{9\\}\\(a\\{0,9\\}\\)\\([0-9]*;.*[^a]\\2\\([0-9]\\)\\)",
+    "a1;;0a1aa2aaa3aaaa4aaaaa5aaaaaa6aaaaaaa7aaaaaaaa8aaaaaaaaa9aa2aa1a0", 0,
+    5, { { 0, 67 }, { 0, 0 }, { 0, 1 }, { 1, 67 }, { 66, 67 } } },
+  /* Test for BRE expression anchoring.  POSIX says just that this may match;
+     in glibc regex it always matched, so avoid changing it.  */
+  { "\\(^\\|foo\\)bar", "bar", 0, 2, { { 0, 3 }, { -1, -1 } } },
+  { "\\(foo\\|^\\)bar", "bar", 0, 2, { { 0, 3 }, { -1, -1 } } },
+  /* In ERE this must be treated as an anchor.  */
+  { "(^|foo)bar", "bar", REG_EXTENDED, 2, { { 0, 3 }, { -1, -1 } } },
+  { "(foo|^)bar", "bar", REG_EXTENDED, 2, { { 0, 3 }, { -1, -1 } } },
+  /* Here ^ cannot be treated as an anchor according to POSIX.  */
+  { "(^|foo)bar", "(^|foo)bar", 0, 2, { { 0, 10 }, { -1, -1 } } },
+  { "(foo|^)bar", "(foo|^)bar", 0, 2, { { 0, 10 }, { -1, -1 } } },
+  /* More tests on backreferences.  */
+  { "()\\1", "x", REG_EXTENDED, 2, { { 0, 0 }, { 0, 0 } } },
+  { "()x\\1", "x", REG_EXTENDED, 2, { { 0, 1 }, { 0, 0 } } },
+  { "()\\1*\\1*", "", REG_EXTENDED, 2, { { 0, 0 }, { 0, 0 } } },
+  { "([0-9]).*\\1(a*)", "7;7a6", REG_EXTENDED, 3, { { 0, 4 }, { 0, 1 }, { 3, 4 } } },
+  { "([0-9]).*\\1(a*)", "7;7a", REG_EXTENDED, 3, { { 0, 4 }, { 0, 1 }, { 3, 4 } } },
+  { "(b)()c\\1", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 1 }, { 1, 1 } } },
+  { "()(b)c\\2", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 0 }, { 0, 1 } } },
+  { "a(b)()c\\1", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 2 }, { 2, 2 } } },
+  { "a()(b)c\\2", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 1 }, { 1, 2 } } },
+  { "()(b)\\1c\\2", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 0 }, { 0, 1 } } },
+  { "(b())\\2\\1", "bbbb", REG_EXTENDED, 3, { { 0, 2 }, { 0, 1 }, { 1, 1 } } },
+  { "a()(b)\\1c\\2", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 1 }, { 1, 2 } } },
+  { "a()d(b)\\1c\\2", "adbcb", REG_EXTENDED, 3, { { 0, 5 }, { 1, 1 }, { 2, 3 } } },
+  { "a(b())\\2\\1", "abbbb", REG_EXTENDED, 3, { { 0, 3 }, { 1, 2 }, { 2, 2 } } },
+  { "(bb())\\2\\1", "bbbb", REG_EXTENDED, 3, { { 0, 4 }, { 0, 2 }, { 2, 2 } } },
+  { "^(.?)(.?)(.?)(.?)(.?).?\\5\\4\\3\\2\\1$",
+    "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } },
+  { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$",
+    "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } },
+  { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$",
+    "abcdedcba", REG_EXTENDED, 1, { { 0, 9 } } },
+#if 0
+  /* XXX Not used since they fail so far.  */
+  { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$",
+    "ababababa", REG_EXTENDED, 1, { { 0, 9 } } },
+  { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$",
+    "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } },
+  { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$",
+    "ababababa", REG_EXTENDED, 1, { { 0, 9 } } },
+#endif
+};
+
+int
+main (void)
+{
+  regex_t re;
+  regmatch_t rm[5];
+  size_t i;
+  int n, ret = 0;
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+    {
+      n = regcomp (&re, tests[i].pattern, tests[i].flags);
+      if (n != 0)
+	{
+	  char buf[500];
+	  regerror (n, &re, buf, sizeof (buf));
+	  printf ("%s: regcomp %lu failed: %s\n", tests[i].pattern, i, buf);
+	  ret = 1;
+	  continue;
+	}
+
+      if (regexec (&re, tests[i].string, tests[i].nmatch, rm, 0))
+	{
+	  printf ("%s: regexec %lu failed\n", tests[i].pattern, i);
+	  ret = 1;
+	  regfree (&re);
+	  continue;
+	}
+
+      for (n = 0; n < tests[i].nmatch; ++n)
+	if (rm[n].rm_so != tests[i].rm[n].rm_so
+              || rm[n].rm_eo != tests[i].rm[n].rm_eo)
+	  {
+	    if (tests[i].rm[n].rm_so == -1 && tests[i].rm[n].rm_eo == -1)
+	      break;
+	    printf ("%s: regexec %lu match failure rm[%d] %d..%d\n",
+		    tests[i].pattern, i, n, rm[n].rm_so, rm[n].rm_eo);
+	    ret = 1;
+	    break;
+	  }
+
+      regfree (&re);
+    }
+
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex12.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex12.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex12.c	(revision 1780)
@@ -0,0 +1,79 @@
+/* Regular expression tests.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Tests supposed to not match.  */
+struct
+{
+  const char *pattern;
+  const char *string;
+  int flags, nmatch;
+} tests[] = {
+  { "^<\\([^~]*\\)\\([^~]\\)[^~]*~\\1\\(.\\).*|=.*\\3.*\\2",
+    "<,.8~2,~so-|=-~.0,123456789<><", REG_NOSUB, 0 },
+  /* In ERE, all carets must be treated as anchors.  */
+  { "a^b", "a^b", REG_EXTENDED, 0 }
+};
+
+int
+main (void)
+{
+  regex_t re;
+  regmatch_t rm[4];
+  size_t i;
+  int n, ret = 0;
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+    {
+      n = regcomp (&re, tests[i].pattern, tests[i].flags);
+      if (n != 0)
+	{
+	  char buf[500];
+	  regerror (n, &re, buf, sizeof (buf));
+	  printf ("regcomp %lu failed: %s\n", i, buf);
+	  ret = 1;
+	  continue;
+	}
+
+      if (! regexec (&re, tests[i].string, tests[i].nmatch,
+		     tests[i].nmatch ? rm : NULL, 0))
+	{
+	  printf ("regexec %lu incorrectly matched\n", i);
+	  ret = 1;
+	}
+
+      regfree (&re);
+    }
+
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex13.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex13.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex13.c	(revision 1780)
@@ -0,0 +1,109 @@
+/* Regular expression tests.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>, 2002.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static struct
+{
+  int syntax;
+  const char *pattern;
+  const char *string;
+  int start;
+} tests[] = {
+  {RE_BACKSLASH_ESCAPE_IN_LISTS, "[0\\-9]", "1", -1}, /* It should not match.  */
+  {RE_BACKSLASH_ESCAPE_IN_LISTS, "[0\\-9]", "-", 0}, /* It should match.  */
+  {RE_SYNTAX_POSIX_BASIC, "s1\n.*\ns3", "s1\ns2\ns3", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}c", "ac", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}c", "abc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}c", "abbc", -1},
+  /* Nested duplication.  */
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{1}c", "ac", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{1}c", "abc", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{1}c", "abbc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{2}{2}c", "ac", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{2}{2}c", "abbc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{2}{2}c", "abbbbc", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{2}{2}c", "abbbbbc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}{1}c", "ac", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}{1}c", "abc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}{1}c", "abbc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{0}c", "ac", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{0}c", "abc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{1}{0}c", "abbc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}*c", "ac", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}*c", "abc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}*c", "abbc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}?c", "ac", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}?c", "abc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}?c", "abbc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}+c", "ac", 0},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}+c", "abc", -1},
+  {RE_SYNTAX_POSIX_EXTENDED, "ab{0}+c", "abbc", -1},
+};
+
+int
+main (void)
+{
+  struct re_pattern_buffer regbuf;
+  const char *err;
+  size_t i;
+  int ret = 0;
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+    {
+      int start;
+      re_set_syntax (tests[i].syntax);
+      memset (&regbuf, '\0', sizeof (regbuf));
+      err = re_compile_pattern (tests[i].pattern, strlen (tests[i].pattern),
+                                &regbuf);
+      if (err != NULL)
+	{
+	  printf ("re_compile_pattern failed: %s\n", err);
+	  ret = 1;
+	  continue;
+	}
+
+      start = re_search (&regbuf, tests[i].string, strlen (tests[i].string),
+                         0, strlen (tests[i].string), NULL);
+      if (start != tests[i].start)
+	{
+	  printf ("re_search failed %d\n", start);
+	  ret = 1;
+	  regfree (&regbuf);
+	  continue;
+	}
+      regfree (&regbuf);
+    }
+
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex14.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex14.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex14.c	(revision 1780)
@@ -0,0 +1,60 @@
+/* Tests re_comp and re_exec.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>, 2002.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#define _REGEX_RE_COMP
+#include <sys/types.h>
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  const char *err;
+  size_t i;
+  int ret = 0;
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  for (i = 0; i < 100; ++i)
+    {
+      err = re_comp ("a t.st");
+      if (err)
+	{
+	  printf ("re_comp failed: %s\n", err);
+	  ret = 1;
+	}
+
+      if (! re_exec ("This is a test."))
+	{
+	  printf ("re_exec failed\n");
+	  ret = 1;
+	}
+    }
+
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex15.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex15.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex15.c	(revision 1780)
@@ -0,0 +1,47 @@
+/* Test for memory/CPU leak in regcomp.  */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define TEST_DATA_LIMIT (32 << 20)
+
+int
+main ()
+{
+#ifdef RLIMIT_DATA
+  regex_t re;
+  int reerr;
+
+  /* Try to avoid eating all memory if a test leaks.  */
+  struct rlimit data_limit;
+  if (getrlimit (RLIMIT_DATA, &data_limit) == 0)
+    {
+      if ((rlim_t) TEST_DATA_LIMIT > data_limit.rlim_max)
+	data_limit.rlim_cur = data_limit.rlim_max;
+      else if (data_limit.rlim_cur > (rlim_t) TEST_DATA_LIMIT)
+	data_limit.rlim_cur = (rlim_t) TEST_DATA_LIMIT;
+      if (setrlimit (RLIMIT_DATA, &data_limit) < 0)
+	perror ("setrlimit: RLIMIT_DATA");
+    }
+  else
+    perror ("getrlimit: RLIMIT_DATA");
+
+  reerr = regcomp (&re, "^6?3?[25]?5?[14]*[25]*[69]*+[58]*87?4?$",
+		   REG_EXTENDED | REG_NOSUB);
+  if (reerr != 0)
+    {
+      char buf[100];
+      regerror (reerr, &re, buf, sizeof buf);
+      printf ("regerror %s\n", buf);
+      return 1;
+    }
+
+  return 0;
+#else
+  return 77;
+#endif
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex16.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex16.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex16.c	(revision 1780)
@@ -0,0 +1,35 @@
+/* Test re_compile_pattern error messages.  */
+
+#include <stdio.h>
+#include <string.h>
+#include <regex.h>
+
+int
+main (void)
+{
+  struct re_pattern_buffer re;
+  const char *s;
+  int ret = 0;
+
+  re_set_syntax (RE_SYNTAX_POSIX_EGREP);
+  memset (&re, 0, sizeof (re));
+  s = re_compile_pattern ("[[.invalid_collating_symbol.]]", 30, &re);
+  if (s == NULL || strcmp (s, "Invalid collation character"))
+    {
+      printf ("re_compile_pattern returned %s\n", s);
+      ret = 1;
+    }
+  s = re_compile_pattern ("[[=invalid_equivalence_class=]]", 31, &re);
+  if (s == NULL || strcmp (s, "Invalid collation character"))
+    {
+      printf ("re_compile_pattern returned %s\n", s);
+      ret = 1;
+    }
+  s = re_compile_pattern ("[[:invalid_character_class:]]", 29, &re);
+  if (s == NULL || strcmp (s, "Invalid character class name"))
+    {
+      printf ("re_compile_pattern returned %s\n", s);
+      ret = 1;
+    }
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex21.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex21.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex21.c	(revision 1780)
@@ -0,0 +1,51 @@
+/* Test for memory leaks in regcomp.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+
+int main (void)
+{
+  regex_t re;
+  int i;
+  int ret = 0;
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  for (i = 0; i < 32; ++i)
+    {
+      if (regcomp (&re, "X-.+:.+Y=\".*\\.(A|B|C|D|E|F|G|H|I",
+		   REG_EXTENDED | REG_ICASE) == 0)
+	{
+	  puts ("regcomp unexpectedly succeeded");
+	  ret = 1;
+	}
+      else
+	regfree (&re);
+    }
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex7.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex7.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex7.c	(revision 1780)
@@ -0,0 +1,92 @@
+/* Test for regs allocation in re_search and re_match.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Stepan Kasal <kasal@math.cas.cz>, 2002.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <regex.h>
+
+
+int
+main (void)
+{
+  struct re_pattern_buffer regex;
+  struct re_registers regs;
+  const char *s;
+  int match, n;
+  int result = 0;
+
+  memset (&regex, '\0', sizeof (regex));
+  regs.start = regs.end = NULL;
+  regs.num_regs = 0;
+  s = re_compile_pattern ("a", 1, &regex);
+  if (s != NULL)
+    {
+      puts ("failed to compile pattern \"a\"");
+      result = 1;
+    }
+  else
+    {
+      match = re_search (&regex, "baobab", 6, 0, 6, &regs);
+      n = 1;
+      if (match != 1)
+	{
+	  printf ("re_search returned %d, expected 1\n", match);
+	  result = 1;
+	}
+      else if (regs.num_regs <= n || regs.start[n] != -1 || regs.end[n] != -1)
+	{
+	  puts ("re_search failed to fill the -1 sentinel");
+	  result = 1;
+	}
+    }
+
+  free (regex.buffer);
+  memset (&regex, '\0', sizeof (regex));
+
+  s = re_compile_pattern ("\\(\\(\\(a\\)\\)\\)", 13, &regex);
+  if (s != NULL)
+    {
+      puts ("failed to compile pattern /\\(\\(\\(a\\)\\)\\)/");
+      result = 1;
+    }
+  else
+    {
+      match = re_match (&regex, "apl", 3, 0, &regs);
+      n = 4;
+      if (match != 1)
+	{
+	  printf ("re_match returned %d, expected 1\n", match);
+	  result = 1;
+	}
+      else if (regs.num_regs <= n || regs.start[n] != -1 || regs.end[n] != -1)
+	{
+	  puts ("re_match failed to fill the -1 sentinel");
+	  result = 1;
+	}
+    }
+
+  if (result == 0)
+    puts (" -> OK");
+
+  return result;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex8.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex8.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex8.c	(revision 1780)
@@ -0,0 +1,84 @@
+/* Test for the STOP parameter of re_match_2 and re_search_2.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Stepan Kasal <kasal@math.cas.cz>, 2002.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <regex.h>
+
+
+int
+main (void)
+{
+  struct re_pattern_buffer regex;
+  const char *s;
+  int match[4];
+
+  memset (&regex, '\0', sizeof (regex));
+
+  s = re_compile_pattern ("xy$", 3, &regex);
+  if (s != NULL)
+    {
+      puts ("failed to compile pattern \"xy$\"");
+      return 1;
+    }
+  else
+    match[0] = re_match_2(&regex,"xyz",3,NULL,0,0,NULL,2);
+
+  free (regex.buffer);
+  memset (&regex, '\0', sizeof (regex));
+
+  s = re_compile_pattern ("xy\\>", 4, &regex);
+  if (s != NULL)
+    {
+      puts ("failed to compile pattern \"xy\\>\"");
+      return 1;
+    }
+  else
+    match[1] = re_search_2(&regex,"xyz",3,NULL,0,0,2,NULL,2);
+
+  free (regex.buffer);
+  memset (&regex, '\0', sizeof (regex));
+
+  s = re_compile_pattern ("xy \\<", 5, &regex);
+  if (s != NULL)
+    {
+      puts ("failed to compile pattern \"xy \\<\"");
+      return 1;
+    }
+  else
+    {
+      match[2] = re_match_2(&regex,"xy  ",4,NULL,0,0,NULL,3);
+      match[3] = re_match_2(&regex,"xy z",4,NULL,0,0,NULL,3);
+    }
+
+  if (match[0] != -1 || match[1] != -1 || match[2] != -1 || match[3] != 3)
+    {
+      printf ("re_{match,search}_2 returned %d,%d,%d,%d, expected -1,-1,-1,3\n",
+		match[0], match[1], match[2], match[3]);
+      return 1;
+    }
+
+  puts (" -> OK");
+
+  return 0;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex9.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex9.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/bug-regex9.c	(revision 1780)
@@ -0,0 +1,73 @@
+/* Test for memory handling in regex.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static const char text[] = "#! /bin/sh";
+
+int
+main (void)
+{
+  regex_t re;
+  regmatch_t rm[2];
+  int n;
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  n = regcomp (&re, "^#! */.*/(k|ba||pdk|z)sh", REG_EXTENDED);
+  if (n != 0)
+    {
+      char buf[500];
+      regerror (n, &re, buf, sizeof (buf));
+      printf ("regcomp failed: %s\n", buf);
+      exit (1);
+    }
+
+  for (n = 0; n < 20; ++n)
+    {
+      if (regexec (&re, text, 2, rm, 0))
+	{
+	  puts ("regexec failed");
+	  exit (2);
+	}
+      if (rm[0].rm_so != 0 || rm[0].rm_eo != 10
+	  || rm[1].rm_so != 8 || rm[1].rm_eo != 8)
+	{
+	  printf ("regexec match failure: %d %d %d %d\n",
+		  rm[0].rm_so, rm[0].rm_eo, rm[1].rm_so, rm[1].rm_eo);
+	  exit (3);
+	}
+    }
+
+  regfree (&re);
+
+  return 0;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/classes.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/classes.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/classes.good	(revision 1780)
@@ -0,0 +1,4 @@
+: ${_cv_='emptyvar'}
+: ${ac_cv_prog/RANLIB='/usr/bin/ranlib'}
+: ${ac_cv_prog/CC='/usr/unsupported/\ \ /lib/_cv_/cc'}
+: ${a/c_cv_prog/CPP='/usr/bin/cpp'}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/classes.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/classes.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/classes.inp	(revision 1780)
@@ -0,0 +1,6 @@
+_cv_=emptyvar
+ac_cv_prog/RANLIB=/usr/bin/ranlib
+ac_cv_prog/CC=/usr/unsupported/\ \ /lib/_cv_/cc
+a/c_cv_prog/CPP=/usr/bin/cpp
+SHELL=bash
+GNU=GNU!UNIX
Index: /tags/kBuild-0.1.4/src/sed/testsuite/classes.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/classes.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/classes.sed	(revision 1780)
@@ -0,0 +1,2 @@
+# inspired by an autoconf generated configure script.
+s/^\([/[:lower:]A-Z0-9]*_cv_[[:lower:][:upper:]/[:digit:]]*\)=\(.*\)/: \${\1='\2'}/p
Index: /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.good	(revision 1780)
@@ -0,0 +1,4 @@
+: ${_cv_='emptyvar'}
+: ${ac_cv_prog_RANLIB='/usr/bin/ranlib'}
+: ${ac_cv_prog_CC='/usr/unsupported/\ \ /lib/_cv_/cc'}
+: ${ac_cv_prog_CPP='/usr/bin/cpp'}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.inp	(revision 1780)
@@ -0,0 +1,6 @@
+_cv_=emptyvar
+ac_cv_prog_RANLIB=/usr/bin/ranlib
+ac_cv_prog_CC=/usr/unsupported/\ \ /lib/_cv_/cc
+ac_cv_prog_CPP=/usr/bin/cpp
+SHELL=bash
+GNU=GNU!UNIX
Index: /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/cv-vars.sed	(revision 1780)
@@ -0,0 +1,2 @@
+# inspired by an autoconf generated configure script.
+s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/: \${\1='\2'}/p
Index: /tags/kBuild-0.1.4/src/sed/testsuite/dc.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/dc.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/dc.good	(revision 1780)
@@ -0,0 +1,3 @@
+31
+March 2002
+1.6A09E667A
Index: /tags/kBuild-0.1.4/src/sed/testsuite/dc.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/dc.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/dc.inp	(revision 1780)
@@ -0,0 +1,14 @@
+# Compute Easter of 2002...
+# usage:   (echo YEAR; cat easter.dc) | dc
+
+2002
+
+[ddsf[lfp[too early
+]Pq]s@1583>@
+ddd19%1+sg100/1+d3*4/12-sx8*5+25/5-sz5*4/lx-10-sdlg11*20+lz+lx-30%
+d[30+]s@0>@d[[1+]s@lg11<@]s@25=@d[1+]s@24=@se44le-d[30+]s@21>@dld+7%-7+
+[March ]smd[31-[April ]sm]s@31<@psnlmPpsn1z>p]splpx
+
+# Compute square root of 2
+
+16oAk2vpq
Index: /tags/kBuild-0.1.4/src/sed/testsuite/dc.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/dc.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/dc.sed	(revision 1780)
@@ -0,0 +1,322 @@
+#!/bin/sed -nf
+#  dc.sed - an arbitrary precision RPN calculator
+#  Created by Greg Ubben <gsu@romulus.ncsc.mil> early 1995, late 1996
+#
+#  Dedicated to MAC's memory of the IBM 1620 ("CADET") computer.
+#  @(#)GSU dc.sed 1.1 06-Mar-1999 [non-explanatory]
+#
+#  Examples:
+#	sqrt(2) to 10 digits:	echo "10k 2vp" | dc.sed
+#	20 factorial:		echo "[d1-d1<!*]s! 20l!xp" | dc.sed
+#	sin(ln(7)):		echo "s(l(7))" | bc -c /usr/lib/lib.b | dc.sed
+#	hex to base 60:		echo "60o16i 6B407.CAFE p" | dc.sed
+#	tests most of dc.sed:	echo 16oAk2vp | dc.sed
+#
+#  To debug or analyze, give the dc Y command as input or add it to
+#  embedded dc routines, or add the sed p command to the beginning of
+#  the main loop or at various points in the low-level sed routines.
+#  If you need to allow [|~] characters in the input, filter this
+#  script through "tr '|~' '\36\37'" first (or use dc.pl).
+#
+#  Not implemented:	! \
+#  But implemented:	K Y t # !< !> != fractional-bases
+#  SunOS limits:	199/199 commands (though could pack in 10-20 more)
+#  Limitations:		scale <= 999; |obase| >= 1; input digits in [0..F]
+#  Completed:		1am Feb 4, 1997
+
+s/^/|P|K0|I10|O10|?~/
+
+: next
+s/|?./|?/
+s/|?#[	 -}]*/|?/
+/|?!*[lLsS;:<>=]\{0,1\}$/N
+/|?!*[-+*/%^<>=]/b binop
+/^|.*|?[dpPfQXZvxkiosStT;:]/b binop
+/|?[_0-9A-F.]/b number
+/|?\[/b string
+/|?l/b load
+/|?L/b Load
+/|?[sS]/b save
+/|?c/ s/[^|]*//
+/|?d/ s/[^~]*~/&&/
+/|?f/ s//&[pSbz0<aLb]dSaxsaLa/
+/|?x/ s/\([^~]*~\)\(.*|?x\)~*/\2\1/
+/|?[KIO]/ s/.*|\([KIO]\)\([^|]*\).*|?\1/\2~&/
+/|?T/ s/\.*0*~/~/
+#  a slow, non-stackable array implementation in dc, just for completeness
+#  A fast, stackable, associative array implementation could be done in sed
+#  (format: {key}value{key}value...), but would be longer, like load & save.
+/|?;/ s/|?;\([^{}]\)/|?~[s}s{L{s}q]S}[S}l\1L}1-d0>}s\1L\1l{xS\1]dS{xL}/
+/|?:/ s/|?:\([^{}]\)/|?~[s}L{s}L{s}L}s\1q]S}S}S{[L}1-d0>}S}l\1s\1L\1l{xS\1]dS{x/
+/|?[ ~	cdfxKIOT]/b next
+/|?\n/b next
+/|?[pP]/b print
+/|?k/ s/^\([0-9]\{1,3\}\)\([.~].*|K\)[^|]*/\2\1/
+/|?i/ s/^\(-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}\)\(~.*|I\)[^|]*/\2\1/
+/|?o/ s/^\(-\{0,1\}[1-9][0-9]*\.\{0,1\}[0-9]*\)\(~.*|O\)[^|]*/\2\1/
+/|?[kio]/b pop
+/|?t/b trunc
+/|??/b input
+/|?Q/b break
+/|?q/b quit
+h
+/|?[XZz]/b count
+/|?v/b sqrt
+s/.*|?\([^Y]\).*/\1 is unimplemented/
+s/\n/\\n/g
+l
+g
+b next
+
+: print
+/^-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}~.*|?p/!b Print
+/|O10|/b Print
+
+#  Print a number in a non-decimal output base.  Uses registers a,b,c,d.
+#  Handles fractional output bases (O<-1 or O>=1), unlike other dc's.
+#  Converts the fraction correctly on negative output bases, unlike
+#  UNIX dc.  Also scales the fraction more accurately than UNIX dc.
+#
+s,|?p,&KSa0kd[[-]Psa0la-]Sad0>a[0P]sad0=a[A*2+]saOtd0>a1-ZSd[[[[ ]P]sclb1\
+!=cSbLdlbtZ[[[-]P0lb-sb]sclb0>c1+]sclb0!<c[0P1+dld>c]scdld>cscSdLbP]q]Sb\
+[t[1P1-d0<c]scd0<c]ScO_1>bO1!<cO[16]<bOX0<b[[q]sc[dSbdA>c[A]sbdA=c[B]sbd\
+B=c[C]sbdC=c[D]sbdD=c[E]sbdE=c[F]sb]xscLbP]~Sd[dtdZOZ+k1O/Tdsb[.5]*[.1]O\
+X^*dZkdXK-1+ktsc0kdSb-[Lbdlb*lc+tdSbO*-lb0!=aldx]dsaxLbsb]sad1!>a[[.]POX\
++sb1[SbO*dtdldx-LbO*dZlb!<a]dsax]sadXd0<asbsasaLasbLbscLcsdLdsdLdLak[]pP,
+b next
+
+: Print
+/|?p/s/[^~]*/&\
+~&/
+s/\(.*|P\)\([^|]*\)/\
+\2\1/
+s/\([^~]*\)\n\([^~]*\)\(.*|P\)/\1\3\2/
+h
+s/~.*//
+/./{ s/.//; p; }
+#  Just s/.//p would work if we knew we were running under the -n option.
+#  Using l vs p would kind of do \ continuations, but would break strings.
+g
+
+: pop
+s/[^~]*~//
+b next
+
+: load
+s/\(.*|?.\)\(.\)/\20~\1/
+s/^\(.\)0\(.*|r\1\([^~|]*\)~\)/\1\3\2/
+s/.//
+b next
+
+: Load
+s/\(.*|?.\)\(.\)/\2\1/
+s/^\(.\)\(.*|r\1\)\([^~|]*~\)/|\3\2/
+/^|/!i\
+register empty
+s/.//
+b next
+
+: save
+s/\(.*|?.\)\(.\)/\2\1/
+/^\(.\).*|r\1/ !s/\(.\).*|/&r\1|/
+/|?S/ s/\(.\).*|r\1/&~/
+s/\(.\)\([^~]*~\)\(.*|r\1\)[^~|]*~\{0,1\}/\3\2/
+b next
+
+: quit
+t quit
+s/|?[^~]*~[^~]*~/|?q/
+t next
+#  Really should be using the -n option to avoid printing a final newline.
+s/.*|P\([^|]*\).*/\1/
+q
+
+: break
+s/[0-9]*/&;987654321009;/
+: break1
+s/^\([^;]*\)\([1-9]\)\(0*\)\([^1]*\2\(.\)[^;]*\3\(9*\).*|?.\)[^~]*~/\1\5\6\4/
+t break1
+b pop
+
+: input
+N
+s/|??\(.*\)\(\n.*\)/|?\2~\1/
+b next
+
+: count
+/|?Z/ s/~.*//
+/^-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}$/ s/[-.0]*\([^.]*\)\.*/\1/
+/|?X/ s/-*[0-9A-F]*\.*\([0-9A-F]*\).*/\1/
+s/|.*//
+/~/ s/[^~]//g
+
+s/./a/g
+: count1
+	s/a\{10\}/b/g
+	s/b*a*/&a9876543210;/
+	s/a.\{9\}\(.\).*;/\1/
+	y/b/a/
+/a/b count1
+G
+/|?z/ s/\n/&~/
+s/\n[^~]*//
+b next
+
+: trunc
+#  for efficiency, doesn't pad with 0s, so 10k 2 5/ returns just .40
+#  The X* here and in a couple other places works around a SunOS 4.x sed bug.
+s/\([^.~]*\.*\)\(.*|K\([^|]*\)\)/\3;9876543210009909:\1,\2/
+: trunc1
+	s/^\([^;]*\)\([1-9]\)\(0*\)\([^1]*\2\(.\)[^:]*X*\3\(9*\)[^,]*\),\([0-9]\)/\1\5\6\4\7,/
+t trunc1
+s/[^:]*:\([^,]*\)[^~]*/\1/
+b normal
+
+: number
+s/\(.*|?\)\(_\{0,1\}[0-9A-F]*\.\{0,1\}[0-9A-F]*\)/\2~\1~/
+s/^_/-/
+/^[^A-F~]*~.*|I10|/b normal
+/^[-0.]*~/b normal
+s:\([^.~]*\)\.*\([^~]*\):[Ilb^lbk/,\1\2~0A1B2C3D4E5F1=11223344556677889900;.\2:
+: digit
+    s/^\([^,]*\),\(-*\)\([0-F]\)\([^;]*\(.\)\3[^1;]*\(1*\)\)/I*+\1\2\6\5~,\2\4/
+t digit
+s:...\([^/]*.\)\([^,]*\)[^.]*\(.*|?.\):\2\3KSb[99]k\1]SaSaXSbLalb0<aLakLbktLbk:
+b next
+
+: string
+/|?[^]]*$/N
+s/\(|?[^]]*\)\[\([^]]*\)]/\1|{\2|}/
+/|?\[/b string
+s/\(.*|?\)|{\(.*\)|}/\2~\1[/
+s/|{/[/g
+s/|}/]/g
+b next
+
+: binop
+/^[^~|]*~[^|]/ !i\
+stack empty
+//!b next
+/^-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}~/ !s/[^~]*\(.*|?!*[^!=<>]\)/0\1/
+/^[^~]*~-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}~/ !s/~[^~]*\(.*|?!*[^!=<>]\)/~0\1/
+h
+/|?\*/b mul
+/|?\//b div
+/|?%/b rem
+/|?^/b exp
+
+/|?[+-]/ s/^\(-*\)\([^~]*~\)\(-*\)\([^~]*~\).*|?\(-\{0,1\}\).*/\2\4s\3o\1\3\5/
+s/\([^.~]*\)\([^~]*~[^.~]*\)\(.*\)/<\1,\2,\3|=-~.0,123456789<></
+/^<\([^,]*,[^~]*\)\.*0*~\1\.*0*~/ s/</=/
+: cmp1
+	s/^\(<[^,]*\)\([0-9]\),\([^,]*\)\([0-9]\),/\1,\2\3,\4/
+t cmp1
+/^<\([^~]*\)\([^~]\)[^~]*~\1\(.\).*|=.*\3.*\2/ s/</>/
+/|?/{
+	s/^\([<>]\)\(-[^~]*~-.*\1\)\(.\)/\3\2/
+	s/^\(.\)\(.*|?!*\)\1/\2!\1/
+	s/|?![^!]\(.\)/&l\1x/
+	s/[^~]*~[^~]*~\(.*|?\)!*.\(.*\)|=.*/\1\2/
+	b next
+}
+s/\(-*\)\1|=.*/;9876543210;9876543210/
+/o-/ s/;9876543210/;0123456789/
+s/^>\([^~]*~\)\([^~]*~\)s\(-*\)\(-*o\3\(-*\)\)/>\2\1s\5\4/
+
+s/,\([0-9]*\)\.*\([^,]*\),\([0-9]*\)\.*\([0-9]*\)/\1,\2\3.,\4;0/
+: right1
+	s/,\([0-9]\)\([^,]*\),;*\([0-9]\)\([0-9]*\);*0*/\1,\2\3,\4;0/
+t right1
+s/.\([^,]*\),~\(.*\);0~s\(-*\)o-*/\1~\30\2~/
+
+: addsub1
+	s/\(.\{0,1\}\)\(~[^,]*\)\([0-9]\)\(\.*\),\([^;]*\)\(;\([^;]*\(\3[^;]*\)\).*X*\1\(.*\)\)/\2,\4\5\9\8\7\6/
+	s/,\([^~]*~\).\{10\}\(.\)[^;]\{0,9\}\([^;]\{0,1\}\)[^;]*/,\2\1\3/
+#	  could be done in one s/// if we could have >9 back-refs...
+/^~.*~;/!b addsub1
+
+: endbin
+s/.\([^,]*\),\([0-9.]*\).*/\1\2/
+G
+s/\n[^~]*~[^~]*//
+
+: normal
+s/^\(-*\)0*\([0-9.]*[0-9]\)[^~]*/\1\2/
+s/^[^1-9~]*~/0~/
+b next
+
+: mul
+s/\(-*\)\([0-9]*\)\.*\([0-9]*\)~\(-*\)\([0-9]*\)\.*\([0-9]*\).*|K\([^|]*\).*/\1\4\2\5.!\3\6,|\2<\3~\5>\6:\7;9876543210009909/
+
+: mul1
+    s/![0-9]\([^<]*\)<\([0-9]\{0,1\}\)\([^>]*\)>\([0-9]\{0,1\}\)/0!\1\2<\3\4>/
+    /![0-9]/ s/\(:[^;]*\)\([1-9]\)\(0*\)\([^0]*\2\(.\).*X*\3\(9*\)\)/\1\5\6\4/
+/<~[^>]*>:0*;/!t mul1
+
+s/\(-*\)\1\([^>]*\).*/;\2^>:9876543210aaaaaaaaa/
+
+: mul2
+    s/\([0-9]~*\)^/^\1/
+    s/<\([0-9]*\)\(.*[~^]\)\([0-9]*\)>/\1<\2>\3/
+
+    : mul3
+	s/>\([0-9]\)\(.*\1.\{9\}\(a*\)\)/\1>\2;9\38\37\36\35\34\33\32\31\30/
+	s/\(;[^<]*\)\([0-9]\)<\([^;]*\).*\2[0-9]*\(.*\)/\4\1<\2\3/
+	s/a[0-9]/a/g
+	s/a\{10\}/b/g
+	s/b\{10\}/c/g
+    /|0*[1-9][^>]*>0*[1-9]/b mul3
+
+    s/;/a9876543210;/
+    s/a.\{9\}\(.\)[^;]*\([^,]*\)[0-9]\([.!]*\),/\2,\1\3/
+    y/cb/ba/
+/|<^/!b mul2
+b endbin
+
+: div
+#  CDDET
+/^[-.0]*[1-9]/ !i\
+divide by 0
+//!b pop
+s/\(-*\)\([0-9]*\)\.*\([^~]*~-*\)\([0-9]*\)\.*\([^~]*\)/\2.\3\1;0\4.\5;0/
+: div1
+	s/^\.0\([^.]*\)\.;*\([0-9]\)\([0-9]*\);*0*/.\1\2.\3;0/
+	s/^\([^.]*\)\([0-9]\)\.\([^;]*;\)0*\([0-9]*\)\([0-9]\)\./\1.\2\30\4.\5/
+t div1
+s/~\(-*\)\1\(-*\);0*\([^;]*[0-9]\)[^~]*/~123456789743222111~\2\3/
+s/\(.\(.\)[^~]*\)[^9]*\2.\{8\}\(.\)[^~]*/\3~\1/
+s,|?.,&SaSadSaKdlaZ+LaX-1+[sb1]Sbd1>bkLatsbLa[dSa2lbla*-*dLa!=a]dSaxsakLasbLb*t,
+b next
+
+: rem
+s,|?%,&Sadla/LaKSa[999]k*Lak-,
+b next
+
+: exp
+#  This decimal method is just a little faster than the binary method done
+#  totally in dc:  1LaKLb [kdSb*LbK]Sb [[.5]*d0ktdSa<bkd*KLad1<a]Sa d1<a kk*
+/^[^~]*\./i\
+fraction in exponent ignored
+s,[^-0-9].*,;9d**dd*8*d*d7dd**d*6d**d5d*d*4*d3d*2lbd**1lb*0,
+: exp1
+	s/\([0-9]\);\(.*\1\([d*]*\)[^l]*\([^*]*\)\(\**\)\)/;dd*d**d*\4\3\5\2/
+t exp1
+G
+s,-*.\{9\}\([^9]*\)[^0]*0.\(.*|?.\),\2~saSaKdsaLb0kLbkK*+k1\1LaktsbkLax,
+s,|?.,&SadSbdXSaZla-SbKLaLadSb[0Lb-d1lb-*d+K+0kkSb[1Lb/]q]Sa0>a[dk]sadK<a[Lb],
+b next
+
+: sqrt
+#  first square root using sed:  8k2v at 1:30am Dec 17, 1996
+/^-/i\
+square root of negative number
+/^[-0]/b next
+s/~.*//
+/^\./ s/0\([0-9]\)/\1/g
+/^\./ !s/[0-9][0-9]/7/g
+G
+s/\n/~/
+s,|?.,&K1+k KSbSb[dk]SadXdK<asadlb/lb+[.5]*[sbdlb/lb+[.5]*dlb>a]dsaxsasaLbsaLatLbk K1-kt,
+b next
+
+#  END OF GSU dc.sed
Index: /tags/kBuild-0.1.4/src/sed/testsuite/distrib.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/distrib.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/distrib.good	(revision 1780)
@@ -0,0 +1,29 @@
+Path: mailnewsgateway
+From crash@cygnus.com  Wed Mar  8 18: 02:42 1995
+From: crash@cygnus.com (Jason Molenda)
+Message-ID: <9503090202.AA06931.alt.buddha.fat.short.guy@phydeaux.cygnus.com>
+Subject: Note for sed testsuite
+Original-To: molenda@msi.umn.edu
+Date: Wed, 8 Mar 1995 18:02:24 -0800 (PST)
+X-Mailer: ELM [version 2.4 PL23]
+Newsgroups: alt.buddha.short.fat.guy
+Distribution: world
+Sender: news@cygnus.com
+Approved: alt.buddha.short.fat.guy@cygnus.com
+
+                _Summum Bonum_
+
+    All the breath and the bloom of the
+            year in the bag of one bee:
+    All the wonder and wealth of the mine in
+         the heart of one gem:
+    In the core of one pearl all the shade and the
+           shine of the sea:
+    Breath and bloom, shade and shine, -- wonder,
+        wealth, and -- how far above them --
+          Truth, thats brighter than gem,
+          Trust, that's purer than pearl, --
+    Brightest truth, purest trust in the universe --
+              all were for me
+                 In the kiss of one girl.
+        -- Robert Browning
Index: /tags/kBuild-0.1.4/src/sed/testsuite/distrib.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/distrib.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/distrib.inp	(revision 1780)
@@ -0,0 +1,28 @@
+From crash@cygnus.com  Wed Mar  8 18:02:42 1995
+Received: from s1.msi.umn.edu (s1.msi.umn.edu [128.101.24.1]) by cygnus.com (8.6.9/8.6.9) with ESMTP id SAA21692 for <crash@cygnus.com>; Wed, 8 Mar 1995 18:02:41 -0800
+Received: from cygint.cygnus.com (cygint.cygnus.com [140.174.1.1]) by s1.msi.umn.edu (8.6.10/8.6.9) with ESMTP id TAA13398 for <molenda@msi.umn.edu>; Wed, 8 Mar 1995 19:59:18 -0600
+Received: from phydeaux.cygnus.com (phydeaux.cygnus.com [140.174.1.85]) by cygnus.com (8.6.9/8.6.9) with SMTP id SAA21688 for <molenda@msi.umn.edu>; Wed, 8 Mar 1995 18:02:33 -0800
+From: Jason Molenda <crash@cygnus.com>
+Received: by phydeaux.cygnus.com (5.65/4.7) id AA06931; Wed, 8 Mar 1995 18:02:28 -0800
+Message-Id: <9503090202.AA06931@phydeaux.cygnus.com>
+Subject: Note for sed testsuite
+To: molenda@msi.umn.edu
+Date: Wed, 8 Mar 1995 18:02:24 -0800 (PST)
+X-Mailer: ELM [version 2.4 PL23]
+
+                _Summum Bonum_
+
+    All the breath and the bloom of the
+            year in the bag of one bee:
+    All the wonder and wealth of the mine in
+         the heart of one gem:
+    In the core of one pearl all the shade and the
+           shine of the sea:
+    Breath and bloom, shade and shine, -- wonder,
+        wealth, and -- how far above them --
+          Truth, thats brighter than gem,
+          Trust, that's purer than pearl, --
+    Brightest truth, purest trust in the universe --
+              all were for me
+                 In the kiss of one girl.
+        -- Robert Browning
Index: /tags/kBuild-0.1.4/src/sed/testsuite/distrib.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/distrib.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/distrib.sed	(revision 1780)
@@ -0,0 +1,56 @@
+#   This is straight out of C News
+#
+#
+# All this does is massage the headers so they look like what news
+# software expects.  To:, Cc: and Resent-*: headers are masked.
+# Reply-To: is turned into references, which is questionable (could
+# just as well be dropped.
+#
+# The From: line is rewritten to use the "address (comments)" form
+# instead of "phrase <route>" form our mailer uses.  Also, addresses
+# with no "@domainname" are assumed to originate locally, and so are
+# given a domain.
+#
+# The Sender: field below reflects the address of the person who
+# maintains our mailing lists.  The Approved: field is in a special
+# form, so that we can do bidirectional gatewaying.  Any message
+# in a newsgroup that bears this stamp will not be fed into the
+# matching mailing list.
+
+1i\
+Path: mailnewsgateway
+	:a
+	/^[Rr]eceived:/b r
+	/^[Nn]ewsgroups:/b r
+	/^[Pp]ath:/b r
+	/^[Tt][Oo]:/s/^/Original-/
+	/^[Cc][Cc]:/s/^/Original-/
+	/^[Rr][Ee][Ss][Ee][Nn][Tt]-.*/s/^/Original-/
+	/^[Mm][Ee][Ss][Ss][Aa][Gg][Ee]-[Ii][Dd]:/s/@/.alt.buddha.fat.short.guy@/
+	s/^[Ii]n-[Rr]eply-[Tt]o:/References:/
+	/^From:/{
+		s/<\([^@]*\)>$/<\1@$thissite>/
+		s/^From:[ 	][	]*\(.*\)  *<\(.*\)>$/From: \2 (\1)/
+		}
+	s/-[Ii]d:/-ID:/
+	s/^[Ss][Uu][Bb][Jj][Ee][Cc][Tt]:[ 	]*$/Subject: (none)/
+	s/^\([^:]*:\)[	 ]*/\1 /
+	/^$/{i\
+Newsgroups: alt.buddha.short.fat.guy\
+Distribution: world\
+Sender: news@cygnus.com\
+Approved: alt.buddha.short.fat.guy@cygnus.com
+	b e
+	}
+	p
+	n
+	b a
+	:r
+	s/.*//g
+	n
+	/^[ 	]/b r
+	b a
+	:e
+	p
+	n
+	b e
Index: /tags/kBuild-0.1.4/src/sed/testsuite/distrib.sh
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/distrib.sh	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/distrib.sh	(revision 1780)
@@ -0,0 +1,63 @@
+#! /bin/sh
+#
+#   This is stolen from C News
+# 
+
+
+#
+# All this does is massage the headers so they look like what news
+# software expects.  To:, Cc: and Resent-*: headers are masked.
+# Reply-To: is turned into references, which is questionable (could
+# just as well be dropped.
+#
+# The From: line is rewritten to use the "address (comments)" form
+# instead of "phrase <route>" form our mailer uses.  Also, addresses
+# with no "@domainname" are assumed to originate locally, and so are
+# given a domain.
+#
+# The Sender: field below reflects the address of the person who
+# maintains our mailing lists.  The Approved: field is in a special
+# form, so that we can do bidirectional gatewaying.  Any message
+# in a newsgroup that bears this stamp will not be fed into the
+# matching mailing list.
+
+sed=${1-sed}
+
+$sed -n -e "1{i\\
+Path: mailnewsgateway
+	}" \
+    -e ":a
+	/^[Rr]eceived:/b r
+	/^[Nn]ewsgroups:/b r
+	/^[Pp]ath:/b r
+	/^[Tt][Oo]:/s/^/Original-/
+	/^[Cc][Cc]:/s/^/Original-/
+	/^[Rr][Ee][Ss][Ee][Nn][Tt]-.*/s/^/Original-/
+	/^[Mm][Ee][Ss][Ss][Aa][Gg][Ee]-[Ii][Dd]:/s/@/.alt.buddha.fat.short.guy@/
+	s/^[Ii]n-[Rr]eply-[Tt]o:/References:/
+	/^From:/{
+		s/<\([^@]*\)>\$/<\1@$thissite>/
+		s/^From:[ 	][	]*\(.*\)  *<\(.*\)>\$/From: \2 (\1)/
+		}
+	s/-[Ii]d:/-ID:/
+	s/^[Ss][Uu][Bb][Jj][Ee][Cc][Tt]:[ 	]*$/Subject: (none)/
+	s/^\([^:]*:\)[	 ]*/\1 /
+	/^\$/{i\\
+Newsgroups: alt.buddha.short.fat.guy\\
+Distribution: world\\
+Sender: news@cygnus.com\\
+Approved: alt.buddha.short.fat.guy@cygnus.com
+	b e
+	}
+	p
+	n
+	b a
+	:r
+	s/.*//g
+	n
+	/^[ 	]/b r
+	b a
+	:e
+	p
+	n
+	b e"
Index: /tags/kBuild-0.1.4/src/sed/testsuite/dollar.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/dollar.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/dollar.good	(revision 1780)
@@ -0,0 +1,4 @@
+I can't quite remember where I heard it,
+but I can't seem to get out of my head
+the phrase
+space the final frontier
Index: /tags/kBuild-0.1.4/src/sed/testsuite/dollar.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/dollar.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/dollar.inp	(revision 1780)
@@ -0,0 +1,4 @@
+I can't quite remember where I heard it,
+but I can't seem to get out of my head
+the phrase
+the final frontier
Index: /tags/kBuild-0.1.4/src/sed/testsuite/dollar.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/dollar.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/dollar.sed	(revision 1780)
@@ -0,0 +1,1 @@
+$s/^/space /
Index: /tags/kBuild-0.1.4/src/sed/testsuite/empty.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/empty.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/empty.good	(revision 1780)
@@ -0,0 +1,2 @@
+x
+
Index: /tags/kBuild-0.1.4/src/sed/testsuite/empty.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/empty.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/empty.inp	(revision 1780)
@@ -0,0 +1,2 @@
+x
+
Index: /tags/kBuild-0.1.4/src/sed/testsuite/empty.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/empty.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/empty.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/^ *//
Index: /tags/kBuild-0.1.4/src/sed/testsuite/enable.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/enable.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/enable.good	(revision 1780)
@@ -0,0 +1,3 @@
+targets
+x11-testing
+wollybears-in-minnesota
Index: /tags/kBuild-0.1.4/src/sed/testsuite/enable.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/enable.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/enable.inp	(revision 1780)
@@ -0,0 +1,3 @@
+--enable-targets=sparc-sun-sunos4.1.3,srec
+--enable-x11-testing=on
+--enable-wollybears-in-minnesota=yes-id-like-that
Index: /tags/kBuild-0.1.4/src/sed/testsuite/enable.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/enable.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/enable.sed	(revision 1780)
@@ -0,0 +1,2 @@
+# inspired by an autoconf generated configure script.
+s/-*enable-//;s/=.*//
Index: /tags/kBuild-0.1.4/src/sed/testsuite/eval.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/eval.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/eval.good	(revision 1780)
@@ -0,0 +1,40 @@
+abcd
+---
+abcd
+---
+abcd
+---
+17380: 2 2 5 11 79
+cpu
+---
+17380: 2 2 5 11 79
+cpu
+---
+17380: 2 2 5 11 79
+cpu
+---
+  abcd  
+---
+  abcd  
+---
+  abcd  
+---
+17380: 2 2 5 11 79
+  cpu  
+---
+17380: 2 2 5 11 79
+  cpu  
+---
+17380: 2 2 5 11 79
+  cpu  
+---
+Doing some more tests -----------------------
+17380: 2 2 5 11 79
+---
+../sed/sed 1q eval.in2
+---
+17380: 2 2 5 11 79
+---
+../sed/sed 1q eval.in2
+---
+../sed/sed 1q eval.in2
Index: /tags/kBuild-0.1.4/src/sed/testsuite/eval.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/eval.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/eval.inp	(revision 1780)
@@ -0,0 +1,5 @@
+17380: 2 2 5 11 79
+abcd
+cpu
+  abcd  
+  cpu  
Index: /tags/kBuild-0.1.4/src/sed/testsuite/eval.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/eval.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/eval.sed	(revision 1780)
@@ -0,0 +1,46 @@
+1d
+
+	#Try eval command
+	/cpu/!b2
+	e../sed/sed 1q eval.in2
+
+:2
+p
+i---
+h
+
+	#Try eval option
+	s,.* *cpu *,../sed/sed 1q eval.in2; echo "&",e
+
+:3
+p
+g
+i---
+
+	h
+	#Try eval option with print
+	s,.* *cpu.*,../sed/sed 1q eval.in2,ep
+	g
+
+
+:4
+p
+i---
+
+$!d
+
+#Do some more tests
+s/.*/Doing some more tests -----------------------/p
+s,.*,../sed/sed 1q eval.in2,ep
+i---
+s,.*,../sed/sed 1q eval.in2,pe
+i---
+s,.*,../sed/sed 1q eval.in2,
+h
+e
+p
+g
+i---
+s/^/echo /ep
+i---
+s/^fubar$/echo wozthis/e
Index: /tags/kBuild-0.1.4/src/sed/testsuite/factor.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/factor.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/factor.good	(revision 1780)
@@ -0,0 +1,15 @@
+2
+3
+2
+2
+5
+2
+2
+2
+11
+2
+2
+2
+2
+13
+11
Index: /tags/kBuild-0.1.4/src/sed/testsuite/factor.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/factor.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/factor.inp	(revision 1780)
@@ -0,0 +1,8 @@
+2
+3
+4
+5
+8
+11
+16
+143
Index: /tags/kBuild-0.1.4/src/sed/testsuite/factor.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/factor.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/factor.sed	(revision 1780)
@@ -0,0 +1,76 @@
+#! /bin/sed -nf
+
+s/.*/&;9aaaaaaaaa8aaaaaaaa7aaaaaaa6aaaaaa5aaaaa4aaaa3aaa2aa1a0/
+:encode
+s/\(a*\)\([0-9]\)\([0-9]*;.*\2\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4\3/
+tencode
+s/;.*//
+
+# Compute a few common factors for speed.  Clear the subst flag
+t7a
+
+# These are placed here to make the flow harder to understand :-)
+:2
+a\
+2
+b2a
+:3
+a\
+3
+b3a
+:5
+a\
+5
+b5a
+:7
+a\
+7
+
+:7a
+s/^\(aa*\)\1\{6\}$/\1/
+t7
+:5a
+s/^\(aa*\)\1\{4\}$/\1/
+t5
+:3a
+s/^\(aa*\)\1\1$/\1/
+t3
+:2a
+s/^\(aa*\)\1$/\1/
+t2
+
+/^a$/b
+
+# The quotient of dividing by 11 is a limit to the remaining prime factors
+s/^\(aa*\)\1\{10\}/\1=&/
+
+# Pattern space looks like CANDIDATE\nNUMBER.  When a candidate is valid,
+# the number is divided and the candidate is tried again
+:factor
+/^\(a\{7,\}\)=\1\1*$/! {
+  # Decrement CANDIDATE, and search again if it is still >1
+  s/^a//
+  /^aa/b factor
+
+  # Print the last remaining factor: since it is stored in the NUMBER
+  # rather than in the CANDIDATE, swap 'em: now NUMBER=1
+  s/\(.*\)=\(.*\)/\2=\1/
+}
+
+# We have a prime factor in CANDIDATE! Print it
+h
+s/=.*/;;0a1aa2aaa3aaaa4aaaaa5aaaaaa6aaaaaaa7aaaaaaaa8aaaaaaaaa9/
+
+:decode
+s/^\(a*\)\1\{9\}\(a\{0,9\}\)\([0-9]*;.*[^a]\2\([0-9]\)\)/\1\4\3/
+/^a/tdecode
+s/;.*//p
+
+g
+:divide
+s/^\(a*\)\(=b*\)\1/\1\2b/
+tdivide
+y/b/a/
+
+# If NUMBER = 1, we don't have any more factors
+/aa$/bfactor
Index: /tags/kBuild-0.1.4/src/sed/testsuite/fasts.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/fasts.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/fasts.good	(revision 1780)
@@ -0,0 +1,14 @@
+aaaaaabbbbbbaaaaaaa
+bbbbbb
+aaaaaabbbbbbaaaaaaa
+aaaaaabbbbbbaaaaaaa
+aaaaaaabbbbbbaaaaaaa
+aaaaaabbbbbbaaaaaaa
+aaaaaaabbbbbbaaaaaa
+bbbbbbbbbbbbbbbbbbb
+
+bbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbb
Index: /tags/kBuild-0.1.4/src/sed/testsuite/fasts.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/fasts.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/fasts.inp	(revision 1780)
@@ -0,0 +1,1 @@
+aaaaaaabbbbbbaaaaaaa
Index: /tags/kBuild-0.1.4/src/sed/testsuite/fasts.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/fasts.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/fasts.sed	(revision 1780)
@@ -0,0 +1,46 @@
+# test `fast' substitutions
+
+h
+s/a//
+p
+g
+s/a//g
+p
+g
+s/^a//p
+g
+s/^a//g
+p
+g
+s/not present//g
+p
+g
+s/^[a-z]//g
+p
+g
+s/a$//
+p
+g
+
+y/a/b/
+h
+s/b//
+p
+g
+s/b//g
+p
+g
+s/^b//p
+g
+s/^b//g
+p
+g
+s/^[a-z]//g
+p
+g
+s/b$//
+p
+g
+
+
+
Index: /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.good	(revision 1780)
@@ -0,0 +1,25 @@
+09 - 02 - 2002 00.00 Tg La7 La7 -
+09 - 02 - 2002 00.00 Brand New Tmc 2 -
+09 - 02 - 2002 00.10 Tg1 Notte Rai Uno -
+09 - 02 - 2002 00.15 Tg Parlamento Rai Due -
+09 - 02 - 2002 00.15 Kung Fu - La Leggenda Continua La7 -
+09 - 02 - 2002 00.20 Berserk - La Confessione Di Gatz Italia 1 Cartoon
+09 - 02 - 2002 00.20 Tg3 - Tg3 Meteo Rai Tre -
+09 - 02 - 2002 00.25 Meteo 2 Rai Due -
+09 - 02 - 2002 00.30 Appuntamento Al Cinema Rai Due -
+09 - 02 - 2002 00.30 Rai Educational - Mediamente Rai Tre -
+09 - 02 - 2002 00.35 Profiler Rai Due -
+09 - 02 - 2002 00.35 Stampa Oggi - Che Tempo Fa Rai Uno -
+09 - 02 - 2002 00.45 Rai Educational - Babele: Euro Rai Uno -
+09 - 02 - 2002 00.45 Bollettino Della Neve Rete 4 News
+09 - 02 - 2002 00.50 Studio Aperto - La Giornata Italia 1 News
+09 - 02 - 2002 00.50 Bocca A Bocca - 2 Tempo Rete 4 Film
+09 - 02 - 2002 01.00 Appuntamento Al Cinema Rai Tre -
+09 - 02 - 2002 01.00 Music Non Stop Tmc 2 -
+09 - 02 - 2002 01.00 Studio Sport Italia 1 Sport
+09 - 02 - 2002 01.00 Tg 5 - Notte Canale 5 News
+09 - 02 - 2002 01.05 Fuori Orario. Cose (Mai) Viste Rai Tre -
+09 - 02 - 2002 01.15 Rainotte Rai Due -
+09 - 02 - 2002 01.15 Sottovoce Rai Uno -
+09 - 02 - 2002 01.15 Giochi Olimpici Invernali - Cerimonia Di Apertura Rai Tre -
+09 - 02 - 2002 01.17 Italia Interroga Rai Due -
Index: /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.inp	(revision 1780)
@@ -0,0 +1,25 @@
+09 - 02 - 2002 00.00 Tg La7 La7 -
+09 - 02 - 2002 00.00 Brand New Tmc 2 -
+09 - 02 - 2002 00.10 Tg1 Notte Rai Uno -
+09 - 02 - 2002 00.15 Tg Parlamento Rai Due -
+09 - 02 - 2002 00.15 Kung Fu - La Leggenda Continua La7 -
+09 - 02 - 2002 00.20 Berserk - La CoNFESSIONE Di Gatz Italia 1 Cartoon
+09 - 02 - 2002 00.20 Tg3 - Tg3 Meteo Rai TrE -
+09 - 02 - 2002 00.25 Meteo 2 Rai Due -
+09 - 02 - 2002 00.30 Appuntamento Al CinEMA RaI Due -
+09 - 02 - 2002 00.30 Rai Educational - Mediamente Rai Tre -
+09 - 02 - 2002 00.35 Profiler Rai Due -
+09 - 02 - 2002 00.35 Stampa OggI - Che Tempo Fa Rai Uno -
+09 - 02 - 2002 00.45 Rai Educational - Babele: Euro Rai Uno -
+09 - 02 - 2002 00.45 BollettINO Della NEVE RETE 4 News
+09 - 02 - 2002 00.50 STUDIO Aperto - La Giornata Italia 1 News
+09 - 02 - 2002 00.50 BOCCA A Bocca - 2 Tempo Rete 4 Film
+09 - 02 - 2002 01.00 AppuntAMENTO Al Cinema Rai Tre -
+09 - 02 - 2002 01.00 Music NoN Stop Tmc 2 -
+09 - 02 - 2002 01.00 Studio SpORT Italia 1 SporT
+09 - 02 - 2002 01.00 Tg 5 - Notte Canale 5 News
+09 - 02 - 2002 01.05 Fuori Orario. CosE (Mai) Viste Rai Tre -
+09 - 02 - 2002 01.15 RAINOTTE Rai Due -
+09 - 02 - 2002 01.15 Sottovoce Rai Uno -
+09 - 02 - 2002 01.15 GiOCHI Olimpici InVERNALI - CERIMONIA Di Apertura Rai Tre -
+09 - 02 - 2002 01.17 Italia Interroga Rai Due -
Index: /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/flipcase.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s,\([^A-Za-z]*\)\([A-Za-z]*\),\1\L\u\2,g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/head.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/head.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/head.good	(revision 1780)
@@ -0,0 +1,3 @@
+   "...by imposing a tiny bit of order in a communication you are
+   translating, you are carving out a little bit of order in the
+   universe.  You will never succeed.  Everything will fail and come
Index: /tags/kBuild-0.1.4/src/sed/testsuite/head.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/head.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/head.inp	(revision 1780)
@@ -0,0 +1,9 @@
+   "...by imposing a tiny bit of order in a communication you are
+   translating, you are carving out a little bit of order in the
+   universe.  You will never succeed.  Everything will fail and come
+   to an end finally.  But you have a chance to carve a little bit
+   of order and maybe even beauty out of the raw materials that
+   surround you everywhere, and I think there is no greater meaning
+   in life."
+
+             Donald L. Philippi, Oct 1930 - Jan 1993
Index: /tags/kBuild-0.1.4/src/sed/testsuite/head.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/head.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/head.sed	(revision 1780)
@@ -0,0 +1,1 @@
+3q
Index: /tags/kBuild-0.1.4/src/sed/testsuite/inclib.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/inclib.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/inclib.good	(revision 1780)
@@ -0,0 +1,34 @@
+	/usr/X11R6/include        
+	/usr/X11R5/include        
+	/usr/X11R4/include        
+	
+	/usr/include/X11R6        
+	/usr/include/X11R5        
+	/usr/include/X11R4        
+	
+	/usr/local/X11R6/include  
+	/usr/local/X11R5/include  
+	/usr/local/X11R4/include  
+	
+	/usr/local/include/X11R6  
+	/usr/local/include/X11R5  
+	/usr/local/include/X11R4  
+	
+	/usr/X11/include          
+	/usr/include/X11          
+	/usr/local/X11/include    
+	/usr/local/include/X11    
+	
+	/usr/X386/include         
+	/usr/x386/include         
+	/usr/XFree86/include/X11  
+	
+	/usr/include              
+	/usr/local/include        
+	/usr/unsupported/include  
+	/usr/athena/include       
+	/usr/local/x11r5/include  
+	/usr/lpp/Xamples/include  
+	
+	/usr/openwin/include      
+	/usr/openwin/share/include 
Index: /tags/kBuild-0.1.4/src/sed/testsuite/inclib.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/inclib.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/inclib.inp	(revision 1780)
@@ -0,0 +1,34 @@
+	/usr/X11R6/lib        
+	/usr/X11R5/lib        
+	/usr/X11R4/lib        
+	
+	/usr/lib/X11R6        
+	/usr/lib/X11R5        
+	/usr/lib/X11R4        
+	
+	/usr/local/X11R6/lib  
+	/usr/local/X11R5/lib  
+	/usr/local/X11R4/lib  
+	
+	/usr/local/lib/X11R6  
+	/usr/local/lib/X11R5  
+	/usr/local/lib/X11R4  
+	
+	/usr/X11/lib          
+	/usr/lib/X11          
+	/usr/local/X11/lib    
+	/usr/local/lib/X11    
+	
+	/usr/X386/lib         
+	/usr/x386/lib         
+	/usr/XFree86/lib/X11  
+	
+	/usr/lib              
+	/usr/local/lib        
+	/usr/unsupported/lib  
+	/usr/athena/lib       
+	/usr/local/x11r5/lib  
+	/usr/lpp/Xamples/lib  
+	
+	/usr/openwin/lib      
+	/usr/openwin/share/lib 
Index: /tags/kBuild-0.1.4/src/sed/testsuite/inclib.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/inclib.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/inclib.sed	(revision 1780)
@@ -0,0 +1,2 @@
+# inspired by an autoconf generated configure script.
+s;lib;include;
Index: /tags/kBuild-0.1.4/src/sed/testsuite/insens.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/insens.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/insens.good	(revision 1780)
@@ -0,0 +1,2 @@
+1.2.3
+1.2.3
Index: /tags/kBuild-0.1.4/src/sed/testsuite/insens.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/insens.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/insens.inp	(revision 1780)
@@ -0,0 +1,1 @@
+Version: 1.2.3
Index: /tags/kBuild-0.1.4/src/sed/testsuite/insens.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/insens.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/insens.sed	(revision 1780)
@@ -0,0 +1,4 @@
+h
+s/Version: *//p
+g
+s/version: *//Ip
Index: /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.good	(revision 1780)
@@ -0,0 +1,32 @@
+1)  Muammar Qaddafi
+2)  Mo'ammar Gadhafi
+3)  Muammar Kaddafi
+4)  Muammar Qadhafi
+5)  Moammar El Kadhafi
+6)  Muammar Gadafi
+7)  Mu'ammar al-Qadafi
+8)  Moamer El Kazzafi
+9)  Moamar al-Gaddafi
+10) Mu'ammar Al Qathafi
+11) Muammar Al Qathafi
+12) Mo'ammar el-Gadhafi
+13) Moamar El Kadhafi
+14) Muammar al-Qadhafi
+15) Mu'ammar al-Qadhdhafi
+16) Mu'ammar Qadafi
+17) Moamar Gaddafi
+18) Mu'ammar Qadhdhafi
+19) Muammar Khaddafi
+20) Muammar al-Khaddafi
+21) Mu'amar al-Kadafi
+22) Muammar Ghaddafy
+23) Muammar Ghadafi
+24) Muammar Ghaddafi
+25) Muamar Kaddafi
+26) Muammar Quathafi
+27) Muammar Gheddafi
+28) Muamar Al-Kaddafi
+29) Moammar Khadafy 
+30) Moammar Qudhafi
+31) Mu'ammar al-Qaddafi
+32) Mulazim Awwal Mu'ammar Muhammad Abu Minyar al-Qadhafi
Index: /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.inp	(revision 1780)
@@ -0,0 +1,32 @@
+1)  Muammar Qaddafi
+2)  Mo'ammar Gadhafi
+3)  Muammar Kaddafi
+4)  Muammar Qadhafi
+5)  Moammar El Kadhafi
+6)  Muammar Gadafi
+7)  Mu'ammar al-Qadafi
+8)  Moamer El Kazzafi
+9)  Moamar al-Gaddafi
+10) Mu'ammar Al Qathafi
+11) Muammar Al Qathafi
+12) Mo'ammar el-Gadhafi
+13) Moamar El Kadhafi
+14) Muammar al-Qadhafi
+15) Mu'ammar al-Qadhdhafi
+16) Mu'ammar Qadafi
+17) Moamar Gaddafi
+18) Mu'ammar Qadhdhafi
+19) Muammar Khaddafi
+20) Muammar al-Khaddafi
+21) Mu'amar al-Kadafi
+22) Muammar Ghaddafy
+23) Muammar Ghadafi
+24) Muammar Ghaddafi
+25) Muamar Kaddafi
+26) Muammar Quathafi
+27) Muammar Gheddafi
+28) Muamar Al-Kaddafi
+29) Moammar Khadafy 
+30) Moammar Qudhafi
+31) Mu'ammar al-Qaddafi
+32) Mulazim Awwal Mu'ammar Muhammad Abu Minyar al-Qadhafi
Index: /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/khadafy.sed	(revision 1780)
@@ -0,0 +1,2 @@
+# The Khadafy test is brought to you by Scott Anderson . . .
+/M[ou]'\{0,1\}am\{1,2\}[ae]r .*\([AEae]l[- ]\)\{0,1\}[GKQ]h\{0,1\}[aeu]\{1,\}\([dtz][dhz]\{0,1\}\)\{1,\}af[iy]/!d
Index: /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.good	(revision 1780)
@@ -0,0 +1,110 @@
+1
+A dialogue on poverty
+2
+
+3
+        On the night when the rain beats,
+4
+        Driven by the wind,
+5
+        On the night when the snowflakes mingle
+6
+        With a sleety rain,
+7
+        I feel so helplessly cold.
+8
+        I nibble at a lump of salt,
+9
+        Sip the hot, oft-diluted dregs of _sake_;
+10
+        And coughing, snuffling,
+11
+        And stroking my scanty beard,
+12
+        I say in my pride,
+13
+        "There's none worthy, save I!"
+14
+        But I shiver still with cold.
+15
+        I pull up my hempen bedclothes,
+16
+        Wear what few sleeveless clothes I have,
+17
+        But cold and bitter is the night!
+18
+        As for those poorer than myself,        
+19
+        Their parents must be cold and hungry,
+20
+        Their wives and children beg and cry.
+21
+        Then, how do you struggle through life?
+22
+        
+23
+        Wide as they call the heaven and earth,
+24
+        For me they have shrunk quite small;
+25
+        Bright though they call the sun and moon,
+26
+        They never shine for me.
+27
+        Is it the same with all men,
+28
+        Or for me alone?
+29
+        By rare chance I was born a man
+30
+        And no meaner than my fellows,
+31
+        But, wearing unwadded sleeveless clothes
+32
+        In tatters, like weeds waving in the sea,
+33
+        Hanging from my shoulders,
+34
+        And under the sunken roof,
+35
+        Within the leaning walls,
+36
+        Here I lie on straw
+37
+        Spread on bare earth,
+38
+        With my parents at my pillow,
+39
+        And my wife and children at my feet,
+40
+        All huddled in grief and tears.
+41
+        No fire sends up smoke
+42
+        At the cooking-place,
+43
+        And in the cauldron
+44
+        A spider spins its web.
+45
+        With not a grain to cook,
+46
+        We moan like the night thrush.
+47
+        Then, "to cut," as the saying is,
+48
+        "The ends of what is already too short,"
+49
+        The village headman comes,
+50
+        With rod in hand, to our sleeping place,
+51
+        Growling for his dues.
+52
+        Must it be so hopeless --
+53
+        The way of this world?
+54
+
+55
+        -- Yamanoue Okura
Index: /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.inp	(revision 1780)
@@ -0,0 +1,55 @@
+A dialogue on poverty
+
+        On the night when the rain beats,
+        Driven by the wind,
+        On the night when the snowflakes mingle
+        With a sleety rain,
+        I feel so helplessly cold.
+        I nibble at a lump of salt,
+        Sip the hot, oft-diluted dregs of _sake_;
+        And coughing, snuffling,
+        And stroking my scanty beard,
+        I say in my pride,
+        "There's none worthy, save I!"
+        But I shiver still with cold.
+        I pull up my hempen bedclothes,
+        Wear what few sleeveless clothes I have,
+        But cold and bitter is the night!
+        As for those poorer than myself,        
+        Their parents must be cold and hungry,
+        Their wives and children beg and cry.
+        Then, how do you struggle through life?
+        
+        Wide as they call the heaven and earth,
+        For me they have shrunk quite small;
+        Bright though they call the sun and moon,
+        They never shine for me.
+        Is it the same with all men,
+        Or for me alone?
+        By rare chance I was born a man
+        And no meaner than my fellows,
+        But, wearing unwadded sleeveless clothes
+        In tatters, like weeds waving in the sea,
+        Hanging from my shoulders,
+        And under the sunken roof,
+        Within the leaning walls,
+        Here I lie on straw
+        Spread on bare earth,
+        With my parents at my pillow,
+        And my wife and children at my feet,
+        All huddled in grief and tears.
+        No fire sends up smoke
+        At the cooking-place,
+        And in the cauldron
+        A spider spins its web.
+        With not a grain to cook,
+        We moan like the night thrush.
+        Then, "to cut," as the saying is,
+        "The ends of what is already too short,"
+        The village headman comes,
+        With rod in hand, to our sleeping place,
+        Growling for his dues.
+        Must it be so hopeless --
+        The way of this world?
+
+        -- Yamanoue Okura
Index: /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/linecnt.sed	(revision 1780)
@@ -0,0 +1,1 @@
+=
Index: /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.good	(revision 1780)
@@ -0,0 +1,200 @@
+## config:mac-pre.in
+## common Macintosh prefix for all Makefile.in in the Kerberos V5 tree
+
+#
+# MPW-style lines for the MakeFile
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+#
+# This first part is long enough that NFS:Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make
+
+#
+# End of MPW-style lines for MakeFile
+#
+
+WHAT = mac
+
+# Directory syntax Ä 
+R=
+C=
+S=:
+U=:
+
+BUILDTOP = :::
+srcdir = 
+
+# FIXME Ä   This doesn't translate to MPW yet, srcdir must be same as objdir
+# File in object dir can come from either the current dir or srcdir
+# 
+# .  Ä  . "{srcdir}"
+
+# Default rule that puts each file into separate segment
+
+.c.o Ä  .c
+   {CC}  {DepDir}{Default}.c {CFLAGS} -s {Default} -o {TargDir}{Default}.c.o
+
+CPPFLAGS =  -i {SRCTOP}:include -i {BUILDTOP}:include -i {SRCTOP}:include:krb5 -i {BUILDTOP}:include:krb5 -i {CIncludes}
+DEFS =   {CPPFLAGS}
+CC = c
+LD = link
+# The funny quoting in the LDFLAGS is to avoid xxx.c.o being mangled by
+# mac-mf.sed into xxx.c.o
+LDFLAGS=-t MPST -c "MPS " -sym on {Libraries}"Runtime."o {CLibraries}"StdClib."o {Libraries}"ToolLibs."o {Libraries}"Interface."o
+CCOPTS = 
+LIBS = 
+KRB5ROOT= @KRB5ROOT@
+KRB4=@KRB4@
+INSTALL=Duplicate -y
+INSTALL_PROGRAM=Duplicate -y
+INSTALL_DATA=Duplicate -y
+INSTALL_SETUID=Duplicate -y
+
+KRB5MANROOT = {KRB5ROOT}{S}man
+ADMIN_BINDIR = {KRB5ROOT}{S}admin
+SERVER_BINDIR = {KRB5ROOT}{S}sbin
+CLIENT_BINDIR = {KRB5ROOT}{S}bin
+ADMIN_MANDIR = {KRB5MANROOT}{S}man8
+SERVER_MANDIR = {KRB5MANROOT}{S}man8
+CLIENT_MANDIR = {KRB5MANROOT}{S}man1
+FILE_MANDIR = {KRB5MANROOT}{S}man5
+KRB5_LIBDIR = {KRB5ROOT}{S}lib
+KRB5_INCDIR = {KRB5ROOT}{S}include
+KRB5_INCSUBDIRS = ¶
+	{KRB5_INCDIR}{S}krb5 ¶
+	{KRB5_INCDIR}{S}asn.1 ¶
+	{KRB5_INCDIR}{S}kerberosIV
+
+
+RM = Delete -y -i
+CP = Duplicate -y
+MV = mv -f
+CHMOD=chmod
+RANLIB = @RANLIB@
+ARCHIVE = @ARCHIVE@
+ARADD = @ARADD@
+LN = @LN_S@
+AWK = @AWK@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+YACC = @YACC@
+
+# FIXME Ä   This won't work for srcdir != objdir.  But on the Mac, there
+# is no easy way to build a relative or absolute path, because  Ä  means
+# both the path separator, and the "go up a directory" indicator
+#SRCTOP = {srcdir}{S}{BUILDTOP}
+SRCTOP = {BUILDTOP}
+SUBDIRS = @subdirs@
+
+TOPLIBD = {BUILDTOP}{S}lib
+
+OBJEXT = c.o
+LIBEXT = a
+EXEEXT =
+
+all ÄÄ 
+# Generated automatically from Makefile.in by configure
+CFLAGS = {CCOPTS} {DEFS} -i ::des
+
+##DOSBUILDTOP = ..\..\:
+##DOSLIBNAME=..\crypto.lib
+##DOS!include {BUILDTOP}\config\windows.in
+
+OBJS=	md5.{OBJEXT} md5glue.{OBJEXT} md5crypto.{OBJEXT}
+
+SRCS=	md5.c md5glue.c md5crypto.c
+
+all ÄÄ  {OBJS} 
+
+t_mddriver Ä  t_mddriver.c.o md5.c.o
+	Link    {LDFLAGS} -o t_mddriver t_mddriver.c.o md5.c.o
+
+t_mddriver.exe Ä 
+	{CC} {CFLAGS2} -o t_mddriver.exe t_mddriver.c md5.c
+
+check ÄÄ  t_mddriver{EXEEXT}
+	{C}t_mddriver{EXEEXT} -x
+
+clean ÄÄ 
+	{RM} t_mddriver{EXEEXT} t_mddriver.{OBJEXT}
+# config:post.in
+# put all ÄÄ  first just in case no other rules occur here
+#
+all ÄÄ 
+
+check ÄÄ 
+
+clean ÄÄ  clean-{WHAT}
+	{RM} config.log pre.c.out post.c.out Makefile.c.out
+
+clean-unix ÄÄ 
+	if test -n "{OBJS}" ; then {RM} {OBJS}; else  Ä ; fi
+
+clean-windows ÄÄ 
+	{RM} Å.{OBJEXT}
+	{RM} msvc.pdb Å.err
Index: /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.inp	(revision 1780)
@@ -0,0 +1,200 @@
+## config/mac-pre.in
+## common Macintosh prefix for all Makefile.in in the Kerberos V5 tree.
+
+#
+# MPW-style lines for the MakeFile.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+#
+# This first part is long enough that NFS/Share doesn't notice the non-ASCII
+# characters in the rest of the file, so it claims that the file is type
+# TEXT, which is what we want.  The non-ASCII chars are necessary for MPW 
+# Make.
+
+#
+# End of MPW-style lines for MakeFile.
+#
+
+WHAT = mac
+
+# Directory syntax:
+R=
+C=
+S=:
+U=:
+
+BUILDTOP = ../../..
+srcdir = .
+
+# FIXME:  This doesn't translate to MPW yet, srcdir must be same as objdir.
+# File in object dir can come from either the current dir or srcdir.
+# 
+# . : . "{srcdir}"
+
+# Default rule that puts each file into separate segment.
+
+.c.o: .c
+   {CC}  {DepDir}{Default}.c {CFLAGS} -s {Default} -o {TargDir}{Default}.c.o
+
+CPPFLAGS =  -I$(SRCTOP)/include -I$(BUILDTOP)/include -I$(SRCTOP)/include/krb5 -I$(BUILDTOP)/include/krb5 -i {CIncludes}
+DEFS =   $(CPPFLAGS)
+CC = c
+LD = link
+# The funny quoting in the LDFLAGS is to avoid xxx.o being mangled by
+# mac-mf.sed into xxx.c.o.
+LDFLAGS=-t MPST -c "MPS " -sym on {Libraries}"Runtime."o {CLibraries}"StdClib."o {Libraries}"ToolLibs."o {Libraries}"Interface."o
+CCOPTS = 
+LIBS = 
+KRB5ROOT= @KRB5ROOT@
+KRB4=@KRB4@
+INSTALL=Duplicate -y
+INSTALL_PROGRAM=Duplicate -y
+INSTALL_DATA=Duplicate -y
+INSTALL_SETUID=Duplicate -y
+
+KRB5MANROOT = $(KRB5ROOT)$(S)man
+ADMIN_BINDIR = $(KRB5ROOT)$(S)admin
+SERVER_BINDIR = $(KRB5ROOT)$(S)sbin
+CLIENT_BINDIR = $(KRB5ROOT)$(S)bin
+ADMIN_MANDIR = $(KRB5MANROOT)$(S)man8
+SERVER_MANDIR = $(KRB5MANROOT)$(S)man8
+CLIENT_MANDIR = $(KRB5MANROOT)$(S)man1
+FILE_MANDIR = $(KRB5MANROOT)$(S)man5
+KRB5_LIBDIR = $(KRB5ROOT)$(S)lib
+KRB5_INCDIR = $(KRB5ROOT)$(S)include
+KRB5_INCSUBDIRS = \
+	$(KRB5_INCDIR)$(S)krb5 \
+	$(KRB5_INCDIR)$(S)asn.1 \
+	$(KRB5_INCDIR)$(S)kerberosIV
+
+
+RM = Delete -y -i
+CP = Duplicate -y
+MV = mv -f
+CHMOD=chmod
+RANLIB = @RANLIB@
+ARCHIVE = @ARCHIVE@
+ARADD = @ARADD@
+LN = @LN_S@
+AWK = @AWK@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+YACC = @YACC@
+
+# FIXME:  This won't work for srcdir != objdir.  But on the Mac, there
+# is no easy way to build a relative or absolute path, because : means
+# both the path separator, and the "go up a directory" indicator.
+#SRCTOP = $(srcdir)$(S)$(BUILDTOP)
+SRCTOP = $(BUILDTOP)
+SUBDIRS = @subdirs@
+
+TOPLIBD = $(BUILDTOP)$(S)lib
+
+OBJEXT = c.o
+LIBEXT = a
+EXEEXT =
+
+all::
+# Generated automatically from Makefile.in by configure.
+CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../des
+
+##DOSBUILDTOP = ..\..\..
+##DOSLIBNAME=..\crypto.lib
+##DOS!include $(BUILDTOP)\config\windows.in
+
+OBJS=	md5.$(OBJEXT) md5glue.$(OBJEXT) md5crypto.$(OBJEXT)
+
+SRCS=	$(srcdir)/md5.c $(srcdir)/md5glue.c $(srcdir)/md5crypto.c
+
+all:: $(OBJS) 
+
+t_mddriver: t_mddriver.o md5.o
+	$(CC) $(CFLAGS) $(LDFLAGS) -o t_mddriver t_mddriver.o md5.o
+
+t_mddriver.exe:
+	$(CC) $(CFLAGS2) -o t_mddriver.exe t_mddriver.c md5.c
+
+check:: t_mddriver$(EXEEXT)
+	$(C)t_mddriver$(EXEEXT) -x
+
+clean::
+	$(RM) t_mddriver$(EXEEXT) t_mddriver.$(OBJEXT)
+# config/post.in
+# put all:: first just in case no other rules occur here
+#
+all::
+
+check::
+
+clean:: clean-$(WHAT)
+	$(RM) config.log pre.out post.out Makefile.out
+
+clean-unix::
+	if test -n "$(OBJS)" ; then $(RM) $(OBJS); else :; fi
+
+clean-windows::
+	$(RM) *.$(OBJEXT)
+	$(RM) msvc.pdb *.err
Index: /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/mac-mf.sed	(revision 1780)
@@ -0,0 +1,154 @@
+# Rewrite default rules from .c.o:  to  .c.o: .c
+/^\./s/^\(\.[a-z]*\)\(\.[a-z]*\)\( *: *\)$/\1\2\3 \1/
+
+# Change dependency char.
+/::/s/::/ \\Option-f\\Option-f /g
+/:/s/:/ \\Option-f /g
+/^[SU]=/s/ \\Option-f /:/g
+
+# Change syntax of Makefile vars.
+/\$/s/\${\([a-zA-Z0-9_]*\)}/{\1}/g
+/\$/s/\$(\([a-zA-Z0-9_]*\))/{\1}/g
+
+# Change $@ to {targ}
+/\$@/s/\$@/{targ}/g
+
+# Change pathname syntax.
+#
+# If line ends with ..  then assume it sets a variable that will
+# be used to prefix something else -- eliminate one colon, assuming
+# that a slash after the ${name} will turn into the missing colon.
+# Mac pathname conventions are IRREGULAR and UGLY!
+/\./s,\.\./\.\.$,::,
+/\./s,\.\.$,:,
+# Same if it ends with  .  (a single dot); turn it into nothing.
+/\./s,\.$,,g
+# Rules for .. and . elsewhere in the line
+# Convert ../: to ::, recur to get whole paths.
+/\./s,\.\./:,::,g
+# Convert ../../ to ::: 
+/\./s,\.\./\.\./,:::,g
+/\./s,\.\./,::,g
+/\.\//s,\./,:,g
+/\//s,/,:,g
+
+/=/s/ = \.$/ = :/
+
+# Comment out any explicit srcdir setting.
+# /srcdir/s/^srcdir/# srcdir/
+
+/version/s/^version=/# version=/
+
+/BASEDIR/s/^BASEDIR =.*$/BASEDIR = "{srcroot}"/
+/{BASEDIR}:/s/{BASEDIR}:/{BASEDIR}/g
+# The original lines screw up -I$(srcdir)/../des  by eliminating a colon.
+# Proposed fix:  Eliminate srcdir prefixes totally.
+#/{srcdir}:/s/{srcdir}:/"{srcdir}"/g
+/{srcdir}:/s/{srcdir}://g
+#/"{srcdir}":/s/"{srcdir}":/"{srcdir}"/g
+
+# Comment out settings of anything set by mpw host config.
+##/CC/s/^CC *=/#CC =/
+##/CFLAGS/s/^CFLAGS *=/#CFLAGS =/
+##/LDFLAGS/s/^LDFLAGS *=/#LDFLAGS =/
+
+# Change -I usage.
+/-I/s/-I\./-i :/g
+/-I/s/-I::bfd/-i ::bfd:/g
+/-I/s/-I::include/-i ::include:/g
+/-I/s/-I/-i /g
+
+# Change -D usage.
+/-D/s/\([ =]\)-D\([^ ]*\)/\1-d \2/g
+
+# Change continuation char.
+/\\$/s/\\$/\\Option-d/
+
+# Change wildcard char.
+/^[^#]/s/\*/\\Option-x/g
+
+# Change path of various types of source files.
+#/\.[chly]/s/\([ 	><=]\)\([-a-zA-Z0-9_$:"]*\)\.\([chly]\)/\1"{s}"\2.\3/g
+#/\.[chly]/s/^\([-a-zA-Z0-9_${}:"]*\)\.\([chly]\)/"{s}"\1.\2/g
+# Skip the {s} and {o} business for now...
+# Fix some overenthusiasms.
+#/{s}/s/"{s}""{srcdir}"/"{srcdir}"/g
+#/{s}/s/"{s}"{\([a-zA-Z0-9_]*\)dir}/"{\1dir}"/g
+#/{s}/s/"{s}"{\([a-zA-Z0-9_]*\)DIR}/"{\1DIR}"/g
+#/{s}/s/"{s}""{\([a-zA-Z0-9_]*\)dir}"/"{\1dir}"/g
+#/{s}/s/"{s}""{\([a-zA-Z0-9_]*\)DIR}"/"{\1DIR}"/g
+#/{s}/s/"{s}":/:/g
+#/{s}/s/^"{s}"//g
+#/^\./s/"{s}"\././g
+
+# Change extension and path of objects, except in the OBJEXT line.
+#/^OBJEXT/!s/\([ 	=]\)\([-a-zA-Z0-9_${}:"]*\)\.o/\1"{o}"\2.c.o/g
+#/\.o/s/^\([-a-zA-Z0-9_${}:"]*\)\.o/"{o}"\1.c.o/g
+# Skip the {o} stuff for now...
+/^OBJEXT/!s/\([ 	=]\)\([-a-zA-Z0-9_${}:"]*\)\.o/\1\2.c.o/g
+/\.o/s/^\([-a-zA-Z0-9_${}:"]*\)\.o/\1.c.o/g
+# Clean up.
+#/\.o/s/"{o}""{o}"/"{o}"/g
+#/{o}/s/^"{o}"\([a-zA-Z0-9_]*\)=/\1=/g
+
+# Change extension of libs.
+# /\.a/s/lib\([a-z]*\)\.a/lib\1.o/g
+
+# Remove non-echo option.
+/^	-/s/^	-/	/
+
+# Change cp to duplicate.
+# /cp/s/^\([ 	]*\)cp /\1Duplicate -d -y /
+# Change mv to rename.
+# /mv/s/^\([ 	]*\)mv /\1Rename -y /
+# /Rename/s/^\([ 	]*\)Rename -y -f/\1Rename -y/
+# Change rm to delete.
+/^RM=/s/rm -f/Delete -i -y/
+# /rm/s/^\([ 	]*\)rm /\1Delete -y /
+# /Delete/s/^\([ 	]*\)Delete -y -f/\1Delete -y/
+# Comment out symlinking.
+# /ln/s/^\([ 	]*\)ln /\1# ln /
+
+# Remove -c from explicit compiler calls.
+# /-c/s/{CC}\(.*\) -c \(.*\)\([-a-z]*\)\.c/{CC}\1 \2\3.c -o "{o}"\3.c.o/g
+# Don't ask... prev subst seems to omit the second filename.
+# /-o/s/\([-a-z]*\)\.c -o "{o}".c.o/\1\.c -o "{o}"\1.c.o/
+
+# Change linking cc to link.
+/LDFLAGS/    s/{CC} \(.*\){CFLAGS}\(.*\){LDFLAGS}/Link \1 \2 {LDFLAGS}/
+/CFLAGS_LINK/s/{CC} \(.*\){CFLAGS_LINK}\(.*\){LDFLAGS}/Link \1 \2 {LDFLAGS}/
+
+# Comment out .PHONY rules.
+/\.PHONY/s/^\.PHONY/# \.PHONY/
+# Comment out .SUFFIXES rules.
+/\.SUFFIXES/s/^\.SUFFIXES/# \.SUFFIXES/
+# Comment out .PRECIOUS rules.
+/\.PRECIOUS/s/^\.PRECIOUS/# \.PRECIOUS/
+## Comment out default rules.
+##/^\./s/^\(\.[a-z]*\.[a-z]* \)/# \1/
+
+#
+#  End of original hack-mf.sed
+#
+#  Begin original hack-mf2.sed
+#
+# Transform expressions.
+
+# Set the install program appropriate.
+# /INSTALL/s/^INSTALL *= *`.*`:install.sh -c/INSTALL = Duplicate -y/
+
+# Include from the extra-include dir.
+# /^INCLUDES = /s/^INCLUDES = /INCLUDES = -i "{srcroot}"extra-include /
+
+# Yuck - remove unconverted autoconf things.
+# /@/s/@[^ 	]*@//g
+
+# Hackery, pure and simple
+# To speed up compiles, remove duplicated -i options.
+/-i/s/\(-i [^ ]*\) \1 /\1 /g
+
+# Note!  There are 8-bit characters in the three lines below:
+#   	0xc4, 0xb6, 0xc5.
+/Option/s/\\Option-f/Ä/g
+/Option/s/\\Option-d/¶/g
+/Option/s/\\Option-x/Å/g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/madding.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/madding.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/madding.good	(revision 1780)
@@ -0,0 +1,1 @@
+The girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with a caged canary -- all probably from the windows of the house just vacated.  There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around.  The handsome girl waited for some time idly in her place, and the only sound heard in the stillness was the hopping of the canary up and down the perches of its prison.  Then she looked attentively downwards.  It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them.  She turned her head to learn if the waggoner were coming.  He was not yet in sight; and her eyes crept back to the package, her thoughts seeming to run upon what was inside it.  At length she drew the article into her lap, and untied the paper covering; a small swing looking- glass was disclosed, in which she proceeded to survey herself attentively.  She parted her lips and smiled.  It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair.  The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm.  What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows; it ended certainly in a real smile.  She blushed at herself, and seeing her reflection blush, blushed the more.  The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess.  The picture was a delicate one.  Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality.  A cynical inference was irresistible by Gabriel Oak as he regarded the scene, generous though he fain would have been.  There was no necessity whatever for her looking in the glass.  She did not adjust her hat, or pat her hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass.  She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won.  Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all.  The waggoner's steps were heard returning.  She put the glass in the paper, and the whole again into its place.  When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll.  About twenty steps still remained between him and the gate, when he heard a dispute.  It was a difference concerning twopence between the persons with the waggon and the man at the toll-bar.  "Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more."  These were the waggoner's words.  "Very well; then mis'ess's niece can't pass," said the turnpike-keeper, closing the gate.  Oak looked from one to the other of the disputants, and fell into a reverie.  There was something in the tone of twopence remarkably insignificant.  Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter; but twopence -- "Here," he said, stepping forward and handing twopence to the gatekeeper; "let the young woman pass."  He looked up at her then; she heard his words, and looked down.  Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety.  The red-jacketed and dark-haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on.  She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind.  The gatekeeper surveyed the retreating vehicle.  "That's a handsome maid," he said to Oak.  "But she has her faults," said Gabriel.  "True, farmer." "And the greatest of them is -- well, what it is always." "Beating people down? ay, 'tis so." "O no." "What, then?" Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, "Vanity, dude."
Index: /tags/kBuild-0.1.4/src/sed/testsuite/madding.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/madding.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/madding.inp	(revision 1780)
@@ -0,0 +1,1 @@
+The girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with a caged canary -- all probably from the windows of the house just vacated.  There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around.  The handsome girl waited for some time idly in her place, and the only sound heard in the stillness was the hopping of the canary up and down the perches of its prison.  Then she looked attentively downwards.  It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them.  She turned her head to learn if the waggoner were coming.  He was not yet in sight; and her eyes crept back to the package, her thoughts seeming to run upon what was inside it.  At length she drew the article into her lap, and untied the paper covering; a small swing looking- glass was disclosed, in which she proceeded to survey herself attentively.  She parted her lips and smiled.  It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair.  The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm.  What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows; it ended certainly in a real smile.  She blushed at herself, and seeing her reflection blush, blushed the more.  The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess.  The picture was a delicate one.  Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality.  A cynical inference was irresistible by Gabriel Oak as he regarded the scene, generous though he fain would have been.  There was no necessity whatever for her looking in the glass.  She did not adjust her hat, or pat her hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass.  She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won.  Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all.  The waggoner's steps were heard returning.  She put the glass in the paper, and the whole again into its place.  When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll.  About twenty steps still remained between him and the gate, when he heard a dispute.  It was a difference concerning twopence between the persons with the waggon and the man at the toll-bar.  "Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more."  These were the waggoner's words.  "Very well; then mis'ess's niece can't pass," said the turnpike-keeper, closing the gate.  Oak looked from one to the other of the disputants, and fell into a reverie.  There was something in the tone of twopence remarkably insignificant.  Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter; but twopence -- "Here," he said, stepping forward and handing twopence to the gatekeeper; "let the young woman pass."  He looked up at her then; she heard his words, and looked down.  Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety.  The red-jacketed and dark-haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on.  She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind.  The gatekeeper surveyed the retreating vehicle.  "That's a handsome maid," he said to Oak.  "But she has her faults," said Gabriel.  "True, farmer." "And the greatest of them is -- well, what it is always." "Beating people down? ay, 'tis so." "O no." "What, then?" Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, "Vanity."
Index: /tags/kBuild-0.1.4/src/sed/testsuite/madding.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/madding.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/madding.sed	(revision 1780)
@@ -0,0 +1,8 @@
+# this is from Thomas Hardy's _Far From the Madding Crowd_.
+#
+# cf ftp://ftp.cdrom.com/pub/gutenberg/etext94/crowd10a.txt
+#
+# the point of this test, in case it isn't obvious, is to overfill fixed
+# buffers wherever they might be.
+#
+s/The girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with a caged canary -- all probably from the windows of the house just vacated.  There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around.  The handsome girl waited for some time idly in her place, and the only sound heard in the stillness was the hopping of the canary up and down the perches of its prison.  Then she looked attentively downwards.  It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them.  She turned her head to learn if the waggoner were coming.  He was not yet in sight; and her eyes crept back to the package, her thoughts seeming to run upon what was inside it.  At length she drew the article into her lap, and untied the paper covering; a small swing looking- glass was disclosed, in which she proceeded to survey herself attentively.  She parted her lips and smiled.  It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair.  The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm.  What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows; it ended certainly in a real smile.  She blushed at herself, and seeing her reflection blush, blushed the more.  The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess.  The picture was a delicate one.  Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality.  A cynical inference was irresistible by Gabriel Oak as he regarded the scene, generous though he fain would have been.  There was no necessity whatever for her looking in the glass.  She did not adjust her hat, or pat her hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass.  She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won.  Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all.  The waggoner's steps were heard returning.  She put the glass in the paper, and the whole again into its place.  When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll.  About twenty steps still remained between him and the gate, when he heard a dispute.  It was a difference concerning twopence between the persons with the waggon and the man at the toll-bar.  "Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more."  These were the waggoner's words.  "Very well; then mis'ess's niece can't pass," said the turnpike-keeper, closing the gate.  Oak looked from one to the other of the disputants, and fell into a reverie.  There was something in the tone of twopence remarkably insignificant.  Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter; but twopence -- "Here," he said, stepping forward and handing twopence to the gatekeeper; "let the young woman pass."  He looked up at her then; she heard his words, and looked down.  Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety.  The red-jacketed and dark-haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on.  She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind.  The gatekeeper surveyed the retreating vehicle.  "That's a handsome maid," he said to Oak.  "But she has her faults," said Gabriel.  "True, farmer." "And the greatest of them is -- well, what it is always." "Beating people down? ay, 'tis so." "O no." "What, then?" Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, "Vanity."/The girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with a caged canary -- all probably from the windows of the house just vacated.  There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around.  The handsome girl waited for some time idly in her place, and the only sound heard in the stillness was the hopping of the canary up and down the perches of its prison.  Then she looked attentively downwards.  It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them.  She turned her head to learn if the waggoner were coming.  He was not yet in sight; and her eyes crept back to the package, her thoughts seeming to run upon what was inside it.  At length she drew the article into her lap, and untied the paper covering; a small swing looking- glass was disclosed, in which she proceeded to survey herself attentively.  She parted her lips and smiled.  It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair.  The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm.  What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows; it ended certainly in a real smile.  She blushed at herself, and seeing her reflection blush, blushed the more.  The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess.  The picture was a delicate one.  Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality.  A cynical inference was irresistible by Gabriel Oak as he regarded the scene, generous though he fain would have been.  There was no necessity whatever for her looking in the glass.  She did not adjust her hat, or pat her hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass.  She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won.  Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all.  The waggoner's steps were heard returning.  She put the glass in the paper, and the whole again into its place.  When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll.  About twenty steps still remained between him and the gate, when he heard a dispute.  It was a difference concerning twopence between the persons with the waggon and the man at the toll-bar.  "Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more."  These were the waggoner's words.  "Very well; then mis'ess's niece can't pass," said the turnpike-keeper, closing the gate.  Oak looked from one to the other of the disputants, and fell into a reverie.  There was something in the tone of twopence remarkably insignificant.  Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter; but twopence -- "Here," he said, stepping forward and handing twopence to the gatekeeper; "let the young woman pass."  He looked up at her then; she heard his words, and looked down.  Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety.  The red-jacketed and dark-haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on.  She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind.  The gatekeeper surveyed the retreating vehicle.  "That's a handsome maid," he said to Oak.  "But she has her faults," said Gabriel.  "True, farmer." "And the greatest of them is -- well, what it is always." "Beating people down? ay, 'tis so." "O no." "What, then?" Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, "Vanity, dude."/
Index: /tags/kBuild-0.1.4/src/sed/testsuite/manis.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/manis.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/manis.good	(revision 1780)
@@ -0,0 +1,22 @@
+s%@CFLAGS@%%g
+s%@CPPFLAGS@%-I/%g
+s%@CXXFLAGS@%-x c++%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%-L/usr/lib%g
+s%@LIBS@%-lgnu -lbfd%g
+s%@exec_prefix@%%g
+s%@prefix@%$prefix%g
+s%@RANLIB@%$RANLIB%g
+s%@CC@%/usr/local/bin/gcc%g
+s%@CPP@%$CPP%g
+s%@XCFLAGS@%$XCFLAGS%g
+s%@XINCLUDES@%$XINCLUDES%g
+s%@XLIBS@%$XLIBS%g
+s%@XPROGS@%$XPROGS%g
+s%@TCLHDIR@%$TCLHDIR%g
+s%@TCLLIB@%$TCLLIB%g
+s%@TKHDIR@%$TKHDIR%g
+s%@TKLIB@%$TKLIB%g
+s%@PTY_TYPE@%$PTY_TYPE%g
+s%@EVENT_TYPE@%$EVENT_TYPE%g
+s%@SETUID@%$SETUID%g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/manis.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/manis.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/manis.inp	(revision 1780)
@@ -0,0 +1,22 @@
+s%@CFLAGS@%%g
+s%@CPPFLAGS@%-I/%g
+s%@CXXFLAGS@%-x c++%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%-L/usr/lib%g
+s%@LIBS@%-lgnu -lbfd%g
+s%@exec_prefix@%%g
+s%@prefix@%$prefix%g
+s%@RANLIB@%$RANLIB%g
+s%@CC@%/usr/local/bin/gcc%g
+s%@CPP@%$CPP%g
+s%@XCFLAGS@%$XCFLAGS%g
+s%@XINCLUDES@%$XINCLUDES%g
+s%@XLIBS@%$XLIBS%g
+s%@XPROGS@%$XPROGS%g
+s%@TCLHDIR@%$TCLHDIR%g
+s%@TCLLIB@%$TCLLIB%g
+s%@TKHDIR@%$TKHDIR%g
+s%@TKLIB@%$TKLIB%g
+s%@PTY_TYPE@%$PTY_TYPE%g
+s%@EVENT_TYPE@%$EVENT_TYPE%g
+s%@SETUID@%$SETUID%g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/manis.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/manis.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/manis.sed	(revision 1780)
@@ -0,0 +1,6 @@
+# straight out of an autoconf-generated configure.
+# The input should look just like the input after this is run.
+#
+# Protect against being on the right side of a sed subst in config.status. 
+s/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g; 
+ s/@@/%@/; s/@@/@%/; s/@g$/%g/
Index: /tags/kBuild-0.1.4/src/sed/testsuite/middle.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/middle.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/middle.good	(revision 1780)
@@ -0,0 +1,3 @@
+   universe.  You will never succeed.  Everything will fail and come
+   to an end finally.  But you have a chance to carve a little bit
+   of order and maybe even beauty out of the raw materials that
Index: /tags/kBuild-0.1.4/src/sed/testsuite/middle.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/middle.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/middle.inp	(revision 1780)
@@ -0,0 +1,9 @@
+   "...by imposing a tiny bit of order in a communication you are
+   translating, you are carving out a little bit of order in the
+   universe.  You will never succeed.  Everything will fail and come
+   to an end finally.  But you have a chance to carve a little bit
+   of order and maybe even beauty out of the raw materials that
+   surround you everywhere, and I think there is no greater meaning
+   in life."
+
+             Donald L. Philippi, Oct 1930 - Jan 1993
Index: /tags/kBuild-0.1.4/src/sed/testsuite/middle.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/middle.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/middle.sed	(revision 1780)
@@ -0,0 +1,1 @@
+3,5p
Index: /tags/kBuild-0.1.4/src/sed/testsuite/modulo.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/modulo.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/modulo.good	(revision 1780)
@@ -0,0 +1,22 @@
+1
+s%@CFLAGS@%%g
+3
+s%@CXXFLAGS@%-x c++%g
+5
+s%@LDFLAGS@%-L/usr/lib%g
+7
+s%@exec_prefix@%%g
+9
+s%@RANLIB@%$RANLIB%g
+11
+s%@CPP@%$CPP%g
+13
+s%@XINCLUDES@%$XINCLUDES%g
+15
+s%@XPROGS@%$XPROGS%g
+17
+s%@TCLLIB@%$TCLLIB%g
+19
+s%@TKLIB@%$TKLIB%g
+21
+s%@EVENT_TYPE@%$EVENT_TYPE%g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/modulo.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/modulo.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/modulo.inp	(revision 1780)
@@ -0,0 +1,22 @@
+s%@CFLAGS@%%g
+s%@CPPFLAGS@%-I/%g
+s%@CXXFLAGS@%-x c++%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%-L/usr/lib%g
+s%@LIBS@%-lgnu -lbfd%g
+s%@exec_prefix@%%g
+s%@prefix@%$prefix%g
+s%@RANLIB@%$RANLIB%g
+s%@CC@%/usr/local/bin/gcc%g
+s%@CPP@%$CPP%g
+s%@XCFLAGS@%$XCFLAGS%g
+s%@XINCLUDES@%$XINCLUDES%g
+s%@XLIBS@%$XLIBS%g
+s%@XPROGS@%$XPROGS%g
+s%@TCLHDIR@%$TCLHDIR%g
+s%@TCLLIB@%$TCLLIB%g
+s%@TKHDIR@%$TKHDIR%g
+s%@TKLIB@%$TKLIB%g
+s%@PTY_TYPE@%$PTY_TYPE%g
+s%@EVENT_TYPE@%$EVENT_TYPE%g
+s%@SETUID@%$SETUID%g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/modulo.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/modulo.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/modulo.sed	(revision 1780)
@@ -0,0 +1,1 @@
+0~2d;=
Index: /tags/kBuild-0.1.4/src/sed/testsuite/newjis.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/newjis.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/newjis.good	(revision 1780)
@@ -0,0 +1,4 @@
+$B$H$J$j$NM9JX6I$K(B
+$B$?$F$+$1$?$N$O(B
+$B$?$F$+$1$?$+$C$?$+$i(B
+$B$?$F$+$1$?!#(B
Index: /tags/kBuild-0.1.4/src/sed/testsuite/newjis.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/newjis.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/newjis.inp	(revision 1780)
@@ -0,0 +1,4 @@
+$B$H$J$j$N$?$1$,$-$K(B
+$B$?$F$+$1$?$N$O(B
+$B$?$F$+$1$?$+$C$?$+$i(B
+$B$?$F$+$1$?!#(B
Index: /tags/kBuild-0.1.4/src/sed/testsuite/newjis.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/newjis.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/newjis.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/$?$1$,$-/M9JX6I/
Index: /tags/kBuild-0.1.4/src/sed/testsuite/noeol.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/noeol.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/noeol.good	(revision 1780)
@@ -0,0 +1,3 @@
+This file is uniquewakuwaku
+in that it doeswakuwaku
+end in a newline.wakuwaku
Index: /tags/kBuild-0.1.4/src/sed/testsuite/noeol.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/noeol.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/noeol.inp	(revision 1780)
@@ -0,0 +1,3 @@
+This file is unique
+in that it does
+end in a newline.
Index: /tags/kBuild-0.1.4/src/sed/testsuite/noeol.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/noeol.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/noeol.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/$/wakuwaku/g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.1good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.1good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.1good	(revision 1780)
@@ -0,0 +1,7 @@
+This file is unique
+in that it does
+end in a newline.
+This file is unique
+in that it does
+end in a newline.
+in that it does
Index: /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.2good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.2good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.2good	(revision 1780)
@@ -0,0 +1,3 @@
+This file is unique
+in that it does
+end in a newline.
Index: /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.good	(revision 1780)
@@ -0,0 +1,12 @@
+This file is unique
+This file is unique
+in that it does
+in that it does
+end in a newline.
+end in a newline.
+This file is unique
+This file is unique
+in that it does
+in that it does
+end in a newline.
+end in a newline.
Index: /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/noeolw.sed	(revision 1780)
@@ -0,0 +1,10 @@
+w noeolw.1out
+$ {
+	x
+	w noeolw.1out
+	x
+}
+h
+1,3w noeolw.2out
+p
+p
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub.good	(revision 1780)
@@ -0,0 +1,1 @@
+foo foo fo oo f oo foo foo foo foo foo foo foo bar foo foo foo foo foo
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub.inp	(revision 1780)
@@ -0,0 +1,2 @@
+foo foo fo oo f oo foo foo foo foo foo foo foo foo foo foo foo foo foo
+foo foo fo oo f oo foo foo foo foo foo foo foo foo foo foo foo foo foo
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub.sed	(revision 1780)
@@ -0,0 +1,7 @@
+# the first one matches, the second doesn't
+1s/foo/bar/10
+2s/foo/bar/20
+
+# The second line should be deleted.  ssed 3.55-3.58 do not.
+t
+d
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub2.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub2.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub2.inp	(revision 1780)
@@ -0,0 +1,1 @@
+
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub2.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub2.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub2.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/a*/b/2
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub3.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub3.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub3.inp	(revision 1780)
@@ -0,0 +1,1 @@
+
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub3.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub3.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub3.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/^a*/b/2
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub4.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub4.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub4.inp	(revision 1780)
@@ -0,0 +1,1 @@
+z
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub4.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub4.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub4.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/^a*/b/2p
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub5.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub5.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub5.inp	(revision 1780)
@@ -0,0 +1,1 @@
+z
Index: /tags/kBuild-0.1.4/src/sed/testsuite/numsub5.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/numsub5.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/numsub5.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/a*/b/3p
Index: /tags/kBuild-0.1.4/src/sed/testsuite/ptestcases.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/ptestcases.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/ptestcases.h	(revision 1780)
@@ -0,0 +1,326 @@
+  { 0, 0, "2.8.2  Regular Expression General Requirement", NULL, },
+  { 2, 4, "bb*", "abbbc",  },
+  { 2, 2, "bb*", "ababbbc",  },
+  { 7, 9, "A#*::", "A:A#:qA::qA#::qA##::q",  },
+  { 1, 5, "A#*::", "A##::A#::qA::qA#:q",  },
+  { 0, 0, "2.8.3.1.2  BRE Special Characters", NULL, },
+  { 0, 0, "GA108", NULL, },
+  { 2, 2, "\\.", "a.c",  },
+  { 2, 2, "\\[", "a[c",  },
+  { 2, 2, "\\\\", "a\\c",  },
+  { 2, 2, "\\*", "a*c",  },
+  { 2, 2, "\\^", "a^c",  },
+  { 2, 2, "\\$", "a$c",  },
+  { 7, 11, "X\\*Y\\*8", "Y*8X*8X*Y*8",  },
+  { 0, 0, "GA109", NULL, },
+  { 2, 2, "[.]", "a.c",  },
+  { 2, 2, "[[]", "a[c",  },
+  { -1, -1, "[[]", "ac",  },
+  { 2, 2, "[\\]", "a\\c",  },
+  { 1, 1, "[\\a]", "abc",  },
+  { 2, 2, "[\\.]", "a\\.c",  },
+  { 2, 2, "[\\.]", "a.\\c",  },
+  { 2, 2, "[*]", "a*c",  },
+  { 2, 2, "[$]", "a$c",  },
+  { 2, 2, "[X*Y8]", "7*8YX",  },
+  { 0, 0, "GA110", NULL, },
+  { 2, 2, "*", "a*c",  },
+  { 3, 4, "*a", "*b*a*c",  },
+  { 1, 5, "**9=", "***9=9",  },
+  { 0, 0, "GA111", NULL, },
+  { 1, 1, "^*", "*bc",  },
+  { -1, -1, "^*", "a*c",  },
+  { -1, -1, "^*", "^*ab",  },
+  { 1, 5, "^**9=", "***9=",  },
+  { -1, -1, "^*5<*9", "5<9*5<*9",  },
+  { 0, 0, "GA112", NULL, },
+  { 2, 3, "\\(*b\\)", "a*b",  },
+  { -1, -1, "\\(*b\\)", "ac",  },
+  { 1, 6, "A\\(**9\\)=", "A***9=79",  },
+  { 0, 0, "GA113(1)", NULL, },
+  { 1, 3, "\\(^*ab\\)", "*ab",  },
+  { -1, -1, "\\(^*ab\\)", "^*ab",  },
+  { -1, -1, "\\(^*b\\)", "a*b",  },
+  { -1, -1, "\\(^*b\\)", "^*b",  },
+  { 0, 0, "GA114", NULL, },
+  { 1, 3, "a^b", "a^b",  },
+  { 1, 3, "a\\^b", "a^b",  },
+  { 1, 1, "^^", "^bc",  },
+  { 2, 2, "\\^", "a^c",  },
+  { 1, 1, "[c^b]", "^abc",  },
+  { 1, 1, "[\\^ab]", "^ab",  },
+  { 2, 2, "[\\^ab]", "c\\d",  },
+  { -1, -1, "[^^]", "^",  },
+  { 1, 3, "\\(a^b\\)", "a^b",  },
+  { 1, 3, "\\(a\\^b\\)", "a^b",  },
+  { 2, 2, "\\(\\^\\)", "a^b",  },
+  { 0, 0, "GA115", NULL, },
+  { 3, 3, "$$", "ab$",  },
+  { -1, -1, "$$", "$ab",  },
+  { 2, 3, "$c", "a$c",  },
+  { 2, 2, "[$]", "a$c",  },
+  { 1, 2, "\\$a", "$a",  },
+  { 3, 3, "\\$$", "ab$",  },
+  { 2, 6, "A\\([34]$[34]\\)B", "XA4$3BY",  },
+  { 0, 0, "2.8.3.1.3  Periods in BREs", NULL, },
+  { 0, 0, "GA116", NULL, },
+  { 1, 1, ".", "abc",  },
+  { -1, -1, ".ab", "abc",  },
+  { 1, 3, "ab.", "abc",  },
+  { 1, 3, "a.b", "a,b",  },
+  { -1, -1, ".......", "PqRs6",  },
+  { 1, 7, ".......", "PqRs6T8",  },
+  { 0, 0, "2.8.3.2  RE Bracket Expression", NULL, },
+  { 0, 0, "GA118", NULL, },
+  { 2, 2, "[abc]", "xbyz",  },
+  { -1, -1, "[abc]", "xyz",  },
+  { 2, 2, "[abc]", "xbay",  },
+  { 0, 0, "GA119", NULL, },
+  { 2, 2, "[^a]", "abc",  },
+  { 4, 4, "[^]cd]", "cd]ef",  },
+  { 2, 2, "[^abc]", "axyz",  },
+  { -1, -1, "[^abc]", "abc",  },
+  { 3, 3, "[^[.a.]b]", "abc",  },
+  { 3, 3, "[^[=a=]b]", "abc",  },
+  { 2, 2, "[^-ac]", "abcde-",  },
+  { 2, 2, "[^ac-]", "abcde-",  },
+  { 3, 3, "[^a-b]", "abcde",  },
+  { 3, 3, "[^a-bd-e]", "dec",  },
+  { 2, 2, "[^---]", "-ab",  },
+  { 16, 16, "[^a-zA-Z0-9]", "pqrstVWXYZ23579#",  },
+  { 0, 0, "GA120(1)", NULL, },
+  { 3, 3, "[]a]", "cd]ef",  },
+  { 1, 1, "[]-a]", "a_b",  },
+  { 3, 3, "[][.-.]-0]", "ab0-]",  },
+  { 1, 1, "[]^a-z]", "string",  },
+  { 0, 0, "GA120(2)", NULL, },
+  { 4, 4, "[^]cd]", "cd]ef",  },
+  { 0, 0, "[^]]*", "]]]]]]]]X",  },
+  { 0, 0, "[^]]*", "]]]]]]]]",  },
+  { 9, 9, "[^]]\\{1,\\}", "]]]]]]]]X",  },
+  { -1, -1, "[^]]\\{1,\\}", "]]]]]]]]",  },
+  { 0, 0, "GA120(3)", NULL, },
+  { 3, 3, "[c[.].]d]", "ab]cd",  },
+  { 2, 8, "[a-z]*[[.].]][A-Z]*", "Abcd]DEFg",  },
+  { 0, 0, "GA121", NULL, },
+  { 2, 2, "[[.a.]b]", "Abc",  },
+  { 1, 1, "[[.a.]b]", "aBc",  },
+  { -1, -1, "[[.a.]b]", "ABc",  },
+  { 3, 3, "[^[.a.]b]", "abc",  },
+  { 3, 3, "[][.-.]-0]", "ab0-]",  },
+  { 3, 3, "[A-[.].]c]", "ab]!",  },
+  { 0, 0, "GA122", NULL, },
+  { -2, -2, "[[.ch.]]", "abc",  },
+  { -2, -2, "[[.ab.][.CD.][.EF.]]", "yZabCDEFQ9",  },
+  { 0, 0, "GA125", NULL, },
+  { 2, 2, "[[=a=]b]", "Abc",  },
+  { 1, 1, "[[=a=]b]", "aBc",  },
+  { -1, -1, "[[=a=]b]", "ABc",  },
+  { 3, 3, "[^[=a=]b]", "abc",  },
+  { 0, 0, "GA126", NULL, },
+  { 0, 0, NULL, "the expected result for [[:alnum:]]* is 2-7 which is wrong" },
+  { 0, 0, "[[:alnum:]]*", " aB28gH",  },
+  { 2, 7, "[[:alnum:]][[:alnum:]]*", " aB28gH",  },
+  { 0, 0, NULL, "the expected result for [^[:alnum:]]* is 2-5 which is wrong" },
+  { 0, 0, "[^[:alnum:]]*", "2 	,a",  },
+  { 2, 5, "[^[:alnum:]][^[:alnum:]]*", "2 	,a",  },
+  { 0, 0, NULL, "the expected result for [[:alpha:]]* is 2-5 which is wrong" },
+  { 0, 0, "[[:alpha:]]*", " aBgH2",  },
+  { 2, 5, "[[:alpha:]][[:alpha:]]*", " aBgH2",  },
+  { 1, 6, "[^[:alpha:]]*", "2 	8,a",  },
+  { 1, 2, "[[:blank:]]*", " 	\r",  },
+  { 1, 8, "[^[:blank:]]*", "aB28gH, ",  },
+  { 1, 2, "[[:cntrl:]]*", "	 ",  },
+  { 1, 8, "[^[:cntrl:]]*", "aB2 8gh,",  },
+  { 0, 0, NULL, "the expected result for [[:digit:]]* is 2-3 which is wrong" },
+  { 0, 0, "[[:digit:]]*", "a28",  },
+  { 2, 3, "[[:digit:]][[:digit:]]*", "a28",  },
+  { 1, 8, "[^[:digit:]]*", "aB 	gH,",  },
+  { 1, 7, "[[:graph:]]*", "aB28gH, ",  },
+  { 1, 3, "[^[:graph:]]*", " 	,",  },
+  { 1, 2, "[[:lower:]]*", "agB",  },
+  { 1, 8, "[^[:lower:]]*", "B2 	8H,a",  },
+  { 1, 8, "[[:print:]]*", "aB2 8gH,	",  },
+  { 1, 2, "[^[:print:]]*", "	 ",  },
+  { 0, 0, NULL, "the expected result for [[:punct:]]* is 2-2 which is wrong" },
+  { 0, 0, "[[:punct:]]*", "a,2",  },
+  { 2, 3, "[[:punct:]][[:punct:]]*", "a,,2",  },
+  { 1, 9, "[^[:punct:]]*", "aB2 	8gH",  },
+  { 1, 3, "[[:space:]]*", " 	\r",  },
+  { 0, 0, NULL, "the expected result for [^[:space:]]* is 2-9 which is wrong" },
+  { 0, 0, "[^[:space:]]*", " aB28gH,	",  },
+  { 2, 9, "[^[:space:]][^[:space:]]*", " aB28gH,	",  },
+  { 0, 0, NULL, "the expected result for [[:upper:]]* is 2-3 which is wrong" },
+  { 0, 0, "[[:upper:]]*", "aBH2",  },
+  { 2, 3, "[[:upper:]][[:upper:]]*", "aBH2",  },
+  { 1, 8, "[^[:upper:]]*", "a2 	8g,B",  },
+  { 0, 0, NULL, "the expected result for [[:xdigit:]]* is 2-5 which is wrong" },
+  { 0, 0, "[[:xdigit:]]*", "gaB28h",  },
+  { 2, 5, "[[:xdigit:]][[:xdigit:]]*", "gaB28h",  },
+  { 0, 0, NULL, "the expected result for [^[:xdigit:]]* is 2-7 which is wrong" },
+  { 2, 7, "[^[:xdigit:]][^[:xdigit:]]*", "a 	gH,2",  },
+  { 0, 0, "GA127", NULL, },
+  { -2, -2, "[b-a]", "abc",  },
+  { 1, 1, "[a-c]", "bbccde",  },
+  { 2, 2, "[a-b]", "-bc",  },
+  { 3, 3, "[a-z0-9]", "AB0",  },
+  { 3, 3, "[^a-b]", "abcde",  },
+  { 3, 3, "[^a-bd-e]", "dec",  },
+  { 1, 1, "[]-a]", "a_b",  },
+  { 2, 2, "[+--]", "a,b",  },
+  { 2, 2, "[--/]", "a.b",  },
+  { 2, 2, "[^---]", "-ab",  },
+  { 3, 3, "[][.-.]-0]", "ab0-]",  },
+  { 3, 3, "[A-[.].]c]", "ab]!",  },
+  { 2, 6, "bc[d-w]xy", "abchxyz",  },
+  { 0, 0, "GA129", NULL, },
+  { 1, 1, "[a-cd-f]", "dbccde",  },
+  { -1, -1, "[a-ce-f]", "dBCCdE",  },
+  { 2, 4, "b[n-zA-M]Y", "absY9Z",  },
+  { 2, 4, "b[n-zA-M]Y", "abGY9Z",  },
+  { 0, 0, "GA130", NULL, },
+  { 3, 3, "[-xy]", "ac-",  },
+  { 2, 4, "c[-xy]D", "ac-D+",  },
+  { 2, 2, "[--/]", "a.b",  },
+  { 2, 4, "c[--/]D", "ac.D+b",  },
+  { 2, 2, "[^-ac]", "abcde-",  },
+  { 1, 3, "a[^-ac]c", "abcde-",  },
+  { 3, 3, "[xy-]", "zc-",  },
+  { 2, 4, "c[xy-]7", "zc-786",  },
+  { 2, 2, "[^ac-]", "abcde-",  },
+  { 2, 4, "a[^ac-]c", "5abcde-",  },
+  { 2, 2, "[+--]", "a,b",  },
+  { 2, 4, "a[+--]B", "Xa,By",  },
+  { 2, 2, "[^---]", "-ab",  },
+  { 4, 6, "X[^---]Y", "X-YXaYXbY",  },
+  { 0, 0, "2.8.3.3  BREs Matching Multiple Characters", NULL, },
+  { 0, 0, "GA131", NULL, },
+  { 3, 4, "cd", "abcdeabcde",  },
+  { 1, 2, "ag*b", "abcde",  },
+  { -1, -1, "[a-c][e-f]", "abcdef",  },
+  { 3, 4, "[a-c][e-f]", "acbedf",  },
+  { 4, 8, "abc*XYZ", "890abXYZ#*",  },
+  { 4, 9, "abc*XYZ", "890abcXYZ#*",  },
+  { 4, 15, "abc*XYZ", "890abcccccccXYZ#*",  },
+  { -1, -1, "abc*XYZ", "890abc*XYZ#*",  },
+  { 0, 0, "GA132", NULL, },
+  { 2, 4, "\\(*bc\\)", "a*bc",  },
+  { 1, 2, "\\(ab\\)", "abcde",  },
+  { 1, 10, "\\(a\\(b\\(c\\(d\\(e\\(f\\(g\\)h\\(i\\(j\\)\\)\\)\\)\\)\\)\\)\\)", "abcdefghijk",  },
+  { 3, 8, "43\\(2\\(6\\)*0\\)AB", "654320ABCD",  },
+  { 3, 9, "43\\(2\\(7\\)*0\\)AB", "6543270ABCD",  },
+  { 3, 12, "43\\(2\\(7\\)*0\\)AB", "6543277770ABCD",  },
+  { 0, 0, "GA133", NULL, },
+  { 1, 10, "\\(a\\(b\\(c\\(d\\(e\\(f\\(g\\)h\\(i\\(j\\)\\)\\)\\)\\)\\)\\)\\)", "abcdefghijk",  },
+  { -1, -1, "\\(a\\(b\\(c\\(d\\(e\\(f\\(g\\)h\\(i\\(k\\)\\)\\)\\)\\)\\)\\)\\)", "abcdefghijk",  },
+  { 0, 0, "GA134", NULL, },
+  { 2, 4, "\\(bb*\\)", "abbbc",  },
+  { 2, 2, "\\(bb*\\)", "ababbbc",  },
+  { 1, 6, "a\\(.*b\\)", "ababbbc",  },
+  { 1, 2, "a\\(b*\\)", "ababbbc",  },
+  { 1, 20, "a\\(.*b\\)c", "axcaxbbbcsxbbbbbbbbc",  },
+  { 0, 0, "GA135", NULL, },
+  { 1, 7, "\\(a\\(b\\(c\\(d\\(e\\)\\)\\)\\)\\)\\4", "abcdededede",  },
+  { 0, 0, NULL, "POSIX does not really specify whether a\\(b\\)*c\\1 matches acb." },
+  { 0, 0, NULL, "back references are supposed to expand to the last match, but what" },
+  { 0, 0, NULL, "if there never was a match as in this case?" },
+  { -1, -1, "a\\(b\\)*c\\1", "acb",  },
+  { 1, 11, "\\(a\\(b\\(c\\(d\\(e\\(f\\(g\\)h\\(i\\(j\\)\\)\\)\\)\\)\\)\\)\\)\\9", "abcdefghijjk",  },
+  { 0, 0, "GA136", NULL, },
+  { 0, 0, NULL, "These two tests have the same problem as the test in GA135.  No match" },
+  { 0, 0, NULL, "of a subexpression, why should the back reference be usable?" },
+  { 0, 0, NULL, "1 2 a\\(b\\)*c\\1 acb" },
+  { 0, 0, NULL, "4 7 a\\(b\\(c\\(d\\(f\\)*\\)\\)\\)\\4¦xYzabcdePQRST" },
+  { -1, -1, "a\\(b\\)*c\\1", "acb",  },
+  { -1, -1, "a\\(b\\(c\\(d\\(f\\)*\\)\\)\\)\\4", "xYzabcdePQRST",  },
+  { 0, 0, "GA137", NULL, },
+  { -2, -2, "\\(a\\(b\\)\\)\\3", "foo",  },
+  { -2, -2, "\\(a\\(b\\)\\)\\(a\\(b\\)\\)\\5", "foo",  },
+  { 0, 0, "GA138", NULL, },
+  { 1, 2, "ag*b", "abcde",  },
+  { 1, 10, "a.*b", "abababvbabc",  },
+  { 2, 5, "b*c", "abbbcdeabbbbbbcde",  },
+  { 2, 5, "bbb*c", "abbbcdeabbbbbbcde",  },
+  { 1, 5, "a\\(b\\)*c\\1", "abbcbbb",  },
+  { -1, -1, "a\\(b\\)*c\\1", "abbdbd",  },
+  { 0, 0, "\\([a-c]*\\)\\1", "abcacdef",  },
+  { 1, 6, "\\([a-c]*\\)\\1", "abcabcabcd",  },
+  { 1, 2, "a^*b", "ab",  },
+  { 1, 5, "a^*b", "a^^^b",  },
+  { 0, 0, "GA139", NULL, },
+  { 1, 2, "a\\{2\\}", "aaaa",  },
+  { 1, 7, "\\([a-c]*\\)\\{0,\\}", "aabcaab",  },
+  { 1, 2, "\\(a\\)\\1\\{1,2\\}", "aabc",  },
+  { 1, 3, "\\(a\\)\\1\\{1,2\\}", "aaaabc",  },
+  { 0, 0, NULL, "the expression \\(\\(a\\)\\1\\)\\{1,2\\} is ill-formed, using \\2" },
+  { 1, 4, "\\(\\(a\\)\\2\\)\\{1,2\\}", "aaaabc",  },
+  { 0, 0, "GA140", NULL, },
+  { 1, 2, "a\\{2\\}", "aaaa",  },
+  { -1, -1, "a\\{2\\}", "abcd",  },
+  { 0, 0, "a\\{0\\}", "aaaa",  },
+  { 1, 64, "a\\{64\\}", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",  },
+  { 0, 0, "GA141", NULL, },
+  { 1, 7, "\\([a-c]*\\)\\{0,\\}", "aabcaab",  },
+  { 0, 0, NULL, "the expected result for \\([a-c]*\\)\\{2,\\} is failure which isn't correct" },
+  { 1, 3, "\\([a-c]*\\)\\{2,\\}", "abcdefg",  },
+  { 1, 3, "\\([a-c]*\\)\\{1,\\}", "abcdefg",  },
+  { -1, -1, "a\\{64,\\}", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",  },
+  { 0, 0, "GA142", NULL, },
+  { 1, 3, "a\\{2,3\\}", "aaaa",  },
+  { -1, -1, "a\\{2,3\\}", "abcd",  },
+  { 0, 0, "\\([a-c]*\\)\\{0,0\\}", "foo",  },
+  { 1, 63, "a\\{1,63\\}", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",  },
+  { 0, 0, "2.8.3.4  BRE Precedence", NULL, },
+  { 0, 0, "GA143", NULL, },
+  { 0, 0, NULL, "There are numerous bugs in the original version." },
+  { 2, 19, "\\^\\[[[.].]]\\\\(\\\\1\\\\)\\*\\\\{1,2\\\\}\\$", "a^[]\\(\\1\\)*\\{1,2\\}$b",  },
+  { 1, 6, "[[=*=]][[=\\=]][[=]=]][[===]][[...]][[:punct:]]", "*\\]=.;",  },
+  { 1, 6, "[$\\(*\\)^]*", "$\\()*^",  },
+  { 1, 1, "[\\1]", "1",  },
+  { 1, 1, "[\\{1,2\\}]", "{",  },
+  { 0, 0, NULL, "the expected result for \\(*\\)*\\1* is 2-2 which isn't correct" },
+  { 0, 0, "\\(*\\)*\\1*", "a*b*11",  },
+  { 2, 3, "\\(*\\)*\\1*b", "a*b*11",  },
+  { 0, 0, NULL, "the expected result for \\(a\\(b\\{1,2\\}\\)\\{1,2\\}\\) is 1-5 which isn't correct" },
+  { 1, 3, "\\(a\\(b\\{1,2\\}\\)\\{1,2\\}\\)", "abbab",  },
+  { 1, 5, "\\(a\\(b\\{1,2\\}\\)\\)\\{1,2\\}", "abbab",  },
+  { 1, 1, "^\\(^\\(^a$\\)$\\)$", "a",  },
+  { 1, 2, "\\(a\\)\\1$", "aa",  },
+  { 1, 3, "ab*", "abb",  },
+  { 1, 4, "ab\\{2,4\\}", "abbbc",  },
+  { 0, 0, "2.8.3.5  BRE Expression Anchoring", NULL, },
+  { 0, 0, "GA144", NULL, },
+  { 1, 1, "^a", "abc",  },
+  { -1, -1, "^b", "abc",  },
+  { -1, -1, "^[a-zA-Z]", "99Nine",  },
+  { 1, 4, "^[a-zA-Z]*", "Nine99",  },
+  { 0, 0, "GA145(1)", NULL, },
+  { 1, 2, "\\(^a\\)\\1", "aabc",  },
+  { -1, -1, "\\(^a\\)\\1", "^a^abc",  },
+  { 1, 2, "\\(^^a\\)", "^a",  },
+  { 1, 1, "\\(^^\\)", "^^",  },
+  { 1, 3, "\\(^abc\\)", "abcdef",  },
+  { -1, -1, "\\(^def\\)", "abcdef",  },
+  { 0, 0, "GA146", NULL, },
+  { 3, 3, "a$", "cba",  },
+  { -1, -1, "a$", "abc",  },
+  { 5, 7, "[a-z]*$", "99ZZxyz",  },
+  { 0, 0, NULL, "the expected result for [a-z]*$ is failure which isn't correct" },
+  { 10, 9, "[a-z]*$", "99ZZxyz99",  },
+  { 3, 3, "$$", "ab$",  },
+  { -1, -1, "$$", "$ab",  },
+  { 3, 3, "\\$$", "ab$",  },
+  { 0, 0, "GA147(1)", NULL, },
+  { -1, -1, "\\(a$\\)\\1", "bcaa",  },
+  { -1, -1, "\\(a$\\)\\1", "ba$",  },
+  { -1, -1, "\\(ab$\\)", "ab$",  },
+  { 1, 2, "\\(ab$\\)", "ab",  },
+  { 4, 6, "\\(def$\\)", "abcdef",  },
+  { -1, -1, "\\(abc$\\)", "abcdef",  },
+  { 0, 0, "GA148", NULL, },
+  { 0, 0, "^$", "",  },
+  { 1, 3, "^abc$", "abc",  },
+  { -1, -1, "^xyz$", "^xyz^",  },
+  { -1, -1, "^234$", "^234$",  },
+  { 1, 9, "^[a-zA-Z0-9]*$", "2aA3bB9zZ",  },
+  { -1, -1, "^[a-z0-9]*$", "2aA3b#B9zZ",  },
Index: /tags/kBuild-0.1.4/src/sed/testsuite/readin.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/readin.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/readin.good	(revision 1780)
@@ -0,0 +1,19 @@
+``Democracy will not come today, this year,
+  nor ever through compromise and fear.
+MOO
+  I have as much right as the other fellow has
+  to stand on my two feet and own the land.
+MOO
+  I tire so of hearing people say
+  let things take their course,
+  tomorrow is another day.
+MOO
+  I do not need my freedom when I'm dead.
+MOO
+  I cannot live on tomorrow's bread.
+MOO
+  Freedom is a strong seed
+  planted in a great need.
+MOO
+  I live here, too.
+MOO
Index: /tags/kBuild-0.1.4/src/sed/testsuite/readin.in2
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/readin.in2	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/readin.in2	(revision 1780)
@@ -0,0 +1,1 @@
+MOO
Index: /tags/kBuild-0.1.4/src/sed/testsuite/readin.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/readin.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/readin.inp	(revision 1780)
@@ -0,0 +1,14 @@
+``Democracy will not come today, this year,
+  nor ever through compromise and fear.
+  I have as much right as the other fellow has
+  to stand on my two feet and own the land.
+  I tire so of hearing people say
+  let things take their course,
+  tomorrow is another day.
+  I do not need my freedom when I'm dead.
+  I cannot live on tomorrow's bread.
+  Freedom is a strong seed
+  planted in a great need.
+  I live here, too.
+  I want freedom just as you.''
+    ``The Weary Blues'', Langston Hughes
Index: /tags/kBuild-0.1.4/src/sed/testsuite/readin.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/readin.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/readin.sed	(revision 1780)
@@ -0,0 +1,2 @@
+/\.$/r readin.in2
+/too\.$/q
Index: /tags/kBuild-0.1.4/src/sed/testsuite/recall.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/recall.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/recall.good	(revision 1780)
@@ -0,0 +1,7 @@
+eeefff
+Xeefff
+XYefff
+XYeYff
+XYeYYf
+XYeYYY
+XYeYYY
Index: /tags/kBuild-0.1.4/src/sed/testsuite/recall.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/recall.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/recall.inp	(revision 1780)
@@ -0,0 +1,1 @@
+eeefff
Index: /tags/kBuild-0.1.4/src/sed/testsuite/recall.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/recall.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/recall.sed	(revision 1780)
@@ -0,0 +1,7 @@
+# Check that the empty regex recalls the last *executed* regex,
+# not the last *compiled* regex
+p
+s/e/X/p
+:x
+s//Y/p
+/f/bx
Index: /tags/kBuild-0.1.4/src/sed/testsuite/recall2.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/recall2.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/recall2.good	(revision 1780)
@@ -0,0 +1,1 @@
+>abb<||>abbbb<
Index: /tags/kBuild-0.1.4/src/sed/testsuite/recall2.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/recall2.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/recall2.inp	(revision 1780)
@@ -0,0 +1,1 @@
+ababb||abbbabbbb
Index: /tags/kBuild-0.1.4/src/sed/testsuite/recall2.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/recall2.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/recall2.sed	(revision 1780)
@@ -0,0 +1,5 @@
+# Starting from sed 4.1.3, regexes are compiled with REG_NOSUB
+# if they are used in an address, so that the matcher does not
+# have to obey leftmost-longest.  The tricky part is to recompile
+# them if they are then used in a substitution.
+/\(ab*\)\+/ s//>\1</g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/runptests.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/runptests.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/runptests.c	(revision 1780)
@@ -0,0 +1,123 @@
+/* POSIX regex testsuite from IEEE 2003.2.
+   Copyright (C) 1998, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include <sys/types.h>
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Data structure to describe the tests.  */
+struct test
+{
+  int start;
+  int end;
+  const char *reg;
+  const char *str;
+  int options;
+} tests[] =
+{
+#include "ptestcases.h"
+};
+
+
+int
+main (int argc, char *argv[])
+{
+  size_t cnt;
+  int errors = 0;
+
+  for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt)
+    if (tests[cnt].str == NULL)
+      {
+	printf ("\n%s\n%.*s\n", tests[cnt].reg,
+		(int) strlen (tests[cnt].reg),
+		"-----------------------------------------------------");
+      }
+    else if (tests[cnt].reg == NULL)
+	printf ("!!! %s\n", tests[cnt].str);
+    else
+      {
+	regex_t re;
+	regmatch_t match[20];
+	int err;
+
+	printf ("regexp: \"%s\", string: \"%s\" -> ", tests[cnt].reg,
+		tests[cnt].str);
+
+	/* Compile the expression.  */
+	err = regcomp (&re, tests[cnt].reg, tests[cnt].options);
+	if (err != 0)
+	  {
+	    if (tests[cnt].start == -2)
+	      puts ("compiling failed, OK");
+	    else
+	      {
+		char buf[100];
+		regerror (err, &re, buf, sizeof (buf));
+		printf ("FAIL: %s\n", buf);
+		++errors;
+	      }
+
+	    continue;
+	  }
+	else if (tests[cnt].start == -2)
+	  {
+	    puts ("compiling suceeds, FAIL");
+	    errors++;
+	    continue;
+	  }
+
+	/* Run the actual test.  */
+	err = regexec (&re, tests[cnt].str, 20, match, 0);
+
+	if (err != 0)
+	  {
+	    if (tests[cnt].start == -1)
+	      puts ("no match, OK");
+	    else
+	      {
+		puts ("no match, FAIL");
+		++errors;
+	      }
+	  }
+	else
+	  {
+	    if (match[0].rm_so == 0 && tests[cnt].start == 0
+		&& match[0].rm_eo == 0 && tests[cnt].end == 0)
+	      puts ("match, OK");
+	    else if (match[0].rm_so + 1 == tests[cnt].start
+		     && match[0].rm_eo == tests[cnt].end)
+	      puts ("match, OK");
+	    else
+	      {
+		printf ("wrong match (%d to %d): FAIL\n",
+			match[0].rm_so, match[0].rm_eo);
+		++errors;
+	      }
+	  }
+
+	/* Free all resources.  */
+	regfree (&re);
+      }
+
+  printf ("\n%Zu tests, %d errors\n", cnt, errors);
+
+  return errors != 0;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/runtest
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/runtest	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/runtest	(revision 1780)
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+: ${MAKE=make}
+: ${srcdir=.}
+: ${SED="../sed/sed"}
+
+makefile="$srcdir/Makefile.tests"
+test=`echo "$@"| sed 's,.*/,,'`
+
+# As a convenience, suppress the output of make if the test passes
+if $MAKE SED="$SED" srcdir="$srcdir" -f "$makefile" $test > tmp.test 2>&1; then
+  rm -f tmp.test
+else
+  exitcode=$?
+  cat tmp.test
+  rm -f tmp.test
+  exit $exitcode
+fi
Index: /tags/kBuild-0.1.4/src/sed/testsuite/runtests.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/runtests.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/runtests.c	(revision 1780)
@@ -0,0 +1,142 @@
+/***********************************************************
+
+Copyright 1995 by Tom Lord
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 the copyright holder not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+Tom Lord DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL TOM LORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+
+
+
+#include <sys/types.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+
+struct a_test
+{
+  int expected;
+  const char * pattern;
+  const unsigned char * data;
+};
+
+static const struct a_test the_tests[] =
+{
+#include "testcases.h"
+  {-1, 0, 0}
+};
+
+
+
+
+
+static int
+run_a_test (int id, const struct a_test * t)
+{
+  static const char * last_pattern = 0;
+  static regex_t r;
+  int err;
+  char errmsg[100];
+  int x;
+  regmatch_t regs[10];
+
+  if (!last_pattern || strcmp (last_pattern, t->pattern))
+    {
+      if (last_pattern)
+	regfree (&r);
+      last_pattern = t->pattern;
+      err = regcomp (&r, t->pattern, REG_EXTENDED);
+      if (err)
+	{
+	  if (t->expected == 2)
+	    {
+	      puts (" OK.");
+	      return 0;
+	    }
+	  if (last_pattern)
+	    regfree (&r);
+	  last_pattern = NULL;
+	  regerror (err, &r, errmsg, 100);
+	  printf (" FAIL: %s.\n", errmsg);
+	  return 1;
+	}
+      else if (t->expected == 2)
+	{
+	  printf ("test %d\n", id);
+	  printf ("pattern \"%s\" successfull compilation not expected\n",
+		  t->pattern);
+	  return 1;
+	}
+    }
+
+  err = regexec (&r, t->data, 10, regs, 0);
+
+  if (err != t->expected)
+    {
+      printf ("test %d\n", id);
+      printf ("pattern \"%s\" data \"%s\" wanted %d got %d\n",
+	      t->pattern, t->data, t->expected, err);
+      for (x = 0; x < 10; ++x)
+	printf ("reg %d == (%d, %d) %.*s\n",
+		x,
+		regs[x].rm_so,
+		regs[x].rm_eo,
+		regs[x].rm_eo - regs[x].rm_so,
+		t->data + regs[x].rm_so);
+      return 1;
+    }
+  puts (" OK.");
+  return 0;
+}
+
+
+
+
+int
+main (int argc, char * argv[])
+{
+  int x;
+  int lo;
+  int hi;
+  int res = 0;
+
+  lo = 0;
+  hi = (sizeof (the_tests) / sizeof (the_tests[0])) - 1;
+
+  if (argc > 1)
+    {
+      lo = atoi (argv[1]);
+      hi = lo + 1;
+
+      if (argc > 2)
+	hi = atoi (argv[2]);
+    }
+
+  for (x = lo; x < hi; ++x)
+    {
+      printf ("#%d:", x);
+      res |= run_a_test (x, &the_tests[x]);
+    }
+  return res != 0;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/sep.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/sep.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/sep.good	(revision 1780)
@@ -0,0 +1,3 @@
+
+///
+//
Index: /tags/kBuild-0.1.4/src/sed/testsuite/sep.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/sep.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/sep.inp	(revision 1780)
@@ -0,0 +1,3 @@
+miss mary mack mack//mack/ran down/the track  track  track
+slashes\aren't%used enough/in/casual-conversation///
+possibly sentences would be more attractive if they ended in two slashes//
Index: /tags/kBuild-0.1.4/src/sed/testsuite/sep.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/sep.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/sep.sed	(revision 1780)
@@ -0,0 +1,4 @@
+# inspired by an autoconf generated configure script.
+s%/[^/][^/]*$%%
+s%[\/][^\/][^\/]*$%%
+s,.*[^\/],,
Index: /tags/kBuild-0.1.4/src/sed/testsuite/space.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/space.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/space.good	(revision 1780)
@@ -0,0 +1,2 @@
+Hello_World_!
+SecondXXine__of_tests
Index: /tags/kBuild-0.1.4/src/sed/testsuite/space.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/space.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/space.inp	(revision 1780)
@@ -0,0 +1,2 @@
+Hello World	!
+Second_line_ of tests
Index: /tags/kBuild-0.1.4/src/sed/testsuite/space.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/space.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/space.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/_\S/XX/g;s/\s/_/g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/subwrite.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/subwrite.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/subwrite.inp	(revision 1780)
@@ -0,0 +1,4 @@
+Not some church, and not the state,
+Not some dark capricious fate.
+Who you are, and when you lose,
+Comes only from the things you choose.
Index: /tags/kBuild-0.1.4/src/sed/testsuite/subwrite.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/subwrite.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/subwrite.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/you/YoU/w subwrite.wout
Index: /tags/kBuild-0.1.4/src/sed/testsuite/subwrt1.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/subwrt1.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/subwrt1.good	(revision 1780)
@@ -0,0 +1,4 @@
+Not some church, and not the state,
+Not some dark capricious fate.
+Who YoU are, and when you lose,
+Comes only from the things YoU choose.
Index: /tags/kBuild-0.1.4/src/sed/testsuite/subwrt2.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/subwrt2.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/subwrt2.good	(revision 1780)
@@ -0,0 +1,2 @@
+Who YoU are, and when you lose,
+Comes only from the things YoU choose.
Index: /tags/kBuild-0.1.4/src/sed/testsuite/testcases.h
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/testcases.h	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/testcases.h	(revision 1780)
@@ -0,0 +1,167 @@
+  {0, "(.*)*\\1", "xx"},
+  {0, "^", ""},
+  {0, "$", ""},
+  {0, "^$", ""},
+  {0, "^a$", "a"},
+  {0, "abc", "abc"},
+  {1, "abc", "xbc"},
+  {1, "abc", "axc"},
+  {1, "abc", "abx"},
+  {0, "abc", "xabcy"},
+  {0, "abc", "ababc"},
+  {0, "ab*c", "abc"},
+  {0, "ab*bc", "abc"},
+  {0, "ab*bc", "abbc"},
+  {0, "ab*bc", "abbbbc"},
+  {0, "ab+bc", "abbc"},
+  {1, "ab+bc", "abc"},
+  {1, "ab+bc", "abq"},
+  {0, "ab+bc", "abbbbc"},
+  {0, "ab?bc", "abbc"},
+  {0, "ab?bc", "abc"},
+  {1, "ab?bc", "abbbbc"},
+  {0, "ab?c", "abc"},
+  {0, "^abc$", "abc"},
+  {1, "^abc$", "abcc"},
+  {0, "^abc", "abcc"},
+  {1, "^abc$", "aabc"},
+  {0, "abc$", "aabc"},
+  {0, "^", "abc"},
+  {0, "$", "abc"},
+  {0, "a.c", "abc"},
+  {0, "a.c", "axc"},
+  {0, "a.*c", "axyzc"},
+  {1, "a.*c", "axyzd"},
+  {1, "a[bc]d", "abc"},
+  {0, "a[bc]d", "abd"},
+  {1, "a[b-d]e", "abd"},
+  {0, "a[b-d]e", "ace"},
+  {0, "a[b-d]", "aac"},
+  {0, "a[-b]", "a-"},
+  {0, "a[b-]", "a-"},
+  {2, "a[b-a]", "-"},
+  {2, "a[]b", "-"},
+  {2, "a[", "-"},
+  {0, "a]", "a]"},
+  {0, "a[]]b", "a]b"},
+  {0, "a[^bc]d", "aed"},
+  {1, "a[^bc]d", "abd"},
+  {0, "a[^-b]c", "adc"},
+  {1, "a[^-b]c", "a-c"},
+  {1, "a[^]b]c", "a]c"},
+  {0, "a[^]b]c", "adc"},
+  {0, "ab|cd", "abc"},
+  {0, "ab|cd", "abcd"},
+  {0, "()ef", "def"},
+  {0, "()*", "-"},
+  {2, "*a", "-"},
+  {2, "^*", "-"},
+  {2, "$*", "-"},
+  {2, "(*)b", "-"},
+  {1, "$b", "b"},
+  {2, "a\\", "-"},
+  {0, "a\\(b", "a(b"},
+  {0, "a\\(*b", "ab"},
+  {0, "a\\(*b", "a((b"},
+  {1, "a\\x", "a\\x"},
+  {1, "abc)", "-"},
+  {2, "(abc", "-"},
+  {0, "((a))", "abc"},
+  {0, "(a)b(c)", "abc"},
+  {0, "a+b+c", "aabbabc"},
+  {0, "a**", "-"},
+  {0, "a*?", "-"},
+  {0, "(a*)*", "-"},
+  {0, "(a*)+", "-"},
+  {0, "(a|)*", "-"},
+  {0, "(a*|b)*", "-"},
+  {0, "(a+|b)*", "ab"},
+  {0, "(a+|b)+", "ab"},
+  {0, "(a+|b)?", "ab"},
+  {0, "[^ab]*", "cde"},
+  {0, "(^)*", "-"},
+  {0, "(ab|)*", "-"},
+  {2, ")(", "-"},
+  {1, "abc", ""},
+  {1, "abc", ""},
+  {0, "a*", ""},
+  {0, "([abc])*d", "abbbcd"},
+  {0, "([abc])*bcd", "abcd"},
+  {0, "a|b|c|d|e", "e"},
+  {0, "(a|b|c|d|e)f", "ef"},
+  {0, "((a*|b))*", "-"},
+  {0, "abcd*efg", "abcdefg"},
+  {0, "ab*", "xabyabbbz"},
+  {0, "ab*", "xayabbbz"},
+  {0, "(ab|cd)e", "abcde"},
+  {0, "[abhgefdc]ij", "hij"},
+  {1, "^(ab|cd)e", "abcde"},
+  {0, "(abc|)ef", "abcdef"},
+  {0, "(a|b)c*d", "abcd"},
+  {0, "(ab|ab*)bc", "abc"},
+  {0, "a([bc]*)c*", "abc"},
+  {0, "a([bc]*)(c*d)", "abcd"},
+  {0, "a([bc]+)(c*d)", "abcd"},
+  {0, "a([bc]*)(c+d)", "abcd"},
+  {0, "a[bcd]*dcdcde", "adcdcde"},
+  {1, "a[bcd]+dcdcde", "adcdcde"},
+  {0, "(ab|a)b*c", "abc"},
+  {0, "((a)(b)c)(d)", "abcd"},
+  {0, "[A-Za-z_][A-Za-z0-9_]*", "alpha"},
+  {0, "^a(bc+|b[eh])g|.h$", "abh"},
+  {0, "(bc+d$|ef*g.|h?i(j|k))", "effgz"},
+  {0, "(bc+d$|ef*g.|h?i(j|k))", "ij"},
+  {1, "(bc+d$|ef*g.|h?i(j|k))", "effg"},
+  {1, "(bc+d$|ef*g.|h?i(j|k))", "bcdd"},
+  {0, "(bc+d$|ef*g.|h?i(j|k))", "reffgz"},
+  {1, "((((((((((a))))))))))", "-"},
+  {0, "(((((((((a)))))))))", "a"},
+  {1, "multiple words of text", "uh-uh"},
+  {0, "multiple words", "multiple words, yeah"},
+  {0, "(.*)c(.*)", "abcde"},
+  {1, "\\((.*),", "(.*)\\)"},
+  {1, "[k]", "ab"},
+  {0, "abcd", "abcd"},
+  {0, "a(bc)d", "abcd"},
+  {0, "a[-]?c", "ac"},
+  {0, "(....).*\\1", "beriberi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Qaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mo'ammar Gadhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Kaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Qadhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Moammar El Kadhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Gadafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mu'ammar al-Qadafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Moamer El Kazzafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Moamar al-Gaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mu'ammar Al Qathafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Al Qathafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mo'ammar el-Gadhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Moamar El Kadhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar al-Qadhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mu'ammar al-Qadhdhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mu'ammar Qadafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Moamar Gaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mu'ammar Qadhdhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Khaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar al-Khaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mu'amar al-Kadafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Ghaddafy"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Ghadafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Ghaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muamar Kaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Quathafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muammar Gheddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Muamar Al-Kaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Moammar Khadafy "},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Moammar Qudhafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mu'ammar al-Qaddafi"},
+  {0, "M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", "Mulazim Awwal Mu'ammar Muhammad Abu Minyar al-Qadhafi"},
+  {0, "[[:digit:]]+", "01234"},
+  {1, "[[:alpha:]]+", "01234"},
+  {0, "^[[:digit:]]*$", "01234"},
+  {1, "^[[:digit:]]*$", "01234a"},
+  {0, "^[[:alnum:]]*$", "01234a"},
+  {0, "^[[:xdigit:]]*$", "01234a"},
+  {1, "^[[:xdigit:]]*$", "01234g"},
+  {0, "^[[:alnum:][:space:]]*$", "Hello world"},
Index: /tags/kBuild-0.1.4/src/sed/testsuite/tst-boost.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/tst-boost.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/tst-boost.c	(revision 1780)
@@ -0,0 +1,233 @@
+/* Regular expression tests.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void
+frob_escapes (char *src, int pattern)
+{
+  char *dst;
+
+  for (dst = src; *src != '\0'; dst++, src++)
+    {
+      if (*src == '\\')
+	{
+	  switch (src[1])
+	    {
+	    case 't':
+	      src++;
+	      *dst = '\t';
+	      continue;
+	    case 'n':
+	      src++;
+	      *dst = '\n';
+	      continue;
+	    case 'r':
+	      src++;
+	      *dst = '\r';
+	      continue;
+	    case '\\':
+	    case '^':
+	    case '{':
+	    case '|':
+	    case '}':
+	      if (!pattern)
+		{
+		  src++;
+		  *dst = *src;
+		  continue;
+		}
+	      break;
+	    }
+	}
+      if (src != dst)
+	*dst = *src;
+    }
+  *dst = '\0';
+}
+
+int
+main (int argc, char **argv)
+{
+  int ret = 0, n;
+  char *line = NULL;
+  size_t line_len = 0;
+  ssize_t len;
+  FILE *f;
+  char *pattern, *string;
+  int flags = REG_EXTENDED;
+  int eflags = 0;
+  regex_t re;
+  regmatch_t rm[20];
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  if (argc < 2)
+    {
+      fprintf (stderr, "Missing test filename\n");
+      return 1;
+    }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL)
+    {
+      fprintf (stderr, "Couldn't open %s\n", argv[1]);
+      return 1;
+    }
+
+  while ((len = getline (&line, &line_len, f)) > 0)
+    {
+      char *p, *q;
+      int i;
+
+      if (line[len - 1] == '\n')
+	line[--len] = '\0';
+
+      puts (line);
+
+      if (line[0] == ';')
+	continue;
+
+      if (line[0] == '\0')
+	continue;
+
+      if (line[0] == '-')
+	{
+	  if (strstr (line, "REG_BASIC"))
+	    flags = 0;
+	  else
+	    flags = REG_EXTENDED;
+	  if (strstr (line, "REG_ICASE"))
+	    flags |= REG_ICASE;
+	  if (strstr (line, "REG_NEWLINE"))
+	    flags |= REG_NEWLINE;
+	  eflags = 0;
+	  if (strstr (line, "REG_NOTBOL"))
+	    eflags |= REG_NOTBOL;
+	  if (strstr (line, "REG_NOTEOL"))
+	    eflags |= REG_NOTEOL;
+	  continue;
+	}
+
+      pattern = line + strspn (line, " \t");
+      if (*pattern == '\0')
+	continue;
+      p = pattern + strcspn (pattern, " \t");
+      if (*p == '\0')
+	continue;
+      *p++ = '\0';
+
+      string = p + strspn (p, " \t");
+      if (*string == '\0')
+	continue;
+      if (*string == '"')
+	{
+	  string++;
+	  p = strchr (string, '"');
+	  if (p == NULL)
+	    continue;
+	  *p++ = '\0';
+	}
+      else
+	{
+	  p = string + strcspn (string, " \t");
+	  if (*string == '!')
+	    string = NULL;
+	  else if (*p == '\0')
+	    continue;
+	  else
+	    *p++ = '\0';
+	}
+
+      frob_escapes (pattern, 1);
+      if (string != NULL)
+	frob_escapes (string, 0);
+
+      n = regcomp (&re, pattern, flags);
+      if (n != 0)
+	{
+	  if (string != NULL)
+	    {
+	      char buf[500];
+	      regerror (n, &re, buf, sizeof (buf));
+	      printf ("FAIL regcomp unexpectedly failed: %s\n",
+		      buf);
+	      ret = 1;
+	    }
+	  continue;
+	}
+      else if (string == NULL)
+	{
+	  regfree (&re);
+	  puts ("FAIL regcomp unpexpectedly succeeded");
+	  ret = 1;
+	  continue;
+	}
+
+      if (regexec (&re, string, 20, rm, eflags))
+	{
+	  for (i = 0; i < 20; ++i)
+	    {
+	      rm[i].rm_so = -1;
+	      rm[i].rm_eo = -1;
+	    }
+	}
+
+      regfree (&re);
+
+      for (i = 0; i < 20 && *p != '\0'; ++i)
+	{
+	  int rm_so, rm_eo;
+
+	  rm_so = strtol (p, &q, 10);
+	  if (p == q)
+	    break;
+	  p = q;
+
+	  rm_eo = strtol (p, &q, 10);
+	  if (p == q)
+	    break;
+	  p = q;
+
+	  if (rm[i].rm_so != rm_so || rm[i].rm_eo != rm_eo)
+	    {
+	      printf ("FAIL rm[%d] %d..%d != expected %d..%d\n",
+		      i, rm[i].rm_so, rm[i].rm_eo, rm_so, rm_eo);
+	      ret = 1;
+	      break;
+	    }
+	}
+    }
+
+  free (line);
+  fclose (f);
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/tst-pcre.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/tst-pcre.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/tst-pcre.c	(revision 1780)
@@ -0,0 +1,247 @@
+/* Regular expression tests.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main (int argc, char **argv)
+{
+  int ret = 0;
+  char *line = NULL;
+  size_t line_len = 0;
+  ssize_t len;
+  FILE *f;
+  char *pattern = NULL, *string = NULL;
+  regmatch_t rm[20];
+  size_t pattern_alloced = 0, string_alloced = 0;
+  int ignorecase = 0;
+  int pattern_valid = 0, rm_valid = 0;
+  size_t linenum;
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  if (argc < 2)
+    {
+      fprintf (stderr, "Missing test filename\n");
+      return 1;
+    }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL)
+    {
+      fprintf (stderr, "Couldn't open %s\n", argv[1]);
+      return 1;
+    }
+
+  if ((len = getline (&line, &line_len, f)) <= 0
+      || strncmp (line, "# PCRE", 6) != 0)
+    {
+      fprintf (stderr, "Not a PCRE test file\n");
+      fclose (f);
+      free (line);
+      return 1;
+    }
+
+  linenum = 1;
+
+  while ((len = getline (&line, &line_len, f)) > 0)
+    {
+      char *p;
+      unsigned long num;
+
+      ++linenum;
+
+      if (line[len - 1] == '\n')
+	line[--len] = '\0';
+
+      if (line[0] == '#')
+	continue;
+
+      if (line[0] == '\0')
+	{
+	  /* End of test.  */
+	  ignorecase = 0;
+	  pattern_valid = 0;
+	  rm_valid = 0;
+	  continue;
+	}
+
+      if (line[0] == '/')
+	{
+	  /* Pattern.  */
+	  p = strrchr (line + 1, '/');
+
+	  pattern_valid = 0;
+	  rm_valid = 0;
+	  if (p == NULL)
+	    {
+	      printf ("%lu: Invalid pattern line: %s\n", linenum, line);
+	      ret = 1;
+	      continue;
+	    }
+
+	  if (p[1] == 'i' && p[2] == '\0')
+	    ignorecase = 1;
+	  else if (p[1] != '\0')
+	    {
+	      printf ("%lu: Invalid pattern line: %s\n", linenum, line);
+	      ret = 1;
+	      continue;
+	    }
+
+	  if (pattern_alloced < (size_t) (p - line))
+	    {
+	      pattern = realloc (pattern, p - line);
+	      if (pattern == NULL)
+		{
+		  printf ("%lu: Cannot record pattern: %m\n", linenum);
+		  ret = 1;
+		  break;
+		}
+	      pattern_alloced = p - line;
+	    }
+
+	  memcpy (pattern, line + 1, p - line - 1);
+	  pattern[p - line - 1] = '\0';
+	  pattern_valid = 1;
+	  continue;
+	}
+
+      if (strncmp (line, "    ", 4) == 0)
+	{
+	  regex_t re;
+	  int n;
+    
+	  if (!pattern_valid)
+	    {
+	      printf ("%lu: No previous valid pattern %s\n", linenum, line);
+	      continue;
+	    }
+
+	  if (string_alloced < (size_t) (len - 3))
+	    {
+	      string = realloc (string, len - 3);
+	      if (string == NULL)
+		{
+		  printf ("%lu: Cannot record search string: %m\n", linenum);
+		  ret = 1;
+		  break;
+		}
+	      string_alloced = len - 3;
+	    }
+
+	  memcpy (string, line + 4, len - 3);
+
+	  n = regcomp (&re, pattern,
+		       REG_EXTENDED | (ignorecase ? REG_ICASE : 0));
+	  if (n != 0)
+	    {
+	      char buf[500];
+	      regerror (n, &re, buf, sizeof (buf));
+	      printf ("%lu: regcomp failed for %s: %s\n",
+		      linenum, pattern, buf);
+	      ret = 1;
+	      continue;
+	    }
+
+	  if (regexec (&re, string, 20, rm, 0))
+	    {
+	      rm[0].rm_so = -1;
+	      rm[0].rm_eo = -1;
+	    }
+
+	  regfree (&re);
+	  rm_valid = 1;
+	  continue;
+	}
+
+      if (!rm_valid)
+	{
+	  printf ("%lu: No preceeding pattern or search string\n", linenum);
+	  ret = 1;
+	  continue;
+	}
+
+      if (strcmp (line, "No match") == 0)
+	{
+	  if (rm[0].rm_so != -1 || rm[0].rm_eo != -1)
+	    {
+	      printf ("%lu: /%s/ on %s unexpectedly matched %d..%d\n",
+		      linenum, pattern, string, rm[0].rm_so, rm[0].rm_eo);
+	      ret = 1;
+	    }
+
+	  continue;
+	}
+
+      p = line;
+      if (*p == ' ')
+        ++p;
+
+      num = strtoul (p, &p, 10);
+      if (num >= 20 || *p != ':' || p[1] != ' ')
+	{
+	  printf ("%lu: Invalid line %s\n", linenum, line);
+	  ret = 1;
+	  continue;
+	}
+
+      if (rm[num].rm_so == -1 || rm[num].rm_eo == -1)
+	{
+	  if (strcmp (p + 2, "<unset>") != 0)
+	    {
+	      printf ("%lu: /%s/ on %s unexpectedly failed to match register %ld %d..%d\n",
+		      linenum, pattern, string, num,
+		      rm[num].rm_so, rm[num].rm_eo);
+	      ret = 1;
+	    }
+	  continue;
+	}
+
+      if (rm[num].rm_eo < rm[num].rm_so
+	  || rm[num].rm_eo - rm[num].rm_so != len - (p + 2 - line)
+	  || strncmp (p + 2, string + rm[num].rm_so,
+		      rm[num].rm_eo - rm[num].rm_so) != 0)
+	{
+	  printf ("%lu: /%s/ on %s unexpectedly failed to match %s for register %ld %d..%d\n",
+		  linenum, pattern, string, p + 2, num,
+		  rm[num].rm_so, rm[num].rm_eo);
+	  ret = 1;
+	  continue;
+	}
+    }
+
+  free (pattern);
+  free (string);
+  free (line);
+  fclose (f);
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/tst-regex2.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/tst-regex2.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/tst-regex2.c	(revision 1780)
@@ -0,0 +1,205 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+int
+main (int argc, char *argv[])
+{
+  struct stat st;
+  static const char *pat[] = {
+    ".?.?.?.?.?.?.?argc",
+    "(.?)(.?)(.?)(.?)(.?)(.?)(.?)argc",
+    "((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))"
+    "((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))"
+    "((((((((((.?))))))))))argc" };
+
+  size_t len;
+  int fd;
+  int testno, i, j, k, l;
+  char *string;
+  char *buf;
+
+  if (argc < 2)
+    abort ();
+
+  fd = open (argv[1], O_RDONLY);
+  if (fd < 0)
+    {
+      printf ("Couldn't open %s: %s\n", argv[1], strerror (errno));
+      abort ();
+    }
+
+  if (fstat (fd, &st) < 0)
+    {
+      printf ("Couldn't fstat %s: %s\n", argv[1], strerror (errno));
+      abort ();
+    }
+
+  buf = malloc (st.st_size + 1);
+  if (buf == NULL)
+    {
+      printf ("Couldn't allocate buffer: %s\n", strerror (errno));
+      abort ();
+    }
+
+  if (read (fd, buf, st.st_size) != (ssize_t) st.st_size)
+    {
+      printf ("Couldn't read %s", argv[1]);
+      abort ();
+    }
+
+  close (fd);
+  buf[st.st_size] = '\0';
+
+  string = buf;
+  len = st.st_size;
+
+  for (testno = 0; testno < 4; ++testno)
+    for (i = 0; i < sizeof (pat) / sizeof (pat[0]); ++i)
+      {
+	regex_t rbuf;
+	struct re_pattern_buffer rpbuf;
+	int err;
+
+	printf ("test %d pattern %d", testno, i);
+	if (testno < 2)
+	  {
+	    err = regcomp (&rbuf, pat[i],
+			   REG_EXTENDED | (testno ? REG_NOSUB : 0));
+	    if (err != 0)
+	      {
+		char errstr[300];
+		putchar ('\n');
+		regerror (err, &rbuf, errstr, sizeof (errstr));
+		puts (errstr);
+		return err;
+	      }
+	  }
+	else
+	  {
+	    const char *s;
+	    re_set_syntax (RE_SYNTAX_POSIX_EGREP
+			   | (testno == 3 ? RE_NO_SUB : 0));
+
+	    memset (&rpbuf, 0, sizeof (rpbuf));
+	    s = re_compile_pattern (pat[i], strlen (pat[i]), &rpbuf);
+	    if (s != NULL)
+	      {
+		printf ("\n%s\n", s);
+		abort ();
+	      }
+
+	    /* Just so that this can be tested with earlier glibc as well.  */
+	    if (testno == 3)
+	      rpbuf.no_sub = 1;
+	  }
+
+      if (testno < 2)
+	{
+	  regmatch_t pmatch[71];
+	  err = regexec (&rbuf, string, 71, pmatch, 0);
+	  if (err == REG_NOMATCH)
+	    {
+	      puts ("\nregexec failed");
+	      abort ();
+	    }
+
+	  if (testno == 0)
+	    {
+	      if (pmatch[0].rm_eo != pmatch[0].rm_so + 11
+		  || pmatch[0].rm_eo > len
+		  || string + pmatch[0].rm_so >= strchr (string, 'R')
+		  || strncmp (string + pmatch[0].rm_so,
+			      "n (int argc",
+			      sizeof "n (int argc" - 1)
+		     != 0)
+		{
+		  puts ("\nregexec without REG_NOSUB did not find the correct match");
+		  abort ();
+		}
+
+	      if (i > 0)
+		for (j = 0, l = 1; j < 7; ++j)
+		  for (k = 0; k < (i == 1 ? 1 : 10); ++k, ++l)
+		    if (pmatch[l].rm_so != pmatch[0].rm_so + j
+			|| pmatch[l].rm_eo != pmatch[l].rm_so + 1)
+		      {
+			printf ("\npmatch[%d] incorrect\n", l);
+			abort ();
+		      }
+	    }
+	}
+      else
+	{
+	  struct re_registers regs;
+	  int match;
+
+	  memset (&regs, 0, sizeof (regs));
+	  match = re_search (&rpbuf, string, len, 0, len,
+				 &regs);
+	  if (match < 0)
+	    {
+	      puts ("\nre_search failed");
+	      abort ();
+	    }
+
+	  if (match + 11 > len
+	      || string + match >= strchr (string, 'R')
+	      || strncmp (string + match,
+			  "n (int argc",
+			  sizeof "n (int argc" - 1)
+		  != 0)
+	    {
+	      puts ("\nre_search did not find the correct match");
+	      abort ();
+	    }
+
+	  if (testno == 2)
+	    {
+	      if (regs.num_regs != 2 + (i == 0 ? 0 : i == 1 ? 7 : 70))
+		{
+		  printf ("\nincorrect num_regs %d\n", regs.num_regs);
+		  abort ();
+		}
+
+	      if (regs.start[0] != match || regs.end[0] != match + 11)
+		{
+		  printf ("\nincorrect regs.{start,end}[0] = { %d, %d}\n",
+			  regs.start[0], regs.end[0]);
+		  abort ();
+		}
+
+	      if (regs.start[regs.num_regs - 1] != -1
+		  || regs.end[regs.num_regs - 1] != -1)
+		{
+		  puts ("\nincorrect regs.{start,end}[num_regs - 1]");
+		  abort ();
+		}
+
+	      if (i > 0)
+		for (j = 0, l = 1; j < 7; ++j)
+		  for (k = 0; k < (i == 1 ? 1 : 10); ++k, ++l)
+		    if (regs.start[l] != match + j
+			|| regs.end[l] != regs.start[l] + 1)
+		      {
+			printf ("\nregs.{start,end}[%d] incorrect\n", l);
+			abort ();
+		      }
+	    }
+	}
+
+      putchar ('\n');
+
+      if (testno < 2)
+	regfree (&rbuf);
+      else
+	regfree (&rpbuf);
+    }
+
+  exit (0);
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/tst-rxspencer.c
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/tst-rxspencer.c	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/tst-rxspencer.c	(revision 1780)
@@ -0,0 +1,558 @@
+/* Regular expression tests.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <getopt.h>
+
+static void
+replace_special_chars (char *str)
+{
+  for (; (str = strpbrk (str, "NTSZ")) != NULL; ++str)
+    switch (*str)
+      {
+      case 'N': *str = '\n'; break;
+      case 'T': *str = '\t'; break;
+      case 'S': *str = ' '; break;
+      case 'Z': *str = '\0'; break;
+      }
+}
+
+static void
+glibc_re_syntax (char *str)
+{
+  char *p, *end = strchr (str, '\0') + 1;
+
+  /* Replace [[:<:]] with \< and [[:>:]] with \>.  */
+  for (p = str; (p = strstr (p, "[[:")) != NULL; )
+    if ((p[3] == '<' || p[3] == '>') && strncmp (p + 4, ":]]", 3) == 0)
+      {
+        p[0] = '\\';
+        p[1] = p[3];
+        memmove (p + 2, p + 7, end - p - 7);
+        end -= 5;
+        p += 2;
+      }
+    else
+      p += 3;
+}
+
+static char *
+mb_replace (char *dst, const char c)
+{
+  switch (c)
+    {
+    /* Replace a with \'a and A with \'A.  */
+    case 'a':
+      *dst++ = '\xc3';
+      *dst++ = '\xa1';
+      break;
+    case 'A':
+      *dst++ = '\xc3';
+      *dst++ = '\x81';
+      break;
+    /* Replace b with \v{c} and B with \v{C}.  */
+    case 'b':
+      *dst++ = '\xc4';
+      *dst++ = '\x8d';
+      break;
+    case 'B':
+      *dst++ = '\xc4';
+      *dst++ = '\x8c';
+      break;
+    /* Replace c with \v{d} and C with \v{D}.  */
+    case 'c':
+      *dst++ = '\xc4';
+      *dst++ = '\x8f';
+      break;
+    case 'C':
+      *dst++ = '\xc4';
+      *dst++ = '\x8e';
+      break;
+    /* Replace d with \'e and D with \'E.  */
+    case 'd':
+      *dst++ = '\xc3';
+      *dst++ = '\xa9';
+      break;
+    case 'D':
+      *dst++ = '\xc3';
+      *dst++ = '\x89';
+      break;
+    }
+  return dst;
+}
+
+static char *
+mb_frob_string (const char *str, const char *letters)
+{
+  char *ret, *dst;
+  const char *src;
+
+  if (str == NULL)
+    return NULL;
+
+  ret = malloc (2 * strlen (str) + 1);
+  if (ret == NULL)
+    return NULL;
+
+  for (src = str, dst = ret; *src; ++src)
+    if (strchr (letters, *src))
+      dst = mb_replace (dst, *src);
+    else
+      *dst++ = *src;
+  *dst = '\0';
+  return ret;
+}
+
+/* Like mb_frob_string, but don't replace anything between
+   [: and :], [. and .] or [= and =].  */
+
+static char *
+mb_frob_pattern (const char *str, const char *letters)
+{
+  char *ret, *dst;
+  const char *src;
+  int in_class = 0;
+
+  if (str == NULL)
+    return NULL;
+
+  ret = malloc (2 * strlen (str) + 1);
+  if (ret == NULL)
+    return NULL;
+
+  for (src = str, dst = ret; *src; ++src)
+    if (!in_class && strchr (letters, *src))
+      dst = mb_replace (dst, *src);
+    else
+      {
+	if (!in_class && *src == '[' && strchr (":.=", src[1]))
+	  in_class = 1;
+	else if (in_class && *src == ']' && strchr (":.=", src[-1]))
+	  in_class = 0;
+	*dst++ = *src;
+      }
+  *dst = '\0';
+  return ret;
+}
+
+static int
+check_match (regmatch_t *rm, int idx, const char *string,
+	     const char *match, const char *fail)
+{
+  if (match[0] == '-' && match[1] == '\0')
+    {
+      if (rm[idx].rm_so == -1 && rm[idx].rm_eo == -1)
+	return 0;
+      printf ("%s rm[%d] unexpectedly matched\n", fail, idx);
+      return 1;
+    }
+
+  if (rm[idx].rm_so == -1 || rm[idx].rm_eo == -1)
+    {
+      printf ("%s rm[%d] unexpectedly did not match\n", fail, idx);
+      return 1;
+    }
+
+  if (match[0] == '@')
+    {
+      if (rm[idx].rm_so != rm[idx].rm_eo)
+	{
+	  printf ("%s rm[%d] not empty\n", fail, idx);
+	  return 1;
+	}
+
+      if (strncmp (string + rm[idx].rm_so, match + 1, strlen (match + 1)
+						      ? strlen (match + 1) : 1))
+	{
+	  printf ("%s rm[%d] not matching %s\n", fail, idx, match);
+	  return 1;
+	}
+      return 0;
+    }
+
+  if (rm[idx].rm_eo - rm[idx].rm_so != strlen (match)
+      || strncmp (string + rm[idx].rm_so, match,
+		  rm[idx].rm_eo - rm[idx].rm_so))
+    {
+      printf ("%s rm[%d] not matching %s\n", fail, idx, match);
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+test (const char *pattern, int cflags, const char *string, int eflags,
+      char *expect, char *matches, const char *fail)
+{
+  regex_t re;
+  regmatch_t rm[10];
+  int n, ret = 0;
+
+  n = regcomp (&re, pattern, cflags);
+  if (n != 0)
+    {
+      char buf[500];
+      if (eflags == -1)
+	{
+	  static struct { reg_errcode_t code; const char *name; } codes []
+#define C(x) { REG_##x, #x }
+	    = { C(NOERROR), C(NOMATCH), C(BADPAT), C(ECOLLATE),
+		C(ECTYPE), C(EESCAPE), C(ESUBREG), C(EBRACK),
+		C(EPAREN), C(EBRACE), C(BADBR), C(ERANGE),
+		C(ESPACE), C(BADRPT) };
+
+	  int i;
+	  for (i = 0; i < sizeof (codes) / sizeof (codes[0]); ++i)
+	    if (n == codes[i].code)
+	      {
+		if (strcmp (string, codes[i].name))
+		  {
+		    printf ("%s regcomp returned REG_%s (expected REG_%s)\n",
+			    fail, codes[i].name, string);
+		    return 1;
+		  }
+	        return 0;
+	      }
+
+	  printf ("%s regcomp return value REG_%d\n", fail, n);
+	  return 1;
+	}
+
+      regerror (n, &re, buf, sizeof (buf));
+      printf ("%s regcomp failed: %s\n", fail, buf);
+      return 1;
+    }
+
+  if (eflags == -1)
+    {
+      regfree (&re);
+
+      /* The test case file assumes something only guaranteed by the
+	 rxspencer regex implementation.  Namely that for empty
+	 expressions regcomp() return REG_EMPTY.  This is not the case
+	 for us and so we ignore this error.  */
+      if (strcmp (string, "EMPTY") == 0)
+	return 0;
+
+      printf ("%s regcomp unexpectedly succeeded\n", fail);
+      return 1;
+    }
+
+  if (regexec (&re, string, 10, rm, eflags))
+    {
+      regfree (&re);
+      if (expect == NULL)
+	return 0;
+      printf ("%s regexec failed\n", fail);
+      return 1;
+    }
+
+  regfree (&re);
+
+  if (expect == NULL)
+    {
+      printf ("%s regexec unexpectedly succeeded\n", fail);
+      return 1;
+    }
+
+  if (cflags & REG_NOSUB)
+    return 0;
+
+  ret = check_match (rm, 0, string, expect, fail);
+  if (matches == NULL)
+    return ret;
+
+  for (n = 1; ret == 0 && n < 10; ++n)
+    {
+      char *p = NULL;
+
+      if (matches)
+	{
+	  p = strchr (matches, ',');
+	  if (p != NULL)
+	    *p = '\0';
+	}
+      ret = check_match (rm, n, string, matches ? matches : "-", fail);
+      if (p)
+	{
+	  *p = ',';
+	  matches = p + 1;
+	}
+      else
+	matches = NULL;
+    }
+
+  return ret;
+}
+
+static int
+mb_test (const char *pattern, int cflags, const char *string, int eflags,
+	 char *expect, const char *matches, const char *letters,
+	 const char *fail)
+{
+  char *pattern_mb = mb_frob_pattern (pattern, letters);
+  const char *string_mb
+    = eflags == -1 ? string : mb_frob_string (string, letters);
+  char *expect_mb = mb_frob_string (expect, letters);
+  char *matches_mb = mb_frob_string (matches, letters);
+  int ret = 0;
+
+  if (!pattern_mb || !string_mb
+      || (expect && !expect_mb) || (matches && !matches_mb))
+    {
+      printf ("%s %m", fail);
+      ret = 1;
+    }
+  else
+    ret = test (pattern_mb, cflags, string_mb, eflags, expect_mb,
+		matches_mb, fail);
+
+  free (matches_mb);
+  free (expect_mb);
+  if (string_mb != string)
+    free ((char *) string_mb);
+  free (pattern_mb);
+  return ret;
+}
+
+static int
+mb_tests (const char *pattern, int cflags, const char *string, int eflags,
+	  char *expect, const char *matches)
+{
+  int ret = 0;
+  int i;
+  char letters[9], fail[20];
+
+  /* The tests aren't supposed to work with xdigit, since a-dA-D are
+     hex digits while \'a \'A \v{c}\v{C}\v{d}\v{D}\'e \'E are not.  */
+  if (strstr (pattern, "[:xdigit:]"))
+    return 0;
+
+  /* XXX: regex ATM handles only single byte equivalence classes.  */
+  if (strstr (pattern, "[[=b=]]"))
+    return 0;
+
+  for (i = 1; i < 16; ++i)
+    {
+      char *p = letters;
+      if (i & 1)
+	{
+	  if (!strchr (pattern, 'a') && !strchr (string, 'a')
+	      && !strchr (pattern, 'A') && !strchr (string, 'A'))
+	    continue;
+	  *p++ = 'a', *p++ = 'A';
+	}
+      if (i & 2)
+	{
+	  if (!strchr (pattern, 'b') && !strchr (string, 'b')
+	      && !strchr (pattern, 'B') && !strchr (string, 'B'))
+	    continue;
+	  *p++ = 'b', *p++ = 'B';
+	}
+      if (i & 4)
+	{
+	  if (!strchr (pattern, 'c') && !strchr (string, 'c')
+	      && !strchr (pattern, 'C') && !strchr (string, 'C'))
+	    continue;
+	  *p++ = 'c', *p++ = 'C';
+	}
+      if (i & 8)
+	{
+	  if (!strchr (pattern, 'd') && !strchr (string, 'd')
+	      && !strchr (pattern, 'D') && !strchr (string, 'D'))
+	    continue;
+	  *p++ = 'd', *p++ = 'D';
+	}
+      *p++ = '\0';
+      sprintf (fail, "UTF-8 %s FAIL", letters);
+      ret |= mb_test (pattern, cflags, string, eflags, expect, matches,
+		      letters, fail);
+    }
+  return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+  int ret = 0;
+  char *line = NULL;
+  size_t line_len = 0;
+  ssize_t len;
+  FILE *f;
+  static int test_utf8 = 0;
+  static const struct option options[] =
+    {
+      {"utf8",	no_argument,	&test_utf8,	1},
+      {NULL,	0,		NULL,		0 }
+    };
+
+#ifdef HAVE_MCHECK_H
+  mtrace ();
+#endif
+
+  while (getopt_long (argc, argv, "", options, NULL) >= 0);
+
+  if (optind + 1 != argc)
+    {
+      fprintf (stderr, "Missing test filename\n");
+      return 1;
+    }
+
+  f = fopen (argv[optind], "r");
+  if (f == NULL)
+    {
+      fprintf (stderr, "Couldn't open %s\n", argv[optind]);
+      return 1;
+    }
+
+  while ((len = getline (&line, &line_len, f)) > 0)
+    {
+      char *pattern, *flagstr, *string, *expect, *matches, *p;
+      int cflags = REG_EXTENDED, eflags = 0, try_bre_ere = 0;
+
+      if (line[len - 1] == '\n')
+        line[len - 1] = '\0';
+
+      /* Skip comments and empty lines.  */
+      if (*line == '#' || *line == '\0')
+	continue;
+
+      puts (line);
+      fflush (stdout);
+
+      pattern = strtok (line, "\t");
+      if (pattern == NULL)
+        continue;
+
+      if (strcmp (pattern, "\"\"") == 0)
+	pattern += 2;
+
+      flagstr = strtok (NULL, "\t");
+      if (flagstr == NULL)
+        continue;
+
+      string = strtok (NULL, "\t");
+      if (string == NULL)
+        continue;
+
+      if (strcmp (string, "\"\"") == 0)
+	string += 2;
+
+      for (p = flagstr; *p; ++p)
+	switch (*p)
+	  {
+	  case '-':
+	    break;
+	  case 'b':
+	    cflags &= ~REG_EXTENDED;
+	    break;
+	  case '&':
+	    try_bre_ere = 1;
+	    break;
+	  case 'C':
+	    eflags = -1;
+	    break;
+	  case 'i':
+	    cflags |= REG_ICASE;
+	    break;
+	  case 's':
+	    cflags |= REG_NOSUB;
+	    break;
+	  case 'n':
+	    cflags |= REG_NEWLINE;
+	    break;
+	  case '^':
+	    eflags |= REG_NOTBOL;
+	    break;
+	  case '$':
+	    eflags |= REG_NOTEOL;
+	    break;
+	  case 'm':
+	  case 'p':
+	  case '#':
+	    /* Not supported.  */
+	    flagstr = NULL;
+	    break;
+	  }
+
+      if (flagstr == NULL)
+	continue;
+
+      replace_special_chars (pattern);
+      glibc_re_syntax (pattern);
+      if (eflags != -1)
+        replace_special_chars (string);
+
+      expect = strtok (NULL, "\t");
+      matches = NULL;
+      if (expect != NULL)
+        {
+	  replace_special_chars (expect);
+	  matches = strtok (NULL, "\t");
+	  if (matches != NULL)
+	    replace_special_chars (matches);
+        }
+
+      if (setlocale (LC_ALL, "C") == NULL)
+	{
+	  puts ("setlocale C failed");
+	  ret = 1;
+	}
+      if (test (pattern, cflags, string, eflags, expect, matches, "FAIL")
+	  || (try_bre_ere
+	      && test (pattern, cflags & ~REG_EXTENDED, string, eflags,
+		       expect, matches, "FAIL")))
+	ret = 1;
+      else if (test_utf8)
+	{
+	  if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL)
+	    {
+	      puts ("setlocale cs_CZ.UTF-8 failed");
+	      ret = 1;
+	    }
+	  else if (test (pattern, cflags, string, eflags, expect, matches,
+			 "UTF-8 FAIL")
+		   || (try_bre_ere
+		       && test (pattern, cflags & ~REG_EXTENDED, string,
+				eflags, expect, matches, "UTF-8 FAIL")))
+	    ret = 1;
+	  else if (mb_tests (pattern, cflags, string, eflags, expect, matches)
+		   || (try_bre_ere
+		       && mb_tests (pattern, cflags & ~REG_EXTENDED, string,
+				    eflags, expect, matches)))
+	    ret = 1;
+	}
+    }
+
+  free (line);
+  fclose (f);
+  return ret;
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/uniq.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/uniq.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/uniq.good	(revision 1780)
@@ -0,0 +1,874 @@
+
+#define DPRINTF(p)		/*nothing */
+#define DPRINTF(p) printf p
+#define GETCHAR(c, eptr) c = *eptr;
+#define GETCHARINC(c, eptr) c = *eptr++;
+#define class pcre_class
+#define match_condassert   0x01	/* Called to check a condition assertion */
+#define match_isgroup      0x02	/* Set if start of bracketed group */
+#else
+#endif
+#ifdef DEBUG			/* Sigh. Some compilers never learn. */
+#ifdef DEBUG
+#ifdef __cplusplus
+#include "internal.h"
+&& length - re->max_match_size > start_offset)
+((*ecode++ == OP_BEG_WORD) ? prev_is_word : cur_is_word))
+((md->ctypes[*eptr] & ctype_word) != 0);
+((md->ctypes[eptr[-1]] & ctype_word) != 0);
+(eptr == md->end_subject - 1 && *eptr != '\n'))
+(i.e. keep it out of the loop). Also we can test that there are at least
+(md->ctypes[*eptr++] & ctype_digit) != 0)
+(md->ctypes[*eptr++] & ctype_digit) == 0)
+(md->ctypes[*eptr++] & ctype_space) != 0)
+(md->ctypes[*eptr++] & ctype_space) == 0)
+(md->ctypes[*eptr++] & ctype_word) != 0)
+(md->ctypes[*eptr++] & ctype_word) == 0)
+(offsetcount - 2) * sizeof (int));
+(offsets == NULL && offsetcount > 0))
+(pcre_free) (match_block.offset_vector);
+(pcre_free) (save);
+(re->tables + fcc_offset)[req_char] : req_char;
+*          Match a back-reference                *
+*         Execute a Regular Expression           *
+*         Match from current position            *
+*        Debugging function to print chars       *
+*      Perl-Compatible Regular Expressions       *
+*    Macros and tables for character handling    *
+*************************************************/
+*/
+*iptr = -1;
+*iptr++ = -1;
+*prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
+*prev == OP_ONCE)
+-----------------------------------------------------------------------------
+-1 => failed to match
+/*
+/* "Once" brackets are like assertion brackets except that after a match,
+/* ... else fall through */
+/* Advance to a possible match for an initial string after study */
+/* Allow compilation as C++ source code, should anybody want to do that. */
+/* Always fail if not enough characters left */
+/* An alternation is the end of a branch; scan along to find the end of the
+/* Assert before internal newline if multiline, or before a terminating
+/* Assertion brackets. Check the alternative branches in turn - the
+/* At the start of a bracketed group, add the current subject pointer to the
+/* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
+/* Caseful comparisons */
+/* Change option settings */
+/* Common code for all repeated single character type matches */
+/* Common code for all repeated single-character matches. We can give
+/* Compute the minimum number of offsets that we need to reset each time. Doing
+/* Conditional group: compilation checked that there are no more than
+/* Continue as from after the assertion, updating the offsets high water
+/* Continue from after the assertion, updating the offsets high water
+/* Control never gets here */
+/* Control never reaches here */
+/* Copy the offset information from temporary store if necessary */
+/* Do a single test if no case difference is set up */
+/* Do not stick any code in here without much thought; it is assumed
+/* End of a group, repeated or non-repeating. If we are at the end of
+/* End of subject assertion (\z) */
+/* End of subject or ending \n assertion (\Z) */
+/* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched
+/* First, ensure the minimum number of matches are present. */
+/* First, ensure the minimum number of matches are present. Use inline
+/* First, ensure the minimum number of matches are present. We get back
+/* Flag bits for the match() function */
+/* For a non-repeating ket, just continue at this level. This also
+/* For anchored or unanchored matches, there may be a "last known required
+/* For extended extraction brackets (large number), we have to fish out
+/* For extended extraction brackets (large number), we have to fish out the
+/* For matches anchored to the end of the pattern, we can often avoid
+/* If a back reference hasn't been set, the length that is passed is greater
+/* If checking an assertion for a condition, return TRUE. */
+/* If hit the end of the group (which could be repeated), fail */
+/* If max == min we can continue with the main loop without the
+/* If maximizing it is worth using inline code for speed, doing the type
+/* If maximizing, find the longest possible run, then work backwards. */
+/* If maximizing, find the longest string and work backwards */
+/* If min = max, continue at the same level without recursing */
+/* If min = max, continue at the same level without recursion.
+/* If minimizing, keep testing the rest of the expression and advancing
+/* If minimizing, keep trying and advancing the pointer */
+/* If minimizing, we have to test the rest of the pattern before each
+/* If req_char is set, we know that that character must appear in the subject
+/* If the expression has got more back references than the offsets supplied can
+/* If the length of the reference is zero, just continue with the
+/* If the reference is unset, set the length to be longer than the amount
+/* If we can't find the required character, break the matching loop */
+/* If we have found the required character, save the point where we
+/* In all other cases except a conditional group we have to check the
+/* In case the recursion has set more capturing values, save the final
+/* Include the internals header, which itself includes Standard C headers plus
+/* Insufficient room for saving captured contents */
+/* Loop for handling unanchored repeated matching attempts; for anchored regexs
+/* Match a back reference, possibly repeatedly. Look past the end of the
+/* Match a character class, possibly repeatedly. Look past the end of the
+/* Match a negated single character */
+/* Match a negated single character repeatedly. This is almost a repeat of
+/* Match a run of characters */
+/* Match a single character repeatedly; different opcodes share code. */
+/* Match a single character type repeatedly; several different opcodes
+/* Match a single character type; inline for speed */
+/* Min and max values for the common repeats; for the maxima, 0 => infinity */
+/* Move the subject pointer back. This occurs only at the start of
+/* Negative assertion: all branches must fail to match */
+/* Now start processing the operations. */
+/* OP_KETRMAX */
+/* On entry ecode points to the first opcode, and eptr to the first character
+/* Opening capturing bracket. If there is space in the offset vector, save
+/* Or to a non-unique first char after study */
+/* Or to a unique first char if possible */
+/* Or to just after \n for a multiline match if possible */
+/* Other types of node can be handled by a switch */
+/* Otherwise test for either case */
+/* Print a sequence of chars in printable format, stopping at the end of the
+/* Recursion matches the current regex, nested. If there are any capturing
+/* Reset the maximum number of extractions we might see. */
+/* Reset the value of the ims flags, in case they got changed during
+/* Reset the working variable associated with each extraction. These should
+/* Separate the caselesss case for speed */
+/* Set up for repetition, or handle the non-repeated case */
+/* Set up the first character to match, if available. The first_char value is
+/* Skip over conditional reference data or large extraction number data if
+/* Start of subject assertion */
+/* Start of subject unless notbol, or after internal newline if multiline */
+/* Structure for building a chain of data that actually lives on the
+/* The code is duplicated for the caseless and caseful cases, for speed,
+/* The condition is an assertion. Call match() to evaluate it - setting
+/* The ims options can vary during the matching as a result of the presence
+/* The repeating kets try the rest of the pattern or restart from the
+/* There's been some horrible disaster. */
+/* This "while" is the end of the "do" above */
+/* This function applies a compiled re to a subject string and picks out
+/* Use a macro for debugging printing, 'cause that limits the use of #ifdef
+/* We don't need to repeat the search if we haven't yet reached the
+/* When a match occurs, substrings will be set for all internal extractions;
+/* Word boundary assertions */
+/*************************************************
+1. This software is distributed in the hope that it will be useful,
+2. The origin of this software must not be misrepresented, either by
+3. Altered versions must be plainly marked as such, and must not be
+4. If PCRE is embedded in any software that is released under the GNU
+5.005. If there is an options reset, it will get obeyed in the normal
+6 : 3 + (ecode[1] << 8) + ecode[2]),
+< -1 => some kind of unexpected problem
+= 0 => success, but offsets is not big enough
+Arguments:
+BOOL anchored;
+BOOL cur_is_word = (eptr < md->end_subject) &&
+BOOL is_subject;
+BOOL minimize = FALSE;
+BOOL prev_is_word = (eptr != md->start_subject) &&
+BOOL rc;
+BOOL startline;
+BOOL using_temporary_offsets = FALSE;
+Copyright (c) 1997-2000 University of Cambridge
+DPRINTF ((">>>> returning %d\n", match_block.errorcode));
+DPRINTF ((">>>> returning %d\n", rc));
+DPRINTF (("Copied offsets from temporary memory\n"));
+DPRINTF (("Freeing temporary memory\n"));
+DPRINTF (("Got memory to hold back references\n"));
+DPRINTF (("Unknown opcode %d\n", *ecode));
+DPRINTF (("bracket %d failed\n", number));
+DPRINTF (("bracket 0 failed\n"));
+DPRINTF (("ims reset to %02lx\n", ims));
+DPRINTF (("ims set to %02lx at group repeat\n", ims));
+DPRINTF (("ims set to %02lx\n", ims));
+DPRINTF (("matching %c{%d,%d} against subject %.*s\n", c, min, max,
+DPRINTF (("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
+DPRINTF (("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
+DPRINTF (("start bracket 0\n"));
+GETCHAR (c, eptr)	/* Get character */
+GETCHARINC (c, eptr)	/* Get character; increment eptr */
+General Purpose Licence (GPL), then the terms of that licence shall
+However, if the referenced string is the empty string, always treat
+If the bracket fails to match, we need to restore this value and also the
+If there isn't enough space in the offset vector, treat this as if it were a
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+Otherwise, we can use the vector supplied, rounding down its size to a multiple
+Permission is granted to anyone to use this software for any purpose on any
+REPEATCHAR:
+REPEATNOTCHAR:
+REPEATTYPE:
+Returns:          > 0 => success; value is the number of elements filled in
+Returns:       TRUE if matched
+Returns:      TRUE if matched
+Returns:     nothing
+They are not both allowed to be zero. */
+This is a library of functions to support regular expressions whose syntax
+This is the forcible breaking of infinite loops as implemented in Perl
+Writing separate code makes it go faster, as does using an autoincrement and
+Written by: Philip Hazel <ph10@cam.ac.uk>
+a move back into the brackets. Check the alternative branches in turn - the
+address of eptr, so that eptr can be a register variable. */
+an assertion "group", stop matching and return TRUE, but record the
+an empty string - recursion will then try other alternatives, if any. */
+an error. Save the top 15 values on the stack, and accept that the rest
+an unanchored pattern, of course. If there's no first char and the pattern was
+analyzing most of the pattern.  length > re->max_match_size is
+anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
+and advance one byte in the pattern code. */
+and reinstate them after the recursion. However, we don't know how many
+and semantics are as close as possible to those of the Perl 5 language. See
+and the required character in fact is caseful. */
+at run time, so we have to test for anchoring. The first char may be unset for
+avoid duplicate testing (which takes significant time). This covers the vast
+backing off on a match. */
+bmtable = extra->data.bmtable;
+both cases of the character. Otherwise set the two values the same, which will
+bracketed group and go to there. */
+brackets - for testing for empty matches
+brackets started but not finished, we have to save their starting points
+break;
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+c != md->lcc[*eptr++])
+c = *ecode++ - OP_CRSTAR;
+c = *ecode++ - OP_NOTSTAR;
+c = *ecode++ - OP_STAR;
+c = *ecode++ - OP_TYPESTAR;
+c = *ecode++;
+c = *eptr++;
+c = 15;
+c = max - min;
+c = md->end_subject - eptr;
+c = md->lcc[c];
+c = md->offset_max;
+c == md->lcc[*eptr++])
+can't just fail here, because of the possibility of quantifiers with zero
+case OP_ALT:
+case OP_ANY:
+case OP_ASSERT:
+case OP_ASSERTBACK:
+case OP_ASSERTBACK_NOT:
+case OP_ASSERT_NOT:
+case OP_BEG_WORD:
+case OP_BRA:		/* Non-capturing bracket: optimized */
+case OP_BRAMINZERO:
+case OP_BRANUMBER:
+case OP_BRAZERO:
+case OP_CHARS:
+case OP_CIRC:
+case OP_CLASS:
+case OP_COND:
+case OP_CREF:
+case OP_CRMINPLUS:
+case OP_CRMINQUERY:
+case OP_CRMINRANGE:
+case OP_CRMINSTAR:
+case OP_CRPLUS:
+case OP_CRQUERY:
+case OP_CRRANGE:
+case OP_CRSTAR:
+case OP_DIGIT:
+case OP_DOLL:
+case OP_END:
+case OP_END_WORD:
+case OP_EOD:
+case OP_EODN:
+case OP_EXACT:
+case OP_KET:
+case OP_KETRMAX:
+case OP_KETRMIN:
+case OP_MINPLUS:
+case OP_MINQUERY:
+case OP_MINSTAR:
+case OP_MINUPTO:
+case OP_NOT:
+case OP_NOTEXACT:
+case OP_NOTMINPLUS:
+case OP_NOTMINQUERY:
+case OP_NOTMINSTAR:
+case OP_NOTMINUPTO:
+case OP_NOTPLUS:
+case OP_NOTQUERY:
+case OP_NOTSTAR:
+case OP_NOTUPTO:
+case OP_NOT_DIGIT:
+case OP_NOT_WHITESPACE:
+case OP_NOT_WORDCHAR:
+case OP_NOT_WORD_BOUNDARY:
+case OP_ONCE:
+case OP_OPT:
+case OP_PLUS:
+case OP_QUERY:
+case OP_RECURSE:
+case OP_REF:
+case OP_REVERSE:
+case OP_SOD:
+case OP_STAR:
+case OP_TYPEEXACT:
+case OP_TYPEMINPLUS:
+case OP_TYPEMINQUERY:
+case OP_TYPEMINSTAR:
+case OP_TYPEMINUPTO:
+case OP_TYPEPLUS:
+case OP_TYPEQUERY:
+case OP_TYPESTAR:
+case OP_TYPEUPTO:
+case OP_UPTO:
+case OP_WHITESPACE:
+case OP_WORDCHAR:
+case OP_WORD_BOUNDARY:
+case matching may be when this character is hit, so test for it in both its
+caselessly, or if there are any changes of this flag within the regex, set up
+cases if necessary. However, the different cased versions will not be set up
+character" set. If the PCRE_CASELESS is set, implying that the match starts
+characters and work backwards. */
+code for maximizing the speed, and do the type test once at the start
+code to character type repeats - written out again for speed. */
+commoning these up that doesn't require a test of the positive/negative
+computer system, and to redistribute it freely, subject to the following
+const char *subject;
+const pcre *re;
+const pcre_extra *extra;
+const uschar *bmtable = NULL;
+const uschar *data = ecode + 1;	/* Save for matching */
+const uschar *end_subject;
+const uschar *next = ecode + 1;
+const uschar *p = md->start_subject + md->offset_vector[offset];
+const uschar *p;
+const uschar *pp = eptr;
+const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
+const uschar *prev = ecode;
+const uschar *req_char_ptr = start_match - 1;
+const uschar *saved_eptr = eptr;
+const uschar *saved_eptr = eptrb->saved_eptr;
+const uschar *saved_eptr;
+const uschar *start_bits = NULL;
+const uschar *start_match = (const uschar *) subject + start_offset;
+continue;	/* With the main loop */
+continue;
+course of events. */
+ctype = *ecode++;	/* Code for the character type */
+cur_is_word == prev_is_word : cur_is_word != prev_is_word)
+current high water mark for use by positive assertions. Do this also
+default:		/* No repeat follows */
+default:
+do
+each branch of a lookbehind assertion. If we are too close to the start to
+each substring: the offsets to the start and end of the substring.
+ecode       position in code
+ecode + ((offset < offset_top && md->offset_vector[offset] >= 0) ?
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += 2;
+ecode += 3 + (ecode[4] << 8) + ecode[5];
+ecode += 33;	/* Advance past the item */
+ecode += 3;		/* Advance past the item */
+ecode += 3;
+ecode += 5;
+ecode = next + 3;
+ecode++;
+else
+else if ((extra->options & PCRE_STUDY_BM) != 0)
+else if (first_char >= 0)
+else if (start_bits != NULL)
+else if (startline)
+encountered */
+end_subject = match_block.end_subject;
+eptr        pointer in subject
+eptr        points into the subject
+eptr += c;
+eptr += length;
+eptr += min;
+eptr -= (ecode[1] << 8) + ecode[2];
+eptr -= length;
+eptr = md->end_match_ptr;
+eptr++;
+eptrb       pointer to chain of blocks containing eptr at start of
+eptrb = &newptrb;
+eptrb = eptrb->prev;	/* Back up the stack of bracket start pointers */
+eptrblock *eptrb;
+eptrblock newptrb;
+eptrblock;
+exactly what going to the ket would do. */
+explicit claim or by omission.
+external_extra  points to "hints" from pcre_study() or is NULL
+external_re     points to the compiled expression
+extraction by setting the offsets and bumping the high water mark. */
+first_char = match_block.lcc[first_char];
+first_char = re->first_char;
+flags       can contain
+for (;;)
+for (i = 1; i <= c; i++)
+for (i = 1; i <= min; i++)
+for (i = min; i < max; i++)
+for (i = min;; i++)
+for the "once" (not-backup up) groups. */
+for the match to succeed. If the first character is set, req_char must be
+found it, so that we don't search again next time round the loop if
+from a previous iteration of this group, and be referred to by a reference
+goto REPEATCHAR;
+goto REPEATNOTCHAR;
+goto REPEATTYPE;
+group number back at the start and if necessary complete handling an
+happens for a repeating ket if no characters were matched in the group.
+here; that is handled in the code for KET. */
+hold, we get a temporary bit of working store to use during the matching.
+i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
+if (!anchored)
+if (!match (start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
+if (!match_ref (offset, eptr, length, md, ims))
+if (!md->endonly)
+if (!rc)
+if (!startline && extra != NULL)
+if ((*ecode++ == OP_WORD_BOUNDARY) ?
+if ((data[c / 8] & (1 << (c & 7))) != 0)
+if ((data[c / 8] & (1 << (c & 7))) == 0)
+if ((extra->options & PCRE_STUDY_MAPPED) != 0)
+if ((flags & match_condassert) != 0)
+if ((flags & match_isgroup) != 0)
+if ((ims & PCRE_CASELESS) != 0)
+if ((ims & PCRE_DOTALL) == 0 && c == '\n')
+if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == '\n')
+if ((ims & PCRE_DOTALL) == 0)
+if ((ims & PCRE_MULTILINE) != 0)
+if ((md->ctypes[*eptr++] & ctype_digit) != 0)
+if ((md->ctypes[*eptr++] & ctype_digit) == 0)
+if ((md->ctypes[*eptr++] & ctype_space) != 0)
+if ((md->ctypes[*eptr++] & ctype_space) == 0)
+if ((md->ctypes[*eptr++] & ctype_word) != 0)
+if ((md->ctypes[*eptr++] & ctype_word) == 0)
+if ((md->ctypes[c] & ctype_digit) != 0)
+if ((md->ctypes[c] & ctype_digit) == 0)
+if ((md->ctypes[c] & ctype_space) != 0)
+if ((md->ctypes[c] & ctype_space) == 0)
+if ((md->ctypes[c] & ctype_word) != 0)
+if ((md->ctypes[c] & ctype_word) == 0)
+if ((options & ~PUBLIC_EXEC_OPTIONS) != 0)
+if ((re->options & PCRE_FIRSTSET) != 0)
+if ((re->options & PCRE_REQCHSET) != 0)
+if ((start_bits[c / 8] & (1 << (c & 7))) == 0)
+if (*ecode != OP_ONCE && *ecode != OP_ALT)
+if (*ecode == OP_KET || eptr == saved_eptr)
+if (*ecode == OP_KET)
+if (*ecode == OP_KETRMIN)
+if (*ecode++ != *eptr++)
+if (*ecode++ == *eptr++)
+if (*eptr != '\n')
+if (*eptr++ == '\n')
+if (*p++ != *eptr++)
+if (*p++ == req_char)
+if (*prev != OP_COND)
+if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
+if (bmtable != NULL)
+if (bmtable[*start_match])
+if (c != *eptr++)
+if (c != md->lcc[*eptr++])
+if (c < 16)
+if (c == *eptr++)
+if (c == md->lcc[*eptr++])
+if (c > md->end_subject - eptr)
+if (cur_is_word == prev_is_word ||
+if (ecode[3] == OP_CREF)	/* Condition is extraction test */
+if (ecode[3] == OP_OPT)
+if (eptr != md->start_subject && eptr[-1] != '\n')
+if (eptr != md->start_subject)
+if (eptr < md->end_subject - 1 ||
+if (eptr < md->end_subject)
+if (eptr < md->start_subject)
+if (eptr >= md->end_subject ||
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
+if (eptr >= md->end_subject || *eptr == '\n')
+if (eptr >= md->end_subject || c != *eptr)
+if (eptr >= md->end_subject || c != md->lcc[*eptr])
+if (eptr >= md->end_subject || c == *eptr)
+if (eptr >= md->end_subject || c == md->lcc[*eptr])
+if (eptr >= md->end_subject)
+if (eptr++ >= md->end_subject)
+if (i >= max || !match_ref (offset, eptr, length, md, ims))
+if (i >= max || eptr >= md->end_subject ||
+if (i >= max || eptr >= md->end_subject || c != *eptr++)
+if (i >= max || eptr >= md->end_subject || c == *eptr++)
+if (i >= max || eptr >= md->end_subject)
+if (is_subject && length > md->end_subject - p)
+if (isprint (c = *(p++)))
+if (length == 0)
+if (length > md->end_subject - eptr)
+if (match (eptr, ecode + 3, offset_top, md, ims, NULL,
+if (match (eptr, ecode + 3, offset_top, md, ims, NULL, match_isgroup))
+if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0) ||
+if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, next + 3, offset_top, md, ims, eptrb, match_isgroup))
+if (match (eptr, next, offset_top, md, ims, eptrb, match_isgroup))
+if (match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
+if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0))
+if (match_block.end_offset_top > offsetcount)
+if (match_block.offset_vector != NULL)
+if (match_block.offset_vector == NULL)
+if (max == 0)
+if (md->lcc[*ecode++] != md->lcc[*eptr++])
+if (md->lcc[*ecode++] == md->lcc[*eptr++])
+if (md->lcc[*p++] != md->lcc[*eptr++])
+if (md->notbol && eptr == md->start_subject)
+if (md->notempty && eptr == md->start_match)
+if (md->noteol)
+if (min == max)
+if (min > 0)
+if (min > md->end_subject - eptr)
+if (minimize)
+if (number > 0)
+if (number > EXTRACT_BASIC_MAX) 
+if (offset < md->offset_max)
+if (offset >= md->offset_max)
+if (offset_top <= offset)
+if (offsetcount < 2)
+if (offsetcount >= 4)
+if (op > OP_BRA)
+if (p > req_char_ptr)
+if (p >= end_subject)
+if (pp == req_char || pp == req_char2)
+if (re == NULL || subject == NULL ||
+if (re->magic_number != MAGIC_NUMBER)
+if (re->max_match_size >= 0
+if (re->top_backref > 0 && re->top_backref >= ocount / 3)
+if (req_char == req_char2)
+if (req_char >= 0)
+if (resetcount > offsetcount)
+if (save != stacksave)
+if (save == NULL)
+if (skipped_chars)
+if (start_match + bmtable[256] > end_subject)
+if (start_match > match_block.start_subject + start_offset)
+if (using_temporary_offsets)
+if certain parts of the pattern were not used. */
+if the malloc fails ... there is no way of returning to the top level with
+implied in the second condition, because start_offset > 0. */
+ims         current /i, /m, and /s options
+ims         the ims flags
+ims = (ims & ~PCRE_IMS) | ecode[4];
+ims = ecode[1];
+ims = original_ims;
+ims = re->options & (PCRE_CASELESS | PCRE_MULTILINE | PCRE_DOTALL);
+in the pattern. */
+in the subject string, while eptrb holds the value of eptr at the start of the
+initialize them to avoid reading uninitialized locations. */
+inline, and there are *still* stupid compilers about that don't like indented
+inside the group.
+int
+int *offsets;
+int *save;
+int c;
+int first_char = -1;
+int flags;
+int length;
+int min, max, ctype;
+int number = *prev - OP_BRA;
+int number = op - OP_BRA;
+int offset = (ecode[1] << 9) | (ecode[2] << 1);		/* Doubled reference number */
+int offset = (ecode[4] << 9) | (ecode[5] << 1);	/* Doubled reference number */
+int offset;
+int offset_top;
+int offsetcount;
+int op = (int) *ecode;
+int options;
+int rc;
+int req_char = -1;
+int req_char2 = -1;
+int resetcount, ocount;
+int save_offset1 = md->offset_vector[offset];
+int save_offset2 = md->offset_vector[offset + 1];
+int save_offset3 = md->offset_vector[md->offset_end - number];
+int skipped_chars = 0;
+int stacksave[15];
+int start_offset;
+is a bit large to put on the stack, but using malloc for small numbers
+is_subject  TRUE if printing from within md->start_subject
+it as matched, any number of times (otherwise there could be infinite
+item to see if there is repeat information following. The code is similar
+item to see if there is repeat information following. Then obey similar
+last bracketed group - used for breaking infinite loops matching zero-length
+later in the subject; otherwise the test starts at the match point. This
+length          length of subject string (may contain binary zeros)
+length      length to be matched
+length      number to print
+length = (offset >= offset_top || md->offset_vector[offset] < 0) ?
+length = md->end_subject - p;
+level without recursing. Otherwise, if minimizing, keep trying the rest of
+loop. */
+loops). */
+main loop. */
+majority of cases. It will be suboptimal when the case flag changes in a regex
+mark, since extracts may have been taken during the assertion. */
+mark, since extracts may have been taken. */
+match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0))
+match (eptr, ecode, offset_top, md, ims, eptrb, flags)
+match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
+match_block.ctypes = re->tables + ctypes_offset;
+match_block.end_subject = match_block.start_subject + length;
+match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
+match_block.errorcode = PCRE_ERROR_NOMATCH;	/* Default error */
+match_block.errorcode == PCRE_ERROR_NOMATCH &&
+match_block.lcc = re->tables + lcc_offset;
+match_block.lcc[*start_match] != first_char)
+match_block.notbol = (options & PCRE_NOTBOL) != 0;
+match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
+match_block.noteol = (options & PCRE_NOTEOL) != 0;
+match_block.offset_end = ocount;
+match_block.offset_max = (2 * ocount) / 3;
+match_block.offset_overflow = FALSE;
+match_block.offset_overflow = TRUE;
+match_block.offset_vector = (int *) (pcre_malloc) (ocount * sizeof (int));
+match_block.offset_vector = offsets;
+match_block.start_match = start_match;
+match_block.start_pattern = re->code;
+match_block.start_subject = (const uschar *) subject;
+match_condassert - this is an assertion condition
+match_condassert | match_isgroup))
+match_data *md;
+match_data match_block;
+match_isgroup - this is the start of a bracketed group
+match_isgroup);
+match_ref (offset, eptr, length, md, ims)
+matches, we carry on as at the end of a normal bracket, leaving the subject
+matching won't pass the KET for an assertion. If any one branch matches,
+matching won't pass the KET for this kind of subpattern. If any one branch
+max = (ecode[1] << 8) + ecode[2];
+max = (ecode[3] << 8) + ecode[4];
+max = INT_MAX;
+max = rep_max[c];	/* zero for max => infinity */
+max, eptr));
+maximum. Alternatively, if maximizing, find the maximum number of
+may be wrong. */
+md          pointer to "static" info for the match
+md          pointer to matching data block, if is_subject is TRUE
+md          points to match data block
+md->end_match_ptr = eptr;	/* For ONCE */
+md->end_match_ptr = eptr;	/* Record where we ended */
+md->end_offset_top = offset_top;	/* and how many extracts were taken */
+md->end_offset_top = offset_top;
+md->end_subject - eptr + 1 :
+md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
+md->offset_overflow = TRUE;
+md->offset_vector[md->offset_end - i] = save[i];
+md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
+md->offset_vector[md->offset_end - number] = save_offset3;
+md->offset_vector[md->offset_end - number];
+md->offset_vector[offset + 1] - md->offset_vector[offset];
+md->offset_vector[offset + 1] = eptr - md->start_subject;
+md->offset_vector[offset + 1] = save_offset2;
+md->offset_vector[offset] =
+md->offset_vector[offset] = save_offset1;
+memcpy (offsets + 2, match_block.offset_vector + 2,
+min = (ecode[1] << 8) + ecode[2];
+min = 0;
+min = max = (ecode[1] << 8) + ecode[2];
+min = max = 1;
+min = rep_min[c];	/* Pick up values from tables; */
+minima. */
+minimize = (*ecode == OP_CRMINRANGE);
+minimize = (c & 1) != 0;
+minimize = *ecode == OP_MINUPTO;
+minimize = *ecode == OP_NOTMINUPTO;
+minimize = *ecode == OP_TYPEMINUPTO;
+minimize = TRUE;
+minimum number of matches are present. If min = max, continue at the same
+misrepresented as being the original software.
+move back, this match function fails. */
+mustn't change the current values of the data slot, because they may be set
+need to recurse. */
+never be used unless previously set, but they get saved and restored, and so we
+never set for an anchored regular expression, but the anchoring may be forced
+newline unless endonly is set, else end of subject unless noteol is set. */
+newptrb.prev = eptrb;
+newptrb.saved_eptr = eptr;
+next += (next[1] << 8) + next[2];
+non-capturing bracket. Don't worry about setting the flag for the error case
+number = (ecode[4] << 8) | ecode[5];
+number = (prev[4] << 8) | prev[5];
+number from a dummy opcode at the start. */
+number, then move along the subject till after the recursive match,
+ocount = offsetcount - (offsetcount % 3);
+ocount = re->top_backref * 3 + 3;
+of (?ims) items in the pattern. They are kept in a local variable so that
+of 3. */
+of subject left; this ensures that every attempt at a match fails. We
+offset      index into the offset vector
+offset = number << 1;
+offset_top  current top pointer
+offset_top = md->end_offset_top;
+offset_top = offset + 2;
+offset_top, md, ims, eptrb, match_isgroup);
+offsetcount     the number of elements in the vector
+offsets         points to a vector of ints to be filled in with offsets
+offsets[0] = start_match - match_block.start_subject;
+offsets[1] = match_block.end_match_ptr - match_block.start_subject;
+op = OP_BRA;
+opcode. */
+optimization can save a huge amount of backtracking in patterns with nested
+option for each character match. Maybe that wouldn't add very much to the
+options         option bits
+p           points to characters
+p--;
+past the end if there is only one branch, but that's OK because that is
+pchars (ecode, length, FALSE, md);
+pchars (eptr, 16, TRUE, md);
+pchars (eptr, length, TRUE, md);
+pchars (p, length, FALSE, md);
+pchars (p, length, is_subject, md)
+pchars (start_match, end_subject - start_match, TRUE, &match_block);
+pcre_exec (re, extra, subject, length, start_offset, options, offsets, offsetcount)
+place we found it at last time. */
+pointer. */
+portions of the string if it matches. Two elements in the vector are set for
+pre-processor statements. I suppose it's only been 10 years... */
+preceded by BRAZERO or BRAMINZERO. */
+preceding bracket, in the appropriate order. */
+preceding bracket, in the appropriate order. We need to reset any options
+printf (" against backref ");
+printf (" against pattern ");
+printf ("%c", c);
+printf (">>>> Match against: ");
+printf (">>>>> Skipped %d chars to reach first character\n",
+printf ("\\x%02x", c);
+printf ("\n");
+printf ("end bracket %d", number);
+printf ("matching subject ");
+printf ("matching subject <null> against pattern ");
+printf ("matching subject <null>");
+printf ("start bracket %d subject=", number);
+rc = 0;
+rc = match (eptr, md->start_pattern, offset_top, md, ims, eptrb,
+rc = match_block.offset_overflow ? 0 : match_block.end_offset_top / 2;
+register const uschar *ecode;
+register const uschar *eptr;
+register const uschar *p = start_match + ((first_char >= 0) ? 1 : 0);
+register int *iend = iptr + resetcount;
+register int *iend = iptr - resetcount / 2 + 1;
+register int *iptr = match_block.offset_vector + ocount;
+register int *iptr = match_block.offset_vector;
+register int c = *start_match;
+register int c;
+register int i;
+register int length = ecode[1];
+register int pp = *p++;
+repeat it in the interests of efficiency. */
+repeat limits are compiled as a number of copies, with the optional ones
+req_char = re->req_char;
+req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0) ?
+req_char_ptr = p;
+resetcount = 2 + re->top_bracket * 2;
+resetcount = ocount;
+restoring at the exit of a group is easy. */
+restrictions:
+return FALSE;
+return PCRE_ERROR_BADMAGIC;
+return PCRE_ERROR_BADOPTION;
+return PCRE_ERROR_NOMATCH;
+return PCRE_ERROR_NOMEMORY;
+return PCRE_ERROR_NULL;
+return TRUE;
+return match (eptr,
+return match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup);
+return match_block.errorcode;
+return rc;
+save = (int *) (pcre_malloc) ((c + 1) * sizeof (int));
+save = stacksave;
+save[i] = md->offset_vector[md->offset_end - i];
+seems expensive. As a compromise, the stack is used when there are fewer
+share code. This is very similar to the code for single characters, but we
+similar code to character type repeats - written out again for speed.
+since matching characters is likely to be quite common. First, ensure the
+skipped_chars += bmtable[*start_match],
+skipped_chars += bmtable[256] - 1;
+skipped_chars -= bmtable[256] - 1;
+skipped_chars);
+skipped_chars++,
+stack of such pointers, to be re-instated at the end of the group when we hit
+stack, for holding the values of the subject pointer at the start of each
+start of each branch to move the current point backwards, so the code at
+start_bits = extra->data.start_bits;
+start_match += bmtable[*start_match];
+start_match += bmtable[256] - 1;
+start_match -= bmtable[256] - 1;
+start_match = (const uschar *) subject + length - re->max_match_size;
+start_match++ < end_subject);
+start_match++;
+start_offset    where to start in the subject string
+startline = (re->options & PCRE_STARTLINE) != 0;
+static BOOL
+static const char rep_max[] =
+static const char rep_min[] =
+static void
+strings.
+struct eptrblock *prev;
+studied, there may be a bitmap of possible first characters. */
+subject         points to the subject string
+subject if the requested.
+subpattern - to break infinite loops. */
+subpattern, so as to detect when an empty string has been matched by a
+subsequent match. */
+such there are (offset_top records the completed total) so we just have
+supersede any condition above with which it is incompatible.
+switch (*ecode)
+switch (ctype)
+switch (op)
+test once at the start (i.e. keep it out of the loop). */
+than 16 values to store; otherwise malloc is used. A problem is what to do
+than the number of characters left in the string, so the match fails.
+that "continue" in the code above comes out to here to repeat the main
+that changed within the bracket before re-running it, so check the next
+that it may occur zero times. It may repeat infinitely, or not at all -
+the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
+the closing ket. When match() is called in other circumstances, we don't add to
+the code for a repeated single character, but I haven't found a nice way of
+the current subject position in the working slot at the top of the vector. We
+the expression and advancing one matching character if failing, up to the
+the external pcre header. */
+the file Tech.Notes for some information on the internals.
+the final argument TRUE causes it to stop at the end of an assertion. */
+the group. */
+the length of the reference string explicitly rather than passing the
+the loop runs just once. */
+the minimum number of bytes before we start. */
+the number from a dummy opcode at the start. */
+the point in the subject string is not moved back. Thus there can never be
+the pointer while it matches the class. */
+the same bracket.
+the stack. */
+the start hasn't passed this character yet. */
+the subject. */
+there were too many extractions, set the return code to zero. In the case
+this level is identical to the lookahead case. */
+this makes a huge difference to execution time when there aren't many brackets
+those back references that we can. In this case there need not be overflow
+time taken, but character matching *is* what this is all about... */
+to save all the potential data. There may be up to 99 such values, which
+to that for character classes, but repeated for efficiency. Then obey
+two branches. If the condition is false, skipping the first branch takes us
+typedef struct eptrblock
+unless PCRE_CASELESS was given or the casing state changes within the regex.
+unlimited repeats that aren't going to match. We don't know what the state of
+unsigned long int ims = 0;
+unsigned long int ims;
+unsigned long int original_ims = ims;		/* Save for resetting on ')' */
+up quickly if there are fewer than the minimum number of characters left in
+using_temporary_offsets = TRUE;
+values of the final offsets, in case they were set by a previous iteration of
+we just need to set up the whole thing as substring 0 before returning. If
+where we had to get some local store to hold offsets for backreferences, copy
+while (!anchored &&
+while (*ecode == OP_ALT)
+while (*ecode == OP_ALT);
+while (*next == OP_ALT);
+while (--iptr >= iend)
+while (eptr >= pp)
+while (iptr < iend)
+while (length-- > 0)
+while (p < end_subject)
+while (start_match < end_subject &&
+while (start_match < end_subject && *start_match != first_char)
+while (start_match < end_subject && start_match[-1] != '\n')
+while (start_match < end_subject)
+{
+{0, 0, 0, 0, 1, 1};
+{0, 0, 1, 1, 0, 0};
+}				/* End of main loop */
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/uniq.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/uniq.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/uniq.inp	(revision 1780)
@@ -0,0 +1,2058 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define DPRINTF(p)		/*nothing */
+#define DPRINTF(p) printf p
+#define GETCHAR(c, eptr) c = *eptr;
+#define GETCHARINC(c, eptr) c = *eptr++;
+#define class pcre_class
+#define match_condassert   0x01	/* Called to check a condition assertion */
+#define match_isgroup      0x02	/* Set if start of bracketed group */
+#else
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#ifdef DEBUG			/* Sigh. Some compilers never learn. */
+#ifdef DEBUG			/* Sigh. Some compilers never learn. */
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef DEBUG
+#ifdef __cplusplus
+#include "internal.h"
+&& length - re->max_match_size > start_offset)
+((*ecode++ == OP_BEG_WORD) ? prev_is_word : cur_is_word))
+((md->ctypes[*eptr] & ctype_word) != 0);
+((md->ctypes[*eptr] & ctype_word) != 0);
+((md->ctypes[eptr[-1]] & ctype_word) != 0);
+((md->ctypes[eptr[-1]] & ctype_word) != 0);
+(eptr == md->end_subject - 1 && *eptr != '\n'))
+(eptr == md->end_subject - 1 && *eptr != '\n'))
+(i.e. keep it out of the loop). Also we can test that there are at least
+(md->ctypes[*eptr++] & ctype_digit) != 0)
+(md->ctypes[*eptr++] & ctype_digit) == 0)
+(md->ctypes[*eptr++] & ctype_space) != 0)
+(md->ctypes[*eptr++] & ctype_space) == 0)
+(md->ctypes[*eptr++] & ctype_word) != 0)
+(md->ctypes[*eptr++] & ctype_word) == 0)
+(offsetcount - 2) * sizeof (int));
+(offsets == NULL && offsetcount > 0))
+(pcre_free) (match_block.offset_vector);
+(pcre_free) (match_block.offset_vector);
+(pcre_free) (save);
+(re->tables + fcc_offset)[req_char] : req_char;
+*          Match a back-reference                *
+*         Execute a Regular Expression           *
+*         Match from current position            *
+*        Debugging function to print chars       *
+*      Perl-Compatible Regular Expressions       *
+*    Macros and tables for character handling    *
+*************************************************/
+*************************************************/
+*************************************************/
+*************************************************/
+*************************************************/
+*************************************************/
+*/
+*/
+*/
+*/
+*/
+*iptr = -1;
+*iptr++ = -1;
+*prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
+*prev == OP_ONCE)
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-1 => failed to match
+/*
+/* "Once" brackets are like assertion brackets except that after a match,
+/* ... else fall through */
+/* ... else fall through */
+/* Advance to a possible match for an initial string after study */
+/* Allow compilation as C++ source code, should anybody want to do that. */
+/* Always fail if not enough characters left */
+/* An alternation is the end of a branch; scan along to find the end of the
+/* Assert before internal newline if multiline, or before a terminating
+/* Assertion brackets. Check the alternative branches in turn - the
+/* At the start of a bracketed group, add the current subject pointer to the
+/* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
+/* Caseful comparisons */
+/* Caseful comparisons */
+/* Change option settings */
+/* Common code for all repeated single character type matches */
+/* Common code for all repeated single-character matches. We can give
+/* Common code for all repeated single-character matches. We can give
+/* Compute the minimum number of offsets that we need to reset each time. Doing
+/* Conditional group: compilation checked that there are no more than
+/* Continue as from after the assertion, updating the offsets high water
+/* Continue from after the assertion, updating the offsets high water
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never gets here */
+/* Control never reaches here */
+/* Control never reaches here */
+/* Copy the offset information from temporary store if necessary */
+/* Do a single test if no case difference is set up */
+/* Do not stick any code in here without much thought; it is assumed
+/* End of a group, repeated or non-repeating. If we are at the end of
+/* End of subject assertion (\z) */
+/* End of subject or ending \n assertion (\Z) */
+/* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched
+/* First, ensure the minimum number of matches are present. */
+/* First, ensure the minimum number of matches are present. Use inline
+/* First, ensure the minimum number of matches are present. We get back
+/* Flag bits for the match() function */
+/* For a non-repeating ket, just continue at this level. This also
+/* For a non-repeating ket, just continue at this level. This also
+/* For anchored or unanchored matches, there may be a "last known required
+/* For extended extraction brackets (large number), we have to fish out
+/* For extended extraction brackets (large number), we have to fish out the
+/* For matches anchored to the end of the pattern, we can often avoid
+/* If a back reference hasn't been set, the length that is passed is greater
+/* If checking an assertion for a condition, return TRUE. */
+/* If hit the end of the group (which could be repeated), fail */
+/* If max == min we can continue with the main loop without the
+/* If maximizing it is worth using inline code for speed, doing the type
+/* If maximizing, find the longest possible run, then work backwards. */
+/* If maximizing, find the longest string and work backwards */
+/* If min = max, continue at the same level without recursing */
+/* If min = max, continue at the same level without recursion.
+/* If minimizing, keep testing the rest of the expression and advancing
+/* If minimizing, keep trying and advancing the pointer */
+/* If minimizing, we have to test the rest of the pattern before each
+/* If req_char is set, we know that that character must appear in the subject
+/* If the expression has got more back references than the offsets supplied can
+/* If the length of the reference is zero, just continue with the
+/* If the reference is unset, set the length to be longer than the amount
+/* If we can't find the required character, break the matching loop */
+/* If we have found the required character, save the point where we
+/* In all other cases except a conditional group we have to check the
+/* In case the recursion has set more capturing values, save the final
+/* Include the internals header, which itself includes Standard C headers plus
+/* Insufficient room for saving captured contents */
+/* Loop for handling unanchored repeated matching attempts; for anchored regexs
+/* Match a back reference, possibly repeatedly. Look past the end of the
+/* Match a character class, possibly repeatedly. Look past the end of the
+/* Match a negated single character */
+/* Match a negated single character repeatedly. This is almost a repeat of
+/* Match a run of characters */
+/* Match a single character repeatedly; different opcodes share code. */
+/* Match a single character type repeatedly; several different opcodes
+/* Match a single character type; inline for speed */
+/* Min and max values for the common repeats; for the maxima, 0 => infinity */
+/* Move the subject pointer back. This occurs only at the start of
+/* Negative assertion: all branches must fail to match */
+/* Now start processing the operations. */
+/* OP_KETRMAX */
+/* OP_KETRMAX */
+/* On entry ecode points to the first opcode, and eptr to the first character
+/* Opening capturing bracket. If there is space in the offset vector, save
+/* Or to a non-unique first char after study */
+/* Or to a unique first char if possible */
+/* Or to just after \n for a multiline match if possible */
+/* Other types of node can be handled by a switch */
+/* Otherwise test for either case */
+/* Print a sequence of chars in printable format, stopping at the end of the
+/* Recursion matches the current regex, nested. If there are any capturing
+/* Reset the maximum number of extractions we might see. */
+/* Reset the value of the ims flags, in case they got changed during
+/* Reset the working variable associated with each extraction. These should
+/* Separate the caselesss case for speed */
+/* Set up for repetition, or handle the non-repeated case */
+/* Set up the first character to match, if available. The first_char value is
+/* Skip over conditional reference data or large extraction number data if
+/* Start of subject assertion */
+/* Start of subject unless notbol, or after internal newline if multiline */
+/* Structure for building a chain of data that actually lives on the
+/* The code is duplicated for the caseless and caseful cases, for speed,
+/* The code is duplicated for the caseless and caseful cases, for speed,
+/* The condition is an assertion. Call match() to evaluate it - setting
+/* The ims options can vary during the matching as a result of the presence
+/* The repeating kets try the rest of the pattern or restart from the
+/* The repeating kets try the rest of the pattern or restart from the
+/* There's been some horrible disaster. */
+/* This "while" is the end of the "do" above */
+/* This function applies a compiled re to a subject string and picks out
+/* Use a macro for debugging printing, 'cause that limits the use of #ifdef
+/* We don't need to repeat the search if we haven't yet reached the
+/* When a match occurs, substrings will be set for all internal extractions;
+/* Word boundary assertions */
+/*************************************************
+/*************************************************
+/*************************************************
+/*************************************************
+/*************************************************
+/*************************************************
+1. This software is distributed in the hope that it will be useful,
+2. The origin of this software must not be misrepresented, either by
+3. Altered versions must be plainly marked as such, and must not be
+4. If PCRE is embedded in any software that is released under the GNU
+5.005. If there is an options reset, it will get obeyed in the normal
+5.005. If there is an options reset, it will get obeyed in the normal
+6 : 3 + (ecode[1] << 8) + ecode[2]),
+< -1 => some kind of unexpected problem
+= 0 => success, but offsets is not big enough
+Arguments:
+Arguments:
+Arguments:
+Arguments:
+BOOL anchored;
+BOOL cur_is_word = (eptr < md->end_subject) &&
+BOOL cur_is_word = (eptr < md->end_subject) &&
+BOOL is_subject;
+BOOL minimize = FALSE;
+BOOL prev_is_word = (eptr != md->start_subject) &&
+BOOL prev_is_word = (eptr != md->start_subject) &&
+BOOL rc;
+BOOL startline;
+BOOL using_temporary_offsets = FALSE;
+Copyright (c) 1997-2000 University of Cambridge
+DPRINTF ((">>>> returning %d\n", match_block.errorcode));
+DPRINTF ((">>>> returning %d\n", rc));
+DPRINTF (("Copied offsets from temporary memory\n"));
+DPRINTF (("Freeing temporary memory\n"));
+DPRINTF (("Freeing temporary memory\n"));
+DPRINTF (("Got memory to hold back references\n"));
+DPRINTF (("Unknown opcode %d\n", *ecode));
+DPRINTF (("bracket %d failed\n", number));
+DPRINTF (("bracket 0 failed\n"));
+DPRINTF (("ims reset to %02lx\n", ims));
+DPRINTF (("ims set to %02lx at group repeat\n", ims));
+DPRINTF (("ims set to %02lx\n", ims));
+DPRINTF (("matching %c{%d,%d} against subject %.*s\n", c, min, max,
+DPRINTF (("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
+DPRINTF (("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
+DPRINTF (("start bracket 0\n"));
+GETCHAR (c, eptr)	/* Get character */
+GETCHARINC (c, eptr)	/* Get character; increment eptr */
+GETCHARINC (c, eptr)	/* Get character; increment eptr */
+General Purpose Licence (GPL), then the terms of that licence shall
+However, if the referenced string is the empty string, always treat
+If the bracket fails to match, we need to restore this value and also the
+If there isn't enough space in the offset vector, treat this as if it were a
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+Otherwise, we can use the vector supplied, rounding down its size to a multiple
+Permission is granted to anyone to use this software for any purpose on any
+REPEATCHAR:
+REPEATNOTCHAR:
+REPEATTYPE:
+Returns:          > 0 => success; value is the number of elements filled in
+Returns:       TRUE if matched
+Returns:      TRUE if matched
+Returns:     nothing
+They are not both allowed to be zero. */
+This is a library of functions to support regular expressions whose syntax
+This is the forcible breaking of infinite loops as implemented in Perl
+This is the forcible breaking of infinite loops as implemented in Perl
+Writing separate code makes it go faster, as does using an autoincrement and
+Written by: Philip Hazel <ph10@cam.ac.uk>
+a move back into the brackets. Check the alternative branches in turn - the
+address of eptr, so that eptr can be a register variable. */
+an assertion "group", stop matching and return TRUE, but record the
+an empty string - recursion will then try other alternatives, if any. */
+an error. Save the top 15 values on the stack, and accept that the rest
+an unanchored pattern, of course. If there's no first char and the pattern was
+analyzing most of the pattern.  length > re->max_match_size is
+anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
+and advance one byte in the pattern code. */
+and reinstate them after the recursion. However, we don't know how many
+and semantics are as close as possible to those of the Perl 5 language. See
+and the required character in fact is caseful. */
+at run time, so we have to test for anchoring. The first char may be unset for
+avoid duplicate testing (which takes significant time). This covers the vast
+backing off on a match. */
+bmtable = extra->data.bmtable;
+both cases of the character. Otherwise set the two values the same, which will
+bracketed group and go to there. */
+brackets - for testing for empty matches
+brackets started but not finished, we have to save their starting points
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+break;
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+c != md->lcc[*eptr++])
+c = *ecode++ - OP_CRSTAR;
+c = *ecode++ - OP_CRSTAR;
+c = *ecode++ - OP_NOTSTAR;
+c = *ecode++ - OP_STAR;
+c = *ecode++ - OP_TYPESTAR;
+c = *ecode++;
+c = *ecode++;
+c = *eptr++;
+c = 15;
+c = max - min;
+c = md->end_subject - eptr;
+c = md->lcc[c];
+c = md->lcc[c];
+c = md->offset_max;
+c == md->lcc[*eptr++])
+can't just fail here, because of the possibility of quantifiers with zero
+case OP_ALT:
+case OP_ANY:
+case OP_ANY:
+case OP_ANY:
+case OP_ANY:
+case OP_ASSERT:
+case OP_ASSERTBACK:
+case OP_ASSERTBACK_NOT:
+case OP_ASSERT_NOT:
+case OP_BEG_WORD:
+case OP_BRA:		/* Non-capturing bracket: optimized */
+case OP_BRAMINZERO:
+case OP_BRANUMBER:
+case OP_BRAZERO:
+case OP_CHARS:
+case OP_CIRC:
+case OP_CLASS:
+case OP_COND:
+case OP_CREF:
+case OP_CRMINPLUS:
+case OP_CRMINPLUS:
+case OP_CRMINQUERY:
+case OP_CRMINQUERY:
+case OP_CRMINRANGE:
+case OP_CRMINRANGE:
+case OP_CRMINSTAR:
+case OP_CRMINSTAR:
+case OP_CRPLUS:
+case OP_CRPLUS:
+case OP_CRQUERY:
+case OP_CRQUERY:
+case OP_CRRANGE:
+case OP_CRRANGE:
+case OP_CRSTAR:
+case OP_CRSTAR:
+case OP_DIGIT:
+case OP_DIGIT:
+case OP_DIGIT:
+case OP_DIGIT:
+case OP_DOLL:
+case OP_END:
+case OP_END_WORD:
+case OP_EOD:
+case OP_EODN:
+case OP_EXACT:
+case OP_KET:
+case OP_KETRMAX:
+case OP_KETRMIN:
+case OP_MINPLUS:
+case OP_MINQUERY:
+case OP_MINSTAR:
+case OP_MINUPTO:
+case OP_NOT:
+case OP_NOTEXACT:
+case OP_NOTMINPLUS:
+case OP_NOTMINQUERY:
+case OP_NOTMINSTAR:
+case OP_NOTMINUPTO:
+case OP_NOTPLUS:
+case OP_NOTQUERY:
+case OP_NOTSTAR:
+case OP_NOTUPTO:
+case OP_NOT_DIGIT:
+case OP_NOT_DIGIT:
+case OP_NOT_DIGIT:
+case OP_NOT_DIGIT:
+case OP_NOT_WHITESPACE:
+case OP_NOT_WHITESPACE:
+case OP_NOT_WHITESPACE:
+case OP_NOT_WHITESPACE:
+case OP_NOT_WORDCHAR:
+case OP_NOT_WORDCHAR:
+case OP_NOT_WORDCHAR:
+case OP_NOT_WORDCHAR:
+case OP_NOT_WORD_BOUNDARY:
+case OP_ONCE:
+case OP_OPT:
+case OP_PLUS:
+case OP_QUERY:
+case OP_RECURSE:
+case OP_REF:
+case OP_REVERSE:
+case OP_SOD:
+case OP_STAR:
+case OP_TYPEEXACT:
+case OP_TYPEMINPLUS:
+case OP_TYPEMINQUERY:
+case OP_TYPEMINSTAR:
+case OP_TYPEMINUPTO:
+case OP_TYPEPLUS:
+case OP_TYPEQUERY:
+case OP_TYPESTAR:
+case OP_TYPEUPTO:
+case OP_UPTO:
+case OP_WHITESPACE:
+case OP_WHITESPACE:
+case OP_WHITESPACE:
+case OP_WHITESPACE:
+case OP_WORDCHAR:
+case OP_WORDCHAR:
+case OP_WORDCHAR:
+case OP_WORDCHAR:
+case OP_WORD_BOUNDARY:
+case matching may be when this character is hit, so test for it in both its
+caselessly, or if there are any changes of this flag within the regex, set up
+cases if necessary. However, the different cased versions will not be set up
+character" set. If the PCRE_CASELESS is set, implying that the match starts
+characters and work backwards. */
+characters and work backwards. */
+code for maximizing the speed, and do the type test once at the start
+code to character type repeats - written out again for speed. */
+commoning these up that doesn't require a test of the positive/negative
+computer system, and to redistribute it freely, subject to the following
+const char *subject;
+const pcre *re;
+const pcre_extra *extra;
+const uschar *bmtable = NULL;
+const uschar *data = ecode + 1;	/* Save for matching */
+const uschar *end_subject;
+const uschar *next = ecode + 1;
+const uschar *next = ecode + 1;
+const uschar *p = md->start_subject + md->offset_vector[offset];
+const uschar *p;
+const uschar *pp = eptr;
+const uschar *pp = eptr;
+const uschar *pp = eptr;
+const uschar *pp = eptr;
+const uschar *pp = eptr;
+const uschar *pp = eptr;
+const uschar *pp = eptr;
+const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
+const uschar *prev = ecode;
+const uschar *req_char_ptr = start_match - 1;
+const uschar *saved_eptr = eptr;
+const uschar *saved_eptr = eptrb->saved_eptr;
+const uschar *saved_eptr;
+const uschar *start_bits = NULL;
+const uschar *start_match = (const uschar *) subject + start_offset;
+continue;	/* With the main loop */
+continue;
+continue;
+continue;
+continue;
+continue;
+continue;
+continue;
+continue;
+continue;
+continue;
+continue;
+continue;
+continue;
+course of events. */
+course of events. */
+ctype = *ecode++;	/* Code for the character type */
+cur_is_word == prev_is_word : cur_is_word != prev_is_word)
+current high water mark for use by positive assertions. Do this also
+default:		/* No repeat follows */
+default:		/* No repeat follows */
+default:
+do
+do
+do
+do
+do
+do
+do
+do
+do
+do
+do
+each branch of a lookbehind assertion. If we are too close to the start to
+each substring: the offsets to the start and end of the substring.
+ecode       position in code
+ecode + ((offset < offset_top && md->offset_vector[offset] >= 0) ?
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += (ecode[1] << 8) + ecode[2];
+ecode += 2;
+ecode += 2;
+ecode += 3 + (ecode[4] << 8) + ecode[5];
+ecode += 33;	/* Advance past the item */
+ecode += 3;		/* Advance past the item */
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 3;
+ecode += 5;
+ecode += 5;
+ecode = next + 3;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+ecode++;
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else
+else if ((extra->options & PCRE_STUDY_BM) != 0)
+else if (first_char >= 0)
+else if (start_bits != NULL)
+else if (startline)
+encountered */
+end_subject = match_block.end_subject;
+eptr        pointer in subject
+eptr        points into the subject
+eptr += c;
+eptr += length;
+eptr += length;
+eptr += length;
+eptr += length;
+eptr += min;
+eptr -= (ecode[1] << 8) + ecode[2];
+eptr -= length;
+eptr = md->end_match_ptr;
+eptr = md->end_match_ptr;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptr++;
+eptrb       pointer to chain of blocks containing eptr at start of
+eptrb = &newptrb;
+eptrb = eptrb->prev;	/* Back up the stack of bracket start pointers */
+eptrblock *eptrb;
+eptrblock newptrb;
+eptrblock;
+exactly what going to the ket would do. */
+explicit claim or by omission.
+external_extra  points to "hints" from pcre_study() or is NULL
+external_re     points to the compiled expression
+extraction by setting the offsets and bumping the high water mark. */
+first_char = match_block.lcc[first_char];
+first_char = re->first_char;
+flags       can contain
+for (;;)
+for (i = 1; i <= c; i++)
+for (i = 1; i <= c; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = 1; i <= min; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min; i < max; i++)
+for (i = min;; i++)
+for (i = min;; i++)
+for (i = min;; i++)
+for (i = min;; i++)
+for (i = min;; i++)
+for (i = min;; i++)
+for (i = min;; i++)
+for the "once" (not-backup up) groups. */
+for the match to succeed. If the first character is set, req_char must be
+found it, so that we don't search again next time round the loop if
+from a previous iteration of this group, and be referred to by a reference
+goto REPEATCHAR;
+goto REPEATCHAR;
+goto REPEATNOTCHAR;
+goto REPEATNOTCHAR;
+goto REPEATTYPE;
+goto REPEATTYPE;
+group number back at the start and if necessary complete handling an
+happens for a repeating ket if no characters were matched in the group.
+happens for a repeating ket if no characters were matched in the group.
+here; that is handled in the code for KET. */
+hold, we get a temporary bit of working store to use during the matching.
+i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
+if (!anchored)
+if (!match (start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
+if (!match_ref (offset, eptr, length, md, ims))
+if (!match_ref (offset, eptr, length, md, ims))
+if (!match_ref (offset, eptr, length, md, ims))
+if (!md->endonly)
+if (!rc)
+if (!startline && extra != NULL)
+if ((*ecode++ == OP_WORD_BOUNDARY) ?
+if ((data[c / 8] & (1 << (c & 7))) != 0)
+if ((data[c / 8] & (1 << (c & 7))) != 0)
+if ((data[c / 8] & (1 << (c & 7))) == 0)
+if ((extra->options & PCRE_STUDY_MAPPED) != 0)
+if ((flags & match_condassert) != 0)
+if ((flags & match_condassert) != 0)
+if ((flags & match_isgroup) != 0)
+if ((ims & PCRE_CASELESS) != 0)
+if ((ims & PCRE_CASELESS) != 0)
+if ((ims & PCRE_CASELESS) != 0)
+if ((ims & PCRE_CASELESS) != 0)
+if ((ims & PCRE_CASELESS) != 0)
+if ((ims & PCRE_CASELESS) != 0)
+if ((ims & PCRE_CASELESS) != 0)
+if ((ims & PCRE_DOTALL) == 0 && c == '\n')
+if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == '\n')
+if ((ims & PCRE_DOTALL) == 0)
+if ((ims & PCRE_DOTALL) == 0)
+if ((ims & PCRE_MULTILINE) != 0)
+if ((ims & PCRE_MULTILINE) != 0)
+if ((md->ctypes[*eptr++] & ctype_digit) != 0)
+if ((md->ctypes[*eptr++] & ctype_digit) == 0)
+if ((md->ctypes[*eptr++] & ctype_space) != 0)
+if ((md->ctypes[*eptr++] & ctype_space) == 0)
+if ((md->ctypes[*eptr++] & ctype_word) != 0)
+if ((md->ctypes[*eptr++] & ctype_word) == 0)
+if ((md->ctypes[c] & ctype_digit) != 0)
+if ((md->ctypes[c] & ctype_digit) == 0)
+if ((md->ctypes[c] & ctype_space) != 0)
+if ((md->ctypes[c] & ctype_space) == 0)
+if ((md->ctypes[c] & ctype_word) != 0)
+if ((md->ctypes[c] & ctype_word) == 0)
+if ((options & ~PUBLIC_EXEC_OPTIONS) != 0)
+if ((re->options & PCRE_FIRSTSET) != 0)
+if ((re->options & PCRE_REQCHSET) != 0)
+if ((start_bits[c / 8] & (1 << (c & 7))) == 0)
+if (*ecode != OP_ONCE && *ecode != OP_ALT)
+if (*ecode == OP_KET || eptr == saved_eptr)
+if (*ecode == OP_KET || eptr == saved_eptr)
+if (*ecode == OP_KET)
+if (*ecode == OP_KETRMIN)
+if (*ecode == OP_KETRMIN)
+if (*ecode++ != *eptr++)
+if (*ecode++ == *eptr++)
+if (*eptr != '\n')
+if (*eptr++ == '\n')
+if (*p++ != *eptr++)
+if (*p++ == req_char)
+if (*prev != OP_COND)
+if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
+if (bmtable != NULL)
+if (bmtable[*start_match])
+if (c != *eptr++)
+if (c != md->lcc[*eptr++])
+if (c < 16)
+if (c == *eptr++)
+if (c == md->lcc[*eptr++])
+if (c > md->end_subject - eptr)
+if (cur_is_word == prev_is_word ||
+if (ecode[3] == OP_CREF)	/* Condition is extraction test */
+if (ecode[3] == OP_OPT)
+if (eptr != md->start_subject && eptr[-1] != '\n')
+if (eptr != md->start_subject)
+if (eptr < md->end_subject - 1 ||
+if (eptr < md->end_subject - 1 ||
+if (eptr < md->end_subject)
+if (eptr < md->end_subject)
+if (eptr < md->start_subject)
+if (eptr >= md->end_subject ||
+if (eptr >= md->end_subject ||
+if (eptr >= md->end_subject ||
+if (eptr >= md->end_subject ||
+if (eptr >= md->end_subject ||
+if (eptr >= md->end_subject ||
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
+if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
+if (eptr >= md->end_subject || *eptr == '\n')
+if (eptr >= md->end_subject || c != *eptr)
+if (eptr >= md->end_subject || c != md->lcc[*eptr])
+if (eptr >= md->end_subject || c == *eptr)
+if (eptr >= md->end_subject || c == md->lcc[*eptr])
+if (eptr >= md->end_subject)
+if (eptr >= md->end_subject)
+if (eptr >= md->end_subject)
+if (eptr >= md->end_subject)
+if (eptr >= md->end_subject)
+if (eptr++ >= md->end_subject)
+if (i >= max || !match_ref (offset, eptr, length, md, ims))
+if (i >= max || eptr >= md->end_subject ||
+if (i >= max || eptr >= md->end_subject ||
+if (i >= max || eptr >= md->end_subject || c != *eptr++)
+if (i >= max || eptr >= md->end_subject || c == *eptr++)
+if (i >= max || eptr >= md->end_subject)
+if (i >= max || eptr >= md->end_subject)
+if (is_subject && length > md->end_subject - p)
+if (isprint (c = *(p++)))
+if (length == 0)
+if (length > md->end_subject - eptr)
+if (length > md->end_subject - eptr)
+if (match (eptr, ecode + 3, offset_top, md, ims, NULL,
+if (match (eptr, ecode + 3, offset_top, md, ims, NULL, match_isgroup))
+if (match (eptr, ecode + 3, offset_top, md, ims, NULL, match_isgroup))
+if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0) ||
+if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0) ||
+if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup))
+if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup))
+if (match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr, next + 3, offset_top, md, ims, eptrb, match_isgroup))
+if (match (eptr, next, offset_top, md, ims, eptrb, match_isgroup))
+if (match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
+if (match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
+if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0))
+if (match (eptr--, ecode, offset_top, md, ims, eptrb, 0))
+if (match_block.end_offset_top > offsetcount)
+if (match_block.offset_vector != NULL)
+if (match_block.offset_vector == NULL)
+if (max == 0)
+if (max == 0)
+if (max == 0)
+if (max == 0)
+if (max == 0)
+if (max == 0)
+if (max == 0)
+if (md->lcc[*ecode++] != md->lcc[*eptr++])
+if (md->lcc[*ecode++] == md->lcc[*eptr++])
+if (md->lcc[*p++] != md->lcc[*eptr++])
+if (md->notbol && eptr == md->start_subject)
+if (md->notempty && eptr == md->start_match)
+if (md->noteol)
+if (md->noteol)
+if (min == max)
+if (min == max)
+if (min == max)
+if (min == max)
+if (min == max)
+if (min == max)
+if (min == max)
+if (min > 0)
+if (min > md->end_subject - eptr)
+if (min > md->end_subject - eptr)
+if (min > md->end_subject - eptr)
+if (minimize)
+if (minimize)
+if (minimize)
+if (minimize)
+if (minimize)
+if (minimize)
+if (minimize)
+if (number > 0)
+if (number > EXTRACT_BASIC_MAX) 
+if (number > EXTRACT_BASIC_MAX) 
+if (offset < md->offset_max)
+if (offset >= md->offset_max)
+if (offset_top <= offset)
+if (offsetcount < 2)
+if (offsetcount >= 4)
+if (op > OP_BRA)
+if (p > req_char_ptr)
+if (p >= end_subject)
+if (pp == req_char || pp == req_char2)
+if (re == NULL || subject == NULL ||
+if (re->magic_number != MAGIC_NUMBER)
+if (re->max_match_size >= 0
+if (re->top_backref > 0 && re->top_backref >= ocount / 3)
+if (req_char == req_char2)
+if (req_char >= 0)
+if (resetcount > offsetcount)
+if (save != stacksave)
+if (save == NULL)
+if (skipped_chars)
+if (start_match + bmtable[256] > end_subject)
+if (start_match > match_block.start_subject + start_offset)
+if (using_temporary_offsets)
+if (using_temporary_offsets)
+if certain parts of the pattern were not used. */
+if the malloc fails ... there is no way of returning to the top level with
+implied in the second condition, because start_offset > 0. */
+ims         current /i, /m, and /s options
+ims         the ims flags
+ims = (ims & ~PCRE_IMS) | ecode[4];
+ims = ecode[1];
+ims = original_ims;
+ims = re->options & (PCRE_CASELESS | PCRE_MULTILINE | PCRE_DOTALL);
+in the pattern. */
+in the subject string, while eptrb holds the value of eptr at the start of the
+initialize them to avoid reading uninitialized locations. */
+inline, and there are *still* stupid compilers about that don't like indented
+inside the group.
+int
+int *offsets;
+int *save;
+int c;
+int first_char = -1;
+int flags;
+int length;
+int length;
+int length;
+int length;
+int min, max, ctype;
+int number = *prev - OP_BRA;
+int number = op - OP_BRA;
+int offset = (ecode[1] << 9) | (ecode[2] << 1);		/* Doubled reference number */
+int offset = (ecode[4] << 9) | (ecode[5] << 1);	/* Doubled reference number */
+int offset;
+int offset;
+int offset;
+int offset_top;
+int offsetcount;
+int op = (int) *ecode;
+int options;
+int rc;
+int req_char = -1;
+int req_char2 = -1;
+int resetcount, ocount;
+int save_offset1 = md->offset_vector[offset];
+int save_offset2 = md->offset_vector[offset + 1];
+int save_offset3 = md->offset_vector[md->offset_end - number];
+int skipped_chars = 0;
+int stacksave[15];
+int start_offset;
+is a bit large to put on the stack, but using malloc for small numbers
+is_subject  TRUE if printing from within md->start_subject
+it as matched, any number of times (otherwise there could be infinite
+item to see if there is repeat information following. The code is similar
+item to see if there is repeat information following. Then obey similar
+last bracketed group - used for breaking infinite loops matching zero-length
+later in the subject; otherwise the test starts at the match point. This
+length          length of subject string (may contain binary zeros)
+length      length to be matched
+length      number to print
+length = (offset >= offset_top || md->offset_vector[offset] < 0) ?
+length = md->end_subject - p;
+level without recursing. Otherwise, if minimizing, keep trying the rest of
+level without recursing. Otherwise, if minimizing, keep trying the rest of
+loop. */
+loops). */
+main loop. */
+majority of cases. It will be suboptimal when the case flag changes in a regex
+mark, since extracts may have been taken during the assertion. */
+mark, since extracts may have been taken. */
+match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0))
+match (eptr, ecode + 3, offset_top, md, ims, eptrb, 0))
+match (eptr, ecode, offset_top, md, ims, eptrb, flags)
+match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
+match (eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
+match_block.ctypes = re->tables + ctypes_offset;
+match_block.end_subject = match_block.start_subject + length;
+match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
+match_block.errorcode = PCRE_ERROR_NOMATCH;	/* Default error */
+match_block.errorcode == PCRE_ERROR_NOMATCH &&
+match_block.lcc = re->tables + lcc_offset;
+match_block.lcc[*start_match] != first_char)
+match_block.notbol = (options & PCRE_NOTBOL) != 0;
+match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
+match_block.noteol = (options & PCRE_NOTEOL) != 0;
+match_block.offset_end = ocount;
+match_block.offset_max = (2 * ocount) / 3;
+match_block.offset_overflow = FALSE;
+match_block.offset_overflow = TRUE;
+match_block.offset_vector = (int *) (pcre_malloc) (ocount * sizeof (int));
+match_block.offset_vector = offsets;
+match_block.start_match = start_match;
+match_block.start_pattern = re->code;
+match_block.start_subject = (const uschar *) subject;
+match_condassert - this is an assertion condition
+match_condassert | match_isgroup))
+match_data *md;
+match_data *md;
+match_data *md;
+match_data match_block;
+match_isgroup - this is the start of a bracketed group
+match_isgroup);
+match_ref (offset, eptr, length, md, ims)
+matches, we carry on as at the end of a normal bracket, leaving the subject
+matching won't pass the KET for an assertion. If any one branch matches,
+matching won't pass the KET for this kind of subpattern. If any one branch
+max = (ecode[1] << 8) + ecode[2];
+max = (ecode[1] << 8) + ecode[2];
+max = (ecode[1] << 8) + ecode[2];
+max = (ecode[3] << 8) + ecode[4];
+max = (ecode[3] << 8) + ecode[4];
+max = INT_MAX;
+max = INT_MAX;
+max = INT_MAX;
+max = INT_MAX;
+max = INT_MAX;
+max = INT_MAX;
+max = INT_MAX;
+max = rep_max[c];	/* zero for max => infinity */
+max = rep_max[c];	/* zero for max => infinity */
+max = rep_max[c];	/* zero for max => infinity */
+max = rep_max[c];	/* zero for max => infinity */
+max = rep_max[c];	/* zero for max => infinity */
+max, eptr));
+max, eptr));
+maximum. Alternatively, if maximizing, find the maximum number of
+maximum. Alternatively, if maximizing, find the maximum number of
+may be wrong. */
+md          pointer to "static" info for the match
+md          pointer to matching data block, if is_subject is TRUE
+md          points to match data block
+md->end_match_ptr = eptr;	/* For ONCE */
+md->end_match_ptr = eptr;	/* Record where we ended */
+md->end_offset_top = offset_top;	/* and how many extracts were taken */
+md->end_offset_top = offset_top;
+md->end_subject - eptr + 1 :
+md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
+md->offset_overflow = TRUE;
+md->offset_vector[md->offset_end - i] = save[i];
+md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
+md->offset_vector[md->offset_end - number] = save_offset3;
+md->offset_vector[md->offset_end - number];
+md->offset_vector[offset + 1] - md->offset_vector[offset];
+md->offset_vector[offset + 1] = eptr - md->start_subject;
+md->offset_vector[offset + 1] = save_offset2;
+md->offset_vector[offset] =
+md->offset_vector[offset] = save_offset1;
+memcpy (offsets + 2, match_block.offset_vector + 2,
+min = (ecode[1] << 8) + ecode[2];
+min = (ecode[1] << 8) + ecode[2];
+min = 0;
+min = 0;
+min = 0;
+min = max = (ecode[1] << 8) + ecode[2];
+min = max = (ecode[1] << 8) + ecode[2];
+min = max = (ecode[1] << 8) + ecode[2];
+min = max = 1;
+min = rep_min[c];	/* Pick up values from tables; */
+min = rep_min[c];	/* Pick up values from tables; */
+min = rep_min[c];	/* Pick up values from tables; */
+min = rep_min[c];	/* Pick up values from tables; */
+min = rep_min[c];	/* Pick up values from tables; */
+minima. */
+minimize = (*ecode == OP_CRMINRANGE);
+minimize = (*ecode == OP_CRMINRANGE);
+minimize = (c & 1) != 0;
+minimize = (c & 1) != 0;
+minimize = (c & 1) != 0;
+minimize = (c & 1) != 0;
+minimize = (c & 1) != 0;
+minimize = *ecode == OP_MINUPTO;
+minimize = *ecode == OP_NOTMINUPTO;
+minimize = *ecode == OP_TYPEMINUPTO;
+minimize = TRUE;
+minimum number of matches are present. If min = max, continue at the same
+minimum number of matches are present. If min = max, continue at the same
+misrepresented as being the original software.
+move back, this match function fails. */
+mustn't change the current values of the data slot, because they may be set
+need to recurse. */
+never be used unless previously set, but they get saved and restored, and so we
+never set for an anchored regular expression, but the anchoring may be forced
+newline unless endonly is set, else end of subject unless noteol is set. */
+newptrb.prev = eptrb;
+newptrb.saved_eptr = eptr;
+next += (next[1] << 8) + next[2];
+next += (next[1] << 8) + next[2];
+non-capturing bracket. Don't worry about setting the flag for the error case
+number = (ecode[4] << 8) | ecode[5];
+number = (prev[4] << 8) | prev[5];
+number from a dummy opcode at the start. */
+number, then move along the subject till after the recursive match,
+ocount = offsetcount - (offsetcount % 3);
+ocount = re->top_backref * 3 + 3;
+of (?ims) items in the pattern. They are kept in a local variable so that
+of 3. */
+of subject left; this ensures that every attempt at a match fails. We
+offset      index into the offset vector
+offset = number << 1;
+offset = number << 1;
+offset_top  current top pointer
+offset_top = md->end_offset_top;
+offset_top = md->end_offset_top;
+offset_top = md->end_offset_top;
+offset_top = offset + 2;
+offset_top, md, ims, eptrb, match_isgroup);
+offsetcount     the number of elements in the vector
+offsets         points to a vector of ints to be filled in with offsets
+offsets[0] = start_match - match_block.start_subject;
+offsets[1] = match_block.end_match_ptr - match_block.start_subject;
+op = OP_BRA;
+opcode. */
+optimization can save a huge amount of backtracking in patterns with nested
+option for each character match. Maybe that wouldn't add very much to the
+options         option bits
+p           points to characters
+p--;
+p--;
+past the end if there is only one branch, but that's OK because that is
+pchars (ecode, length, FALSE, md);
+pchars (eptr, 16, TRUE, md);
+pchars (eptr, length, TRUE, md);
+pchars (eptr, length, TRUE, md);
+pchars (p, length, FALSE, md);
+pchars (p, length, is_subject, md)
+pchars (start_match, end_subject - start_match, TRUE, &match_block);
+pcre_exec (re, extra, subject, length, start_offset, options, offsets, offsetcount)
+place we found it at last time. */
+pointer. */
+portions of the string if it matches. Two elements in the vector are set for
+pre-processor statements. I suppose it's only been 10 years... */
+preceded by BRAZERO or BRAMINZERO. */
+preceding bracket, in the appropriate order. */
+preceding bracket, in the appropriate order. We need to reset any options
+printf (" against backref ");
+printf (" against pattern ");
+printf ("%c", c);
+printf (">>>> Match against: ");
+printf (">>>>> Skipped %d chars to reach first character\n",
+printf ("\\x%02x", c);
+printf ("\n");
+printf ("\n");
+printf ("\n");
+printf ("\n");
+printf ("\n");
+printf ("end bracket %d", number);
+printf ("matching subject ");
+printf ("matching subject ");
+printf ("matching subject <null> against pattern ");
+printf ("matching subject <null>");
+printf ("start bracket %d subject=", number);
+rc = 0;
+rc = match (eptr, md->start_pattern, offset_top, md, ims, eptrb,
+rc = match_block.offset_overflow ? 0 : match_block.end_offset_top / 2;
+register const uschar *ecode;
+register const uschar *eptr;
+register const uschar *eptr;
+register const uschar *p = start_match + ((first_char >= 0) ? 1 : 0);
+register int *iend = iptr + resetcount;
+register int *iend = iptr - resetcount / 2 + 1;
+register int *iptr = match_block.offset_vector + ocount;
+register int *iptr = match_block.offset_vector;
+register int c = *start_match;
+register int c;
+register int i;
+register int length = ecode[1];
+register int pp = *p++;
+repeat it in the interests of efficiency. */
+repeat limits are compiled as a number of copies, with the optional ones
+req_char = re->req_char;
+req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0) ?
+req_char_ptr = p;
+resetcount = 2 + re->top_bracket * 2;
+resetcount = ocount;
+restoring at the exit of a group is easy. */
+restrictions:
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return FALSE;
+return PCRE_ERROR_BADMAGIC;
+return PCRE_ERROR_BADOPTION;
+return PCRE_ERROR_NOMATCH;
+return PCRE_ERROR_NOMEMORY;
+return PCRE_ERROR_NULL;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return TRUE;
+return match (eptr,
+return match (eptr, ecode + 3, offset_top, md, ims, eptrb, match_isgroup);
+return match_block.errorcode;
+return rc;
+save = (int *) (pcre_malloc) ((c + 1) * sizeof (int));
+save = stacksave;
+save = stacksave;
+save[i] = md->offset_vector[md->offset_end - i];
+seems expensive. As a compromise, the stack is used when there are fewer
+share code. This is very similar to the code for single characters, but we
+similar code to character type repeats - written out again for speed.
+since matching characters is likely to be quite common. First, ensure the
+since matching characters is likely to be quite common. First, ensure the
+skipped_chars += bmtable[*start_match],
+skipped_chars += bmtable[256] - 1;
+skipped_chars -= bmtable[256] - 1;
+skipped_chars);
+skipped_chars++,
+skipped_chars++,
+skipped_chars++,
+skipped_chars++,
+stack of such pointers, to be re-instated at the end of the group when we hit
+stack, for holding the values of the subject pointer at the start of each
+start of each branch to move the current point backwards, so the code at
+start_bits = extra->data.start_bits;
+start_match += bmtable[*start_match];
+start_match += bmtable[256] - 1;
+start_match -= bmtable[256] - 1;
+start_match = (const uschar *) subject + length - re->max_match_size;
+start_match++ < end_subject);
+start_match++;
+start_match++;
+start_match++;
+start_match++;
+start_offset    where to start in the subject string
+startline = (re->options & PCRE_STARTLINE) != 0;
+static BOOL
+static BOOL
+static const char rep_max[] =
+static const char rep_min[] =
+static void
+strings.
+struct eptrblock *prev;
+studied, there may be a bitmap of possible first characters. */
+subject         points to the subject string
+subject if the requested.
+subpattern - to break infinite loops. */
+subpattern, so as to detect when an empty string has been matched by a
+subsequent match. */
+such there are (offset_top records the completed total) so we just have
+supersede any condition above with which it is incompatible.
+switch (*ecode)
+switch (*ecode)
+switch (ctype)
+switch (ctype)
+switch (ctype)
+switch (op)
+test once at the start (i.e. keep it out of the loop). */
+than 16 values to store; otherwise malloc is used. A problem is what to do
+than the number of characters left in the string, so the match fails.
+that "continue" in the code above comes out to here to repeat the main
+that changed within the bracket before re-running it, so check the next
+that it may occur zero times. It may repeat infinitely, or not at all -
+the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
+the closing ket. When match() is called in other circumstances, we don't add to
+the code for a repeated single character, but I haven't found a nice way of
+the current subject position in the working slot at the top of the vector. We
+the expression and advancing one matching character if failing, up to the
+the expression and advancing one matching character if failing, up to the
+the external pcre header. */
+the file Tech.Notes for some information on the internals.
+the final argument TRUE causes it to stop at the end of an assertion. */
+the group. */
+the length of the reference string explicitly rather than passing the
+the loop runs just once. */
+the minimum number of bytes before we start. */
+the number from a dummy opcode at the start. */
+the point in the subject string is not moved back. Thus there can never be
+the pointer while it matches the class. */
+the same bracket.
+the stack. */
+the start hasn't passed this character yet. */
+the subject. */
+the subject. */
+there were too many extractions, set the return code to zero. In the case
+this level is identical to the lookahead case. */
+this makes a huge difference to execution time when there aren't many brackets
+those back references that we can. In this case there need not be overflow
+time taken, but character matching *is* what this is all about... */
+to save all the potential data. There may be up to 99 such values, which
+to that for character classes, but repeated for efficiency. Then obey
+two branches. If the condition is false, skipping the first branch takes us
+typedef struct eptrblock
+unless PCRE_CASELESS was given or the casing state changes within the regex.
+unlimited repeats that aren't going to match. We don't know what the state of
+unsigned long int ims = 0;
+unsigned long int ims;
+unsigned long int ims;
+unsigned long int original_ims = ims;		/* Save for resetting on ')' */
+up quickly if there are fewer than the minimum number of characters left in
+up quickly if there are fewer than the minimum number of characters left in
+using_temporary_offsets = TRUE;
+values of the final offsets, in case they were set by a previous iteration of
+we just need to set up the whole thing as substring 0 before returning. If
+where we had to get some local store to hold offsets for backreferences, copy
+while (!anchored &&
+while (*ecode == OP_ALT)
+while (*ecode == OP_ALT);
+while (*ecode == OP_ALT);
+while (*ecode == OP_ALT);
+while (*ecode == OP_ALT);
+while (*ecode == OP_ALT);
+while (*ecode == OP_ALT);
+while (*ecode == OP_ALT);
+while (*ecode == OP_ALT);
+while (*next == OP_ALT);
+while (*next == OP_ALT);
+while (--iptr >= iend)
+while (eptr >= pp)
+while (eptr >= pp)
+while (eptr >= pp)
+while (eptr >= pp)
+while (eptr >= pp)
+while (eptr >= pp)
+while (eptr >= pp)
+while (iptr < iend)
+while (length-- > 0)
+while (length-- > 0)
+while (length-- > 0)
+while (length-- > 0)
+while (length-- > 0)
+while (p < end_subject)
+while (p < end_subject)
+while (start_match < end_subject &&
+while (start_match < end_subject && *start_match != first_char)
+while (start_match < end_subject && start_match[-1] != '\n')
+while (start_match < end_subject)
+while (start_match < end_subject)
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{
+{0, 0, 0, 0, 1, 1};
+{0, 0, 1, 1, 0, 0};
+}				/* End of main loop */
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/uniq.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/uniq.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/uniq.sed	(revision 1780)
@@ -0,0 +1,20 @@
+h
+
+:b
+# On the last line, print and exit
+$b
+N
+/^\(.*\)\n\1$/ {
+    # The two lines are identical.  Undo the effect of
+    # the n command.
+    g
+    bb
+}
+
+# If the @code{N} command had added the last line, print and exit
+$b
+
+# The lines are different; print the first and go
+# back working on the second.
+P
+D
Index: /tags/kBuild-0.1.4/src/sed/testsuite/version.gin
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/version.gin	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/version.gin	(revision 1780)
@@ -0,0 +1,5 @@
+GNU sed version @VERSION@
+Copyright (C) 2003 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,
+to the extent permitted by law.
Index: /tags/kBuild-0.1.4/src/sed/testsuite/writeout.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/writeout.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/writeout.inp	(revision 1780)
@@ -0,0 +1,4 @@
+Facts are simple and facts are straight
+Facts are lazy and facts are late
+Facts all come with points of view
+Facts don't do what I want them to
Index: /tags/kBuild-0.1.4/src/sed/testsuite/writeout.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/writeout.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/writeout.sed	(revision 1780)
@@ -0,0 +1,1 @@
+/^Facts ar/w writeout.wout
Index: /tags/kBuild-0.1.4/src/sed/testsuite/wrtout1.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/wrtout1.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/wrtout1.good	(revision 1780)
@@ -0,0 +1,4 @@
+Facts are simple and facts are straight
+Facts are lazy and facts are late
+Facts all come with points of view
+Facts don't do what I want them to
Index: /tags/kBuild-0.1.4/src/sed/testsuite/wrtout2.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/wrtout2.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/wrtout2.good	(revision 1780)
@@ -0,0 +1,2 @@
+Facts are simple and facts are straight
+Facts are lazy and facts are late
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.good	(revision 1780)
@@ -0,0 +1,4 @@
+roses are red
+violets are blue
+my feet are cold
+your feet are too
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.inp	(revision 1780)
@@ -0,0 +1,4 @@
+roses are red
+violets are blue
+my feet are cold
+your feet are blue
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xabcx.sed	(revision 1780)
@@ -0,0 +1,2 @@
+# from the ChangeLog (Fri May 21 1993)
+\xfeetxs/blue/too/
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.good	(revision 1780)
@@ -0,0 +1,7 @@
+x
+xbx
+xbxcx
+xbxcx
+xbxcx
+xbxcx
+xbxcx
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.inp	(revision 1780)
@@ -0,0 +1,7 @@
+
+b
+bc
+bac
+baac
+baaac
+baaaac
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx.sed	(revision 1780)
@@ -0,0 +1,2 @@
+# from the ChangeLog (Wed Sep 5 2001)
+s/a*/x/g
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.good	(revision 1780)
@@ -0,0 +1,7 @@
+
+b
+bcx
+bacx
+baacx
+baaacx
+baaaacx
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.inp	(revision 1780)
@@ -0,0 +1,7 @@
+
+b
+bc
+bac
+baac
+baaac
+baaaac
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xbxcx3.sed	(revision 1780)
@@ -0,0 +1,1 @@
+s/a*/x/3
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.good	(revision 1780)
@@ -0,0 +1,67 @@
+#Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+#Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#Free Software Foundation, Inc.
+#This Makefile.in is free software; the Free Software Foundation
+#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_MAKE@"
+
+#Automake requirements
+
+"SHELL = @SHELL@"
+
+"PACKAGE = sed"
+
+"EXTRA_DIST = BUGS THANKS README.boot bootstrap.sh dc.sed autogen \\"
+"	m4/codeset.m4  m4/gettext.m4  m4/iconv.m4      m4/lcmessage.m4 \\"
+"	m4/getline.m4  m4/glibc21.m4  m4/isc-posix.m4  m4/progtest.m4 \\"
+"	m4/obstack.m4"
+
+"subdir = ."
+"ACLOCAL_M4 = $(top_srcdir)/aclocal.m4"
+"mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs"
+"CONFIG_HEADER = config.h"
+"CONFIG_CLEAN_FILES = bootstrap.sh intl/Makefile"
+"DIST_SOURCES ="
+"DATA = $(noinst_DATA)"
+
+"HEADERS = $(noinst_HEADERS)"
+
+
+"RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \\"
+"	uninstall-info-recursive all-recursive install-data-recursive \\"
+"	install-exec-recursive installdirs-recursive install-recursive \\"
+"	uninstall-recursive check-recursive installcheck-recursive"
+"DIST_COMMON = README $(noinst_HEADERS) ./stamp-h.in ABOUT-NLS AUTHORS \\"
+"	COPYING ChangeLog INSTALL Makefile.am Makefile.in NEWS THANKS \\"
+"	TODO acconfig.h aclocal.m4 bootstrap.sh.in config.guess \\"
+"	config.sub config_h.in configure configure.ac depcomp \\"
+"	install-sh missing mkinstalldirs"
+"DIST_SUBDIRS = $(SUBDIRS)"
+"all: config.h"
+"	$(MAKE) $(AM_MAKEFLAGS) all-recursive"
+
+".SUFFIXES:"
+"$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.ac $(ACLOCAL_M4)"
+"	cd $(top_srcdir) && \\"
+"	  $(AUTOMAKE) --gnu  Makefile"
+"Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status"
+"	cd $(top_builddir) && \\"
+"	  CONFIG_HEADERS= CONFIG_LINKS= \\"
+"	  CONFIG_FILES=$@ $(SHELL) ./config.status"
+
+"$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)"
+"	$(SHELL) ./config.status --recheck"
+"$(srcdir)/configure:  $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)"
+"	cd $(srcdir) && $(AUTOCONF)"
+
+"$(ACLOCAL_M4):  configure.ac m4/codeset.m4 m4/getline.m4 m4/gettext.m4 m4/glibc21.m4 m4/iconv.m4 m4/isc-posix.m4 m4/lcmessage.m4 m4/obstack.m4 m4/progtest.m4"
+"	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)"
+"config.h: stamp-h"
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.inp	(revision 1780)
@@ -0,0 +1,67 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# 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_MAKE@
+
+# Automake requirements
+
+SHELL = @SHELL@
+
+PACKAGE = sed
+
+EXTRA_DIST = BUGS THANKS README.boot bootstrap.sh dc.sed autogen \
+	m4/codeset.m4  m4/gettext.m4  m4/iconv.m4      m4/lcmessage.m4 \
+	m4/getline.m4  m4/glibc21.m4  m4/isc-posix.m4  m4/progtest.m4 \
+	m4/obstack.m4
+
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = bootstrap.sh intl/Makefile
+DIST_SOURCES =
+DATA = $(noinst_DATA)
+
+HEADERS = $(noinst_HEADERS)
+
+
+RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \
+	uninstall-info-recursive all-recursive install-data-recursive \
+	install-exec-recursive installdirs-recursive install-recursive \
+	uninstall-recursive check-recursive installcheck-recursive
+DIST_COMMON = README $(noinst_HEADERS) ./stamp-h.in ABOUT-NLS AUTHORS \
+	COPYING ChangeLog INSTALL Makefile.am Makefile.in NEWS THANKS \
+	TODO acconfig.h aclocal.m4 bootstrap.sh.in config.guess \
+	config.sub config_h.in configure configure.ac depcomp \
+	install-sh missing mkinstalldirs
+DIST_SUBDIRS = $(SUBDIRS)
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && \
+	  CONFIG_HEADERS= CONFIG_LINKS= \
+	  CONFIG_FILES=$@ $(SHELL) ./config.status
+
+$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+$(srcdir)/configure:  $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+	cd $(srcdir) && $(AUTOCONF)
+
+$(ACLOCAL_M4):  configure.ac m4/codeset.m4 m4/getline.m4 m4/gettext.m4 m4/glibc21.m4 m4/iconv.m4 m4/isc-posix.m4 m4/lcmessage.m4 m4/obstack.m4 m4/progtest.m4
+	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+config.h: stamp-h
Index: /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/xemacs.sed	(revision 1780)
@@ -0,0 +1,16 @@
+# Inspired by xemacs' config.status script
+# submitted by John Fremlin (john@fremlin.de)
+
+/^# Generated/d
+s%/\*\*/#.*%%
+s/^ *# */#/
+/^##/d
+/^#/ {
+  p
+  d
+}
+/./ {
+  s/\([\"]\)/\\\1/g
+  s/^/"/
+  s/$/"/
+}
Index: /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.good	(revision 1780)
@@ -0,0 +1,1 @@
+Are you sure (y/n)?  y] 
Index: /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.inp	(revision 1780)
@@ -0,0 +1,1 @@
+Are you sure (y/n)? [y] 
Index: /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/y-bracket.sed	(revision 1780)
@@ -0,0 +1,1 @@
+y/[/ /
Index: /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.good
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.good	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.good	(revision 1780)
@@ -0,0 +1,1 @@
+Are Sou Yure (S/n)? [S] $$Are Sou Yure (S/n)? [S] 
Index: /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.inp
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.inp	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.inp	(revision 1780)
@@ -0,0 +1,1 @@
+Are you sure (y/n)? [y] 
Index: /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.sed
===================================================================
--- /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.sed	(revision 1780)
+++ /tags/kBuild-0.1.4/src/sed/testsuite/y-newline.sed	(revision 1780)
@@ -0,0 +1,3 @@
+H
+G
+y/Ss\nYy/yY$sS/
Index: /tags/kBuild-0.1.4/tests/Config.kmk
===================================================================
--- /tags/kBuild-0.1.4/tests/Config.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/Config.kmk	(revision 1780)
@@ -0,0 +1,95 @@
+# $Id$
+## @file
+# Tests - Configuration.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+
+
+#
+# Template for building commandline tools.
+#
+TEMPLATE_TST = Commandline binary
+
+TEMPLATE_TST_INST               = tests/
+ifeq ($(BUILD_TARGET),os2)
+ TEMPLATE_TST_TOOL              = GCC3OMF
+ TEMPLATE_TST_CFLAGS.profile    = -pg
+ TEMPLATE_TST_CFLAGS.release    = -O3
+ TEMPLATE_TST_LDFLAGS           = -Zhigh-mem -Zstack=1024
+endif
+
+ifeq ($(BUILD_TARGET),darwin)
+ TEMPLATE_TST_TOOL              = GCC4MACHO
+ TEMPLATE_TST_CFLAGS.profile    =
+ TEMPLATE_TST_CFLAGS.release    = -O3
+ TEMPLATE_TST_LDFLAGS           =
+endif
+
+ifeq ($(filter-out win nt,$(BUILD_TARGET)),)
+ ifeq ($(BUILD_TARGET_ARCH),x86)
+  include $(PATH_KBUILD)/tools/VCC70.kmk	# fixme! template expanding does something bad to _LIBS /me thinks.
+  TEMPLATE_TST_TOOL             = VCC70
+ else ifeq ($(BUILD_TARGET_ARCH),amd64)
+  TEMPLATE_TST_TOOL             = VCC80AMD64
+  TEMPLATE_TST_DEFS             = _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS
+ endif
+ TEMPLATE_TST_SDKS              = WINPSDK
+ TEMPLATE_TST_CFLAGS            = -W3 -Zi -Zl
+ TEMPLATE_TST_CFLAGS.release    = -O2
+ TEMPLATE_TST_CFLAGS.profile    = -O2 -GH -Gh
+ TEMPLATE_TST_LDFLAGS           = /SUBSYSTEM:console /INCREMENTAL:no /NOD /DEBUG
+ TEMPLATE_TST_CFLAGS           += -MD
+ TEMPLATE_TST_LIBS              = \
+	$(PATH_TOOL_$(TEMPLATE_TST_TOOL)_LIB)/oldnames.lib \
+	$(PATH_TOOL_$(TEMPLATE_TST_TOOL)_LIB)/msvcrt.lib
+ TEMPLATE_TST_LIBS.profile      = Y:/coding/libc/svn/trunk/out/win.$(BUILD_TARGET_ARCH)/debug/kStuff/lib/kPrf2.lib
+endif
+
+ifndef TEMPLATE_TST_TOOL
+ # Use GCC3 when we're certain that the system is using GNU ld and ar.
+ ifeq ($(filter-out linux freebsd openbsd netbsd,$(BUILD_TARGET)),)
+  TEMPLATE_TST_TOOL             = GCC3
+ else
+  TEMPLATE_TST_TOOL             = GCC3PLAIN
+ endif
+ TEMPLATE_TST_CFLAGS.release    = -O3
+ ifeq ($(BUILD_TARGET),solaris)
+  TEMPLATE_TST_CFLAGS.x86      += -m32
+  TEMPLATE_TST_CFLAGS.amd64    += -m64
+  TEMPLATE_TST_CXXFLAGS.x86    += -m32
+  TEMPLATE_TST_CXXFLAGS.amd64  += -m64
+  TEMPLATE_TST_LDFLAGS.x86     += -m32
+  TEMPLATE_TST_LDFLAGS.amd64   += -m64
+  TEMPLATE_TST_LDFLAGS         += -Wl,-i
+ endif
+endif
+
+#
+# Template for building libraries for the tools.
+#
+TEMPLATE_TSTLIB = Library for Commandline binary
+TEMPLATE_TSTLIB_EXTENDS = BIN
+TEMPLATE_TSTLIB_INST    = lib/
+
+
Index: /tags/kBuild-0.1.4/tests/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/tests/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/Makefile.kmk	(revision 1780)
@@ -0,0 +1,34 @@
+# $Id$
+## @file
+# Tests - Top Level Makefile.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+
+include $(PATH_KBUILD)/header.kmk
+
+SUBDIRS = \
+	inherit-target \
+	inherit-bld \
+
+include $(FILE_KBUILD_FOOTER)
Index: /tags/kBuild-0.1.4/tests/dummy.c
===================================================================
--- /tags/kBuild-0.1.4/tests/dummy.c	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/dummy.c	(revision 1780)
@@ -0,0 +1,30 @@
+/* $Id$ */
+/** @file
+ * Tests - Dummy test program.
+ */
+
+/*
+ * Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+int main()
+{
+    return 0;
+}
Index: /tags/kBuild-0.1.4/tests/dummy_defined_X.c
===================================================================
--- /tags/kBuild-0.1.4/tests/dummy_defined_X.c	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/dummy_defined_X.c	(revision 1780)
@@ -0,0 +1,43 @@
+/* $Id$ */
+/** @file
+ * Tests - Dummy test program checking that X == 42, possibly doing this via y.
+ */
+
+/*
+ * Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef X
+# error "X isn't defined, test the is busted."
+#endif
+
+#ifndef y
+# define y 42
+#endif
+
+#if X != 42
+# error "X != 42"
+#endif
+
+int main()
+{
+    return 0;
+}
+
Index: /tags/kBuild-0.1.4/tests/dummy_defined_Y.c
===================================================================
--- /tags/kBuild-0.1.4/tests/dummy_defined_Y.c	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/dummy_defined_Y.c	(revision 1780)
@@ -0,0 +1,39 @@
+/* $Id$ */
+/** @file
+ * Tests - Dummy test program checking that Y == 42.
+ */
+
+/*
+ * Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef Y
+# error "Y isn't defined, test the is busted."
+#endif
+
+#if Y != 42
+# error "Y != 42"
+#endif
+
+int main()
+{
+    return 0;
+}
+
Index: /tags/kBuild-0.1.4/tests/hello.c
===================================================================
--- /tags/kBuild-0.1.4/tests/hello.c	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/hello.c	(revision 1780)
@@ -0,0 +1,34 @@
+/* $Id$ */
+/** @file
+ * Tests - Hello world test program.
+ */
+
+/*
+ * Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild 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.
+ *
+ * kBuild 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 kBuild; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+
+int main()
+{
+    printf("hello world\n");
+    return 0;
+}
+
Index: /tags/kBuild-0.1.4/tests/inherit-bld/Config.kmk
===================================================================
--- /tags/kBuild-0.1.4/tests/inherit-bld/Config.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/inherit-bld/Config.kmk	(revision 1780)
@@ -0,0 +1,81 @@
+# $Id$
+## @file
+# Tests - Build Type Inheritance.
+#
+# Just to set up some additional build types the correct way.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+
+#
+# Include our parent Config.kmk
+#
+include $(PATH_ROOT)/tests/Config.kmk
+
+
+#
+# For inherit-bld3 - no inheritance.
+#
+KBUILD_BLD_TYPES += dbgbld3
+
+
+#
+# For inherit-bld4 - default inheritance (override).
+#
+KBUILD_BLD_TYPES += dbgbld4
+BLD_TYPE_dbgbld4_EXTENDS = dbgbld3
+
+#
+# For inherit-bld5 - appending inheritance.
+#
+KBUILD_BLD_TYPES += dbgbld5
+BLD_TYPE_dbgbld5_EXTENDS = dbgbld3
+BLD_TYPE_dbgbld5_EXTENDS_BY = appending
+
+#
+# For inherit-bld6 - prepending inheritance.
+#
+KBUILD_BLD_TYPES += dbgbld6
+BLD_TYPE_dbgbld6_EXTENDS = dbgbld3
+BLD_TYPE_dbgbld6_EXTENDS_BY = prepending
+
+#
+# For inherit-bld7 - overriding inheritance.
+#
+KBUILD_BLD_TYPES += dbgbld7
+BLD_TYPE_dbgbld7_EXTENDS = dbgbld3
+BLD_TYPE_dbgbld7_EXTENDS_BY = overriding
+
+#
+# For inherit-bld10 thru 19 - overriding inheritance.
+#
+KBUILD_BLD_TYPES += dbgbld10 dbgbld11
+BLD_TYPE_dbgbld11_EXTENDS = dbgbld10
+
+#
+# For inherit-bld20 thru 29 - prepending inheritance.
+#
+KBUILD_BLD_TYPES += dbgbld20 dbgbld21
+BLD_TYPE_dbgbld21_EXTENDS = dbgbld20
+BLD_TYPE_dbgbld21_EXTENDS_BY = prepending
+
Index: /tags/kBuild-0.1.4/tests/inherit-bld/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/tests/inherit-bld/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/inherit-bld/Makefile.kmk	(revision 1780)
@@ -0,0 +1,116 @@
+# $Id$
+## @file
+# Test - Build Type Inheritance.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+
+# Plain setup just for a reality check.
+PROGRAMS += inherit-bld1
+inherit-bld1_TEMPLATE = TST
+inherit-bld1_DEFS = X=y
+inherit-bld1_SOURCES = ../dummy_defined_X.c
+
+# Test that the BLD_TYPE feature works.
+PROGRAMS += inherit-bld2
+inherit-bld2_TEMPLATE = TST
+inherit-bld2_BLD_TYPE = debug
+inherit-bld2_DEFS.debug = X=y
+inherit-bld2_SOURCES = ../dummy_defined_X.c
+
+# Test that an simple alternative build type works.
+PROGRAMS += inherit-bld3
+inherit-bld3_TEMPLATE = TST
+inherit-bld3_BLD_TYPE = dbgbld3
+inherit-bld3_DEFS.dbgbld3 = X=y
+inherit-bld3_SOURCES = ../dummy_defined_X.c
+
+# Test that default build type inheritance works - dbgbld4 extends dbgbld3.
+PROGRAMS += inherit-bld4
+inherit-bld4_TEMPLATE = TST
+inherit-bld4_BLD_TYPE = dbgbld4
+inherit-bld4_DEFS.dbgbld3 = X=y
+inherit-bld4_SOURCES = ../dummy_defined_X.c
+
+# Test that appending build type inheritance works - dbgbld5 extends dbgbld3.
+PROGRAMS += inherit-bld5
+inherit-bld5_TEMPLATE = TST
+inherit-bld5_BLD_TYPE = dbgbld5
+inherit-bld5_DEFS.dbgbld3 = X=y y=0
+inherit-bld5_DEFS.dbgbld5 = y=42
+inherit-bld5_SOURCES = ../dummy_defined_X.c
+
+# Test that prepending build type inheritance works - dbgbld6 extends dbgbld3.
+PROGRAMS += inherit-bld6
+inherit-bld6_TEMPLATE = TST
+inherit-bld6_BLD_TYPE = dbgbld6
+inherit-bld6_DEFS.dbgbld3 = X=y y=42
+inherit-bld6_DEFS.dbgbld6 = y=0
+inherit-bld6_SOURCES = ../dummy_defined_X.c
+
+
+#
+# Tests where we inherit from a target and force build type which
+# relies on inheritance. These are the fine points...
+#
+PROGRAMS += inherit-bld10
+inherit-bld10_TEMPLATE = TST
+inherit-bld10_BLD_TYPE = dbgbld11
+inherit-bld10_DEFS = X=y
+inherit-bld10_DEFS.dbgbld10 = y=42
+inherit-bld10_SOURCES = ../dummy_defined_X.c
+
+# Tests that target and build inheriting works together.
+PROGRAMS += inherit-bld11
+inherit-bld11_EXTENDS = inherit-bld10
+
+# Tests that dbgbld11 is picked from the target rather than the parent.
+PROGRAMS += inherit-bld12
+inherit-bld12_EXTENDS = inherit-bld10
+inherit-bld12_DEFS = y=0
+inherit-bld12_DEFS.dbgbld11 = X=z z=42
+
+# Tests that prepending works.
+PROGRAMS += inherit-bld20
+inherit-bld20_TEMPLATE = TST
+inherit-bld20_BLD_TYPE = dbgbld21
+inherit-bld20_DEFS = X=y
+inherit-bld20_DEFS.dbgbld20 = y=42
+inherit-bld20_DEFS.dbgbld21 = y=0
+#inherit-bld20_DEFS.dbgbld21 = y=0 y=42 <-- expected result.
+inherit-bld20_SOURCES = ../dummy_defined_X.c
+
+# Tests that prepending + target inheritance works as expected. funky!
+PROGRAMS += inherit-bld21
+inherit-bld21_EXTENDS = inherit-bld20
+inherit-bld21_DEFS.dbgbld20 = Y=y
+#inherit-bld21_DEFS.dbgbld21 = y=0 y=42 Y=y <-- expected result; dbgbld21 from parent + our dbgbld20.
+inherit-bld21_SOURCES = ../dummy_defined_Y.c
+
+
+include $(FILE_KBUILD_FOOTER)
+
Index: /tags/kBuild-0.1.4/tests/inherit-target/Makefile.kmk
===================================================================
--- /tags/kBuild-0.1.4/tests/inherit-target/Makefile.kmk	(revision 1780)
+++ /tags/kBuild-0.1.4/tests/inherit-target/Makefile.kmk	(revision 1780)
@@ -0,0 +1,90 @@
+# $Id$
+## @file
+# Test - Target Inheritance.
+#
+
+#
+# Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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.
+#
+# kBuild 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 kBuild; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+#
+
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+
+PROGRAMS += inherit-target1
+inherit-target1_TEMPLATE = TST
+inherit-target1_SOURCES = ../dummy_defined_X.c
+inherit-target1_DEFS = X=y
+
+PROGRAMS += inherit-target2
+inherit-target2_EXTENDS = inherit-target1
+
+PROGRAMS += inherit-target3
+inherit-target3_EXTENDS = inherit-target2
+
+PROGRAMS += inherit-target4
+inherit-target4_EXTENDS = inherit-target3
+
+PROGRAMS += inherit-target5
+inherit-target5_EXTENDS = inherit-target3
+
+# out of target order.
+PROGRAMS += inherit-target6
+inherit-target6_EXTENDS = inherit-target9
+
+PROGRAMS += inherit-target7
+inherit-target7_EXTENDS = inherit-target1
+
+PROGRAMS += inherit-target8
+inherit-target8_EXTENDS = inherit-target7
+
+PROGRAMS += inherit-target9
+inherit-target9_EXTENDS = inherit-target8
+
+
+# More complicated, with a couple of SDKs and TEMPLATES.
+SDK_inh1 = target inherit test sdk 1
+SDK_inh1_DEFS = Z=42
+
+SDK_inh2 = target inherit test sdk 2
+SDK_inh2_DEFS = Y=128
+
+SDK_inh3 = target inherit test sdk 3
+SDK_inh3_DEFS = P=42
+
+TEMPLATE_inh1 = target inherit test template 1
+TEMPLATE_inh1_EXTENDS = TST
+TEMPLATE_inh1_DEFS = Q=256
+
+PROGRAMS += inherit-target10
+inherit-target10_TEMPLATE = inh1
+inherit-target10_SOURCES = ../dummy_defined_X.c
+inherit-target10_SDKS = inh1 inh2
+inherit-target10_DEFS = X=Z
+
+PROGRAMS += inherit-target11
+inherit-target11_EXTENDS = inherit-target10
+inherit-target11_SOURCES = ../dummy_defined_Y.c
+inherit-target11_SDKS = inh3
+inherit-target11_DEFS = Y=P
+
+
+include $(FILE_KBUILD_FOOTER)
+
